1 /*
2 ================================================================================
3     PROJECT:
4 
5         John Eddy's Genetic Algorithms (JEGA)
6 
7     CONTENTS:
8 
9         Implementation of class DesignTarget.
10 
11     NOTES:
12 
13         See notes of DesignTarget.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.0.0
30 
31     CHANGES:
32 
33         Tue Dec 20 08:11:48 2005 - 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 DesignTarget class.
48  */
49 
50 
51 
52 
53 /*
54 ================================================================================
55 Includes
56 ================================================================================
57 */
58 // JEGAConfig.hpp should be the first include in all JEGA files.
59 #include <../Utilities/include/JEGAConfig.hpp>
60 
61 #ifdef JEGA_THREADSAFE
62 #include <threads/include/mutex.hpp>
63 #include <threads/include/mutex_lock.hpp>
64 #endif
65 
66 #include <../Utilities/include/Design.hpp>
67 #include <../Utilities/include/Logging.hpp>
68 #include <../Utilities/include/DesignTarget.hpp>
69 #include <utilities/include/EDDY_DebugScope.hpp>
70 #include <../Utilities/include/RegionOfSpace.hpp>
71 #include <../Utilities/include/LRUDesignCache.hpp>
72 #include <../Utilities/include/ConstraintInfo.hpp>
73 #include <../Utilities/include/DesignMultiSet.hpp>
74 #include <../Utilities/include/DesignVariableInfo.hpp>
75 #include <../Utilities/include/ObjectiveFunctionInfo.hpp>
76 
77 
78 
79 
80 
81 
82 
83 /*
84 ================================================================================
85 Namespace Using Directives
86 ================================================================================
87 */
88 JEGA_IF_THREADSAFE(using namespace eddy::threads;)
89 using namespace JEGA::Logging;
90 
91 
92 
93 
94 
95 
96 /*
97 ================================================================================
98 Begin Namespace
99 ================================================================================
100 */
101 namespace JEGA {
102     namespace Utilities {
103 
104 
105 
106 /*
107 ================================================================================
108 Nested Utility Class Implementations
109 ================================================================================
110 */
111 #ifdef JEGA_THREADSAFE
112 
113 /// A class housing all mutexes used by the DesignTarget.
114 /**
115  * This gets removed if JEGA_THREADSAFE is not defined.
116  */
117 class DesignTarget::Mutexes
118 {
119     /*
120     ============================================================================
121     Member Data Declarations
122     ============================================================================
123     */
124     public:
125 
126         /// A mutex to protect the collection of discards.
127         mutable mutex _discardMutex;
128 
129     /*
130     ============================================================================
131     Structors
132     ============================================================================
133     */
134     public:
135 
136         /**
137          * \brief Default constructs a Mutexes object which default constructs
138          *        all mutexes.
139          */
Mutexes()140         Mutexes(
141             ) :
142                 _discardMutex(PTHREAD_MUTEX_RECURSIVE)
143         {
144             EDDY_FUNC_DEBUGSCOPE
145         }
146 
147 }; // class DesignTarget::Mutexes
148 
149 #endif // JEGA_THREADSAFE
150 
151 /*
152 ================================================================================
153 Static Member Data Definitions
154 ================================================================================
155 */
156 
157 const std::size_t DesignTarget::DEFAULT_MAX_GUFF_SIZE = 1000;
158 
159 
160 
161 
162 /*
163 ================================================================================
164 Mutators
165 ================================================================================
166 */
167 
168 void
SetTrackDiscards(bool use)169 DesignTarget::SetTrackDiscards(
170     bool use
171     )
172 {
173     EDDY_FUNC_DEBUGSCOPE
174     this->_trackDiscards = use;
175 
176     JEGALOG_II_G(lverbose(), this,
177         ostream_entry(
178             lverbose(), "Design Target: The track discards flag is now set to "
179             // The compiler on sass9000 doesn't like boolalpha.
180             //) << std::boolalpha << this->_trackDiscards
181             ) << (this->_trackDiscards ? "true" : "false")
182         )
183 }
184 
185 void
SetMaxGuffSize(std::size_t mgs)186 DesignTarget::SetMaxGuffSize(
187     std::size_t mgs
188     )
189 {
190     EDDY_FUNC_DEBUGSCOPE
191 
192     EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
193     this->_maxGuffSize = mgs;
194     this->_guff.reserve(this->_maxGuffSize);
195 
196     // do lazy size decrease.  Don't trim the end here.  Just wait for it to
197     // fall below the desired number.
198 
199     JEGALOG_II_G(lverbose(), this,
200         ostream_entry(
201             lverbose(), "Design Target: The maximum Guff size is now set to "
202             ) << this->_maxGuffSize << '.'
203         )
204 }
205 
206 void
SetMaxDiscardCacheSize(std::size_t maxSize)207 DesignTarget::SetMaxDiscardCacheSize(
208     std::size_t maxSize
209     )
210 {
211     EDDY_FUNC_DEBUGSCOPE
212 
213     EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
214     this->_discCache->max_size(maxSize);
215 
216     JEGALOG_II_G(lverbose(), this,
217         ostream_entry(
218             lverbose(), "Design Target: The maximum discards cache size is "
219             "now set to ") << this->_maxGuffSize << '.'
220         )
221 }
222 
223 
224 
225 
226 
227 
228 
229 
230 
231 /*
232 ================================================================================
233 Accessors
234 ================================================================================
235 */
236 std::size_t
GetMaxDiscardCacheSize() const237 DesignTarget::GetMaxDiscardCacheSize(
238     ) const
239 {
240     EDDY_FUNC_DEBUGSCOPE
241     return this->_discCache->max_size();
242 }
243 
244 
245 
246 
247 
248 
249 
250 /*
251 ================================================================================
252 Public Methods
253 ================================================================================
254 */
255 
256 
257 
258 
259 
260 
261 
262 
263 /*
264 ================================================================================
265 Subclass Visible Methods
266 ================================================================================
267 */
268 
269 
270 
271 
272 
273 
274 
275 
276 /*
277 ================================================================================
278 Subclass Overridable Methods
279 ================================================================================
280 */
281 const LRUDesignCache&
CheckoutDiscards() const282 DesignTarget::CheckoutDiscards(
283     ) const
284 {
285     EDDY_FUNC_DEBUGSCOPE
286     JEGA_IF_THREADSAFE(this->_mutexes->_discardMutex.lock();)
287     return *this->_discCache;
288 }
289 
290 void
CheckinDiscards() const291 DesignTarget::CheckinDiscards(
292     ) const
293 {
294     EDDY_FUNC_DEBUGSCOPE
295     JEGA_IF_THREADSAFE(this->_mutexes->_discardMutex.unlock();)
296 }
297 
298 Design*
GetNewDesign() const299 DesignTarget::GetNewDesign(
300     ) const
301 {
302     EDDY_FUNC_DEBUGSCOPE
303 
304     Design* ret = 0x0;
305     {
306         EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
307         if(this->_guff.empty())
308             return new Design(const_cast<DesignTarget&>(*this));
309         ret = this->_guff.back();
310         this->_guff.pop_back();
311     }
312     ret->ResetID();
313     return ret;
314 }
315 
316 Design*
GetNewDesign(const Design & copy) const317 DesignTarget::GetNewDesign(
318     const Design& copy
319     ) const
320 {
321     EDDY_FUNC_DEBUGSCOPE
322 
323     Design* ret = 0x0;
324     {
325         EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
326         if(this->_guff.empty()) return new Design(copy);
327         ret = this->_guff.back();
328         this->_guff.pop_back();
329     }
330     ret->operator =(copy);
331     ret->ResetID();
332     return ret;
333 }
334 
335 bool
CheckFeasibility(Design & des) const336 DesignTarget::CheckFeasibility(
337     Design& des
338     ) const
339 {
340     EDDY_FUNC_DEBUGSCOPE
341 
342     this->CheckSideConstraints(des);
343     this->CheckNonSideConstraints(des);
344     return des.IsFeasible();
345 }
346 
347 bool
CheckSideConstraints(Design & des) const348 DesignTarget::CheckSideConstraints(
349     Design& des
350     ) const
351 {
352     EDDY_FUNC_DEBUGSCOPE
353 
354     // Iterating through the design variables and look for out-of-bounds values.
355     for(DesignVariableInfoVector::const_iterator dit(this->_dvInfos.begin());
356         dit!=this->_dvInfos.end(); ++dit)
357     {
358         if(!(*dit)->IsRepInBounds((*dit)->WhichRep(des)))
359         {
360             des.SetSatisfiesBounds(false);
361             return false;
362         }
363     }
364 
365     // if we make it here, we satisfied them all.
366     des.SetSatisfiesBounds(true);
367     return true;
368 }
369 
370 bool
CheckNonSideConstraints(Design & des) const371 DesignTarget::CheckNonSideConstraints(
372     Design& des
373     ) const
374 {
375     EDDY_FUNC_DEBUGSCOPE
376 
377     // iterate through the constraint info list and check for violations.
378     for(ConstraintInfoVector::const_iterator cit(this->_cnInfos.begin());
379         cit!=this->_cnInfos.end(); ++cit)
380     {
381         if((*cit)->GetViolationAmount(des) != 0.0)
382         {
383             des.SetSatisfiesConstraints(false);
384             return false;
385         }
386     }
387 
388     // if we make it here, we satisfied them all.
389     des.SetSatisfiesConstraints(true);
390     return true;
391 }
392 
393 void
TakeDesign(Design * des)394 DesignTarget::TakeDesign(
395     Design* des
396     )
397 {
398     EDDY_FUNC_DEBUGSCOPE
399     EDDY_ASSERT(des != 0x0);
400     EDDY_ASSERT(&des->GetDesignTarget() == this);
401 
402     if(this->_trackDiscards && des->IsEvaluated())
403     {
404         EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
405         this->_discCache->insert(des);
406     }
407     else
408     {
409         {
410             EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
411             if(this->_guff.size() < this->_maxGuffSize)
412             {
413                 // Must clear prior to unlocking mutex b/c otherwise the design
414                 // could be pulled out and used prior to clearing, then get
415                 // cleared, etc.
416                 des->Dispose();
417                 this->_guff.push_back(des);
418                 return;
419             }
420         }
421 
422         // if we make it here, we're not keeping the design at all.  Delete it.
423         delete des;
424     }
425 }
426 
427 bool
ReclaimDesign(const Design & des)428 DesignTarget::ReclaimDesign(
429     const Design& des
430     )
431 {
432     EDDY_FUNC_DEBUGSCOPE
433 
434     EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
435     DesignDVSortSet::iterator it(
436         this->_discCache->find_exact(const_cast<Design*>(&des))
437         );
438 
439     if(it == this->_discCache->end()) return false;
440     this->_discCache->erase(it);
441     return true;
442 }
443 
444 void
RecordAllConstraintViolations(const Design & des) const445 DesignTarget::RecordAllConstraintViolations(
446     const Design& des
447     ) const
448 {
449     EDDY_FUNC_DEBUGSCOPE
450 
451     for(ConstraintInfoVector::const_iterator it(this->_cnInfos.begin());
452         it!=this->_cnInfos.end(); ++it)
453             (*it)->RecordViolation(des);
454 }
455 
456 bool
AddDesignVariableInfo(DesignVariableInfo & info)457 DesignTarget::AddDesignVariableInfo(
458     DesignVariableInfo& info
459     )
460 {
461     EDDY_FUNC_DEBUGSCOPE
462     EDDY_ASSERT(&info.GetDesignTarget() == this);
463     EDDY_ASSERT(this->_discCache->empty());
464 
465     if(&info.GetDesignTarget() != this) return false;
466 
467     info.SetNumber(this->_dvInfos.size());
468     this->_dvInfos.push_back(&info);
469 
470     JEGALOG_II_G(lverbose(), this,
471         ostream_entry(lverbose(), "Design Target: Design variable " +
472             info.GetLabel() + " added.  ") << this->_dvInfos.size()
473             << " design variables now in target."
474             )
475 
476     EDDY_SCOPEDLOCK(l2, this->_mutexes->_discardMutex)
477     this->_discCache->flush();
478     this->FlushTheGuff();
479     return true;
480 }
481 
482 bool
AddConstraintInfo(ConstraintInfo & info)483 DesignTarget::AddConstraintInfo(
484     ConstraintInfo& info
485     )
486 {
487     EDDY_FUNC_DEBUGSCOPE
488     EDDY_ASSERT(&info.GetDesignTarget() == this);
489     EDDY_ASSERT(this->_discCache->empty());
490 
491     if(&info.GetDesignTarget() != this) return false;
492 
493     info.SetNumber(this->_cnInfos.size());
494     this->_cnInfos.push_back(&info);
495 
496     JEGALOG_II_G(lverbose(), this,
497         ostream_entry(lverbose(), "Design Target: Constraint " +
498             info.GetLabel()) << '(' << info.GetEquation() << ") added.  "
499             << this->_cnInfos.size() << " constraints now in target."
500             )
501 
502     EDDY_SCOPEDLOCK(l2, this->_mutexes->_discardMutex)
503     this->_discCache->flush();
504     this->FlushTheGuff();
505     return true;
506 }
507 
508 bool
AddObjectiveFunctionInfo(ObjectiveFunctionInfo & info)509 DesignTarget::AddObjectiveFunctionInfo(
510     ObjectiveFunctionInfo& info
511     )
512 {
513     EDDY_FUNC_DEBUGSCOPE
514     EDDY_ASSERT(&info.GetDesignTarget() == this);
515     EDDY_ASSERT(this->_discCache->empty());
516 
517     if(&info.GetDesignTarget() != this) return false;
518 
519     info.SetNumber(this->_ofInfos.size());
520     this->_ofInfos.push_back(&info);
521 
522     JEGALOG_II_G(lverbose(), this,
523         ostream_entry(lverbose(), "Design Target: Objective " +
524             info.GetLabel() + " added.  ") << this->_ofInfos.size()
525             << " objectives now in target."
526             )
527 
528     EDDY_SCOPEDLOCK(l2, this->_mutexes->_discardMutex)
529     this->_discCache->flush();
530     this->FlushTheGuff();
531     return true;
532 }
533 
534 RegionOfSpace
GetDesignSpace() const535 DesignTarget::GetDesignSpace(
536     ) const
537 {
538     EDDY_FUNC_DEBUGSCOPE
539     RegionOfSpace ret(this->_dvInfos.size());
540     for(DesignVariableInfoVector::const_iterator it(this->_dvInfos.begin());
541         it!=this->_dvInfos.end(); ++it)
542             ret.SetLimits(
543                 (*it)->GetNumber(),
544                 (*it)->GetMinRep(),
545                 (*it)->GetMaxRep()
546                 );
547 
548     return ret;
549 }
550 
551 
552 /*
553 ================================================================================
554 Private Methods
555 ================================================================================
556 */
557 
558 void
FlushTheGuff()559 DesignTarget::FlushTheGuff(
560     )
561 {
562     EDDY_FUNC_DEBUGSCOPE
563     EDDY_SCOPEDLOCK(l, this->_mutexes->_discardMutex)
564     for(size_t i=0; i<this->_guff.size(); ++i) delete this->_guff[i];
565     this->_guff.clear();
566 }
567 
568 
569 
570 
571 
572 
573 
574 /*
575 ================================================================================
576 Structors
577 ================================================================================
578 */
DesignTarget()579 DesignTarget::DesignTarget(
580     ) :
581         _trackDiscards(true),
582         _discCache(new LRUDesignCache(100)),
583         //_discards(new DesignDVSortSet()),
584         _dvInfos(),
585         _ofInfos(),
586         _cnInfos(),
587         _guff(),
588         _maxGuffSize(DEFAULT_MAX_GUFF_SIZE) JEGA_COMMA_IF_THREADSAFE
589         JEGA_IF_THREADSAFE(_mutexes(new Mutexes()))
590 {
591     EDDY_FUNC_DEBUGSCOPE
592 }
593 
~DesignTarget()594 DesignTarget::~DesignTarget(
595     )
596 {
597     EDDY_FUNC_DEBUGSCOPE
598 
599     JEGA_IF_THREADSAFE(this->_mutexes->_discardMutex.lock();)
600     //this->_discards->flush();
601     this->_discCache->flush();
602     this->FlushTheGuff();
603     JEGA_IF_THREADSAFE(this->_mutexes->_discardMutex.unlock();)
604 
605     DesignVariableInfoVector::iterator dit(this->_dvInfos.begin());
606     for(; dit!=this->_dvInfos.end(); ++dit) delete *dit;
607 
608     ConstraintInfoVector::iterator cit(this->_cnInfos.begin());
609     for(; cit!=this->_cnInfos.end(); ++cit) delete *cit;
610 
611     ObjectiveFunctionInfoVector::iterator oit(this->_ofInfos.begin());
612     for(; oit!=this->_ofInfos.end(); ++oit) delete *oit;
613 
614     JEGA_IF_THREADSAFE(delete this->_mutexes;)
615     //delete this->_discards;
616     delete this->_discCache;
617 }
618 
619 
620 
621 
622 
623 
624 /*
625 ================================================================================
626 End Namespace
627 ================================================================================
628 */
629     } // namespace Utilities
630 } // namespace JEGA
631 
632