/home/coin/SVN-release/OS-2.4.2/Couenne/src/convex/operators/powNewton.cpp

Go to the documentation of this file.
00001 /* $Id: powNewton.cpp 490 2011-01-14 16:07:12Z pbelotti $
00002  *
00003  * Name:    powNewton.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: numerically find tangents to power functions
00006  *
00007  * (C) Carnegie-Mellon University, 2006-07.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include <math.h>
00012 
00013 #include "CouenneTypes.hpp"
00014 
00015 #define MAX_ITER 10
00016 #define COU_POW_TOLERANCE 1e-12
00017 
00018 //#define DEBUG_POWNEW
00019 
00020 #ifndef DEBUG_POWNEW
00021 #include "CouenneFunTriplets.hpp"
00022 #else
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #endif
00026 
00027 namespace Couenne {
00028 
00029 CouNumber powNewton (CouNumber xc, CouNumber yc, 
00030                      unary_function f, 
00031                      unary_function fp, 
00032                      unary_function fpp) {
00033 
00034   // Find a zero to the function
00035   //
00036   // F(x) = x - xc + f'(x) (f(x) - yc)
00037   //
00038   // where f(x) is either x^k, exp(x), or log(x).
00039   // The derivative of F(x) is
00040   //
00041   // F'(x) = 1 + f''(x) (f(x) - yc) + (f'(x))^2
00042   //
00043   // Apply usual update:
00044   //
00045   // x(k+1) = x(k) - F(x(k))/F'(x(k))
00046 
00047   register CouNumber xk = xc;
00048 
00049   CouNumber fk  = f (xk) - yc,
00050             fpk = fp (xk),
00051             F   = fpk * fk,
00052             Fp  = 1 + fpp (xk) * fk + fpk * fpk;
00053 
00054   // Newton loop. Tolerance is set above
00055   for (int k = MAX_ITER; k--;) {
00056 
00057     xk -= F / Fp;
00058 
00059     fk  = f (xk) - yc;
00060     fpk = fp (xk);
00061     F   = xk - xc + fpk * fk;
00062 
00063     //    printf ("xk = %g; F = %g, fk = %g, fpk = %g\n", xk, F, fk, fpk);
00064 
00065     if (fabs (F) < COU_POW_TOLERANCE) break;
00066     Fp  = 1 + fpp (xk) * fk + fpk * fpk;
00067   }
00068 
00069   return xk;
00070 }
00071 
00072 #ifndef DEBUG_POWNEW
00073 
00075 CouNumber powNewton (CouNumber xc, CouNumber yc, funtriplet *tri) {
00076 
00077   // Find a zero to the function
00078   //
00079   // F(x) = x - xc + f'(x) (f(x) - yc)
00080   //
00081   // where f(x) is either x^k, exp(x), or log(x).
00082   // The derivative of F(x) is
00083   //
00084   // F'(x) = 1 + f''(x) (f(x) - yc) + (f'(x))^2
00085   //
00086   // Apply usual update:
00087   //
00088   // x(k+1) = x(k) - f(x(k))/f'(x(k))
00089 
00090   register CouNumber xk = xc;
00091 
00092   CouNumber fk  = tri -> F (xk) - yc,
00093             fpk = tri -> Fp (xk),
00094             F   = fpk * fk,
00095             Fp  = 1 + tri -> Fpp (xk) * fk + fpk * fpk;
00096 
00097   // Newton loop. Tolerance is set above
00098   for (int k = MAX_ITER; k--;) {
00099 
00100     xk -= F / Fp;
00101 
00102     fk  = tri -> F (xk) - yc;
00103     fpk = tri -> Fp (xk);
00104     F   = xk - xc + fpk * fk;
00105     if (fabs (F) < COU_POW_TOLERANCE) break;
00106     Fp  = 1 + tri -> Fpp (xk) * fk + fpk * fpk;
00107   }
00108 
00109   return xk;
00110 }
00111 #else
00112 
00114 inline CouNumber inv (register CouNumber arg) 
00115 {return 1.0 / arg;}
00116 
00117 
00119 inline CouNumber oppInvSqr (register CouNumber x) 
00120 {return (- inv (x*x));}
00121 
00122 
00124 inline CouNumber inv_dblprime (register CouNumber x) 
00125 {return (2 * inv (x*x*x));}
00126 
00127 
00128 int main (int argc, char **argv) {
00129 
00130   CouNumber r, 
00131     xc = atof (argv [2]),
00132     yc = atof (argv [3]);
00133 
00134   unary_function 
00135     f   = log,
00136     fp  = inv,
00137     fpp = oppInvSqr;
00138 
00139   //expon = atof (argv [1]);
00140 
00141   for (register int i=1; i--;)
00142     r = powNewton (xc, yc, f, fp, fpp);
00143 
00144   printf ("xc = %.14f: xk = %.15f, slope %.15f -- %.15f ==> [%.15f = -1?]\n", 
00145           xc, r, fp (r), 
00146                    (yc - f (r)) / (xc - r), 
00147           fp (r) * (yc - f (r)) / (xc - r));
00148 
00149   return 0;
00150 }
00151 
00152 #endif
00153 
00154 }

Generated on Wed Nov 30 03:03:59 2011 by  doxygen 1.4.7