//===========================================================================
/*!
*
*
* \brief AbstractOptimizer
*
*
*
* \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_ABSTRACTOPTIMIZER_H
#define SHARK_OBJECTIVEFUNCTIONS_ABSTRACTOPTIMIZER_H
#include
namespace shark {
/// \brief An optimizer that optimizes general objective functions
///
/// After construction and configurationg the optimizer, init() is called with the objective function
/// to be used. After that step() can be called until the required solution is found. The solution can be queried
/// using solution(). The type of the solution depends on the optimisation problem at hand.
/// It is allowed to add constrains on the features the objective function needs to offer
///
/// These are:
/// - REQUIRES_VALUE: The function is evaluated to use the optimizer and
/// the HAS_VALUE-flag must be set
/// - REQUIRES_FIRST_DERIVATIVE: The first derivative needs to be evaluated and
/// - HAS_FIRST_DERIVATIVE must be set
/// - REQUIRES_SECOND_DERIVATIVE: The second derivative needs to be evaluated and
/// - HAS_SECOND_DERIVATIVE must be set
/// - CAN_SOLVE_CONSTRAINED: The optimizer can solve functions which are constrained and
/// where the IS_CONSTRAINED_FEATURE is set.
/// - REQUIRES_CLOSEST_FEASIBLE: If the function is constrained, it must offer a way to
/// construct the closest feasible point and
/// - CAN_PROVIDE_CLOSEST_FEASIBLE must be set
///
/// Also when init() is called as offered by the AbstractOptimizer interface, the function
/// is required to have the CAN_PROPOSE_STARTING_POINT flag.
///
/// \tparam PointType The type of search space the optimizer works upon.
/// \tparam ResultT The objective space the optimizer works upon.
/// \tparam SolutionTypeT The type of the final solution.
template
class AbstractOptimizer : public INameable, public ISerializable {
public:
typedef PointType SearchPointType;
typedef ResultT ResultType;
typedef SolutionTypeT SolutionType;
typedef AbstractObjectiveFunction ObjectiveFunctionType;
/// \brief Models features that the optimizer requires from the objective function.
/// \sa AbstractObjectiveFunction
enum Feature {
REQUIRES_VALUE = 1,
REQUIRES_FIRST_DERIVATIVE = 2,
REQUIRES_SECOND_DERIVATIVE = 4,
CAN_SOLVE_CONSTRAINED = 8,
REQUIRES_CLOSEST_FEASIBLE = 16
};
SHARK_FEATURE_INTERFACE;
bool requiresValue()const{
return features()& REQUIRES_VALUE;
}
bool requiresFirstDerivative()const{
return features()& REQUIRES_FIRST_DERIVATIVE;
}
bool requiresSecondDerivative()const{
return features()& REQUIRES_SECOND_DERIVATIVE;
}
bool canSolveConstrained()const{
return features()& CAN_SOLVE_CONSTRAINED;
}
bool requiresClosestFeasible()const{
return features()& REQUIRES_CLOSEST_FEASIBLE;
}
virtual ~AbstractOptimizer() {}
/// \brief Returns the number of points this method requires for initialisation
///
/// The number of points supplied is allowed to be smaller, however in this case
/// the optimizer will resort to techniques generating additional points if needed.
virtual std::size_t numInitPoints() const = 0;
/// \brief Initialize the optimizer for the supplied objective function.
///
/// Be aware that function.init() has to be called before calling this function!
/// This function will initialize the algorithm with a number of points proposed
/// by the function. Note that this must fail if the function can not propose starting point(s).
///
/// \param [in] function The objective function to initialize for.
virtual void init( ObjectiveFunctionType const& function ){
SHARK_RUNTIME_CHECK(function.canProposeStartingPoint(), "Objective function does not propose a starting point");
std::vector initPoints(numInitPoints());
for(SearchPointType& point: initPoints){
point = function.proposeStartingPoint();
}
init(function,initPoints);
}
/// \brief Initialize the optimizer for the supplied objective function using a set of initialisation points
///
/// Most single objective algorithms only require a single point. However multi-objective algorithms
/// need a set of initialisation points. The number of points required should be numInitPoints().
/// Otherwise the algorithm might use heuristics to generate additional points if needed.
///
/// Be aware that function.init() has to be called before calling this function!
/// \param [in] function The objective function to initialize for.
/// \param [in] initPoints points used for initialisation. Should be at least numInitPoints().
virtual void init( ObjectiveFunctionType const& function, std::vector const& initPoints ) = 0;
/// \brief Carry out one step of the optimizer for the supplied objective function.
/// \param [in] function The objective function to initialize for.
virtual void step( ObjectiveFunctionType const& function ) = 0;
/// \brief Accesses the best solution obtained so far.
/// \return An immutable reference to the best solution obtained so far.
virtual SolutionType const& solution() const = 0; //mt_hint: try accessing this thing via solution().point and solution().value..
protected:
/// \brief Convenience function that checks whether the features of the supplied objective function match with the required features of the optimizer.
/// \param [in] objectiveFunction The function to match with.
/// \throws shark::Exception
void checkFeatures (ObjectiveFunctionType const& objectiveFunction){
//test whether the function can be evaluated
SHARK_RUNTIME_CHECK(!requiresValue() || objectiveFunction.hasValue(), name()+" Requires value of objective function");
//test first derivative
SHARK_RUNTIME_CHECK(!requiresFirstDerivative() || objectiveFunction.hasFirstDerivative(), name()+" Requires first derivative of objective function");
//test second derivative
SHARK_RUNTIME_CHECK(!requiresSecondDerivative() || objectiveFunction.hasSecondDerivative(), name()+" Requires second derivative of objective function");
//test for constraints
if(objectiveFunction.isConstrained()){
SHARK_RUNTIME_CHECK(canSolveConstrained(), name()+" Can not solve constrained problems");
SHARK_RUNTIME_CHECK(
!requiresClosestFeasible() || objectiveFunction.canProvideClosestFeasible(),
name()+" Requires closest feasible solution for solving constrained problems"
);
}
}
};
}
#endif // SHARK_CORE_ABSTRACTOPTIMIZER_H