00001 //=========================================================================== 00002 // GoTools - SINTEF Geometry Tools version 1.1 00003 // 00004 // GoTools module: CORE 00005 // 00006 // Copyright (C) 2000-2007 SINTEF ICT, Applied Mathematics, Norway. 00007 // 00008 // This program is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU General Public License 00010 // as published by the Free Software Foundation version 2 of the License. 00011 // 00012 // This program is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this program; if not, write to the Free Software 00019 // Foundation, Inc., 00020 // 59 Temple Place - Suite 330, 00021 // Boston, MA 02111-1307, USA. 00022 // 00023 // Contact information: E-mail: tor.dokken@sintef.no 00024 // SINTEF ICT, Department of Applied Mathematics, 00025 // P.O. Box 124 Blindern, 00026 // 0314 Oslo, Norway. 00027 // 00028 // Other licenses are also available for this software, notably licenses 00029 // for: 00030 // - Building commercial software. 00031 // - Building software whose source code you wish to keep private. 00032 //=========================================================================== 00033 #ifndef _GENERAL_FUNCTIONMINIMIZER_H 00034 #define _GENERAL_FUNCTIONMINIMIZER_H 00035 00036 #include "Point.h" 00037 #include <vector> 00038 #include <limits> 00039 00040 namespace Go { 00043 00044 00045 template<class Functor> class FunctionMinimizer; 00046 00047 00051 //=========================================================================== 00052 template<class Functor> 00053 void minimise_conjugated_gradient(FunctionMinimizer<Functor>& dfmin); 00054 //=========================================================================== 00055 00110 template<class Functor> 00111 class FunctionMinimizer 00112 { 00113 public: 00117 FunctionMinimizer(int num_param, const Functor& fun, 00118 const double* const seed, 00119 double tol = std::sqrt(std::numeric_limits<double>::epsilon())); 00120 00121 ~FunctionMinimizer() 00122 {} 00123 00130 double minimize(const Point& dir, bool& hit_domain_edge); 00131 00132 00147 double linminBrent(const Point& dir, 00148 const double* bracket, 00149 const double* fval_brak); 00150 00151 00153 inline double fval() const; 00154 00157 inline double fval(const Point& param) const; 00158 00161 inline void grad(Point& result) const; 00162 00165 inline void grad(const Point& param, Point& result) const; 00166 00169 inline void moveUV(const Point& dir, double multiplier); 00170 00173 bool atMin(int param_ix) const {return at_min_[param_ix];} 00174 bool atMax(int param_ix) const {return at_max_[param_ix];} 00175 00177 double getPar(int param_ix) const {return par_[param_ix];} 00178 00180 const double* getPar() const {return par_.begin();} 00181 00183 int numPars() const {return par_.size();} 00184 00185 private: 00186 const Functor fun_; 00187 00188 Point par_; 00189 std::vector<bool> at_min_; 00190 std::vector<bool> at_max_; 00191 00192 mutable bool cached_value_updated_; 00193 mutable bool cached_grad_updated_; 00194 00195 mutable double cached_value_; 00196 mutable Point cached_grad_; 00197 00198 const double minimization_tol_; 00199 std::vector<double> param_tol_; 00200 00201 static const double root_machine_precision_; 00202 static const double rel_tol_; 00203 static const double perturbation_; 00204 static const double golden_ratio_; 00205 static const double default_partition_; 00206 static const double tiny_; 00207 static const int max_iter_; 00208 00209 00210 // update at_umin_, at_umax_, at_vmin_ and at_vmax_. Should be called whenever the 00211 // current parameters ('cur_uv_') are changed. 00212 inline void checkBorder(); 00213 00214 // clear cached values. Should be called whenever the current parameters ('cur_uv_') 00215 // are changed. 00216 inline void resetCache() const; 00217 00218 // determine how far we are allowed to step from the current parameter point in a certain 00219 // direction ('dir') before going out of the valid parameter domain. 00220 double determineMaxSteplength(const Point& dir) const; 00221 00222 // Bracket the function minimum from the current parameter point along a certain 00223 // direction ('dir'). The maximum allowed steplength is given in 'max_step'. 00224 // Upon completion, two things might happen: 00225 // Possibility 1 : the function was able to bracket a minimum. The position of the 00226 // bracketing points (from current parameters, along 'dir') is 00227 // returned in 'bracket' (3 values), and the corresponding distance 00228 // function values are returned in fval_brak. The function returns 'true'. 00229 // Possibility 2 : the function hit the 'max_step' before it was able to bracket any 00230 // minimum. The function returns 'false'. 00231 bool bracketInterval(const Point& dir, 00232 const double max_step, 00233 //const double working_tolerance, 00234 double* bracket, // points to 3-array 00235 double* fval_brak); // points to 3-array 00236 00237 // given a direction 'dir', this function generates a direction 'result' that is a scaled 00238 // version of 'dir', with a possible sign change to make sure that the direction is 00239 // "downhill" (negative scalar product with function gradient). Returns 'true' on success, 00240 // and 'false' if the direction was practically perpendicular to the function gradient. 00241 bool orientDirection(const Point& dir, Point& result); 00242 00243 // Returns -1 if the scalar product of p1 and p2 is negative, +1 if the scalar product 00244 // is positive and 0 if it close to 0. In this case, 'close to 0' means that it is 00245 // impossible to judge the derivatives sign when taking into account the numerical 00246 // noise associated with the magnitude of the points' components. 00247 int scalarProductSign(const Point& p1, const Point& p2); 00248 00249 // Estimate the minimum of a parabola where two points and one tangent is known. The 00250 // two points are the current parameter point and the point obtained by marching from this 00251 // point a distance of 'dir' multiplied by 'p2'. The function value in this second point 00252 // must also be given by 'fp2'. The tangent known is the one for the current parameter 00253 // point. The abscissa for the minimum point of the parabola is returned. 00254 double parabolicEstimate(double p2, double fp2, const Point& dir); 00255 00256 // Estimate the minimum of a parabola where three points are known. If the minimum is found 00257 // to lie within the distance 'max_from_b' from b, the point is returned as 'u', and the 00258 // function returns 'true'. Otherwise, it returns 'false', and 'u' is not calculated. 00259 static bool parabolicFit(double a, double fa, 00260 double b, double fb, 00261 double c, double fc, 00262 double max_from_b, double&u); 00263 00264 // determine the smallest detectable change around the value 'c' 00265 static double numerical_tolerance(double c); 00266 00267 // Determine the numerical tolerance around a given point in a given direction 00268 static double numerical_tolerance(const Point& x, const Point& dir); 00269 00270 // Determine the numerical tolerance around a given point in a given direction, also 00271 // considering the change in function value (fx is the function at x, dfx is the derivative) 00272 static double numerical_tolerance(const Point& x, const Point& dir, 00273 const double fx, const double dfx); 00274 00275 00276 // A helper function for linminBrent. A new point has been evaluated (u, fu), and we must 00277 // update the other points used by the algorithm. 00278 static void adjustBrackets(double& a, double& fa, 00279 double& b, double& fb, 00280 double& c, double& fc, 00281 double& b2, double& fb2, 00282 double& b3, double& fb3, 00283 double u, double fu); 00284 00285 static void shift3(double& a, double& b, double& c, double d) 00286 { a = b; b = c; c = d;} 00287 static void shift2(double& a, double& b, double c) 00288 { a = b; b = c;} 00289 }; 00290 00292 }; // end namespace Go 00293 00294 #include "GeneralFunctionMinimizer_implementation.h" 00295 00296 #endif // _GENERAL_FUNCTIONMINIMIZER_H 00297 00298