EvaluationArchive.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief Archive of evaluated points as an objective function wrapper.
6 
7  *
8  *
9  * \author T. Glasmachers
10  * \date 2013
11  *
12  *
13  * \par Copyright 1995-2017 Shark Development Team
14  *
15  * <BR><HR>
16  * This file is part of Shark.
17  * <http://shark-ml.org/>
18  *
19  * Shark is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU Lesser General Public License as published
21  * by the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * Shark is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU Lesser General Public License
30  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 //===========================================================================
34 #ifndef SHARK_OBJECTIVEFUNCTIONS_EVALUATIONARCHIVE_H
35 #define SHARK_OBJECTIVEFUNCTIONS_EVALUATIONARCHIVE_H
36 
37 
39 
40 #include <set>
41 #include <string>
42 #include <sstream>
43 
44 
45 namespace shark {
46 
47 
48 ///
49 /// \brief Objective function wrapper storing all function evaluations.
50 ///
51 /// \tparam PointType The search space the function is defined upon.
52 /// \tparam ResultT The objective space the function is defined upon.
53 ///
54 /// \par
55 /// The EvaluationArchive class serves as an archive of all evaluated
56 /// points and the corresponding result. It can be used transparently
57 /// instead of the original objective function, e.g., by an optimizer.
58 /// Point/result pairs are added to the archive only if the specific
59 /// combination is not yet stored.
60 ///
61 /// \par
62 /// For fast-to-evaluate objective functions the archive wrapper can
63 /// be a considerable performance killer. However, whenever function
64 /// evaluations are costly (and an archive makes sense) then the
65 /// storage and maintenance overhead should be negligible.
66 ///
67 template <typename PointType, typename ResultT>
68 class EvaluationArchive : public AbstractObjectiveFunction<PointType, ResultT>
69 {
70 public:
74 
77 
78  /// \brief Pair of point and result.
80  {
81  public:
82  PointResultPairType(SearchPointType const& p, ResultType r)
83  : point(p)
84  , result(r)
85  { }
86 
88  : point(other.point)
89  , result(other.result)
90  { }
91 
92  // Comparison is based on string representation.
93  // This is a hack, but it is quite generic.
94  // And a generic solution is needed for std::set.
95  bool operator == (PointResultPairType const& other) const
96  {
97  return (toString() == other.toString());
98  }
99  bool operator < (PointResultPairType const& other) const
100  {
101  return (toString() < other.toString());
102  }
103 
104  SearchPointType point;
105  ResultType result;
106 
107  private:
108  std::string toString() const
109  {
110  std::stringstream ss;
111  ss << point << " " << result;
112  return ss.str();
113  }
114  };
115 
116  typedef std::set<PointResultPairType> PointResultPairContainer;
117  typedef typename PointResultPairContainer::iterator PointResultPairIterator;
118  typedef typename PointResultPairContainer::const_iterator PointResultPairConstIterator;
119 
120  /// \brief Constructor.
121  ///
122  /// \par
123  /// The constructor takes the objective function to be wrapped
124  /// as an argument. It is assumed that the objective object's
125  /// life time exceeds the life time of the present instance.
127  : mep_objective(objective)
128  {
129  base_type::m_features = mep_objective->features();
130  base_type::m_constraintHandler = mep_objective->hasConstraintHandler() ? &mep_objective->getConstraintHandler() : NULL;
131  }
132 
133 
134  /// \brief Access to the underlying objective function.
135  base_type* objective()
136  { return mep_objective; }
137 
138  /// \brief Access to the underlying objective function.
139  const base_type* objective() const
140  { return mep_objective; }
141 
142  /// \brief Wrapper function.
143  void init(){
144  mep_objective->setRng(this->mep_rng);
145  mep_objective->init();
146  }
147 
148  /// \brief Wrapper function.
149  virtual std::size_t numberOfObjectives() const
150  { return mep_objective->numberOfObjectives(); }
151 
152  /// \brief Wrapper function.
154  { return mep_objective->hasScalableObjectives(); }
155 
156  /// \brief Wrapper function.
158  { mep_objective->setNumberOfObjectives(numberOfObjectives); }
159 
160  /// \brief Wrapper function.
161  bool isFeasible(const SearchPointType& input) const
162  { return mep_objective->isFeasible(input); }
163 
164  /// \brief Wrapper function.
165  void closestFeasible(SearchPointType& input) const
166  { return mep_objective->closestFeasible(input); }
167 
168  /// \brief Wrapper function.
169  void proposeStartingPoint(SearchPointType& startingPoint) const
170  { return mep_objective->proposeStartingPoint(startingPoint); }
171 
172  /// \brief Wrapper function; conditional on vector space property.
173  std::size_t numberOfVariables() const
174  {
175  return mep_objective->numberOfVariables();
176  }
177 
178  /// \brief Wrapper function storing point and result.
179  ResultType eval(const SearchPointType& input) const
180  {
181  ResultType r = mep_objective->eval(input);
183  m_archive.insert(PointResultPairType(input, r));
184  return r;
185  }
186 
187  // TG: Could someone enlighten me: why do I have to copy this
188  // from the super class to make the compiler find the f**king
189  // operator??
190  ResultType operator()( const SearchPointType & input ) const
191  { return eval(input); }
192 
193  /// \brief Wrapper function storing point and result.
194  ResultType evalDerivative(const SearchPointType& input, FirstOrderDerivative& derivative) const
195  {
196  ResultType r = mep_objective->evalDerivative(input, derivative);
198  m_archive.insert(PointResultPairType(input, r));
199  return r;
200  }
201 
202  /// \brief Wrapper function storing point and result.
203  ResultType evalDerivative(const SearchPointType& input, SecondOrderDerivative& derivative) const
204  {
205  ResultType r = mep_objective->evalDerivative(input, derivative);
207  m_archive.insert(PointResultPairType(input, r));
208  return r;
209  }
210 
211 
212  ////////////////////////////////////////////////////////////
213  // access to the archive
214  //
215 
216  /// Return the size of the archive; which is the number of point/result pairs.
217  std::size_t size() const
218  { return m_archive.size(); }
219 
220  /// Begin iterator to the point/result pairs.
221  PointResultPairIterator begin()
222  { return m_archive.begin(); }
223 
224  /// Begin iterator to the point/result pairs.
225  PointResultPairConstIterator begin() const
226  { return m_archive.begin(); }
227 
228  /// End iterator to the point/result pairs.
229  PointResultPairIterator end()
230  { return m_archive.end(); }
231 
232  /// End iterator to the point/result pairs.
233  PointResultPairConstIterator end() const
234  { return m_archive.end(); }
235 
236 private:
237  base_type* mep_objective; ///< objective function to be wrapped
238  mutable PointResultPairContainer m_archive; ///< evaluated point/result pairs
239 };
240 
241 
242 };
243 #endif