ECF 1.5
AlgDifferentialEvolution.cpp
1#include "ECF_base.h"
2#include "ECF_macro.h"
3#include "SelRandomOp.h"
4#include "AlgDifferentialEvolution.h"
5#include "floatingpoint/FloatingPoint.h"
6#include <iostream>
7
8
9DifferentialEvolution::DifferentialEvolution()
10{
11 // define algorithm name
12 name_ = "DifferentialEvolution";
13
14 // by default, the algorithm is unconstrained
15 bounded_ = false;
16
17 // create selection operators needed
18 selRandomOp = static_cast<SelectionOperatorP> (new SelRandomOp);
19}
20
21
23{
24 registerParameter(state, "F", (voidP) new double(1.), ECF::DOUBLE, "scaling constant");
25 registerParameter(state, "CR", (voidP) new double(0.9), ECF::DOUBLE, "crossover rate");
26 registerParameter(state, "bounded", (voidP) new uint(0), ECF::UINT,
27 "should the algorithm respect the bounds defined in the genotype or not (default: 0)");
28}
29
30
32{
33 selRandomOp->initialize(state);
34 donor_vector.clear();
35
36 // read parameters, check defined genotype (only a single FloatingPoint is allowed)
37 voidP F = getParameterValue(state, "F");
38 Fconst_ = *((double*) F.get());
39 voidP CR = getParameterValue(state, "CR");
40 CR_ = *((double*) CR.get());
41
42 // algorithm accepts a single FloatingPoint or Binary genotype
43 // or a genotype derived from the abstract RealValueGenotype class
44 GenotypeP activeGenotype = state->getGenotypes()[0];
45 RealValueGenotypeP rv = boost::dynamic_pointer_cast<RealValueGenotype> (activeGenotype);
46 if(!rv) {
47 ECF_LOG_ERROR(state, "Error: Differential evolution algorithm accepts only a RealValueGenotype derived genotype! (FloatingPoint or Binary)");
48 throw ("");
49 }
50
51 voidP bounded = getParameterValue(state, "bounded");
52 bounded_ = *((bool*) bounded.get());
53
54 return true;
55}
56
57
58bool DifferentialEvolution::advanceGeneration(StateP state, DemeP deme)
59{
60 // create donor vectors for each population member
61 for(uint iIter = 0; iIter < deme->size(); iIter++){
62 createDonorVectors(deme, state);
63 }
64
65 // perform DE crossover, generate trial vectors (stored in donor_vector)
66 for(uint iIter = 0; iIter < deme->size(); iIter++) {
67 crossover(deme, iIter, state);
68 }
69
70 // select the better one for each population member and trial vector
71 for(uint iIter = 0; iIter < deme->size(); iIter++) {
72 evaluate(donor_vector[iIter]);
73 if(donor_vector[iIter]->fitness->isBetterThan(deme->at(iIter)->fitness))
74 replaceWith(deme->at(iIter), donor_vector[iIter]);
75 }
76
77 //for(uint i = 0; i < deme->size(); i++){
78 // state->getLogger()->log(5, "deme[" + uint2str(i) + "]: " + dbl2str(deme->at(i)->fitness->getValue()) + "\t" + uint2str(deme->at(i)->index));
79 //}
80
81 donor_vector.clear();
82
83 return true;
84}
85
86
88void DifferentialEvolution::createDonorVectors(DemeP deme, StateP state)
89{
90 IndividualP ind1, ind2, ind3;
91
92 // select three different population members
93 ind1 = selRandomOp->select(*deme);
94 ind2 = selRandomOp->select(*deme);
95 while (ind1->index == ind2->index)
96 ind2 = selRandomOp->select(*deme);
97 ind3 = selRandomOp->select(*deme);
98 while (ind1->index == ind3->index || ind2->index == ind3->index)
99 ind3 = selRandomOp->select(*deme);
100
101 // get their genotypes
102 RealValueGenotype* flp1 = (RealValueGenotype*) (ind1->getGenotype().get());
103 RealValueGenotype* flp2 = (RealValueGenotype*) (ind2->getGenotype().get());
104 RealValueGenotype* flp3 = (RealValueGenotype*) (ind3->getGenotype().get());
105
106 // create new individual to contain new donor vector
107 IndividualP v (new Individual(state));
108 RealValueGenotype* b = (RealValueGenotype*) v->getGenotype().get();
109 double donor_value;
110
111 // calculate new donor vector elements
112 for(uint i = 0; i < flp2->realValue.size(); i++){
113 donor_value = flp1->realValue[i] + Fconst_ * (flp2->realValue[i] - flp3->realValue[i]);
114
115 // check for bounds
116 if(bounded_) {
117 if(donor_value < b->getLBound())
118 donor_value = b->getLBound();
119 if(donor_value > b->getUBound())
120 donor_value = b->getUBound();
121 }
122
123 b->realValue[i] = donor_value;
124 }
125
126 donor_vector.push_back(v);
127}
128
129
131void DifferentialEvolution::crossover(DemeP deme, uint index, StateP state)
132{
133 // get population member and corresponding donor vector
134 RealValueGenotype* flp1 = (RealValueGenotype*) (deme->at(index)->getGenotype().get());
135 int dim = (int) flp1->realValue.size();
136 RealValueGenotype* flp2 = (RealValueGenotype*) donor_vector[index]->getGenotype().get();
137
138 // crossover their elements (keep the result in donor_vector)
139 for(uint i = 0; i < flp1->realValue.size(); i++) {
140 if (state->getRandomizer()->getRandomDouble() <= CR_ || i == state->getRandomizer()->getRandomInteger(dim)) {
141 }
142 else {
143 flp2->realValue[i] = flp1->realValue[i];
144 }
145 }
146
147}
std::string name_
algorithm name
Definition: Algorithm.h:23
bool registerParameter(StateP state, std::string name, voidP value, enum ECF::type T, std::string description="")
Helper function: register a single parameter with the system.
Definition: Algorithm.h:35
voidP getParameterValue(StateP state, std::string name)
Helper function: get parameter value from the system.
Definition: Algorithm.h:46
void replaceWith(IndividualP oldInd, IndividualP newInd)
Helper function: replace an individual in current deme.
Definition: Algorithm.h:187
void evaluate(IndividualP ind)
Helper function: evaluate an individual.
Definition: Algorithm.h:157
bool initialize(StateP state)
Initialize the algorithm, read parameters from the system, do a sanity check.
void registerParameters(StateP state)
Register algorithm's parameters (if any).
std::vector< IndividualP > donor_vector
vector of donor solutions (individuals)
bool bounded_
constrained or not
void crossover(DemeP deme, uint index, StateP state)
cross donor vectors with population members to create trial vectors
double Fconst_
scaling constant
bool advanceGeneration(StateP state, DemeP deme)
Perform a single generation on a single deme.
void createDonorVectors(DemeP deme, StateP state)
create donor vectors (the same number as the population size)
Individual class - inherits a vector of Genotype objects.
Definition: Individual.h:12
RealValueGenotype class - abstract genotype class for genotypes that represent a vector of real value...
double getUBound()
return upper bound of the defined interval
std::vector< double > realValue
vector of floating point values
double getLBound()
return lower bound of the defined interval
Random individual selection operator.
Definition: SelRandomOp.h:12