1 /*
2 ================================================================================
3     PROJECT:
4 
5         John Eddy's Genetic Algorithms (JEGA)
6 
7     CONTENTS:
8 
9         Implementation of class MaxDesignsNichePressureApplicator.
10 
11     NOTES:
12 
13         See notes of MaxDesignsNichePressureApplicator.hpp.
14 
15     PROGRAMMERS:
16 
17         John Eddy (jpeddy@sandia.gov) (JE)
18 
19     ORGANIZATION:
20 
21         Sandia National Laboratories
22 
23     COPYRIGHT:
24 
25         See the LICENSE file in the top level JEGA directory.
26 
27     VERSION:
28 
29         2.7.0
30 
31     CHANGES:
32 
33         Wed Dec 21 16:25:44 2011 - Original Version (JE)
34 
35 ================================================================================
36 */
37 
38 
39 
40 
41 /*
42 ================================================================================
43 Document This File
44 ================================================================================
45 */
46 /** \file
47  * \brief Contains the implementation of the MaxDesignsNichePressureApplicator
48  *        class.
49  */
50 
51 
52 
53 
54 /*
55 ================================================================================
56 Includes
57 ================================================================================
58 */
59 // JEGAConfig.hpp should be the first include in all JEGA files.
60 #include <../Utilities/include/JEGAConfig.hpp>
61 
62 #include <FitnessRecord.hpp>
63 #include <GeneticAlgorithmSelector.hpp>
64 #include <../Utilities/include/Logging.hpp>
65 #include <../Utilities/include/DesignGroup.hpp>
66 #include <utilities/include/EDDY_DebugScope.hpp>
67 #include <../Utilities/include/ParameterExtractor.hpp>
68 #include <utilities/include/RandomNumberGenerator.hpp>
69 #include <../Utilities/include/MultiObjectiveStatistician.hpp>
70 #include <../MOGA/include/NichePressureApplicators/MaxDesignsNichePressureApplicator.hpp>
71 
72 
73 
74 
75 
76 
77 
78 /*
79 ================================================================================
80 Namespace Using Directives
81 ================================================================================
82 */
83 using namespace std;
84 using namespace JEGA::Logging;
85 using namespace JEGA::Utilities;
86 using namespace eddy::utilities;
87 
88 
89 
90 
91 
92 
93 /*
94 ================================================================================
95 Begin Namespace
96 ================================================================================
97 */
98 namespace JEGA {
99     namespace Algorithms {
100 
101 
102 
103 
104 
105 /*
106 ================================================================================
107 Static Member Data Definitions
108 ================================================================================
109 */
110 const double MaxDesignsNichePressureApplicator::DEFAULT_DIST_PCT(0.01);
111 const size_t MaxDesignsNichePressureApplicator::DEFAULT_MAX_DESIGNS(100);
112 
113 
114 
115 
116 
117 
118 
119 /*
120 ================================================================================
121 Mutators
122 ================================================================================
123 */
124 
125 void
SetDistancePercentages(const JEGA::DoubleVector & pcts)126 MaxDesignsNichePressureApplicator::SetDistancePercentages(
127     const JEGA::DoubleVector& pcts
128     )
129 {
130     EDDY_FUNC_DEBUGSCOPE
131 
132     const std::size_t nof = this->GetDesignTarget().GetNOF();
133 
134     JEGAIFLOG_CF_II(nof < pcts.size(), this->GetLogger(), lquiet(), this,
135         text_entry(lquiet(),
136             this->GetName() + ": Received more percentages than there are "
137             "objective functions.  Extras will be ignored.")
138         )
139 
140     JEGAIFLOG_CF_II(nof > pcts.size() && pcts.size() > 1, this->GetLogger(),
141         lquiet(), this, ostream_entry(lquiet(),
142             this->GetName() + ": Received fewer percentages (") << pcts.size()
143             << ") than there are objective functions (" << nof << ").  "
144             "Using default value of " << DEFAULT_DIST_PCT << " to fill in."
145         )
146 
147     JEGAIFLOG_CF_II(nof > pcts.size() && pcts.size() == 1, this->GetLogger(),
148         lquiet(), this, ostream_entry(lquiet(),
149             this->GetName() + ": Received a single distance percentage for a ")
150             << nof << " objective function problem.  Using the supplied value "
151             "of " << pcts[0] << " for all objectives."
152         )
153 
154     this->_distPcts = pcts;
155 
156     const double fill_val =
157         (this->_distPcts.size() == 1) ? this->_distPcts[0] : DEFAULT_DIST_PCT;
158 
159     if(nof > this->_distPcts.size())
160         this->_distPcts.resize(
161             static_cast<JEGA::DoubleVector::size_type>(nof), fill_val
162             );
163 
164     // now go through and set each one individually so that they can be checked
165     // for legitimacy.
166     for(JEGA::DoubleVector::size_type i=0; i<nof; ++i)
167         this->SetDistancePercentage(i, this->_distPcts[i]);
168 }
169 
170 void
SetDistancePercentages(double pct)171 MaxDesignsNichePressureApplicator::SetDistancePercentages(
172     double pct
173     )
174 {
175     EDDY_FUNC_DEBUGSCOPE
176 
177     JEGA_LOGGING_IF_ON(
178         static const double minPct = std::numeric_limits<double>::min();
179         )
180 
181     const std::size_t nof = this->GetDesignTarget().GetNOF();
182 
183     JEGAIFLOG_CF_II(pct < 0.0, this->GetLogger(), lquiet(), this,
184         ostream_entry(lquiet(),
185             this->GetName() + ": Distance percentages must be at least ")
186             << minPct << " Supplied value of " << pct
187             << " will be replaced by the minimum."
188         )
189 
190     JEGAIFLOG_CF_II(pct > 1.0, this->GetLogger(), lquiet(), this,
191         ostream_entry(lquiet(),
192             this->GetName() + ": Distance percentages cannot exceed 100%.  "
193             "Supplied value of ") << pct << " will be replaced by 100%."
194         )
195 
196     pct = Math::Max(0.0, Math::Min(pct, 1.0));
197 
198     this->_distPcts.assign(
199         static_cast<JEGA::DoubleVector::size_type>(nof), pct
200         );
201 
202     JEGALOG_II(this->GetLogger(), lverbose(), this,
203         ostream_entry(lverbose(),
204             this->GetName() + ": All distance percentages now = ") << pct
205         )
206 }
207 
208 void
SetDistancePercentage(std::size_t of,double pct)209 MaxDesignsNichePressureApplicator::SetDistancePercentage(
210     std::size_t of,
211     double pct
212     )
213 {
214     EDDY_FUNC_DEBUGSCOPE
215 
216     JEGA_LOGGING_IF_ON(
217         static const double minPct = std::numeric_limits<double>::min();
218         )
219 
220     const DesignTarget& target = GetDesignTarget();
221     const std::size_t nof = target.GetNOF();
222     const JEGA::DoubleVector::size_type dvsof =
223         static_cast<JEGA::DoubleVector::size_type>(of);
224 
225     // make sure we have enough locations in the percentages vector.
226     this->_distPcts.resize(
227         static_cast<JEGA::DoubleVector::size_type>(nof), DEFAULT_DIST_PCT
228         );
229 
230     // now verify the supplied objective function index.
231     JEGAIFLOG_CF_II_F(of >= nof, this->GetLogger(), this,
232         ostream_entry(lfatal(),
233             this->GetName() + ": Request to change objective with index #")
234             << of << ".  Valid indices are 0 through " << (nof-1) << "."
235         )
236 
237     // now verify the supplied value.
238     JEGAIFLOG_CF_II(pct < 0.0, this->GetLogger(), lquiet(), this,
239         ostream_entry(lquiet(),
240             this->GetName() + ": Distance percentages must be at least ")
241             << minPct << " Supplied value of " << pct << " for objective \""
242             << target.GetObjectiveFunctionInfos()[dvsof]->GetLabel()
243             << "\" will be replaced by the minimum."
244         )
245 
246     JEGAIFLOG_CF_II(pct < 0.0, this->GetLogger(), lquiet(), this,
247         ostream_entry(lquiet(),
248             this->GetName() + ": Distance percentages cannot exceed 100%.  "
249             "Supplied value of ") << pct << " for objective \""
250             << target.GetObjectiveFunctionInfos()[dvsof]->GetLabel()
251             << "\" will be replaced by 100%."
252         )
253 
254     pct = Math::Max(0.0, Math::Min(pct, 1.0));
255 
256     this->_distPcts[dvsof] = pct;
257 
258     JEGALOG_II(this->GetLogger(), lverbose(), this,
259         ostream_entry(lverbose(),
260             this->GetName() + ": Distance for objective \"")
261             << target.GetObjectiveFunctionInfos()[dvsof]->GetLabel()
262             << "\" now = " << pct << "."
263         )
264 }
265 
266 void
SetMaximumDesigns(std::size_t maxDesigns)267 MaxDesignsNichePressureApplicator::SetMaximumDesigns(
268     std::size_t maxDesigns
269     )
270 {
271     EDDY_FUNC_DEBUGSCOPE
272 
273     this->_maxDesigns = maxDesigns;
274 
275     JEGALOG_II(this->GetLogger(), lverbose(), this,
276         ostream_entry(lverbose(),
277             this->GetName() + ": Maximum designs now = "
278             ) << this->_maxDesigns
279         )
280 }
281 
282 
283 
284 
285 
286 
287 
288 
289 /*
290 ================================================================================
291 Accessors
292 ================================================================================
293 */
294 
295 
296 
297 /*
298 ================================================================================
299 Public Methods
300 ================================================================================
301 */
302 
303 const string&
Name()304 MaxDesignsNichePressureApplicator::Name(
305     )
306 {
307     EDDY_FUNC_DEBUGSCOPE
308     static const string ret("max_designs");
309     return ret;
310 }
311 
312 const string&
Description()313 MaxDesignsNichePressureApplicator::Description(
314     )
315 {
316     EDDY_FUNC_DEBUGSCOPE
317 
318     static const string ret(
319         "This niche pressure applicator is designed to choose a limited "
320         "number of solutions to remain in the population.  It does so in "
321         "order to balance the tendency for populations to grow very large "
322         "and thus consuming too many computer resources.  It operates by "
323         "ranking designs according to their fitness standing and a "
324         "computed count of how many other designs are too close to them.  Too "
325         "close is a function of the supplied niche_vector.  Once the designs "
326         "are all ranked, the top max_designs designs are kept in the "
327         "population and the remaining ones are buffered or discarded "
328         "depending on the value of the cache_niched_designs flag.  Note that "
329         "like other niching operators, this one will not discard an extreme "
330         "design."
331         );
332     return ret;
333 }
334 
335 GeneticAlgorithmOperator*
Create(GeneticAlgorithm & algorithm)336 MaxDesignsNichePressureApplicator::Create(
337     GeneticAlgorithm& algorithm
338     )
339 {
340     EDDY_FUNC_DEBUGSCOPE
341     return new MaxDesignsNichePressureApplicator(algorithm);
342 }
343 
344 
345 
346 
347 
348 
349 
350 /*
351 ================================================================================
352 Subclass Visible Methods
353 ================================================================================
354 */
355 
356 
357 JEGA::DoubleVector
ComputeCutoffDistances(const eddy::utilities::extremes<obj_val_t> & exts) const358 MaxDesignsNichePressureApplicator::ComputeCutoffDistances(
359     const eddy::utilities::extremes<obj_val_t>& exts
360     ) const
361 {
362     EDDY_FUNC_DEBUGSCOPE
363 
364     typedef eddy::utilities::extremes<obj_val_t> extremes_t;
365 
366     // the cutoff distance is a percentage of the range of the objective
367     // considering only the non-dominated designs.
368     const std::size_t nof = this->GetDesignTarget().GetNOF();
369 
370     JEGAIFLOG_CF_II_F(nof != exts.size(), GetLogger(), this,
371         ostream_entry(lfatal(), this->GetName() + ": Extremes contain "
372             "record of ") << exts.size() << " objectives for an "
373             << nof << " objective problem."
374         )
375 
376     // Prepare a vector for return.
377     JEGA::DoubleVector ret(nof);
378 
379     for(extremes_t::size_type i=0; i<nof; ++i)
380         ret[i] = Math::Abs(
381             this->GetDistancePercentage(i) * exts.get_range(i)
382             );
383 
384     // return the square route of the sum of squares.
385     return ret;
386 }
387 
388 double
ComputeObjectiveDistance(const Design & des1,const Design & des2,size_t of)389 MaxDesignsNichePressureApplicator::ComputeObjectiveDistance(
390     const Design& des1,
391     const Design& des2,
392     size_t of
393     )
394 {
395     EDDY_FUNC_DEBUGSCOPE
396     return Math::Abs(des1.GetObjective(of) - des2.GetObjective(of));
397 }
398 
399 
400 
401 
402 
403 
404 /*
405 ================================================================================
406 Subclass Overridable Methods
407 ================================================================================
408 */
409 
410 
411 string
GetName() const412 MaxDesignsNichePressureApplicator::GetName(
413     ) const
414 {
415     EDDY_FUNC_DEBUGSCOPE
416     return MaxDesignsNichePressureApplicator::Name();
417 }
418 
419 string
GetDescription() const420 MaxDesignsNichePressureApplicator::GetDescription(
421     ) const
422 {
423     EDDY_FUNC_DEBUGSCOPE
424     return MaxDesignsNichePressureApplicator::Description();
425 }
426 
427 GeneticAlgorithmOperator*
Clone(GeneticAlgorithm & algorithm) const428 MaxDesignsNichePressureApplicator::Clone(
429     GeneticAlgorithm& algorithm
430     ) const
431 {
432     EDDY_FUNC_DEBUGSCOPE
433     return new MaxDesignsNichePressureApplicator(*this, algorithm);
434 }
435 
436 bool
PollForParameters(const ParameterDatabase & db)437 MaxDesignsNichePressureApplicator::PollForParameters(
438     const ParameterDatabase& db
439     )
440 {
441     EDDY_FUNC_DEBUGSCOPE
442 
443     bool success = ParameterExtractor::GetDoubleVectorFromDB(
444         db, "method.jega.niche_vector", this->_distPcts
445         );
446 
447     // If we did not find the distance percentages, warn about it and use the
448     // default values.  Note that if !success, then _distPcts has not been
449     // altered.
450     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
451         text_entry(lverbose(), this->GetName() + ": The distance percentages "
452             "were not found in the parameter database.  Using the current "
453             "values.")
454         )
455 
456     this->SetDistancePercentages(this->_distPcts);
457 
458     success = ParameterExtractor::GetSizeTypeFromDB(
459         db, "method.jega.max_designs", this->_maxDesigns
460         );
461 
462     // If we did not find the maximum number of designs, warn about it and move
463     // on to trying the population size.  Note that if !success, then
464     // _maxDesigns has not been altered.
465     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
466         text_entry(lverbose(), this->GetName() + ": The maximum post niching "
467             "design count was not found in the parameter database.  Attempting "
468             "to find the population size to use it.")
469         )
470 
471     if(!success) success = ParameterExtractor::GetSizeTypeFromDB(
472         db, "method.population_size", this->_maxDesigns
473         );
474 
475     // If we did not find the population size either, warn about it and move
476     // on to using the default size.  Note that if !success, then
477     // _maxDesigns has not been altered.
478     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
479         text_entry(lverbose(), this->GetName() + ": The population size "
480             "was not found in the parameter database either.  Using the "
481             "default value for the maximum post niching design count.")
482         )
483 
484     this->SetMaximumDesigns(this->_maxDesigns);
485 
486     return this->GeneticAlgorithmNichePressureApplicator::PollForParameters(db);
487 }
488 
489 void
PreSelection(DesignGroup & population)490 MaxDesignsNichePressureApplicator::PreSelection(
491     DesignGroup& population
492     )
493 {
494     EDDY_FUNC_DEBUGSCOPE
495 
496     // if we are not caching designs, we needn't do anything here.
497     if(!this->GetCacheDesigns()) return;
498 
499     // Synchronize the lists just in case.
500     population.SynchronizeOFAndDVContainers();
501 
502     JEGA_LOGGING_IF_ON(
503         const DesignOFSortSet::size_type initPSize = population.SizeOF();
504         )
505 
506     // Re-assimilate the buffered designs into the population so that they
507     // can be considered when making the initial selection.  We will cull
508     // them out again when ApplyNichePressure is called later if appropriate.
509     this->ReAssimilateBufferedDesigns(population);
510 
511     JEGALOG_II(this->GetLogger(), lverbose(), this,
512         ostream_entry(lverbose(), this->GetName() + ": Returned ")
513             << (population.SizeOF() - initPSize) << " designs during "
514                "pre-selection phase of niche pressure application."
515         )
516 }
517 
518 
519 void
ApplyNichePressure(DesignGroup & population,const FitnessRecord & fitnesses)520 MaxDesignsNichePressureApplicator::ApplyNichePressure(
521     DesignGroup& population,
522     const FitnessRecord& fitnesses
523     )
524 {
525     EDDY_FUNC_DEBUGSCOPE
526 
527     JEGALOG_II(GetLogger(), ldebug(), this, text_entry(ldebug(),
528         "max designs nicher: in use."))
529 
530     // If the population is empty, we needn't go any further.
531     if(population.IsEmpty()) return;
532 
533     // Make sure that the Taboo mark is clear on all designs.
534     for(DesignDVSortSet::const_iterator it(population.BeginDV());
535         it!=population.EndDV(); ++it) (*it)->ModifyAttribute(TABOO_MARK, false);
536 
537     // in case we are not caching, we will need the target below.
538     DesignTarget& target = this->GetDesignTarget();
539 
540     // we will need the number of objectives for a few things here.
541     const size_t nof = target.GetNOF();
542 
543     // Synchronize the lists just in case.
544     population.SynchronizeOFAndDVContainers();
545 
546     // The number of designs to keep for repeated use below.
547     const size_t n2Keep = this->GetMaximumDesigns();
548 
549     // See if there are fewer solutions in the population than we are to
550     // niche to.  If so, we keep them all.
551     if(population.SizeOF() < n2Keep) return;
552 
553     JEGALOG_II(this->GetLogger(), lverbose(), this,
554         ostream_entry(lverbose(), this->GetName() + ": Population size "
555             "before niching is ") << population.GetSize() << "."
556         )
557 
558     const DesignOFSortSet& popByOf = population.GetOFSortContainer();
559 
560     JEGA_LOGGING_IF_ON(std::size_t prevPopSize = popByOf.size();)
561 
562     // Now continue by extracting the populations objective function extremes
563     eddy::utilities::extremes<obj_val_t> popExtremes(
564         DesignStatistician::GetObjectiveFunctionExtremes(popByOf)
565         );
566 
567     NicheCountMap ncts(this->ComputeNicheCounts(popByOf, popExtremes));
568 
569     // We want to make sure not to discard any "Pareto" extremes.  So find them
570     // all and keep them.  Then go into the loop below.
571     DesignOFSortSet pareto(GetBest(popByOf, fitnesses));
572 
573     // Now continue by extracting the Pareto extremes
574     this->TagTabooNicheDesigns(pareto);
575 
576     double minFit = DBL_MAX;
577     double maxFit = DBL_MIN;
578 
579     for(DesignOFSortSet::const_iterator it(popByOf.begin());
580         it!=popByOf.end(); ++it)
581     {
582         const double fit = fitnesses.GetFitness(**it);
583         if(fit < minFit) minFit = fit;
584         if(fit > maxFit) maxFit = fit;
585     }
586 
587     const double fitRng = maxFit - minFit;
588 
589     const size_t maxNCT = ncts.GetMaxValue();
590     const size_t nctRng = maxNCT - ncts.GetMinValue();
591 
592     FitnessRecord nicheFits(popByOf.size());
593     vector<const Design*> allDesVec;
594     allDesVec.reserve(popByOf.size());
595 
596     for(DesignOFSortSet::const_iterator curr(popByOf.begin());
597         curr!=popByOf.end(); ++curr)
598     {
599         const Design& des = **curr;
600         double normFit = (fitnesses.GetFitness(des) - minFit) / fitRng;
601         double normNCV = double(maxNCT - ncts.GetValue(des)) / nctRng;
602         nicheFits.AddFitness(&des, normFit + normNCV);
603         allDesVec.push_back(&des);
604     }
605 
606     sort(
607         allDesVec.begin(), allDesVec.end(),
608         GeneticAlgorithmSelector::FitnessPred(nicheFits)
609         );
610 
611     // Start at the end of the list and remove the required number all the while
612     // skipping any taboo.
613     size_t n2Remove = allDesVec.size() - n2Keep;
614     size_t index = allDesVec.size()-1;
615 
616     while(n2Remove > 0)
617     {
618         const Design* des = allDesVec[index--];
619         if(des->HasAttribute(TABOO_MARK)) continue;
620 
621         const bool buffered = this->BufferDesign(des);
622         population.Erase(des);
623         if(!buffered) target.TakeDesign(const_cast<Design*>(des));
624         --n2Remove;
625     }
626 
627     JEGALOG_II(this->GetLogger(), lverbose(), this,
628         ostream_entry(lverbose(), this->GetName() + ": Final population size "
629             "after niching is ") << population.GetSize() << "."
630         )
631 
632 }
633 
634 /*
635 ================================================================================
636 Private Methods
637 ================================================================================
638 */
639 MaxDesignsNichePressureApplicator::NicheCountMap
ComputeNicheCounts(const DesignOFSortSet & designs,const eddy::utilities::extremes<obj_val_t> & exts) const640 MaxDesignsNichePressureApplicator::ComputeNicheCounts(
641     const DesignOFSortSet& designs,
642     const eddy::utilities::extremes<obj_val_t>& exts
643     ) const
644 {
645     NicheCountMap ncm(designs.size());
646     ncm.SuspendStatistics();
647 
648     JEGA::DoubleVector dists(this->ComputeCutoffDistances(exts));
649 
650     const size_t nof = this->GetDesignTarget().GetNOF();
651 
652     for(
653         DesignOFSortSet::const_iterator iit(designs.begin());
654         iit!=designs.end(); ++iit
655         )
656     {
657         size_t ncAfter = 1; // 1 to count self
658         const Design& id = **iit;
659 
660         DesignOFSortSet::const_iterator jit(iit);
661         for(++jit; jit!=designs.end(); ++jit)
662         {
663             const Design& jd = **jit;
664 
665             // If jit is too close to iit, then we increment ncAfter and
666             // increment the count for jit stored in ncm.  That way, ncm will
667             // always have record of those that are too close prior to iit at
668             // the beginning of an iit loop.
669             const double obj0Dist = this->ComputeObjectiveDistance(id, jd, 0);
670 
671             // If the distance at obj0 is large enough, we can get out of this
672             // inner loop and move onto the next "iit".  This is b/c of the
673             // hierarchical sorting by obj0.
674             if(obj0Dist > dists[0]) break;
675 
676             // prepare to store whether or not jit is too close.
677             bool tooClose = true;
678 
679             // We need to see if the distances are all too small.  If any are
680             // larger than the cutoff, then jit is far enough away.
681             for(size_t of=1; of<nof; ++of)
682                 if(this->ComputeObjectiveDistance(id, jd, of) > dists[of])
683                 { tooClose = false; break; }
684 
685             // If it is too close, we mark it as such.  Otherwise we move on.
686             if(tooClose)
687             {
688                 ++ncAfter;
689                 ncm.AddToValue(jd, 1);
690             }
691         }
692 
693         ncm.AddToValue(id, ncAfter);
694     }
695 
696     ncm.ResumeStatistics(true);
697     return ncm;
698 }
699 
700 
701 
702 
703 
704 
705 /*
706 ================================================================================
707 Structors
708 ================================================================================
709 */
710 
711 
712 
MaxDesignsNichePressureApplicator(GeneticAlgorithm & algorithm)713 MaxDesignsNichePressureApplicator::MaxDesignsNichePressureApplicator(
714     GeneticAlgorithm& algorithm
715     ) :
716         GeneticAlgorithmNichePressureApplicator(algorithm),
717         _maxDesigns(DEFAULT_MAX_DESIGNS)
718 {
719     EDDY_FUNC_DEBUGSCOPE
720 }
721 
MaxDesignsNichePressureApplicator(const MaxDesignsNichePressureApplicator & copy)722 MaxDesignsNichePressureApplicator::MaxDesignsNichePressureApplicator(
723     const MaxDesignsNichePressureApplicator& copy
724     ) :
725         GeneticAlgorithmNichePressureApplicator(copy),
726         _maxDesigns(copy._maxDesigns)
727 {
728     EDDY_FUNC_DEBUGSCOPE
729 }
730 
MaxDesignsNichePressureApplicator(const MaxDesignsNichePressureApplicator & copy,GeneticAlgorithm & algorithm)731 MaxDesignsNichePressureApplicator::MaxDesignsNichePressureApplicator(
732     const MaxDesignsNichePressureApplicator& copy,
733     GeneticAlgorithm& algorithm
734     ) :
735         GeneticAlgorithmNichePressureApplicator(copy, algorithm),
736         _maxDesigns(copy._maxDesigns)
737 {
738     EDDY_FUNC_DEBUGSCOPE
739 }
740 
741 
742 
743 
744 
745 
746 /*
747 ================================================================================
748 End Namespace
749 ================================================================================
750 */
751     } // namespace Algorithms
752 } // namespace JEGA
753 
754