xref: /petsc/src/tao/interface/taosolver_fg.c (revision 8f3f2bf165a4f0437decc2ac63b7a7aad35aeb6e)
1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2 
3 /*@
4   TaoSetInitialVector - Sets the initial guess for the solve
5 
6   Logically collective on Tao
7 
8   Input Parameters:
9 + tao - the Tao context
10 - x0  - the initial guess
11 
12   Level: beginner
13 .seealso: TaoCreate(), TaoSolve()
14 @*/
15 
16 PetscErrorCode TaoSetInitialVector(Tao tao, Vec x0)
17 {
18   PetscErrorCode ierr;
19 
20   PetscFunctionBegin;
21   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
22   if (x0) {
23     PetscValidHeaderSpecific(x0,VEC_CLASSID,2);
24     PetscObjectReference((PetscObject)x0);
25   }
26   ierr = VecDestroy(&tao->solution);CHKERRQ(ierr);
27   tao->solution = x0;
28   PetscFunctionReturn(0);
29 }
30 
31 /*@
32   TaoComputeGradient - Computes the gradient of the objective function
33 
34   Collective on Tao
35 
36   Input Parameters:
37 + tao - the Tao context
38 - X - input vector
39 
40   Output Parameter:
41 . G - gradient vector
42 
43   Notes:
44     TaoComputeGradient() is typically used within minimization implementations,
45   so most users would not generally call this routine themselves.
46 
47   Level: advanced
48 
49 .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine()
50 @*/
51 PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
52 {
53   PetscErrorCode ierr;
54   PetscReal      dummy;
55 
56   PetscFunctionBegin;
57   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
58   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
59   PetscValidHeaderSpecific(G,VEC_CLASSID,2);
60   PetscCheckSameComm(tao,1,X,2);
61   PetscCheckSameComm(tao,1,G,3);
62   ierr = VecLockPush(X);CHKERRQ(ierr);
63   if (tao->ops->computegradient) {
64     ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
65     PetscStackPush("Tao user gradient evaluation routine");
66     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
67     PetscStackPop;
68     ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
69     tao->ngrads++;
70   } else if (tao->ops->computeobjectiveandgradient) {
71     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
72     PetscStackPush("Tao user objective/gradient evaluation routine");
73     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr);
74     PetscStackPop;
75     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
76     tao->nfuncgrads++;
77   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called");
78   ierr = VecLockPop(X);CHKERRQ(ierr);
79   PetscFunctionReturn(0);
80 }
81 
82 /*@
83   TaoComputeObjective - Computes the objective function value at a given point
84 
85   Collective on Tao
86 
87   Input Parameters:
88 + tao - the Tao context
89 - X - input vector
90 
91   Output Parameter:
92 . f - Objective value at X
93 
94   Notes:
95     TaoComputeObjective() is typically used within minimization implementations,
96   so most users would not generally call this routine themselves.
97 
98   Level: advanced
99 
100 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
101 @*/
102 PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
103 {
104   PetscErrorCode ierr;
105   Vec            temp;
106 
107   PetscFunctionBegin;
108   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
109   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
110   PetscCheckSameComm(tao,1,X,2);
111   ierr = VecLockPush(X);CHKERRQ(ierr);
112   if (tao->ops->computeobjective) {
113     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
114     PetscStackPush("Tao user objective evaluation routine");
115     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
116     PetscStackPop;
117     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
118     tao->nfuncs++;
119   } else if (tao->ops->computeobjectiveandgradient) {
120     ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr);
121     ierr = VecDuplicate(X,&temp);CHKERRQ(ierr);
122     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr);
123     PetscStackPush("Tao user objective/gradient evaluation routine");
124     ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr);
125     PetscStackPop;
126     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr);
127     ierr = VecDestroy(&temp);CHKERRQ(ierr);
128     tao->nfuncgrads++;
129   }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called");
130   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
131   ierr = VecLockPop(X);CHKERRQ(ierr);
132   PetscFunctionReturn(0);
133 }
134 
135 /*@
136   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point
137 
138   Collective on Tao
139 
140   Input Parameters:
141 + tao - the Tao context
142 - X - input vector
143 
144   Output Parameter:
145 + f - Objective value at X
146 - g - Gradient vector at X
147 
148   Notes:
149     TaoComputeObjectiveAndGradient() is typically used within minimization implementations,
150   so most users would not generally call this routine themselves.
151 
152   Level: advanced
153 
154 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
155 @*/
156 PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
157 {
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
162   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
163   PetscValidHeaderSpecific(G,VEC_CLASSID,4);
164   PetscCheckSameComm(tao,1,X,2);
165   PetscCheckSameComm(tao,1,G,4);
166   ierr = VecLockPush(X);CHKERRQ(ierr);
167   if (tao->ops->computeobjectiveandgradient) {
168     ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
169     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
170       ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr);
171       ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr);
172     } else {
173       PetscStackPush("Tao user objective/gradient evaluation routine");
174       ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr);
175       PetscStackPop;
176     }
177     ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr);
178     tao->nfuncgrads++;
179   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
180     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
181     PetscStackPush("Tao user objective evaluation routine");
182     ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr);
183     PetscStackPop;
184     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
185     tao->nfuncs++;
186     ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
187     PetscStackPush("Tao user gradient evaluation routine");
188     ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr);
189     PetscStackPop;
190     ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr);
191     tao->ngrads++;
192   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set");
193   ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr);
194   ierr = VecLockPop(X);CHKERRQ(ierr);
195   PetscFunctionReturn(0);
196 }
197 
198 /*@C
199   TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization
200 
201   Logically collective on Tao
202 
203   Input Parameter:
204 + tao - the Tao context
205 . func - the objective function
206 - ctx - [optional] user-defined context for private data for the function evaluation
207         routine (may be NULL)
208 
209   Calling sequence of func:
210 $      func (Tao tao, Vec x, PetscReal *f, void *ctx);
211 
212 + x - input vector
213 . f - function value
214 - ctx - [optional] user-defined function context
215 
216   Level: beginner
217 
218 .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
219 @*/
220 PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
221 {
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
224   tao->user_objP = ctx;
225   tao->ops->computeobjective = func;
226   PetscFunctionReturn(0);
227 }
228 
229 /*@C
230   TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications
231 
232   Logically collective on Tao
233 
234   Input Parameter:
235 + tao - the Tao context
236 . func - the objective function evaluation routine
237 - ctx - [optional] user-defined context for private data for the function evaluation
238         routine (may be NULL)
239 
240   Calling sequence of func:
241 $      func (Tao tao, Vec x, Vec f, void *ctx);
242 
243 + x - input vector
244 . f - function value vector
245 - ctx - [optional] user-defined function context
246 
247   Level: beginner
248 
249 .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine()
250 @*/
251 PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
252 {
253   PetscFunctionBegin;
254   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
255   PetscValidHeaderSpecific(sepobj, VEC_CLASSID,2);
256   tao->user_sepobjP = ctx;
257   tao->sep_objective = sepobj;
258   tao->ops->computeseparableobjective = func;
259   PetscFunctionReturn(0);
260 }
261 
262 /*@
263   TaoSetSeparableObjectiveWeights - Give weights for the separable objective values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give. If this function is not used, or if sigma_v and sigma_w are both NULL, then the default identity matrix will be used for weights.
264 
265   Collective on Tao
266 
267   Input Parameters:
268 + tao - the Tao context
269 . sigma_v - vector of weights (diagonal terms only)
270 . n       - the number of weights (if using off-diagonal)
271 . rows    - index list of rows for sigma_w
272 . cols    - index list of columns for sigma_w
273 - vals - array of weights
274 
275 
276 
277   Note: Either sigma_v or sigma_w (or both) should be NULL
278 
279   Level: intermediate
280 
281 .seealso: TaoSetSeparableObjectiveRoutine()
282 @*/
283 PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
284 {
285   PetscErrorCode ierr;
286   PetscInt       i;
287   PetscFunctionBegin;
288   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
289   ierr = VecDestroy(&tao->sep_weights_v);CHKERRQ(ierr);
290   tao->sep_weights_v=sigma_v;
291   if (sigma_v) {
292     ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr);
293   }
294   if (vals) {
295     if (tao->sep_weights_n) {
296       ierr = PetscFree(tao->sep_weights_rows);CHKERRQ(ierr);
297       ierr = PetscFree(tao->sep_weights_cols);CHKERRQ(ierr);
298       ierr = PetscFree(tao->sep_weights_w);CHKERRQ(ierr);
299     }
300     ierr = PetscMalloc1(n,&tao->sep_weights_rows);CHKERRQ(ierr);
301     ierr = PetscMalloc1(n,&tao->sep_weights_cols);CHKERRQ(ierr);
302     ierr = PetscMalloc1(n,&tao->sep_weights_w);CHKERRQ(ierr);
303     tao->sep_weights_n=n;
304     for (i=0;i<n;i++) {
305       tao->sep_weights_rows[i]=rows[i];
306       tao->sep_weights_cols[i]=cols[i];
307       tao->sep_weights_w[i]=vals[i];
308     }
309   } else {
310     tao->sep_weights_n=0;
311     tao->sep_weights_rows=0;
312     tao->sep_weights_cols=0;
313   }
314   PetscFunctionReturn(0);
315 }
316 /*@
317   TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications)
318 
319   Collective on Tao
320 
321   Input Parameters:
322 + tao - the Tao context
323 - X - input vector
324 
325   Output Parameter:
326 . f - Objective vector at X
327 
328   Notes:
329     TaoComputeSeparableObjective() is typically used within minimization implementations,
330   so most users would not generally call this routine themselves.
331 
332   Level: advanced
333 
334 .seealso: TaoSetSeparableObjectiveRoutine()
335 @*/
336 PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F)
337 {
338   PetscErrorCode ierr;
339 
340   PetscFunctionBegin;
341   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
342   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
343   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
344   PetscCheckSameComm(tao,1,X,2);
345   PetscCheckSameComm(tao,1,F,3);
346   if (tao->ops->computeseparableobjective) {
347     ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
348     PetscStackPush("Tao user separable objective evaluation routine");
349     ierr = (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);CHKERRQ(ierr);
350     PetscStackPop;
351     ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr);
352     tao->nfuncs++;
353   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called");
354   ierr = PetscInfo(tao,"TAO separable function evaluation.\n");CHKERRQ(ierr);
355   PetscFunctionReturn(0);
356 }
357 
358 /*@C
359   TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization
360 
361   Logically collective on Tao
362 
363   Input Parameter:
364 + tao - the Tao context
365 . func - the gradient function
366 - ctx - [optional] user-defined context for private data for the gradient evaluation
367         routine (may be NULL)
368 
369   Calling sequence of func:
370 $      func (Tao tao, Vec x, Vec g, void *ctx);
371 
372 + x - input vector
373 . g - gradient value (output)
374 - ctx - [optional] user-defined function context
375 
376   Level: beginner
377 
378 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
379 @*/
380 PetscErrorCode TaoSetGradientRoutine(Tao tao,  PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
381 {
382   PetscFunctionBegin;
383   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
384   tao->user_gradP = ctx;
385   tao->ops->computegradient = func;
386   PetscFunctionReturn(0);
387 }
388 
389 /*@C
390   TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization
391 
392   Logically collective on Tao
393 
394   Input Parameter:
395 + tao - the Tao context
396 . func - the gradient function
397 - ctx - [optional] user-defined context for private data for the gradient evaluation
398         routine (may be NULL)
399 
400   Calling sequence of func:
401 $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);
402 
403 + x - input vector
404 . f - objective value (output)
405 . g - gradient value (output)
406 - ctx - [optional] user-defined function context
407 
408   Level: beginner
409 
410 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
411 @*/
412 PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx)
413 {
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
416   tao->user_objgradP = ctx;
417   tao->ops->computeobjectiveandgradient = func;
418   PetscFunctionReturn(0);
419 }
420 
421 /*@
422   TaoIsObjectiveDefined -- Checks to see if the user has
423   declared an objective-only routine.  Useful for determining when
424   it is appropriate to call TaoComputeObjective() or
425   TaoComputeObjectiveAndGradient()
426 
427   Collective on Tao
428 
429   Input Parameter:
430 + tao - the Tao context
431 - ctx - PETSC_TRUE if objective function routine is set by user,
432         PETSC_FALSE otherwise
433   Level: developer
434 
435 .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined()
436 @*/
437 PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
438 {
439   PetscFunctionBegin;
440   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
441   if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE;
442   else *flg = PETSC_TRUE;
443   PetscFunctionReturn(0);
444 }
445 
446 /*@
447   TaoIsGradientDefined -- Checks to see if the user has
448   declared an objective-only routine.  Useful for determining when
449   it is appropriate to call TaoComputeGradient() or
450   TaoComputeGradientAndGradient()
451 
452   Not Collective
453 
454   Input Parameter:
455 + tao - the Tao context
456 - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise
457   Level: developer
458 
459 .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined()
460 @*/
461 PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
462 {
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
465   if (tao->ops->computegradient == 0) *flg = PETSC_FALSE;
466   else *flg = PETSC_TRUE;
467   PetscFunctionReturn(0);
468 }
469 
470 /*@
471   TaoIsObjectiveAndGradientDefined -- Checks to see if the user has
472   declared a joint objective/gradient routine.  Useful for determining when
473   it is appropriate to call TaoComputeObjective() or
474   TaoComputeObjectiveAndGradient()
475 
476   Not Collective
477 
478   Input Parameter:
479 + tao - the Tao context
480 - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise
481   Level: developer
482 
483 .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined()
484 @*/
485 PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(tao,TAO_CLASSID,1);
489   if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE;
490   else *flg = PETSC_TRUE;
491   PetscFunctionReturn(0);
492 }
493