ECF 1.5
AlgClonalg.cpp
1#include "ECF_base.h"
2#include "ECF_macro.h"
3#include "AlgClonalg.h"
4#include <cmath>
5
6
7Clonalg::Clonalg()
8{
9 // define algorithm name
10 name_ = "Clonalg";
11
12 areGenotypesAdded_ = false;
13}
14
15
17{
18 registerParameter(state, "n", (voidP) new uint(100), ECF::INT,
19 "number of antibodies cloned every generation (default: 100)");
20 registerParameter(state, "beta", (voidP) new double(1), ECF::DOUBLE,
21 "number of clones (percentage) for every antibody (default: 1.0)");
22 registerParameter(state, "c", (voidP) new double(0.2), ECF::DOUBLE,
23 "mutation rate (default: 0.2)");
24 registerParameter(state, "d", (voidP) new double(0.0), ECF::DOUBLE,
25 "fraction of population regenerated every generation (default: 0)");
26 registerParameter(state, "cloningVersion", (voidP) new std::string("proportional"), ECF::STRING,
27 "cloning version, static or proportional (default: proportional)");
28 registerParameter(state, "selectionScheme", (voidP) new std::string("CLONALG1"), ECF::STRING,
29 "which selection scheme to use, CLONALG1 or CLONALG2 (default: CLONALG1)");
30}
31
32
33bool Clonalg::initialize(StateP state)
34{
35 voidP lBound = state->getGenotypes()[0]->getParameterValue(state, "lbound");
36 lbound = *((double*) lBound.get());
37
38 voidP uBound = state->getGenotypes()[0]->getParameterValue(state, "ubound");
39 ubound = *((double*) uBound.get());
40
41 voidP dimension_ = state->getGenotypes()[0]->getParameterValue(state, "dimension");
42 dimension = *((uint*) dimension_.get());
43
44
45 voidP populationSize_ = state->getRegistry()->getEntry("population.size");
46 uint populationSize = *((uint*) populationSize_.get());
47
48 voidP n_ = getParameterValue(state, "n");
49 n = *((uint*) n_.get());
50 if( n<1 || n>populationSize) {
51 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'n' to be an integer in range <0, population.size] ");
52 throw "";}
53
54
55 voidP beta_ = getParameterValue(state, "beta");
56 beta = *((double*) beta_.get());
57 if( beta <= 0 ) {
58 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'beta' to be a double greater than 0");
59 throw "";}
60
61
62 voidP c_ = getParameterValue(state, "c");
63 c = *((double*) c_.get());
64 if( c <= 0 ) {
65 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'c' to be a double greater than 0");
66 throw "";}
67
68
69 voidP d_ = getParameterValue(state, "d");
70 d = *((double*) d_.get());
71 if( d<0 || d>1 ) {
72 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'd' to be a double in range [0, 1] ");
73 throw "";}
74
75 voidP cloning_ = getParameterValue(state, "cloningVersion");
76 cloningVersion = *((std::string*) cloning_.get());
77 if( cloningVersion != "static" && cloningVersion != "proportional" ) {
78 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'cloningVersion' to be either 'static' or a 'proportional'");
79 throw "";}
80
81 voidP selection_ = getParameterValue(state, "selectionScheme");
82 selectionScheme = *((std::string*) selection_.get());
83 if( selectionScheme != "CLONALG1" && selectionScheme != "CLONALG2" ) {
84 ECF_LOG(state, 1, "Error: CLONALG requires parameter 'selectionScheme' to be either 'CLONALG1' or 'CLONALG2'");
85 throw "";}
86
87
88 // algorithm accepts a single FloatingPoint or Binary genotype
89 // or a genotype derived from the abstract RealValueGenotype class
90 GenotypeP activeGenotype = state->getGenotypes()[0];
91 RealValueGenotypeP rv = boost::dynamic_pointer_cast<RealValueGenotype> (activeGenotype);
92 if(!rv) {
93 ECF_LOG_ERROR(state, "Error: CLONALG algorithm accepts only a RealValueGenotype derived genotype! (FloatingPoint or Binary)");
94 throw ("");
95 }
96
97 // batch run check
98 if(areGenotypesAdded_)
99 return true;
100
101 //add parentAntibody genotype
102 if( selectionScheme == "CLONALG1"){
103 FloatingPointP flpoint[2];
104 for(uint iGen = 1; iGen < 2; iGen++) {
105 flpoint[iGen] = (FloatingPointP) new FloatingPoint::FloatingPoint;
106 state->setGenotype(flpoint[iGen]);
107
108 flpoint[iGen]->setParameterValue(state, "dimension", (voidP) new uint(1));
109
110 // initial value of age parameter should be (or as close as possible to) 0
111 flpoint[iGen]->setParameterValue(state, "lbound", (voidP) new double(0));
112 flpoint[iGen]->setParameterValue(state, "ubound", (voidP) new double(0.01));
113
114 }
115 ECF_LOG(state, 1, "CLONALG algorithm: added 1 FloatingPoint genotype (parentAntibody)");
116 }
117
118 // mark adding of genotypes
119 areGenotypesAdded_ = true;
120
121 return true;
122}
123
124
125bool Clonalg::advanceGeneration(StateP state, DemeP deme)
126{
127 std::vector<IndividualP> clones;
128 if (selectionScheme == "CLONALG1")
129 markAntibodies(deme);
130 cloningPhase(state, deme, clones);
131 hypermutationPhase(state, deme, clones);
132 selectionPhase(state, deme, clones);
133 birthPhase(state, deme, clones);
134 replacePopulation(state, deme, clones);
135
136 return true;
137}
138
139
142{
143 for( uint i = 0; i < deme->getSize(); i++ ) { // for each antibody
144 RealValueGenotypeP flp = boost::static_pointer_cast<RealValueGenotype> (deme->at(i)->getGenotype(1));
145 double &parentAb = flp->realValue[0];
146 parentAb = (double)i;
147 }
148 return true;
149}
150
151
152bool Clonalg::cloningPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
153{
154 // calculate number of clones per antibody
155 uint clonesPerAntibody = (uint) (beta * deme->getSize());
156
157 // storing all antibodies in a vector
158 for( uint i = 0; i < deme->getSize(); i++ ) // for each antibody
159 clones.push_back(deme->at(i));
160
161 // sorting all antibodies
162 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
163
164 // leaving n best antibodies for cloning
165 clones.erase (clones.begin()+n,clones.end());
166
167 for( uint i = 0; i < n; i++ ) { // for each antibody in clones vector
168 IndividualP antibody = clones.at(i);
169
170 //static cloning : cloning each antibody beta*populationSize times
171 if (cloningVersion == "static") {
172 for (uint j = 0; j < clonesPerAntibody; j++)
173 clones.push_back(copy(antibody));
174 }
175
176 //proportional cloning
177 else {
178 uint proportionalCloneNo = clonesPerAntibody/(i+1);
179 for (uint j = 0; j < proportionalCloneNo ; j++)
180 clones.push_back(copy(antibody));
181 }
182 }
183
184 return true;
185}
186
187
188bool Clonalg::hypermutationPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
189{
190 // sorting all antibodies
191 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
192
193 uint M; // M - number of mutations of a single antibody
194 uint k;
195
196 // calculate number of clones per antibody
197 uint clonesPerAntibody = (uint) (beta * deme->getSize());
198
199 // these get used in case of proportional cloning
200 uint counter = 0;
201 uint parentIndex = 0;
202
203 for( uint i = 0; i < clones.size(); i++ ) { // for each antibody in vector clones
204 IndividualP antibody = clones.at(i);
205
206 RealValueGenotypeP flp = boost::static_pointer_cast<RealValueGenotype> (antibody->getGenotype(0));
207 std::vector< double > &antibodyVars = flp->realValue;
208
209 // inversely proportional hypermutation (better antibodies are mutated less)
210 if (cloningVersion == "static")
211 k = 1+ i/(clonesPerAntibody +1);
212 else{
213 if (counter == i) {
214 parentIndex++;
215 counter += 1 + clonesPerAntibody/parentIndex;
216 }
217 k = parentIndex;
218 }
219
220 M = (int) ((1- 1/(double)(k)) * (c*dimension) + (c*dimension));
221
222 // mutate M times
223 for (uint j = 0; j < M; j++) {
224 uint param = state->getRandomizer()->getRandomInteger((int)antibodyVars.size());
225
226 double randDouble1 = state->getRandomizer()->getRandomDouble();
227 double randDouble2 = state->getRandomizer()->getRandomDouble();
228 double value = antibodyVars[param] + (1-2*randDouble1)* 0.2 * (ubound - lbound) * pow(2, -16*randDouble2 );
229
230 if (value > ubound)
231 value = ubound;
232 else if (value <lbound)
233 value = lbound;
234
235 //produce a mutation on the antibody
236 antibodyVars[param] = value;
237 }
238 evaluate(antibody);
239 }
240 return true;
241}
242
243
244bool Clonalg::selectionPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
245{
246 if( selectionScheme == "CLONALG1") {
247
248 std::sort (clones.begin(), clones.end(), sortPopulationByParentAndFitness);
249
250 int formerParent = -1;
251 std::vector<IndividualP> temp_clones;
252
253 for (uint i = 0; i < clones.size(); i++) {
254 RealValueGenotypeP flp = boost::static_pointer_cast<RealValueGenotype> (clones.at(i)->getGenotype(1));
255 double &parentAb = flp->realValue[0];
256 if (formerParent != parentAb) {
257 temp_clones.push_back(clones.at(i));
258 formerParent = (int) parentAb;
259 }
260 }
261 clones = temp_clones;
262 }
263
264 std::sort (clones.begin(), clones.end(), sortPopulationByFitness);
265 uint selNumber = (uint)((1-d)*deme->getSize());
266
267 //keep best (1-d)*populationSize antibodies ( or all if the number of clones is less than that )
268 if(selNumber < clones.size())
269 clones.erase (clones.begin()+ selNumber, clones.end());
270
271 return true;
272}
273
274
275bool Clonalg::birthPhase(StateP state, DemeP deme, std::vector<IndividualP> &clones)
276{
277 // birthNumber - number of new antibodies randomly created and added
278 uint birthNumber = (uint) (deme->getSize() - clones.size());
279
280 IndividualP newAntibody = copy(deme->at(0));
281 RealValueGenotypeP flp = boost::static_pointer_cast<RealValueGenotype> (newAntibody->getGenotype(0));
282
283 for (uint i = 0; i<birthNumber; i++) {
284 //create a random antibody
285 flp->initialize(state);
286 evaluate(newAntibody);
287
288 //add it to the clones vector
289 clones.push_back(copy(newAntibody));
290 }
291 return true;
292}
293
294
296bool Clonalg::replacePopulation(StateP state, DemeP deme, std::vector<IndividualP> &clones)
297{
298 for( uint i = 0; i < clones.size(); i++ ) // for each antibody
299 deme->replace(i, clones.at(i));
300
301 clones.clear();
302
303 return true;
304}
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
double d
fraction of population regenerated every generation
Definition: AlgClonalg.h:36
static bool sortPopulationByFitness(IndividualP ab1, IndividualP ab2)
sort vector of antibodies in regards to their fitness
Definition: AlgClonalg.h:41
static bool sortPopulationByParentAndFitness(IndividualP ab1, IndividualP ab2)
sort vector of antibodies first by their antibody parents and then by their fitness
Definition: AlgClonalg.h:44
std::string cloningVersion
specifies whether to use static or proportional cloning
Definition: AlgClonalg.h:37
bool initialize(StateP state)
Initialize the algorithm, read parameters from the system, do a sanity check.
Definition: AlgClonalg.cpp:33
bool markAntibodies(DemeP deme)
mark antibodies so the alg can know which clone belongs to which parent Antibody
Definition: AlgClonalg.cpp:141
uint n
number of antibodies cloned every generation
Definition: AlgClonalg.h:33
double beta
parameter which determines the number of clones for every antibody
Definition: AlgClonalg.h:34
bool advanceGeneration(StateP state, DemeP deme)
Perform a single generation on a single deme.
Definition: AlgClonalg.cpp:125
bool replacePopulation(StateP state, DemeP deme, std::vector< IndividualP > &clones)
replace population with the contents of clones vector
Definition: AlgClonalg.cpp:296
double c
mutation parameter
Definition: AlgClonalg.h:35
std::string selectionScheme
specifies which selection scheme to use CLONALG1 or CLONALG2
Definition: AlgClonalg.h:38
void registerParameters(StateP state)
Register algorithm's parameters (if any).
Definition: AlgClonalg.cpp:16
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