1 /*
2 * Open BEAGLE
3 * Copyright (C) 2001-2007 by Christian Gagne and Marc Parizeau
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Contact:
20 * Laboratoire de Vision et Systemes Numeriques
21 * Departement de genie electrique et de genie informatique
22 * Universite Laval, Quebec, Canada, G1K 7P4
23 * http://vision.gel.ulaval.ca
24 *
25 */
26
27 /*!
28 * \file beagle/src/EvaluationMultipleOp.cpp
29 * \brief Source code of class EvaluationMultipleOp.
30 * \author Matthew Walker
31 * $Revision: 1.12.2.1 $
32 * $Date: 2007/05/09 01:51:18 $
33 */
34
35 #include "beagle/Beagle.hpp"
36
37 #include <algorithm>
38 #include <string>
39 #include <deque>
40
41
42 using namespace Beagle;
43
44 /*!
45 * \brief Construct a new multiple-individual evaluation operator.
46 * \param inIndisPerCaseAndGroup Number of individuals per test cases and group.
47 * \param inName Name of the operator.
48 */
EvaluationMultipleOp(unsigned int inIndisPerCaseAndGroup,Beagle::string inName)49 EvaluationMultipleOp::EvaluationMultipleOp(unsigned int inIndisPerCaseAndGroup,
50 Beagle::string inName) :
51 EvaluationOp(inName),
52 mIndisPerCase(inIndisPerCaseAndGroup),
53 mIndisPerGroup(inIndisPerCaseAndGroup)
54 { }
55
56
57 /*!
58 * \brief Construct a new multiple-individual evaluation operator.
59 * \param inIndisPerCase Number of individuals per test cases.
60 * \param inIndisPerGroup Number of individuals per group.
61 * \param inName Name of the operator.
62 */
EvaluationMultipleOp(unsigned int inIndisPerCase,unsigned int inIndisPerGroup,Beagle::string inName)63 EvaluationMultipleOp::EvaluationMultipleOp(unsigned int inIndisPerCase,
64 unsigned int inIndisPerGroup,
65 Beagle::string inName) :
66 EvaluationOp(inName),
67 mIndisPerCase(inIndisPerCase),
68 mIndisPerGroup(inIndisPerGroup)
69 { }
70
71
72 /*!
73 * \brief Apply the evaluation operation on a breeding pool, returning a evaluated bred individual.
74 * \param inBreedingPool Breeding pool to use for the breeding operation.
75 * \param inChild Node handle associated to child node in the breeder tree.
76 * \param ioContext Evolutionary context of the breeding operation.
77 * \return Evaluated bred individual.
78 */
breed(Individual::Bag & inBreedingPool,BreederNode::Handle inChild,Context & ioContext)79 Individual::Handle EvaluationMultipleOp::breed(Individual::Bag& inBreedingPool,
80 BreederNode::Handle inChild,
81 Context& ioContext)
82 {
83 Beagle_StackTraceBeginM();
84 throw Beagle_UndefinedMethodInternalExceptionM("EvaluationMultipleOp", "breed", getName());
85 return Individual::Handle(NULL);
86 Beagle_StackTraceEndM("Individual::Handle EvaluationMultipleOp::breed(Individual::Bag& inBreedingPool, BreederNode::Handle inChild, Context& ioContext)");
87 }
88
89
90 /*!
91 * \brief Add individuals to the bag such that the total equals getIndisPerGroup().
92 * \param ioIndividuals Bag of individuals to evaluate.
93 * \param ioContexts Bag of evolutionary context.
94 * \return The number of individuals added to the bag.
95 *
96 * The new individuals are chosen from the current deme.
97 */
enlargeGroup(Individual::Bag & ioIndividuals,Context::Bag & ioContexts)98 unsigned int EvaluationMultipleOp::enlargeGroup(Individual::Bag& ioIndividuals,
99 Context::Bag& ioContexts)
100 {
101 Beagle_StackTraceBeginM();
102 Context& lContext = castObjectT<Context&>(*(ioContexts[0]));
103
104 // Calculate the number of individuals to add
105 unsigned int lNumToAdd = mIndisPerGroup - ioIndividuals.size();
106 Beagle_LogVerboseM(
107 lContext.getSystem().getLogger(),
108 "evaluation", "Beagle::EvaluationMultipleOp",
109 string("Adding ")+uint2str(lNumToAdd)+string(" individuals to the group (for padding)")
110 );
111
112 // Resize the bags
113 unsigned int lIndisCounter = ioIndividuals.size();
114 ioIndividuals.resize(mIndisPerGroup);
115 ioContexts.resize(mIndisPerGroup);
116
117 // Loop through all the individuals in the deme
118 Deme& lDeme = lContext.getDeme();
119 std::vector< unsigned int,BEAGLE_STLALLOCATOR<unsigned int> > lSelectableIndis;
120 lSelectableIndis.resize(lDeme.size());
121 unsigned int lSelectableIndisCounter = 0;
122 for (unsigned int i=0; i<lDeme.size(); i++) {
123 // Loop through all the individuals in the bag
124 bool lAdd = true;
125 for(unsigned int j=0; j<ioIndividuals.size(); j++) {
126 if(lDeme[i] == ioIndividuals[j]) {
127 lAdd = false;
128 break;
129 }
130 }
131 // If the individual is not already in the bag, add it as an option
132 if(lAdd) {
133 lSelectableIndis[lSelectableIndisCounter] = i;
134 lSelectableIndisCounter++;
135 }
136 }
137
138 // Check there are sufficient individuals to choose
139 if(lSelectableIndis.size() < lNumToAdd) {
140 throw Beagle_RunTimeExceptionM("There are insufficient individuals in the deme to perform evaluation");
141 }
142
143 // Add individuals
144 for(unsigned int i=0; i<lNumToAdd; i++) {
145 unsigned int lIndex =
146 lContext.getSystem().getRandomizer().rollInteger(0,lSelectableIndisCounter-1);
147 unsigned int lIndiIndex = lSelectableIndis[lIndex];
148 Beagle_LogVerboseM(
149 lContext.getSystem().getLogger(),
150 "evaluation", "Beagle::EvaluationMultipleOp",
151 string("Adding ")+uint2ordinal(lIndiIndex+1)+
152 string(" individual to the group (for padding)")
153 );
154 Beagle_AssertM(lIndiIndex < lDeme.size());
155 ioIndividuals[lIndisCounter] = lDeme[ lIndiIndex ];
156 ioContexts[lIndisCounter]
157 = castHandleT<Context>(lContext.getSystem().getContextAllocator().clone( *(ioContexts[0]) ));
158 ioContexts[lIndisCounter]->setIndividualHandle( ioIndividuals[lIndisCounter] );
159 ioContexts[lIndisCounter]->setIndividualIndex( lIndiIndex );
160 lIndisCounter++;
161 }
162 Beagle_AssertM( lIndisCounter==ioIndividuals.size() );
163
164 return lNumToAdd;
165 Beagle_StackTraceEndM("unsigned int EvaluationMultipleOp::enlargeGroup(Individual::Bag&,Context::Bag&)");
166 }
167
168
169
170 /*!
171 * \brief Evaluate the fitness of the given individual.
172 * \param inIndividual Current individual to evaluate.
173 * \param ioContext Evolutionary context.
174 * \return Handle to the fitness value of the individual.
175 *
176 * This method evaluates only a single individual. For this
177 * operator, it is much better to group individuals into a bag and
178 * pass the bag to evaluate(Individual::Bag& ioIndividuals, Context::Bag& ioContexts).
179 */
evaluate(Individual & inIndividual,Context & ioContext)180 Fitness::Handle EvaluationMultipleOp::evaluate(Individual& inIndividual, Context& ioContext)
181 {
182 Beagle_StackTraceBeginM();
183 // Create a bag for the individual
184 Individual::Bag lIndividuals;
185 lIndividuals.resize(1);
186 Beagle_AssertM(inIndividual == ioContext.getIndividual());
187 lIndividuals[0] = ioContext.getIndividualHandle();
188
189 // Create a context for the individual
190 Context::Bag lContexts;
191 lContexts.resize(1);
192 lContexts[0] =
193 castHandleT<Context>(ioContext.getSystem().getContextAllocator().clone( ioContext));
194
195 // Call evalutate()
196 Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals,lContexts);
197
198 // Return fitness
199 Beagle_AssertM( !lFitnessBag->empty() );
200 return lFitnessBag->at(0);
201 Beagle_StackTraceEndM("Fitness::Handle EvaluationMultipleOp::evaluate(Individual&,Context&)");
202 }
203
204
205 /*!
206 * \brief Evaluate the fitness of the given bag of individuals.
207 * \param ioIndividuals Bag of individuals to evaluate.
208 * \param ioContexts Bag of evolutionary context.
209 * \return Handle to a bag of fitness values, one for each individual.
210 */
evaluateIndividuals(Individual::Bag & ioIndividuals,Context::Bag & ioContexts)211 Fitness::Bag::Handle EvaluationMultipleOp::evaluateIndividuals(Individual::Bag& ioIndividuals,
212 Context::Bag& ioContexts)
213 {
214 Beagle_StackTraceBeginM();
215 Beagle_AssertM(ioIndividuals.size()==ioContexts.size());
216 Beagle_AssertM(ioIndividuals.size()!=0);
217
218 Context& lContext = castObjectT<Context&>(*(ioContexts[0]));
219
220 // Check if sufficient individuals are in the bag
221 Beagle_AssertM( ioIndividuals.size() <= mIndisPerGroup );
222 unsigned int lNumToIgnore = 0;
223 if (ioIndividuals.size() != mIndisPerGroup) {
224 lNumToIgnore = enlargeGroup(ioIndividuals, ioContexts);
225 }
226
227 // Create bag of null-fitnesses
228 Fitness::Bag::Handle lFitnessBagAll = new Fitness::Bag;
229 lFitnessBagAll->resize( ioIndividuals.size() );
230 Beagle_NonNullPointerAssertM( lFitnessBagAll );
231
232 // Set up cases
233 if (mCases == NULL) setupCases(ioIndividuals.size(),lContext);
234 Case::Bag::Handle lCases = pruneIgnorableCases(lNumToIgnore);
235
236 // Call evaluateCase for each case
237 for (unsigned int i=0; i<lCases->size(); i++) {
238 Beagle_LogVerboseM(
239 lContext.getSystem().getLogger(),
240 "evaluation", "Beagle::EvaluationMultipleOp",
241 string("Evaluating the ")+uint2ordinal(i+1)+string(" case")
242 );
243 Case& lCase = *(lCases->at(i));
244 Beagle_AssertM( lCase.mIndices.size() == mIndisPerCase );
245
246 // Setup bags of individuals and contexts
247 Individual::Bag lIndividuals;
248 Context::Bag lContexts;
249 lIndividuals.resize( mIndisPerCase );
250 lContexts.resize( mIndisPerCase );
251 for (unsigned int j=0; j<mIndisPerCase; j++) {
252 unsigned int lIndex = lCase.mIndices[j];
253 lIndividuals[j] = ioIndividuals[ lIndex ];
254 lContexts[j] = ioContexts[ lIndex ];
255 }
256
257 // Log individual's details
258 std::ostringstream lOSS;
259 for (unsigned int j=0; j<lIndividuals.size(); j++) {
260 if (j!=0) lOSS << ", ";
261 lOSS << uint2ordinal(lContexts[j]->getIndividualIndex()+1);
262 }
263 Beagle_LogDebugM(
264 lContext.getSystem().getLogger(),
265 "evaluation", "Beagle::EvaluationMultipleOp",
266 uint2ordinal(i+1)+string(" case: ")+
267 lOSS.str().c_str()
268 );
269
270 // Call evalutateCase()
271 Fitness::Bag::Handle lFitnessBagCase =
272 evaluateCase(lIndividuals, lContexts);
273
274 // Log resulting fitnesses
275 Beagle_NonNullPointerAssertM( lFitnessBagCase );
276 Beagle_LogDebugM(
277 lContext.getSystem().getLogger(),
278 "evaluation", "Beagle::EvaluationMultipleOp",
279 string("Evaluation of the case is complete. The fitnesses are as follows:")
280 );
281 for (unsigned int j=0; j<mIndisPerCase; j++) {
282 Beagle_NonNullPointerAssertM( lFitnessBagCase->at(j) );
283 Beagle_LogDebugM(
284 lContext.getSystem().getLogger(),
285 "evaluation", "Beagle::EvaluationMultipleOp",
286 string("Fitness of the ")+
287 uint2ordinal(ioContexts[lCase.mIndices[j]]->getIndividualIndex()+1)+
288 string(" individual: ")+lFitnessBagCase->at(j)->serialize()
289 );
290
291 // Need to assign fitness values from case to lFitnessBagAll
292 unsigned int lIndex = lCase.mIndices[j];
293 Beagle_LogDebugM(
294 lContext.getSystem().getLogger(),
295 "evaluation", "Beagle::EvaluationMultipleOp",
296 string("Setting fitness for lFitnessBagAll at index ")+uint2str(lIndex)
297 );
298 Beagle_AssertM(lIndex < lFitnessBagAll->size());
299 if (lFitnessBagAll->at(lIndex)==NULL) {
300 (*lFitnessBagAll)[lIndex] = lFitnessBagCase->at(j);
301 }
302 else {
303 combineFitnesses(lFitnessBagAll->at(lIndex),
304 lFitnessBagCase->at(j) );
305 Beagle_LogDebugM(
306 lContext.getSystem().getLogger(),
307 "evaluation", "Beagle::EvaluationMultipleOp",
308 string("Fitness of the ")+uint2ordinal(ioContexts[lIndex]->getIndividualIndex()+1)+
309 string(" individual has been combined to: ")+lFitnessBagAll->at(lIndex)->serialize()
310 );
311 }
312 }
313 }
314
315 Beagle_LogDebugM(
316 lContext.getSystem().getLogger(),
317 "evaluation", "Beagle::EvaluationMultipleOp",
318 string("Evaluation of all cases is complete. Fitnesses are as follows:")
319 );
320 for (unsigned int i=0;
321 i<ioIndividuals.size();
322 i++) {
323 if (i>=mIndisPerGroup-lNumToIgnore) {
324 // Nullify ignorable individuals' fitness scores
325 Beagle_LogDebugM(
326 lContext.getSystem().getLogger(),
327 "evaluation", "Beagle::EvaluationMultipleOp",
328 string("Ignoring fitness of the ")+uint2ordinal(ioContexts[i]->getIndividualIndex()+1)+
329 string(" individual")
330 );
331 (*lFitnessBagAll)[i] = NULL;
332 continue;
333 }
334 Beagle_NonNullPointerAssertM( lFitnessBagAll->at(i) );
335 Beagle_LogDebugM(
336 lContext.getSystem().getLogger(),
337 "evaluation", "Beagle::EvaluationMultipleOp",
338 string("Fitness of the ")+uint2ordinal(ioContexts[i]->getIndividualIndex()+1)+
339 lFitnessBagAll->at(i)->serialize()
340 );
341 }
342
343 return lFitnessBagAll;
344 Beagle_StackTraceEndM("Fitness::Bag::Handle EvaluationMultipleOp::evaluateIndividuals(Individual::Bag&,Context::Bag&)");
345 }
346
347
348 /*!
349 * \brief Apply the evaluation process on the invalid individuals of the deme.
350 * \param ioDeme Deme to process.
351 * \param ioContext Context of the evolution.
352 */
operate(Deme & ioDeme,Context & ioContext)353 void EvaluationMultipleOp::operate(Deme& ioDeme, Context& ioContext)
354 {
355 Beagle_StackTraceBeginM();
356 Beagle_LogTraceM(
357 ioContext.getSystem().getLogger(),
358 "evaluation", "Beagle::EvaluationMultipleOp",
359 string("Evaluating the fitness of the individuals in the ")+
360 uint2ordinal(ioContext.getDemeIndex()+1)+" deme"
361 );
362
363 Beagle_AssertM( ioDeme.size()!=0 );
364
365 // Prepare stats
366 prepareStats(ioDeme,ioContext);
367
368 // Generate a vector of indicies into the population
369 std::vector< unsigned int,BEAGLE_STLALLOCATOR<unsigned int> > lEvalVector;
370 for(unsigned int i=0; i<ioDeme.size(); i++) {
371 if((ioDeme[i]->getFitness() == NULL) ||
372 (ioDeme[i]->getFitness()->isValid() == false)) {
373 lEvalVector.push_back(i);
374 Beagle_LogDebugM(
375 ioContext.getSystem().getLogger(),
376 "evaluation", "Beagle::EvaluationMultipleOp",
377 string("Added ")+uint2ordinal(i+1)+string(" individual for evaluation.")
378 );
379 }
380 }
381 std::random_shuffle(lEvalVector.begin(), lEvalVector.end(),
382 ioContext.getSystem().getRandomizer());
383
384 Beagle_LogDebugM(
385 ioContext.getSystem().getLogger(),
386 "evaluation", "Beagle::EvaluationMultipleOp",
387 string("There are ")+uint2str(lEvalVector.size())+
388 string(" individuals to be evaluated.")
389 );
390
391 while ( !lEvalVector.empty() ) {
392 // Put individuals and context into bags.
393 Individual::Bag lIndividuals;
394 Context::Bag lContexts;
395 lIndividuals.resize( mIndisPerGroup );
396 lContexts.resize( mIndisPerGroup );
397 unsigned int lIndiCounter =0;
398
399 for (unsigned int i=0; i<mIndisPerGroup; i++) {
400 // Set individual
401 lIndividuals[i] = ioDeme[lEvalVector.back()];
402 lIndiCounter++;
403 // Set context
404 Context::Handle lContext =
405 castHandleT<Context>(ioContext.getSystem().getContextAllocator().clone(ioContext));
406 lContext->setIndividualIndex( lEvalVector.back() );
407 lContext->setIndividualHandle( ioDeme[lEvalVector.back()] );
408 lContexts[i] = lContext;
409 // Remove this index from the evaluation vector
410 lEvalVector.pop_back();
411 if(lEvalVector.empty()) {
412 lIndividuals.resize( lIndiCounter );
413 lContexts.resize( lIndiCounter );
414 break;
415 }
416 }
417
418 // Evaluate individuals
419 std::ostringstream lOSS;
420 for (unsigned int i=0; i<lIndiCounter; i++) {
421 // Add to message
422 if (i==lIndiCounter-1) lOSS << " and ";
423 lOSS << uint2ordinal(lContexts[i]->getIndividualIndex()+1);
424 if (i<lIndiCounter-2) lOSS << ", ";
425 }
426 Beagle_LogVerboseM(
427 ioContext.getSystem().getLogger(),
428 "evaluation", "Beagle::EvaluationMultipleOp",
429 string("Evaluating the fitness of the ")+string(lOSS.str().c_str())+
430 " individuals"
431 );
432 Fitness::Bag::Handle lFitnessBag = evaluateIndividuals(lIndividuals, lContexts);
433
434 // Assign fitnesses
435 for (unsigned int i=0; i<lIndiCounter; i++) {
436 Beagle_LogDebugM(
437 ioContext.getSystem().getLogger(),
438 "evaluation", "Beagle::EvaluationMultipleOp",
439 string("Considering fitness of the ")+
440 uint2ordinal(lContexts[i]->getIndividualIndex()+1)+string(" individual")
441 );
442 Beagle_AssertM( i < lFitnessBag->size() );
443 Fitness::Handle lFitness = lFitnessBag->at(i);
444 Beagle_NonNullPointerAssertM( lFitness );
445 lIndividuals[i]->setFitness( lFitness );
446 lIndividuals[i]->getFitness()->setValid();
447
448 Beagle_LogVerboseM(
449 ioContext.getSystem().getLogger(),
450 "evaluation", "Beagle::EvaluationMultipleOp",
451 string("The fitness of the ")+uint2ordinal(lContexts[i]->getIndividualIndex()+1)+
452 string(" individual is: ")+
453 lIndividuals[i]->getFitness()->serialize()
454 );
455 }
456
457 // Update stats
458 updateStats(lIndividuals.size(),ioContext);
459 }
460
461 updateHallOfFameWithDeme(ioDeme,ioContext);
462 Beagle_StackTraceEndM("void EvaluationMultipleOp::operate(Deme&,Context&)");
463 }
464
465
466 /*!
467 * \brief Removes cases that contain only references to individuals
468 * that are acting a padding.
469 * \param inNumToIgnore Number of individuals that have been added as padding.
470 */
471 EvaluationMultipleOp::Case::Bag::Handle
pruneIgnorableCases(unsigned int inNumToIgnore)472 EvaluationMultipleOp::pruneIgnorableCases(unsigned int inNumToIgnore)
473 {
474 Beagle_StackTraceBeginM();
475 if (inNumToIgnore==0) return mCases;
476
477 Case::Bag::Handle lCases = new Case::Bag;
478 lCases->resize( mCases->size() );
479 unsigned int lCaseCounter = 0;
480
481 // Check every case
482 for (unsigned int i=0; i<mCases->size(); i++) {
483 // Check if any of the indices are not able to be ignored
484 Case& lCase = *(mCases->at(i));
485 bool lAdd = false;
486 for (unsigned int j=0; j<lCase.mIndices.size(); j++) {
487 if (lCase.mIndices[j] < mIndisPerGroup-inNumToIgnore) {
488 lAdd=true;
489 break;
490 }
491 }
492 // If it cannot be ignored, add it to the bag of "un-ignorables"
493 if (lAdd) {
494 (*lCases)[lCaseCounter] = (*mCases)[i];
495 lCaseCounter++;
496 }
497 }
498
499 lCases->resize(lCaseCounter);
500 return lCases;
501 Beagle_StackTraceEndM("EvaluationMultipleOp::Case::Bag::Handle EvaluationMultipleOp::pruneIgnorableCases(unsigned int)");
502 }
503
504
505 /*!
506 * \brief Sets up cases.
507 * \param inSize Number of individuals in a group.
508 * \param ioContext Context of the evolution.
509 *
510 * A case is a vector of indices into a bag of individuals. This
511 * method creates cases. The number of cases is decided by inSize.
512 *
513 * For example, if inSize is 4 (set by setIndisPerGroup), then the
514 * indices will range from 0 to 3. If each case contains just two
515 * individuals (as set by setIndisPerCase) then the cases will be:
516 * (0,1) (0,2) (0,3)
517 * (1,2) (1,3)
518 * (2,3)
519 * Where (x,y) dictates a case when individual x will compete against
520 * indiviudal y.
521 */
setupCases(unsigned int inSize,Context & ioContext)522 void EvaluationMultipleOp::setupCases(unsigned int inSize, Context& ioContext)
523 {
524 Beagle_StackTraceBeginM();
525 Beagle_LogDebugM(
526 ioContext.getSystem().getLogger(),
527 "evaluation", "Beagle::EvaluationMultipleOp",
528 string("Creating evaluation cases")
529 );
530 Beagle_AssertM(inSize >= mIndisPerCase);
531 Beagle_AssertM(inSize == mIndisPerGroup);
532
533 // Create cases with each case containing one individual
534 mCases = new Case::Bag;
535 Beagle_NonNullPointerAssertM( mCases );
536 for (unsigned int i=0; i<inSize; i++) {
537 Case::Handle lCase = new Case;
538 lCase->mIndices.push_back( i );
539 setupCaseRecursive(inSize,i,lCase);
540 }
541
542 // Log cases
543 Beagle_LogDebugM(
544 ioContext.getSystem().getLogger(),
545 "evaluation", "Beagle::EvaluationMultipleOp",
546 uint2str(mCases->size())+string(" evaluation cases were created")
547 );
548 for (unsigned int i=0; i<mCases->size(); i++) {
549 std::ostringstream lOSS;
550 for (unsigned int j=0; j<mCases->at(i)->mIndices.size(); j++) {
551 if (j!=0) lOSS << ", ";
552 lOSS << mCases->at(i)->mIndices[j];
553 }
554 Beagle_LogDebugM(
555 ioContext.getSystem().getLogger(),
556 "evaluation", "Beagle::EvaluationMultipleOp",
557 uint2ordinal(i+1)+string(" case: ")+
558 lOSS.str().c_str()
559 );
560 }
561 Beagle_StackTraceEndM("void EvaluationMultipleOp::setupCases(unsigned int,Context&)");
562 }
563
564
565 /*!
566 * \brief Sets up cases by adding one more individual into a clone of
567 * inCase, and then calling this method for each one of those cases.
568 * \param inSize Number of individuals in a group.
569 * \param inLastIndex The index of the last individual that was
570 * inserted into the case.
571 * \param inCase The case on which to work.
572 */
setupCaseRecursive(unsigned int inSize,unsigned int inLastIndex,Case::Handle inCase)573 void EvaluationMultipleOp::setupCaseRecursive(unsigned int inSize,
574 unsigned int inLastIndex,
575 Case::Handle inCase)
576 {
577 using namespace std;
578 Beagle_StackTraceBeginM();
579 unsigned int lCaseSize = inCase->mIndices.size();
580
581 // Check if the case is finished.
582 if (lCaseSize == mIndisPerCase) {
583 unsigned int lSize = mCases->size();
584 mCases->resize( lSize + 1 );
585 (*mCases)[lSize]=inCase;
586 return;
587 }
588
589 // Case isn't finished, add another individual to it.
590 Beagle_AssertM( lCaseSize<mIndisPerCase );
591 for (unsigned int i=inLastIndex+1;
592 i<inSize;
593 i++) {
594 Case::Handle lNewCase = new Case(*(inCase));
595 lNewCase->mIndices.push_back(i);
596 setupCaseRecursive(inSize,i,lNewCase);
597 }
598 Beagle_StackTraceEndM("void EvaluationMultipleOp::setupCaseRecursive(unsigned int,unsigned int,Case::Handle");
599 }
600