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-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_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 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 /// IS_CONSTRAINED_FEATURE: The function has constraints and isFeasible might return false;
68 /// CAN_PROPOSE_STARTING_POINT: the function can return a possibly randomized starting point;
69 /// CAN_PROVIDE_CLOSEST_FEASIBLE: if the function is constrained, closest feasible can be
70 /// called to construct a feasible point.
71 ///
72 /// In the single objective case, the shark convention is to return a double value, while in
73 /// Multi objective optimization a RealVector is returned with an entry for every objective.
74 /// Moreoever, derivatives in the single objective case are RealVectors, while they are
75 /// RealMatrix in the multi-objective case (i.e. the jacobian of the function).
76 ///
77 /// Calling the derivatives, proposeStartingPoint or closestFeasible when the flags are not set
78 /// will throw an exception.
79 /// The features can be queried using the method features() as in
80 /// if(!(f.features()&Function::HAS_VALUE))
81 
82 /// \tparam PointType The search space the function is defined upon.
83 /// \tparam ResultT The objective space the function is defined upon.
84 template <typename PointType, typename ResultT>
86 public:
87  typedef PointType SearchPointType;
88  typedef ResultT ResultType;
89 
90  //if the result type is not an arithmetic type, we assume it is a vector-type->multi objective optimization
91  typedef typename boost::mpl::if_<
92  std::is_arithmetic<ResultT>,
94  RealMatrix
96 
98  FirstOrderDerivative gradient;
99  RealMatrix hessian;
100  };
101 
102  /// \brief List of features that are supported by an implementation.
103  enum Feature {
104  HAS_VALUE = 1, ///< The function can be evaluated and evalDerivative returns a meaningless value (for example std::numeric_limits<double>::quiet_nan()).
105  HAS_FIRST_DERIVATIVE = 2, ///< The method evalDerivative is implemented for the first derivative and returns a sensible value.
106  HAS_SECOND_DERIVATIVE = 4, ///< The method evalDerivative is implemented for the second derivative and returns a sensible value.
107  CAN_PROPOSE_STARTING_POINT = 8, ///< The function can propose a sensible starting point to search algorithms.
108  IS_CONSTRAINED_FEATURE = 16, ///< The objective function is constrained.
109  HAS_CONSTRAINT_HANDLER = 32, ///< The constraints are governed by a constraint handler which can be queried by getConstraintHandler()
110  CAN_PROVIDE_CLOSEST_FEASIBLE = 64, ///< If the function is constrained, the method closestFeasible is implemented and returns a "repaired" solution.
111  IS_THREAD_SAFE = 128, ///< can eval or evalDerivative be called in parallel?
112  IS_NOISY = 256 ///< The function value is perturbed by some kind of noise
113  };
114 
115  /// This statement declares the member m_features. See Core/Flags.h for details.
117 
118  /// \brief returns whether this function can calculate it's function value
119  bool hasValue()const{
120  return m_features & HAS_VALUE;
121  }
122 
123  /// \brief returns whether this function can calculate the first derivative
124  bool hasFirstDerivative()const{
126  }
127 
128  /// \brief returns whether this function can calculate the second derivative
129  bool hasSecondDerivative()const{
131  }
132 
133  /// \brief returns whether this function can propose a starting point.
136  }
137 
138  /// \brief returns whether this function can return
139  bool isConstrained()const{
141  }
142 
143  /// \brief returns whether this function can return
144  bool hasConstraintHandler()const{
146  }
147 
148  /// \brief Returns whether this function can calculate thee closest feasible to an infeasible point.
151  }
152 
153  /// \brief Returns true, when the function can be usd in parallel threads.
154  bool isThreadSafe()const{
155  return m_features & IS_THREAD_SAFE;
156  }
157 
158  /// \brief Returns true, when the function can be usd in parallel threads.
159  bool isNoisy()const{
160  return m_features & IS_NOISY;
161  }
162 
163  /// \brief Default ctor.
166  }
167  /// \brief Virtual destructor
169 
170  virtual void init() {
172  }
173 
174  ///\brief Sets the Rng used by the objective function.
175  ///
176  /// Objective functions need random numbers for different tasks,
177  /// e.g. to provide a first starting point or for example
178  /// mini batch learning where batches are chosen randomly.
179  /// By default, shark::random::globalRng is used.
180  /// In a multi-threaded environment this might not be safe as
181  /// the Rng is not thread safe. In this case, every thread should use its
182  /// own Rng.
183  void setRng(random::rng_type* rng){
184  mep_rng = rng;
185  }
186 
187  /// \brief Accesses the number of variables
188  virtual std::size_t numberOfVariables() const=0;
189 
190  virtual bool hasScalableDimensionality()const{
191  return false;
192  }
193 
194  /// \brief Adjusts the number of variables if the function is scalable.
195  /// \param [in] numberOfVariables The new dimension.
196  virtual void setNumberOfVariables( std::size_t numberOfVariables ){
197  throw SHARKEXCEPTION("dimensionality of function is not scalable");
198  }
199 
200  virtual std::size_t numberOfObjectives() const{
201  return 1;
202  }
203  virtual bool hasScalableObjectives()const{
204  return false;
205  }
206 
207  /// \brief Adjusts the number of objectives if the function is scalable.
208  /// \param numberOfObjectives The new number of objectives to optimize for.
209  virtual void setNumberOfObjectives( std::size_t numberOfObjectives ){
210  throw SHARKEXCEPTION("dimensionality of function is not scaleable");
211  }
212 
213 
214  /// \brief Accesses the evaluation counter of the function.
215  std::size_t evaluationCounter() const {
216  return m_evaluationCounter;
217  }
218 
219  /// \brief Returns the constraint handler of the function if it has one.
220  ///
221  /// If the function does not offer a constraint handler, an exception is thrown.
223  SHARK_RUNTIME_CHECK(m_constraintHandler, "Objective Function does not have an constraint handler!");
224  return *m_constraintHandler;
225  }
226 
227  /// \brief Tests whether a point in SearchSpace is feasible, e.g., whether the constraints are fulfilled.
228  /// \param [in] input The point to be tested for feasibility.
229  /// \return true if the point is feasible, false otherwise.
230  virtual bool isFeasible( const SearchPointType & input) const {
231  if(hasConstraintHandler()) return getConstraintHandler().isFeasible(input);
232  SHARK_RUNTIME_CHECK(!isConstrained(), "Not overwritten, even though function is constrained");
233  return true;
234  }
235 
236  /// \brief If supported, the supplied point is repaired such that it satisfies all of the function's constraints.
237  ///
238  /// \param [in,out] input The point to be repaired.
239  ///
240  /// \throws FeatureNotAvailableException in the default implementation.
241  virtual void closestFeasible( SearchPointType & input ) const {
242  if(!isConstrained()) return;
243  if(hasConstraintHandler()) return getConstraintHandler().closestFeasible(input);
245  }
246 
247  /// \brief Proposes a starting point in the feasible search space of the function.
248  ///
249  /// \return The generated starting point.
250  /// \throws FeatureNotAvailableException in the default implementation
251  /// and if a function does not support this feature.
252  virtual SearchPointType proposeStartingPoint()const {
253  if(hasConstraintHandler()&& getConstraintHandler().canGenerateRandomPoint()){
254  SearchPointType startingPoint;
255  getConstraintHandler().generateRandomPoint(*mep_rng, startingPoint);
256  return startingPoint;
257  }
258  else{
260  }
261  }
262 
263  /// \brief Evaluates the objective function for the supplied argument.
264  /// \param [in] input The argument for which the function shall be evaluated.
265  /// \return The result of evaluating the function for the supplied argument.
266  /// \throws FeatureNotAvailableException in the default implementation
267  /// and if a function does not support this feature.
268  virtual ResultType eval( SearchPointType const& input )const {
270  }
271 
272  /// \brief Evaluates the function. Useful together with STL-Algorithms like std::transform.
273  ResultType operator()( SearchPointType const& input ) const {
274  return eval(input);
275  }
276 
277  /// \brief Evaluates the objective function and calculates its gradient.
278  /// \param [in] input The argument to eval the function for.
279  /// \param [out] derivative The derivate is placed here.
280  /// \return The result of evaluating the function for the supplied argument.
281  /// \throws FeatureNotAvailableException in the default implementation
282  /// and if a function does not support this feature.
283  virtual ResultType evalDerivative( SearchPointType const& input, FirstOrderDerivative & derivative )const {
285  }
286 
287  /// \brief Evaluates the objective function and calculates its gradient.
288  /// \param [in] input The argument to eval the function for.
289  /// \param [out] derivative The derivate and the Hessian are placed here.
290  /// \return The result of evaluating the function for the supplied argument.
291  /// \throws FeatureNotAvailableException in the default implementation
292  /// and if a function does not support this feature.
293  virtual ResultType evalDerivative( SearchPointType const& input, SecondOrderDerivative & derivative )const {
295  }
296 
297 protected:
298  mutable std::size_t m_evaluationCounter; ///< Evaluation counter, default value: 0.
300  random::rng_type* mep_rng;
301 
302  /// \brief helper function which is called to announce the presence of an constraint handler.
303  ///
304  /// This function quries the propabilities of the handler and sts up the flags accordingly
306  SHARK_RUNTIME_CHECK(handler, "[AbstractObjectiveFunction::AnnounceConstraintHandler] Handler is not allowed to be NULL");
307  m_constraintHandler = handler;
310  if(handler->canGenerateRandomPoint())
312  if(handler->canProvideClosestFeasible())
314  }
315 };
316 
319 
320 }
321 
322 #endif