XCSF  1.4.7
XCSF learning classifier system
cond_ternary.c
Go to the documentation of this file.
1 /*
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation, either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 
25 #include "cond_ternary.h"
26 #include "ea.h"
27 #include "sam.h"
28 #include "utils.h"
29 
30 #define DONT_CARE ('#')
31 #define N_MU (1)
32 
36 static const int MU_TYPE[N_MU] = { SAM_LOG_NORMAL };
37 
43 static void
44 cond_ternary_rand(const struct XCSF *xcsf, const struct Cl *c)
45 {
46  const struct CondTernary *cond = c->cond;
47  for (int i = 0; i < cond->length; ++i) {
48  if (rand_uniform(0, 1) < xcsf->cond->p_dontcare) {
49  cond->string[i] = DONT_CARE;
50  } else if (rand_uniform(0, 1) < 0.5) {
51  cond->string[i] = '0';
52  } else {
53  cond->string[i] = '1';
54  }
55  }
56 }
57 
63 void
64 cond_ternary_init(const struct XCSF *xcsf, struct Cl *c)
65 {
66  struct CondTernary *new = malloc(sizeof(struct CondTernary));
67  new->length = xcsf->x_dim * xcsf->cond->bits;
68  new->string = malloc(sizeof(char) * new->length);
69  new->tmp_input = malloc(sizeof(char) * xcsf->cond->bits);
70  new->mu = malloc(sizeof(double) * N_MU);
71  sam_init(new->mu, N_MU, MU_TYPE);
72  c->cond = new;
74 }
75 
81 void
82 cond_ternary_free(const struct XCSF *xcsf, const struct Cl *c)
83 {
84  (void) xcsf;
85  const struct CondTernary *cond = c->cond;
86  free(cond->string);
87  free(cond->tmp_input);
88  free(cond->mu);
89  free(c->cond);
90 }
91 
98 void
99 cond_ternary_copy(const struct XCSF *xcsf, struct Cl *dest,
100  const struct Cl *src)
101 {
102  struct CondTernary *new = malloc(sizeof(struct CondTernary));
103  const struct CondTernary *src_cond = src->cond;
104  new->length = src_cond->length;
105  new->string = malloc(sizeof(char) * src_cond->length);
106  new->tmp_input = malloc(sizeof(char) * xcsf->cond->bits);
107  new->mu = malloc(sizeof(double) * N_MU);
108  memcpy(new->string, src_cond->string, sizeof(char) * src_cond->length);
109  memcpy(new->mu, src_cond->mu, sizeof(double) * N_MU);
110  dest->cond = new;
111 }
112 
119 void
120 cond_ternary_cover(const struct XCSF *xcsf, const struct Cl *c, const double *x)
121 {
122  const struct CondTernary *cond = c->cond;
123  const int bits = xcsf->cond->bits;
124  for (int i = 0; i < xcsf->x_dim; ++i) {
125  float_to_binary(x[i], cond->tmp_input, bits);
126  for (int j = 0; j < bits; ++j) {
127  if (rand_uniform(0, 1) < xcsf->cond->p_dontcare) {
128  cond->string[i * bits + j] = DONT_CARE;
129  } else {
130  cond->string[i * bits + j] = cond->tmp_input[j];
131  }
132  }
133  }
134 }
135 
143 void
144 cond_ternary_update(const struct XCSF *xcsf, const struct Cl *c,
145  const double *x, const double *y)
146 {
147  (void) xcsf;
148  (void) c;
149  (void) x;
150  (void) y;
151 }
152 
160 bool
161 cond_ternary_match(const struct XCSF *xcsf, const struct Cl *c, const double *x)
162 {
163  const struct CondTernary *cond = c->cond;
164  const int bits = xcsf->cond->bits;
165  for (int i = 0; i < xcsf->x_dim; ++i) {
166  float_to_binary(x[i], cond->tmp_input, bits);
167  for (int j = 0; j < bits; ++j) {
168  const char s = cond->string[i * bits + j];
169  if (s != DONT_CARE && s != cond->tmp_input[j]) {
170  return false;
171  }
172  }
173  }
174  return true;
175 }
176 
184 bool
185 cond_ternary_crossover(const struct XCSF *xcsf, const struct Cl *c1,
186  const struct Cl *c2)
187 {
188  const struct CondTernary *cond1 = c1->cond;
189  const struct CondTernary *cond2 = c2->cond;
190  bool changed = false;
191  if (rand_uniform(0, 1) < xcsf->ea->p_crossover) {
192  for (int i = 0; i < cond1->length; ++i) {
193  if (rand_uniform(0, 1) < 0.5) {
194  const char tmp = cond1->string[i];
195  cond1->string[i] = cond2->string[i];
196  cond2->string[i] = tmp;
197  changed = true;
198  }
199  }
200  }
201  return changed;
202 }
203 
210 bool
211 cond_ternary_mutate(const struct XCSF *xcsf, const struct Cl *c)
212 {
213  (void) xcsf;
214  const struct CondTernary *cond = c->cond;
215  sam_adapt(cond->mu, N_MU, MU_TYPE);
216  bool changed = false;
217  for (int i = 0; i < cond->length; ++i) {
218  if (rand_uniform(0, 1) < cond->mu[0]) {
219  if (cond->string[i] == DONT_CARE) {
220  cond->string[i] = (rand_uniform(0, 1) < 0.5) ? '0' : '1';
221  } else {
222  cond->string[i] = DONT_CARE;
223  }
224  changed = true;
225  }
226  }
227  return changed;
228 }
229 
237 bool
238 cond_ternary_general(const struct XCSF *xcsf, const struct Cl *c1,
239  const struct Cl *c2)
240 {
241  (void) xcsf;
242  const struct CondTernary *cond1 = c1->cond;
243  const struct CondTernary *cond2 = c2->cond;
244  bool general = false;
245  for (int i = 0; i < cond1->length; ++i) {
246  if (cond1->string[i] != DONT_CARE &&
247  cond1->string[i] != cond2->string[i]) {
248  return false;
249  }
250  if (cond1->string[i] != cond2->string[i]) {
251  general = true;
252  }
253  }
254  return general;
255 }
256 
262 void
263 cond_ternary_print(const struct XCSF *xcsf, const struct Cl *c)
264 {
265  char *json_str = cond_ternary_json_export(xcsf, c);
266  printf("%s\n", json_str);
267  free(json_str);
268 }
269 
276 double
277 cond_ternary_size(const struct XCSF *xcsf, const struct Cl *c)
278 {
279  (void) xcsf;
280  const struct CondTernary *cond = c->cond;
281  return cond->length;
282 }
283 
291 size_t
292 cond_ternary_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
293 {
294  (void) xcsf;
295  size_t s = 0;
296  const struct CondTernary *cond = c->cond;
297  s += fwrite(&cond->length, sizeof(int), 1, fp);
298  s += fwrite(cond->string, sizeof(char), cond->length, fp);
299  s += fwrite(cond->mu, sizeof(double), N_MU, fp);
300  return s;
301 }
302 
310 size_t
311 cond_ternary_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
312 {
313  size_t s = 0;
314  struct CondTernary *new = malloc(sizeof(struct CondTernary));
315  new->length = 0;
316  s += fread(&new->length, sizeof(int), 1, fp);
317  if (new->length < 1) {
318  printf("cond_ternary_load(): read error\n");
319  new->length = 1;
320  exit(EXIT_FAILURE);
321  }
322  new->string = malloc(sizeof(char) * new->length);
323  s += fread(new->string, sizeof(char), new->length, fp);
324  new->tmp_input = malloc(sizeof(char) * xcsf->cond->bits);
325  new->mu = malloc(sizeof(double) * N_MU);
326  s += fread(new->mu, sizeof(double), N_MU, fp);
327  c->cond = new;
328  return s;
329 }
330 
337 char *
338 cond_ternary_json_export(const struct XCSF *xcsf, const struct Cl *c)
339 {
340  (void) xcsf;
341  const struct CondTernary *cond = c->cond;
342  cJSON *json = cJSON_CreateObject();
343  cJSON_AddStringToObject(json, "type", "ternary");
344  char buff[cond->length + 1];
345  memcpy(buff, cond->string, sizeof(char) * cond->length);
346  buff[cond->length] = '\0';
347  cJSON_AddStringToObject(json, "string", buff);
348  cJSON *mutation = cJSON_CreateDoubleArray(cond->mu, N_MU);
349  cJSON_AddItemToObject(json, "mutation", mutation);
350  char *string = cJSON_Print(json);
351  cJSON_Delete(json);
352  return string;
353 }
354 
361 void
362 cond_ternary_json_import(const struct XCSF *xcsf, struct Cl *c,
363  const cJSON *json)
364 {
365  (void) xcsf;
366  struct CondTernary *cond = c->cond;
367  const cJSON *item = cJSON_GetObjectItem(json, "string");
368  if (item != NULL && cJSON_IsString(item)) {
369  for (int i = 0; i < cond->length; ++i) {
370  const char bit = item->valuestring[i];
371  if (bit == '\0') {
372  printf("Import error: string terminated early\n");
373  exit(EXIT_FAILURE);
374  }
375  cond->string[i] = bit;
376  }
377  }
378  sam_json_import(cond->mu, N_MU, json);
379 }
380 
386 char *
388 {
389  const struct ArgsCond *cond = xcsf->cond;
390  cJSON *json = cJSON_CreateObject();
391  cJSON_AddNumberToObject(json, "p_dontcare", cond->p_dontcare);
392  cJSON_AddNumberToObject(json, "bits", cond->bits);
393  char *string = cJSON_Print(json);
394  cJSON_Delete(json);
395  return string;
396 }
397 
404 char *
406 {
407  for (cJSON *iter = json; iter != NULL; iter = iter->next) {
408  if (strncmp(iter->string, "p_dontcare\0", 11) == 0 &&
409  cJSON_IsNumber(iter)) {
410  cond_param_set_p_dontcare(xcsf, iter->valuedouble);
411  } else if (strncmp(iter->string, "bits\0", 5) == 0 &&
412  cJSON_IsNumber(iter)) {
413  cond_param_set_bits(xcsf, iter->valueint);
414  } else {
415  return iter->string;
416  }
417  }
418  return NULL;
419 }
420 
425 void
427 {
430 }
double cond_ternary_size(const struct XCSF *xcsf, const struct Cl *c)
Returns the size of a ternary condition.
Definition: cond_ternary.c:277
static const int MU_TYPE[(1)]
Self-adaptation method for mutating ternary conditions.
Definition: cond_ternary.c:36
void cond_ternary_init(const struct XCSF *xcsf, struct Cl *c)
Creates and initialises a ternary bitstring condition.
Definition: cond_ternary.c:64
bool cond_ternary_match(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Calculates whether a ternary condition matches an input.
Definition: cond_ternary.c:161
char * cond_ternary_param_json_export(const struct XCSF *xcsf)
Returns a json formatted string of the ternary parameters.
Definition: cond_ternary.c:387
void cond_ternary_update(const struct XCSF *xcsf, const struct Cl *c, const double *x, const double *y)
Dummy update function.
Definition: cond_ternary.c:144
bool cond_ternary_general(const struct XCSF *xcsf, const struct Cl *c1, const struct Cl *c2)
Returns whether classifier c1 has a condition more general than c2.
Definition: cond_ternary.c:238
void cond_ternary_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
Copies a ternary condition from one classifier to another.
Definition: cond_ternary.c:99
char * cond_ternary_param_json_import(struct XCSF *xcsf, cJSON *json)
Sets the ternary parameters from a cJSON object.
Definition: cond_ternary.c:405
void cond_ternary_cover(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Generates a ternary condition that matches the current input.
Definition: cond_ternary.c:120
bool cond_ternary_mutate(const struct XCSF *xcsf, const struct Cl *c)
Mutates a ternary condition.
Definition: cond_ternary.c:211
#define N_MU
Number of ternary mutation rates.
Definition: cond_ternary.c:31
void cond_ternary_print(const struct XCSF *xcsf, const struct Cl *c)
Prints a ternary condition.
Definition: cond_ternary.c:263
void cond_ternary_json_import(const struct XCSF *xcsf, struct Cl *c, const cJSON *json)
Creates a ternary condition from a cJSON object.
Definition: cond_ternary.c:362
void cond_ternary_free(const struct XCSF *xcsf, const struct Cl *c)
Frees the memory used by a ternary condition.
Definition: cond_ternary.c:82
bool cond_ternary_crossover(const struct XCSF *xcsf, const struct Cl *c1, const struct Cl *c2)
Performs uniform crossover with two ternary conditions.
Definition: cond_ternary.c:185
size_t cond_ternary_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
Writes a ternary condition to a file.
Definition: cond_ternary.c:292
char * cond_ternary_json_export(const struct XCSF *xcsf, const struct Cl *c)
Returns a json formatted string representation of a ternary condition.
Definition: cond_ternary.c:338
void cond_ternary_param_defaults(struct XCSF *xcsf)
Initialises default ternary condition parameters.
Definition: cond_ternary.c:426
static void cond_ternary_rand(const struct XCSF *xcsf, const struct Cl *c)
Randomises a ternary condition.
Definition: cond_ternary.c:44
size_t cond_ternary_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
Reads a ternary condition from a file.
Definition: cond_ternary.c:311
#define DONT_CARE
Don't care symbol.
Definition: cond_ternary.c:30
Ternary condition functions.
void cond_param_set_bits(struct XCSF *xcsf, const int a)
Definition: condition.c:429
void cond_param_set_p_dontcare(struct XCSF *xcsf, const double a)
Definition: condition.c:404
Evolutionary algorithm functions.
Definition: __init__.py:1
void sam_json_import(double *mu, const int N, const cJSON *json)
Initialises a mutation vector from a cJSON object.
Definition: sam.c:100
void sam_init(double *mu, const int N, const int *type)
Initialises self-adaptive mutation rates.
Definition: sam.c:43
void sam_adapt(double *mu, const int N, const int *type)
Self-adapts mutation rates.
Definition: sam.c:68
Self-adaptive mutation functions.
#define SAM_LOG_NORMAL
Log normal self-adaptation.
Definition: sam.h:28
Parameters for initialising and operating conditions.
Definition: condition.h:60
double p_dontcare
Don't care probability.
Definition: condition.h:65
int bits
Bits per float to binarise inputs.
Definition: condition.h:67
Classifier data structure.
Definition: xcsf.h:45
void * cond
Condition structure.
Definition: xcsf.h:49
Ternary condition data structure.
Definition: cond_ternary.h:32
int length
Length of the bitstring.
Definition: cond_ternary.h:34
char * string
Ternary bitstring.
Definition: cond_ternary.h:33
double * mu
Mutation rates.
Definition: cond_ternary.h:35
char * tmp_input
Temporary storage for float conversion.
Definition: cond_ternary.h:36
XCSF data structure.
Definition: xcsf.h:85
double rand_uniform(const double min, const double max)
Returns a uniform random float [min,max].
Definition: utils.c:62
Utility functions for random number handling, etc.
static void float_to_binary(const double f, char *binary, const int bits)
Generates a binary string from a float.
Definition: utils.h:110