Ipopt Documentation  
 
Loading...
Searching...
No Matches
IpCachedResults.hpp
Go to the documentation of this file.
1// Copyright (C) 2004, 2011 International Business Machines and others.
2// All Rights Reserved.
3// This code is published under the Eclipse Public License.
4//
5// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
6
7#ifndef __IPCACHEDRESULTS_HPP__
8#define __IPCACHEDRESULTS_HPP__
9
10#include "IpTaggedObject.hpp"
11#include "IpObserver.hpp"
12#include <algorithm>
13#include <vector>
14#include <list>
15
16namespace Ipopt
17{
18
19#if IPOPT_CHECKLEVEL > 2
20# define IP_DEBUG_CACHE
21#endif
22#ifdef IP_DEBUG_CACHE
23# include "IpDebug.hpp"
24#endif
25
26// Forward Declarations
27
28template<class T>
29class DependentResult;
30
31// AW: I'm taking this out, since this is by far the most used
32// class. We should keep it as simple as possible.
33// /** Cache Priority Enum */
34// enum CachePriority
35// {
36// CP_Lowest,
37// CP_Standard,
38// CP_Trial,
39// CP_Iterate
40// };
41
67template<class T>
69{
70public:
71#ifdef IP_DEBUG_CACHE
73 static const Index dbg_verbosity;
74#endif
75
78
80 int max_cache_size
81 );
82
84 virtual ~CachedResults();
86
89
93 const T& result,
94 const std::vector<const TaggedObject*>& dependents,
95 const std::vector<Number>& scalar_dependents
96 );
97
103 T& retResult,
104 const std::vector<const TaggedObject*>& dependents,
105 const std::vector<Number>& scalar_dependents
106 ) const;
107
110 const T& result,
111 const std::vector<const TaggedObject*>& dependents
112 );
113
116 T& retResult,
117 const std::vector<const TaggedObject*>& dependents
118 ) const;
120
125
129 const T& result,
130 const TaggedObject* dependent1
131 );
132
137 T& retResult,
138 const TaggedObject* dependent1
139 );
140
145 const T& result,
146 const TaggedObject* dependent1,
147 const TaggedObject* dependent2
148 );
149
154 T& retResult,
155 const TaggedObject* dependent1,
156 const TaggedObject* dependent2
157 );
158
163 const T& result,
164 const TaggedObject* dependent1,
165 const TaggedObject* dependent2,
166 const TaggedObject* dependent3
167 );
168
173 T& retResult,
174 const TaggedObject* dependent1,
175 const TaggedObject* dependent2,
176 const TaggedObject* dependent3
177 );
178
182 T& retResult,
183 const TaggedObject& dependent1
184 )
185 {
186 return GetCachedResult1Dep(retResult, &dependent1);
187 }
188
190 T& retResult,
191 const TaggedObject& dependent1,
192 const TaggedObject& dependent2
193 )
194 {
195 return GetCachedResult2Dep(retResult, &dependent1, &dependent2);
196 }
197
199 T& retResult,
200 const TaggedObject& dependent1,
201 const TaggedObject& dependent2,
202 const TaggedObject& dependent3)
203 {
204 return GetCachedResult3Dep(retResult, &dependent1, &dependent2, &dependent3);
205 }
206
208 const T& result,
209 const TaggedObject& dependent1
210 )
211 {
212 AddCachedResult1Dep(result, &dependent1);
213 }
214
216 const T& result,
217 const TaggedObject& dependent1,
218 const TaggedObject& dependent2
219 )
220 {
221 AddCachedResult2Dep(result, &dependent1, &dependent2);
222 }
223
225 const T& result,
226 const TaggedObject& dependent1,
227 const TaggedObject& dependent2,
228 const TaggedObject& dependent3
229 )
230 {
231 AddCachedResult3Dep(result, &dependent1, &dependent2, &dependent3);
232 }
234
242 const std::vector<const TaggedObject*>& dependents,
243 const std::vector<Number>& scalar_dependents
244 );
245
247 void Clear();
248
250 void Clear(
251 int max_cache_size
252 );
253
254private:
265
267
270 const CachedResults&
271 );
272
275 const CachedResults&
276 );
278
281
283 mutable std::list<DependentResult<T>*>* cached_results_;
284
290
293};
294
300template<class T>
302{
303public:
304
305#ifdef IP_DEBUG_CACHE
306 static const Index dbg_verbosity;
307#endif
308
311
313 const T& result,
314 const std::vector<const TaggedObject*>& dependents,
315 const std::vector<Number>& scalar_dependents
316 );
317
321
324
325 bool IsStale() const;
326
328 void Invalidate();
329
331 const T& GetResult() const;
333
339 const std::vector<const TaggedObject*>& dependents,
340 const std::vector<Number>& scalar_dependents
341 ) const;
342
344 void DebugPrint() const;
345
346protected:
356 virtual void ReceiveNotification(
357 NotifyType notify_type,
358 const Subject* subject
359 );
360
361private:
362
373
375
378 const DependentResult&
379 );
380
383 const DependentResult&
384 );
386
392 bool stale_;
394 const T result_;
396 std::vector<TaggedObject::Tag> dependent_tags_;
398 std::vector<Number> scalar_dependents_;
399};
400
401#ifdef IP_DEBUG_CACHE
402template <class T>
404
405template <class T>
407#endif
408
409template<class T>
411 const T& result,
412 const std::vector<const TaggedObject*>& dependents,
413 const std::vector<Number>& scalar_dependents
414)
415 : stale_(false),
416 result_(result),
417 dependent_tags_(dependents.size()),
418 scalar_dependents_(scalar_dependents)
419{
420#ifdef IP_DEBUG_CACHE
421 DBG_START_METH("DependentResult<T>::DependentResult()", dbg_verbosity);
422#endif
423
424 for( Index i = 0; i < (Index) dependents.size(); ++i )
425 {
426 if( dependents[i] )
427 {
428 // Call the RequestAttach method of the Observer base class.
429 // This will add this dependent result in the Observer list
430 // for the Subject dependents[i]. As a consequence, the
431 // ReceiveNotification method of this DependentResult will be
432 // called with notify_type=NT_Changed, whenever the
433 // TaggedResult dependents[i] is changed (i.e. its HasChanged
434 // method is called).
435 RequestAttach(NT_Changed, dependents[i]);
436 dependent_tags_[i] = dependents[i]->GetTag();
437 }
438 else
439 {
440 dependent_tags_[i] = 0;
441 }
442 }
443}
444
445template<class T>
447{
448#ifdef IP_DEBUG_CACHE
449 DBG_START_METH("DependentResult<T>::~DependentResult()", dbg_verbosity);
450 //DBG_ASSERT(stale_ == true);
451#endif
452 // Nothing to be done here, destructor
453 // of T should sufficiently remove
454 // any memory, etc.
455}
456
457template<class T>
459{
460 return stale_;
461}
462
463template<class T>
465{
466 stale_ = true;
467}
468
469template<class T>
471 NotifyType notify_type,
472 const Subject* /*subject*/
473)
474{
475#ifdef IP_DEBUG_CACHE
476 DBG_START_METH("DependentResult<T>::ReceiveNotification", dbg_verbosity);
477#endif
478
479 if( notify_type == NT_Changed || notify_type == NT_BeingDestroyed )
480 {
481 stale_ = true;
482 // technically, I could unregister the notifications here, but they
483 // aren't really hurting anything
484 }
485}
486
487template<class T>
489 const std::vector<const TaggedObject*>& dependents,
490 const std::vector<Number>& scalar_dependents
491) const
492{
493#ifdef IP_DEBUG_CACHE
494 DBG_START_METH("DependentResult<T>::DependentsIdentical", dbg_verbosity);
495 DBG_ASSERT(stale_ == false);
496 DBG_ASSERT(dependents.size() == dependent_tags_.size());
497#endif
498
499 bool retVal = true;
500
501 if( dependents.size() != dependent_tags_.size() || scalar_dependents.size() != scalar_dependents_.size() )
502 {
503 retVal = false;
504 }
505 else
506 {
507 for( Index i = 0; i < (Index) dependents.size(); i++ )
508 {
509 if( ( dependents[i] && dependents[i]->GetTag() != dependent_tags_[i])
510 || (!dependents[i] && dependent_tags_[i] != 0) )
511 {
512 retVal = false;
513 break;
514 }
515 }
516 if( retVal )
517 for( Index i = 0; i < (Index) scalar_dependents.size(); i++ )
518 if( scalar_dependents[i] != scalar_dependents_[i] )
519 {
520 retVal = false;
521 break;
522 }
523 }
524
525 return retVal;
526}
527
528template<class T>
530{
531#ifdef IP_DEBUG_CACHE
532 DBG_START_METH("DependentResult<T>::GetResult()", dbg_verbosity);
533 DBG_ASSERT(stale_ == false);
534#endif
535
536 return result_;
537}
538
539template<class T>
541{
542#ifdef IP_DEBUG_CACHE
543 DBG_START_METH("DependentResult<T>::DebugPrint", dbg_verbosity);
544#endif
545
546}
547
548template<class T>
550 int max_cache_size
551)
552 : max_cache_size_(max_cache_size),
553 cached_results_(NULL)
554{
555#ifdef IP_DEBUG_CACHE
556 DBG_START_METH("CachedResults<T>::CachedResults", dbg_verbosity);
557#endif
558
559}
560
561template<class T>
563{
564#ifdef IP_DEBUG_CACHE
565 DBG_START_METH("CachedResults<T>::!CachedResults()", dbg_verbosity);
566#endif
567
568 if( cached_results_ )
569 {
570 for( typename std::list<DependentResult<T>*>::iterator iter = cached_results_->begin(); iter != cached_results_->end(); ++iter )
571 {
572 delete *iter;
573 }
574
575 delete cached_results_;
576 }
577 /*
578 while (!cached_results_.empty()) {
579 DependentResult<T>* result = cached_results_.back();
580 cached_results_.pop_back();
581 delete result;
582 }
583 */
584}
585
586template<class T>
588 const T& result,
589 const std::vector<const TaggedObject*>& dependents,
590 const std::vector<Number>& scalar_dependents
591)
592{
593#ifdef IP_DEBUG_CACHE
594 DBG_START_METH("CachedResults<T>::AddCachedResult", dbg_verbosity);
595#endif
596
597 CleanupInvalidatedResults();
598
599 // insert the new one here
601 if( !cached_results_ )
602 {
603 cached_results_ = new std::list<DependentResult<T>*>;
604 }
605
606 cached_results_->push_front(newResult);
607
608 // keep the list small enough
609 if( max_cache_size_ >= 0 )
610 {
611 // if negative, allow infinite cache
612 // non-negative - limit size of list to max_cache_size
613 DBG_ASSERT(cached_results_->size() <= (size_t)max_cache_size_ + 1);
614 if( cached_results_->size() > (size_t)max_cache_size_ )
615 {
616 delete cached_results_->back();
617 cached_results_->pop_back();
618 }
619 }
620
621#ifdef IP_DEBUG_CACHE
622 DBG_EXEC(2, DebugPrintCachedResults());
623#endif
624
625}
626
627template<class T>
629 const T& result,
630 const std::vector<const TaggedObject*>& dependents
631)
632{
633 std::vector<Number> scalar_dependents;
634 AddCachedResult(result, dependents, scalar_dependents);
635}
636
637template<class T>
639 T& retResult,
640 const std::vector<const TaggedObject*>& dependents,
641 const std::vector<Number>& scalar_dependents
642) const
643{
644#ifdef IP_DEBUG_CACHE
645 DBG_START_METH("CachedResults<T>::GetCachedResult", dbg_verbosity);
646#endif
647
648 if( !cached_results_ )
649 {
650 return false;
651 }
652
653 CleanupInvalidatedResults();
654
655 bool retValue = false;
656 for( typename std::list<DependentResult<T>*>::const_iterator iter = cached_results_->begin(); iter != cached_results_->end(); ++iter )
657 if( (*iter)->DependentsIdentical(dependents, scalar_dependents) )
658 {
659 retResult = (*iter)->GetResult();
660 retValue = true;
661 break;
662 }
663
664#ifdef IP_DEBUG_CACHE
665 DBG_EXEC(2, DebugPrintCachedResults());
666#endif
667
668 return retValue;
669}
670
671template<class T>
673 T& retResult,
674 const std::vector<const TaggedObject*>& dependents
675) const
676{
677 std::vector<Number> scalar_dependents;
678 return GetCachedResult(retResult, dependents, scalar_dependents);
679}
680
681template<class T>
683 const T& result,
685)
686{
687#ifdef IP_DEBUG_CACHE
688 DBG_START_METH("CachedResults<T>::AddCachedResult1Dep", dbg_verbosity);
689#endif
690
691 std::vector<const TaggedObject*> dependents(1);
693
694 AddCachedResult(result, dependents);
695}
696
697template<class T>
699 T& retResult,
701)
702{
703#ifdef IP_DEBUG_CACHE
704 DBG_START_METH("CachedResults<T>::GetCachedResult1Dep", dbg_verbosity);
705#endif
706
707 std::vector<const TaggedObject*> dependents(1);
709
710 return GetCachedResult(retResult, dependents);
711}
712
713template<class T>
715 const T& result,
718)
719
720{
721#ifdef IP_DEBUG_CACHE
722 DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
723#endif
724
725 std::vector<const TaggedObject*> dependents(2);
728
729 AddCachedResult(result, dependents);
730}
731
732template<class T>
734 T& retResult,
737)
738{
739#ifdef IP_DEBUG_CACHE
740 DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
741#endif
742
743 std::vector<const TaggedObject*> dependents(2);
746
747 return GetCachedResult(retResult, dependents);
748}
749
750template<class T>
752 const T& result,
756)
757{
758#ifdef IP_DEBUG_CACHE
759 DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
760#endif
761
762 std::vector<const TaggedObject*> dependents(3);
766
767 AddCachedResult(result, dependents);
768}
769
770template<class T>
772 T& retResult,
776)
777{
778#ifdef IP_DEBUG_CACHE
779 DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
780#endif
781
782 std::vector<const TaggedObject*> dependents(3);
786
787 return GetCachedResult(retResult, dependents);
788}
789
790template<class T>
792 const std::vector<const TaggedObject*>& dependents,
793 const std::vector<Number>& scalar_dependents
794)
795{
796 if( !cached_results_ )
797 {
798 return false;
799 }
800
801 CleanupInvalidatedResults();
802
803 bool retValue = false;
804 for( typename std::list<DependentResult<T>*>::const_iterator iter = cached_results_->begin(); iter != cached_results_->end(); ++iter )
805 if( (*iter)->DependentsIdentical(dependents, scalar_dependents) )
806 {
807 (*iter)->Invalidate();
808 retValue = true;
809 break;
810 }
811
812 return retValue;
813}
814
815template<class T>
817{
818 if( !cached_results_ )
819 {
820 return;
821 }
822
823 for( typename std::list<DependentResult<T>*>::const_iterator iter = cached_results_->begin(); iter != cached_results_->end(); ++iter )
824 {
825 (*iter)->Invalidate();
826 }
827
828 CleanupInvalidatedResults();
829}
830
831template<class T>
834)
835{
836 Clear();
837 max_cache_size_ = max_cache_size;
838}
839
840template<class T>
842{
843#ifdef IP_DEBUG_CACHE
844 DBG_START_METH("CachedResults<T>::CleanupInvalidatedResults", dbg_verbosity);
845#endif
846
847 if( !cached_results_ )
848 {
849 return;
850 }
851
852 typename std::list<DependentResult<T>*>::iterator iter;
853 iter = cached_results_->begin();
854 while( iter != cached_results_->end() )
855 {
856 if( (*iter)->IsStale() )
857 {
858 typename std::list<DependentResult<T>*>::iterator iter_to_remove = iter++;
859 DependentResult<T>* result_to_delete = (*iter_to_remove);
860 cached_results_->erase(iter_to_remove);
861 delete result_to_delete;
862 }
863 else
864 {
865 ++iter;
866 }
867 }
868}
869
870template<class T>
872{
873#ifdef IP_DEBUG_CACHE
874 DBG_START_METH("CachedResults<T>::DebugPrintCachedResults", dbg_verbosity);
875 if (DBG_VERBOSITY() >= 2 )
876 {
877 if (!cached_results_)
878 {
879 DBG_PRINT((2, "Currentlt no cached results:\n"));
880 }
881 else
882 {
883 typename std::list< DependentResult<T>* >::const_iterator iter;
884 DBG_PRINT((2, "Current set of cached results:\n"));
885 for (iter = cached_results_->begin(); iter != cached_results_->end(); ++iter)
886 {
887 DBG_PRINT((2, " DependentResult: %p\n", (void*)*iter));
888 }
889 }
890 }
891#endif
892
893}
894
895} // namespace Ipopt
896
897#endif
#define DBG_ASSERT(test)
Definition IpDebug.hpp:27
#define DBG_PRINT(__printf_args)
Definition IpDebug.hpp:39
#define DBG_VERBOSITY()
Definition IpDebug.hpp:43
#define DBG_START_METH(__func_name, __verbose_level)
Definition IpDebug.hpp:38
#define DBG_EXEC(__verbosity, __cmd)
Definition IpDebug.hpp:42
Templated class for Cached Results.
CachedResults()
Default Constructor.
void operator=(const CachedResults &)
Default Assignment Operator.
std::list< DependentResult< T > * > * cached_results_
list of currently cached results.
void Clear()
Invalidates all cached results.
void DebugPrintCachedResults() const
Print list of currently cached results.
void AddCachedResult2Dep(const T &result, const TaggedObject *dependent1, const TaggedObject *dependent2)
Method for adding a result to the cache, proving two dependencies as a TaggedObject explicitly.
void AddCachedResult1Dep(const T &result, const TaggedObject *dependent1)
Method for adding a result to the cache, proving one dependency as a TaggedObject explicitly.
bool GetCachedResult2Dep(T &retResult, const TaggedObject &dependent1, const TaggedObject &dependent2)
bool GetCachedResult1Dep(T &retResult, const TaggedObject *dependent1)
Method for retrieving a cached result, proving one dependency as a TaggedObject explicitly.
bool InvalidateResult(const std::vector< const TaggedObject * > &dependents, const std::vector< Number > &scalar_dependents)
Invalidates the result for given dependencies.
CachedResults(const CachedResults &)
Copy Constructor.
bool GetCachedResult(T &retResult, const std::vector< const TaggedObject * > &dependents) const
Method for retrieving a cached result, providing only a std::vector of TaggedObjects.
bool GetCachedResult(T &retResult, const std::vector< const TaggedObject * > &dependents, const std::vector< Number > &scalar_dependents) const
Generic method for retrieving a cached results, given the dependencies as a std::vector of TaggesObje...
void AddCachedResult3Dep(const T &result, const TaggedObject &dependent1, const TaggedObject &dependent2, const TaggedObject &dependent3)
bool GetCachedResult3Dep(T &retResult, const TaggedObject *dependent1, const TaggedObject *dependent2, const TaggedObject *dependent3)
Method for retrieving a cached result, proving three dependencies as a TaggedObject explicitly.
void CleanupInvalidatedResults() const
internal method for removing stale DependentResults from the list
void AddCachedResult(const T &result, const std::vector< const TaggedObject * > &dependents)
Method for adding a result, providing only a std::vector of TaggedObjects.
int max_cache_size_
maximum number of cached results
CachedResults(int max_cache_size)
Constructor.
void Clear(int max_cache_size)
Invalidate all cached results and changes max_cache_size.
bool GetCachedResult2Dep(T &retResult, const TaggedObject *dependent1, const TaggedObject *dependent2)
Method for retrieving a cached result, proving two dependencies as a TaggedObject explicitly.
virtual ~CachedResults()
Destructor.
void AddCachedResult1Dep(const T &result, const TaggedObject &dependent1)
void AddCachedResult3Dep(const T &result, const TaggedObject *dependent1, const TaggedObject *dependent2, const TaggedObject *dependent3)
Method for adding a result to the cache, proving three dependencies as a TaggedObject explicitly.
bool GetCachedResult1Dep(T &retResult, const TaggedObject &dependent1)
bool GetCachedResult3Dep(T &retResult, const TaggedObject &dependent1, const TaggedObject &dependent2, const TaggedObject &dependent3)
void AddCachedResult2Dep(const T &result, const TaggedObject &dependent1, const TaggedObject &dependent2)
void AddCachedResult(const T &result, const std::vector< const TaggedObject * > &dependents, const std::vector< Number > &scalar_dependents)
Generic method for adding a result to the cache, given a std::vector of TaggesObjects and a std::vect...
Templated class which stores one entry for the CachedResult class.
void DebugPrint() const
Print information about this DependentResults.
const T & GetResult() const
Returns the cached result.
DependentResult()
Default Constructor.
DependentResult(const DependentResult &)
Copy Constructor.
std::vector< TaggedObject::Tag > dependent_tags_
Dependencies in form of TaggedObjects.
const T result_
The value of the dependent results.
bool stale_
Flag indicating, if the cached result is still valid.
std::vector< Number > scalar_dependents_
Dependencies in form a Numbers.
virtual void ReceiveNotification(NotifyType notify_type, const Subject *subject)
Notification Receiver Method.
void Invalidate()
Invalidates the cached result.
bool DependentsIdentical(const std::vector< const TaggedObject * > &dependents, const std::vector< Number > &scalar_dependents) const
This method returns true if the dependencies provided to this function are identical to the ones stor...
bool IsStale() const
Indicates, whether the DependentResult is no longer valid.
void operator=(const DependentResult &)
Default Assignment Operator.
Slight Variation of the Observer Design Pattern.
NotifyType
Enumeration specifying the type of notification.
void RequestAttach(NotifyType notify_type, const Subject *subject)
Derived classes should call this method to request an "Attach" to a Subject.
Slight Variation of the Observer Design Pattern (Subject part).
TaggedObject class.
This file contains a base class for all exceptions and a set of macros to help with exceptions.
ipindex Index
Type of all indices of vectors, matrices etc.
Definition IpTypes.hpp:20