00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "stdafx.h"
00021
00022 #include <iostream>
00023
00024 #include "gul_types.h"
00025 #include "gul_matrix.h"
00026 #include "guma_lineq.h"
00027 #include "guma_newton.h"
00028
00029
00030 namespace guma {
00031
00032 using gul::Ptr;
00033 using gul::rtr;
00034 using gul::Max;
00035 using gul::MCopy;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 template< class T >
00050 bool LinearSearch(
00051 const Ptr<T>& p,
00052 const Ptr<T>& xold,
00053 T fold,
00054 const Ptr<T>& g,
00055 const Ptr<T>& x1,
00056 const Ptr<T>& x2,
00057 newton_info<T>& I,
00058
00059 bool& found,
00060 bool& check,
00061
00062 Ptr<T>& x,
00063 T *fx
00064 )
00065 {
00066 T sum, slope, test, temp, alamin, alam, alphamin, alpha, stpmax;
00067 T a, b, alam2, disc, f2, fold2, rhs1, rhs2, tmplam;
00068 int i, n;
00069 T f;
00070
00071 found = false;
00072 n = I.dim;
00073
00074
00075
00076 alphamin = 1.0;
00077
00078 for( i = 0; i < n; i++ )
00079 {
00080 if( xold[i] + p[i] < x1[i] )
00081 alpha = (x1[i] - xold[i]) / p[i];
00082 else if( xold[i] + p[i] > x2[i] )
00083 alpha = (x2[i] - xold[i]) / p[i];
00084 else
00085 alpha = 1.0;
00086
00087 if( rtr<T>::fabs(alpha) == 0.0 )
00088 {
00089 p[i] = 0.0;
00090 alpha = 1.0;
00091 }
00092
00093 if( alpha < alphamin )
00094 alphamin = alpha;
00095 }
00096
00097 for( sum = 0.0, i = 0; i < n; i++ )
00098 sum += p[i] * p[i];
00099
00100 stpmax = rtr<T>::fabs(alphamin) * rtr<T>::sqrt(sum);
00101
00102
00103
00104 for( sum = 0.0, i = 0; i < n; i++ )
00105 sum += p[i] * p[i];
00106 sum = rtr<T>::sqrt( sum );
00107
00108 if( sum > stpmax )
00109 for( i = 0; i < n; i++ )
00110 p[i] *= stpmax / sum;
00111
00112 for( slope = 0.0, i = 0; i < n; i++ )
00113 slope += g[i] * p[i];
00114
00115 test = 0.0;
00116
00117 for( i = 0; i < n; i++ )
00118 {
00119 temp = rtr<T>::fabs(p[i]) / Max(rtr<T>::fabs(xold[i]),(T)1);
00120 if( temp > test ) test = temp;
00121 }
00122 if( test == (T)0 ) test = rtr<T>::tiny();
00123
00124 alamin = I.tolx / test;
00125 alam = (T)1;
00126
00127 for( ;; )
00128 {
00129 for( i = 0; i < n; i++ )
00130 {
00131 x[i] = xold[i] + alam * p[i];
00132
00133 if( x[i] < x1[i] ) x[i] = x1[i];
00134 else if( x[i] > x2[i] ) x[i] = x2[i];
00135 }
00136
00137 found = I.calcf( x, &f );
00138 if( found ) { check = false; break; }
00139
00140 if( alam < alamin )
00141 {
00142 for( i = 0; i < n; i++ )
00143 x[i] = xold[i];
00144 check = true;
00145 break;
00146 }
00147
00148 if( f <= fold + I.alf * alam * slope )
00149 { check = false; break; }
00150
00151 if( alam == (T)1 )
00152 tmplam = -slope / ((T)2 * (f-fold-slope));
00153 else
00154 {
00155 rhs1 = f - fold - alam * slope;
00156 rhs2 = f2 - fold2 - alam2 * slope;
00157 a = (rhs1/(alam*alam) - rhs2/(alam2*alam2)) / (alam-alam2);
00158 b = (-alam2*rhs1/(alam*alam) + alam*rhs2/(alam2*alam2)) / (alam-alam2);
00159
00160 if( a == (T)0 )
00161 tmplam = -slope/((T)2*b);
00162 else
00163 {
00164 disc = b*b - (T)3*a*slope;
00165
00166 if( disc < (T)0 )
00167 return false;
00168
00169 tmplam = (-b + rtr<T>::sqrt(disc)) / ((T)3*a);
00170 }
00171
00172 if( tmplam > (T)0.5 * alam )
00173 tmplam = (T)0.5 * alam;
00174 }
00175
00176 alam2 = alam;
00177 f2 = f;
00178 fold2 = fold;
00179 alam = Max( tmplam, (T)0.1*alam );
00180 }
00181
00182 *fx = f;
00183 return true;
00184 }
00185
00186 template bool LinearSearch(
00187 const Ptr<float>& p,
00188 const Ptr<float>& xold,
00189 float fold,
00190 const Ptr<float>& g,
00191 const Ptr<float>& x1,
00192 const Ptr<float>& x2,
00193 newton_info<float>& I,
00194
00195 bool& found,
00196 bool& check,
00197
00198 Ptr<float>& x,
00199 float *fx
00200 );
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 template< class T >
00215 bool Newton(
00216 Ptr<T>& x,
00217 const Ptr<T>& x1,
00218 const Ptr<T>& x2,
00219 newton_info<T>& I,
00220 int maxits )
00221 {
00222 int its, i, j, n;
00223 T f, fold, sum, temp, test;
00224 bool result, found, check;
00225 Ptr<int> indx;
00226 Ptr<T> g,p,xold;
00227 Ptr< Ptr<T> > A;
00228 int sign;
00229
00230 n = I.dim;
00231
00232 A.reserve_pool(n);
00233 for( i = 0; i < n; i++ )
00234 A[i].reserve_pool(n);
00235
00236 indx.reserve_pool(n);
00237 g.reserve_pool(n);
00238 p.reserve_pool(n);
00239 xold.reserve_pool(n);
00240
00241
00242
00243 found = I.calcf( x, &f );
00244 if( found ) { return true; }
00245
00246 for( its = 1; its < maxits; its++ )
00247 {
00248 for( i = 0; i < n; i++ )
00249 {
00250 for( sum = 0.0, j = 0; j < n; j++ )
00251 sum += I.fvec[j] * I.fjac[j][i];
00252 g[i] = sum;
00253 }
00254
00255 for( i = 0; i < n; i++ )
00256 xold[i] = x[i];
00257 fold = f;
00258
00259 for( i = 0; i < n; i++ )
00260 p[i] = -I.fvec[i];
00261
00262 MCopy(n,n,I.fjac,A);
00263 result = LUDecomposition( n, A, &sign, indx );
00264 if( !result ) return(false);
00265 LUBackSubstitution( n, indx, A, p );
00266
00267
00268
00269 result = LinearSearch( p, xold, fold, g, x1, x2, I, found, check, x, &f );
00270
00271 if( !result ) return false;
00272
00273
00274
00275
00276
00277
00278 if( found ) { return true; }
00279
00280 test = 0.0;
00281 for( i = 0; i < n; i++ )
00282 {
00283 temp = (rtr<T>::fabs(x[i]-xold[i])) / Max(rtr<T>::fabs(x[i]),(T)1);
00284 if( temp > test ) test = temp;
00285 }
00286 if( test < I.tolx ) return true;
00287 }
00288
00289
00290 return false;
00291 }
00292
00293 template bool Newton(
00294 Ptr<float>& x,
00295 const Ptr<float>& x1,
00296 const Ptr<float>& x2,
00297 newton_info<float>& I,
00298 int maxits );
00299 template bool Newton(
00300 Ptr<double>& x,
00301 const Ptr<double>& x1,
00302 const Ptr<double>& x2,
00303 newton_info<double>& I,
00304 int maxits );
00305
00306
00307
00308
00309
00310
00311
00312 #if 0
00313
00314 *******************************************************************
00315 old version
00316 *******************************************************************
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 template< class T >
00333 bool Newton(
00334 Ptr<T>& x,
00335 const Ptr<T>& x1,
00336 const Ptr<T>& x2,
00337 newton_info<T>& I,
00338 int maxits,
00339 bool& check
00340 )
00341 {
00342 T a;
00343 int its, i, j, n;
00344 T den, f, fold, stpmax, sum, temp, test;
00345 T alpha, alphamin;
00346 bool result;
00347 Ptr<int> indx;
00348 Ptr<T> g,p,xold;
00349 Ptr< Ptr<T> > A;
00350 int sign;
00351
00352 n = I.dim;
00353
00354 A.reserve_pool(n);
00355 for( i = 0; i < n; i++ )
00356 A[i].reserve_pool(n);
00357
00358 indx.reserve_pool(n);
00359 g.reserve_pool(n);
00360 p.reserve_pool(n);
00361 xold.reserve_pool(n);
00362
00363 f = I.calcf( x );
00364
00365 for( test = (T)0, i = 0; i < n; i++ )
00366 {
00367 a = rtr<T>::fabs(I.fvec[i]);
00368 if( a > test ) test = a;
00369 }
00370 if( test < (T)0.01 * I.tolf )
00371 {
00372 check = false;
00373 return true;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 for( its = 1; its < maxits; its++ )
00387 {
00388 I.Fjac( x );
00389
00390 for( i = 0; i < n; i++ )
00391 {
00392 for( sum = 0.0, j = 0; j < n; j++ )
00393 sum += I.fvec[j] * I.fjac[j][i];
00394 g[i] = sum;
00395 }
00396
00397 for( i = 0; i < n; i++ )
00398 xold[i] = x[i];
00399 fold = f;
00400
00401 for( i = 0; i < n; i++ )
00402 p[i] = -I.fvec[i];
00403
00404 MCopy(n,n,I.fjac,A);
00405 result = LUDecomposition( n, A, &sign, indx );
00406 if( !result ) return(false);
00407 LUBackSubstitution( n, indx, A, p );
00408
00409
00410
00411 alphamin = 1.0;
00412
00413 for( i = 0; i < n; i++ )
00414 {
00415 if( xold[i] + p[i] < x1[i] )
00416 alpha = (x1[i] - xold[i]) / p[i];
00417 else if( xold[i] + p[i] > x2[i] )
00418 alpha = (x2[i] - xold[i]) / p[i];
00419 else
00420 alpha = 1.0;
00421
00422 if( rtr<T>::fabs(alpha) == 0.0 )
00423 {
00424 p[i] = 0.0;
00425 alpha = 1.0;
00426 }
00427
00428 if( alpha < alphamin )
00429 alphamin = alpha;
00430 }
00431
00432 for( sum = 0.0, i = 0; i < n; i++ )
00433 sum += p[i] * p[i];
00434
00435 stpmax = rtr<T>::fabs(alphamin) * rtr<T>::sqrt(sum);
00436
00437
00438
00439 result = LinearSearch( p, xold, fold, g, stpmax, I, check, x, &f );
00440 if( !result ) return false;
00441
00442 for( i = 0; i < n; i++ )
00443 {
00444 if( x[i] < x1[i] )
00445 x[i] = x1[i];
00446 else if( x[i] > x2[i] )
00447 x[i] = x2[i];
00448 }
00449
00450 for( test = 0.0, i = 0; i < n; i++ )
00451 if( fabs(I.fvec[i]) > test )
00452 test = rtr<T>::fabs(I.fvec[i]);
00453 if( test < 0.01 * I.tolf )
00454 {
00455 check = false;
00456 return true;
00457 }
00458
00459 if( check )
00460 {
00461 test = 0.0;
00462 den = Max( f, (T)0.5*(T)n );
00463
00464 for( i = 0; i < n; i++ )
00465 {
00466 temp = rtr<T>::fabs(g[i])*Max(rtr<T>::fabs(x[i]), (T)1) / den;
00467 if( temp > test ) test = temp;
00468 }
00469 check = (test < I.tolmin ? true : false);
00470 return true;
00471 }
00472
00473 test = 0.0;
00474 for( i = 0; i < n; i++ )
00475 {
00476 temp = (rtr<T>::fabs(x[i]-xold[i])) / Max(rtr<T>::fabs(x[i]),(T)1);
00477 if( temp > test ) test = temp;
00478 }
00479 if( test < I.tolx ) return true;
00480 }
00481
00482
00483 return false;
00484 }
00485
00486 template bool Newton(
00487 Ptr<float>& x,
00488 const Ptr<float>& x1,
00489 const Ptr<float>& x2,
00490 newton_info<float>& I,
00491 int maxits );
00492 #endif
00493
00494
00495
00496 }
00497
00498
00499
00500
00501
00502
00503
00504