1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (C) 2004, 2006 International Business Machines and others.
// All Rights Reserved.
// This code is published under the Eclipse Public License.
//
// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
#ifndef __IPTAGGEDOBJECT_HPP__
#define __IPTAGGEDOBJECT_HPP__
#include "IpUtils.hpp"
#include "IpDebug.hpp"
#include "IpReferenced.hpp"
#include "IpObserver.hpp"
namespace Ipopt
{
/** TaggedObject class.
* Often, certain calculations or operations are expensive,
* and it can be very inefficient to perform these calculations
* again if the input to the calculation has not changed
* since the result was last stored.
* This base class provides an efficient mechanism to update
* a tag, indicating that the object has changed.
* Users of a TaggedObject class, need their own Tag data
* member to keep track of the state of the TaggedObject, the
* last time they performed a calculation. A basic use case for
* users of a class inheriting from TaggedObject follows like
* this:
*
* 1. Initialize your own Tag to zero in constructor.
*
* 2. Before an expensive calculation,
* check if the TaggedObject has changed, passing in
* your own Tag, indicating the last time you used
* the object for the calculation. If it has changed,
* perform the calculation again, and store the result.
* If it has not changed, simply return the stored result.
*
* Here is a simple example:
\verbatim
if (vector.HasChanged(my_vector_tag_)) {
my_vector_tag_ = vector.GetTag();
result = PerformExpensiveCalculation(vector);
return result;
}
else {
return result;
}
\endverbatim
*
* Objects derived from TaggedObject must indicate that they have changed to
* the base class using the protected member function ObjectChanged(). For
* example, a Vector class, inside its own set method, MUST call
* ObjectChanged() to update the internally stored tag for comparison.
*/
class IPOPTLIB_EXPORT TaggedObject : public ReferencedObject, public Subject
{
public:
/** Type for the Tag values */
typedef unsigned int Tag;
/** Constructor. */
TaggedObject()
:
Subject()
{
ObjectChanged();
}
/** Destructor. */
virtual ~TaggedObject()
{}
/** Users of TaggedObjects call this to
* update their own internal tags every time
* they perform the expensive operation.
*/
Tag GetTag() const
{
return tag_;
}
/** Users of TaggedObjects call this to
* check if the object HasChanged since
* they last updated their own internal
* tag.
*/
bool HasChanged(const Tag comparison_tag) const
{
return (comparison_tag == tag_) ? false : true;
}
protected:
/** Objects derived from TaggedObject MUST call this
* method every time their internal state changes to
* update the internal tag for comparison
*/
void ObjectChanged();
private:
/**@name Default Compiler Generated Methods (Hidden to avoid
* implicit creation/calling). These methods are not implemented
* and we do not want the compiler to implement them for us, so we
* declare them private and do not define them. This ensures that
* they will not be implicitly created/called. */
///@{
/** Copy Constructor */
TaggedObject(const TaggedObject&);
/** Default Assignment Operator */
void operator=(const TaggedObject&);
///@}
/** The tag indicating the current state of the object.
* We use this to compare against the comparison_tag
* in the HasChanged method. This member is updated
* from the unique_tag_ every time the object changes.
*/
Tag tag_;
/** The index indicating the cache priority for this
* TaggedObject. If a result that depended on this
* TaggedObject is cached, it will be cached with this
* priority
*/
Index cache_priority_;
};
} // namespace Ipopt
#endif