//===========================================================================
/*!
*
*
* \brief CombinedObjectiveFunction
*
*
*
* \author T.Voss, T. Glasmachers, O.Krause
* \date 2010-2011
*
*
* \par Copyright 1995-2017 Shark Development Team
*
*
* This file is part of Shark.
*
*
* Shark is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Shark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Shark. If not, see .
*
*/
//===========================================================================
#ifndef SHARK_OBJECTIVEFUNCTIONS_COMBINEDOBJECTIVEFUNCTION_H
#define SHARK_OBJECTIVEFUNCTIONS_COMBINEDOBJECTIVEFUNCTION_H
#include
namespace shark {
///
/// \brief Linear combination of objective functions
///
/// \par
/// The CombinedObjectiveFunction is a linear combination of
/// objective functions. It assumed that the result type is
/// capable of forming linear combinations with real coefficients.
///
template
class CombinedObjectiveFunction : public AbstractObjectiveFunction
{
public:
typedef AbstractObjectiveFunction super;
typedef AbstractObjectiveFunction element;
/// Constructor
CombinedObjectiveFunction(){
this->m_features|=super::HAS_FIRST_DERIVATIVE;
this->m_features|=super::HAS_SECOND_DERIVATIVE;
}
/// \brief From INameable: return the class name.
std::string name() const
{ return "CombinedObjectiveFunction"; }
/// Adds a new objective function with a
/// weight of one to the linear combination.
void add(element& e){
add(1.0, e);
}
/// Adds a new objective function with
/// a weight to the linear combination.
void add(double weight, element& e)
{
SHARK_RUNTIME_CHECK(weight >= 0.0, "[CombinedObjectiveFunction::add] weight must be non-negative");
m_weight.push_back(weight);
m_elements.push_back(&e);
if (e.features().test(element::IS_CONSTRAINED_FEATURE)) this->m_features.set(super::IS_CONSTRAINED_FEATURE);
if (! e.features().test(element::HAS_FIRST_DERIVATIVE)) this->m_features.reset(super::HAS_FIRST_DERIVATIVE);
if (! e.features().test(element::HAS_SECOND_DERIVATIVE)) this->m_features.reset(super::HAS_SECOND_DERIVATIVE);
}
/// Tests whether a point in SearchSpace is feasible,
/// e.g., whether the constraints are fulfilled.
bool isFeasible( const typename super::SearchPointType & input) const {
std::size_t ic = m_elements.size();
for ( std::size_t i=0; iisFeasible(input))
return false;
return true;
}
void init(){
for ( std::size_t i=0; isetRng(this->mep_rng);
m_elements[i]->init();
}
}
std::size_t numberOfVariables()const{
//todo sthis will fail if SarchPointType != Vectorspace
return m_elements.size() == 0? 0: m_elements[0]->numberOfVariables();
}
/// Evaluates the objective function.
typename super::ResultType eval( const typename super::SearchPointType & input ) const
{
++this->m_evaluationCounter;
std::size_t ic = m_elements.size();
typename super::ResultType ret = m_weight[0] * m_elements[0]->eval(input);
for (std::size_t i=1; ieval(input);
return ret;
}
/// Evaluates the objective function
/// and calculates its gradient.
typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::FirstOrderDerivative & derivative ) const {
++this->m_evaluationCounter;
SHARK_RUNTIME_CHECK(this->m_features.test(super::HAS_FIRST_DERIVATIVE), "[CombinedObjectiveFunction::evalDerivative] At least one of the objective functions combined is not differentiable");
typename super::FirstOrderDerivative der;
std::size_t ic = m_elements.size();
typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
derivative = m_weight[0] * der;
for (std::size_t i=1; i != ic; i++)
{
ret += m_weight[i] * m_elements[i]->evalDerivative(input, der);
derivative += m_weight[i] * der;
}
return ret;
}
/// Evaluates the objective function
/// and calculates its gradient and
/// its Hessian.
typename super::ResultType evalDerivative( const typename super::SearchPointType & input, typename super::SecondOrderDerivative & derivative )const {
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");
typename super::SecondOrderDerivative der;
std::size_t ic = m_elements.size();
typename super::ResultType ret = m_weight[0] * m_elements[0]->evalDerivative(input, der);
derivative.gradient = m_weight[0] * der.gradient;
derivative.hessian = m_weight[0] * der.hessian;
for (std::size_t i=1; ievalDerivative(input, der);
derivative.gradient += m_weight[i] * der.gradient;
derivative.hessian += m_weight[i] * der.hessian;
}
return ret;
}
protected:
/// list of weights
std::vector m_weight;
/// list of "base" objective functions
std::vector m_elements;
};
}
#endif // SHARK_CORE_COBINEDOBJECTIVEFUNCTION_H