XCSF 1.4.8
XCSF learning classifier system
Loading...
Searching...
No Matches
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
36static const int MU_TYPE[N_MU] = { SAM_LOG_NORMAL };
37
43static void
44cond_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
63void
64cond_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
81void
82cond_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
98void
99cond_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
119void
120cond_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
143void
144cond_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
160bool
161cond_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
184bool
185cond_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
210bool
211cond_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
237bool
238cond_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
262void
263cond_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
276double
277cond_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
291size_t
292cond_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
310size_t
311cond_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
337char *
338cond_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
361void
362cond_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
386char *
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
404char *
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
425void
double cond_ternary_size(const struct XCSF *xcsf, const struct Cl *c)
Returns the size of a ternary condition.
static const int MU_TYPE[(1)]
Self-adaptation method for mutating ternary conditions.
char * cond_ternary_json_export(const struct XCSF *xcsf, const struct Cl *c)
Returns a json formatted string representation of a ternary condition.
void cond_ternary_init(const struct XCSF *xcsf, struct Cl *c)
Creates and initialises a ternary bitstring condition.
bool cond_ternary_match(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Calculates whether a ternary condition matches an input.
void cond_ternary_update(const struct XCSF *xcsf, const struct Cl *c, const double *x, const double *y)
Dummy update function.
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.
void cond_ternary_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
Copies a ternary condition from one classifier to another.
void cond_ternary_cover(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Generates a ternary condition that matches the current input.
bool cond_ternary_mutate(const struct XCSF *xcsf, const struct Cl *c)
Mutates a ternary condition.
#define N_MU
Number of ternary mutation rates.
void cond_ternary_print(const struct XCSF *xcsf, const struct Cl *c)
Prints a ternary condition.
char * cond_ternary_param_json_import(struct XCSF *xcsf, cJSON *json)
Sets the ternary parameters from a cJSON object.
void cond_ternary_json_import(const struct XCSF *xcsf, struct Cl *c, const cJSON *json)
Creates a ternary condition from a cJSON object.
void cond_ternary_free(const struct XCSF *xcsf, const struct Cl *c)
Frees the memory used by a ternary condition.
bool cond_ternary_crossover(const struct XCSF *xcsf, const struct Cl *c1, const struct Cl *c2)
Performs uniform crossover with two ternary conditions.
char * cond_ternary_param_json_export(const struct XCSF *xcsf)
Returns a json formatted string of the ternary parameters.
size_t cond_ternary_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
Writes a ternary condition to a file.
void cond_ternary_param_defaults(struct XCSF *xcsf)
Initialises default ternary condition parameters.
static void cond_ternary_rand(const struct XCSF *xcsf, const struct Cl *c)
Randomises a ternary condition.
size_t cond_ternary_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
Reads a ternary condition from a file.
#define DONT_CARE
Don't care symbol.
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.
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.
int length
Length of the bitstring.
char * string
Ternary bitstring.
double * mu
Mutation rates.
char * tmp_input
Temporary storage for float conversion.
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