//===========================================================================
/*!
*
*
* \brief Generalized Rosenbrock benchmark function
*
* This non-convex benchmark function for real-valued optimization is
* a generalization from two to multiple dimensions of a classic
* function first proposed in:
*
* H. H. Rosenbrock. An automatic method for finding the greatest or
* least value of a function. The Computer Journal 3: 175-184, 1960
*
*
*
* \author -
* \date -
*
*
* \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_BENCHMARK_ROSENBROCK_H
#define SHARK_OBJECTIVEFUNCTIONS_BENCHMARK_ROSENBROCK_H
#include
#include
namespace shark {
/*! \brief Generalized Rosenbrock benchmark function
*
* This non-convex benchmark function for real-valued optimization is a
* generalization from two to multiple dimensions of a classic
* function first proposed in:
*
* H. H. Rosenbrock. An automatic method for finding the greatest or
* least value of a function. The Computer Journal 3: 175-184,
* 1960
*/
struct Rosenbrock : public SingleObjectiveFunction {
/// \brief Constructs the problem
///
/// \param dimensions number of dimensions to optimize
/// \param initialSpread spread of the initial starting point
Rosenbrock(std::size_t dimensions=23, double initialSpread = 1.0)
:m_numberOfVariables(dimensions), m_initialSpread(initialSpread) {
m_features|=CAN_PROPOSE_STARTING_POINT;
m_features|=HAS_FIRST_DERIVATIVE;
m_features|=HAS_SECOND_DERIVATIVE;
}
/// \brief From INameable: return the class name.
std::string name() const
{ return "Rosenbrock"; }
std::size_t numberOfVariables()const{
return m_numberOfVariables;
}
bool hasScalableDimensionality()const{
return true;
}
void setNumberOfVariables( std::size_t numberOfVariables ){
m_numberOfVariables = numberOfVariables;
}
SearchPointType proposeStartingPoint() const {
RealVector x(numberOfVariables());
for (std::size_t i = 0; i < x.size(); i++) {
x(i) = random::uni(*mep_rng, 0, m_initialSpread );
}
return x;
}
double eval( const SearchPointType & p ) const {
m_evaluationCounter++;
double sum = 0;
for( std::size_t i = 0; i < p.size()-1; i++ ) {
sum += 100*sqr( p(i+1) - sqr( p( i ) ) ) +sqr( 1. - p( i ) );
}
return( sum );
}
virtual ResultType evalDerivative( const SearchPointType & p, FirstOrderDerivative & derivative )const {
double result = eval(p);
size_t size = p.size();
derivative.resize(size);
derivative(0) = 2*( p(0) - 1 ) - 400 * ( p(1) - sqr( p(0) ) ) * p(0);
derivative(size-1) = 200 * ( p(size - 1) - sqr( p( size - 2 ) ) ) ;
for(size_t i=1; i != size-1; ++i){
derivative( i ) = 2 * ( p(i) - 1 ) - 400 * (p(i+1) - sqr( p(i) ) ) * p( i )+200 * ( p( i )- sqr( p(i-1) ) );
}
return result;
}
virtual ResultType evalDerivative( const SearchPointType & p, SecondOrderDerivative & derivative )const {
double result = eval(p);
size_t size = p.size();
derivative.gradient.resize(size);
derivative.hessian.resize(size,size);
derivative.hessian.clear();
derivative.gradient(0) = 2*( p(0) - 1 ) - 400 * ( p(1) - sqr( p(0) ) ) * p(0);
derivative.gradient(size-1) = 200 * ( p(size - 1) - sqr( p( size - 2 ) ) ) ;
derivative.hessian(0,0) = 2 - 400* (p(1) - 3*sqr(p(0))) ;
derivative.hessian(0,1) = -400 * p(0) ;
derivative.hessian(size-1,size-1) = 200;
derivative.hessian(size-1,size-2) = -400 * p( size - 2 );
for(size_t i=1; i != size-1; ++i){
derivative.gradient( i ) = 2 * ( p(i) - 1 ) - 400 * (p(i+1) - sqr( p(i) ) ) * p( i )+200 * ( p( i )- sqr( p(i-1) ) );
derivative.hessian(i,i) = 202 - 400 * ( p(i+1) - 3 * sqr(p(i)));
derivative.hessian(i,i+1) = - 400 * ( p(i) );
derivative.hessian(i,i-1) = - 400 * ( p(i-1) );
}
return result;
}
private:
std::size_t m_numberOfVariables;
double m_initialSpread;
};
}
#endif