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