00001 #include "ECF_base.h"
00002
00003 const int RANDOM_GENOTYPE = 0;
00004 const int ALL_GENOTYPES = 1;
00005
00006
00010 void Crossover::registerParameters(StateP state)
00011 {
00012 state->getRegistry()->registerEntry("crossover.genotypes", (voidP) new std::string("random"), ECF::STRING,
00013 "if there are multiple genotypes, which to cross? 'random': a random pair, 'all': all pairs (default: random)");
00014 state->getRegistry()->registerEntry("crossover.protected", (voidP) new std::string(""), ECF::STRING,
00015 "indexes of genotypes (separated by spaces) that are excluded (protected) from crossover (default: none)");
00016 }
00017
00018
00022 bool Crossover::initialize(StateP state)
00023 {
00024 state_ = state;
00025 protectedGenotypes_.clear();
00026 protectedGenotypes_.insert(protectedGenotypes_.begin(), operators.size(), false);
00027 opProb.clear();
00028
00029 voidP sptr = state->getRegistry()->getEntry("crossover.genotypes");
00030 std::string crxGen = *((std::string*)sptr.get());
00031
00032 crxGenotypes_ = RANDOM_GENOTYPE;
00033 if(crxGen == "all")
00034 crxGenotypes_ = ALL_GENOTYPES;
00035 else if(crxGen == "random")
00036 crxGenotypes_ = RANDOM_GENOTYPE;
00037 else
00038 ECF_LOG_ERROR(state, "Warning: invalid parameter value (key: crossover.genotypes)");
00039
00040
00041 std::stringstream ss;
00042 sptr = state->getRegistry()->getEntry("crossover.protected");
00043 ss << *((std::string*) sptr.get());
00044 uint genId;
00045 while(ss >> genId) {
00046 if(genId >= protectedGenotypes_.size()) {
00047 ECF_LOG_ERROR(state, "Error: invalid genotype index (key: crossover.protected)!");
00048 throw("");
00049 }
00050 protectedGenotypes_[genId] = true;
00051 }
00052
00053
00054 for(uint gen = 0; gen < operators.size(); gen++) {
00055 uint nOps = (uint) operators[gen].size();
00056
00057 if(nOps == 0) {
00058 protectedGenotypes_[gen] = true;
00059 std::vector<double> empty;
00060 opProb.push_back(empty);
00061 break;
00062 }
00063 for(uint i = 0; i < nOps; i++) {
00064 operators[gen][i]->state_ = state;
00065 operators[gen][i]->initialize(state);
00066 }
00067
00068 std::vector<double> probs(nOps);
00069 probs[0] = operators[gen][0]->probability_;
00070 for(uint i = 1; i < nOps; i++) {
00071 probs[i] = probs[i - 1] + operators[gen][i]->probability_;
00072 }
00073 if(probs[nOps - 1] == 0)
00074 probs[0] = -1;
00075 else
00076 if(probs[nOps - 1] != 1) {
00077 double normal = probs[nOps - 1];
00078 ECF_LOG_ERROR(state, "Warning: " + operators[gen][0]->myGenotype_->getName() +
00079 " crossover operators: cumulative probability not equal to 1 (sum = " + dbl2str(normal) + ")");
00080 for(uint i = 0; i < probs.size(); i++)
00081 probs[i] /= normal;
00082 }
00083 opProb.push_back(probs);
00084 }
00085 return true;
00086 }
00087
00088
00095 bool Crossover::mate(IndividualP ind1, IndividualP ind2, IndividualP child)
00096 {
00097 child->fitness->setInvalid();
00098
00099 state_->getContext()->firstParent = ind1;
00100 state_->getContext()->secondParent = ind2;
00101 state_->getContext()->child = child;
00102 ECF_LOG(state_, 5, "Crossover, 1st parent: " + ind1->toString()
00103 + "\nCrossover, 2nd parent: " + ind2->toString());
00104
00105
00106 if(ind1 == child) {
00107 ind1 = (IndividualP) ind1->copy();
00108 }
00109 if(ind2 == child) {
00110 ind2 = (IndividualP) ind2->copy();
00111 }
00112
00113
00114
00115
00116 if(crxGenotypes_ == RANDOM_GENOTYPE) {
00117 uint iGenotype = state_->getRandomizer()->getRandomInteger((int)ind1->size());
00118 if(protectedGenotypes_[iGenotype])
00119 return false;
00120
00121 for(uint i = 0; i < iGenotype; i++)
00122 child->at(i) = (GenotypeP) ind1->at(i)->copy();
00123 for(uint i = iGenotype + 1; i < child->size(); i++)
00124 child->at(i) = (GenotypeP) ind2->at(i)->copy();
00125
00126 uint iOperator;
00127 if(opProb[iGenotype][0] < 0)
00128 iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size());
00129 else {
00130 double random = state_->getRandomizer()->getRandomDouble();
00131 iOperator = 0;
00132 while(opProb[iGenotype][iOperator] < random)
00133 iOperator++;
00134 }
00135 operators[iGenotype][iOperator]->mate(ind1->at(iGenotype), ind2->at(iGenotype), child->at(iGenotype));
00136 }
00137
00138 else if(crxGenotypes_ == ALL_GENOTYPES) {
00139 for(uint iGenotype = 0; iGenotype < ind1->size(); iGenotype++) {
00140 if(protectedGenotypes_[iGenotype])
00141 continue;
00142
00143 uint iOperator;
00144 if(opProb[iGenotype][0] < 0)
00145 iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size());
00146 else {
00147 double random = state_->getRandomizer()->getRandomDouble();
00148 iOperator = 0;
00149 while(opProb[iGenotype][iOperator] < random)
00150 iOperator++;
00151 }
00152 operators[iGenotype][iOperator]->mate(ind1->at(iGenotype), ind2->at(iGenotype), child->at(iGenotype));
00153 }
00154 }
00155
00156 ECF_LOG(state_, 5, "Crossover, new individual: " + child->toString());
00157
00158 return true;
00159 }