//=========================================================================== /*! * * * \brief Archive of evaluated points as an objective function wrapper. * * * \author T. Glasmachers * \date 2013 * * * \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_EVALUATIONARCHIVE_H #define SHARK_OBJECTIVEFUNCTIONS_EVALUATIONARCHIVE_H #include #include #include #include namespace shark { /// /// \brief Objective function wrapper storing all function evaluations. /// /// \tparam PointType The search space the function is defined upon. /// \tparam ResultT The objective space the function is defined upon. /// /// \par /// The EvaluationArchive class serves as an archive of all evaluated /// points and the corresponding result. It can be used transparently /// instead of the original objective function, e.g., by an optimizer. /// Point/result pairs are added to the archive only if the specific /// combination is not yet stored. /// /// \par /// For fast-to-evaluate objective functions the archive wrapper can /// be a considerable performance killer. However, whenever function /// evaluations are costly (and an archive makes sense) then the /// storage and maintenance overhead should be negligible. /// template class EvaluationArchive : public AbstractObjectiveFunction { public: typedef AbstractObjectiveFunction base_type; typedef typename base_type::SearchPointType SearchPointType; typedef typename base_type::ResultType ResultType; typedef typename base_type::FirstOrderDerivative FirstOrderDerivative; typedef typename base_type::SecondOrderDerivative SecondOrderDerivative; /// \brief Pair of point and result. class PointResultPairType { public: PointResultPairType(SearchPointType const& p, ResultType r) : point(p) , result(r) { } PointResultPairType(PointResultPairType const& other) : point(other.point) , result(other.result) { } // Comparison is based on string representation. // This is a hack, but it is quite generic. // And a generic solution is needed for std::set. bool operator == (PointResultPairType const& other) const { return (toString() == other.toString()); } bool operator < (PointResultPairType const& other) const { return (toString() < other.toString()); } SearchPointType point; ResultType result; private: std::string toString() const { std::stringstream ss; ss << point << " " << result; return ss.str(); } }; typedef std::set PointResultPairContainer; typedef typename PointResultPairContainer::iterator PointResultPairIterator; typedef typename PointResultPairContainer::const_iterator PointResultPairConstIterator; /// \brief Constructor. /// /// \par /// The constructor takes the objective function to be wrapped /// as an argument. It is assumed that the objective object's /// life time exceeds the life time of the present instance. EvaluationArchive(base_type* objective) : mep_objective(objective) { base_type::m_features = mep_objective->features(); base_type::m_constraintHandler = mep_objective->hasConstraintHandler() ? &mep_objective->getConstraintHandler() : NULL; } /// \brief Access to the underlying objective function. base_type* objective() { return mep_objective; } /// \brief Access to the underlying objective function. const base_type* objective() const { return mep_objective; } /// \brief Wrapper function. void init(){ mep_objective->setRng(this->mep_rng); mep_objective->init(); } /// \brief Wrapper function. virtual std::size_t numberOfObjectives() const { return mep_objective->numberOfObjectives(); } /// \brief Wrapper function. bool hasScalableObjectives() const { return mep_objective->hasScalableObjectives(); } /// \brief Wrapper function. void setNumberOfObjectives(std::size_t numberOfObjectives) { mep_objective->setNumberOfObjectives(numberOfObjectives); } /// \brief Wrapper function. bool isFeasible(const SearchPointType& input) const { return mep_objective->isFeasible(input); } /// \brief Wrapper function. void closestFeasible(SearchPointType& input) const { return mep_objective->closestFeasible(input); } /// \brief Wrapper function. void proposeStartingPoint(SearchPointType& startingPoint) const { return mep_objective->proposeStartingPoint(startingPoint); } /// \brief Wrapper function; conditional on vector space property. std::size_t numberOfVariables() const { return mep_objective->numberOfVariables(); } /// \brief Wrapper function storing point and result. ResultType eval(const SearchPointType& input) const { ResultType r = mep_objective->eval(input); base_type::m_evaluationCounter++; m_archive.insert(PointResultPairType(input, r)); return r; } // TG: Could someone enlighten me: why do I have to copy this // from the super class to make the compiler find the f**king // operator?? ResultType operator()( const SearchPointType & input ) const { return eval(input); } /// \brief Wrapper function storing point and result. ResultType evalDerivative(const SearchPointType& input, FirstOrderDerivative& derivative) const { ResultType r = mep_objective->evalDerivative(input, derivative); base_type::m_evaluationCounter++; m_archive.insert(PointResultPairType(input, r)); return r; } /// \brief Wrapper function storing point and result. ResultType evalDerivative(const SearchPointType& input, SecondOrderDerivative& derivative) const { ResultType r = mep_objective->evalDerivative(input, derivative); base_type::m_evaluationCounter++; m_archive.insert(PointResultPairType(input, r)); return r; } //////////////////////////////////////////////////////////// // access to the archive // /// Return the size of the archive; which is the number of point/result pairs. std::size_t size() const { return m_archive.size(); } /// Begin iterator to the point/result pairs. PointResultPairIterator begin() { return m_archive.begin(); } /// Begin iterator to the point/result pairs. PointResultPairConstIterator begin() const { return m_archive.begin(); } /// End iterator to the point/result pairs. PointResultPairIterator end() { return m_archive.end(); } /// End iterator to the point/result pairs. PointResultPairConstIterator end() const { return m_archive.end(); } private: base_type* mep_objective; ///< objective function to be wrapped mutable PointResultPairContainer m_archive; ///< evaluated point/result pairs }; }; #endif