openModeller  Version 1.5.0
rules_base.cpp
Go to the documentation of this file.
1 
35 #include <openmodeller/Random.hh>
36 #include <math.h>
37 #include <string.h>
38 
39 #include <openmodeller/Log.hh>
40 #include <openmodeller/Sample.hh>
42 
44 
45 #include "rules_base.hh"
46 
47 #define MIN_SIG_NO 10
48 
49 #ifdef WIN32
50 #ifndef INFINITY //in mingw this is already defined in math.h
51 #define INFINITY 1000000000
52 #endif
53 #endif
54 
55 #ifndef WIN32
56 int min(int v1, int v2)
57 {
58  return (v1 < v2)? v1 : v2;
59 }
60 #endif
61 
62 bool equalEps(double v1, double v2)
63 {
64  return (fabs(v1 - v2) < 0.000001);
65 }
66 
67 bool between(double value, double min, double max)
68 {
69  //Log::instance()->info("Between: %f <= %f <= %f? %d\n", min, value, max, ((value >= min) && (value <= max)));
70  return ((value >= min) && (value <= max));
71 }
72 
73 int membership(double value1, double value2, double value)
74 {
75  if (equalEps(value1, -1.0) && equalEps(value2, +1.0))
76  return 255;
77  else if (value < value1 || value > value2)
78  return 0;
79  else
80  return 1;
81 }
82 
83 
84 /****************************************************************/
85 /****************** GarpRule Constructor ************************/
86 
88  _chrom1(),
89  _chrom2(),
90  _prediction(0),
91  _numGenes(0),
92  _needsEvaluation(true)
93 {
94  _origin = type();
95  for (int i = 0; i < 10; i++)
96  _performance[i] = 0.0;
97 }
98 
99 GarpRule::GarpRule(int numGenes) :
100  _chrom1(numGenes, -1.0),
101  _chrom2(numGenes, +1.0),
102  _prediction(0),
103  _numGenes(numGenes),
104  _needsEvaluation(true)
105 {
106  _origin = type();
107 
108  for (int i = 0; i < 10; i++)
109  _performance[i] = 0.0;
110 }
111 
112 // *****************
113 GarpRule::GarpRule(Scalar prediction, int numGenes,
114  const Sample& chrom1, const Sample& chrom2,
115  const double * performances) :
116  _chrom1(chrom1),
117  _chrom2(chrom2),
118  _prediction(prediction),
119  _numGenes(numGenes),
120  _needsEvaluation(true),
121  _origin(OriginColonization)
122 
123 {
124  for (int i = 0; i < 10; i++)
125  { *(_performance + i) = *(performances + i); }
126 }
127 
128 /****************************************************************/
129 /****************** GarpRule Destructor *************************/
130 
132 { }
133 
135 {
136  GarpRule * newRule = objFactory();
137 
138  newRule->_numGenes = _numGenes;
139  newRule->_chrom1 = _chrom1;
140  newRule->_chrom2 = _chrom2;
141 
142  for (int i = 0; i < 10; i++)
143  newRule->_performance[i] = _performance[i];
144 
146  newRule->_prediction = _prediction;
147  newRule->_origin = _origin;
148 
149  return newRule;
150 }
151 
157 int GarpRule::copy(const GarpRule * fromRule)
158 {
159  if (type() != fromRule->type())
160  return 0;
161 
162  _chrom1 = fromRule->_chrom1;
163  _chrom2 = fromRule->_chrom2;
164 
165  for (int i = 0; i < 10; i++)
166  _performance[i] = fromRule->_performance[i];
167 
169  _prediction = fromRule->_prediction;
170  _origin = fromRule->_origin;
171 
172  return 1;
173 }
174 
175 
176 // ==========================================================================
177 double GarpRule::getPerformance(PerfIndex perfIndex) const
178 {
179  return _performance[perfIndex];
180 }
181 
182 // ==========================================================================
184 {
185  return (_prediction == pred);
186 }
187 
188 // ==========================================================================
189 double GarpRule::getError(Scalar predefinedValue, Scalar pred) const
190 {
191  return (double) fabs(predefinedValue - pred);
192 }
193 
194 // ==========================================================================
195 void GarpRule::adjustRange(Scalar& v1, Scalar& v2) const
196 {
197  if (v1 > +1.0) v1 = +1.0;
198  if (v2 > +1.0) v2 = +1.0;
199  if (v1 < -1.0) v1 = -1.0;
200  if (v2 < -1.0) v2 = -1.0;
201 
202  if (v1 > v2)
203  {
204  // swap v1 and v2
205  Scalar aux = v1;
206  v1 = v2;
207  v2 = aux;
208  }
209 }
210 
211 // ==========================================================================
212 void GarpRule::crossover(GarpRule * rule, int xpt1, int xpt2)
213 {
214  int i, diff, aux;
215  Scalar temp;
216 
217  diff = 0;
218  if (xpt1 > xpt2)
219  {
220  aux = xpt1;
221  xpt1 = xpt2;
222  xpt2 = aux;
223  }
224 
225  for ( i = xpt1; i < xpt2; i++)
226  {
227  temp = _chrom1[i];
228  _chrom1[i] = rule->_chrom1[i];
229  rule->_chrom1[i] = temp;
230  diff += (_chrom1[i] != rule->_chrom1[i]);
231 
232  temp = _chrom2[i];
233  _chrom2[i] = rule->_chrom2[i];
234  rule->_chrom2[i] = temp;
235 
236  diff += (_chrom2[i] != rule->_chrom2[i]);
237  }
238 
239  if (diff)
240  {
242  forceEvaluation();
243 
244  rule->_origin = OriginCrossover;
245  rule->forceEvaluation();
246  }
247 }
248 
249 // ==========================================================================
250 void GarpRule::mutate(double temperature)
251 {
252  Scalar rnd1, rnd2;
253  Random rnd;
254  int j;
255 
256  j = rnd.get(_numGenes);
257 
258  rnd1 = rnd.get(-temperature, +temperature);
259  rnd2 = rnd.get(-temperature, +temperature);
260 
261  _chrom1[j] -= rnd1;
262  _chrom2[j] += rnd2;
263 
264  adjustRange(_chrom1[j], _chrom2[j]);
265 
266  _needsEvaluation = true;
268 }
269 
270 // ==========================================================================
271 bool GarpRule::similar(const GarpRule * otherRule) const
272 {
273  if (type() != otherRule->type())
274  { return false; }
275 
276  // check rule value (presence/absence)
277  if (_prediction != otherRule->_prediction)
278  { return false; }
279 
280  for (int i = 0; i < _numGenes; i++)
281  {
282  // rA and rB indicates whether gene <i> is being used or not
283  bool rA = (equalEps(_chrom1[i], -1.0) &&
284  equalEps(_chrom2[i], +1.0));
285 
286  bool rB = (equalEps(otherRule->_chrom1[i], -1.0) &&
287  equalEps(otherRule->_chrom2[i], +1.0));
288 
289  if ( rA != rB )
290  { return false; }
291  }
292 
293  return true;
294 }
295 
296 // ==========================================================================
298 {
299  int i;
300 
301  double utility[10];
302 
303  //next line commented out since its not used
304  //int dimension = (*occs)[0]->environment().size();
305 
306  int n = occs->numOccurrences();
307 
308  // value of dependent variable from the current sample point
309  //next line commented out since its not used
310  //Scalar pointValue = 0.0;
311 
312  // 1 if rule applies to sample point, i.e., values satisfies rule precondition
313  // 0 otherwise
314  int strength;
315 
316  // indicates whether rule has the same conclusion as the current point
317  // (i.e., rule prediction is equal to value dependent variable)
318  int certainty;
319 
320  // error
321  double error;
322 
323  // number of points that rule applies to (sum of strength)
324  int pXs;
325 
326  // number of points with the same conclusion as the rule (sum of certainty)
327  int pYs;
328 
329  // sum of points correctly predicted by the rule
330  int pXYs;
331 
332  // number of points selected by the rule
333  int no;
334 
335  // other intermediate statistics
336  double pYcXs, pYcs;
337 
338  // prior probability
339  double priorProb;
340 
341  // note that pXSs is always equals to no, so it has been removed
342 
343  // reset counters
344  pXs = pYs = pXYs = no = 0;
345  pYcXs = pYcs = 0.0;
346 
347  // reset utility values
348  for (i = 1; i < 10; i++)
349  utility[i] = 0.0;
350 
351  utility[0] = 1.0;
352 
353  //FILE * flog = fopen("evaluate.log", "w");
354 
355  OccurrencesImpl::const_iterator it = occs->begin();
356  OccurrencesImpl::const_iterator end = occs->end();
357 
358  while (it != end)
359  {
360  // environmental (independent) variables values from current sample point
361  Scalar pointValue = ( (*it)->abundance() > 0.0 ) ? 1.0 : 0.0;
362  Sample sample = (*it)->environment();
363 
364  strength = getStrength(sample);
365  certainty = getCertainty(pointValue);
366  error = getError(0, pointValue);
367 
368  pXs += strength;
369  pYs += certainty;
370  pYcs += error;
371 
372  if (strength > 0)
373  {
374  no++;
375  pXYs += certainty; // strength is always 1, then success == certainty
376  pYcXs += getError(error, pointValue);
377  }
378 
379  ++it;
380 
381  /*
382  fprintf(flog, "Sample %5d: [%d %d %d] (%+3.2f) ",
383  i, strength, certainty, min(strength, certainty), pointValue);
384  for (u = 0; u < dimension; u++)
385  {
386  fprintf(flog, "%+8.4f ", values[u]);
387  }
388  fprintf(flog, "\n");
389  */
390  }
391 
392  if (no != pXs)
393  {
394  Log::instance()->error("Assertion failed (no != pXs): %d != %d", no, pXs);
395  throw AlgorithmException("Assertion failed");
396  }
397 
398  // Priors
399  utility[1] = pXs / (double) n; // proportion
400  utility[2] = pYs / (double) n; // Prior probability
401  utility[3] = pYcs / (double) n;
402 
403  priorProb = utility[2];
404 
405  if (no > 0)
406  {
407  utility[4] = no / (double) n; // Posterior strength
408  utility[5] = pXYs / (double) no; // Posterior probability
409  utility[6] = pYcXs / no;
410  utility[7] = no / (double) n; // Coverage
411  }
412 
413  // Crisp Significance
414  if ( (no >= MIN_SIG_NO) && (priorProb > 0) && (priorProb < 1.0))
415  {
416  utility[8] = (pXYs - priorProb * no) /
417  sqrt( no * priorProb * (1.0 - priorProb));
418  }
419 
420  //flags!!! not implemented yet
421  //if (Postflag)
422  utility[0] *= utility[5];
423 
424  //if (Sigflag)
425  utility[0] *= utility[8];
426 
427  //printf("%c] u0=%+7.3f u1=%+7.3f u2=%+7.3f u8=%+7.3f pXYs=%5d no=%4d n=%4d\n",
428  // type(), utility[0], utility[1], utility[2], utility[8], pXYs, no, n);
429 
430  //if (Compflag) utility[0] *= utility[7];
431  //if (Ecoflag) utility[0] *= ecoSpace();
432  //if (Lengthflag) utility[0] /= length();
433 
434  // Record performance in rule
435  for (i = 0; i < 10; i++)
436  _performance[i] = utility[i];
437 
438 
439  /*
440  fprintf(flog, "Sums (pXs, pYs, pXYs, n, no): %5d %5d %5d %5d %5d ([%c] pred=%+3.1f sig=%+10.4f)\n",
441  pXs, pYs, pXYs, n, no, type(), _prediction, utility[8]);
442 
443  if ((utility[8] > 15) && (_prediction == 0.0))
444  {
445  Scalar *gen = _genes;
446  Scalar *end = gen + 2 * _numGenes;
447  fprintf(flog, "Genes: ");
448  while ( gen < end )
449  fprintf(flog, "%+8.4f ", *gen++ );
450 
451  fprintf(flog, "- (%.2f) : %f\n", _prediction, getPerformance(PerfSig) );
452 
453  fclose(flog);
454  Log::instance()->error(1, "Check rule statistics"); //DEBUG
455  }
456  fclose(flog);
457  */
458 
459  /*
460  static int ii = 0;
461  if (utility[8] < 2.7)
462  printf("%4d] Rule performance is low: %+6.2f\n", ++ii, utility[8]);
463  */
464 
465  return (utility[0]);
466 }
467 
468 // ==========================================================================
470 {
471  for (int i = 0; i < _numGenes * 2; i += 2)
472  {
473  if (fabs(_chrom1[i] - _chrom2[i]) >= 2.0)
474  Log::instance()->info( "****** ****** ");
475  else
476  Log::instance()->info( "%+6.2f %+6.2f ", _chrom1[i], _chrom2[i] );
477  }
478 
479  Log::instance()->info( "- (%.2f) : %f\n", _prediction, getPerformance(PerfSig));
480 }
481 
482 // ==========================================================================
virtual void crossover(GarpRule *rule, int xpt1, int xpt2)
Definition: rules_base.cpp:212
PerfIndex
Definition: rules_base.hh:42
double get(double min, double max)
Definition: Random.cpp:54
double _performance[10]
Vector for storing the performance values for the rule.
Definition: rules_base.hh:188
virtual void log()
Definition: rules_base.cpp:469
double Scalar
Type of map values.
Definition: om_defs.hh:39
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Definition: Log.cpp:45
bool _needsEvaluation
Definition: rules_base.hh:189
Scalar _prediction
Definition: rules_base.hh:182
void error(const char *format,...)
'Error' level.
Definition: Log.cpp:290
Sample _chrom1
BYTE vector containing the genes (representation of the variables in a Genetic Algorithm.
Definition: rules_base.hh:180
char _origin
Definition: rules_base.hh:190
Definition: Random.hh:44
void forceEvaluation()
Definition: rules_base.hh:154
double evaluate(const OccurrencesPtr &occs)
Definition: rules_base.cpp:297
void adjustRange(Scalar &v1, Scalar &v2) const
Definition: rules_base.cpp:195
bool between(double value, double min, double max)
Definition: rules_base.cpp:67
int membership(double value1, double value2, double value)
Definition: rules_base.cpp:73
GarpRule()
Definition: Rule.cpp:492
virtual GarpRule * objFactory() const =0
int _numGenes
Number of genes stored by the rule.
Definition: rules_base.hh:185
virtual GarpRule * clone() const
Definition: rules_base.cpp:134
virtual int copy(const GarpRule *fromRule)
Definition: rules_base.cpp:157
bool equalEps(double v1, double v2)
Definition: rules_base.cpp:62
Sample _chrom2
Definition: rules_base.hh:181
virtual ~GarpRule()
Definition: Rule.cpp:495
virtual void mutate(double temperature)
Definition: rules_base.cpp:250
virtual int getStrength(const Sample &sample) const =0
virtual char type() const
Definition: Rule.h:122
Definition: Rule.h:116
virtual int getCertainty(const Scalar pred) const
Definition: rules_base.cpp:183
void info(const char *format,...)
'Info' level.
Definition: Log.cpp:256
double getPerformance(PerfIndex perfIndex) const
Definition: rules_base.cpp:177
virtual double getError(const Scalar predefinedValue, const Scalar prediction) const
Definition: rules_base.cpp:189
#define MIN_SIG_NO
Definition: rules_base.cpp:47
std::vector< OccurrencePtr >::const_iterator const_iterator
Definition: Occurrences.hh:85
virtual bool similar(const GarpRule *compareToRule) const
Definition: rules_base.cpp:271
int min(int v1, int v2)
Definition: rules_base.cpp:56
Definition: Sample.hh:25
static char error[256]
Definition: FileParser.cpp:42