0001 function [rRelStep, nFlag]=ls_pennon(obj, dir)
0002
0003
0004
0005
0006
0007 XTOL = 1.0E-1;
0008 ETA = 0.9;
0009
0010
0011
0012
0013 MAX_LS_ITER = obj.allopts.max_ls_iter;
0014
0015 xall0=obj.xall;
0016
0017 fx=obj.ALx;
0018
0019
0020 mu1 = 1.; mu2 = 1.; sml=0.5;
0021 alp0 = 0; alp1 = 0; alp2 = 0; alps = 0; alpm = 0; alpd = 0; omega1 = 0; omega2 = 0;
0022 stpmin = 0; stpmax = 1.0E20; alp = 1.; denom = 0.;
0023 FTOL = 1-ETA;
0024
0025
0026 lsiter=0;
0027 nEff = 0; iterations = 0;
0028 k = 0; ksh = 0; ier = 0;
0029 bLong = 0; bSafeguard = 0;
0030
0031 bLinesearch = 1;
0032
0033 rRelStep=0.; nFlag=99;
0034
0035
0036
0037
0038
0039
0040
0041 pi=dir'*obj.ALdx;
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 if (pi > 0)
0069 obj.print(3,Inf,'LS (pen): No Descent');
0070
0071 bLinesearch = 0;
0072 rRelStep=0;
0073 nFlag=1;
0074 return;
0075 elseif (abs(pi) < 1.0E-10)
0076 alp = 1.0;
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 if (abs(pi) < 1.0E-15)
0088 obj.ls_small_cnt=obj.ls_small_cnt+1;
0089 else
0090 obj.ls_small_cnt=0;
0091 end
0092
0093 if (obj.ls_small_cnt > 2)
0094
0095
0096
0097
0098 rRelStep=0.;
0099 nFlag=2;
0100 obj.print(3,Inf,'LS (pen): %.4e (almost not descent), no step', pi);
0101 else
0102 obj.xall = xall0 + alp*dir;
0103
0104 obj.eval_alx();
0105 obj.eval_aldx();
0106
0107
0108 obj.print(3,Inf,'LS (pen): %.4e (small full step)', pi);
0109 rRelStep=1.;
0110 nFlag=0;
0111 lsiter=lsiter+1;
0112 end
0113
0114 return;
0115
0116
0117 end
0118
0119 obj.ls_small_cnt=0;
0120
0121
0122
0123
0124
0125 if (FTOL <= 0)
0126 mu1s = 1./3.;
0127 mu2s = 2./3.;
0128 eff = 4./9.;
0129 else
0130 mu1s = min(FTOL,1/3);
0131 mu2s = 1-mu1s;
0132 eff = 2*mu1s*mu2s;
0133 end
0134
0135 if (XTOL >= 1.)
0136 kappa = 2.;
0137 else
0138 kappa = 1. / min(1.,1.-XTOL);
0139 end
0140
0141 f0 = obj.ALx; f1 = obj.ALx; f2 = obj.ALx; fbest = obj.ALx;
0142 pi0 = pi;
0143
0144
0145
0146
0147
0148 nFlag=3;
0149
0150 for iterations=1:MAX_LS_ITER
0151 ier = 0;
0152
0153
0154
0155
0156 obj.xall = xall0+alp*dir;
0157
0158
0159
0160
0161
0162 obj.eval_alx();
0163 f = obj.ALx;
0164 nEff = 0;
0165
0166
0167
0168
0169
0170
0171 k=k+1;
0172
0173
0174
0175 if (alp < stpmin || alp <= alp2)
0176
0177 obj.print(4,Inf,'LS (pen): ERROR: new step size too small');
0178 nEff = 0;
0179 ier = 1;
0180 break;
0181 elseif (alp > stpmax || (alp >= alp1 && alp1 > 0))
0182
0183 obj.print(4,Inf,'LS (pen): ERROR: new step size too large');
0184 nEff = 0;
0185 ier = 1;
0186 break;
0187 end
0188
0189
0190 if (f < fbest || (f == fbest && f == f0))
0191 fbest=f;
0192 if (f == f0 && (ksh == 0 || alp < alps))
0193
0194 alps = alp;
0195 end
0196 if (f == f0 && (ksh == 0 || alp > alpm))
0197
0198 alpm = alp;
0199 end
0200 if (f == f0)
0201 ksh=ksh+1;
0202 end
0203 end
0204
0205
0206 if (alp1*alp2 > 0)
0207 alp0 = alp1;
0208 denom = (f-f1)/(alp-alp1)-(f-f2)/(alp-alp2);
0209 if (denom > 0)
0210 alp0 = 0.5*(alp1+alp2-(f1-f2)/denom);
0211 end
0212 end
0213
0214
0215 mu = (f-f0)/(alp*pi0);
0216 if (f == f0 && f2 == f0)
0217
0218 if (f1 < f0 || ksh <= 6)
0219
0220 mu = 1.;
0221 end
0222 end
0223
0224
0225 bLong = (mu < mu1s);
0226 if (bLong)
0227
0228 alp1 = alp;
0229 f1 = f;
0230 mu1 = mu;
0231 if (k == 1 && mu > 0.5)
0232 mu1 = 0;
0233 end
0234 omega1 = 2*abs(1.-mu1)/alp1;
0235 else
0236
0237 alp2 = alp;
0238 f2 = f;
0239 mu2 = mu;
0240 omega2 = 2*abs(1.-mu2)/alp2;
0241 end
0242
0243 if (f2 == f0 && f1 >= f0 && k >= 2)
0244
0245
0246
0247 if (ksh == 7 || (ksh == 1 && f1 > f0 && alp1 == alp2*1.1))
0248 ksh=9999;
0249
0250 alp1 = alps;
0251 f1 = f0;
0252 mu1 = 0;
0253 omega1 = 0;
0254 alp2 = 0;
0255 f2 = f0;
0256 mu2 = 1;
0257 omega2 = 0;
0258 end
0259 end
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 if (bLong)
0274 if (alp1 == stpmin && alp1 ~= 0.)
0275
0276 obj.print(3,Inf,'WARNING: end of line search forced by stpmin');
0277 nEff = 2;
0278 ier = 0;
0279 break;
0280 end
0281 else
0282
0283 if (0)
0284 if (k >= 3 && alp == alp2 && alp1 <= kappa*alp2)
0285
0286 nEff = 1;
0287 ier = 0;
0288 break;
0289 end
0290 end
0291
0292 if (alp2*mu2*max(omega1,omega2) >= eff && f ~= f0)
0293
0294 nEff = 1;
0295 ier = 0;
0296 break;
0297 end
0298
0299
0300 if (alp1 == stpmin && alp1 ~= 0.)
0301
0302 obj.print(3,Inf,'WARNING: end of line search forced by stpmin');
0303 nEff = 2;
0304 ier = 0;
0305 break;
0306 end
0307
0308 if (alp2 == stpmax)
0309
0310 obj.print(3,Inf,'WARNING: end of line search forced by stpmax');
0311 nEff = 2;
0312 ier = 0;
0313 break;
0314 end
0315 end
0316
0317
0318
0319
0320
0321 bSafeguard = 1;
0322
0323
0324 if (alp1 == 0.)
0325
0326 if (fbest == f0)
0327
0328 alp = alp2/sml;
0329
0330 if (ksh == 1)
0331 alp = alp2*1.1;
0332 end
0333 elseif (k == 1)
0334
0335 alp = alp/max(2-2*mu,sml);
0336 else
0337
0338 divs = max(2.,min(4.,4.*mu2));
0339 alp = alp2*divs;
0340 end
0341
0342 bSafeguard = 0;
0343 else
0344
0345 if (alp2 == 0.)
0346
0347
0348 alpd = alp1/(2-2*mu1);
0349 elseif (fbest == f0)
0350
0351 alp = alp2*sqrt(alp1/alp2);
0352
0353 if (ksh == 1)
0354 alp = min(alp,alp2*1.1);
0355 end
0356 bSafeguard = 0;
0357 else
0358
0359 fact = (alp1/alp2)^(1/3);
0360 if (denom > 0 && (alp0 >= fact*alp2 && alp1 >= fact*alp0))
0361
0362 alpd = alp0;
0363 else
0364 alpd = alp2;
0365 end
0366 end
0367 end
0368
0369 if (bSafeguard)
0370
0371 q = (alpd-alp2)/(alp1-alp2);
0372
0373
0374
0375
0376
0377 if (alp1 == 0)
0378 error('programming error in extrapolation step of line search (alp1==0)');
0379 elseif (alp2 == 0)
0380
0381 if (q >= sml*sml && q <= sml)
0382
0383 alp = q*alp1;
0384 else
0385
0386 alp = sml*alp1;
0387 end
0388 else
0389
0390 alpd = alp2+q*(alp1-alp2);
0391 fact = (alp1/alp2)^(1/3);
0392 if (0)
0393
0394 alpd = fact*alp2;
0395 else
0396
0397 if (alpd<fact*alp2)
0398
0399 alpd = fact*alp2;
0400 end
0401 end
0402
0403 alp = min(alpd,alp1/fact);
0404 if (alp ~= alpd || alp >= alp1 || alp<=alp2)
0405
0406 alp = alp1*sqrt(alp2/alp1);
0407 end
0408 end
0409 end
0410
0411
0412
0413
0414
0415
0416 if (alp < stpmin)
0417 alp = stpmin;
0418 elseif (alp > stpmax)
0419 alp=stpmax;
0420 end
0421
0422 if (alp > alp2 && (alp < alp1 || alp1 == 0.))
0423
0424
0425 ;
0426 else
0427
0428 if (alp2*mu2*max(omega1,omega2) >= eff && f ~= f0)
0429
0430 obj.print(3,Inf,'WARNING: end of line search forced by machine accuracy');
0431 nEff = 2;
0432 ier = 0;
0433 break;
0434 else
0435 obj.print(3,Inf,'WARNING: end of line search forced by machine accuracy');
0436 nEff = 0;
0437 ier = 1;
0438 break;
0439 end
0440 end
0441
0442 if (alp2 == 0)
0443 fact = alp1/alp;
0444 else
0445 fact = alp/alp2;
0446 end
0447
0448
0449
0450 end
0451
0452
0453
0454
0455 if (ier == 0)
0456 if (f < fx)
0457
0458 bLinesearch = 0;
0459
0460 fx=f;
0461 obj.eval_aldx();
0462
0463 nFlag=0;
0464 else
0465 if (ksh>0 && alpm > 0.)
0466
0467
0468
0469 alp = alpm;
0470
0471
0472 obj.xall=xall0+alp*dir;
0473
0474
0475
0476
0477 bLinesearch = 0;
0478
0479
0480
0481 obj.eval_alx();
0482 obj.eval_aldx();
0483 fx = obj.ALx;
0484
0485 nFlag=0;
0486 else
0487 alp = 0;
0488 end
0489 end
0490 else
0491 alp = 0;
0492 end
0493
0494 lsiter=lsiter+iterations;
0495 obj.lsiter_last=obj.lsiter_last + lsiter;
0496
0497 obj.print(3,Inf,'LS (pen): %.4e, %d steps, Step width: %f', pi0, iterations, alp);
0498
0499
0500 rRelStep=alp;
0501 return;
0502
0503