use population
[maximus:bitbreeder.git] / cmetric.c
1 #include <math.h>
2
3 #define N (6 * 3 + 1)
4
5 struct metric {
6   double weight[N];
7   double target[N];
8 };
9
10 struct stats {
11   double s0[N];
12   double s1[N];
13   double s2[N];
14 };
15
16 void stats_insert(struct stats *m, const double *x) {
17   for (int i = 0; i < N; ++i) {
18     if (! isinf(x[i]) && ! isnan(x[i])) {
19       m->s0[i] += 1;
20       m->s1[i] += x[i];
21       m->s2[i] += x[i] * x[i];
22     }
23   }
24 }
25
26 void stats_delete(struct stats *m, const double *x) {
27   for (int i = 0; i < N; ++i) {
28     if (! isinf(x[i]) && ! isnan(x[i])) {
29       m->s0[i] -= 1;
30       m->s1[i] -= x[i];
31       m->s2[i] -= x[i] * x[i];
32     }
33   }
34 }
35
36 void stats_metric(struct metric *m, const struct stats *s, const double *w, const double *v) {
37   for (int i = 0; i < N; ++i) {
38     double mean   = s->s1[i] / s->s0[i];
39     double stddev = sqrt(s->s0[i] * s->s2[i] - s->s1[i] * s->s1[i]) / s->s0[i];
40     if (isinf(stddev) || isnan(stddev)) {
41       stddev = 0;
42     }
43     m->target[i] = mean + stddev * v[i];
44     m->weight[i] = w[i] / stddev;
45   }
46 }
47
48 double metric_score(const struct metric *m, const double *x) {
49   double s = 0;
50   for (int i = 0; i < N; ++i) {
51     double d = m->weight[i] * (x[i] - m->target[i]);
52     if (isinf(d) || isnan(d)) { d = 0; }
53     s += d * d;
54   }
55   return s;
56 }