ECF 1.5
Crossover.cpp
1#include "ECF_base.h"
2
3const int RANDOM_GENOTYPE = 0;
4const int ALL_GENOTYPES = 1;
5
6
11{
12 state->getRegistry()->registerEntry("crossover.genotypes", (voidP) new std::string("random"), ECF::STRING,
13 "if there are multiple genotypes, which to cross? 'random': a random pair, 'all': all pairs (default: random)");
14 state->getRegistry()->registerEntry("crossover.protected", (voidP) new std::string(""), ECF::STRING,
15 "indexes of genotypes (separated by spaces) that are excluded (protected) from crossover (default: none)");
16}
17
18
22bool Crossover::initialize(StateP state)
23{
24 state_ = state;
25 protectedGenotypes_.clear();
26 protectedGenotypes_.insert(protectedGenotypes_.begin(), operators.size(), false);
27 opProb.clear();
28
29 voidP sptr = state->getRegistry()->getEntry("crossover.genotypes");
30 std::string crxGen = *((std::string*)sptr.get());
31
32 crxGenotypes_ = RANDOM_GENOTYPE;
33 if(crxGen == "all")
34 crxGenotypes_ = ALL_GENOTYPES;
35 else if(crxGen == "random")
36 crxGenotypes_ = RANDOM_GENOTYPE;
37 else
38 ECF_LOG_ERROR(state, "Warning: invalid parameter value (key: crossover.genotypes)");
39
40 // read protected genotypes
41 std::stringstream ss;
42 sptr = state->getRegistry()->getEntry("crossover.protected");
43 ss << *((std::string*) sptr.get());
44 uint genId;
45 while(ss >> genId) { // read all the data from string
46 if(genId >= protectedGenotypes_.size()) {
47 ECF_LOG_ERROR(state, "Error: invalid genotype index (key: crossover.protected)!");
48 throw("");
49 }
50 protectedGenotypes_[genId] = true;
51 }
52
53 // initialize operators for all genotypes
54 for(uint gen = 0; gen < operators.size(); gen++) {
55 uint nOps = (uint) operators[gen].size();
56 // if the genotype doesn't define crossover operators
57 if(nOps == 0) {
58 protectedGenotypes_[gen] = true;
59 std::vector<double> empty;
60 opProb.push_back(empty);
61 break;
62 }
63 for(uint i = 0; i < nOps; i++) {
64 operators[gen][i]->state_ = state;
65 operators[gen][i]->initialize(state);
66 }
67 // calculate cumulative operator probabilities
68 std::vector<double> probs(nOps);
69 probs[0] = operators[gen][0]->probability_;
70 for(uint i = 1; i < nOps; i++) {
71 probs[i] = probs[i - 1] + operators[gen][i]->probability_;
72 }
73 if(probs[nOps - 1] == 0)
74 probs[0] = -1;
75 else
76 if(probs[nOps - 1] != 1) {
77 double normal = probs[nOps - 1];
78 ECF_LOG_ERROR(state, "Warning: " + operators[gen][0]->myGenotype_->getName() +
79 " crossover operators: cumulative probability not equal to 1 (sum = " + dbl2str(normal) + ")");
80 for(uint i = 0; i < probs.size(); i++)
81 probs[i] /= normal;
82 }
83 opProb.push_back(probs);
84 }
85 return true;
86}
87
88
95bool Crossover::mate(IndividualP ind1, IndividualP ind2, IndividualP child)
96{
97 child->fitness->setInvalid();
98 // set crossover context
99 state_->getContext()->firstParent = ind1;
100 state_->getContext()->secondParent = ind2;
101 state_->getContext()->child = child;
102 ECF_LOG(state_, 5, "Crossover, 1st parent: " + ind1->toString()
103 + "\nCrossover, 2nd parent: " + ind2->toString());
104
105 // check if any of the parents is also the child
106 if(ind1 == child) {
107 ind1 = (IndividualP) ind1->copy();
108 }
109 if(ind2 == child) {
110 ind2 = (IndividualP) ind2->copy();
111 }
112
113 // TODO: parameter for genotype exchange (instead of genotype crossover)
114
115 // default: choose radnom genotype pair to crx
116 if(crxGenotypes_ == RANDOM_GENOTYPE) {
117 uint iGenotype = state_->getRandomizer()->getRandomInteger((int)ind1->size());
118 if(protectedGenotypes_[iGenotype])
119 return false;
120 // copy unchanged genotypes from parents
121 for(uint i = 0; i < iGenotype; i++)
122 child->at(i) = (GenotypeP) ind1->at(i)->copy();
123 for(uint i = iGenotype + 1; i < child->size(); i++)
124 child->at(i) = (GenotypeP) ind2->at(i)->copy();
125 // choose operator
126 uint iOperator;
127 if(opProb[iGenotype][0] < 0)
128 iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size());
129 else {
130 double random = state_->getRandomizer()->getRandomDouble();
131 iOperator = 0;
132 while(opProb[iGenotype][iOperator] < random)
133 iOperator++;
134 }
135 operators[iGenotype][iOperator]->mate(ind1->at(iGenotype), ind2->at(iGenotype), child->at(iGenotype));
136 }
137 // otherwise: crx all genotypes
138 else if(crxGenotypes_ == ALL_GENOTYPES) {
139 for(uint iGenotype = 0; iGenotype < ind1->size(); iGenotype++) {
140 if(protectedGenotypes_[iGenotype])
141 continue;
142 // choose operator
143 uint iOperator;
144 if(opProb[iGenotype][0] < 0)
145 iOperator = state_->getRandomizer()->getRandomInteger((int)operators[iGenotype].size());
146 else {
147 double random = state_->getRandomizer()->getRandomDouble();
148 iOperator = 0;
149 while(opProb[iGenotype][iOperator] < random)
150 iOperator++;
151 }
152 operators[iGenotype][iOperator]->mate(ind1->at(iGenotype), ind2->at(iGenotype), child->at(iGenotype));
153 }
154 }
155
156 ECF_LOG(state_, 5, "Crossover, new individual: " + child->toString());
157
158 return true;
159}
void registerParameters(StateP)
Register crossover related but Genotype unrelated parameters.
Definition: Crossover.cpp:10
uint crxGenotypes_
what genotypes (if more than one) to cross (random, all)
Definition: Crossover.h:68
std::vector< bool > protectedGenotypes_
protected (non-crossable) genotypes flags
Definition: Crossover.h:69
bool mate(IndividualP ind1, IndividualP ind2, IndividualP child)
Crosses 2 individuals.
Definition: Crossover.cpp:95
std::vector< std::vector< double > > opProb
usage probabilities for each CrossoverOp operator
Definition: Crossover.h:64
bool initialize(StateP)
Initialize all crossover operators of all active genotypes.
Definition: Crossover.cpp:22
std::vector< std::vector< CrossoverOpP > > operators
vectors of crx operators for each genotype
Definition: Crossover.h:63