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