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