openModeller  Version 1.4.0
RuleSet.cpp
Go to the documentation of this file.
00001 
00002 /* **************************************
00003  *  GARP Modeling Package
00004  *
00005  * **************************************
00006  *
00007  * Copyright (c), The Center for Research, University of Kansas, 2385 Irving Hill Road, Lawrence, KS 66044-4755, USA.
00008  * Copyright (C), David R.B. Stockwell of Symbiotik Pty. Ltd.
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the license that is distributed with the software.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * license.txt file included with this software for more details.
00017  */
00018 
00019 // RuleSet.cpp : Implementation of CRuleSet
00020 
00021 #ifdef WIN32
00022 // avoid warnings caused by problems in VC headers
00023 #define _SCL_SECURE_NO_DEPRECATE
00024 #endif
00025 
00026 #include "Rule.h"
00027 #include "RuleSet.h"
00028 #include "EnvCell.h"
00029 #include "EnvCellSet.h"
00030 #include "Utilities.h"
00031 
00032 // ==========================================================================
00033 //  RuleSet implementation
00034 // ==========================================================================
00035 RuleSet::RuleSet() 
00036 {
00037   // rule set starts empty (without rules)
00038   intRules = 0;
00039 
00040   // reset rule pointers
00041   for (int i = 0; i < MAX_RULES; i++)
00042     objRules[i] = NULL;
00043 
00044   // reset area counters
00045   iTotalArea = iPresenceArea = iAbsenceArea = iNonPredictedArea = 0;
00046 }
00047 
00048 // ==========================================================================
00049 RuleSet::~RuleSet() 
00050 {
00051   clear();
00052 }
00053 
00054 // ==========================================================================
00055 void RuleSet::clear()
00056 {
00057   for (int i = 0; i < intRules; i++)
00058     if (objRules[i])
00059     {
00060       delete objRules[i];
00061       objRules[i] = NULL;
00062     }
00063 
00064   // rule set become empty (without rules)
00065   intRules = 0;
00066 
00067   // reset area counters
00068   iTotalArea = iPresenceArea = iAbsenceArea = iNonPredictedArea = 0;
00069 }
00070 
00071 // ==========================================================================
00072 void RuleSet::setActiveGenes(bool * bGeneIsActivePtr, int * iGeneIndexPtr, int iActiveGenesAux)
00073 {
00074   for (int i = 0; i < intRules; i++)
00075   {
00076     objRules[i]->bGeneIsActive = bGeneIsActivePtr;
00077     objRules[i]->iGeneIndex = iGeneIndexPtr;
00078     objRules[i]->iActiveGenes = iActiveGenesAux;
00079   }
00080 }
00081 
00082 // ==========================================================================
00083 char * RuleSet::toXML(char * id)
00084 {
00085   /* XML Sample
00086 
00087      <RuleSet Id="Best">
00088      <Rule>...</Rule>
00089      .      .
00090      .      . 
00091      .      .
00092      <Rule>...</Rule>
00093      </RuleSet>
00094      */
00095 
00096   int i;
00097   int size;
00098   char * strXML, *strXMLRule;
00099 
00100   size = (1024 * intRules) + 2048;
00101   strXML = new char[size];
00102 
00103 
00104   // rules
00105   if (!id)
00106     strcpy(strXML, "<RuleSet>\n");
00107   else
00108     sprintf(strXML, "<RuleSet Id=\"%s\">\n", id);
00109 
00110   for (i = 0; i < intRules; i++)
00111   {
00112     strXMLRule = objRules[i]->toXML();
00113     sprintf(strXML, "%s%s\n", strXML, strXMLRule);
00114     delete[] strXMLRule;
00115   }
00116   strcat(strXML, "</RuleSet>");
00117 
00118   // check string sizes
00119   if (strlen(strXML) > size_t(size))
00120     throw GarpException(82, "String size exceeded in RuleSet::toXML()");
00121 
00122   // return result
00123   return strXML;
00124 }
00125 
00126 // ==========================================================================
00127 void RuleSet::saveText(char * strSaveFilename)
00128 {
00129   FILE * outf;
00130   int i;
00131 
00132   if (strcmp(strSaveFilename, "") == 0)
00133     throw GarpException(3, "Cannot save rule set with an empty filename");
00134 
00135   outf = fopen(strSaveFilename, "w");
00136 
00137   if (outf)
00138   {
00139     for (i = 0; i < intRules; i++)
00140       fprintf(outf, "%s\n", objRules[i]->toString());
00141 
00142     fclose(outf);
00143   }
00144   else
00145   {
00146     char msg[256];
00147     sprintf(msg, "Rule set file <%s> could not be opened for writing", strSaveFilename);
00148     throw GarpException(4, msg);
00149   }
00150 }
00151 
00152 // ==========================================================================
00153 Rule * RuleSet::get(int index)
00154 { return objRules[index]; }
00155 
00156 // ==========================================================================
00157 int RuleSet::size()
00158 { return intRules; }
00159 
00160 // ==========================================================================
00161 void RuleSet::set(int index, Rule * objRule)
00162 { objRules[index] = objRule; }
00163 
00164 // ==========================================================================
00165 void RuleSet::add(Rule * objRule)
00166 {
00167   if (objRule)
00168   {
00169     if (intRules < MAX_RULES - 1)
00170       objRules[intRules++] = objRule;
00171     else
00172       throw GarpException(16, "Cannot add rule. Ruleset is full");
00173   }
00174   else
00175     throw GarpException(17, "Cannot add null rule");
00176 }
00177 
00178 // ==========================================================================
00179 void RuleSet::trim(int intMaxRules)
00180 {
00181   int intInitialRules = intRules;
00182   for (int i = intMaxRules; i < intInitialRules; i++)
00183   {
00184     delete objRules[i];
00185     objRules[i] = NULL;
00186     intRules--;
00187   }
00188 }
00189 
00190 // ==========================================================================
00191 //  Discard rules which performance (determined by the iPerfIndex) is less
00192 //   than the specified dValue
00193 // ==========================================================================
00194 void RuleSet::discardRules(int iPerfIndex, double dValue)
00195 {
00196   int i, j;
00197 
00198   i = 0;
00199   while (i < intRules)
00200   {
00201     if (!GarpUtil::equalEps(objRules[i]->dblPerformance[8], objRules[i]->_dSig, 0.0001))
00202       throw GarpException(1, "The actual and calculated significance values of this rule do not match.");
00203 
00204     if (objRules[i]->dblPerformance[iPerfIndex] < dValue)
00205     {
00206       // this rule has not enough performance
00207       // delete rule 
00208       delete objRules[i];
00209 
00210       // and shift rules up
00211       for (j = i; j < intRules - 1; j++)
00212         objRules[j] = objRules[j + 1];
00213 
00214       // remove the duplicated reference to the last rule
00215       objRules[intRules - 1] = NULL;
00216 
00217       // update the number of rules in this set
00218       // no need to increment <i> because the rules were shifted up one position
00219       intRules--;
00220     }
00221     else
00222     {
00223       // this rule passed the test
00224       // go to the next one
00225       i++;
00226     }
00227   }
00228 }
00229 
00230 // ==========================================================================
00231 void RuleSet::setEvaluation(bool value)
00232 {
00233   for (int i = 0; i < intRules; i++)
00234     objRules[i]->blnNeedsEvaluation = value;
00235 }
00236 
00237 // ==========================================================================
00238 void RuleSet::setPad(char pad)
00239 {
00240   for (int i = 0; i < intRules; i++)
00241     objRules[i]->chrPad = pad;
00242 }
00243 
00244 // ==========================================================================
00245 int RuleSet::countPad(char pad)
00246 {
00247   int sum = 0;
00248 
00249   for (int i = 0; i < intRules; i++)
00250     if (objRules[i]->chrPad == pad)
00251       sum++;
00252 
00253   return sum;
00254 }
00255 
00256 // ==========================================================================
00257 void RuleSet::sort(int intPerfIndex)
00258 {
00259   // sort the entire ruleset using the provided performance index 
00260   // implemented using bubble sort (argh!!) to be improved
00261   Rule * temp;
00262   int i, j;
00263 
00264   double dSum;
00265 
00266   dSum = 0.0;
00267   for (i = 0; i < this->intRules; i++)
00268     dSum += objRules[i]->dblPerformance[9];
00269 
00270   for (i = 0; i < intRules - 1; i++)
00271     for (j = intRules - 1; j > i; j--)
00272       if (objRules[j]->dblPerformance[intPerfIndex] > objRules[j - 1]->dblPerformance[intPerfIndex])
00273       {
00274         temp = objRules[j];
00275         objRules[j] = objRules[j - 1];
00276         objRules[j - 1] = temp;
00277       }
00278 }
00279 
00280 // ==========================================================================
00281 void RuleSet::verify(EnvCellSet * objTestDataset, double dAccLimit)
00282 {
00283   EnvCell * cell;
00284   int iRuleIndex, iPredictedValue, iActualValue;
00285   int i, n;
00286 
00287   double dSum;
00288 
00289   dSum = 0.0;
00290   for (i = 0; i < this->intRules; i++)
00291     dSum += objRules[i]->dblPerformance[9];
00292 
00293   // init temp structures
00294   resetConfMatrix(objTestDataset);
00295 
00296   n = objTestDataset->count();
00297   for (i = 0; i < n; i++)
00298   {
00299     // apply rules to each cell in the dataset
00300     cell = objTestDataset->get(i);
00301     iRuleIndex = applyRulesToCell(cell, dAccLimit);
00302 
00303     if (iRuleIndex >= 0)
00304     {
00305       // rule applies
00306       iPredictedValue = objRules[iRuleIndex]->Gene[0];
00307       iActualValue    = cell->values[0];
00308 
00309       addConfMatrix(iPredictedValue, iActualValue);
00310     }
00311   }
00312 
00313   dSum = 0.0;
00314   for (i = 0; i < this->intRules; i++)
00315     dSum += objRules[i]->dblPerformance[9];
00316 }
00317 
00318 // ==========================================================================
00319 void RuleSet::resetConfMatrix(EnvCellSet * objTestDataset)
00320 {
00321   // init temp structures
00322   iConfMatrix[0][0] = 0;
00323   iConfMatrix[0][1] = 0;
00324   iConfMatrix[1][0] = 0;
00325   iConfMatrix[1][1] = 0;
00326 
00327   iTotalPoints = objTestDataset->count();
00328 }
00329 // ==========================================================================
00330 int RuleSet::getConfMatrix(int iPredictedValue, int iActualValue)
00331 {
00332   if ((iActualValue < 0) || (iActualValue > 1) || (iPredictedValue < 0) || (iPredictedValue > 1))
00333     throw GarpException(1, "Confusion matrix index out of range");
00334 
00335   return iConfMatrix[iActualValue][iPredictedValue];
00336 }
00337 
00338 // ==========================================================================
00339 void RuleSet::addConfMatrix(int iPredictedValue, int iActualValue)
00340 {
00341   if ((iActualValue < 0) || (iActualValue > 1) || (iPredictedValue < 0) || (iPredictedValue > 1))
00342     throw GarpException(1, "Confusion matrix index out of range");
00343 
00344   iConfMatrix[iActualValue][iPredictedValue]++;
00345 }
00346 
00347 // ==========================================================================
00348 int RuleSet::getTotalPoints()
00349 { 
00350   return iTotalPoints; 
00351 }
00352 // ==========================================================================
00353 int RuleSet::getPredictedPoints()
00354 {
00355   return (iConfMatrix[0][0] + iConfMatrix[0][1] + iConfMatrix[1][0] + iConfMatrix[1][1]);
00356 }
00357 
00358 // ==========================================================================
00359 int RuleSet::getUnpredictedPoints()
00360 {
00361   return getTotalPoints() - getPredictedPoints();
00362 }
00363 
00364 // ==========================================================================
00365 double RuleSet::getAccuracy()
00366 {
00367   return (double) (iConfMatrix[0][0] + iConfMatrix[1][1]) / (double) getPredictedPoints();
00368 }
00369 // ==========================================================================
00370 double RuleSet::getOverallAccuracy()
00371 {
00372   return (double) (iConfMatrix[0][0] + iConfMatrix[1][1]) / (double) getTotalPoints();
00373 }
00374 
00375 // ==========================================================================
00376 void RuleSet::updateRuleUsage()
00377 {
00378   throw GarpException(131, "Method RuleSet::updateRuleUsage not implemented yet");
00379 }
00380 
00381 // ==========================================================================
00382 double RuleSet::getOveralPerformance(int iPerfIndex, int iFirstRulesToBeIncluded)
00383 {
00384   int i;
00385   double dResult, dWeight, dWSum;
00386 
00387   dWSum   = 0.0;
00388   dResult = 0.0;
00389   dWeight = (double) iFirstRulesToBeIncluded;
00390 
00391   for (i = 0; i < iFirstRulesToBeIncluded; i++)
00392   {
00393     if (i < intRules)
00394     {
00395       dResult += objRules[i]->dblPerformance[iPerfIndex] * dWeight;
00396       dWSum += dWeight;
00397       dWeight--;
00398 
00399       //dResult += objRules[i]->dblPerformance[iPerfIndex];
00400     }
00401     else
00402       break;
00403   }
00404 
00405   dResult /= dWSum;
00406 
00407   return dResult;
00408 }
00409 
00410 // ==========================================================================
00411 Scalar RuleSet::getValue(const Sample& sample) const
00412 {
00413   // convert values to EnvCell
00414   BYTE bytes[256];
00415   EnvCell cell(_dim + 2, bytes);
00416 
00417   // first element of bytes is reserved for presence/absence value
00418   for (int i = 1; i < _dim; i++)
00419   {
00420     // Guard against values outside the normalization range
00421     // due to reprojection to a non-native range
00422     Scalar value = sample[i - 1];
00423     if (value > 253.0) value = 253.0;
00424     if (value < 1.0)   value = 1.0;
00425 
00426     bytes[i] = (BYTE) value;
00427   }
00428 
00429   int ruleIndex = applyRulesToCell(&cell, 0.0);
00430   //printf(" Idx=%+2d Pred=%+4.1f\n", ruleIndex, (ruleIndex >= 0)? (Scalar) (objRules[ruleIndex]->Gene[0]) : -1.0);
00431 
00432   if (ruleIndex >= 0)
00433     return (Scalar) (objRules[ruleIndex]->Gene[0]);
00434 
00435   return 0.0;
00436 }
00437 
00438 // ==========================================================================
00439 void RuleSet::log()
00440 {
00441   for ( int i = 0; i < intRules; i++ )
00442   {
00443     printf( "%2d] ", i );
00444     objRules[i]->log();
00445   }
00446 }
00447 
00448 /*
00449 // ==========================================================================
00450 void RuleSet::predict(EnvLayer * objPredictionLayer, EnvLayerSet * objPredictionArea, double Accuracylimit)
00451 {
00452 int row, col, pos;
00453 int intRows, intColumns, intSize;
00454 int ruleIndex;
00455 bool status;
00456 BYTE bytPred;
00457 EnvCell cell;
00458 BYTE values[MAX_ENV_LAYERS];
00459 
00460 intRows    = objPredictionArea->rows();
00461 intColumns = objPredictionArea->columns();
00462 
00463 // number of values in each cell (including species and mask values (+2)
00464 intSize    = objPredictionArea->size() + 2;
00465 
00466 // reset position counter
00467 pos = 0;
00468 
00469 // set cell parameters
00470 cell.setSize(intSize);
00471 cell.setValues(values);
00472 
00473 // reset area counters
00474 iTotalArea = iPresenceArea = iAbsenceArea = iNonPredictedArea = 0;
00475 
00476 // new prediction algorithm
00477 // for each cell do
00478 // visit each row
00479 for (row = 0; row < intRows; row++)
00480 {
00481 // visit each column within the current row
00482 for (col = 0; col < intColumns; col++)
00483 {
00484 // get current position
00485 //pos = (row * intColumns) + col;
00486 
00487 // get current cell value
00488 status = objPredictionArea->getValue(pos, &cell);
00489 
00490 // check if cell is not masked
00491 if (status) 
00492 {
00493 // NOTE: the element Item[0] should never be used in prediction!!!
00494 // we don't need the datapoints to project the model back to the env. layers
00495 
00496 // cell is not masked: add one cell to the total area counter
00497 iTotalArea++;
00498 
00499 // check which (if any) rule apply to this cell
00500 ruleIndex = applyRulesToCell(&cell, Accuracylimit);
00501 
00502 // if there is a rule that applies to this cell, write the rule value to file
00503 if (ruleIndex >= 0)
00504 {
00505 // rule <ruleIndex> applies: write its value to output layer
00506 bytPred = (BYTE) objRules[ruleIndex]->Gene[0];
00507 objPredictionLayer->set(pos, bytPred);
00508 
00509 // increment area counter (depending on the prediction)
00510 if (bytPred == PRESENCE)
00511 iPresenceArea++;
00512 else if (bytPred == ABSENCE)
00513 iAbsenceArea++;
00514 }
00515 
00516 else
00517 {
00518 // no rule applies: write NODATA
00519 objPredictionLayer->set(pos, (BYTE) MISSING_VALUE);
00520 iNonPredictedArea++;
00521 }
00522 
00523 }
00524 else
00525 {
00526   // if it is masked then write NODATA to cell
00527   objPredictionLayer->set(pos, (BYTE) MASK_VALUE);
00528 }
00529 
00530 // visit next cell
00531 pos++;
00532 }
00533 
00534 
00535 //GarpProgressEvents::fireProcessEvent((int) (row * 100 / intRows), 0, 0);
00536 }
00537 
00538 //GarpProgressEvents::fireProcessEvent(100, 0, 0);
00539 }
00540 
00541 // ==========================================================================
00542 void RuleSet::predictRuleCoverage(EnvLayer * objPredictionLayer, EnvLayerSet * objPredictionArea, double Accuracylimit)
00543 {
00544   int row, col, pos;
00545   int intRows, intColumns, intSize;
00546   int ruleIndex;
00547   bool status;
00548   EnvCell cell;
00549   BYTE values[MAX_ENV_LAYERS];
00550 
00551   intRows    = objPredictionArea->rows();
00552   intColumns = objPredictionArea->columns();
00553 
00554   // number of values in each cell (including species and mask values (+2)
00555   intSize    = objPredictionArea->size() + 2;
00556 
00557   // reset position counter
00558   pos = 0;
00559 
00560   // set cell parameters
00561   cell.setSize(intSize);
00562   cell.setValues(values);
00563 
00564   // new prediction algorithm
00565   // for each cell do
00566   // visit each row
00567   for (row = 0; row < intRows; row++)
00568   {
00569     // visit each column within the current row
00570     for (col = 0; col < intColumns; col++)
00571     {
00572       // get current position
00573       //pos = (row * intColumns) + col;
00574 
00575       // get current cell value
00576       status = objPredictionArea->getValue(pos, &cell);
00577 
00578       // check if cell is not masked
00579       if (status) 
00580       {
00581         // NOTE: the element Item[0] should never be used in prediction!!!
00582         // we don't need the datapoints to project the model back to the env. layers
00583 
00584         // check which (if any) rule apply to this cell
00585         ruleIndex = applyRulesToCell(&cell, Accuracylimit);
00586 
00587         // if there is a rule that applies to this cell, write the rule value to file
00588         if (ruleIndex >= 0)
00589         {
00590           // rule <ruleIndex> applies: write its value to output layer
00591           //objPredictionLayer->set(pos, (BYTE) objRules[ruleIndex]->Gene[0]);
00592           objPredictionLayer->set(pos, (BYTE) ruleIndex + 1);
00593         }
00594 
00595         else
00596         {
00597           // no rule applies: write NODATA
00598           objPredictionLayer->set(pos, (BYTE) MISSING_VALUE);
00599         }
00600 
00601       }
00602       else
00603       {
00604         // if it is masked then write NODATA to cell
00605         objPredictionLayer->set(pos, (BYTE) MASK_VALUE);
00606       }
00607 
00608       // visit next cell
00609       pos++;
00610     }
00611 
00612 
00613     //GarpProgressEvents::fireProcessEvent((int) (row * 100 / intRows), 0, 0);
00614   }
00615 
00616   //GarpProgressEvents::fireProcessEvent(100, 0, 0);
00617 }
00618 
00619 */
00620 
00621 // ==========================================================================
00622 int RuleSet::applyRulesToCell(EnvCell * cell, double Accuracylimit) const
00623 {
00624   int i, maxi, ruleIndex;
00625   double u, max;
00626   int b_membership[256]; 
00627 
00628   for (i = 0; i < 256; i++)
00629     b_membership[i] = 0;
00630 
00631   max = maxi = 0;
00632 
00633   ruleIndex = -1;
00634 
00635   // check every rule
00636   i = 0;
00637   while ((i < intRules) && (ruleIndex == -1))
00638   {
00639     // get the 5th performance value
00640     u = (int)(255.0 * objRules[i]->dblPerformance[5]);
00641 
00642     if (objRules[i]->dblPerformance[5] >= Accuracylimit)
00643     {
00644       if (objRules[i]->applyToCell(cell))
00645       {
00646         ruleIndex = i;
00647 
00648         // update value for 
00649         if (objRules[i]->intScreen)
00650         {
00651           if (b_membership[objRules[i]->Gene[0]] < u) 
00652             b_membership[objRules[i]->Gene[0]] = (int) u;
00653 
00654           if (max < u) 
00655           {
00656             max  = u;
00657             maxi = i;
00658           }
00659         }
00660       }
00661     }
00662 
00663     // check next rule
00664     i++;
00665   }
00666 
00667   if (max) 
00668     objRules[maxi]->dblPerformance[9]++;
00669 
00670   return ruleIndex;
00671 }
00672 
00673 /*
00674 // ==========================================================================
00675 bool RuleSet::projectRuleSet(EnvLayerSet * oToLayerSet, bool bConservative, RuleSet * oToRuleSet)
00676 {
00677 // check if rule set is not null
00678 if ((intRules <= 0) || (objModelLayerSet->size() == 0) || (oToLayerSet->size() == 0) ||
00679 (objModelLayerSet->size() != oToLayerSet->size()))
00680 return false;
00681 
00682 // this code does not work right, I guess. See the other implementation below it
00683 int i, j, iLayers;
00684 int iNatMin[MAX_ENV_LAYERS];
00685 int iNatMax[MAX_ENV_LAYERS];
00686 int iProjMin[MAX_ENV_LAYERS];
00687 int iProjMax[MAX_ENV_LAYERS];
00688 double dFactor[MAX_ENV_LAYERS];
00689 
00690 EnvLayer * oNat, *oProj;
00691 
00692 // find out how many genes a rule have
00693 iLayers = objModelLayerSet->size();
00694 
00695 // now calculate the factor, min and max values for each gene
00696 // those values will be used to modify the gene values in the
00697 // result dataset
00698 for (i = 0; i < iLayers; i++)
00699 {
00700 // get one layer from native range
00701 // and other from projection area
00702 oNat  = objModelLayerSet->getLayerByIndex(i);
00703 oProj = oToLayerSet->getLayerByIndex(i);
00704 
00705 // get projection values for each gene
00706 // min values
00707 if (oNat->dblMinValue > oProj->dblMinValue)
00708 {
00709 iNatMin[i] = MIN_SCALED_VALUE;
00710 iProjMin[i] = oProj->scale(oNat->dblMinValue);
00711 }
00712 else
00713 {
00714 iNatMin[i] = oNat->scale(oProj->dblMinValue);
00715 iProjMin[i] = MIN_SCALED_VALUE;
00716 }
00717 
00718 // now max values
00719 if (oNat->dblMaxValue > oProj->dblMaxValue)
00720 {
00721 iNatMax[i] = MAX_SCALED_VALUE;
00722 iProjMax[i] = oProj->scale(oNat->dblMaxValue);
00723 }
00724 else
00725 {
00726 iNatMax[i] = oNat->scale(oProj->dblMaxValue);
00727 iProjMax[i] = MAX_SCALED_VALUE;
00728 }
00729 
00730 dFactor[i] = (((double) iProjMax[i] - (double) iProjMin[i]) / 
00731 ((double) iNatMax[i]  - (double) iNatMin[i]));
00732 }
00733 
00734 // first clear the rule set
00735 oToRuleSet->trim(0);
00736 
00737 // copy the rules to the result rule set and modify the rules
00738 for (j = 0; j < intRules; j++)
00739 {
00740 Rule * oAuxRule;
00741 
00742 // get a clone of the ith rule in the current 
00743 oAuxRule = objRules[j]->clone();
00744 
00745 // modify the gene values
00746 // projecting the values from the Native Dataset to the projection area
00747 // jump first gene (rule value for the species - 
00748 // - presence or absence - cannot project these values)
00749 for (i = 0; i < iLayers; i++)
00750 {
00751 int iOldValue1, iOldValue2;
00752 int iNewValue1, iNewValue2;
00753 
00754 iOldValue1 = (int) oAuxRule->Gene[(i + 1) * 2];
00755 iOldValue2 = (int) oAuxRule->Gene[(i + 1) * 2 + 1];
00756 
00757 iNewValue1 = (int) ((iOldValue1 - iNatMin[i]) * dFactor[i]) + iProjMin[i];
00758 iNewValue2 = (int) ((iOldValue2 - iNatMin[i]) * dFactor[i]) + iProjMin[i];
00759 
00760 // correct the values to avoid values out of range
00761 if (iNewValue1 < 0)
00762   iNewValue1 = 0;
00763 else if (iNewValue1 > 255)
00764   iNewValue1 = 255;
00765 
00766 if (iNewValue2 < 0)
00767   iNewValue2 = 0;
00768 else if (iNewValue2 > 255)
00769   iNewValue2 = 255;
00770 
00771   // decide if it is an conservative or liberal projection
00772   // In conservative projections, if the value of a gene
00773   // is in one of the bounds of the native range layer value,
00774   // this value is mapped to the correspondent value to the
00775   // projection area. In liberal projections, a value in one
00776   // of the bounds of the layer values means that the rule 
00777   // applies for all values above (or below) that gene value
00778 
00779 if (iOldValue1 == 0 && !bConservative)
00780   iNewValue1 = 0;
00781 
00782 if (iOldValue2 == 0 && !bConservative)
00783   iNewValue2 = 0;
00784 
00785   oAuxRule->Gene[(i + 1) * 2]     = (BYTE) iNewValue1;
00786   oAuxRule->Gene[(i + 1) * 2 + 1] = (BYTE) iNewValue2;
00787   }
00788 
00789 // add rule to the rule set
00790 oToRuleSet->add(oAuxRule);
00791 } 
00792 
00793 //
00794 
00795 int i, j, iLayers;
00796 int iOldValue1, iOldValue2;
00797 int iNewValue1, iNewValue2;
00798 EnvLayer * oNat, *oProj;
00799 Rule * oAuxRule;
00800 
00801 // find out how many genes a rule have
00802 iLayers = objModelLayerSet->size();
00803 
00804 // first clear the rule set
00805 oToRuleSet->trim(0);
00806 
00807 // copy the rules to the result rule set and modify the rules
00808 for (j = 0; j < intRules; j++)
00809 {
00810   // get a clone of the ith rule in the current 
00811   oAuxRule = objRules[j]->clone();
00812 
00813   // logit rules cannot be projected using this approach
00814   // so, for now, let's just copy them and hope for the best
00815   // that means, for logit rules, projection will disconsider the difference in the range of values
00816   if (oAuxRule->type() != 'r')
00817   {
00818     // modify the gene values
00819     // projecting the values from the Native Dataset to the projection area
00820     // jump first gene (rule value for the species - 
00821     // - presence or absence - cannot project these values)
00822     for (i = 0; i < iLayers; i++)
00823     {
00824       oNat  = objModelLayerSet->getLayerByIndex(i);
00825       oProj = oToLayerSet->getLayerByIndex(i);
00826 
00827       // assertion
00828       //if ((oAuxRule->Gene[(i + 1) * 2]     != objRules[j]->Gene[(i + 1) * 2]) || 
00829       //  (oAuxRule->Gene[(i + 1) * 2 + 1] != objRules[j]->Gene[(i + 1) * 2 + 1]))
00830       //  return false;
00831       //
00832 
00833       iOldValue1 = (int) oAuxRule->Gene[(i + 1) * 2];
00834       iOldValue2 = (int) oAuxRule->Gene[(i + 1) * 2 + 1];
00835 
00836       iNewValue1 = (int) oProj->scale(oNat->unscale(iOldValue1) + 0.000000000001);
00837       iNewValue2 = (int) oProj->scale(oNat->unscale(iOldValue2) + 0.000000000001);
00838 
00839       // correct the values to avoid values out of range
00840       if (iNewValue1 < 0)
00841         iNewValue1 = 1;
00842       else if (iNewValue1 > 255)
00843         iNewValue1 = 254;
00844 
00845       if (iNewValue2 < 0)
00846         iNewValue2 = 1;
00847       else if (iNewValue2 > 255)
00848         iNewValue2 = 254;
00849 
00850       // decide if it is an conservative or liberal projection
00851       // In conservative projections, if the value of a gene
00852       // is in one of the bounds of the native range layer value,
00853       // this value is mapped to the correspondent value to the
00854       // projection area. In liberal projections, a value in one
00855       // of the bounds of the layer values means that the rule 
00856       // applies for all values above (or below) that gene value
00857 
00858       if (iOldValue1 == 0 && !bConservative)
00859         iNewValue1 = 0;
00860 
00861       if (iOldValue2 == 0 && !bConservative)
00862         iNewValue2 = 0;
00863 
00864       if (iOldValue1 == 255 && !bConservative)
00865         iNewValue1 = 255;
00866 
00867       if (iOldValue2 == 255 && !bConservative)
00868         iNewValue2 = 255;
00869 
00870       oAuxRule->Gene[(i + 1) * 2]     = (BYTE) iNewValue1;
00871       oAuxRule->Gene[(i + 1) * 2 + 1] = (BYTE) iNewValue2;
00872     }
00873   } // end if oAuxRule->type() != 'r'
00874 
00875   // add rule to the rule set
00876   oToRuleSet->add(oAuxRule);
00877 }
00878 
00879 oToRuleSet->objModelLayerSet = oToLayerSet;
00880 
00881 return true;
00882 }
00883 */
00884 // ==========================================================================
00885 
00886 // ==============================================================
00887 
00888 // gather rule set statistics
00889 void RuleSet::gatherRuleSetStats(int gen)
00890 {
00891   char type='0'; //initialise to something invalid
00892 
00893   printf("%4d]", gen);
00894 
00895   for (int i = 0; i < 3; i++)
00896   {
00897     switch (i)
00898     {
00899       case 0: type ='d'; break;
00900       case 1: type ='!'; break;
00901       case 2: type ='r'; break;
00902               //case 3: type ='a'; break;
00903     }
00904 
00905     double max = -10000;
00906     double sum = 0;
00907     int ct = 0;
00908     int pres = 0;
00909     for (int j = 0; j < intRules; j++)
00910     {
00911       Rule * rule = objRules[j];
00912       if (rule->type() == type)
00913       {
00914         ct++;
00915         sum += rule->dblPerformance[0];
00916         pres += (int) rule->Gene[0];
00917         if (max < rule->dblPerformance[0])
00918           max = rule->dblPerformance[0];
00919       }
00920     }
00921 
00922     if (max == -10000)
00923       max = 0;
00924 
00925     printf("%c %2d %+7.2f %+7.2f %2d|", type, ct, max, sum / ct, pres);
00926   }
00927 
00928   printf("\n");
00929 }