IpCachedResults.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  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 2276 2013-05-05 12:33:44Z stefan $
  6. //
  7. // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
  8. #ifndef __IPCACHEDRESULTS_HPP__
  9. #define __IPCACHEDRESULTS_HPP__
  10. #include "IpTaggedObject.hpp"
  11. #include "IpObserver.hpp"
  12. #include <algorithm>
  13. #include <vector>
  14. #include <list>
  15. namespace Ipopt
  16. {
  17. #if COIN_IPOPT_CHECKLEVEL > 2
  18. # define IP_DEBUG_CACHE
  19. #endif
  20. #ifdef IP_DEBUG_CACHE
  21. # include "IpDebug.hpp"
  22. #endif
  23. // Forward Declarations
  24. template <class T>
  25. class DependentResult;
  26. // AW: I'm taking this out, since this is by far the most used
  27. // class. We should keep it as simple as possible.
  28. // /** Cache Priority Enum */
  29. // enum CachePriority
  30. // {
  31. // CP_Lowest,
  32. // CP_Standard,
  33. // CP_Trial,
  34. // CP_Iterate
  35. // };
  36. /** Templated class for Cached Results. This class stores up to a
  37. * given number of "results", entities that are stored here
  38. * together with identifiers, that can be used to later retrieve the
  39. * information again.
  40. *
  41. * Typically, T is a SmartPtr for some calculated quantity that
  42. * should be stored (such as a Vector). The identifiers (or
  43. * dependencies) are a (possibly varying) number of Tags from
  44. * TaggedObjects, and a number of Numbers. Results are added to
  45. * the cache using the AddCachedResults methods, and the can be
  46. * retrieved with the GetCachedResults methods. The second set of
  47. * methods checks whether a result has been cached for the given
  48. * identifiers. If a corresponding result is found, a copy of it
  49. * is returned and the method evaluates to true, otherwise it
  50. * evaluates to false.
  51. *
  52. * Note that cached results can become "stale", namely when a
  53. * TaggedObject that is used to identify this CachedResult is
  54. * changed. When this happens, the cached result can never be
  55. * asked for again, so that there is no point in storing it any
  56. * longer. For this purpose, a cached result, which is stored as a
  57. * DependentResult, inherits off an Observer. This Observer
  58. * retrieves notification whenever a TaggedObject dependency has
  59. * changed. Stale results are later removed from the cache.
  60. */
  61. template <class T>
  62. class CachedResults
  63. {
  64. public:
  65. #ifdef IP_DEBUG_CACHE
  66. /** (Only if compiled in DEBUG mode): debug verbosity level */
  67. static const Index dbg_verbosity;
  68. #endif
  69. /** @name Constructors and Destructors. */
  70. //@{
  71. /** Constructor, where max_cache_size is the maximal number of
  72. * results that should be cached. If max_cache_size is negative,
  73. * we allow an infinite amount of cache.
  74. */
  75. CachedResults(Int max_cache_size);
  76. /** Destructor */
  77. virtual ~CachedResults();
  78. //@}
  79. /** @name Generic methods for adding and retrieving cached results. */
  80. //@{
  81. /** Generic method for adding a result to the cache, given a
  82. * std::vector of TaggesObjects and a std::vector of Numbers.
  83. */
  84. void AddCachedResult(const T& result,
  85. const std::vector<const TaggedObject*>& dependents,
  86. const std::vector<Number>& scalar_dependents);
  87. /** Generic method for retrieving a cached results, given the
  88. * dependencies as a std::vector of TaggesObjects and a
  89. * std::vector of Numbers.
  90. */
  91. bool GetCachedResult(T& retResult,
  92. const std::vector<const TaggedObject*>& dependents,
  93. const std::vector<Number>& scalar_dependents) const;
  94. /** Method for adding a result, providing only a std::vector of
  95. * TaggedObjects.
  96. */
  97. void AddCachedResult(const T& result,
  98. const std::vector<const TaggedObject*>& dependents);
  99. /** Method for retrieving a cached result, providing only a
  100. * std::vector of TaggedObjects.
  101. */
  102. bool GetCachedResult(T& retResult,
  103. const std::vector<const TaggedObject*>& dependents) const;
  104. //@}
  105. /** @name Pointer-based methods for adding and retrieving cached
  106. * results, providing dependencies explicitly.
  107. */
  108. //@{
  109. /** Method for adding a result to the cache, proving one
  110. * dependency as a TaggedObject explicitly.
  111. */
  112. void AddCachedResult1Dep(const T& result,
  113. const TaggedObject* dependent1);
  114. /** Method for retrieving a cached result, proving one dependency
  115. * as a TaggedObject explicitly.
  116. */
  117. bool GetCachedResult1Dep(T& retResult, const TaggedObject* dependent1);
  118. /** Method for adding a result to the cache, proving two
  119. * dependencies as a TaggedObject explicitly.
  120. */
  121. void AddCachedResult2Dep(const T& result,
  122. const TaggedObject* dependent1,
  123. const TaggedObject* dependent2);
  124. /** Method for retrieving a cached result, proving two
  125. * dependencies as a TaggedObject explicitly.
  126. */
  127. bool GetCachedResult2Dep(T& retResult,
  128. const TaggedObject* dependent1,
  129. const TaggedObject* dependent2);
  130. /** Method for adding a result to the cache, proving three
  131. * dependencies as a TaggedObject explicitly.
  132. */
  133. void AddCachedResult3Dep(const T& result,
  134. const TaggedObject* dependent1,
  135. const TaggedObject* dependent2,
  136. const TaggedObject* dependent3);
  137. /** Method for retrieving a cached result, proving three
  138. * dependencies as a TaggedObject explicitly.
  139. */
  140. bool GetCachedResult3Dep(T& retResult,
  141. const TaggedObject* dependent1,
  142. const TaggedObject* dependent2,
  143. const TaggedObject* dependent3);
  144. /** @name Pointer-free version of the Add and Get methods */
  145. //@{
  146. bool GetCachedResult1Dep(T& retResult, const TaggedObject& dependent1)
  147. {
  148. return GetCachedResult1Dep(retResult, &dependent1);
  149. }
  150. bool GetCachedResult2Dep(T& retResult,
  151. const TaggedObject& dependent1,
  152. const TaggedObject& dependent2)
  153. {
  154. return GetCachedResult2Dep(retResult, &dependent1, &dependent2);
  155. }
  156. bool GetCachedResult3Dep(T& retResult,
  157. const TaggedObject& dependent1,
  158. const TaggedObject& dependent2,
  159. const TaggedObject& dependent3)
  160. {
  161. return GetCachedResult3Dep(retResult, &dependent1, &dependent2, &dependent3);
  162. }
  163. void AddCachedResult1Dep(const T& result,
  164. const TaggedObject& dependent1)
  165. {
  166. AddCachedResult1Dep(result, &dependent1);
  167. }
  168. void AddCachedResult2Dep(const T& result,
  169. const TaggedObject& dependent1,
  170. const TaggedObject& dependent2)
  171. {
  172. AddCachedResult2Dep(result, &dependent1, &dependent2);
  173. }
  174. void AddCachedResult3Dep(const T& result,
  175. const TaggedObject& dependent1,
  176. const TaggedObject& dependent2,
  177. const TaggedObject& dependent3)
  178. {
  179. AddCachedResult3Dep(result, &dependent1, &dependent2, &dependent3);
  180. }
  181. //@}
  182. /** Invalidates the result for given dependencies. Sets the stale
  183. * flag for the corresponding cached result to true if it is
  184. * found. Returns true, if the result was found. */
  185. bool InvalidateResult(const std::vector<const TaggedObject*>& dependents,
  186. const std::vector<Number>& scalar_dependents);
  187. /** Invalidates all cached results */
  188. void Clear();
  189. /** Invalidate all cached results and changes max_cache_size */
  190. void Clear(Int max_cache_size);
  191. private:
  192. /**@name Default Compiler Generated Methods
  193. * (Hidden to avoid implicit creation/calling).
  194. * These methods are not implemented and
  195. * we do not want the compiler to implement
  196. * them for us, so we declare them private
  197. * and do not define them. This ensures that
  198. * they will not be implicitly created/called. */
  199. //@{
  200. /** Default Constructor */
  201. CachedResults();
  202. /** Copy Constructor */
  203. CachedResults(const CachedResults&);
  204. /** Overloaded Equals Operator */
  205. void operator=(const CachedResults&);
  206. //@}
  207. /** maximum number of cached results */
  208. Int max_cache_size_;
  209. /** list of currently cached results. */
  210. mutable std::list<DependentResult<T>*>* cached_results_;
  211. /** internal method for removing stale DependentResults from the
  212. * list. It is called at the beginning of every
  213. * GetDependentResult method.
  214. */
  215. void CleanupInvalidatedResults() const;
  216. /** Print list of currently cached results */
  217. void DebugPrintCachedResults() const;
  218. };
  219. /** Templated class which stores one entry for the CachedResult
  220. * class. It stores the result (of type T), together with its
  221. * dependencies (vector of TaggedObjects and vector of Numbers).
  222. * It also stores a priority.
  223. */
  224. template <class T>
  225. class DependentResult : public Observer
  226. {
  227. public:
  228. #ifdef IP_DEBUG_CACHE
  229. static const Index dbg_verbosity;
  230. #endif
  231. /** @name Constructor, Destructors */
  232. //@{
  233. /** Constructor, given all information about the result. */
  234. DependentResult(const T& result, const std::vector<const TaggedObject*>& dependents,
  235. const std::vector<Number>& scalar_dependents);
  236. /** Destructor. */
  237. ~DependentResult();
  238. //@}
  239. /** @name Accessor method. */
  240. //@{
  241. /** This returns true, if the DependentResult is no longer valid. */
  242. bool IsStale() const;
  243. /** Invalidates the cached result. */
  244. void Invalidate();
  245. /** Returns the cached result. */
  246. const T& GetResult() const;
  247. //@}
  248. /** This method returns true if the dependencies provided to this
  249. * function are identical to the ones stored with the
  250. * DependentResult.
  251. */
  252. bool DependentsIdentical(const std::vector<const TaggedObject*>& dependents,
  253. const std::vector<Number>& scalar_dependents) const;
  254. /** Print information about this DependentResults. */
  255. void DebugPrint() const;
  256. protected:
  257. /** This method is overloading the pure virtual method from the
  258. * Observer base class. This method is called when a Subject
  259. * registered for this Observer sends a notification. In this
  260. * particular case, if this method is called with
  261. * notify_type==NT_Changed or NT_BeingDeleted, then this results
  262. * is marked as stale.
  263. */
  264. virtual void RecieveNotification(NotifyType notify_type, const Subject* subject);
  265. private:
  266. /**@name Default Compiler Generated Methods
  267. * (Hidden to avoid implicit creation/calling).
  268. * These methods are not implemented and
  269. * we do not want the compiler to implement
  270. * them for us, so we declare them private
  271. * and do not define them. This ensures that
  272. * they will not be implicitly created/called. */
  273. //@{
  274. /** Default Constructor */
  275. DependentResult();
  276. /** Copy Constructor */
  277. DependentResult(const DependentResult&);
  278. /** Overloaded Equals Operator */
  279. void operator=(const DependentResult&);
  280. //@}
  281. /** Flag indicating, if the cached result is still valid. A
  282. result becomes invalid, if the RecieveNotification method is
  283. called with NT_Changed */
  284. bool stale_;
  285. /** The value of the dependent results */
  286. const T result_;
  287. /** Dependencies in form of TaggedObjects */
  288. std::vector<TaggedObject::Tag> dependent_tags_;
  289. /** Dependencies in form a Numbers */
  290. std::vector<Number> scalar_dependents_;
  291. };
  292. #ifdef IP_DEBUG_CACHE
  293. template <class T>
  294. const Index CachedResults<T>::dbg_verbosity = 0;
  295. template <class T>
  296. const Index DependentResult<T>::dbg_verbosity = 0;
  297. #endif
  298. template <class T>
  299. DependentResult<T>::DependentResult(
  300. const T& result,
  301. const std::vector<const TaggedObject*>& dependents,
  302. const std::vector<Number>& scalar_dependents)
  303. :
  304. stale_(false),
  305. result_(result),
  306. dependent_tags_(dependents.size()),
  307. scalar_dependents_(scalar_dependents)
  308. {
  309. #ifdef IP_DEBUG_CACHE
  310. DBG_START_METH("DependentResult<T>::DependentResult()", dbg_verbosity);
  311. #endif
  312. for (Index i=0; i<(Index)dependents.size(); i++) {
  313. if (dependents[i]) {
  314. // Call the RequestAttach method of the Observer base class.
  315. // This will add this dependent result in the Observer list
  316. // for the Subject dependents[i]. As a consequence, the
  317. // RecieveNotification method of this DependentResult will be
  318. // called with notify_type=NT_Changed, whenever the
  319. // TaggedResult dependents[i] is changed (i.e. its HasChanged
  320. // method is called).
  321. RequestAttach(NT_Changed, dependents[i]);
  322. dependent_tags_[i] = dependents[i]->GetTag();
  323. }
  324. else {
  325. dependent_tags_[i] = TaggedObject::Tag();
  326. }
  327. }
  328. }
  329. template <class T>
  330. DependentResult<T>::~DependentResult()
  331. {
  332. #ifdef IP_DEBUG_CACHE
  333. DBG_START_METH("DependentResult<T>::~DependentResult()", dbg_verbosity);
  334. //DBG_ASSERT(stale_ == true);
  335. #endif
  336. // Nothing to be done here, destructor
  337. // of T should sufficiently remove
  338. // any memory, etc.
  339. }
  340. template <class T>
  341. bool DependentResult<T>::IsStale() const
  342. {
  343. return stale_;
  344. }
  345. template <class T>
  346. void DependentResult<T>::Invalidate()
  347. {
  348. stale_ = true;
  349. }
  350. template <class T>
  351. void DependentResult<T>::RecieveNotification(NotifyType notify_type, const Subject* subject)
  352. {
  353. #ifdef IP_DEBUG_CACHE
  354. DBG_START_METH("DependentResult<T>::RecieveNotification", dbg_verbosity);
  355. #endif
  356. if (notify_type == NT_Changed || notify_type==NT_BeingDestroyed) {
  357. stale_ = true;
  358. // technically, I could unregister the notifications here, but they
  359. // aren't really hurting anything
  360. }
  361. }
  362. template <class T>
  363. bool DependentResult<T>::DependentsIdentical(const std::vector<const TaggedObject*>& dependents,
  364. const std::vector<Number>& scalar_dependents) const
  365. {
  366. #ifdef IP_DEBUG_CACHE
  367. DBG_START_METH("DependentResult<T>::DependentsIdentical", dbg_verbosity);
  368. DBG_ASSERT(stale_ == false);
  369. DBG_ASSERT(dependents.size() == dependent_tags_.size());
  370. #endif
  371. bool retVal = true;
  372. if (dependents.size() != dependent_tags_.size()
  373. || scalar_dependents.size() != scalar_dependents_.size()) {
  374. retVal = false;
  375. }
  376. else {
  377. for (Index i=0; i<(Index)dependents.size(); i++) {
  378. if ( (dependents[i] && dependents[i]->GetTag() != dependent_tags_[i])
  379. || (!dependents[i] && dependent_tags_[i] != TaggedObject::Tag()) ) {
  380. retVal = false;
  381. break;
  382. }
  383. }
  384. if (retVal) {
  385. for (Index i=0; i<(Index)scalar_dependents.size(); i++) {
  386. if (scalar_dependents[i] != scalar_dependents_[i]) {
  387. retVal = false;
  388. break;
  389. }
  390. }
  391. }
  392. }
  393. return retVal;
  394. }
  395. template <class T>
  396. const T& DependentResult<T>::GetResult() const
  397. {
  398. #ifdef IP_DEBUG_CACHE
  399. DBG_START_METH("DependentResult<T>::GetResult()", dbg_verbosity);
  400. DBG_ASSERT(stale_ == false);
  401. #endif
  402. return result_;
  403. }
  404. template <class T>
  405. void DependentResult<T>::DebugPrint() const
  406. {
  407. #ifdef IP_DEBUG_CACHE
  408. DBG_START_METH("DependentResult<T>::DebugPrint", dbg_verbosity);
  409. #endif
  410. }
  411. template <class T>
  412. CachedResults<T>::CachedResults(Int max_cache_size)
  413. :
  414. max_cache_size_(max_cache_size),
  415. cached_results_(NULL)
  416. {
  417. #ifdef IP_DEBUG_CACHE
  418. DBG_START_METH("CachedResults<T>::CachedResults", dbg_verbosity);
  419. #endif
  420. }
  421. template <class T>
  422. CachedResults<T>::~CachedResults()
  423. {
  424. #ifdef IP_DEBUG_CACHE
  425. DBG_START_METH("CachedResults<T>::!CachedResults()", dbg_verbosity);
  426. #endif
  427. if (cached_results_) {
  428. for (typename std::list< DependentResult<T>* >::iterator iter = cached_results_->
  429. begin();
  430. iter != cached_results_->end();
  431. iter++) {
  432. delete *iter;
  433. }
  434. delete cached_results_;
  435. }
  436. /*
  437. while (!cached_results_.empty()) {
  438. DependentResult<T>* result = cached_results_.back();
  439. cached_results_.pop_back();
  440. delete result;
  441. }
  442. */
  443. }
  444. template <class T>
  445. void CachedResults<T>::AddCachedResult(const T& result,
  446. const std::vector<const TaggedObject*>& dependents,
  447. const std::vector<Number>& scalar_dependents)
  448. {
  449. #ifdef IP_DEBUG_CACHE
  450. DBG_START_METH("CachedResults<T>::AddCachedResult", dbg_verbosity);
  451. #endif
  452. CleanupInvalidatedResults();
  453. // insert the new one here
  454. DependentResult<T>* newResult = new DependentResult<T>(result, dependents, scalar_dependents);
  455. if (!cached_results_) {
  456. cached_results_ = new std::list<DependentResult<T>*>;
  457. }
  458. cached_results_->push_front(newResult);
  459. // keep the list small enough
  460. if (max_cache_size_ >= 0) { // if negative, allow infinite cache
  461. // non-negative - limit size of list to max_cache_size
  462. DBG_ASSERT((Int)cached_results_->size()<=max_cache_size_+1);
  463. if ((Int)cached_results_->size() > max_cache_size_) {
  464. delete cached_results_->back();
  465. cached_results_->pop_back();
  466. }
  467. }
  468. #ifdef IP_DEBUG_CACHE
  469. DBG_EXEC(2, DebugPrintCachedResults());
  470. #endif
  471. }
  472. template <class T>
  473. void CachedResults<T>::AddCachedResult(const T& result,
  474. const std::vector<const TaggedObject*>& dependents)
  475. {
  476. std::vector<Number> scalar_dependents;
  477. AddCachedResult(result, dependents, scalar_dependents);
  478. }
  479. template <class T>
  480. bool CachedResults<T>::GetCachedResult(T& retResult, const std::vector<const TaggedObject*>& dependents,
  481. const std::vector<Number>& scalar_dependents) const
  482. {
  483. #ifdef IP_DEBUG_CACHE
  484. DBG_START_METH("CachedResults<T>::GetCachedResult", dbg_verbosity);
  485. #endif
  486. if (!cached_results_)
  487. return false;
  488. CleanupInvalidatedResults();
  489. bool retValue = false;
  490. typename std::list< DependentResult<T>* >::const_iterator iter;
  491. for (iter = cached_results_->begin(); iter != cached_results_->end(); iter++) {
  492. if ((*iter)->DependentsIdentical(dependents, scalar_dependents)) {
  493. retResult = (*iter)->GetResult();
  494. retValue = true;
  495. break;
  496. }
  497. }
  498. #ifdef IP_DEBUG_CACHE
  499. DBG_EXEC(2, DebugPrintCachedResults());
  500. #endif
  501. return retValue;
  502. }
  503. template <class T>
  504. bool CachedResults<T>::GetCachedResult(
  505. T& retResult, const std::vector<const TaggedObject*>& dependents) const
  506. {
  507. std::vector<Number> scalar_dependents;
  508. return GetCachedResult(retResult, dependents, scalar_dependents);
  509. }
  510. template <class T>
  511. void CachedResults<T>::AddCachedResult1Dep(const T& result,
  512. const TaggedObject* dependent1)
  513. {
  514. #ifdef IP_DEBUG_CACHE
  515. DBG_START_METH("CachedResults<T>::AddCachedResult1Dep", dbg_verbosity);
  516. #endif
  517. std::vector<const TaggedObject*> dependents(1);
  518. dependents[0] = dependent1;
  519. AddCachedResult(result, dependents);
  520. }
  521. template <class T>
  522. bool CachedResults<T>::GetCachedResult1Dep(T& retResult, const TaggedObject* dependent1)
  523. {
  524. #ifdef IP_DEBUG_CACHE
  525. DBG_START_METH("CachedResults<T>::GetCachedResult1Dep", dbg_verbosity);
  526. #endif
  527. std::vector<const TaggedObject*> dependents(1);
  528. dependents[0] = dependent1;
  529. return GetCachedResult(retResult, dependents);
  530. }
  531. template <class T>
  532. void CachedResults<T>::AddCachedResult2Dep(const T& result, const TaggedObject* dependent1,
  533. const TaggedObject* dependent2)
  534. {
  535. #ifdef IP_DEBUG_CACHE
  536. DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
  537. #endif
  538. std::vector<const TaggedObject*> dependents(2);
  539. dependents[0] = dependent1;
  540. dependents[1] = dependent2;
  541. AddCachedResult(result, dependents);
  542. }
  543. template <class T>
  544. bool CachedResults<T>::GetCachedResult2Dep(T& retResult, const TaggedObject* dependent1, const TaggedObject* dependent2)
  545. {
  546. #ifdef IP_DEBUG_CACHE
  547. DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
  548. #endif
  549. std::vector<const TaggedObject*> dependents(2);
  550. dependents[0] = dependent1;
  551. dependents[1] = dependent2;
  552. return GetCachedResult(retResult, dependents);
  553. }
  554. template <class T>
  555. void CachedResults<T>::AddCachedResult3Dep(const T& result, const TaggedObject* dependent1,
  556. const TaggedObject* dependent2,
  557. const TaggedObject* dependent3)
  558. {
  559. #ifdef IP_DEBUG_CACHE
  560. DBG_START_METH("CachedResults<T>::AddCachedResult2dDep", dbg_verbosity);
  561. #endif
  562. std::vector<const TaggedObject*> dependents(3);
  563. dependents[0] = dependent1;
  564. dependents[1] = dependent2;
  565. dependents[2] = dependent3;
  566. AddCachedResult(result, dependents);
  567. }
  568. template <class T>
  569. bool CachedResults<T>::GetCachedResult3Dep(T& retResult, const TaggedObject* dependent1,
  570. const TaggedObject* dependent2,
  571. const TaggedObject* dependent3)
  572. {
  573. #ifdef IP_DEBUG_CACHE
  574. DBG_START_METH("CachedResults<T>::GetCachedResult2Dep", dbg_verbosity);
  575. #endif
  576. std::vector<const TaggedObject*> dependents(3);
  577. dependents[0] = dependent1;
  578. dependents[1] = dependent2;
  579. dependents[2] = dependent3;
  580. return GetCachedResult(retResult, dependents);
  581. }
  582. template <class T>
  583. bool CachedResults<T>::InvalidateResult(const std::vector<const TaggedObject*>& dependents,
  584. const std::vector<Number>& scalar_dependents)
  585. {
  586. if (!cached_results_)
  587. return false;
  588. CleanupInvalidatedResults();
  589. bool retValue = false;
  590. typename std::list< DependentResult<T>* >::const_iterator iter;
  591. for (iter = cached_results_->begin(); iter != cached_results_->end();
  592. iter++) {
  593. if ((*iter)->DependentsIdentical(dependents, scalar_dependents)) {
  594. (*iter)->Invalidate();
  595. retValue = true;
  596. break;
  597. }
  598. }
  599. return retValue;
  600. }
  601. template <class T>
  602. void CachedResults<T>::Clear()
  603. {
  604. if (!cached_results_)
  605. return;
  606. typename std::list< DependentResult<T>* >::const_iterator iter;
  607. for (iter = cached_results_->begin(); iter != cached_results_->end();
  608. iter++) {
  609. (*iter)->Invalidate();
  610. }
  611. CleanupInvalidatedResults();
  612. }
  613. template <class T>
  614. void CachedResults<T>::Clear(Int max_cache_size)
  615. {
  616. Clear();
  617. max_cache_size_ = max_cache_size;
  618. }
  619. template <class T>
  620. void CachedResults<T>::CleanupInvalidatedResults() const
  621. {
  622. #ifdef IP_DEBUG_CACHE
  623. DBG_START_METH("CachedResults<T>::CleanupInvalidatedResults", dbg_verbosity);
  624. #endif
  625. if (!cached_results_)
  626. return;
  627. typename std::list< DependentResult<T>* >::iterator iter;
  628. iter = cached_results_->begin();
  629. while (iter != cached_results_->end()) {
  630. if ((*iter)->IsStale()) {
  631. typename std::list< DependentResult<T>* >::iterator
  632. iter_to_remove = iter;
  633. iter++;
  634. DependentResult<T>* result_to_delete = (*iter_to_remove);
  635. cached_results_->erase(iter_to_remove);
  636. delete result_to_delete;
  637. }
  638. else {
  639. iter++;
  640. }
  641. }
  642. }
  643. template <class T>
  644. void CachedResults<T>::DebugPrintCachedResults() const
  645. {
  646. #ifdef IP_DEBUG_CACHE
  647. DBG_START_METH("CachedResults<T>::DebugPrintCachedResults", dbg_verbosity);
  648. if (DBG_VERBOSITY()>=2 ) {
  649. if (!cached_results_) {
  650. DBG_PRINT((2,"Currentlt no cached results:\n"));
  651. }
  652. else {
  653. typename std::list< DependentResult<T>* >::const_iterator iter;
  654. DBG_PRINT((2,"Current set of cached results:\n"));
  655. for (iter = cached_results_->begin(); iter != cached_results_->end(); iter++) {
  656. DBG_PRINT((2," DependentResult:0x%x\n", (*iter)));
  657. }
  658. }
  659. }
  660. #endif
  661. }
  662. } // namespace Ipopt
  663. #endif