AbstractObjectiveFunction.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief AbstractObjectiveFunction
6 
7  *
8  *
9  * \author T.Voss, T. Glasmachers, O.Krause
10  * \date 2010-2011
11  *
12  *
13  * \par Copyright 1995-2015 Shark Development Team
14  *
15  * <BR><HR>
16  * This file is part of Shark.
17  * <http://image.diku.dk/shark/>
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_ABSTRACTOBJECTIVEFUNCTION_H
35 #define SHARK_OBJECTIVEFUNCTIONS_ABSTRACTOBJECTIVEFUNCTION_H
36 
37 #include <shark/Core/INameable.h>
38 #include <shark/Core/Exception.h>
39 #include <shark/Core/Flags.h>
40 #include <shark/LinAlg/Base.h>
42 
43 namespace shark {
44 
45 /// \brief Super class of all objective functions for optimization and learning.
46 
47 /// \par
48 /// The AbstractObjectiveFunction template class is the most general
49 /// interface for a function to be minimized or maximized by an
50 /// optimizer. It subsumes many more specialized classes,
51 /// ranging from classical test problems in evolutionary algorithms to
52 /// data-dependent objective functions in supervised learning. This
53 /// interface allows all general purpose optimization procedures to be
54 /// used as model training algorithms in a learning task, with
55 /// applications ranging from training of neural networks to direct
56 /// policy search in reinforcement learning.
57 
58 /// AbstractObjectiveFunction offers a rich interface to support
59 /// different types of optimizers. Since not every objective function meets
60 /// every requirement, a flag system exists which tells the optimizer
61 /// which features are available. These are:
62 /// HAS_VALUE: The function can be evaluated. If not set, evalDerivative returns a meaningless
63 /// value (for example std::numeric_limits<double>::quiet_nan());
64 /// HAS_FIRST_DERIVATIVE: evalDerivative can be called for the FirstOrderDerivative.
65 /// The Derivative is defined and as exact as possible;
66 /// HAS_SECOND_DERIVATIVE: evalDerivative can be called for the second derivative.
67 /// It is defined and non-zero;
68 /// IS_CONSTRAINED_FEATURE: The function has constraints and isFeasible might return false;
69 /// CAN_PROPOSE_STARTING_POINT: the function can return a possibly randomized starting point;
70 /// CAN_PROVIDE_CLOSEST_FEASIBLE: if the function is constrained, closest feasible can be
71 /// called to construct a feasible point.
72 
73 /// Calling the derivatives, proposeStartingPoint or closestFeasible when the flags are not set
74 /// will throw an exception.
75 /// The features can be queried using the method features() as in
76 /// if(!(f.features()&Function::HAS_VALUE))
77 
78 /// \tparam PointType The search space the function is defined upon.
79 /// \tparam ResultT The objective space the function is defined upon.
80 template <typename PointType, typename ResultT>
82 public:
83  typedef PointType SearchPointType;
84  typedef ResultT ResultType;
85 
86  typedef SearchPointType FirstOrderDerivative;
88  RealVector gradient;
89  RealMatrix hessian;
90  };
91 
92  /// \brief List of features that are supported by an implementation.
93  enum Feature {
94  HAS_VALUE = 1, ///< The function can be evaluated and evalDerivative returns a meaningless value (for example std::numeric_limits<double>::quiet_nan()).
95  HAS_FIRST_DERIVATIVE = 2, ///< The method evalDerivative is implemented for the first derivative and returns a sensible value.
96  HAS_SECOND_DERIVATIVE = 4, ///< The method evalDerivative is implemented for the second derivative and returns a sensible value.
97  CAN_PROPOSE_STARTING_POINT = 8, ///< The function can propose a sensible starting point to search algorithms.
98  IS_CONSTRAINED_FEATURE = 16, ///< The objective function is constrained.
99  HAS_CONSTRAINT_HANDLER = 32, ///< The constraints are governed by a constraint handler which can be queried by getConstraintHandler()
100  CAN_PROVIDE_CLOSEST_FEASIBLE = 64, ///< If the function is constrained, the method closestFeasible is implemented and returns a "repaired" solution.
101  IS_THREAD_SAFE = 128 ///< can eval or evalDerivative be called in parallel?
102  };
103 
104  /// This statement declares the member m_features. See Core/Flags.h for details.
106 
107  /// \brief returns whether this function can calculate it's function value
108  bool hasValue()const{
109  return m_features & HAS_VALUE;
110  }
111 
112  /// \brief returns whether this function can calculate the first derivative
113  bool hasFirstDerivative()const{
115  }
116 
117  /// \brief returns whether this function can calculate the second derivative
118  bool hasSecondDerivative()const{
120  }
121 
122  /// \brief returns whether this function can propose a starting point.
125  }
126 
127  /// \brief returns whether this function can return
128  bool isConstrained()const{
130  }
131 
132  /// \brief returns whether this function can return
133  bool hasConstraintHandler()const{
135  }
136 
137  /// \brief Returns whether this function can calculate thee closest feasible to an infeasible point.
140  }
141 
142  /// \brief Returns true, when the function can be usd in parallel threads.
143  bool isThreadSafe()const{
144  return m_features & IS_THREAD_SAFE;
145  }
146 
147  /// \brief Default ctor.
150  }
151  /// \brief Virtual destructor
153 
154  virtual void init() {
156  }
157 
158  /// \brief Accesses the number of variables
159  virtual std::size_t numberOfVariables() const=0;
160 
161  virtual bool hasScalableDimensionality()const{
162  return false;
163  }
164 
165  /// \brief Adjusts the number of variables if the function is scalable.
166  /// \param [in] numberOfVariables The new dimension.
167  virtual void setNumberOfVariables( std::size_t numberOfVariables ){
168  throw SHARKEXCEPTION("dimensionality of function is not scalable");
169  }
170 
171  virtual std::size_t numberOfObjectives() const{
172  return 1;
173  }
174  virtual bool hasScalableObjectives()const{
175  return false;
176  }
177 
178  /// \brief Adjusts the number of objectives if the function is scalable.
179  /// \param numberOfObjectives The new number of objectives to optimize for.
180  virtual void setNumberOfObjectives( std::size_t numberOfObjectives ){
181  throw SHARKEXCEPTION("dimensionality of function is not scaleable");
182  }
183 
184 
185  /// \brief Accesses the evaluation counter of the function.
186  std::size_t evaluationCounter() const {
187  return m_evaluationCounter;
188  }
189 
190  /// \brief Returns the constraint handler of the function if it has one.
191  ///
192  /// If the function does not offer a constraint handler, an exception is thrown.
194  if(m_constraintHandler == NULL)
195  throw SHARKEXCEPTION("Objective Function does not have an constraint handler!");
196  return *m_constraintHandler;
197  }
198 
199  /// \brief Tests whether a point in SearchSpace is feasible, e.g., whether the constraints are fulfilled.
200  /// \param [in] input The point to be tested for feasibility.
201  /// \return true if the point is feasible, false otherwise.
202  virtual bool isFeasible( const SearchPointType & input) const {
203  if(hasConstraintHandler()) return getConstraintHandler().isFeasible(input);
204  if(isConstrained())
205  throw SHARKEXCEPTION("[AbstractObjectiveFunction::isFasible] not overwritten, even though function is constrained");
206  return true;
207  }
208 
209  /// \brief If supported, the supplied point is repaired such that it satisfies all of the function's constraints.
210  ///
211  /// \param [in,out] input The point to be repaired.
212  ///
213  /// \throws FeatureNotAvailableException in the default implementation.
214  virtual void closestFeasible( SearchPointType & input ) const {
215  if(!isConstrained()) return;
216  if(hasConstraintHandler()) return getConstraintHandler().closestFeasible(input);
218  }
219 
220  /// \brief Proposes a starting point in the feasible search space of the function.
221  ///
222  /// \return The generated starting point.
223  /// \throws FeatureNotAvailableException in the default implementation
224  /// and if a function does not support this feature.
225  virtual SearchPointType proposeStartingPoint()const {
226  if(hasConstraintHandler()&& getConstraintHandler().canGenerateRandomPoint()){
227  SearchPointType startingPoint;
228  getConstraintHandler().generateRandomPoint(startingPoint);
229  return startingPoint;
230  }
231  else{
233  }
234  }
235 
236  /// \brief Evaluates the objective function for the supplied argument.
237  /// \param [in] input The argument for which the function shall be evaluated.
238  /// \return The result of evaluating the function for the supplied argument.
239  /// \throws FeatureNotAvailableException in the default implementation
240  /// and if a function does not support this feature.
241  virtual ResultType eval( const SearchPointType & input )const {
243  }
244 
245  /// \brief Evaluates the function. Useful together with STL-Algorithms like std::transform.
246  ResultType operator()( const SearchPointType & input ) const {
247  return eval(input);
248  }
249 
250  /// \brief Evaluates the objective function and calculates its gradient.
251  /// \param [in] input The argument to eval the function for.
252  /// \param [out] derivative The derivate is placed here.
253  /// \return The result of evaluating the function for the supplied argument.
254  /// \throws FeatureNotAvailableException in the default implementation
255  /// and if a function does not support this feature.
256  virtual ResultType evalDerivative( const SearchPointType & input, FirstOrderDerivative & derivative )const {
258  }
259 
260  /// \brief Evaluates the objective function and calculates its gradient.
261  /// \param [in] input The argument to eval the function for.
262  /// \param [out] derivative The derivate and the Hessian are placed here.
263  /// \return The result of evaluating the function for the supplied argument.
264  /// \throws FeatureNotAvailableException in the default implementation
265  /// and if a function does not support this feature.
266  virtual ResultType evalDerivative( const SearchPointType & input, SecondOrderDerivative & derivative )const {
268  }
269 
270 protected:
271  mutable std::size_t m_evaluationCounter; ///< Evaluation counter, default value: 0.
273 
274  /// \brief helper function which is called to announce the presence of an constraint handler.
275  ///
276  /// This function quries the propabilities of the handler and sts up the flags accordingly
278  SHARK_CHECK(handler != NULL, "[AbstractObjectiveFunction::AnnounceConstraintHandler] Handler is not allowed to be NULL");
279  m_constraintHandler = handler;
282  if(handler->canGenerateRandomPoint())
284  if(handler->canProvideClosestFeasible())
286  }
287 };
288 
291 
292 }
293 
294 #endif