TooN 2.1
optimization/golden_section.h
00001 #ifndef TOON_GOLDEN_SECTION_H
00002 #define TOON_GOLDEN_SECTION_H
00003 #include <TooN/TooN.h>
00004 #include <limits>
00005 #include <cmath>
00006 #include <cstdlib>
00007 #include <iomanip>
00008 
00009 namespace TooN
00010 {
00011     using std::numeric_limits;
00012 
00013     /// golden_section_search performs a golden section search line minimization
00014     /// on the functor provided. The inputs a, b, c must bracket the minimum, and
00015     /// must be in order, so  that \f$ a < b < c \f$ and \f$ f(a) > f(b) < f(c) \f$.
00016     /// @param a The most negative point along the line.
00017     /// @param b The central point.
00018     /// @param fb The value of the function at the central point (\f$b\f$).
00019     /// @param c The most positive point along the line.
00020     /// @param func The functor to minimize
00021     /// @param maxiterations  Maximum number of iterations
00022     /// @param tol Tolerance at which the search should be stopped.
00023     /// @return The minima position is returned as the first element of the vector,
00024     ///         and the minimal value as the second element.
00025     /// @ingroup gOptimize
00026     template<class Functor, class Precision> Vector<2, Precision> golden_section_search(Precision a, Precision b, Precision c, Precision fb, const Functor& func, int maxiterations, Precision tol = sqrt(numeric_limits<Precision>::epsilon()))
00027     {
00028         using std::abs;
00029         //The golden ratio:
00030         const Precision g = (3.0 - sqrt(5))/2;
00031 
00032         Precision x1, x2, fx1, fx2;
00033 
00034         //Perform an initial iteration, to get a 4 point
00035         //bracketing. This is rather more convenient than
00036         //a 3 point bracketing.
00037         if(abs(b-a) > abs(c-b))
00038         {
00039             x1 = b - g*(b-a);
00040             x2 = b;
00041 
00042             fx1 = func(x1);
00043             fx2 = fb;
00044         }
00045         else
00046         {
00047             x2 = b + g * (c-b);
00048             x1 = b;
00049 
00050             fx1 = fb;
00051             fx2 = func(x2);
00052         }
00053 
00054         //We now have an ordered list of points a x1 x2 c
00055 
00056         //Termination condition from NR in C
00057         int itnum = 1; //We've already done one iteration.
00058         while(abs(c-a) > tol * (abs(x2)+abs(x1)) && itnum < maxiterations)
00059         {
00060             if(fx1 > fx2)
00061             {
00062                 // Bracketing does:
00063                 // a     x1     x2     c
00064                 //        a     x1  x2 c
00065                 a = x1;
00066                 x1 = x2;
00067                 x2 = x1 + g * (c-x1);
00068                 
00069                 fx1 = fx2;
00070                 fx2 = func(x2);
00071             }
00072             else
00073             {
00074                 // Bracketing does:
00075                 // a     x1     x2     c
00076                 // a  x1 x2     c
00077                 c = x2;
00078                 x2 = x1;
00079                 x1= x2 - g * (x2 - a);
00080                 
00081                 fx2 = fx1;
00082                 fx1 = func(x1);
00083             }
00084         }
00085 
00086         
00087         if(fx1 < fx2)
00088             return makeVector<Precision>(x1, fx1);
00089         else
00090             return makeVector<Precision>(x2, fx2);
00091     }
00092 
00093     /// golden_section_search performs a golden section search line minimization
00094     /// on the functor provided. The inputs a, b, c must bracket the minimum, and
00095     /// must be in order, so  that \f$ a < b < c \f$ and \f$ f(a) > f(b) < f(c) \f$.
00096     /// @param a The most negative point along the line.
00097     /// @param b The central point.
00098     /// @param c The most positive point along the line.
00099     /// @param func The functor to minimize
00100     /// @param maxiterations  Maximum number of iterations
00101     /// @param tol Tolerance at which the search should be stopped.
00102     /// @return The minima position is returned as the first element of the vector,
00103     ///         and the minimal value as the second element.
00104     /// @ingroup gOptimize
00105     template<class Functor, class Precision> Vector<2, Precision> golden_section_search(Precision a, Precision b, Precision c, const Functor& func, int maxiterations, Precision tol = sqrt(numeric_limits<Precision>::epsilon()))
00106     {
00107         return golden_section_search(a, b, c, func(b), func, maxiterations, tol);
00108     }
00109 
00110 }
00111 #endif