CombinedObjectiveFunction.h
Go to the documentation of this file.
1 //===========================================================================
2 /*!
3  *
4  *
5  * \brief CombinedObjectiveFunction
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_COMBINEDOBJECTIVEFUNCTION_H
35 #define SHARK_OBJECTIVEFUNCTIONS_COMBINEDOBJECTIVEFUNCTION_H
36 
37 
39 
40 namespace shark {
41 
42 
43 ///
44 /// \brief Linear combination of objective functions
45 ///
46 /// \par
47 /// The CombinedObjectiveFunction is a linear combination of
48 /// objective functions. It assumed that the result type is
49 /// capable of forming linear combinations with real coefficients.
50 ///
51 template <typename SearchSpaceType, typename ResultT>
52 class CombinedObjectiveFunction : public AbstractObjectiveFunction<SearchSpaceType, ResultT>
53 {
54 public:
55 
58 
59  /// Constructor
63  }
64 
65  /// \brief From INameable: return the class name.
66  std::string name() const
67  { return "CombinedObjectiveFunction"; }
68 
69 
70  /// Adds a new objective function with a
71  /// weight of one to the linear combination.
72  void add(element const& e){
73  add(1.0, e);
74  }
75 
76  /// Adds a new objective function with
77  /// a weight to the linear combination.
78  void add(double weight, element const& e)
79  {
80  SHARK_CHECK(weight >= 0.0, "[CombinedObjectiveFunction::add] weight must be non-negative");
81 
82  m_weight.push_back(weight);
83  m_elements.push_back(&e);
84 
88  }
89 
90  /// Tests whether a point in SearchSpace is feasible,
91  /// e.g., whether the constraints are fulfilled.
92  bool isFeasible( const typename super::SearchPointType & input) const {
93  std::size_t ic = m_elements.size();
94  for ( std::size_t i=0; i<ic; i++)
95  if (! m_elements[i]->isFeasible(input))
96  return false;
97  return true;
98  }
99 
100  std::size_t numberOfVariables()const{
101  //todo sthis will fail if SarchPointType != Vectorspace
102  return m_elements.size() == 0? 0: m_elements[0]->numberOfVariables();
103  }
104 
105  /// Evaluates the objective function.
106  typename super::ResultType eval( const typename super::SearchPointType & input ) const
107  {
108  ++this->m_evaluationCounter;
109  std::size_t ic = m_elements.size();
110  typename super::ResultType ret = m_weight[0] * m_elements[0]->eval(input);
111  for (std::size_t i=1; i<ic; i++)
112  ret += m_weight[i] * m_elements[i]->eval(input);
113  return ret;
114  }
115 
116  /// Evaluates the objective function
117  /// and calculates its gradient.
118  typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::FirstOrderDerivative & derivative ) const {
119  ++this->m_evaluationCounter;
120  SHARK_CHECK(this->m_features.test(super::HAS_FIRST_DERIVATIVE), "[CombinedObjectiveFunction::evalDerivative] At least one of the objective functions combined is not differentiable");
121  typename super::FirstOrderDerivative der;
122  std::size_t ic = m_elements.size();
123  typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
124  derivative = m_weight[0] * der;
125  for (std::size_t i=1; i != ic; i++)
126  {
127  ret += m_weight[i] * m_elements[i]->evalDerivative(input, der);
128  derivative += m_weight[i] * der;
129  }
130  return ret;
131  }
132 
133  /// Evaluates the objective function
134  /// and calculates its gradient and
135  /// its Hessian.
136  typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::SecondOrderDerivative & derivative )const {
137  SHARK_CHECK(this->m_features.test(super::HAS_SECOND_DERIVATIVE), "[CombinedObjectiveFunction::evalDerivative] At least one of the objective functions combined is not twice differentiable");
138  typename super::SecondOrderDerivative der;
139  std::size_t ic = m_elements.size();
140  typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
141  derivative.gradient = m_weight[0] * der.gradient;
142  derivative.hessian = m_weight[0] * der.hessian;
143  for (std::size_t i=1; i<ic; i++)
144  {
145  ret += m_weight[i] * m_elements[i]->evalDerivative(input, der);
146  derivative.gradient += m_weight[i] * der.gradient;
147  derivative.hessian += m_weight[i] * der.hessian;
148  }
149  return ret;
150  }
151 
152 protected:
153  /// list of weights
154  std::vector<double> m_weight;
155 
156  /// list of "base" objective functions
157  std::vector<const element*> m_elements;
158 };
159 
160 
161 }
162 #endif // SHARK_CORE_COBINEDOBJECTIVEFUNCTION_H