ECF 1.5
AlgOptIA.cpp
1#include "ECF_base.h"
2#include "ECF_macro.h"
3#include "AlgOptIA.h"
4#include <cmath>
5
6
7
8OptIA::OptIA()
9{ // define algorithm name
10 name_ = "OptIA";
11
12 areGenotypesAdded_ = false;
13}
14
15
16void OptIA::registerParameters(StateP state)
17{
18 registerParameter(state, "dup", (voidP) new uint(5), ECF::INT,
19 "number of clones for each individual in clone population (dafault: 5)");
20 registerParameter(state, "c", (voidP) new double(0.2), ECF::DOUBLE,
21 "mutation rate (default: 0.2)");
22 registerParameter(state, "tauB", (voidP) new double(100), ECF::DOUBLE,
23 "maximum number of generations to keep an individual without improvement (default: 100)");
24 registerParameter(state, "elitism", (voidP) new uint(0), ECF::UINT,
25 "use elitism (default: 0)");
26}
27
28
29bool OptIA::initialize(StateP state)
30{
31 voidP lBound = state->getGenotypes()[0]->getParameterValue(state, "lbound");
32 lbound = *((double*) lBound.get());
33
34 voidP uBound = state->getGenotypes()[0]->getParameterValue(state, "ubound");
35 ubound = *((double*) uBound.get());
36
37 voidP dimension_ = state->getGenotypes()[0]->getParameterValue(state, "dimension");
38 dimension = *((uint*) dimension_.get());
39
40 voidP dup_ = getParameterValue(state, "dup");
41 dup = *((uint*) dup_.get());
42 if( *((int*) dup_.get()) <= 0 ) {
43 ECF_LOG(state, 1, "Error: opt-IA requires parameter 'dup' to be an integer greater than 0");
44 throw "";}
45
46 voidP c_ = getParameterValue(state, "c");
47 c = *((double*) c_.get());
48 if( c <= 0 ) {
49 ECF_LOG(state, 1, "Error: opt-IA requires parameter 'c' to be a double greater than 0");
50 throw "";}
51
52 voidP tauB_ = getParameterValue(state, "tauB");
53 tauB = *((double*) tauB_.get());
54 if( tauB < 0 ) {
55 ECF_LOG(state, 1, "Error: opt-IA requires parameter 'tauB' to be a nonnegative double value");
56 throw "";}
57
58 voidP elitism_ = getParameterValue(state, "elitism");
59 elitism = (*((uint*) elitism_.get())) != 0;
60
61 // algorithm accepts a single FloatingPoint or Binary genotype
62 // or a genotype derived from the abstract RealValueGenotype class
63 GenotypeP activeGenotype = state->getGenotypes()[0];
64 RealValueGenotypeP rv = boost::dynamic_pointer_cast<RealValueGenotype> (activeGenotype);
65 if(!rv) {
66 ECF_LOG_ERROR(state, "Error: opt-IA accepts only a RealValueGenotype derived genotype! (FloatingPoint or Binary)");
67 throw ("");
68 }
69
70 // batch run check
71 if(areGenotypesAdded_)
72 return true;
73
74 // algorithm adds another FloatingPoint genotype (age)
75 FloatingPointP flpoint[2];
76 for(uint iGen = 1; iGen < 2; iGen++) {
77 flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint;
78 state->setGenotype(flpoint[iGen]);
79
80 flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1));
81
82 // initial value of age parameter should be (or as close as possible to) 0
83 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0));
84 flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(0.01));
85
86 }
87 ECF_LOG(state, 1, "opt-IA algorithm: added 1 FloatingPoint genotype (antibody age)");
88
89 // mark adding of genotypes
90 areGenotypesAdded_ = true;
91
92 return true;
93}
94
95
96bool OptIA::advanceGeneration(StateP state, DemeP deme)
97{
98 std::vector<IndividualP> clones;
99
100 cloningPhase(state, deme, clones);
101 hypermutationPhase(state, deme, clones);
102 agingPhase(state, deme, clones);
103 selectionPhase(state, deme, clones);
104 birthPhase(state, deme, clones);
105 replacePopulation(state, deme, clones);
106
107 return true;
108}
109
110
111bool OptIA::cloningPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
112{
113 // storing all antibodies in a vector
114 for( uint i = 0; i < deme->getSize(); i++ ) // for each antibody
115 clones.push_back(deme->at(i));
116
117 for( uint i = 0; i < deme->getSize(); i++ ){ // for each antibody in clones vector
118 IndividualP antibody = clones.at(i);
119
120 // static cloning is fitness independent : : cloning each antibody dup times
121 for (uint j = 0; j < dup; j++)
122 clones.push_back(copy(antibody));
123 }
124
125 return true;
126}
127
128
129bool OptIA::hypermutationPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
130{
131 uint M; // M - number of mutations of a single antibody
132 uint k;
133
134 //sort
135 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
136
137 for( uint i = 0; i < clones.size(); i++ ){ // for each antibody in vector clones
138 IndividualP antibody = clones.at(i);
139
140 FloatingPointP flp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (antibody->getGenotype(0));
141 std::vector< double > &antibodyVars = flp->realValue;
142
143 k = 1 + i/(dup+1);
144 M =(int) ((1- 1/(double)(k)) * (c*dimension) + (c*dimension));
145
146 // mutate M times
147 for (uint j = 0; j < M; j++){
148 uint param = state->getRandomizer()->getRandomInteger((int)antibodyVars.size());
149
150 double randDouble1 = state->getRandomizer()->getRandomDouble();
151 double randDouble2 = state->getRandomizer()->getRandomDouble();
152 double value = antibodyVars[param] + (1-2*randDouble1)* 0.2 * (ubound - lbound) * pow(2, -16*randDouble2 );
153
154 if (value > ubound)
155 value = ubound;
156 else if (value <lbound)
157 value = lbound;
158
159 //produce a mutation on the antibody
160 antibodyVars[param] = value;
161 }
162 FitnessP parentFitness = antibody->fitness;
163 evaluate(antibody);
164
165 // if the clone is better than its parent, reset clone's age
166 if(antibody-> fitness->isBetterThan(parentFitness)){
167 flp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (antibody->getGenotype(1));
168 double &age = flp->realValue[0];
169 age = 0;
170 }
171 }
172 return true;
173}
174
175
176bool OptIA::agingPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
177{
178 //sort
179 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
180
181 std::vector<IndividualP> temp_clones;
182
183 for (uint i = 0; i < clones.size(); i++){// for each antibody
184 IndividualP antibody = clones.at(i);
185
186 //age each antibody
187 FloatingPointP flp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (antibody->getGenotype(1));
188 double &age = flp->realValue[0];
189 age += 1;
190
191 // static aging: if an antibody exceeds tauB number of trials, it is replaced with a new randomly created antibody
192 if (age <=tauB)
193 temp_clones.push_back(antibody);
194 // if elitism = true , preserve the best antibody regardless of its age
195 else if (elitism == 1 && i == 0)
196 temp_clones.push_back(antibody);
197 }
198 clones = temp_clones;
199 return true;
200}
201
202
203bool OptIA::selectionPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
204{
205 //sort
206 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
207
208 //keep best populationSize antibodies ( or all if the number of clones is less than that ), erase the rest
209 if(clones.size() > deme->getSize())
210 clones.erase (clones.begin()+ deme->getSize(), clones.end());
211
212 return true;
213}
214
215
216bool OptIA::birthPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
217{
218 //number of new antibodies (randomly created)
219 uint birthNumber = deme->getSize() - clones.size();
220
221 //if no new antibodies are needed, return (this if part is optional, code works fine w/o it)
222 if (birthNumber == 0) return true;
223
224 IndividualP newAntibody = copy(deme->at(0));
225 FloatingPointP flp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (newAntibody->getGenotype(0));
226
227 for (uint i = 0; i<birthNumber; i++){
228 //create a random antibody
229 flp->initialize(state);
230 evaluate(newAntibody);
231
232 //reset its age
233 flp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (newAntibody->getGenotype(1));
234 double &age = flp->realValue[0];
235 age = 0;
236
237 //add it to the clones vector
238 clones.push_back(copy(newAntibody));
239 }
240 return true;
241}
242
243
245bool OptIA::replacePopulation(StateP state, DemeP deme, std::vector<IndividualP> &clones)
246{
247 for( uint i = 0; i < clones.size(); i++ ) // for each antibody
248 deme->replace(i, clones.at(i));
249
250 clones.clear();
251
252 return true;
253}
IndividualP copy(IndividualP source)
Helper function: make a copy of an individual.
Definition: Algorithm.h:291
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 evaluate(IndividualP ind)
Helper function: evaluate an individual.
Definition: Algorithm.h:157
FloatingPoint class - implements genotype as a vector of floating point values.
Definition: FloatingPoint.h:39
bool setParameterValue(StateP state, std::string name, voidP value)
Write single parameter value to Registry.
Definition: Genotype.cpp:16
void registerParameters(StateP state)
Register algorithm's parameters (if any).
Definition: AlgOptIA.cpp:16
bool advanceGeneration(StateP state, DemeP deme)
Perform a single generation on a single deme.
Definition: AlgOptIA.cpp:96
bool replacePopulation(StateP state, DemeP deme, std::vector< IndividualP > &clones)
replace population with the contents of the clones vector
Definition: AlgOptIA.cpp:245
double c
mutation parameter
Definition: AlgOptIA.h:32
double tauB
maximum number of generations without improvement
Definition: AlgOptIA.h:33
bool initialize(StateP state)
Initialize the algorithm, read parameters from the system, do a sanity check.
Definition: AlgOptIA.cpp:29
bool elitism
specifies whether to use elitism or not
Definition: AlgOptIA.h:34
static bool sortPopulationByFitness(IndividualP ab1, IndividualP ab2)
sort vector of antibodies in regards to their fitness
Definition: AlgOptIA.h:37
uint dup
number of clones per antibody
Definition: AlgOptIA.h:31