ECF 1.5
AlgGenHookeJeeves.cpp
1#include "ECF_base.h"
2#include "ECF_macro.h"
3#include "AlgGenHookeJeeves.h"
4#include "SelFitnessProportionalOp.h"
5#include "SelRandomOp.h"
6#include "floatingpoint/FloatingPoint.h"
7
8
9GenHookeJeeves::GenHookeJeeves()
10{
11 // define algorithm name (for referencing in config file)
12 name_ = "GenHookeJeeves";
13
14 // inital state
15 areGenotypesAdded_ = false;
16
17 // create selection operators needed
18 selFitPropOp_ = static_cast<SelectionOperatorP> (new SelFitnessProportionalOp);
19 selBestOp_ = static_cast<SelectionOperatorP> (new SelBestOp);
20 selRandomOp_ = static_cast<SelectionOperatorP> (new SelRandomOp);
21}
22
23
25{
26 // preciznost: minimalni delta_x
27 registerParameter(state, "precision", (voidP) new double(0.000001), ECF::DOUBLE);
28 // pocetni pomak (pocetni delta_x)
29 registerParameter(state, "delta", (voidP) new double(1.), ECF::DOUBLE);
30 // samo lokalna pretraga
31 registerParameter(state, "localonly", (voidP) new uint(0), ECF::UINT);
32}
33
34
36{
37 // algorithm accepts a single FloatingPoint or Binary genotype
38 // or a genotype derived from the abstract RealValueGenotype class
39 GenotypeP activeGenotype = state->getGenotypes()[0];
40 RealValueGenotypeP rv = boost::dynamic_pointer_cast<RealValueGenotype> (activeGenotype);
41 if(!rv) {
42 ECF_LOG_ERROR(state, "Error: This algorithm accepts only a RealValueGenotype derived genotype! (FloatingPoint or Binary)");
43 throw ("");
44 }
45
46 // initialize all operators
47 selFitPropOp_->initialize(state);
48 selBestOp_->initialize(state);
49 selRandomOp_->initialize(state);
50
51 // read parameter values
52 voidP sptr = getParameterValue(state, "precision");
53 precision_ = *((double*) sptr.get());
54 sptr = getParameterValue(state, "delta");
55 initialMove_ = *((double*) sptr.get());
56 sptr = getParameterValue(state, "localonly");
57 localOnly_ = *((uint*) sptr.get()) ? true : false;
58
59 // init pomake i zastavice postupka
60 sptr = state->getRegistry()->getEntry("population.size");
61 uint size = *((uint*) sptr.get());
62 for(uint i = 0; i < size; i++) {
63 delta_.push_back(initialMove_);
64 changed_.push_back(true);
65 converged_.push_back(false);
66 }
67
68 convergedTotal_ = 0;
69
70 // batch run check
71 if(areGenotypesAdded_)
72 return true;
73
74 // procitaj parametre prvog genotipa i prepisi u novi genotip
75 // (drugi genotip nam treba za operaciju pretrazivanja)
76 // to sve moze i jednostavnije (npr. s privatnim vektorom genotipa), ali ovako mozemo koristiti i milestone!
77 sptr = state->getGenotypes()[0]->getParameterValue(state, "dimension");
78 uint numDimension = *((uint*) sptr.get());
79 sptr = state->getGenotypes()[0]->getParameterValue(state, "lbound");
80 lbound_ = *((double*) sptr.get());
81 sptr = state->getGenotypes()[0]->getParameterValue(state, "ubound");
82 ubound_ = *((double*) sptr.get());
83
84 // stvori i dodaj novi genotip
85 FloatingPointP fp (static_cast<FloatingPoint::FloatingPoint*> (new FloatingPoint::FloatingPoint));
86 state->setGenotype(fp);
87
88 // ako je lokalna pretraga, stvori i dodaj novi genotip za broj koraka do konvergencije svake jedinke
89 if(localOnly_) {
90 FloatingPointP fp2 (static_cast<FloatingPoint::FloatingPoint*> (new FloatingPoint::FloatingPoint));
91 state->setGenotype(fp2);
92 fp2->setParameterValue(state, "dimension", (voidP) new uint(1));
93 fp2->setParameterValue(state, "lbound", (voidP) new double(0));
94 fp2->setParameterValue(state, "ubound", (voidP) new double(1));
95 }
96
97 // postavi jednake parametre
98 fp->setParameterValue(state, "dimension", (voidP) new uint(numDimension));
99 fp->setParameterValue(state, "lbound", (voidP) new double(lbound_));
100 fp->setParameterValue(state, "ubound", (voidP) new double(ubound_));
101
102 // mark adding of genotypes
103 areGenotypesAdded_ = true;
104
105 return true;
106}
107
108
109bool GenHookeJeeves::advanceGeneration(StateP state, DemeP deme)
110{
111 // fitnesi i pomocna jedinka za postupak pretrazivanja (koristimo Fitness objekte tako da radi i za min i max probleme)
112 FitnessP neighbor[2];
113 neighbor[0] = (FitnessP) (*deme)[0]->fitness->copy();
114 neighbor[1] = (FitnessP) (*deme)[0]->fitness->copy();
115 IndividualP temp (new Individual(state));
116
117 uint mutacija = 0;
118
119 // vrti isto za sve jedinke
120 for(uint i = 0; i < deme->size(); i++) {
121
122 if(localOnly_ && converged_[i])
123 continue;
124
125 IndividualP ind = deme->at(i);
126 // bazna tocka:
127 FloatingPointP x = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (ind->getGenotype(0));
128 // pocetna tocka pretrazivanja:
129 FloatingPointP xn = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (ind->getGenotype(1));
130
131 FitnessP finalFit;
132 // je li prva iteracija uz ovaj deltax?
133 if(changed_[i]) {
134 xn = (FloatingPointP) x->copy();
135 changed_[i] = false;
136 finalFit = (FitnessP) ind->fitness->copy();
137 }
138 // ako nije, trebamo evaluirati i pocetnu tocku pretrazivanja
139 else {
140 (*temp)[0] = xn;
141 evaluate(temp);
142 finalFit = temp->fitness;
143 }
144
145 // pretrazivanje
146 for(uint dim = 0; dim < x->realValue.size(); dim++) {
147 xn->realValue[dim] += delta_[i]; // pomak vektora
148
149 // ogranicenja: provjeri novu tocku samo ako zadovoljava
150 if(xn->realValue[dim] <= ubound_) {
151 (*temp)[0] = xn; // stavimo u pomocnu jedinku
152 evaluate(temp); // evaluiramo jedinku
153 neighbor[0] = temp->fitness; // zabiljezimo fitnes
154
155 // VARIJANTA A: originalni postupak za unimodalne fje
156 // ako je drugi bolji, treceg niti ne gledamo
157 if(neighbor[0]->isBetterThan(finalFit)) {
158 finalFit = neighbor[0];
159 continue;
160 }
161
162 }
163
164 // onda idemo na drugu stranu
165 xn->realValue[dim] -= 2 * delta_[i];
166
167 // ogranicenja: provjeri novu tocku samo ako zadovoljava
168 if(xn->realValue[dim] >= lbound_) {
169 (*temp)[0] = xn;
170 evaluate(temp);
171 neighbor[1] = temp->fitness;
172
173 // je li treci bolji?
174 if(neighbor[1]->isBetterThan(finalFit)) {
175 finalFit = neighbor[1];
176 continue;
177 }
178 }
179
180 // ako nije, vrati u sredinu
181 xn->realValue[dim] += delta_[i]; // vrati u sredinu
182 continue;
183
184
185 // VARIJANTA B: gledamo sve tri tocke (za visemodalni slucaj)
186 // odredi najbolju od 3
187 if(finalFit->isBetterThan(neighbor[0]) && finalFit->isBetterThan(neighbor[1]))
188 ;
189 else if(neighbor[0]->isBetterThan(neighbor[1])) {
190 xn->realValue[dim] += delta_[i];
191 finalFit = neighbor[0];
192 }
193 else {
194 xn->realValue[dim] -= delta_[i];
195 finalFit = neighbor[1];
196 }
197
198 } // kraj pretrazivanja
199
200
201 // je li tocka nakon pretrazivanja bolja od bazne tocke?
202 if(finalFit->isBetterThan(ind->fitness)) {
203 FloatingPointP xnc (xn->copy());
204 // preslikavanje:
205 for(uint dim = 0; dim < x->realValue.size(); dim++)
206 xn->realValue[dim] = 2 * xn->realValue[dim] - x->realValue[dim];
207
208 // ogranicenja: pomakni na granicu
209 for(uint dim = 0; dim < xn->realValue.size(); dim++) {
210 if(xn->realValue[dim] < lbound_)
211 xn->realValue[dim] = lbound_;
212 if(xn->realValue[dim] > ubound_)
213 xn->realValue[dim] = ubound_;
214 }
215
216 x = xnc; // nova bazna tocka
217 ind->fitness = finalFit; // ne zaboravimo i novi fitnes
218 }
219 // nije, smanji deltax i resetiraj tocku pretrazivanja
220 else {
221 delta_[i] /= 2;
222 xn = (FloatingPointP) x->copy();
223 changed_[i] = true;
224 }
225
226 // azuriraj genotipe (pointeri u jedinki):
227 (*ind)[0] = x;
228 (*ind)[1] = xn;
229
230
231 // dio koji obradjuje samo Hooke-Jeeves (localonly)
232 if(localOnly_) {
233 if(converged_[i] == false && changed_[i] == true && delta_[i] < precision_) {
234 converged_[i] = true;
235 convergedTotal_++;
236
237 // zapisi generaciju u kojoj je jedinka konvergirala
238 FloatingPointP fp = boost::static_pointer_cast<FloatingPoint::FloatingPoint> (ind->getGenotype(2));
239 fp->realValue[0] = (double) state->getGenerationNo();
240 }
241
242
243 if(convergedTotal_ == converged_.size()) {
244 state->setTerminateCond();
245 std::cout << "svi konvergirali!" << std::endl;
246 }
247
248 continue; // sljedeca jedinka
249
250 }
251
252 // ako je jedinka konvergirala (i ako nije trenutno najbolja), stvori novu krizanjem + mutacijom
253 if(changed_[i] == true && delta_[i] < precision_ && (selBestOp_->select(*deme) != ind)) {
254 IndividualP first, second;
255 first = second = selFitPropOp_->select(*deme);
256 while(second == first)
257 second = selFitPropOp_->select(*deme);
258
259 // VARIJANTA C: slucajni odabir roditelja (umjesto fitness proportional)
260// first = second = selRandomOp_->select(*deme);
261// while(second == first)
262// second = selRandomOp_->select(*deme);
263
264 // krizanje, mutacija, evaluacija
265 mate(first, second, ind);
266 mutate(ind);
267 evaluate(ind);
268 delta_[i] = initialMove_; // ponovo pocetni pomak
269 }
270
271 }
272
273 return true;
274}
uint mutate(const std::vector< IndividualP > &pool)
Helper function: send a vector of individuals to mutation.
Definition: Algorithm.h:169
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
bool mate(IndividualP p1, IndividualP p2, IndividualP child)
Helper function: crossover two individuals.
Definition: Algorithm.h:285
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 advanceGeneration(StateP state, DemeP deme)
Perform a single generation on a single deme.
void registerParameters(StateP state)
Register algorithm's parameters (if any).
bool initialize(StateP state)
Initialize the algorithm, read parameters from the system, do a sanity check.
Individual class - inherits a vector of Genotype objects.
Definition: Individual.h:12
Best individual selection operator.
Definition: SelBestOp.h:10
Fitness proportional (and inverse proportional) individual selection operator.
Random individual selection operator.
Definition: SelRandomOp.h:12