XCSF 1.4.8
XCSF learning classifier system
Loading...
Searching...
No Matches
cond_ellipsoid.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
24#include "cond_ellipsoid.h"
25#include "ea.h"
26#include "sam.h"
27#include "utils.h"
28
29#define N_MU (1)
30
34static const int MU_TYPE[N_MU] = { SAM_LOG_NORMAL };
35
45static double
46cond_ellipsoid_dist(const struct XCSF *xcsf, const struct Cl *c,
47 const double *x)
48{
49 const struct CondEllipsoid *cond = c->cond;
50 double dist = 0;
51 for (int i = 0; i < xcsf->x_dim; ++i) {
52 const double d = (x[i] - cond->center[i]) / cond->spread[i];
53 dist += d * d;
54 }
55 return dist;
56}
57
64void
65cond_ellipsoid_init(const struct XCSF *xcsf, struct Cl *c)
66{
67 struct CondEllipsoid *new = malloc(sizeof(struct CondEllipsoid));
68 new->center = malloc(sizeof(double) * xcsf->x_dim);
69 new->spread = malloc(sizeof(double) * xcsf->x_dim);
70 new->mu = malloc(sizeof(double) * N_MU);
71 const double spread_max = fabs(xcsf->cond->max - xcsf->cond->min);
72 for (int i = 0; i < xcsf->x_dim; ++i) {
73 new->center[i] = rand_uniform(xcsf->cond->min, xcsf->cond->max);
74 new->spread[i] = rand_uniform(xcsf->cond->spread_min, spread_max);
75 }
76 sam_init(new->mu, N_MU, MU_TYPE);
77 c->cond = new;
78}
79
85void
86cond_ellipsoid_free(const struct XCSF *xcsf, const struct Cl *c)
87{
88 (void) xcsf;
89 const struct CondEllipsoid *cond = c->cond;
90 free(cond->center);
91 free(cond->spread);
92 free(cond->mu);
93 free(c->cond);
94}
95
102void
103cond_ellipsoid_copy(const struct XCSF *xcsf, struct Cl *dest,
104 const struct Cl *src)
105{
106 struct CondEllipsoid *new = malloc(sizeof(struct CondEllipsoid));
107 const struct CondEllipsoid *src_cond = src->cond;
108 new->center = malloc(sizeof(double) * xcsf->x_dim);
109 new->spread = malloc(sizeof(double) * xcsf->x_dim);
110 new->mu = malloc(sizeof(double) * N_MU);
111 memcpy(new->center, src_cond->center, sizeof(double) * xcsf->x_dim);
112 memcpy(new->spread, src_cond->spread, sizeof(double) * xcsf->x_dim);
113 memcpy(new->mu, src_cond->mu, sizeof(double) * N_MU);
114 dest->cond = new;
115}
116
123void
124cond_ellipsoid_cover(const struct XCSF *xcsf, const struct Cl *c,
125 const double *x)
126{
127 const struct CondEllipsoid *cond = c->cond;
128 const double spread_max = fabs(xcsf->cond->max - xcsf->cond->min);
129 for (int i = 0; i < xcsf->x_dim; ++i) {
130 cond->center[i] = x[i];
131 cond->spread[i] = rand_uniform(xcsf->cond->spread_min, spread_max);
132 }
133}
134
142void
143cond_ellipsoid_update(const struct XCSF *xcsf, const struct Cl *c,
144 const double *x, const double *y)
145{
146 (void) y;
147 if (xcsf->cond->eta > 0) {
148 const struct CondEllipsoid *cond = c->cond;
149 for (int i = 0; i < xcsf->x_dim; ++i) {
150 cond->center[i] += xcsf->cond->eta * (x[i] - cond->center[i]);
151 }
152 }
153}
154
162bool
163cond_ellipsoid_match(const struct XCSF *xcsf, const struct Cl *c,
164 const double *x)
165{
166 return (cond_ellipsoid_dist(xcsf, c, x) < 1);
167}
168
176bool
177cond_ellipsoid_crossover(const struct XCSF *xcsf, const struct Cl *c1,
178 const struct Cl *c2)
179{
180 const struct CondEllipsoid *cond1 = c1->cond;
181 const struct CondEllipsoid *cond2 = c2->cond;
182 bool changed = false;
183 if (rand_uniform(0, 1) < xcsf->ea->p_crossover) {
184 for (int i = 0; i < xcsf->x_dim; ++i) {
185 if (rand_uniform(0, 1) < 0.5) {
186 const double tmp = cond1->center[i];
187 cond1->center[i] = cond2->center[i];
188 cond2->center[i] = tmp;
189 changed = true;
190 }
191 if (rand_uniform(0, 1) < 0.5) {
192 const double tmp = cond1->spread[i];
193 cond1->spread[i] = cond2->spread[i];
194 cond2->spread[i] = tmp;
195 changed = true;
196 }
197 }
198 }
199 return changed;
200}
201
208bool
209cond_ellipsoid_mutate(const struct XCSF *xcsf, const struct Cl *c)
210{
211 bool changed = false;
212 const struct CondEllipsoid *cond = c->cond;
213 double *center = cond->center;
214 double *spread = cond->spread;
215 sam_adapt(cond->mu, N_MU, MU_TYPE);
216 for (int i = 0; i < xcsf->x_dim; ++i) {
217 double orig = center[i];
218 center[i] += rand_normal(0, cond->mu[0]);
219 center[i] = clamp(center[i], xcsf->cond->min, xcsf->cond->max);
220 if (orig != center[i]) {
221 changed = true;
222 }
223 orig = spread[i];
224 spread[i] += rand_normal(0, cond->mu[0]);
225 spread[i] = fmax(DBL_EPSILON, spread[i]);
226 if (orig != spread[i]) {
227 changed = true;
228 }
229 }
230 return changed;
231}
232
240bool
241cond_ellipsoid_general(const struct XCSF *xcsf, const struct Cl *c1,
242 const struct Cl *c2)
243{
244 const struct CondEllipsoid *cond1 = c1->cond;
245 const struct CondEllipsoid *cond2 = c2->cond;
246 double *temp = malloc(sizeof(double) * xcsf->x_dim);
247 memcpy(temp, cond2->center, sizeof(double) * xcsf->x_dim);
248 for (int i = 0; i < xcsf->x_dim; ++i) {
249 if (cond1->center[i] != cond2->center[i] ||
250 cond1->spread[i] != cond2->spread[i]) {
251 temp[i] += cond2->spread[i];
252 if (cond_ellipsoid_dist(xcsf, c1, temp) > 1) {
253 free(temp);
254 return false;
255 }
256 temp[i] -= 2 * cond2->spread[i];
257 if (cond_ellipsoid_dist(xcsf, c1, temp) > 1) {
258 free(temp);
259 return false;
260 }
261 temp[i] = cond2->center[i];
262 }
263 }
264 free(temp);
265 return true;
266}
267
273void
274cond_ellipsoid_print(const struct XCSF *xcsf, const struct Cl *c)
275{
276 char *json_str = cond_ellipsoid_json_export(xcsf, c);
277 printf("%s\n", json_str);
278 free(json_str);
279}
280
287double
288cond_ellipsoid_size(const struct XCSF *xcsf, const struct Cl *c)
289{
290 (void) c;
291 return xcsf->x_dim;
292}
293
301size_t
302cond_ellipsoid_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
303{
304 size_t s = 0;
305 const struct CondEllipsoid *cond = c->cond;
306 s += fwrite(cond->center, sizeof(double), xcsf->x_dim, fp);
307 s += fwrite(cond->spread, sizeof(double), xcsf->x_dim, fp);
308 s += fwrite(cond->mu, sizeof(double), N_MU, fp);
309 return s;
310}
311
319size_t
320cond_ellipsoid_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
321{
322 size_t s = 0;
323 struct CondEllipsoid *new = malloc(sizeof(struct CondEllipsoid));
324 new->center = malloc(sizeof(double) * xcsf->x_dim);
325 new->spread = malloc(sizeof(double) * xcsf->x_dim);
326 new->mu = malloc(sizeof(double) * N_MU);
327 s += fread(new->center, sizeof(double), xcsf->x_dim, fp);
328 s += fread(new->spread, sizeof(double), xcsf->x_dim, fp);
329 s += fread(new->mu, sizeof(double), N_MU, fp);
330 c->cond = new;
331 return s;
332}
333
340char *
341cond_ellipsoid_json_export(const struct XCSF *xcsf, const struct Cl *c)
342{
343 const struct CondEllipsoid *cond = c->cond;
344 cJSON *json = cJSON_CreateObject();
345 cJSON_AddStringToObject(json, "type", "hyperellipsoid");
346 cJSON *center = cJSON_CreateDoubleArray(cond->center, xcsf->x_dim);
347 cJSON *spread = cJSON_CreateDoubleArray(cond->spread, xcsf->x_dim);
348 cJSON *mutation = cJSON_CreateDoubleArray(cond->mu, N_MU);
349 cJSON_AddItemToObject(json, "center", center);
350 cJSON_AddItemToObject(json, "spread", spread);
351 cJSON_AddItemToObject(json, "mutation", mutation);
352 char *string = cJSON_Print(json);
353 cJSON_Delete(json);
354 return string;
355}
356
363void
364cond_ellipsoid_json_import(const struct XCSF *xcsf, struct Cl *c,
365 const cJSON *json)
366{
367 struct CondEllipsoid *cond = c->cond;
368 const cJSON *item = cJSON_GetObjectItem(json, "center");
369 if (item != NULL && cJSON_IsArray(item)) {
370 if (cJSON_GetArraySize(item) == xcsf->x_dim) {
371 for (int i = 0; i < xcsf->x_dim; ++i) {
372 const cJSON *item_i = cJSON_GetArrayItem(item, i);
373 cond->center[i] = item_i->valuedouble;
374 }
375 } else {
376 printf("Import error: center length mismatch\n");
377 exit(EXIT_FAILURE);
378 }
379 }
380 item = cJSON_GetObjectItem(json, "spread");
381 if (item != NULL && cJSON_IsArray(item)) {
382 if (cJSON_GetArraySize(item) == xcsf->x_dim) {
383 for (int i = 0; i < xcsf->x_dim; ++i) {
384 const cJSON *item_i = cJSON_GetArrayItem(item, i);
385 cond->spread[i] = item_i->valuedouble;
386 }
387 } else {
388 printf("Import error: spread length mismatch\n");
389 exit(EXIT_FAILURE);
390 }
391 }
392 sam_json_import(cond->mu, N_MU, json);
393}
void cond_ellipsoid_free(const struct XCSF *xcsf, const struct Cl *c)
Frees the memory used by a hyperellipsoid condition.
static const int MU_TYPE[(1)]
Self-adaptation method for mutating hyperellipsoids.
size_t cond_ellipsoid_load(const struct XCSF *xcsf, struct Cl *c, FILE *fp)
Reads a hyperellipsoid condition from a file.
void cond_ellipsoid_print(const struct XCSF *xcsf, const struct Cl *c)
Prints a hyperellipsoid condition.
size_t cond_ellipsoid_save(const struct XCSF *xcsf, const struct Cl *c, FILE *fp)
Writes a hyperellipsoid condition to a file.
char * cond_ellipsoid_json_export(const struct XCSF *xcsf, const struct Cl *c)
Returns a json formatted string representation of a hyperellipsoid.
bool cond_ellipsoid_match(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Calculates whether a hyperellipsoid condition matches an input.
void cond_ellipsoid_json_import(const struct XCSF *xcsf, struct Cl *c, const cJSON *json)
Creates a hyperellipsoid from a cJSON object.
#define N_MU
Number of hyperellipsoid mutation rates.
static double cond_ellipsoid_dist(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Returns the relative distance to a hyperellipsoid.
double cond_ellipsoid_size(const struct XCSF *xcsf, const struct Cl *c)
Returns the size of a hyperellipsoid condition.
void cond_ellipsoid_update(const struct XCSF *xcsf, const struct Cl *c, const double *x, const double *y)
Updates a hyperellipsoid, sliding the centers towards the mean input.
bool cond_ellipsoid_crossover(const struct XCSF *xcsf, const struct Cl *c1, const struct Cl *c2)
Performs uniform crossover with two hyperellipsoid conditions.
bool cond_ellipsoid_mutate(const struct XCSF *xcsf, const struct Cl *c)
Mutates a hyperellipsoid condition with the self-adaptive rate.
bool cond_ellipsoid_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_ellipsoid_init(const struct XCSF *xcsf, struct Cl *c)
Creates and initialises a hyperellipsoid condition.
void cond_ellipsoid_copy(const struct XCSF *xcsf, struct Cl *dest, const struct Cl *src)
Copies a hyperellipsoid condition from one classifier to another.
void cond_ellipsoid_cover(const struct XCSF *xcsf, const struct Cl *c, const double *x)
Generates a hyperellipsoid that matches the current input.
Hyperellipsoid condition functions.
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
Classifier data structure.
Definition xcsf.h:45
void * cond
Condition structure.
Definition xcsf.h:49
Hyperellipsoid condition data structure.
double * center
Centers.
double * spread
Spreads.
double * mu
Mutation rates.
XCSF data structure.
Definition xcsf.h:85
double rand_normal(const double mu, const double sigma)
Returns a random Gaussian with specified mean and standard deviation.
Definition utils.c:87
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 double clamp(const double a, const double min, const double max)
Returns a float clamped within the specified range.
Definition utils.h:60