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