1 /*
2 ================================================================================
3     PROJECT:
4 
5         John Eddy's Genetic Algorithms (JEGA)
6 
7     CONTENTS:
8 
9         Implementation of class GeneticAlgorithm.
10 
11     NOTES:
12 
13         See notes of GeneticAlgorithm.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         1.0.0
30 
31     CHANGES:
32 
33         Thu May 15 08:25:23 2003 - 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 GeneticAlgorithm class.
48  */
49 
50 
51 /*
52 ================================================================================
53 Includes
54 ================================================================================
55 */
56 // JEGAConfig.hpp should be the first include in all JEGA files.
57 #include <../Utilities/include/JEGAConfig.hpp>
58 
59 #include <ctime>
60 #include <cfloat>
61 #include <fstream>
62 #include <FitnessRecord.hpp>
63 #include <GeneticAlgorithm.hpp>
64 #include <GeneticAlgorithmMutator.hpp>
65 #include <GeneticAlgorithmCrosser.hpp>
66 #include <GeneticAlgorithmMainLoop.hpp>
67 #include <GeneticAlgorithmSelector.hpp>
68 #include <GeneticAlgorithmConverger.hpp>
69 #include <GeneticAlgorithmEvaluator.hpp>
70 #include <GeneticAlgorithmInitializer.hpp>
71 #include <../Utilities/include/Logging.hpp>
72 #include <GeneticAlgorithmFitnessAssessor.hpp>
73 #include <PostProcessors/NullPostProcessor.hpp>
74 #include <utilities/include/EDDY_DebugScope.hpp>
75 #include <../Utilities/include/LRUDesignCache.hpp>
76 #include <../Utilities/include/DesignGroupVector.hpp>
77 #include <../Utilities/include/ParameterExtractor.hpp>
78 #include <../Utilities/include/DesignVariableInfo.hpp>
79 #include <GeneticAlgorithmNichePressureApplicator.hpp>
80 
81 
82 /*
83 ================================================================================
84 Namespace Using Directives
85 ================================================================================
86 */
87 using namespace std;
88 using namespace JEGA::Logging;
89 using namespace JEGA::Utilities;
90 
91 
92 
93 
94 
95 
96 
97 /*
98 ================================================================================
99 Begin Namespace
100 ================================================================================
101 */
102 namespace JEGA {
103     namespace Algorithms {
104 
105 
106 
107 /*
108 ================================================================================
109 File Scope Helper Functions
110 ================================================================================
111 */
112 /// Creates a string from the argument \a val using an ostringstream.
113 /**
114  * \param val The value of type T to convert to a string.
115  * \return The string representation of \a val created using an ostringstream.
116  */
117 template <typename T>
118 string
asstring(const T & val)119 asstring(
120     const T& val
121     )
122 {
123     EDDY_FUNC_DEBUGSCOPE
124     ostringstream ostr;
125     ostr << val;
126     return ostr.str();
127 }
128 
129 /**
130  * \brief Replaces all occurrences of some search string within a source string
131  *        with a supplied replacement string.
132  *
133  * \param of The string to search for.
134  * \param in The string in which to search.
135  * \param with The string with which to replace all occurrences of \a of in
136  *             \a in.
137  */
138 string
ReplaceAllOccurances(const string & of,string in,const string & with)139 ReplaceAllOccurances(
140     const string& of,
141     string in,
142     const string& with
143     )
144 {
145     EDDY_FUNC_DEBUGSCOPE
146 
147     string::size_type cpos = in.find(of);
148 
149     while(cpos != string::npos)
150     {
151         in.replace(cpos, of.size(), with);
152         cpos = in.find(of, cpos + with.size());
153     }
154 
155     return in;
156 }
157 
158 
159 
160 /*
161 ================================================================================
162 Private Template Method Implementations
163 ================================================================================
164 */
165 
166 template<typename Op_T>
167 bool
SetOperator(Op_T * op,Op_T & (GeneticAlgorithmOperatorSet::* getFunc)(),void (GeneticAlgorithmOperatorSet::* setFunc)(Op_T * op),bool groupHasOp,const std::string & JEGA_LOGGING_IF_ON (opType))168 GeneticAlgorithm::SetOperator(
169     Op_T* op,
170     Op_T& (GeneticAlgorithmOperatorSet::*getFunc)(), // Get
171     void (GeneticAlgorithmOperatorSet::*setFunc)(Op_T* op),
172     bool groupHasOp,
173     const std::string& JEGA_LOGGING_IF_ON(opType)
174     )
175 {
176     EDDY_FUNC_DEBUGSCOPE
177 
178     // See if the current group has the operator.  If it does, we can go ahead
179     // and use the supplied operator without any further considerations.
180     if(groupHasOp)
181     {
182         (this->GetOperatorSet().*setFunc)(op);
183         return true;
184     }
185 
186     // if it doesn't, we have to see if we can find a group that does.
187     // Begin by storing the current converger.
188     Op_T& current = (this->GetOperatorSet().*getFunc)();
189 
190     // now put the new converger in the set so we can match the it.
191     (this->GetOperatorSet().*setFunc)(op);
192 
193     const GeneticAlgorithmOperatorGroup* match =
194         this->MatchGroup(this->GetOperatorSet());
195 
196     // now, warn if we had no success matching a group.
197     if(match == 0x0)
198     {
199         JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
200             "Cannot set " + opType + " to " + op->GetName() +
201             ".  It is incompatible with the other existing operators "
202             "according to the known groups.  Retaining current " + opType +
203             " of " + current.GetName())
204             )
205         (this->GetOperatorSet().*setFunc)(&current);
206         return false;
207     }
208 
209     // we matched a group.  Adopt the new group and warn about it.
210     JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
211         this->GetName() + ": Matched the modified set to group " +
212         match->GetName() + " in response to a set " + opType + " call."))
213 
214     this->SetOperatorGroup(*match);
215 
216     return true;
217 }
218 
219 
220 
221 /*
222 ================================================================================
223 Static Member Data Definitions
224 ================================================================================
225 */
226 eddy::utilities::uint64_t GeneticAlgorithm::_instanceCt = 0;
227 
228 
229 
230 
231 
232 
233 
234 /*
235 ================================================================================
236 Mutators
237 ================================================================================
238 */
239 
240 void
SetCurrentFitnesses(const FitnessRecord * ftns)241 GeneticAlgorithm::SetCurrentFitnesses(
242     const FitnessRecord* ftns
243     )
244 {
245     EDDY_FUNC_DEBUGSCOPE
246     this->_lastFtns.reset(ftns);
247 }
248 
249 void
SetName(const std::string & name)250 GeneticAlgorithm::SetName(
251     const std::string& name
252     )
253 {
254     EDDY_FUNC_DEBUGSCOPE
255 
256     if(name.empty())
257     {
258         if(this->_name.empty())
259         {
260             this->_name = GetDefaultName();
261             JEGALOG_II(this->GetLogger(), lquiet(), this,
262                 text_entry(lquiet(), this->_name + ": Empty name supplied to "
263                     "unnamed GA.  Using default name of " + this->_name + "."
264                     )
265                 )
266         }
267         else
268         {
269             JEGALOG_II(this->GetLogger(), lquiet(), this,
270                 text_entry(lquiet(), this->_name + ": Attempt to rename GA "
271                     "from " + this->_name + " to an empty string failed.  "
272                     "Keeping the existing name"
273                     )
274                 )
275         }
276     }
277     else this->_name = name;
278 
279     JEGALOG_II(this->GetLogger(), lverbose(), this,
280         text_entry(
281             lverbose(), this->_name + ": The name of this GA is now " +
282             this->_name
283             )
284         )
285 }
286 
287 void
SetFinalDataFilename(const std::string & name)288 GeneticAlgorithm::SetFinalDataFilename(
289     const std::string& name
290     )
291 {
292     EDDY_FUNC_DEBUGSCOPE
293 
294     if(name.empty())
295     {
296         if(this->_finalDataFile.empty())
297         {
298             this->_finalDataFile = "finaldata#.dat";
299             JEGALOG_II(this->GetLogger(), lquiet(), this,
300                 text_entry(lquiet(), this->_name + ": Empty name supplied for "
301                     "final data filename.  Using default name of " +
302                     this->_finalDataFile + "."
303                     )
304                 )
305         }
306     }
307     else this->_finalDataFile = name;
308 
309     this->_finalDataFile.assign(
310         ReplaceAllOccurances(
311             "#", this->_finalDataFile, asstring(this->_instanceNum)
312             )
313         );
314 
315     JEGALOG_II(this->GetLogger(), lverbose(), this,
316         text_entry(lverbose(), this->GetName() + ": The name of the file to "
317             "which final data will be written is now " + this->_finalDataFile)
318         )
319 }
320 
321 void
SetPrintFinalData(bool print)322 GeneticAlgorithm::SetPrintFinalData(
323     bool print
324     )
325 {
326     EDDY_FUNC_DEBUGSCOPE
327 
328     this->_printFinalData = print;
329 
330     JEGALOG_II(this->GetLogger(), lverbose(), this,
331         ostream_entry(lverbose(), this->GetName() +
332             ": The print final data flag is now set to ")
333             << this->_printFinalData
334         )
335 }
336 
337 void
SetDataDirectory(const std::string & dir)338 GeneticAlgorithm::SetDataDirectory(
339     const std::string& dir
340     )
341 {
342     EDDY_FUNC_DEBUGSCOPE
343 
344     this->_dataDir = dir;
345 
346     JEGALOG_II(this->GetLogger(), lverbose(), this,
347         ostream_entry(lverbose(), this->GetName() +
348             ": The data directory is now set to ")
349             << this->_dataDir
350         )
351 }
352 
353 void
SetPrintDiscards(bool print)354 GeneticAlgorithm::SetPrintDiscards(
355     bool print
356     )
357 {
358     EDDY_FUNC_DEBUGSCOPE
359 
360     this->_printDiscards = print;
361 
362     JEGALOG_II(this->GetLogger(), lverbose(), this,
363         ostream_entry(lverbose(), this->GetName() +
364             ": The print discards flag is now set to ")
365             << this->_printDiscards
366         )
367 }
368 
369 
370 void
SetPrintEachPopulation(bool print)371 GeneticAlgorithm::SetPrintEachPopulation(
372     bool print
373     )
374 {
375     EDDY_FUNC_DEBUGSCOPE
376 
377     this->_printPopEachGen = print;
378 
379     JEGALOG_II(this->GetLogger(), lverbose(), this,
380         ostream_entry(lverbose(), this->GetName() +
381             ": The print each population flag is now set to ")
382             << this->_printPopEachGen
383         )
384 }
385 
386 
387 
388 
389 
390 
391 /*
392 ================================================================================
393 Accessors
394 ================================================================================
395 */
396 const FitnessRecord&
GetCurrentFitnesses()397 GeneticAlgorithm::GetCurrentFitnesses(
398     )
399 {
400     EDDY_FUNC_DEBUGSCOPE
401     if(this->_lastFtns.get() == 0x0)
402     {
403         DesignGroupVector dgv(2, &this->_pop);
404         dgv[1] = &this->_cldrn;
405         this->SetCurrentFitnesses(
406             this->GetFitnessAssessor().AssessFitness(dgv)
407             );
408     }
409     return *this->_lastFtns;
410 }
411 
412 
413 
414 
415 
416 
417 
418 /*
419 ================================================================================
420 Public Methods
421 ================================================================================
422 */
423 
424 bool
ExtractParameters(const ParameterDatabase & pdb)425 GeneticAlgorithm::ExtractParameters(
426     const ParameterDatabase& pdb
427     )
428 {
429     EDDY_FUNC_DEBUGSCOPE
430     bool ret = this->PollForParameters(pdb);
431     this->ExtractOperatorParameters(this->GetConverger(), pdb);
432     this->ExtractOperatorParameters(this->GetCrosser(), pdb);
433     this->ExtractOperatorParameters(this->GetEvaluator(), pdb);
434     this->ExtractOperatorParameters(this->GetFitnessAssessor(), pdb);
435     this->ExtractOperatorParameters(this->GetInitializer(), pdb);
436     this->ExtractOperatorParameters(this->GetNichePressureApplicator(), pdb);
437     this->ExtractOperatorParameters(this->GetMainLoop(), pdb);
438     this->ExtractOperatorParameters(this->GetMutator(), pdb);
439     this->ExtractOperatorParameters(this->GetSelector(), pdb);
440     this->ExtractOperatorParameters(this->GetPostProcessor(), pdb);
441     return ret;
442 }
443 
444 
445 eddy::utilities::uint64_t
GetNumberEvaluations() const446 GeneticAlgorithm::GetNumberEvaluations(
447     ) const
448 {
449     EDDY_FUNC_DEBUGSCOPE
450     return this->GetEvaluator().GetNumberEvaluations();
451 }
452 
453 eddy::utilities::uint64_t
GetGenerationNumber() const454 GeneticAlgorithm::GetGenerationNumber(
455     ) const
456 {
457     EDDY_FUNC_DEBUGSCOPE
458     return this->GetMainLoop().GetCurrentGeneration();
459 }
460 
461 bool
SetOperatorGroup(const GeneticAlgorithmOperatorGroup & to)462 GeneticAlgorithm::SetOperatorGroup(
463     const GeneticAlgorithmOperatorGroup& to
464     )
465 {
466     EDDY_FUNC_DEBUGSCOPE
467 
468     GeneticAlgorithmOperatorGroupRegistry& ogReg =
469         this->GetOperatorGroupRegistry();
470 
471     bool ret = ogReg.is_registered(to.GetName());
472     if(ret)
473     {
474         if(!to.ContainsSet(this->GetOperatorSet()))
475         {
476             JEGALOG_II(this->GetLogger(), ldebug(), this,
477                 text_entry(ldebug(), this->GetName() + ": Current operator set "
478                     "is not compatible with new operator group \"" +
479                     to.GetName() + "\".  Clearing the set and "
480                     "adopting the group.")
481                 )
482             this->GetOperatorSet().Clear();
483         }
484         this->_opGroup = &to;
485     }
486     return ret;
487 }
488 
489 #define SET_OP_METHOD(optype) \
490     bool \
491     GeneticAlgorithm::Set##optype( \
492         GeneticAlgorithm##optype* to \
493         ) \
494     { \
495         EDDY_FUNC_DEBUGSCOPE \
496         return this->SetOperator<GeneticAlgorithm##optype>( \
497                 to, \
498                 &GeneticAlgorithmOperatorSet::Get##optype, \
499                 &GeneticAlgorithmOperatorSet::Set##optype, \
500                 this->GetOperatorGroup().Has##optype(*to), \
501                 #optype \
502                 ); \
503     }
504 
505 SET_OP_METHOD(Converger)
SET_OP_METHOD(Crosser)506 SET_OP_METHOD(Crosser)
507 SET_OP_METHOD(Evaluator)
508 SET_OP_METHOD(FitnessAssessor)
509 SET_OP_METHOD(Initializer)
510 SET_OP_METHOD(MainLoop)
511 SET_OP_METHOD(Mutator)
512 SET_OP_METHOD(Selector)
513 SET_OP_METHOD(PostProcessor)
514 SET_OP_METHOD(NichePressureApplicator)
515 
516 bool
517 GeneticAlgorithm::SetOperatorSet(
518     const GeneticAlgorithmOperatorSet& to
519     )
520 {
521     EDDY_FUNC_DEBUGSCOPE
522 
523     const GeneticAlgorithmOperatorGroup* gp = this->MatchGroup(to);
524 
525     // first, warn if we had no success matching a group.
526     if(gp == 0x0)
527     {
528         JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
529             this->GetName() + ": Attempt to use an operator set which cannot "
530             "be matched to a group failed.  Retaining current operator set."))
531         return false;
532     }
533 
534     // start by accepting our new set b/c we have success.
535     this->_opSet->operator =(to);
536 
537     // we matched a group.  now we must see if it is our current group.
538     // if it is, fine.  If not, adopt the new group and warn about it.
539     if(gp != this->_opGroup)
540     {
541         JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
542             this->GetName() + ": Matched new set to a group that is not the "
543             "current group.  Adopting the new group."))
544         this->SetOperatorGroup(*gp);
545     }
546 
547     // return our success
548     return true;
549 }
550 
551 Design*
GetNewDesign() const552 GeneticAlgorithm::GetNewDesign(
553     ) const
554 {
555     EDDY_FUNC_DEBUGSCOPE
556 
557     Design* ret = this->_target.GetNewDesign();
558     EDDY_ASSERT(ret != 0x0);
559     return ret;
560 }
561 
562 Design*
GetNewDesign(const Design & copy) const563 GeneticAlgorithm::GetNewDesign(
564     const Design& copy
565     ) const
566 {
567     EDDY_FUNC_DEBUGSCOPE
568 
569     Design* ret = this->_target.GetNewDesign(copy);
570     EDDY_ASSERT(ret != 0x0);
571     return ret;
572 }
573 
574 size_t
ValidateVariableValues(const DesignGroupVector & groups) const575 GeneticAlgorithm::ValidateVariableValues(
576     const DesignGroupVector& groups
577     ) const
578 {
579     EDDY_FUNC_DEBUGSCOPE
580 
581     size_t numIll = 0;
582 
583     // iterate over the "groups" and call the overload
584     for(size_t i=0; i<groups.size(); ++i)
585         numIll += this->ValidateVariableValues(*groups[i]);
586 
587     return numIll;
588 }
589 
590 size_t
LogIllconditionedDesigns(const JEGA::Utilities::DesignGroup & from) const591 GeneticAlgorithm::LogIllconditionedDesigns(
592     const JEGA::Utilities::DesignGroup& from
593     ) const
594 {
595     size_t nLogged = 0;
596 
597 #if defined(JEGA_LOGGING_ON)
598     if(this->GetLogger().Gate().will_log(
599         this->GetLogger().Gate().get_default_level(), lquiet()
600         ))
601     {
602         ostream_entry ent(lquiet(), this->GetName());
603 
604         ent << ": Design Variable Values for Ill-conditioned "
605                "Designs:\n";
606 
607         for(
608             DesignDVSortSet::const_iterator dvit(from.BeginDV());
609             dvit!=from.EndDV(); ++dvit
610             )
611         {
612             const Design* des = *dvit;
613             if(des->IsIllconditioned())
614             {
615                 ent << des->GetVariableValue(0);
616                 for(size_t i=1; i<des->GetNDV(); ++i)
617                     ent << ' ' << des->GetVariableValue(i);
618                 ent << '\n';
619                 ++nLogged;
620             }
621         }
622         this->GetLogger().Gate().simple_log(lquiet(), ent);
623     }
624 #endif
625 
626     return nLogged;
627 }
628 
629 size_t
ValidateVariableValues(DesignGroup & group) const630 GeneticAlgorithm::ValidateVariableValues(
631     DesignGroup& group
632     ) const
633 {
634     EDDY_FUNC_DEBUGSCOPE
635 
636     // get the design variable info objects.
637     const DesignVariableInfoVector& dvInfos =
638         this->_target.GetDesignVariableInfos();
639 
640     size_t ndv = dvInfos.size();
641 
642     // keep a temporary list of the altered designs.
643     vector<Design*> changedDesigns;
644     changedDesigns.reserve(group.SizeDV());
645 
646     size_t numIll = 0;
647 
648     // go through the Designs and then the infos
649     const DesignDVSortSet::const_iterator de(group.EndDV());
650 
651     for(DesignDVSortSet::iterator dit(group.BeginDV()); dit!=de;)
652     {
653         // keep track of whether or not the design gets changed.
654         bool changed = false;
655 
656         Design* des = *dit;
657 
658         for(size_t dv = 0; dv<ndv; ++dv)
659         {
660             var_rep_t rep = des->GetVariableRep(dv);
661 
662             const DesignVariableInfo& dvi = *dvInfos[dv];
663 
664             if(dvi.IsValidRep(rep)) continue;
665 
666             // get a corrected variable value.
667             var_rep_t corrected = dvi.IsRepInBounds(rep) ?
668                 dvi.GetNearestValidRep(rep) : dvi.GetRandomRep();
669 
670             // a return of -limits::max means that the rep could
671             // not be corrected.
672 			if(corrected == -std::numeric_limits<var_rep_t>::max())
673             {
674                 JEGALOG_II(this->GetLogger(), lquiet(), this,
675                     ostream_entry(lquiet(), this->GetName() + ": "
676                         "Non-correctable invalid variable rep of ")
677                         << rep << " found for variable " << dvi.GetLabel()
678                     )
679                 des->SetIllconditioned(true);
680                 ++numIll;
681                 break;
682             }
683             // otherwise, install the corrected value and
684             // set the flag so that we know to remove and
685             // re-insert the Design.
686             else if(corrected != rep)
687             {
688                 JEGALOG_II(this->GetLogger(), lquiet(), this,
689                     ostream_entry(
690                         lquiet(), this->GetName() + ": Invalid variable rep of "
691                         )
692                         << rep << " found for variable " << dvi.GetLabel()
693                         << ".  Corrected to " << corrected << " (value="
694                         << dvi.GetValueOf(corrected) << ")."
695                     )
696                 des->SetVariableRep(dv, corrected);
697                 des->RemoveAsClone();
698                 changed = true;
699             }
700         }
701 
702         // if the design was changed, we have to remove it temporarily.
703         if(changed)
704         {
705             changedDesigns.push_back(des);
706             dit = group.EraseRetDV(dit);
707         }
708         else ++dit;
709     }
710 
711     // now put back all the changed Designs.
712     for(size_t i=0; i<changedDesigns.size(); ++i)
713     {
714         changedDesigns[i]->SetEvaluated(false);
715         changedDesigns[i]->SetIllconditioned(false);
716         group.Insert(changedDesigns[i]);
717     }
718 
719     // this will verify that all variables are now valid.
720 #if defined(JEGA_LOGGING_ON) && defined(JEGA_OPTION_DEBUG)
721 
722     for(DesignDVSortSet::iterator dit(group.BeginDV()); dit!=de; ++dit)
723     {
724         for(DesignVariableInfoVector::const_iterator dvit(dvInfos.begin());
725             dvit != dvInfos.end(); ++dvit)
726         {
727             JEGAIFLOG_CF_F(!(*dit)->IsIllconditioned() &&
728                         !(*dvit)->IsValidRep(
729                             (*dvit)->WhichRep(**dit)
730                             ),
731                         this->GetLogger(),
732                         ostream_entry(lfatal(),
733                             "Invalid variable representation found in "
734                             "non-ill-conditioned design after variable "
735                             "correction operation.  Variable ")
736                                 << (*dvit)->GetLabel() << ", Representation "
737                                 << (*dvit)->WhichRep(**dit)
738                         )
739         }
740     }
741 #endif
742 
743     return numIll;
744 }
745 
746 double
GetElapsedTime() const747 GeneticAlgorithm::GetElapsedTime(
748     ) const
749 {
750     EDDY_FUNC_DEBUGSCOPE
751     return double(clock() - this->_startTime) / CLOCKS_PER_SEC;
752 }
753 
754 /*
755 ================================================================================
756 Subclass Visible Methods
757 ================================================================================
758 */
759 
760 string
GetDefaultName() const761 GeneticAlgorithm::GetDefaultName(
762     ) const
763 {
764     EDDY_FUNC_DEBUGSCOPE
765 
766     ostringstream ostr;
767     ostr << this->GetAlgorithmTypeName() << " #" << this->GetInstanceNumber();
768     return ostr.str();
769 }
770 
771 void
ExtractOperatorParameters(GeneticAlgorithmOperator & op,const ParameterDatabase & pdb)772 GeneticAlgorithm::ExtractOperatorParameters(
773     GeneticAlgorithmOperator& op,
774     const ParameterDatabase& pdb
775     )
776 {
777     EDDY_FUNC_DEBUGSCOPE
778     JEGAIFLOG_CF_II_F(!op.ExtractParameters(pdb), this->GetLogger(), this,
779         text_entry(lfatal(),
780             this->GetName() + ": Failed to retrieve the parameters for \""
781             ) << op.GetName() << "\"."
782         );
783 }
784 
785 const GeneticAlgorithmOperatorGroupRegistry&
GetOperatorGroupRegistry() const786 GeneticAlgorithm::GetOperatorGroupRegistry(
787     ) const
788 {
789     EDDY_FUNC_DEBUGSCOPE
790     return const_cast<GeneticAlgorithm*>(this)->GetOperatorGroupRegistry_FWD();
791 }
792 
793 bool
WritePopulationToFile() const794 GeneticAlgorithm::WritePopulationToFile(
795     ) const
796 {
797     EDDY_FUNC_DEBUGSCOPE
798 
799     ostringstream fname;
800     fname << "population_" << this->GetGenerationNumber() << ".dat";
801     return this->WritePopulationToFile(
802         this->GetDataDirectory() + "/" + fname.str()
803         );
804 }
805 
806 bool
WritePopulationToFile(const std::string & fname) const807 GeneticAlgorithm::WritePopulationToFile(
808     const std::string& fname
809     ) const
810 {
811     EDDY_FUNC_DEBUGSCOPE
812     return this->WriteGroupToFile(this->_pop.GetOFSortContainer(), fname);
813 }
814 
815 bool
WriteGroupToFile(const JEGA::Utilities::DesignDVSortSet & group,const std::string & fname) const816 GeneticAlgorithm::WriteGroupToFile(
817     const JEGA::Utilities::DesignDVSortSet& group,
818     const std::string& fname
819     ) const
820 {
821     EDDY_FUNC_DEBUGSCOPE
822 
823     ofstream ofile(fname.c_str());
824 
825     if(!ofile.is_open())
826     {
827         JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
828             this->GetName() + ": Unable to open file " + fname +
829             " for writing design group.  No data written.")
830              )
831         return false;
832     }
833 
834     group.stream_out(ofile);
835     ofile.close();
836 
837     JEGALOG_II(this->GetLogger(), lverbose(), this,
838         text_entry(lverbose(),
839             this->GetName() + ": Wrote designs file \"" + fname + "\".")
840         )
841 
842     return true;
843 }
844 
845 bool
WriteGroupToFile(const JEGA::Utilities::DesignOFSortSet & group,const std::string & fname) const846 GeneticAlgorithm::WriteGroupToFile(
847     const JEGA::Utilities::DesignOFSortSet& group,
848     const std::string& fname
849     ) const
850 {
851     EDDY_FUNC_DEBUGSCOPE
852 
853     ofstream ofile(fname.c_str());
854 
855     if(!ofile.is_open())
856     {
857         JEGALOG_II(this->GetLogger(), lquiet(), this, text_entry(lquiet(),
858             this->GetName() + ": Unable to open file " + fname +
859             " for writing design group.  No data written.")
860              )
861         return false;
862     }
863 
864     group.stream_out(ofile);
865     ofile.close();
866 
867     JEGALOG_II(this->GetLogger(), lverbose(), this,
868         text_entry(lverbose(),
869             this->GetName() + ": Wrote designs file \"" + fname + "\".")
870         )
871 
872     return true;
873 }
874 
875 
876 
877 
878 
879 /*
880 ================================================================================
881 Subclass Overridable Methods
882 ================================================================================
883 */
884 bool
PollForParameters(const JEGA::Utilities::ParameterDatabase & db)885 GeneticAlgorithm::PollForParameters(
886     const JEGA::Utilities::ParameterDatabase& db
887     )
888 {
889     EDDY_FUNC_DEBUGSCOPE
890 
891     string tname;
892     bool success = ParameterExtractor::GetStringFromDB(
893         db, "method.jega.algorithm_name", tname
894         );
895 
896     // If we did not find the name, warn about it and use the default
897     // value.  Note that if !success, then tname is unaltered
898     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
899         text_entry(lverbose(), this->GetName() + ": The algorithm name string "
900             "was not found in the parameter database.  A default name will "
901             "be created.")
902         )
903 
904     SetName(tname);
905 
906     bool tmp = false;
907 
908     // Begin by extracting the population printing flag.
909     success = ParameterExtractor::GetBooleanFromDB(
910         db, "method.print_each_pop", tmp
911         );
912 
913     if(success) this->SetPrintEachPopulation(tmp);
914 
915     // If we did not find the flag, warn about it and use the default
916     // value.  Note that if !success, then _printPopEachGen is unaltered
917     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
918         ostream_entry(lverbose(), this->GetName() + ": The population printing "
919             "flag was not found in the parameter database.  Using the current "
920             "value of ") << (this->_printPopEachGen ? "true." : "false.")
921         )
922 
923     success = ParameterExtractor::GetBooleanFromDB(
924         db, "method.print_final_data", tmp
925         );
926 
927     if(success) this->SetPrintFinalData(tmp);
928 
929     // If we did not find the flag, warn about it and use the default
930     // value.  Note that if !success, then _printFinalData is unaltered
931     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
932         ostream_entry(lverbose(), this->GetName() + ": The final data printing "
933             "flag was not found in the parameter database.  Using the current "
934             "value of ") << (this->_printFinalData ? "true." : "false.")
935         )
936 
937     success = ParameterExtractor::GetBooleanFromDB(
938         db, "method.print_discards", tmp
939         );
940 
941     if(success) this->SetPrintDiscards(tmp);
942 
943     // If we did not find the flag, warn about it and use the default
944     // value.  Note that if !success, then _printDiscards is unaltered
945     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
946         ostream_entry(lverbose(), this->GetName() + ": The discards printing "
947             "flag was not found in the parameter database.  Using the current "
948             "value of ") << (this->_printDiscards ? "true." : "false.")
949         )
950 
951     success = ParameterExtractor::GetStringFromDB(
952         db, "method.jega.final_data_filename", tname
953         );
954 
955     if(success) this->SetFinalDataFilename(tname);
956 
957     // If we did not find the name, warn about it and use the default
958     // value.  Note that if !success, then tname is unaltered
959     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
960         text_entry(lverbose(), this->GetName() + ": The final data "
961             "filename/pattern was not found in the parameter database.  Using "
962             "the current pattern of " + this->_finalDataFile + ".")
963         )
964 
965     success = ParameterExtractor::GetStringFromDB(
966         db, "method.jega.data_directory", tname
967         );
968 
969     if(success) this->SetDataDirectory(tname);
970 
971     // If we did not find the data directory, warn about it and use the default
972     // value.  Note that if !success, then tname is unaltered
973     JEGAIFLOG_CF_II(!success, this->GetLogger(), lverbose(), this,
974         text_entry(lverbose(), this->GetName() + ": The data directory "
975             "was not found in the parameter database.  Using the current "
976             "value of " + this->_dataDir + ".")
977         )
978 
979     return success;
980 }
981 
982 
983 void
DoCrossover()984 GeneticAlgorithm::DoCrossover(
985     )
986 {
987     EDDY_FUNC_DEBUGSCOPE
988 
989     // it should be unnecessary to do this but we will anyway.
990     this->_cldrn.FlushAll();
991 
992     // all is set to use the crossover operator.
993     // cross members of _pop and put the results in _cldrn.
994     this->GetCrosser().Crossover(this->_pop, this->_cldrn);
995 }
996 
997 const FitnessRecord*
DoFitnessAssessment()998 GeneticAlgorithm::DoFitnessAssessment(
999     )
1000 {
1001     EDDY_FUNC_DEBUGSCOPE
1002 
1003     // create a vector of groups to be simultaneously considered
1004     // for fitness assessment.
1005     DesignGroupVector gpvec(2, &this->_pop);
1006     gpvec[1] = &this->_cldrn;
1007 
1008     // now use the fitness assessor operator on the collected groups.
1009     return this->GetFitnessAssessor().AssessFitness(gpvec);
1010 }
1011 
1012 void
DoMutation()1013 GeneticAlgorithm::DoMutation(
1014     )
1015 {
1016     EDDY_FUNC_DEBUGSCOPE
1017 
1018     // Everything should be all set to go right into the mutation operator.
1019     this->GetMutator().Mutate(this->_pop, this->_cldrn);
1020 }
1021 
1022 void
DoPreSelection()1023 GeneticAlgorithm::DoPreSelection(
1024     )
1025 {
1026     EDDY_FUNC_DEBUGSCOPE
1027     this->GetNichePressureApplicator().PreSelection(this->_pop);
1028 }
1029 
1030 void
AbsorbEvaluatorInjections(bool allowDuplicates)1031 GeneticAlgorithm::AbsorbEvaluatorInjections(
1032     bool allowDuplicates
1033     )
1034 {
1035     EDDY_FUNC_DEBUGSCOPE
1036 
1037     // Merge in any designs injected via the evaluator.  They get merged
1038     // into the children and must already be evaluated.
1039     GeneticAlgorithmEvaluator& evaler = this->GetEvaluator();
1040     if(evaler.GetInjections().empty()) return;
1041 
1042     evaler.MergeInjectedDesigns(this->_cldrn, false, false, allowDuplicates);
1043 
1044     // Now verify that there are no children that duplicate population members
1045     // if disallowing duplicates.
1046     if(!allowDuplicates)
1047     {
1048         std::size_t nrem =
1049             this->GetPopulation().GetDVSortContainer().test_for_clones(
1050                 this->_cldrn.GetDVSortContainer()
1051                 );
1052 
1053         if(nrem > 0)
1054         {
1055             nrem = this->_cldrn.FlushCloneDesigns();
1056 
1057             JEGAIFLOG_CF_II(nrem > 0, this->GetLogger(),
1058                 lverbose(), this,
1059                 ostream_entry(lverbose(), this->GetName() + ": flushed ")
1060                     << nrem << " designs from the children set (possibly "
1061                     "injections) that duplicated existing population members."
1062                 )
1063         }
1064     }
1065 
1066     // now that we've absorbed them all, dispose of them in the evaluator.
1067     evaler.ClearInjectedDesigns();
1068 }
1069 
1070 void
DoSelection(const FitnessRecord & fitnesses)1071 GeneticAlgorithm::DoSelection(
1072     const FitnessRecord& fitnesses
1073     )
1074 {
1075     EDDY_FUNC_DEBUGSCOPE
1076 
1077     // create a vector of all groups to be selected from.
1078     DesignGroupVector gpvec(2, &this->_pop);
1079     gpvec[1] = &this->_cldrn;
1080 
1081     JEGA_LOGGING_IF_ON(const std::size_t iPopSize = this->_pop.GetSize());
1082     JEGA_LOGGING_IF_ON(const std::size_t iCldrnSize = this->_cldrn.GetSize());
1083 
1084     // prepare a group to put the results into.
1085     DesignGroup into(this->_target);
1086 
1087     // actually perform the selection
1088     this->GetSelector().Select(gpvec, into, this->_pop.GetSize(), fitnesses);
1089 
1090     // expel whatever is left in the Population and Children after indicating
1091     // what is gone and what remains.
1092     JEGALOG_II(this->GetLogger(), lverbose(), this,
1093         ostream_entry(lverbose(), this->GetName() + ": ")
1094             << this->_pop.GetSize() << " of " << iPopSize
1095             << " population members were not selected to continue.  "
1096             << this->_cldrn.GetSize() << " of " << iCldrnSize
1097             << " offspring were immediately rejected."
1098         )
1099 
1100     this->_pop.FlushAll();
1101     this->_cldrn.FlushAll();
1102 
1103     // set the new population to be the new group
1104     this->_pop = into;
1105 }
1106 
1107 void
ApplyNichePressure(JEGA::Utilities::DesignGroup & group,const FitnessRecord & fitnesses)1108 GeneticAlgorithm::ApplyNichePressure(
1109     JEGA::Utilities::DesignGroup& group,
1110     const FitnessRecord& fitnesses
1111     )
1112 {
1113     EDDY_FUNC_DEBUGSCOPE
1114     this->GetNichePressureApplicator().ApplyNichePressure(group, fitnesses);
1115 }
1116 
1117 void
InitializePopulation()1118 GeneticAlgorithm::InitializePopulation(
1119     )
1120 {
1121     EDDY_FUNC_DEBUGSCOPE
1122 
1123     // Everything should be all set to go right into the initialization
1124     // operator.
1125     this->GetInitializer().Initialize(this->_pop);
1126 }
1127 
1128 bool
DoEvaluation(DesignGroup & group)1129 GeneticAlgorithm::DoEvaluation(
1130     DesignGroup& group
1131     )
1132 {
1133     EDDY_FUNC_DEBUGSCOPE
1134 
1135     // Everything should be all set to go right into the evaluator operator.
1136     bool success = this->GetEvaluator().Evaluate(group);
1137 
1138     // now refresh the DesignOFSortSet of group so that it reflects
1139     // the fact that it's Designs should now be evaluated.
1140     group.SynchronizeOFAndDVContainers();
1141     return success;
1142 }
1143 
1144 bool
TestForConvergence(const FitnessRecord & fitnesses)1145 GeneticAlgorithm::TestForConvergence(
1146     const FitnessRecord& fitnesses
1147     )
1148 {
1149     EDDY_FUNC_DEBUGSCOPE
1150 
1151     // all should be set to use the convergence operator.
1152     // recall that the CheckConvergence operator returns
1153     // whether or not convergence has occurred.
1154     return this->GetConverger().CheckConvergence(this->_pop, fitnesses);
1155 }
1156 
1157 void
DoPostProcessing()1158 GeneticAlgorithm::DoPostProcessing(
1159     )
1160 {
1161     EDDY_FUNC_DEBUGSCOPE
1162     this->GetPostProcessor().PostProcess(this->_pop);
1163 }
1164 
1165 bool
AlgorithmInitialize()1166 GeneticAlgorithm::AlgorithmInitialize(
1167     )
1168 {
1169     EDDY_FUNC_DEBUGSCOPE
1170 
1171     this->_startTime = clock();
1172 
1173     // initialize the populations design variable values.
1174     this->InitializePopulation();
1175 
1176     if(this->GetInitializer().CanProduceInvalidVariableValues())
1177     {
1178         // verify the validity of each design variable of each Design.
1179         size_t numIll = this->ValidateVariableValues(this->_pop);
1180 
1181         // any designs that could not be evaluated must be removed.
1182         if(numIll > 0)
1183         {
1184             this->LogIllconditionedDesigns(this->_pop);
1185 
1186             JEGA_LOGGING_IF_ON(DesignDVSortSet::size_type nrem =)
1187                 this->_pop.FlushIllconditionedDesigns();
1188 
1189             JEGAIFLOG_CF_II(nrem > 0, this->GetLogger(), lquiet(), this,
1190                 ostream_entry(lquiet(), this->GetName() + ": flushed ") << nrem
1191                     << " designs from the initial population whose variables "
1192                        "could not be corrected."
1193                     )
1194         }
1195     }
1196 
1197     // check for clones in the initial population to avoid re-evaluation
1198     this->_pop.GetDVSortContainer().test_within_list_for_clones();
1199 
1200     // check for duplicates in the discarded designs to avoid re-evaluations.
1201     const LRUDesignCache& discards =
1202         this->GetDesignTarget().CheckoutDiscards();
1203     discards.test_for_clones(this->_pop.GetDVSortContainer());
1204     this->GetDesignTarget().CheckinDiscards();
1205 
1206     // perform evaluation.
1207     bool evald = this->DoEvaluation(this->_pop);
1208 
1209     JEGAIFLOG_CF_II(!evald, this->GetLogger(), lquiet(), this,
1210         text_entry(
1211             lquiet(), this->GetName() + ": Errors were encountered while "
1212             "evaluating the offspring designs"
1213             )
1214         )
1215 
1216     // any designs that could not be evaluated must be removed.
1217     if(!evald)
1218     {
1219         this->LogIllconditionedDesigns(this->_pop);
1220 
1221         JEGA_LOGGING_IF_ON(DesignDVSortSet::size_type nrem =)
1222             this->_pop.FlushIllconditionedDesigns();
1223 
1224         JEGAIFLOG_CF_II(nrem > 0, this->GetLogger(), lquiet(), this,
1225             ostream_entry(
1226                 lquiet(), this->GetName() + ": encountered and flushed "
1227                 )
1228                 << nrem
1229                 << " ill-conditioned designs after evaluation of the initial "
1230                    "population."
1231                 )
1232     }
1233 
1234     // load the designs into the objective function sorted list.
1235     this->_pop.SynchronizeOFAndDVContainers();
1236 
1237     // initialize the generation number to 0.
1238     this->GetMainLoop().SetCurrentGeneration(0);
1239 
1240     if(this->_printPopEachGen) this->WritePopulationToFile();
1241 
1242     this->_isInitialized = true;
1243 
1244     return true;
1245 }
1246 
1247 bool
AlgorithmProcess()1248 GeneticAlgorithm::AlgorithmProcess(
1249     )
1250 {
1251     EDDY_FUNC_DEBUGSCOPE
1252 
1253     // If this algorithm has already reported itself converged, don't do
1254     // anything.
1255     // Or, similarly, if we test it for convergence using the parameter-less
1256     // convergence method and it says it is converged, then do nothing.
1257     if(this->GetConverger().GetConverged() ||
1258        this->GetConverger().CheckConvergence())
1259         return false;
1260 
1261     const bool ret = this->GetMainLoop().RunGeneration();
1262 
1263     if(this->_printPopEachGen) this->WritePopulationToFile();
1264 
1265     JEGA_LOGGING_IF_ON(
1266         this->GetLogger().FlushStreams();
1267         if(&this->GetLogger() != &Logger::Global())
1268             Logger::Global().FlushStreams();
1269         )
1270 
1271     return ret;
1272 }
1273 
1274 bool
AlgorithmFinalize()1275 GeneticAlgorithm::AlgorithmFinalize(
1276     )
1277 {
1278     EDDY_FUNC_DEBUGSCOPE
1279 
1280     JEGA_LOGGING_IF_ON(std::size_t prevSize = this->_pop.GetSize();)
1281 
1282     // make sure that the children structure is empty.
1283     this->_cldrn.FlushAll();
1284     // prepare a return value.
1285     bool ret = true;
1286 
1287     // Finalize all the operators with the exception of the post processor
1288     // and the fitness assessor both of which will be needed below.
1289     ret &= this->GetConverger().Finalize();
1290     ret &= this->GetCrosser().Finalize();
1291     ret &= this->GetEvaluator().Finalize();
1292     ret &= this->GetInitializer().Finalize();
1293     ret &= this->GetMainLoop().Finalize();
1294     ret &= this->GetMutator().Finalize();
1295     ret &= this->GetNichePressureApplicator().Finalize();
1296     ret &= this->GetSelector().Finalize();
1297 
1298     // reclaim any optimal from the discards.
1299     this->ReclaimOptimal();
1300 
1301     JEGALOG_II(this->GetLogger(), lverbose(), this,
1302         ostream_entry(lquiet(), this->GetName() + ": Reclaimed ")
1303             << (this->_pop.GetSize() - prevSize) << " optimal designs that "
1304                "had been selected out."
1305         )
1306 
1307     // now flush out all non-optimal designs.
1308     this->FlushNonOptimal();
1309 
1310     // Now run the post-processor.
1311     this->DoPostProcessing();
1312 
1313     // now we can finalize our fitness assessor and post processor.
1314     ret &= this->GetFitnessAssessor().Finalize();
1315     ret &= this->GetPostProcessor().Finalize();
1316 
1317     JEGALOG_II(this->GetLogger(), lquiet(), this,
1318         ostream_entry(lquiet(), this->GetName() + ": Ran ")
1319             << this->GetGenerationNumber() << " total generations."
1320         )
1321 
1322     // let the user know how many final Designs are left
1323     JEGALOG_II(this->GetLogger(), lquiet(), this,
1324         ostream_entry(lquiet(), this->GetName() + ": Final population size = ")
1325             << this->_pop.GetSize()
1326         )
1327 
1328     // write out the final set of optimal designs to a tab delimited file.
1329     if(this->_printFinalData &&
1330        !this->WritePopulationToFile(
1331             this->GetDataDirectory() + "/" + this->_finalDataFile
1332         )) ret = false;
1333 
1334     // now write all other Designs considered to another tab delimited file.
1335     if(this->_printDiscards)
1336     {
1337         const LRUDesignCache& discards =
1338             this->GetDesignTarget().CheckoutDiscards();
1339         if(!this->WriteGroupToFile(
1340             discards.DVSortSet(),
1341             this->GetDataDirectory() + "/" + "discards.dat"
1342             )) ret = false;
1343         this->GetDesignTarget().CheckinDiscards();
1344     }
1345 
1346     this->_isFinalized = true;
1347 
1348     return ret;
1349 }
1350 
1351 const Design*
GetBestDesign()1352 GeneticAlgorithm::GetBestDesign(
1353     )
1354 {
1355     EDDY_FUNC_DEBUGSCOPE
1356 
1357     DesignGroupVector gps(1, &this->GetPopulation());
1358 
1359     DesignOFSortSet bests(this->GetSelector().SelectNBest(
1360         gps, 1, this->GetCurrentFitnesses()
1361         ));
1362 
1363     return bests.empty() ? 0x0 : *bests.begin();
1364 }
1365 
1366 /*
1367 ================================================================================
1368 Private Methods
1369 ================================================================================
1370 */
1371 const GeneticAlgorithmOperatorGroup*
MatchGroup(const GeneticAlgorithmOperatorSet & set) const1372 GeneticAlgorithm::MatchGroup(
1373     const GeneticAlgorithmOperatorSet& set
1374     ) const
1375 {
1376     EDDY_FUNC_DEBUGSCOPE
1377 
1378     // go through all the possible groups until one is found that matches.
1379     // when one is found, make it the new group and return true.
1380     // if none are found, return false.
1381     const GeneticAlgorithmOperatorGroupRegistry& gReg =
1382         GetOperatorGroupRegistry();
1383 
1384     GeneticAlgorithmOperatorGroupRegistry::const_iterator it(gReg.begin());
1385 
1386     for(; it!=gReg.end(); ++it)
1387     {
1388         const GeneticAlgorithmOperatorGroup& cgp = (*it).second();
1389 
1390         JEGALOG_II(this->GetLogger(), lverbose(), this,
1391             text_entry(
1392                 ldebug(), this->GetName() + " Matching Group: Trying \"" +
1393                 cgp.GetName() + "\"."
1394                 )
1395             )
1396 
1397         if(cgp.ContainsSet(set))
1398         {
1399             JEGALOG_II(this->GetLogger(), lverbose(), this,
1400                 text_entry(ldebug(),
1401                     this->GetName() + " Matching Group: \"" + cgp.GetName() +
1402                     "\" match succeeded.")
1403                 )
1404             return &cgp;
1405         }
1406     }
1407 
1408     return 0x0;
1409 }
1410 
1411 const GeneticAlgorithmOperatorGroupRegistry&
GetOperatorGroupRegistry_FWD()1412 GeneticAlgorithm::GetOperatorGroupRegistry_FWD(
1413     )
1414 {
1415     EDDY_FUNC_DEBUGSCOPE
1416     return this->GetOperatorGroupRegistry();
1417 }
1418 
1419 
1420 
1421 
1422 
1423 
1424 /*
1425 ================================================================================
1426 Structors
1427 ================================================================================
1428 */
GeneticAlgorithm(DesignTarget & target,Logger & logger)1429 GeneticAlgorithm::GeneticAlgorithm(
1430     DesignTarget& target,
1431     Logger& logger
1432     ) :
1433         _opGroup(0x0),
1434         _opSet(0x0),
1435         _pop(target),
1436         _cldrn(target),
1437         _target(target),
1438         _log(logger),
1439         _name(),
1440         _finalDataFile("finaldata#.dat"),
1441         _instanceNum(++_instanceCt),
1442         _printPopEachGen(false),
1443         _printFinalData(true),
1444         _printDiscards(true),
1445         _myDesignSpace(target.GetDesignSpace()),
1446         _isFinalized(false),
1447         _isInitialized(false),
1448         _lastFtns(nullptr),
1449         _dataDir("./"),
1450         _startTime(std::numeric_limits<clock_t>::max())
1451 {
1452     EDDY_FUNC_DEBUGSCOPE
1453     this->_opSet = new GeneticAlgorithmOperatorSet(*this);
1454 }
1455 
~GeneticAlgorithm()1456 GeneticAlgorithm::~GeneticAlgorithm(
1457     )
1458 {
1459     EDDY_FUNC_DEBUGSCOPE
1460 
1461     this->_pop.FlushAll();
1462     this->_cldrn.FlushAll();
1463     this->_opSet->DestroyOperators();
1464     delete this->_opSet;
1465 
1466     JEGALOG_II(this->GetLogger(), lverbose(), this,
1467         text_entry(lquiet(), this->GetName() + ": goodbye!\n\n")
1468         )
1469 
1470     this->GetLogger().FlushStreams();
1471 }
1472 
1473 
1474 
1475 
1476 
1477 /*
1478 ================================================================================
1479 End Namespace
1480 ================================================================================
1481 */
1482     } // namespace Algorithms
1483 } // namespace JEGA
1484