xref: /petsc/src/tao/linesearch/impls/armijo/armijo.c (revision a7e14dcfba0d07adf6226a919460249440ec94c7)
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 "armijo.h"
5*a7e14dcfSSatish Balay 
6*a7e14dcfSSatish Balay #define REPLACE_FIFO 1
7*a7e14dcfSSatish Balay #define REPLACE_MRU  2
8*a7e14dcfSSatish Balay 
9*a7e14dcfSSatish Balay #define REFERENCE_MAX  1
10*a7e14dcfSSatish Balay #define REFERENCE_AVE  2
11*a7e14dcfSSatish Balay #define REFERENCE_MEAN 3
12*a7e14dcfSSatish Balay 
13*a7e14dcfSSatish Balay #undef __FUNCT__
14*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchDestroy_Armijo"
15*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchDestroy_Armijo(TaoLineSearch ls)
16*a7e14dcfSSatish Balay {
17*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP = (TAOLINESEARCH_ARMIJO_CTX *)ls->data;
18*a7e14dcfSSatish Balay   PetscErrorCode ierr;
19*a7e14dcfSSatish Balay 
20*a7e14dcfSSatish Balay   PetscFunctionBegin;
21*a7e14dcfSSatish Balay 
22*a7e14dcfSSatish Balay   if (armP->memory != PETSC_NULL) {
23*a7e14dcfSSatish Balay     ierr = PetscFree(armP->memory); CHKERRQ(ierr);
24*a7e14dcfSSatish Balay     armP->memory = PETSC_NULL;
25*a7e14dcfSSatish Balay   }
26*a7e14dcfSSatish Balay   if (armP->x) {
27*a7e14dcfSSatish Balay     ierr = PetscObjectDereference((PetscObject)armP->x); CHKERRQ(ierr);
28*a7e14dcfSSatish Balay   }
29*a7e14dcfSSatish Balay   ierr = VecDestroy(&armP->work); CHKERRQ(ierr);
30*a7e14dcfSSatish Balay   ierr = PetscFree(ls->data); CHKERRQ(ierr);
31*a7e14dcfSSatish Balay   ls->data = PETSC_NULL;
32*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
33*a7e14dcfSSatish Balay }
34*a7e14dcfSSatish Balay 
35*a7e14dcfSSatish Balay #undef __FUNCT__
36*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchReset_Armijo"
37*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchReset_Armijo(TaoLineSearch ls)
38*a7e14dcfSSatish Balay {
39*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP = (TAOLINESEARCH_ARMIJO_CTX *)ls->data;
40*a7e14dcfSSatish Balay   PetscErrorCode ierr;
41*a7e14dcfSSatish Balay 
42*a7e14dcfSSatish Balay   PetscFunctionBegin;
43*a7e14dcfSSatish Balay 
44*a7e14dcfSSatish Balay   if (armP->memory != PETSC_NULL) {
45*a7e14dcfSSatish Balay     ierr = PetscFree(armP->memory); CHKERRQ(ierr);
46*a7e14dcfSSatish Balay     armP->memory = PETSC_NULL;
47*a7e14dcfSSatish Balay   }
48*a7e14dcfSSatish Balay   armP->memorySetup = PETSC_FALSE;
49*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
50*a7e14dcfSSatish Balay }
51*a7e14dcfSSatish Balay 
52*a7e14dcfSSatish Balay #undef __FUNCT__
53*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchSetFromOptions_Armijo"
54*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchSetFromOptions_Armijo(TaoLineSearch ls)
55*a7e14dcfSSatish Balay {
56*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP = (TAOLINESEARCH_ARMIJO_CTX *)ls->data;
57*a7e14dcfSSatish Balay   PetscErrorCode ierr;
58*a7e14dcfSSatish Balay 
59*a7e14dcfSSatish Balay   PetscFunctionBegin;
60*a7e14dcfSSatish Balay   ierr = PetscOptionsHead("Armijo linesearch options");CHKERRQ(ierr);
61*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_armijo_alpha", "initial reference constant", "", armP->alpha, &armP->alpha, 0); CHKERRQ(ierr);
62*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_armijo_beta_inf", "decrease constant one", "", armP->beta_inf, &armP->beta_inf, 0); CHKERRQ(ierr);
63*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_armijo_beta", "decrease constant", "", armP->beta, &armP->beta, 0); CHKERRQ(ierr);
64*a7e14dcfSSatish Balay   ierr = PetscOptionsReal("-tao_ls_armijo_sigma", "acceptance constant", "", armP->sigma, &armP->sigma, 0); CHKERRQ(ierr);
65*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_armijo_memory_size", "number of historical elements", "", armP->memorySize, &armP->memorySize, 0); CHKERRQ(ierr);
66*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_armijo_reference_policy", "policy for updating reference value", "", armP->referencePolicy, &armP->referencePolicy, 0); CHKERRQ(ierr);
67*a7e14dcfSSatish Balay   ierr = PetscOptionsInt("-tao_ls_armijo_replacement_policy", "policy for updating memory", "", armP->replacementPolicy, &armP->replacementPolicy, 0); CHKERRQ(ierr);
68*a7e14dcfSSatish Balay   ierr = PetscOptionsBool("-tao_ls_armijo_nondescending","Use nondescending armijo algorithm","",armP->nondescending,&armP->nondescending, 0); CHKERRQ(ierr);
69*a7e14dcfSSatish Balay   ierr = PetscOptionsTail();CHKERRQ(ierr);
70*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
71*a7e14dcfSSatish Balay }
72*a7e14dcfSSatish Balay 
73*a7e14dcfSSatish Balay #undef __FUNCT__
74*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchView_Armijo"
75*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchView_Armijo(TaoLineSearch ls, PetscViewer pv)
76*a7e14dcfSSatish Balay {
77*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP = (TAOLINESEARCH_ARMIJO_CTX *)ls->data;
78*a7e14dcfSSatish Balay   PetscBool isascii;
79*a7e14dcfSSatish Balay   PetscErrorCode ierr;
80*a7e14dcfSSatish Balay 
81*a7e14dcfSSatish Balay   PetscFunctionBegin;
82*a7e14dcfSSatish Balay   ierr = PetscObjectTypeCompare((PetscObject)pv, PETSCVIEWERASCII, &isascii); CHKERRQ(ierr);
83*a7e14dcfSSatish Balay   if (isascii) {
84*a7e14dcfSSatish Balay     ierr = PetscViewerASCIIPrintf(pv,"  maxf=%D, ftol=%G, gtol=%G\n",ls->max_funcs, ls->rtol, ls->ftol); CHKERRQ(ierr);
85*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"  Armijo linesearch",armP->alpha);CHKERRQ(ierr);
86*a7e14dcfSSatish Balay     if (armP->nondescending) {
87*a7e14dcfSSatish Balay       ierr = PetscViewerASCIIPrintf(pv, " (nondescending)"); CHKERRQ(ierr);
88*a7e14dcfSSatish Balay     }
89*a7e14dcfSSatish Balay     if (ls->bounded) {
90*a7e14dcfSSatish Balay       ierr = PetscViewerASCIIPrintf(pv," (projected)"); CHKERRQ(ierr);
91*a7e14dcfSSatish Balay     }
92*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,": alpha=%G beta=%G ",armP->alpha,armP->beta);CHKERRQ(ierr);
93*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"sigma=%G ",armP->sigma);CHKERRQ(ierr);
94*a7e14dcfSSatish Balay     ierr=PetscViewerASCIIPrintf(pv,"memsize=%D\n",armP->memorySize);CHKERRQ(ierr);
95*a7e14dcfSSatish Balay   } else {
96*a7e14dcfSSatish Balay     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for Armijo TaoLineSearch",((PetscObject)pv)->type_name);
97*a7e14dcfSSatish Balay   }
98*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
99*a7e14dcfSSatish Balay }
100*a7e14dcfSSatish Balay 
101*a7e14dcfSSatish Balay #undef __FUNCT__
102*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchApply_Armijo"
103*a7e14dcfSSatish Balay /* @ TaoApply_Armijo - This routine performs a linesearch. It
104*a7e14dcfSSatish Balay    backtracks until the (nonmonotone) Armijo conditions are satisfied.
105*a7e14dcfSSatish Balay 
106*a7e14dcfSSatish Balay    Input Parameters:
107*a7e14dcfSSatish Balay +  tao - TaoSolver context
108*a7e14dcfSSatish Balay .  X - current iterate (on output X contains new iterate, X + step*S)
109*a7e14dcfSSatish Balay .  S - search direction
110*a7e14dcfSSatish Balay .  f - merit function evaluated at X
111*a7e14dcfSSatish Balay .  G - gradient of merit function evaluated at X
112*a7e14dcfSSatish Balay .  W - work vector
113*a7e14dcfSSatish Balay -  step - initial estimate of step length
114*a7e14dcfSSatish Balay 
115*a7e14dcfSSatish Balay    Output parameters:
116*a7e14dcfSSatish Balay +  f - merit function evaluated at new iterate, X + step*S
117*a7e14dcfSSatish Balay .  G - gradient of merit function evaluated at new iterate, X + step*S
118*a7e14dcfSSatish Balay .  X - new iterate
119*a7e14dcfSSatish Balay -  step - final step length
120*a7e14dcfSSatish Balay 
121*a7e14dcfSSatish Balay    Info is set to one of:
122*a7e14dcfSSatish Balay .   0 - the line search succeeds; the sufficient decrease
123*a7e14dcfSSatish Balay    condition and the directional derivative condition hold
124*a7e14dcfSSatish Balay 
125*a7e14dcfSSatish Balay    negative number if an input parameter is invalid
126*a7e14dcfSSatish Balay -   -1 -  step < 0
127*a7e14dcfSSatish Balay 
128*a7e14dcfSSatish Balay    positive number > 1 if the line search otherwise terminates
129*a7e14dcfSSatish Balay +    1 -  Step is at the lower bound, stepmin.
130*a7e14dcfSSatish Balay @ */
131*a7e14dcfSSatish Balay static PetscErrorCode TaoLineSearchApply_Armijo(TaoLineSearch ls, Vec x, PetscReal *f, Vec g, Vec s)
132*a7e14dcfSSatish Balay {
133*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP = (TAOLINESEARCH_ARMIJO_CTX *)ls->data;
134*a7e14dcfSSatish Balay   PetscErrorCode ierr;
135*a7e14dcfSSatish Balay   PetscInt i;
136*a7e14dcfSSatish Balay   PetscReal fact, ref, gdx;
137*a7e14dcfSSatish Balay   PetscInt idx;
138*a7e14dcfSSatish Balay   PetscBool g_computed=PETSC_FALSE; /* to prevent extra gradient computation */
139*a7e14dcfSSatish Balay 
140*a7e14dcfSSatish Balay   PetscFunctionBegin;
141*a7e14dcfSSatish Balay 
142*a7e14dcfSSatish Balay   ls->reason = TAOLINESEARCH_CONTINUE_ITERATING;
143*a7e14dcfSSatish Balay   if (!armP->work) {
144*a7e14dcfSSatish Balay     ierr = VecDuplicate(x,&armP->work); CHKERRQ(ierr);
145*a7e14dcfSSatish Balay     armP->x = x;
146*a7e14dcfSSatish Balay     ierr = PetscObjectReference((PetscObject)armP->x); CHKERRQ(ierr);
147*a7e14dcfSSatish Balay   }
148*a7e14dcfSSatish Balay   /* If x has changed, then recreate work */
149*a7e14dcfSSatish Balay   else if (x != armP->x) {
150*a7e14dcfSSatish Balay     ierr = VecDestroy(&armP->work); CHKERRQ(ierr);
151*a7e14dcfSSatish Balay     ierr = VecDuplicate(x,&armP->work); CHKERRQ(ierr);
152*a7e14dcfSSatish Balay     ierr = PetscObjectDereference((PetscObject)armP->x); CHKERRQ(ierr);
153*a7e14dcfSSatish Balay     armP->x = x;
154*a7e14dcfSSatish Balay     ierr = PetscObjectReference((PetscObject)armP->x); CHKERRQ(ierr);
155*a7e14dcfSSatish Balay   }
156*a7e14dcfSSatish Balay 
157*a7e14dcfSSatish Balay   /* Check linesearch parameters */
158*a7e14dcfSSatish Balay   if (armP->alpha < 1) {
159*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Armijo line search error: alpha (%G) < 1\n", armP->alpha); CHKERRQ(ierr);
160*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
161*a7e14dcfSSatish Balay   }
162*a7e14dcfSSatish Balay 
163*a7e14dcfSSatish Balay   else if ((armP->beta <= 0) || (armP->beta >= 1)) {
164*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Armijo line search error: beta (%G) invalid\n", armP->beta); CHKERRQ(ierr);
165*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
166*a7e14dcfSSatish Balay 
167*a7e14dcfSSatish Balay   }
168*a7e14dcfSSatish Balay 
169*a7e14dcfSSatish Balay   else if ((armP->beta_inf <= 0) || (armP->beta_inf >= 1)) {
170*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Armijo line search error: beta_inf (%G) invalid\n", armP->beta_inf); CHKERRQ(ierr);
171*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
172*a7e14dcfSSatish Balay   }
173*a7e14dcfSSatish Balay 
174*a7e14dcfSSatish Balay   else if ((armP->sigma <= 0) || (armP->sigma >= 0.5)) {
175*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Armijo line search error: sigma (%G) invalid\n", armP->sigma); CHKERRQ(ierr);
176*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
177*a7e14dcfSSatish Balay   }
178*a7e14dcfSSatish Balay 
179*a7e14dcfSSatish Balay   else if (armP->memorySize < 1) {
180*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Armijo line search error: memory_size (%D) < 1\n", armP->memorySize); CHKERRQ(ierr);
181*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
182*a7e14dcfSSatish Balay   }
183*a7e14dcfSSatish Balay 
184*a7e14dcfSSatish Balay   else if ((armP->referencePolicy != REFERENCE_MAX) &&
185*a7e14dcfSSatish Balay       (armP->referencePolicy != REFERENCE_AVE) &&
186*a7e14dcfSSatish Balay       (armP->referencePolicy != REFERENCE_MEAN)) {
187*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"Armijo line search error: reference_policy invalid\n"); CHKERRQ(ierr);
188*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
189*a7e14dcfSSatish Balay 
190*a7e14dcfSSatish Balay   }
191*a7e14dcfSSatish Balay 
192*a7e14dcfSSatish Balay   else if ((armP->replacementPolicy != REPLACE_FIFO) &&
193*a7e14dcfSSatish Balay       (armP->replacementPolicy != REPLACE_MRU)) {
194*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"Armijo line search error: replacement_policy invalid\n"); CHKERRQ(ierr);
195*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
196*a7e14dcfSSatish Balay   }
197*a7e14dcfSSatish Balay 
198*a7e14dcfSSatish Balay   else if (PetscIsInfOrNanReal(*f)) {
199*a7e14dcfSSatish Balay     ierr = PetscInfo(ls,"Armijo line search error: initial function inf or nan\n"); CHKERRQ(ierr);
200*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_BADPARAMETER;
201*a7e14dcfSSatish Balay   }
202*a7e14dcfSSatish Balay 
203*a7e14dcfSSatish Balay   if (ls->reason != TAOLINESEARCH_CONTINUE_ITERATING) {
204*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
205*a7e14dcfSSatish Balay   }
206*a7e14dcfSSatish Balay 
207*a7e14dcfSSatish Balay   /* Check to see of the memory has been allocated.  If not, allocate
208*a7e14dcfSSatish Balay      the historical array and populate it with the initial function
209*a7e14dcfSSatish Balay      values. */
210*a7e14dcfSSatish Balay   if (armP->memory == PETSC_NULL) {
211*a7e14dcfSSatish Balay     ierr = PetscMalloc(sizeof(PetscReal)*armP->memorySize, &armP->memory ); CHKERRQ(ierr);
212*a7e14dcfSSatish Balay   }
213*a7e14dcfSSatish Balay 
214*a7e14dcfSSatish Balay   if (!armP->memorySetup) {
215*a7e14dcfSSatish Balay     for (i = 0; i < armP->memorySize; i++) {
216*a7e14dcfSSatish Balay       armP->memory[i] = armP->alpha*(*f);
217*a7e14dcfSSatish Balay     }
218*a7e14dcfSSatish Balay 
219*a7e14dcfSSatish Balay     armP->current = 0;
220*a7e14dcfSSatish Balay     armP->lastReference = armP->memory[0];
221*a7e14dcfSSatish Balay     armP->memorySetup=PETSC_TRUE;
222*a7e14dcfSSatish Balay   }
223*a7e14dcfSSatish Balay 
224*a7e14dcfSSatish Balay   /* Calculate reference value (MAX) */
225*a7e14dcfSSatish Balay   ref = armP->memory[0];
226*a7e14dcfSSatish Balay   idx = 0;
227*a7e14dcfSSatish Balay 
228*a7e14dcfSSatish Balay   for (i = 1; i < armP->memorySize; i++) {
229*a7e14dcfSSatish Balay     if (armP->memory[i] > ref) {
230*a7e14dcfSSatish Balay       ref = armP->memory[i];
231*a7e14dcfSSatish Balay       idx = i;
232*a7e14dcfSSatish Balay     }
233*a7e14dcfSSatish Balay   }
234*a7e14dcfSSatish Balay 
235*a7e14dcfSSatish Balay   if (armP->referencePolicy == REFERENCE_AVE) {
236*a7e14dcfSSatish Balay     ref = 0;
237*a7e14dcfSSatish Balay     for (i = 0; i < armP->memorySize; i++) {
238*a7e14dcfSSatish Balay       ref += armP->memory[i];
239*a7e14dcfSSatish Balay     }
240*a7e14dcfSSatish Balay     ref = ref / armP->memorySize;
241*a7e14dcfSSatish Balay     ref = PetscMax(ref, armP->memory[armP->current]);
242*a7e14dcfSSatish Balay   }
243*a7e14dcfSSatish Balay   else if (armP->referencePolicy == REFERENCE_MEAN) {
244*a7e14dcfSSatish Balay     ref = PetscMin(ref, 0.5*(armP->lastReference + armP->memory[armP->current]));
245*a7e14dcfSSatish Balay   }
246*a7e14dcfSSatish Balay   ierr = VecDot(g,s,&gdx); CHKERRQ(ierr);
247*a7e14dcfSSatish Balay 
248*a7e14dcfSSatish Balay   if (PetscIsInfOrNanReal(gdx)) {
249*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Initial Line Search step * g is Inf or Nan (%G)\n",gdx); CHKERRQ(ierr);
250*a7e14dcfSSatish Balay     ls->reason=TAOLINESEARCH_FAILED_INFORNAN;
251*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
252*a7e14dcfSSatish Balay   }
253*a7e14dcfSSatish Balay   if (gdx >= 0.0) {
254*a7e14dcfSSatish Balay     ierr = PetscInfo1(ls,"Initial Line Search step is not descent direction (g's=%G)\n",gdx); CHKERRQ(ierr);
255*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_FAILED_ASCENT;
256*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
257*a7e14dcfSSatish Balay   }
258*a7e14dcfSSatish Balay 
259*a7e14dcfSSatish Balay   if (armP->nondescending) {
260*a7e14dcfSSatish Balay     fact = armP->sigma;
261*a7e14dcfSSatish Balay   } else {
262*a7e14dcfSSatish Balay     fact = armP->sigma * gdx;
263*a7e14dcfSSatish Balay   }
264*a7e14dcfSSatish Balay   ls->step = ls->initstep;
265*a7e14dcfSSatish Balay   while (ls->step >= ls->stepmin && (ls->nfeval+ls->nfgeval) < ls->max_funcs) {
266*a7e14dcfSSatish Balay     /* Calculate iterate */
267*a7e14dcfSSatish Balay     ierr = VecCopy(x,armP->work); CHKERRQ(ierr);
268*a7e14dcfSSatish Balay     ierr = VecAXPY(armP->work,ls->step,s); CHKERRQ(ierr);
269*a7e14dcfSSatish Balay     if (ls->bounded) {
270*a7e14dcfSSatish Balay       ierr = VecMedian(ls->lower,armP->work,ls->upper,armP->work); CHKERRQ(ierr);
271*a7e14dcfSSatish Balay     }
272*a7e14dcfSSatish Balay 
273*a7e14dcfSSatish Balay     /* Calculate function at new iterate */
274*a7e14dcfSSatish Balay     if (ls->hasobjective) {
275*a7e14dcfSSatish Balay       ierr = TaoLineSearchComputeObjective(ls,armP->work,f); CHKERRQ(ierr);
276*a7e14dcfSSatish Balay       g_computed=PETSC_FALSE;
277*a7e14dcfSSatish Balay     } else if (ls->usegts) {
278*a7e14dcfSSatish Balay       ierr = TaoLineSearchComputeObjectiveAndGTS(ls,armP->work,f,&gdx); CHKERRQ(ierr);
279*a7e14dcfSSatish Balay       g_computed=PETSC_FALSE;
280*a7e14dcfSSatish Balay     } else {
281*a7e14dcfSSatish Balay       ierr = TaoLineSearchComputeObjectiveAndGradient(ls,armP->work,f,g); CHKERRQ(ierr);
282*a7e14dcfSSatish Balay       g_computed=PETSC_TRUE;
283*a7e14dcfSSatish Balay     }
284*a7e14dcfSSatish Balay     if (ls->step == ls->initstep) {
285*a7e14dcfSSatish Balay       ls->f_fullstep = *f;
286*a7e14dcfSSatish Balay     }
287*a7e14dcfSSatish Balay 
288*a7e14dcfSSatish Balay     if (PetscIsInfOrNanReal(*f)) {
289*a7e14dcfSSatish Balay       ls->step *= armP->beta_inf;
290*a7e14dcfSSatish Balay     }
291*a7e14dcfSSatish Balay     else {
292*a7e14dcfSSatish Balay       /* Check descent condition */
293*a7e14dcfSSatish Balay       if (armP->nondescending && *f <= ref - ls->step*fact*ref)
294*a7e14dcfSSatish Balay 	break;
295*a7e14dcfSSatish Balay       if (!armP->nondescending && *f <= ref + ls->step*fact) {
296*a7e14dcfSSatish Balay         break;
297*a7e14dcfSSatish Balay       }
298*a7e14dcfSSatish Balay 
299*a7e14dcfSSatish Balay       ls->step *= armP->beta;
300*a7e14dcfSSatish Balay     }
301*a7e14dcfSSatish Balay   }
302*a7e14dcfSSatish Balay 
303*a7e14dcfSSatish Balay   /* Check termination */
304*a7e14dcfSSatish Balay   if (PetscIsInfOrNanReal(*f)) {
305*a7e14dcfSSatish Balay     ierr = PetscInfo(ls, "Function is inf or nan.\n"); CHKERRQ(ierr);
306*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_FAILED_INFORNAN;
307*a7e14dcfSSatish Balay   } else if (ls->step < ls->stepmin) {
308*a7e14dcfSSatish Balay     ierr = PetscInfo(ls, "Step length is below tolerance.\n"); CHKERRQ(ierr);
309*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_HALTED_RTOL;
310*a7e14dcfSSatish Balay   } else if ((ls->nfeval+ls->nfgeval) >= ls->max_funcs) {
311*a7e14dcfSSatish Balay     ierr = PetscInfo2(ls, "Number of line search function evals (%D) > maximum allowed (%D)\n",ls->nfeval+ls->nfgeval, ls->max_funcs); CHKERRQ(ierr);
312*a7e14dcfSSatish Balay     ls->reason = TAOLINESEARCH_HALTED_MAXFCN;
313*a7e14dcfSSatish Balay   }
314*a7e14dcfSSatish Balay   if (ls->reason) {
315*a7e14dcfSSatish Balay     PetscFunctionReturn(0);
316*a7e14dcfSSatish Balay   }
317*a7e14dcfSSatish Balay 
318*a7e14dcfSSatish Balay   /* Successful termination, update memory */
319*a7e14dcfSSatish Balay   armP->lastReference = ref;
320*a7e14dcfSSatish Balay   if (armP->replacementPolicy == REPLACE_FIFO) {
321*a7e14dcfSSatish Balay     armP->memory[armP->current++] = *f;
322*a7e14dcfSSatish Balay     if (armP->current >= armP->memorySize) {
323*a7e14dcfSSatish Balay       armP->current = 0;
324*a7e14dcfSSatish Balay     }
325*a7e14dcfSSatish Balay   } else {
326*a7e14dcfSSatish Balay     armP->current = idx;
327*a7e14dcfSSatish Balay     armP->memory[idx] = *f;
328*a7e14dcfSSatish Balay   }
329*a7e14dcfSSatish Balay 
330*a7e14dcfSSatish Balay   /* Update iterate and compute gradient */
331*a7e14dcfSSatish Balay   ierr = VecCopy(armP->work,x); CHKERRQ(ierr);
332*a7e14dcfSSatish Balay   if (!g_computed) {
333*a7e14dcfSSatish Balay     ierr = TaoLineSearchComputeGradient(ls, x, g); CHKERRQ(ierr);
334*a7e14dcfSSatish Balay   }
335*a7e14dcfSSatish Balay 
336*a7e14dcfSSatish Balay   /* Finish computations */
337*a7e14dcfSSatish Balay   ierr = PetscInfo2(ls, "%D function evals in line search, step = %G\n",ls->nfeval, ls->step); CHKERRQ(ierr);
338*a7e14dcfSSatish Balay 
339*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
340*a7e14dcfSSatish Balay }
341*a7e14dcfSSatish Balay 
342*a7e14dcfSSatish Balay EXTERN_C_BEGIN
343*a7e14dcfSSatish Balay #undef __FUNCT__
344*a7e14dcfSSatish Balay #define __FUNCT__ "TaoLineSearchCreate_Armijo"
345*a7e14dcfSSatish Balay PetscErrorCode TaoLineSearchCreate_Armijo(TaoLineSearch ls)
346*a7e14dcfSSatish Balay {
347*a7e14dcfSSatish Balay   TAOLINESEARCH_ARMIJO_CTX *armP;
348*a7e14dcfSSatish Balay   PetscErrorCode ierr;
349*a7e14dcfSSatish Balay 
350*a7e14dcfSSatish Balay   PetscFunctionBegin;
351*a7e14dcfSSatish Balay   PetscValidHeaderSpecific(ls,TAOLINESEARCH_CLASSID,1);
352*a7e14dcfSSatish Balay   ierr = PetscNewLog(ls,TAOLINESEARCH_ARMIJO_CTX, &armP);CHKERRQ(ierr);
353*a7e14dcfSSatish Balay 
354*a7e14dcfSSatish Balay   armP->memory = PETSC_NULL;
355*a7e14dcfSSatish Balay   armP->alpha = 1.0;
356*a7e14dcfSSatish Balay   armP->beta = 0.5;
357*a7e14dcfSSatish Balay   armP->beta_inf = 0.5;
358*a7e14dcfSSatish Balay   armP->sigma = 1e-4;
359*a7e14dcfSSatish Balay   armP->memorySize = 1;
360*a7e14dcfSSatish Balay   armP->referencePolicy = REFERENCE_MAX;
361*a7e14dcfSSatish Balay   armP->replacementPolicy = REPLACE_MRU;
362*a7e14dcfSSatish Balay   armP->nondescending=PETSC_FALSE;
363*a7e14dcfSSatish Balay   ls->data = (void*)armP;
364*a7e14dcfSSatish Balay   ls->initstep=1.0;
365*a7e14dcfSSatish Balay   ls->ops->setup=0;
366*a7e14dcfSSatish Balay   ls->ops->apply=TaoLineSearchApply_Armijo;
367*a7e14dcfSSatish Balay   ls->ops->view = TaoLineSearchView_Armijo;
368*a7e14dcfSSatish Balay   ls->ops->destroy = TaoLineSearchDestroy_Armijo;
369*a7e14dcfSSatish Balay   ls->ops->reset = TaoLineSearchReset_Armijo;
370*a7e14dcfSSatish Balay   ls->ops->setfromoptions = TaoLineSearchSetFromOptions_Armijo;
371*a7e14dcfSSatish Balay 
372*a7e14dcfSSatish Balay   PetscFunctionReturn(0);
373*a7e14dcfSSatish Balay }
374*a7e14dcfSSatish Balay EXTERN_C_END
375