MPogoda

c++ powell method

Dec 3rd, 2012
475
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.10 KB | None | 0 0
  1. #include <array>
  2. #include <utility>
  3. #include <cassert>
  4.  
  5. typedef double qreal;
  6.  
  7. const
  8. std::pair< std::array< qreal, 3 >,
  9.            std::array< qreal, 3 > >
  10. sven_method( const std::function< qreal(qreal) >& f,
  11.              const qreal x0,
  12.              qreal delta )
  13. {
  14.     const qreal epsilon( 0.000001 );
  15.     assert (delta > 0);
  16.  
  17.     const qreal x_minus( x0 - delta );
  18.     const qreal x_plus( x0 + delta );
  19.     const qreal f_minus( f(x_minus) );
  20.     const qreal f_plus( f(x_plus) );
  21.  
  22.     qreal x_cur( x0 );
  23.     qreal f_cur( f(x_cur) );
  24.  
  25.     qreal x_prev;
  26.     qreal x_next;
  27.     qreal f_prev;
  28.     qreal f_next;
  29.  
  30.     if ((f_minus < f_cur + epsilon) && (f_cur + epsilon > f_plus))
  31.     {
  32.         //NON UNIMODAL
  33.         assert (false);
  34.     } else if (f_minus + epsilon > f_cur)
  35.     {
  36.         x_prev = x_minus; f_prev = f_minus;
  37.         x_next = x_plus;  f_next = f_plus;
  38.     } else // f_minus < f_cur
  39.     {
  40.         // change direction
  41.         delta *= -1.0;
  42.         x_prev = x_plus;  f_prev = f_plus;
  43.         x_next = x_minus; f_next = f_minus;
  44.     }
  45.  
  46.     while (f_cur + epsilon > f_next)
  47.     {
  48.         x_prev = x_cur;  f_prev = f_cur;
  49.         x_cur  = x_next; f_cur  = f_next;
  50.  
  51.         delta *= 2.0;
  52.         x_next += delta;
  53.         f_next = f(x_next);
  54.     }
  55.  
  56.     qreal x_mid = 0.5 * (x_cur + x_next);
  57.     qreal f_mid = f(x_mid);
  58.  
  59.     if (f_mid < f_cur + epsilon)
  60.     {
  61.         x_prev = x_cur; f_prev = f_cur;
  62.         x_cur  = x_mid; f_cur  = f_mid;
  63.     } else
  64.     {
  65.         x_next = x_mid; f_next = f_mid;
  66.     }
  67.  
  68.     if (delta < 0)
  69.     {
  70.         std::swap(x_prev, x_next);
  71.         std::swap(f_prev, f_next);
  72.     }
  73.  
  74.     const std::array< qreal, 3 > xs = { x_prev, x_cur, x_next };
  75.     const std::array< qreal, 3 > fs = { f_prev, f_cur, f_next };
  76.  
  77.     return std::make_pair( xs, fs);
  78. }
  79.  
  80. const
  81. std::pair< qreal, qreal >
  82. dsk_powell_method(const std::function< qreal(qreal) >& f,
  83.                   qreal x0,
  84.                   const qreal delta,
  85.                   const std::pair< qreal, qreal >& epsilon)
  86. {
  87.     const std::pair<
  88.             std::array< qreal, 3 >,
  89.             std::array< qreal, 3> > sven_result( sven_method(f, x0, delta) );
  90.  
  91.     qreal x_1( sven_result.first[0] );
  92.     qreal x_2( sven_result.first[1] );
  93.     qreal x_3( sven_result.first[2] );
  94.     qreal f_1( sven_result.second[0] );
  95.     qreal f_2( sven_result.second[1] );
  96.     qreal f_3( sven_result.second[2] );
  97.  
  98.     qreal x_ast( x_2 + delta * (f_1 - f_3) / (2.0 * (f_1 - 2.0 * f_2 + f_3)) );
  99.     qreal f_ast( f(x_ast) );
  100.  
  101.     while ((qAbs(f_ast - f_2) > epsilon.second) || (qAbs(x_ast - x_2) > epsilon.first))
  102.     {
  103.         if (f_ast < f_2)
  104.         {
  105.             if (x_ast < x_2)
  106.             {
  107.                 x_3 = x_2; f_3 = f_2;
  108.             } else
  109.             {
  110.                 x_1 = x_2; f_1 = f_2;
  111.             }
  112.  
  113.             x_2 = x_ast; f_2 = f_ast;
  114.         } else
  115.         {
  116.             if (x_ast < x_2)
  117.             {
  118.                 x_1 = x_ast; f_1 = f_ast;
  119.             } else
  120.             {
  121.                 x_3 = x_ast; f_3 = f_ast;
  122.             }
  123.         }
  124.  
  125.         const qreal a_1( (f_2 - f_1) / (x_2 - x_1) );
  126.         const qreal a_2( ((f_3 - f_1)/(x_3 - x_1) - a_1)/(x_3 - x_2) );
  127.  
  128.         x_ast = 0.5 * (x_1 + x_2) - a_1 / (2 * a_2);
  129.         f_ast = f(x_ast);
  130.     }
  131.  
  132.     if (f_ast < f_2)
  133.         return std::make_pair(x_ast, f_ast);
  134.     else
  135.         return std::make_pair(x_2, f_2);
  136. }
  137.  
  138. template< std::size_t N >
  139. const std::array< qreal, N >
  140. wrap_s( std::array< qreal, N > x,
  141.         const qreal lambda,
  142.         const std::array< qreal, N >& s)
  143. {
  144.     for (auto i( 0 ); N != i; ++i)
  145.         x[i] += lambda * s[i];
  146.  
  147.     return x;
  148. }
  149.  
  150. template< std::size_t N >
  151. const qreal
  152. vecAbs( std::array< qreal, N > a,
  153.         std::array< qreal, N > b)
  154. {
  155.     qreal result( 0.0 );
  156.     for (auto i( 0 ); N != i; ++i)
  157.         result += qPow((a[i] - b[i]), 2);
  158.  
  159.     return qSqrt(result);
  160. }
  161.  
  162. template< std::size_t N >
  163. const std::pair< std::array< qreal, N >,
  164.            qreal >
  165. powell_method(std::function< qreal(std::array< qreal, N >) > f,
  166.               const std::array< qreal, N >& x0,
  167.               const qreal delta,
  168.               const std::pair< qreal, qreal>& epsilon)
  169. {
  170.     std::array< std::array< qreal, N >, N > S;
  171.  
  172.     for (auto i( 0 ); N != i; ++i)
  173.         for (auto j( 0 ); N != j; ++j)
  174.             if (i != j)
  175.                 S[i][j] = 0.0;
  176.             else
  177.                 S[i][i] = 1.0;
  178.  
  179.     print_s(S);
  180.  
  181.     std::array< qreal, N > x( x0 );
  182.     print_x(x);
  183.     qreal _f = f( x );
  184.  
  185.     forever
  186.     {
  187.         std::size_t k( N - 1);
  188.         std::array< qreal, N > x_before;
  189.         qreal f_before;
  190.         do
  191.         {
  192.             const std::array< qreal, N >& s = S[k];
  193.             const std::function< qreal(qreal) > g = [&f, &x, &s](qreal lambda)
  194.             {
  195.                 return f( wrap_s(x, lambda, s ));
  196.             };
  197.  
  198.             std::pair< qreal, qreal > dskp_result( dsk_powell_method(g,
  199.                                                                      0.0,
  200.                                                                      delta,
  201.                                                                      epsilon) );
  202.  
  203.             x = wrap_s( x, dskp_result.first, s);
  204.             _f = dskp_result.second;
  205.  
  206.             k = ++k % N;
  207.  
  208.             if (0 == k)
  209.             {
  210.                 x_before = x; f_before = _f;
  211.             }
  212.  
  213.         } while (N - 1 != k);
  214.  
  215.         for (auto i( 0 ); i < N - 1; ++i)
  216.             std::swap( S[i], S[i + 1]);
  217.         for (auto i( 0 ); i < N; ++i)
  218.             S.back()[i] = x[i] - x_before[i];
  219.  
  220.         if ((qAbs(f_before - _f) < epsilon.second) || (vecAbs(x, x_before) < epsilon.first))
  221.             return std::make_pair( x, _f);
  222.     }
  223. }
  224.  
  225.  
  226. int main(int argc, char** argv)
  227. {
  228.     std::function< qreal( std::array<qreal, 2>)> f = [](std::array< qreal, 2 > x)
  229.     {
  230.         return (x.front() - 1.0) * (x.front() - 1.0) + (x.back() - 2.0) * (x.back() - 2.0);
  231.     };
  232.  
  233.  
  234.     std::array< qreal, 2 > x0 = { 0.0, 0.0 };
  235.  
  236.     auto result =
  237.             powell_method(f, x0, 0.5, std::make_pair(0.01, 0.01));
  238. }
Advertisement
Add Comment
Please, Sign In to add comment