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-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_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& 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& e)
79  {
80  SHARK_RUNTIME_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  void init(){
101  for ( std::size_t i=0; i<m_elements.size(); i++){
102  m_elements[i]->setRng(this->mep_rng);
103  m_elements[i]->init();
104  }
105  }
106 
107  std::size_t numberOfVariables()const{
108  //todo sthis will fail if SarchPointType != Vectorspace
109  return m_elements.size() == 0? 0: m_elements[0]->numberOfVariables();
110  }
111 
112  /// Evaluates the objective function.
113  typename super::ResultType eval( const typename super::SearchPointType & input ) const
114  {
115  ++this->m_evaluationCounter;
116  std::size_t ic = m_elements.size();
117  typename super::ResultType ret = m_weight[0] * m_elements[0]->eval(input);
118  for (std::size_t i=1; i<ic; i++)
119  ret += m_weight[i] * m_elements[i]->eval(input);
120  return ret;
121  }
122 
123  /// Evaluates the objective function
124  /// and calculates its gradient.
125  typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::FirstOrderDerivative & derivative ) const {
126  ++this->m_evaluationCounter;
127  SHARK_RUNTIME_CHECK(this->m_features.test(super::HAS_FIRST_DERIVATIVE), "[CombinedObjectiveFunction::evalDerivative] At least one of the objective functions combined is not differentiable");
128  typename super::FirstOrderDerivative der;
129  std::size_t ic = m_elements.size();
130  typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
131  derivative = m_weight[0] * der;
132  for (std::size_t i=1; i != ic; i++)
133  {
134  ret += m_weight[i] * m_elements[i]->evalDerivative(input, der);
135  derivative += m_weight[i] * der;
136  }
137  return ret;
138  }
139 
140  /// Evaluates the objective function
141  /// and calculates its gradient and
142  /// its Hessian.
143  typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::SecondOrderDerivative & derivative )const {
144  SHARK_RUNTIME_CHECK(this->m_features.test(super::HAS_SECOND_DERIVATIVE), "[CombinedObjectiveFunction::evalDerivative] At least one of the objective functions combined is not twice differentiable");
145  typename super::SecondOrderDerivative der;
146  std::size_t ic = m_elements.size();
147  typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
148  derivative.gradient = m_weight[0] * der.gradient;
149  derivative.hessian = m_weight[0] * der.hessian;
150  for (std::size_t i=1; i<ic; i++)
151  {
152  ret += m_weight[i] * m_elements[i]->evalDerivative(input, der);
153  derivative.gradient += m_weight[i] * der.gradient;
154  derivative.hessian += m_weight[i] * der.hessian;
155  }
156  return ret;
157  }
158 
159 protected:
160  /// list of weights
161  std::vector<double> m_weight;
162 
163  /// list of "base" objective functions
164  std::vector<element*> m_elements;
165 };
166 
167 
168 }
169 #endif // SHARK_CORE_COBINEDOBJECTIVEFUNCTION_H