1 #include <petsc/private/taolinesearchimpl.h> 2 #include <../src/tao/linesearch/impls/morethuente/morethuente.h> 3 4 /* 5 This algorithm is taken from More' and Thuente, "Line search algorithms 6 with guaranteed sufficient decrease", Argonne National Laboratory, 7 Technical Report MCS-P330-1092. 8 */ 9 10 static PetscErrorCode Tao_mcstep(TaoLineSearch ls, PetscReal *stx, PetscReal *fx, PetscReal *dx, PetscReal *sty, PetscReal *fy, PetscReal *dy, PetscReal *stp, PetscReal *fp, PetscReal *dp); 11 12 static PetscErrorCode TaoLineSearchDestroy_MT(TaoLineSearch ls) 13 { 14 TaoLineSearch_MT *mt = (TaoLineSearch_MT *)(ls->data); 15 16 PetscFunctionBegin; 17 PetscCall(PetscObjectDereference((PetscObject)mt->x)); 18 PetscCall(VecDestroy(&mt->work)); 19 PetscCall(PetscFree(ls->data)); 20 PetscFunctionReturn(PETSC_SUCCESS); 21 } 22 23 static PetscErrorCode TaoLineSearchSetFromOptions_MT(TaoLineSearch ls, PetscOptionItems *PetscOptionsObject) 24 { 25 PetscFunctionBegin; 26 PetscFunctionReturn(PETSC_SUCCESS); 27 } 28 29 static PetscErrorCode TaoLineSearchMonitor_MT(TaoLineSearch ls) 30 { 31 TaoLineSearch_MT *mt = (TaoLineSearch_MT *)ls->data; 32 33 PetscFunctionBegin; 34 PetscCall(PetscViewerASCIIPrintf(ls->viewer, "stx: %g, fx: %g, dgx: %g\n", (double)mt->stx, (double)mt->fx, (double)mt->dgx)); 35 PetscCall(PetscViewerASCIIPrintf(ls->viewer, "sty: %g, fy: %g, dgy: %g\n", (double)mt->sty, (double)mt->fy, (double)mt->dgy)); 36 PetscFunctionReturn(PETSC_SUCCESS); 37 } 38 39 static PetscErrorCode TaoLineSearchApply_MT(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s) 40 { 41 TaoLineSearch_MT *mt = (TaoLineSearch_MT *)(ls->data); 42 PetscReal xtrapf = 4.0; 43 PetscReal finit, width, width1, dginit, fm, fxm, fym, dgm, dgxm, dgym; 44 PetscReal dgx, dgy, dg, dg2, fx, fy, stx, sty, dgtest; 45 PetscReal ftest1 = 0.0, ftest2 = 0.0; 46 PetscInt i, stage1, n1, n2, nn1, nn2; 47 PetscReal bstepmin1, bstepmin2, bstepmax, ostepmin, ostepmax; 48 PetscBool g_computed = PETSC_FALSE; /* to prevent extra gradient computation */ 49 50 PetscFunctionBegin; 51 ls->reason = TAOLINESEARCH_CONTINUE_ITERATING; 52 PetscCall(TaoLineSearchMonitor(ls, 0, *f, 0.0)); 53 /* Check work vector */ 54 if (!mt->work) { 55 PetscCall(VecDuplicate(x, &mt->work)); 56 mt->x = x; 57 PetscCall(PetscObjectReference((PetscObject)mt->x)); 58 } else if (x != mt->x) { 59 PetscCall(VecDestroy(&mt->work)); 60 PetscCall(VecDuplicate(x, &mt->work)); 61 PetscCall(PetscObjectDereference((PetscObject)mt->x)); 62 mt->x = x; 63 PetscCall(PetscObjectReference((PetscObject)mt->x)); 64 } 65 66 ostepmax = ls->stepmax; 67 ostepmin = ls->stepmin; 68 69 if (ls->bounded) { 70 /* Compute step length needed to make all variables equal a bound */ 71 /* Compute the smallest steplength that will make one nonbinding variable 72 equal the bound */ 73 PetscCall(VecGetLocalSize(ls->upper, &n1)); 74 PetscCall(VecGetLocalSize(mt->x, &n2)); 75 PetscCall(VecGetSize(ls->upper, &nn1)); 76 PetscCall(VecGetSize(mt->x, &nn2)); 77 PetscCheck(n1 == n2 && nn1 == nn2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Variable vector not compatible with bounds vector"); 78 PetscCall(VecScale(s, -1.0)); 79 PetscCall(VecBoundGradientProjection(s, x, ls->lower, ls->upper, s)); 80 PetscCall(VecScale(s, -1.0)); 81 PetscCall(VecStepBoundInfo(x, s, ls->lower, ls->upper, &bstepmin1, &bstepmin2, &bstepmax)); 82 ls->stepmax = PetscMin(bstepmax, ls->stepmax); 83 } 84 85 PetscCall(VecDot(g, s, &dginit)); 86 if (PetscIsInfOrNanReal(dginit)) { 87 PetscCall(PetscInfo(ls, "Initial Line Search step * g is Inf or Nan (%g)\n", (double)dginit)); 88 ls->reason = TAOLINESEARCH_FAILED_INFORNAN; 89 PetscFunctionReturn(PETSC_SUCCESS); 90 } 91 if (dginit >= 0.0) { 92 PetscCall(PetscInfo(ls, "Initial Line Search step * g is not descent direction (%g)\n", (double)dginit)); 93 ls->reason = TAOLINESEARCH_FAILED_ASCENT; 94 PetscFunctionReturn(PETSC_SUCCESS); 95 } 96 97 /* Initialization */ 98 mt->bracket = 0; 99 stage1 = 1; 100 finit = *f; 101 dgtest = ls->ftol * dginit; 102 width = ls->stepmax - ls->stepmin; 103 width1 = width * 2.0; 104 PetscCall(VecCopy(x, mt->work)); 105 /* Variable dictionary: 106 stx, fx, dgx - the step, function, and derivative at the best step 107 sty, fy, dgy - the step, function, and derivative at the other endpoint 108 of the interval of uncertainty 109 step, f, dg - the step, function, and derivative at the current step */ 110 111 stx = 0.0; 112 fx = finit; 113 dgx = dginit; 114 sty = 0.0; 115 fy = finit; 116 dgy = dginit; 117 118 ls->step = ls->initstep; 119 for (i = 0; i < ls->max_funcs; i++) { 120 /* Set min and max steps to correspond to the interval of uncertainty */ 121 if (mt->bracket) { 122 ls->stepmin = PetscMin(stx, sty); 123 ls->stepmax = PetscMax(stx, sty); 124 } else { 125 ls->stepmin = stx; 126 ls->stepmax = ls->step + xtrapf * (ls->step - stx); 127 } 128 129 /* Force the step to be within the bounds */ 130 ls->step = PetscMax(ls->step, ls->stepmin); 131 ls->step = PetscMin(ls->step, ls->stepmax); 132 133 /* If an unusual termination is to occur, then let step be the lowest 134 point obtained thus far */ 135 if (stx != 0 && ((mt->bracket && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) || (mt->bracket && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) || (ls->nfeval + ls->nfgeval >= ls->max_funcs - 1) || mt->infoc == 0)) 136 ls->step = stx; 137 138 PetscCall(VecWAXPY(mt->work, ls->step, s, x)); /* W = X + step*S */ 139 140 if (ls->step == 0.0) { 141 PetscCall(PetscInfo(ls, "Step is zero.")); 142 ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; 143 break; 144 } 145 146 if (ls->bounded) PetscCall(VecMedian(ls->lower, mt->work, ls->upper, mt->work)); 147 if (ls->usegts) { 148 PetscCall(TaoLineSearchComputeObjectiveAndGTS(ls, mt->work, f, &dg)); 149 g_computed = PETSC_FALSE; 150 } else { 151 PetscCall(TaoLineSearchComputeObjectiveAndGradient(ls, mt->work, f, g)); 152 g_computed = PETSC_TRUE; 153 if (ls->bounded) { 154 PetscCall(VecDot(g, x, &dg)); 155 PetscCall(VecDot(g, mt->work, &dg2)); 156 dg = (dg2 - dg) / ls->step; 157 } else { 158 PetscCall(VecDot(g, s, &dg)); 159 } 160 } 161 162 /* update bracketing parameters in the MT context for printouts in monitor */ 163 mt->stx = stx; 164 mt->fx = fx; 165 mt->dgx = dgx; 166 mt->sty = sty; 167 mt->fy = fy; 168 mt->dgy = dgy; 169 PetscCall(TaoLineSearchMonitor(ls, i + 1, *f, ls->step)); 170 171 if (i == 0) ls->f_fullstep = *f; 172 173 if (PetscIsInfOrNanReal(*f) || PetscIsInfOrNanReal(dg)) { 174 /* User provided compute function generated Not-a-Number, assume 175 domain violation and set function value and directional 176 derivative to infinity. */ 177 *f = PETSC_INFINITY; 178 dg = PETSC_INFINITY; 179 } 180 181 ftest1 = finit + ls->step * dgtest; 182 if (ls->bounded) ftest2 = finit + ls->step * dgtest * ls->ftol; 183 184 /* Convergence testing */ 185 if ((*f - ftest1 <= PETSC_SMALL * PetscAbsReal(finit)) && (PetscAbsReal(dg) + ls->gtol * dginit <= 0.0)) { 186 PetscCall(PetscInfo(ls, "Line search success: Sufficient decrease and directional deriv conditions hold\n")); 187 ls->reason = TAOLINESEARCH_SUCCESS; 188 break; 189 } 190 191 /* Check Armijo if beyond the first breakpoint */ 192 if (ls->bounded && *f <= ftest2 && ls->step >= bstepmin2) { 193 PetscCall(PetscInfo(ls, "Line search success: Sufficient decrease.\n")); 194 ls->reason = TAOLINESEARCH_SUCCESS; 195 break; 196 } 197 198 /* Checks for bad cases */ 199 if ((mt->bracket && (ls->step <= ls->stepmin || ls->step >= ls->stepmax)) || !mt->infoc) { 200 PetscCall(PetscInfo(ls, "Rounding errors may prevent further progress. May not be a step satisfying\nsufficient decrease and curvature conditions. Tolerances may be too small.\n")); 201 ls->reason = TAOLINESEARCH_HALTED_OTHER; 202 break; 203 } 204 if (ls->step == ls->stepmax && *f <= ftest1 && dg <= dgtest) { 205 PetscCall(PetscInfo(ls, "Step is at the upper bound, stepmax (%g)\n", (double)ls->stepmax)); 206 ls->reason = TAOLINESEARCH_HALTED_UPPERBOUND; 207 break; 208 } 209 if (ls->step == ls->stepmin && *f >= ftest1 && dg >= dgtest) { 210 PetscCall(PetscInfo(ls, "Step is at the lower bound, stepmin (%g)\n", (double)ls->stepmin)); 211 ls->reason = TAOLINESEARCH_HALTED_LOWERBOUND; 212 break; 213 } 214 if (mt->bracket && (ls->stepmax - ls->stepmin <= ls->rtol * ls->stepmax)) { 215 PetscCall(PetscInfo(ls, "Relative width of interval of uncertainty is at most rtol (%g)\n", (double)ls->rtol)); 216 ls->reason = TAOLINESEARCH_HALTED_RTOL; 217 break; 218 } 219 220 /* In the first stage, we seek a step for which the modified function 221 has a nonpositive value and nonnegative derivative */ 222 if (stage1 && *f <= ftest1 && dg >= dginit * PetscMin(ls->ftol, ls->gtol)) stage1 = 0; 223 224 /* A modified function is used to predict the step only if we 225 have not obtained a step for which the modified function has a 226 nonpositive function value and nonnegative derivative, and if a 227 lower function value has been obtained but the decrease is not 228 sufficient */ 229 230 if (stage1 && *f <= fx && *f > ftest1) { 231 fm = *f - ls->step * dgtest; /* Define modified function */ 232 fxm = fx - stx * dgtest; /* and derivatives */ 233 fym = fy - sty * dgtest; 234 dgm = dg - dgtest; 235 dgxm = dgx - dgtest; 236 dgym = dgy - dgtest; 237 238 /* if (dgxm * (ls->step - stx) >= 0.0) */ 239 /* Update the interval of uncertainty and compute the new step */ 240 PetscCall(Tao_mcstep(ls, &stx, &fxm, &dgxm, &sty, &fym, &dgym, &ls->step, &fm, &dgm)); 241 242 fx = fxm + stx * dgtest; /* Reset the function and */ 243 fy = fym + sty * dgtest; /* gradient values */ 244 dgx = dgxm + dgtest; 245 dgy = dgym + dgtest; 246 } else { 247 /* Update the interval of uncertainty and compute the new step */ 248 PetscCall(Tao_mcstep(ls, &stx, &fx, &dgx, &sty, &fy, &dgy, &ls->step, f, &dg)); 249 } 250 251 /* Force a sufficient decrease in the interval of uncertainty */ 252 if (mt->bracket) { 253 if (PetscAbsReal(sty - stx) >= 0.66 * width1) ls->step = stx + 0.5 * (sty - stx); 254 width1 = width; 255 width = PetscAbsReal(sty - stx); 256 } 257 } 258 if (ls->nfeval + ls->nfgeval > ls->max_funcs) { 259 PetscCall(PetscInfo(ls, "Number of line search function evals (%" PetscInt_FMT ") > maximum (%" PetscInt_FMT ")\n", ls->nfeval + ls->nfgeval, ls->max_funcs)); 260 ls->reason = TAOLINESEARCH_HALTED_MAXFCN; 261 } 262 ls->stepmax = ostepmax; 263 ls->stepmin = ostepmin; 264 265 /* Finish computations */ 266 PetscCall(PetscInfo(ls, "%" PetscInt_FMT " function evals in line search, step = %g\n", ls->nfeval + ls->nfgeval, (double)ls->step)); 267 268 /* Set new solution vector and compute gradient if needed */ 269 PetscCall(VecCopy(mt->work, x)); 270 if (!g_computed) PetscCall(TaoLineSearchComputeGradient(ls, mt->work, g)); 271 PetscFunctionReturn(PETSC_SUCCESS); 272 } 273 274 /*MC 275 TAOLINESEARCHMT - Line-search type with cubic interpolation that satisfies both the sufficient decrease and 276 curvature conditions. This method can take step lengths greater than 1. 277 278 More-Thuente line-search can be selected with "-tao_ls_type more-thuente". 279 280 References: 281 . * - JORGE J. MORE AND DAVID J. THUENTE, LINE SEARCH ALGORITHMS WITH GUARANTEED SUFFICIENT DECREASE. 282 ACM Trans. Math. Software 20, no. 3 (1994): 286-307. 283 284 Level: developer 285 286 .seealso: `TaoLineSearchCreate()`, `TaoLineSearchSetType()`, `TaoLineSearchApply()` 287 288 .keywords: Tao, linesearch 289 M*/ 290 PETSC_EXTERN PetscErrorCode TaoLineSearchCreate_MT(TaoLineSearch ls) 291 { 292 TaoLineSearch_MT *ctx; 293 294 PetscFunctionBegin; 295 PetscValidHeaderSpecific(ls, TAOLINESEARCH_CLASSID, 1); 296 PetscCall(PetscNew(&ctx)); 297 ctx->bracket = 0; 298 ctx->infoc = 1; 299 ls->data = (void *)ctx; 300 ls->initstep = 1.0; 301 ls->ops->setup = NULL; 302 ls->ops->reset = NULL; 303 ls->ops->apply = TaoLineSearchApply_MT; 304 ls->ops->destroy = TaoLineSearchDestroy_MT; 305 ls->ops->setfromoptions = TaoLineSearchSetFromOptions_MT; 306 ls->ops->monitor = TaoLineSearchMonitor_MT; 307 PetscFunctionReturn(PETSC_SUCCESS); 308 } 309 310 /* 311 The subroutine mcstep is taken from the work of Jorge Nocedal. 312 this is a variant of More' and Thuente's routine. 313 314 subroutine mcstep 315 316 the purpose of mcstep is to compute a safeguarded step for 317 a linesearch and to update an interval of uncertainty for 318 a minimizer of the function. 319 320 the parameter stx contains the step with the least function 321 value. the parameter stp contains the current step. it is 322 assumed that the derivative at stx is negative in the 323 direction of the step. if bracket is set true then a 324 minimizer has been bracketed in an interval of uncertainty 325 with endpoints stx and sty. 326 327 the subroutine statement is 328 329 subroutine mcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,bracket, 330 stpmin,stpmax,info) 331 332 where 333 334 stx, fx, and dx are variables which specify the step, 335 the function, and the derivative at the best step obtained 336 so far. The derivative must be negative in the direction 337 of the step, that is, dx and stp-stx must have opposite 338 signs. On output these parameters are updated appropriately. 339 340 sty, fy, and dy are variables which specify the step, 341 the function, and the derivative at the other endpoint of 342 the interval of uncertainty. On output these parameters are 343 updated appropriately. 344 345 stp, fp, and dp are variables which specify the step, 346 the function, and the derivative at the current step. 347 If bracket is set true then on input stp must be 348 between stx and sty. On output stp is set to the new step. 349 350 bracket is a logical variable which specifies if a minimizer 351 has been bracketed. If the minimizer has not been bracketed 352 then on input bracket must be set false. If the minimizer 353 is bracketed then on output bracket is set true. 354 355 stpmin and stpmax are input variables which specify lower 356 and upper bounds for the step. 357 358 info is an integer output variable set as follows: 359 if info = 1,2,3,4,5, then the step has been computed 360 according to one of the five cases below. otherwise 361 info = 0, and this indicates improper input parameters. 362 363 subprograms called 364 365 fortran-supplied ... abs,max,min,sqrt 366 367 argonne national laboratory. minpack project. june 1983 368 jorge j. more', david j. thuente 369 370 */ 371 372 static PetscErrorCode Tao_mcstep(TaoLineSearch ls, PetscReal *stx, PetscReal *fx, PetscReal *dx, PetscReal *sty, PetscReal *fy, PetscReal *dy, PetscReal *stp, PetscReal *fp, PetscReal *dp) 373 { 374 TaoLineSearch_MT *mtP = (TaoLineSearch_MT *)ls->data; 375 PetscReal gamma1, p, q, r, s, sgnd, stpc, stpf, stpq, theta; 376 PetscInt bound; 377 378 PetscFunctionBegin; 379 /* Check the input parameters for errors */ 380 mtP->infoc = 0; 381 PetscCheck(!mtP->bracket || (*stp > PetscMin(*stx, *sty) && *stp < PetscMax(*stx, *sty)), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "bad stp in bracket"); 382 PetscCheck(*dx * (*stp - *stx) < 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "dx * (stp-stx) >= 0.0"); 383 PetscCheck(ls->stepmax >= ls->stepmin, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "stepmax > stepmin"); 384 385 /* Determine if the derivatives have opposite sign */ 386 sgnd = *dp * (*dx / PetscAbsReal(*dx)); 387 388 if (*fp > *fx) { 389 /* Case 1: a higher function value. 390 The minimum is bracketed. If the cubic step is closer 391 to stx than the quadratic step, the cubic step is taken, 392 else the average of the cubic and quadratic steps is taken. */ 393 394 mtP->infoc = 1; 395 bound = 1; 396 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 397 s = PetscMax(PetscAbsReal(theta), PetscAbsReal(*dx)); 398 s = PetscMax(s, PetscAbsReal(*dp)); 399 gamma1 = s * PetscSqrtScalar(PetscPowScalar(theta / s, 2.0) - (*dx / s) * (*dp / s)); 400 if (*stp < *stx) gamma1 = -gamma1; 401 /* Can p be 0? Check */ 402 p = (gamma1 - *dx) + theta; 403 q = ((gamma1 - *dx) + gamma1) + *dp; 404 r = p / q; 405 stpc = *stx + r * (*stp - *stx); 406 stpq = *stx + ((*dx / ((*fx - *fp) / (*stp - *stx) + *dx)) * 0.5) * (*stp - *stx); 407 408 if (PetscAbsReal(stpc - *stx) < PetscAbsReal(stpq - *stx)) stpf = stpc; 409 else stpf = stpc + 0.5 * (stpq - stpc); 410 mtP->bracket = 1; 411 } else if (sgnd < 0.0) { 412 /* Case 2: A lower function value and derivatives of 413 opposite sign. The minimum is bracketed. If the cubic 414 step is closer to stx than the quadratic (secant) step, 415 the cubic step is taken, else the quadratic step is taken. */ 416 417 mtP->infoc = 2; 418 bound = 0; 419 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 420 s = PetscMax(PetscAbsReal(theta), PetscAbsReal(*dx)); 421 s = PetscMax(s, PetscAbsReal(*dp)); 422 gamma1 = s * PetscSqrtScalar(PetscPowScalar(theta / s, 2.0) - (*dx / s) * (*dp / s)); 423 if (*stp > *stx) gamma1 = -gamma1; 424 p = (gamma1 - *dp) + theta; 425 q = ((gamma1 - *dp) + gamma1) + *dx; 426 r = p / q; 427 stpc = *stp + r * (*stx - *stp); 428 stpq = *stp + (*dp / (*dp - *dx)) * (*stx - *stp); 429 430 if (PetscAbsReal(stpc - *stp) > PetscAbsReal(stpq - *stp)) stpf = stpc; 431 else stpf = stpq; 432 mtP->bracket = 1; 433 } else if (PetscAbsReal(*dp) < PetscAbsReal(*dx)) { 434 /* Case 3: A lower function value, derivatives of the 435 same sign, and the magnitude of the derivative decreases. 436 The cubic step is only used if the cubic tends to infinity 437 in the direction of the step or if the minimum of the cubic 438 is beyond stp. Otherwise the cubic step is defined to be 439 either stepmin or stepmax. The quadratic (secant) step is also 440 computed and if the minimum is bracketed then the step 441 closest to stx is taken, else the step farthest away is taken. */ 442 443 mtP->infoc = 3; 444 bound = 1; 445 theta = 3 * (*fx - *fp) / (*stp - *stx) + *dx + *dp; 446 s = PetscMax(PetscAbsReal(theta), PetscAbsReal(*dx)); 447 s = PetscMax(s, PetscAbsReal(*dp)); 448 449 /* The case gamma1 = 0 only arises if the cubic does not tend 450 to infinity in the direction of the step. */ 451 gamma1 = s * PetscSqrtScalar(PetscMax(0.0, PetscPowScalar(theta / s, 2.0) - (*dx / s) * (*dp / s))); 452 if (*stp > *stx) gamma1 = -gamma1; 453 p = (gamma1 - *dp) + theta; 454 q = (gamma1 + (*dx - *dp)) + gamma1; 455 r = p / q; 456 if (r < 0.0 && gamma1 != 0.0) stpc = *stp + r * (*stx - *stp); 457 else if (*stp > *stx) stpc = ls->stepmax; 458 else stpc = ls->stepmin; 459 stpq = *stp + (*dp / (*dp - *dx)) * (*stx - *stp); 460 461 if (mtP->bracket) { 462 if (PetscAbsReal(*stp - stpc) < PetscAbsReal(*stp - stpq)) stpf = stpc; 463 else stpf = stpq; 464 } else { 465 if (PetscAbsReal(*stp - stpc) > PetscAbsReal(*stp - stpq)) stpf = stpc; 466 else stpf = stpq; 467 } 468 } else { 469 /* Case 4: A lower function value, derivatives of the 470 same sign, and the magnitude of the derivative does 471 not decrease. If the minimum is not bracketed, the step 472 is either stpmin or stpmax, else the cubic step is taken. */ 473 474 mtP->infoc = 4; 475 bound = 0; 476 if (mtP->bracket) { 477 theta = 3 * (*fp - *fy) / (*sty - *stp) + *dy + *dp; 478 s = PetscMax(PetscAbsReal(theta), PetscAbsReal(*dy)); 479 s = PetscMax(s, PetscAbsReal(*dp)); 480 gamma1 = s * PetscSqrtScalar(PetscPowScalar(theta / s, 2.0) - (*dy / s) * (*dp / s)); 481 if (*stp > *sty) gamma1 = -gamma1; 482 p = (gamma1 - *dp) + theta; 483 q = ((gamma1 - *dp) + gamma1) + *dy; 484 r = p / q; 485 stpc = *stp + r * (*sty - *stp); 486 stpf = stpc; 487 } else if (*stp > *stx) { 488 stpf = ls->stepmax; 489 } else { 490 stpf = ls->stepmin; 491 } 492 } 493 494 /* Update the interval of uncertainty. This update does not 495 depend on the new step or the case analysis above. */ 496 497 if (*fp > *fx) { 498 *sty = *stp; 499 *fy = *fp; 500 *dy = *dp; 501 } else { 502 if (sgnd < 0.0) { 503 *sty = *stx; 504 *fy = *fx; 505 *dy = *dx; 506 } 507 *stx = *stp; 508 *fx = *fp; 509 *dx = *dp; 510 } 511 512 /* Compute the new step and safeguard it. */ 513 stpf = PetscMin(ls->stepmax, stpf); 514 stpf = PetscMax(ls->stepmin, stpf); 515 *stp = stpf; 516 if (mtP->bracket && bound) { 517 if (*sty > *stx) *stp = PetscMin(*stx + 0.66 * (*sty - *stx), *stp); 518 else *stp = PetscMax(*stx + 0.66 * (*sty - *stx), *stp); 519 } 520 PetscFunctionReturn(PETSC_SUCCESS); 521 } 522