Ipopt 3.11.9
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// $Id: IpCachedResults.hpp 2476 2014-04-08 09:41:07Z stefan $
6//
7// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
8
9#ifndef __IPCACHEDRESULTS_HPP__
10#define __IPCACHEDRESULTS_HPP__
11
12#include "IpTaggedObject.hpp"
13#include "IpObserver.hpp"
14#include <algorithm>
15#include <vector>
16#include <list>
17
18namespace Ipopt
19{
20
21#if COIN_IPOPT_CHECKLEVEL > 2
22# define IP_DEBUG_CACHE
23#endif
24#ifdef IP_DEBUG_CACHE
25# include "IpDebug.hpp"
26#endif
27
28 // Forward Declarations
29
30 template <class T>
31 class DependentResult;
32
33 // AW: I'm taking this out, since this is by far the most used
34 // class. We should keep it as simple as possible.
35 // /** Cache Priority Enum */
36 // enum CachePriority
37 // {
38 // CP_Lowest,
39 // CP_Standard,
40 // CP_Trial,
41 // CP_Iterate
42 // };
43
69 template <class T>
71 {
72 public:
73#ifdef IP_DEBUG_CACHE
75 static const Index dbg_verbosity;
76#endif
77
84 CachedResults(Int max_cache_size);
85
87 virtual ~CachedResults();
89
95 void AddCachedResult(const T& result,
96 const std::vector<const TaggedObject*>& dependents,
97 const std::vector<Number>& scalar_dependents);
98
103 bool GetCachedResult(T& retResult,
104 const std::vector<const TaggedObject*>& dependents,
105 const std::vector<Number>& scalar_dependents) const;
106
110 void AddCachedResult(const T& result,
111 const std::vector<const TaggedObject*>& dependents);
112
116 bool GetCachedResult(T& retResult,
117 const std::vector<const TaggedObject*>& dependents) const;
119
127 void AddCachedResult1Dep(const T& result,
128 const TaggedObject* dependent1);
129
133 bool GetCachedResult1Dep(T& retResult, const TaggedObject* dependent1);
134
138 void AddCachedResult2Dep(const T& result,
139 const TaggedObject* dependent1,
140 const TaggedObject* dependent2);
141
145 bool GetCachedResult2Dep(T& retResult,
146 const TaggedObject* dependent1,
147 const TaggedObject* dependent2);
148
152 void AddCachedResult3Dep(const T& result,
153 const TaggedObject* dependent1,
154 const TaggedObject* dependent2,
155 const TaggedObject* dependent3);
156
160 bool GetCachedResult3Dep(T& retResult,
161 const TaggedObject* dependent1,
162 const TaggedObject* dependent2,
163 const TaggedObject* dependent3);
164
167 bool GetCachedResult1Dep(T& retResult, const TaggedObject& dependent1)
168 {
169 return GetCachedResult1Dep(retResult, &dependent1);
170 }
171 bool GetCachedResult2Dep(T& retResult,
172 const TaggedObject& dependent1,
173 const TaggedObject& dependent2)
174 {
175 return GetCachedResult2Dep(retResult, &dependent1, &dependent2);
176 }
177 bool GetCachedResult3Dep(T& retResult,
178 const TaggedObject& dependent1,
179 const TaggedObject& dependent2,
180 const TaggedObject& dependent3)
181 {
182 return GetCachedResult3Dep(retResult, &dependent1, &dependent2, &dependent3);
183 }
184 void AddCachedResult1Dep(const T& result,
185 const TaggedObject& dependent1)
186 {
187 AddCachedResult1Dep(result, &dependent1);
188 }
189 void AddCachedResult2Dep(const T& result,
190 const TaggedObject& dependent1,
191 const TaggedObject& dependent2)
192 {
193 AddCachedResult2Dep(result, &dependent1, &dependent2);
194 }
195 void AddCachedResult3Dep(const T& result,
196 const TaggedObject& dependent1,
197 const TaggedObject& dependent2,
198 const TaggedObject& dependent3)
199 {
200 AddCachedResult3Dep(result, &dependent1, &dependent2, &dependent3);
201 }
203
207 bool InvalidateResult(const std::vector<const TaggedObject*>& dependents,
208 const std::vector<Number>& scalar_dependents);
209
211 void Clear();
212
214 void Clear(Int max_cache_size);
215
216 private:
227
230
234
237
239 mutable std::list<DependentResult<T>*>* cached_results_;
240
246
249 };
250
256 template <class T>
258 {
259 public:
260
261#ifdef IP_DEBUG_CACHE
262 static const Index dbg_verbosity;
263#endif
264
268 DependentResult(const T& result, const std::vector<const TaggedObject*>& dependents,
269 const std::vector<Number>& scalar_dependents);
270
274
278 bool IsStale() const;
279
282
284 const T& GetResult() const;
286
291 bool DependentsIdentical(const std::vector<const TaggedObject*>& dependents,
292 const std::vector<Number>& scalar_dependents) const;
293
295 void DebugPrint() const;
296
297 protected:
305 virtual void RecieveNotification(NotifyType notify_type, const Subject* subject);
306
307 private:
308
319
322
326
330 bool stale_;
332 const T result_;
334 std::vector<TaggedObject::Tag> dependent_tags_;
336 std::vector<Number> scalar_dependents_;
337 };
338
339#ifdef IP_DEBUG_CACHE
340 template <class T>
342
343 template <class T>
345#endif
346
347 template <class T>
349 const T& result,
350 const std::vector<const TaggedObject*>& dependents,
351 const std::vector<Number>& scalar_dependents)
352 :
353 stale_(false),
354 result_(result),
355 dependent_tags_(dependents.size()),
356 scalar_dependents_(scalar_dependents)
357 {
358#ifdef IP_DEBUG_CACHE
359 DBG_START_METH("DependentResult<T>::DependentResult()", dbg_verbosity);
360#endif
361
362 for (Index i=0; i<(Index)dependents.size(); i++) {
363 if (dependents[i]) {
364 // Call the RequestAttach method of the Observer base class.
365 // This will add this dependent result in the Observer list
366 // for the Subject dependents[i]. As a consequence, the
367 // RecieveNotification method of this DependentResult will be
368 // called with notify_type=NT_Changed, whenever the
369 // TaggedResult dependents[i] is changed (i.e. its HasChanged
370 // method is called).
371 RequestAttach(NT_Changed, dependents[i]);
372 dependent_tags_[i] = dependents[i]->GetTag();
373 }
374 else {
375 dependent_tags_[i] = 0;
376 }
377 }
378 }
379
380 template <class T>
382 {
383#ifdef IP_DEBUG_CACHE
384 DBG_START_METH("DependentResult<T>::~DependentResult()", dbg_verbosity);
385 //DBG_ASSERT(stale_ == true);
386#endif
387 // Nothing to be done here, destructor
388 // of T should sufficiently remove
389 // any memory, etc.
390 }
391
392 template <class T>
394 {
395 return stale_;
396 }
397
398 template <class T>
400 {
401 stale_ = true;
402 }
403
404 template <class T>
406 {
407#ifdef IP_DEBUG_CACHE
408 DBG_START_METH("DependentResult<T>::RecieveNotification", dbg_verbosity);
409#endif
410
411 if (notify_type == NT_Changed || notify_type==NT_BeingDestroyed) {
412 stale_ = true;
413 // technically, I could unregister the notifications here, but they
414 // aren't really hurting anything
415 }
416 }
417
418 template <class T>
419 bool DependentResult<T>::DependentsIdentical(const std::vector<const TaggedObject*>& dependents,
420 const std::vector<Number>& scalar_dependents) const
421 {
422#ifdef IP_DEBUG_CACHE
423 DBG_START_METH("DependentResult<T>::DependentsIdentical", dbg_verbosity);
424 DBG_ASSERT(stale_ == false);
425 DBG_ASSERT(dependents.size() == dependent_tags_.size());
426#endif
427
428 bool retVal = true;
429
430 if (dependents.size() != dependent_tags_.size()
431 || scalar_dependents.size() != scalar_dependents_.size()) {
432 retVal = false;
433 }
434 else {
435 for (Index i=0; i<(Index)dependents.size(); i++) {
436 if ( (dependents[i] && dependents[i]->GetTag() != dependent_tags_[i])
437 || (!dependents[i] && dependent_tags_[i] != 0) ) {
438 retVal = false;
439 break;
440 }
441 }
442 if (retVal) {
443 for (Index i=0; i<(Index)scalar_dependents.size(); i++) {
444 if (scalar_dependents[i] != scalar_dependents_[i]) {
445 retVal = false;
446 break;
447 }
448 }
449 }
450 }
451
452 return retVal;
453 }
454
455 template <class T>
457 {
458#ifdef IP_DEBUG_CACHE
459 DBG_START_METH("DependentResult<T>::GetResult()", dbg_verbosity);
460 DBG_ASSERT(stale_ == false);
461#endif
462
463 return result_;
464 }
465
466 template <class T>
468 {
469#ifdef IP_DEBUG_CACHE
470 DBG_START_METH("DependentResult<T>::DebugPrint", dbg_verbosity);
471#endif
472
473 }
474
475 template <class T>
477 :
478 max_cache_size_(max_cache_size),
479 cached_results_(NULL)
480 {
481#ifdef IP_DEBUG_CACHE
482 DBG_START_METH("CachedResults<T>::CachedResults", dbg_verbosity);
483#endif
484
485 }
486
487 template <class T>
489 {
490#ifdef IP_DEBUG_CACHE
491 DBG_START_METH("CachedResults<T>::!CachedResults()", dbg_verbosity);
492#endif
493
494 if (cached_results_) {
495 for (typename std::list< DependentResult<T>* >::iterator iter = cached_results_->
496 begin();
497 iter != cached_results_->end();
498 iter++) {
499 delete *iter;
500 }
501 delete cached_results_;
502 }
503 /*
504 while (!cached_results_.empty()) {
505 DependentResult<T>* result = cached_results_.back();
506 cached_results_.pop_back();
507 delete result;
508 }
509 */
510 }
511
512 template <class T>
514 const std::vector<const TaggedObject*>& dependents,
515 const std::vector<Number>& scalar_dependents)
516 {
517#ifdef IP_DEBUG_CACHE
518 DBG_START_METH("CachedResults<T>::AddCachedResult", dbg_verbosity);
519#endif
520
521 CleanupInvalidatedResults();
522
523 // insert the new one here
524 DependentResult<T>* newResult = new DependentResult<T>(result, dependents, scalar_dependents);
525 if (!cached_results_) {
526 cached_results_ = new std::list<DependentResult<T>*>;
527 }
528 cached_results_->push_front(newResult);
529
530 // keep the list small enough
531 if (max_cache_size_ >= 0) { // if negative, allow infinite cache
532 // non-negative - limit size of list to max_cache_size
533 DBG_ASSERT((Int)cached_results_->size()<=max_cache_size_+1);
534 if ((Int)cached_results_->size() > max_cache_size_) {
535 delete cached_results_->back();
536 cached_results_->pop_back();
537 }
538 }
539
540#ifdef IP_DEBUG_CACHE
541 DBG_EXEC(2, DebugPrintCachedResults());
542#endif
543
544 }
545
546 template <class T>
548 const std::vector<const TaggedObject*>& dependents)
549 {
550 std::vector<Number> scalar_dependents;
551 AddCachedResult(result, dependents, scalar_dependents);
552 }
553
554 template <class T>
555 bool CachedResults<T>::GetCachedResult(T& retResult, const std::vector<const TaggedObject*>& dependents,
556 const std::vector<Number>& scalar_dependents) const
557 {
558#ifdef IP_DEBUG_CACHE
559 DBG_START_METH("CachedResults<T>::GetCachedResult", dbg_verbosity);
560#endif
561
562 if (!cached_results_)
563 return false;
564
565 CleanupInvalidatedResults();
566
567 bool retValue = false;
568 typename std::list< DependentResult<T>* >::const_iterator iter;
569 for (iter = cached_results_->begin(); iter != cached_results_->end(); iter++) {
570 if ((*iter)->DependentsIdentical(dependents, scalar_dependents)) {
571 retResult = (*iter)->GetResult();
572 retValue = true;
573 break;
574 }
575 }
576
577#ifdef IP_DEBUG_CACHE
578 DBG_EXEC(2, DebugPrintCachedResults());
579#endif
580
581 return retValue;
582 }
583
584 template <class T>
586 T& retResult, const std::vector<const TaggedObject*>& dependents) const
587 {
588 std::vector<Number> scalar_dependents;
589 return GetCachedResult(retResult, dependents, scalar_dependents);
590 }
591
592 template <class T>
594 const TaggedObject* dependent1)
595 {
596#ifdef IP_DEBUG_CACHE
597 DBG_START_METH("CachedResults<T>::AddCachedResult1Dep", dbg_verbosity);
598#endif
599
600 std::vector<const TaggedObject*> dependents(1);
601 dependents[0] = dependent1;
602
603 AddCachedResult(result, dependents);
604 }
605
606 template <class T>
607 bool CachedResults<T>::GetCachedResult1Dep(T& retResult, const TaggedObject* dependent1)
608 {
609#ifdef IP_DEBUG_CACHE
610 DBG_START_METH("CachedResults<T>::GetCachedResult1Dep", dbg_verbosity);
611#endif
612
613 std::vector<const TaggedObject*> dependents(1);
614 dependents[0] = dependent1;
615
616 return GetCachedResult(retResult, dependents);
617 }
618
619 template <class T>
620 void CachedResults<T>::AddCachedResult2Dep(const T& result, const TaggedObject* dependent1,
621 const TaggedObject* dependent2)
622
623 {
624#ifdef IP_DEBUG_CACHE
625 DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
626#endif
627
628 std::vector<const TaggedObject*> dependents(2);
629 dependents[0] = dependent1;
630 dependents[1] = dependent2;
631
632 AddCachedResult(result, dependents);
633 }
634
635 template <class T>
636 bool CachedResults<T>::GetCachedResult2Dep(T& retResult, const TaggedObject* dependent1, const TaggedObject* dependent2)
637 {
638#ifdef IP_DEBUG_CACHE
639 DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
640#endif
641
642 std::vector<const TaggedObject*> dependents(2);
643 dependents[0] = dependent1;
644 dependents[1] = dependent2;
645
646 return GetCachedResult(retResult, dependents);
647 }
648
649 template <class T>
650 void CachedResults<T>::AddCachedResult3Dep(const T& result, const TaggedObject* dependent1,
651 const TaggedObject* dependent2,
652 const TaggedObject* dependent3)
653
654 {
655#ifdef IP_DEBUG_CACHE
656 DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
657#endif
658
659 std::vector<const TaggedObject*> dependents(3);
660 dependents[0] = dependent1;
661 dependents[1] = dependent2;
662 dependents[2] = dependent3;
663
664 AddCachedResult(result, dependents);
665 }
666
667 template <class T>
668 bool CachedResults<T>::GetCachedResult3Dep(T& retResult, const TaggedObject* dependent1,
669 const TaggedObject* dependent2,
670 const TaggedObject* dependent3)
671 {
672#ifdef IP_DEBUG_CACHE
673 DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
674#endif
675
676 std::vector<const TaggedObject*> dependents(3);
677 dependents[0] = dependent1;
678 dependents[1] = dependent2;
679 dependents[2] = dependent3;
680
681 return GetCachedResult(retResult, dependents);
682 }
683
684 template <class T>
685 bool CachedResults<T>::InvalidateResult(const std::vector<const TaggedObject*>& dependents,
686 const std::vector<Number>& scalar_dependents)
687 {
688 if (!cached_results_)
689 return false;
690
691 CleanupInvalidatedResults();
692
693 bool retValue = false;
694 typename std::list< DependentResult<T>* >::const_iterator iter;
695 for (iter = cached_results_->begin(); iter != cached_results_->end();
696 iter++) {
697 if ((*iter)->DependentsIdentical(dependents, scalar_dependents)) {
698 (*iter)->Invalidate();
699 retValue = true;
700 break;
701 }
702 }
703
704 return retValue;
705 }
706
707 template <class T>
709 {
710 if (!cached_results_)
711 return;
712
713 typename std::list< DependentResult<T>* >::const_iterator iter;
714 for (iter = cached_results_->begin(); iter != cached_results_->end();
715 iter++) {
716 (*iter)->Invalidate();
717 }
718
719 CleanupInvalidatedResults();
720 }
721
722 template <class T>
723 void CachedResults<T>::Clear(Int max_cache_size)
724 {
725 Clear();
726 max_cache_size_ = max_cache_size;
727 }
728
729 template <class T>
731 {
732#ifdef IP_DEBUG_CACHE
733 DBG_START_METH("CachedResults<T>::CleanupInvalidatedResults", dbg_verbosity);
734#endif
735
736 if (!cached_results_)
737 return;
738
739 typename std::list< DependentResult<T>* >::iterator iter;
740 iter = cached_results_->begin();
741 while (iter != cached_results_->end()) {
742 if ((*iter)->IsStale()) {
743 typename std::list< DependentResult<T>* >::iterator
744 iter_to_remove = iter;
745 iter++;
746 DependentResult<T>* result_to_delete = (*iter_to_remove);
747 cached_results_->erase(iter_to_remove);
748 delete result_to_delete;
749 }
750 else {
751 iter++;
752 }
753 }
754 }
755
756 template <class T>
758 {
759#ifdef IP_DEBUG_CACHE
760 DBG_START_METH("CachedResults<T>::DebugPrintCachedResults", dbg_verbosity);
761 if (DBG_VERBOSITY()>=2 ) {
762 if (!cached_results_) {
763 DBG_PRINT((2,"Currentlt no cached results:\n"));
764 }
765 else {
766 typename std::list< DependentResult<T>* >::const_iterator iter;
767 DBG_PRINT((2,"Current set of cached results:\n"));
768 for (iter = cached_results_->begin(); iter != cached_results_->end(); iter++) {
769 DBG_PRINT((2," DependentResult:0x%x\n", (*iter)));
770 }
771 }
772 }
773#endif
774
775 }
776
777} // namespace Ipopt
778
779#endif
#define DBG_ASSERT(test)
Definition IpDebug.hpp:38
#define DBG_PRINT(__printf_args)
Definition IpDebug.hpp:50
#define DBG_VERBOSITY()
Definition IpDebug.hpp:54
#define DBG_START_METH(__func_name, __verbose_level)
Definition IpDebug.hpp:49
#define DBG_EXEC(__verbosity, __cmd)
Definition IpDebug.hpp:53
Templated class for Cached Results.
CachedResults()
Default Constructor.
void operator=(const CachedResults &)
Overloaded Equals Operator.
void Clear(Int max_cache_size)
Invalidate all cached results and changes max_cache_size.
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.
CachedResults(Int max_cache_size)
Constructor, where max_cache_size is the maximal number of results that should be cached.
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.
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)
Int max_cache_size_
maximum number of cached results
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.
DependentResult(const T &result, const std::vector< const TaggedObject * > &dependents, const std::vector< Number > &scalar_dependents)
Constructor, given all information about the result.
std::vector< Number > scalar_dependents_
Dependencies in form a Numbers.
void Invalidate()
Invalidates the cached result.
virtual void RecieveNotification(NotifyType notify_type, const Subject *subject)
This method is overloading the pure virtual method from the Observer base class.
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
This returns true, if the DependentResult is no longer valid.
void operator=(const DependentResult &)
Overloaded Equals 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.
int Int
Type of default integer.
Definition IpTypes.hpp:21
int Index
Type of all indices of vectors, matrices etc.
Definition IpTypes.hpp:19