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