1 /*
2 ================================================================================
3     PROJECT:
4 
5         John Eddy's Genetic Algorithms (JEGA)
6 
7     CONTENTS:
8 
9         Implementation of class MOGA.
10 
11     NOTES:
12 
13         See notes of MOGA.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         Mon Jun 02 14:26:59 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 MOGA class.
48  */
49 
50 
51 
52 /*
53 ================================================================================
54 Includes
55 ================================================================================
56 */
57 // JEGAConfig.hpp should be the first include in all JEGA files.
58 #include <../Utilities/include/JEGAConfig.hpp>
59 
60 #include <cfloat>
61 #include <memory> // for unique_ptr
62 #include <../MOGA/include/MOGA.hpp>
63 #include <utilities/include/extremes.hpp>
64 #include <../Utilities/include/Logging.hpp>
65 #include <utilities/include/EDDY_DebugScope.hpp>
66 #include <../Utilities/include/LRUDesignCache.hpp>
67 #include <../Utilities/include/DesignStatistician.hpp>
68 #include <../Utilities/include/MultiObjectiveStatistician.hpp>
69 #include <../MOGA/include/OperatorGroups/MOGAOperatorGroup.hpp>
70 #include <../MOGA/include/OperatorGroups/DominationCountOperatorGroup.hpp>
71 
72 /*
73 ================================================================================
74 Namespace Using Directives
75 ================================================================================
76 */
77 using namespace std;
78 using namespace JEGA::Utilities;
79 using namespace JEGA::Logging;
80 using namespace eddy::utilities;
81 
82 
83 
84 
85 
86 
87 
88 /*
89 ================================================================================
90 Begin Namespace
91 ================================================================================
92 */
93 namespace JEGA {
94     namespace Algorithms {
95 
96 
97 
98 
99 /*
100 ================================================================================
101 Static Member Data Definitions
102 ================================================================================
103 */
104 const bool MOGA::_registered_operator_groups =
105 
106 
107     MOGA::RegistryOfOperatorGroups().register_(
108         MOGAOperatorGroup::Name(),
109         &MOGAOperatorGroup::Instance) &&
110 
111 
112     MOGA::RegistryOfOperatorGroups().register_(
113         DominationCountOperatorGroup::Name(),
114         &DominationCountOperatorGroup::Instance) &&
115 
116 
117 true;
118 
119 
120 
121 
122 
123 /*
124 ================================================================================
125 Mutators
126 ================================================================================
127 */
128 
129 
130 
131 
132 
133 
134 
135 
136 /*
137 ================================================================================
138 Accessors
139 ================================================================================
140 */
141 
142 
143 
144 
145 
146 
147 
148 
149 /*
150 ================================================================================
151 Public Methods
152 ================================================================================
153 */
154 GeneticAlgorithmOperatorGroupRegistry&
RegistryOfOperatorGroups()155 MOGA::RegistryOfOperatorGroups(
156     )
157 {
158     EDDY_FUNC_DEBUGSCOPE
159     static GeneticAlgorithmOperatorGroupRegistry registry;
160     return registry;
161 }
162 
163 void
ReclaimOptimal()164 MOGA::ReclaimOptimal(
165     )
166 {
167     EDDY_FUNC_DEBUGSCOPE
168 
169     JEGALOG_II(this->GetLogger(), ldebug(), this,
170         text_entry(
171             ldebug(),
172             this->GetName() +
173             ": Reclaiming optimal designs from target discards."
174             )
175         )
176 
177     // Go through all the discarded Designs and re-claim any
178     // that are non-dominated but got selected out.
179     DesignTarget& target = this->GetDesignTarget();
180 
181     // store the discards for repeated use.
182     const LRUDesignCache& discards = target.CheckoutDiscards();
183 
184     // Create a DesignGroup from the discards so that we'll have something we
185     // can iterate while reclaiming designs and so we'll have an OF sort set.
186     DesignGroup discardGroup(target, discards.DVSortSet());
187     discardGroup.FlushNonEvaluatedDesigns();
188 
189     // Get the current population.
190     DesignGroup& pop = this->GetPopulation();
191     pop.FlushNonEvaluatedDesigns();
192 
193     // Also get a reference to pop's DesignOFSortSet
194     const DesignOFSortSet& popDeque = pop.GetOFSortContainer();
195 
196     // iterate over the Designs in the discards and take any
197     // that we find to be non-dominated in the population.
198     JEGA_LOGGING_IF_ON(size_t numReclaimed = 0;)
199     for(DesignOFSortSet::iterator it(discardGroup.BeginOF());
200         it!=discardGroup.EndOF(); ++it)
201     {
202         if(!MultiObjectiveStatistician::IsDominatedByAtLeast1(**it, popDeque))
203         {
204             // Get the discarded Design out of the discards.
205             if(target.ReclaimDesign(**it))
206             {
207                 // now put the discarded Design into our population.
208                 pop.Insert(*it);
209                 JEGA_LOGGING_IF_ON(++numReclaimed;)
210             }
211         }
212     }
213 
214     // now we can unlock the discards
215     target.CheckinDiscards();
216 
217     JEGALOG_II(this->GetLogger(), lverbose(), this,
218         ostream_entry(lverbose(), this->GetName() + ": Reclaimed ")
219             << numReclaimed << " optimal designs from the discards."
220             )
221 }
222 
223 
224 
225 
226 /*
227 ================================================================================
228 Subclass Visible Methods
229 ================================================================================
230 */
231 
232 
233 
234 
235 
236 
237 
238 
239 /*
240 ================================================================================
241 Subclass Overridable Methods
242 ================================================================================
243 */
244 
245 const Design*
GetBestDesign()246 MOGA::GetBestDesign(
247     )
248 {
249     EDDY_FUNC_DEBUGSCOPE
250 
251     // Retrieve any potentially lost Optimal designs
252     this->ReclaimOptimal();
253 
254     // Store the population for repeated use.
255     DesignGroup& pop = this->GetPopulation();
256 
257     if(pop.CountFeasible() != 0)
258     {
259         // There are feasible designs so the infeasible are of
260         // no interest.  So flush them.
261         this->GetPopulation().FlushNonFeasibleDesigns();
262 
263         //now find and store those extremes
264         extremes<obj_val_t> extremeSet(
265             MultiObjectiveStatistician::FindParetoExtremes(
266                 pop.GetOFSortContainer()
267                 )
268             );
269 
270         //get number of objective functions
271         const std::size_t nof = this->GetDesignTarget().GetNOF();
272         EDDY_ASSERT(nof == extremeSet.size());
273 
274         // This will store the minimum squared deviation from the
275         // utopia point.  Initialize it to a very large number.
276         double minDistance = std::numeric_limits<double>::max();
277 
278         // Create a pointer to store the best design as each is
279         // considered.  Initialize it to the null pointer.
280         const Design* bestDesign = 0x0;
281 
282         // prepare to iterate the designs by objective function
283         // and find the best.
284         DesignOFSortSet::const_iterator it(pop.BeginOF());
285         const DesignOFSortSet::const_iterator e(pop.EndOF());
286 
287         for(; it!=e; ++it)
288         {
289             // prepare a place to store sum-of-squared distance
290             // for this Design as we traverse the objective functions.
291             double tempDistance = 0.0;
292 
293             // compute the sum-of-squares between the current point and
294             // the utopia point.  Store it as tempDistance.
295             for(size_t i=0; i<nof; ++i)
296             {
297                 const double objDist =
298                     (*it)->GetObjective(i)-extremeSet.get_min(i);
299                 tempDistance += (objDist * objDist);
300             }
301 
302             // now, if this Design turns out to be closer to the utopia
303             // point than any previously considered Design, take it as
304             // the best and update our current minimum distance.
305             if (tempDistance < minDistance)
306             {
307                 bestDesign = *it;
308                 minDistance = tempDistance;
309             }
310         }
311         // now return our best Design.  The only way this value
312         // could be null at this point is if every Design in our feasible
313         // set has sum-of-squares distance from the utopia point == limits::max.
314         return bestDesign;
315     }
316 
317     else
318 
319         // If there are no feasible designs, we are here and we return
320         // a null pointer indicating that there is no best.  Perhaps in
321         // the future, we should search for the "best of the worst".
322         return 0x0;
323 
324 }
325 
326 
327 GeneticAlgorithmOperatorGroupRegistry&
GetOperatorGroupRegistry()328 MOGA::GetOperatorGroupRegistry(
329     )
330 {
331     EDDY_FUNC_DEBUGSCOPE
332     return RegistryOfOperatorGroups();
333 }
334 
335 void
FlushNonOptimal()336 MOGA::FlushNonOptimal(
337     )
338 {
339     EDDY_FUNC_DEBUGSCOPE
340 
341     JEGA_LOGGING_IF_ON(const std::size_t numRem = )
342         MultiObjectiveStatistician::FlushDominatedFrom(this->GetPopulation());
343 
344     JEGALOG_II(this->GetLogger(), lverbose(), this,
345         ostream_entry(lverbose(), this->GetName() + ": Flushed ")
346             << numRem << " dominated designs from the population."
347         )
348 }
349 
350 DesignOFSortSet
GetCurrentSolution() const351 MOGA::GetCurrentSolution(
352     ) const
353 {
354     EDDY_FUNC_DEBUGSCOPE
355 
356     const DesignGroup& pop = this->GetPopulation();
357     const DesignTarget& target = this->GetDesignTarget();
358 
359     // if we've finalized, the current solution is in the population.
360     // There is no need to search the discards, etc.
361     if(this->IsFinalized()) return pop.GetOFSortContainer();
362 
363     // Get the Pareto from the population.
364     DesignOFSortSet pareto(MultiObjectiveStatistician::GetNonDominated(
365         pop.GetOFSortContainer()
366         ));
367 
368     const LRUDesignCache& discards = target.CheckoutDiscards();
369 
370     // popPareto is either all feasible or all infeasible.  Whatever the
371     // case, we will add any non-dominated designs from the discards back in.
372     for(DesignDVSortSet::const_iterator it(discards.begin());
373         it!=discards.end(); ++it)
374     {
375         if(!MultiObjectiveStatistician::IsDominatedByAtLeast1(**it, pareto))
376             pareto.insert(*it);
377     }
378 
379     // we are done with the discards now and can check them back in.
380     target.CheckinDiscards();
381 
382     return pareto;
383 }
384 
385 string
GetAlgorithmTypeName() const386 MOGA::GetAlgorithmTypeName(
387     ) const
388 {
389     EDDY_FUNC_DEBUGSCOPE
390     return "moga";
391 }
392 
393 
394 
395 /*
396 ================================================================================
397 Private Methods
398 ================================================================================
399 */
400 
401 
402 
403 
404 
405 
406 
407 
408 /*
409 ================================================================================
410 Structors
411 ================================================================================
412 */
MOGA(DesignTarget & target,Logger & logger)413 MOGA::MOGA(
414     DesignTarget& target,
415     Logger& logger
416     ) :
417         GeneticAlgorithm(target, logger)
418 {
419     EDDY_FUNC_DEBUGSCOPE
420 }
421 
422 
423 
424 
425 
426 
427 
428 /*
429 ================================================================================
430 End Namespace
431 ================================================================================
432 */
433     } // namespace Algorithms
434 } // namespace JEGA
435