Ipopt  3.12.8
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 2472 2014-04-05 17:47:20Z 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 
18 namespace 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>
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
74 
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:
226  CachedResults();
227 
230 
232  void operator=(const CachedResults&);
234 
237 
239  mutable std::list<DependentResult<T>*>* cached_results_;
240 
245  void CleanupInvalidatedResults() const;
246 
248  void DebugPrintCachedResults() const;
249  };
250 
256  template <class T>
257  class DependentResult : public Observer
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 
272  ~DependentResult();
274 
278  bool IsStale() const;
279 
281  void Invalidate();
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 
318  DependentResult();
319 
322 
324  void operator=(const DependentResult&);
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>
513  void CachedResults<T>::AddCachedResult(const T& result,
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>
547  void CachedResults<T>::AddCachedResult(const T& result,
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
const T result_
The value of the dependent results.
int Index
Type for all incides.
CachedResults()
Default Constructor.
NotifyType
Enumeration specifying the type of notification.
Definition: IpObserver.hpp:59
int Int
Type of default integer.
Definition: IpTypes.hpp:21
std::vector< Number > scalar_dependents_
Dependencies in form a Numbers.
bool GetCachedResult2Dep(T &retResult, const TaggedObject *dependent1, const TaggedObject *dependent2)
Method for retrieving a cached result, proving two dependencies as a TaggedObject explicitly...
std::vector< TaggedObject::Tag > dependent_tags_
Dependencies in form of TaggedObjects.
#define DBG_START_METH(__func_name, __verbose_level)
Definition: IpDebug.hpp:49
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 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...
void operator=(const CachedResults &)
Overloaded Equals Operator.
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...
#define DBG_EXEC(__verbosity, __cmd)
Definition: IpDebug.hpp:53
Slight Variation of the Observer Design Pattern (Subject part).
Definition: IpObserver.hpp:129
DependentResult()
Default Constructor.
Int max_cache_size_
maximum number of cached results
void AddCachedResult1Dep(const T &result, const TaggedObject &dependent1)
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 CleanupInvalidatedResults() const
internal method for removing stale DependentResults from the list.
TaggedObject class.
Slight Variation of the Observer Design Pattern.
Definition: IpObserver.hpp:39
virtual ~CachedResults()
Destructor.
bool GetCachedResult2Dep(T &retResult, const TaggedObject &dependent1, const TaggedObject &dependent2)
Cache Priority Enum.
bool GetCachedResult1Dep(T &retResult, const TaggedObject &dependent1)
bool GetCachedResult1Dep(T &retResult, const TaggedObject *dependent1)
Method for retrieving a cached result, proving one dependency as a TaggedObject explicitly.
void Clear()
Invalidates all cached results.
int Index
Type of all indices of vectors, matrices etc.
Definition: IpTypes.hpp:19
#define DBG_ASSERT(test)
Definition: IpDebug.hpp:38
void AddCachedResult3Dep(const T &result, const TaggedObject &dependent1, const TaggedObject &dependent2, const TaggedObject &dependent3)
std::list< DependentResult< T > * > * cached_results_
list of currently cached results.
#define DBG_PRINT(__printf_args)
Definition: IpDebug.hpp:50
Templated class which stores one entry for the CachedResult class.
bool InvalidateResult(const std::vector< const TaggedObject *> &dependents, const std::vector< Number > &scalar_dependents)
Invalidates the result for given dependencies.
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...
void AddCachedResult1Dep(const T &result, const TaggedObject *dependent1)
Method for adding a result to the cache, proving one dependency as a TaggedObject explicitly...
bool stale_
Flag indicating, if the cached result is still valid.
void DebugPrintCachedResults() const
Print list of currently cached results.
void AddCachedResult2Dep(const T &result, const TaggedObject &dependent1, const TaggedObject &dependent2)
#define DBG_VERBOSITY()
Definition: IpDebug.hpp:54
bool GetCachedResult3Dep(T &retResult, const TaggedObject &dependent1, const TaggedObject &dependent2, const TaggedObject &dependent3)