xref: /petsc/src/tao/interface/taosolver_bounds.c (revision bcee047adeeb73090d7e36cc71e39fc287cdbb97)
1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2 
3 /*@
4   TaoSetVariableBounds - Sets the upper and lower bounds for the optimization problem
5 
6   Logically Collective
7 
8   Input Parameters:
9 + tao - the `Tao` context
10 . XL  - vector of lower bounds
11 - XU  - vector of upper bounds
12 
13   Level: beginner
14 
15 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetVariableBounds()`
16 @*/
17 PetscErrorCode TaoSetVariableBounds(Tao tao, Vec XL, Vec XU)
18 {
19   PetscFunctionBegin;
20   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
21   if (XL) PetscValidHeaderSpecific(XL, VEC_CLASSID, 2);
22   if (XU) PetscValidHeaderSpecific(XU, VEC_CLASSID, 3);
23   PetscCall(PetscObjectReference((PetscObject)XL));
24   PetscCall(PetscObjectReference((PetscObject)XU));
25   PetscCall(VecDestroy(&tao->XL));
26   PetscCall(VecDestroy(&tao->XU));
27   tao->XL      = XL;
28   tao->XU      = XU;
29   tao->bounded = (PetscBool)(XL || XU);
30   PetscFunctionReturn(PETSC_SUCCESS);
31 }
32 
33 /*@C
34   TaoSetVariableBoundsRoutine - Sets a function to be used to compute lower and upper variable bounds for the optimization
35 
36   Logically Collective
37 
38   Input Parameters:
39 + tao - the `Tao` context
40 . func - the bounds computation routine
41 - ctx - [optional] user-defined context for private data for the bounds computation (may be `NULL`)
42 
43   Calling sequence of `func`:
44 $ PetscErrorCode func(Tao tao, Vec xl, Vec xu, void *ctx);
45 + tao - the `Tao` solver
46 . xl  - vector of lower bounds
47 . xu  - vector of upper bounds
48 - ctx - the (optional) user-defined function context
49 
50   Level: beginner
51 
52   Note:
53   The func passed to `TaoSetVariableBoundsRoutine()` takes precedence over any values set in `TaoSetVariableBounds()`.
54 
55 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
56 @*/
57 PetscErrorCode TaoSetVariableBoundsRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
58 {
59   PetscFunctionBegin;
60   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
61   tao->user_boundsP       = ctx;
62   tao->ops->computebounds = func;
63   tao->bounded            = func ? PETSC_TRUE : PETSC_FALSE;
64   PetscFunctionReturn(PETSC_SUCCESS);
65 }
66 
67 /*@
68   TaoGetVariableBounds - Gets the upper and lower bounds vectors set with `TaoSetVariableBounds()`
69 
70   Not Collective
71 
72   Input Parameter:
73 . tao - the `Tao` context
74 
75   Output Parameters:
76 + XL  - vector of lower bounds
77 - XU  - vector of upper bounds
78 
79   Level: beginner
80 
81 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
82 @*/
83 PetscErrorCode TaoGetVariableBounds(Tao tao, Vec *XL, Vec *XU)
84 {
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
87   if (XL) *XL = tao->XL;
88   if (XU) *XU = tao->XU;
89   PetscFunctionReturn(PETSC_SUCCESS);
90 }
91 
92 /*@C
93    TaoComputeVariableBounds - Compute the variable bounds using the
94    routine set by `TaoSetVariableBoundsRoutine()`.
95 
96    Collective
97 
98    Input Parameter:
99 .  tao - the `Tao` context
100 
101    Level: developer
102 
103 .seealso: [](ch_tao), `Tao`, `TaoSetVariableBoundsRoutine()`, `TaoSetVariableBounds()`
104 @*/
105 PetscErrorCode TaoComputeVariableBounds(Tao tao)
106 {
107   PetscFunctionBegin;
108   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
109   if (tao->ops->computebounds) {
110     if (!tao->XL) {
111       PetscCall(VecDuplicate(tao->solution, &tao->XL));
112       PetscCall(VecSet(tao->XL, PETSC_NINFINITY));
113     }
114     if (!tao->XU) {
115       PetscCall(VecDuplicate(tao->solution, &tao->XU));
116       PetscCall(VecSet(tao->XU, PETSC_INFINITY));
117     }
118     PetscCallBack("Tao callback variable bounds", (*tao->ops->computebounds)(tao, tao->XL, tao->XU, tao->user_boundsP));
119   }
120   PetscFunctionReturn(PETSC_SUCCESS);
121 }
122 
123 /*@
124   TaoSetInequalityBounds - Sets the upper and lower bounds
125 
126   Logically Collective
127 
128   Input Parameters:
129 + tao - the `Tao` context
130 . IL  - vector of lower bounds
131 - IU  - vector of upper bounds
132 
133   Level: beginner
134 
135 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoGetInequalityBounds()`
136 @*/
137 PetscErrorCode TaoSetInequalityBounds(Tao tao, Vec IL, Vec IU)
138 {
139   PetscFunctionBegin;
140   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
141   if (IL) PetscValidHeaderSpecific(IL, VEC_CLASSID, 2);
142   if (IU) PetscValidHeaderSpecific(IU, VEC_CLASSID, 3);
143   PetscCall(PetscObjectReference((PetscObject)IL));
144   PetscCall(PetscObjectReference((PetscObject)IU));
145   PetscCall(VecDestroy(&tao->IL));
146   PetscCall(VecDestroy(&tao->IU));
147   tao->IL               = IL;
148   tao->IU               = IU;
149   tao->ineq_doublesided = (PetscBool)(IL || IU);
150   PetscFunctionReturn(PETSC_SUCCESS);
151 }
152 
153 /*@
154   TaoGetInequalityBounds - Gets the upper and lower bounds set via `TaoSetInequalityBounds()`
155 
156   Logically Collective
157 
158   Input Parameter:
159 . tao - the `Tao` context
160 
161   Output Parameters:
162 + IL  - vector of lower bounds
163 - IU  - vector of upper bounds
164 
165   Level: beginner
166 
167 .seealso: [](ch_tao), `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetInequalityBounds()`
168 @*/
169 PetscErrorCode TaoGetInequalityBounds(Tao tao, Vec *IL, Vec *IU)
170 {
171   PetscFunctionBegin;
172   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
173   if (IL) *IL = tao->IL;
174   if (IU) *IU = tao->IU;
175   PetscFunctionReturn(PETSC_SUCCESS);
176 }
177 
178 /*@C
179    TaoComputeConstraints - Compute the variable bounds using the
180    routine set by `TaoSetConstraintsRoutine()`.
181 
182    Collective
183 
184    Input Parameters:
185 +  tao - the `Tao` context
186 -  X - location to evaluate the constraints
187 
188    Output Parameter:
189 .  C - the constraints
190 
191    Level: developer
192 
193 .seealso: [](ch_tao), `Tao`, `TaoSetConstraintsRoutine()`, `TaoComputeJacobian()`
194 @*/
195 PetscErrorCode TaoComputeConstraints(Tao tao, Vec X, Vec C)
196 {
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
199   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
200   PetscValidHeaderSpecific(C, VEC_CLASSID, 3);
201   PetscCheckSameComm(tao, 1, X, 2);
202   PetscCheckSameComm(tao, 1, C, 3);
203   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, C, NULL));
204   PetscCallBack("Tao callback constraints", (*tao->ops->computeconstraints)(tao, X, C, tao->user_conP));
205   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, C, NULL));
206   tao->nconstraints++;
207   PetscFunctionReturn(PETSC_SUCCESS);
208 }
209 
210 /*@C
211   TaoSetConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
212 
213   Logically Collective
214 
215   Input Parameters:
216 + tao - the `Tao` context
217 . c   - A vector that will be used to store constraint evaluation
218 . func - the bounds computation routine
219 - ctx - [optional] user-defined context for private data for the constraints computation (may be `NULL`)
220 
221   Calling sequence of `func`:
222 $ PetscErrorCode func(Tao tao, Vec x, Vec c, void *ctx);
223 + tao - the `Tao` solver
224 . x   - point to evaluate constraints
225 . c   - vector constraints evaluated at `x`
226 - ctx - the (optional) user-defined function context
227 
228   Level: intermediate
229 
230 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariablevBounds()`
231 @*/
232 PetscErrorCode TaoSetConstraintsRoutine(Tao tao, Vec c, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
233 {
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
236   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
237   PetscCall(PetscObjectReference((PetscObject)c));
238   PetscCall(VecDestroy(&tao->constraints));
239   tao->constrained             = func ? PETSC_TRUE : PETSC_FALSE;
240   tao->constraints             = c;
241   tao->user_conP               = ctx;
242   tao->ops->computeconstraints = func;
243   PetscFunctionReturn(PETSC_SUCCESS);
244 }
245 
246 /*@
247   TaoComputeDualVariables - Computes the dual vectors corresponding to the bounds
248   of the variables
249 
250   Collective
251 
252   Input Parameter:
253 . tao - the `Tao` context
254 
255   Output Parameters:
256 + DL - dual variable vector for the lower bounds
257 - DU - dual variable vector for the upper bounds
258 
259   Level: advanced
260 
261   Note:
262   DL and DU should be created before calling this routine.  If calling
263   this routine after using an unconstrained solver, `DL` and `DU` are set to all
264   zeros.
265 
266 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoSetVariableBounds()`
267 @*/
268 PetscErrorCode TaoComputeDualVariables(Tao tao, Vec DL, Vec DU)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
272   PetscValidHeaderSpecific(DL, VEC_CLASSID, 2);
273   PetscValidHeaderSpecific(DU, VEC_CLASSID, 3);
274   PetscCheckSameComm(tao, 1, DL, 2);
275   PetscCheckSameComm(tao, 1, DU, 3);
276   if (tao->ops->computedual) {
277     PetscUseTypeMethod(tao, computedual, DL, DU);
278   } else {
279     PetscCall(VecSet(DL, 0.0));
280     PetscCall(VecSet(DU, 0.0));
281   }
282   PetscFunctionReturn(PETSC_SUCCESS);
283 }
284 
285 /*@
286   TaoGetDualVariables - Gets the dual vectors
287 
288   Collective
289 
290   Input Parameter:
291 . tao - the `Tao` context
292 
293   Output Parameters:
294 + DE - dual variable vector for the lower bounds
295 - DI - dual variable vector for the upper bounds
296 
297   Level: advanced
298 
299 .seealso: [](ch_tao), `Tao`, `TaoComputeDualVariables()`
300 @*/
301 PetscErrorCode TaoGetDualVariables(Tao tao, Vec *DE, Vec *DI)
302 {
303   PetscFunctionBegin;
304   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
305   if (DE) *DE = tao->DE;
306   if (DI) *DI = tao->DI;
307   PetscFunctionReturn(PETSC_SUCCESS);
308 }
309 
310 /*@C
311   TaoSetEqualityConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
312 
313   Logically Collective
314 
315   Input Parameters:
316 + tao - the `Tao` context
317 . ce   - A vector that will be used to store equality constraint evaluation
318 . func - the bounds computation routine
319 - ctx - [optional] user-defined context for private data for the equality constraints computation (may be `NULL`)
320 
321   Calling sequence of `func`:
322 $ PetscErrorCode func(Tao tao, Vec x, Vec ce, void *ctx);
323 + tao - the `Tao` solver
324 . x   - point to evaluate equality constraints
325 . ce   - vector of equality constraints evaluated at x
326 - ctx - the (optional) user-defined function context
327 
328   Level: intermediate
329 
330 .seealso: [](ch_tao), `Tao`, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
331 @*/
332 PetscErrorCode TaoSetEqualityConstraintsRoutine(Tao tao, Vec ce, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
333 {
334   PetscFunctionBegin;
335   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
336   if (ce) PetscValidHeaderSpecific(ce, VEC_CLASSID, 2);
337   PetscCall(PetscObjectReference((PetscObject)ce));
338   PetscCall(VecDestroy(&tao->constraints_equality));
339   tao->eq_constrained                  = func ? PETSC_TRUE : PETSC_FALSE;
340   tao->constraints_equality            = ce;
341   tao->user_con_equalityP              = ctx;
342   tao->ops->computeequalityconstraints = func;
343   PetscFunctionReturn(PETSC_SUCCESS);
344 }
345 
346 /*@C
347   TaoSetInequalityConstraintsRoutine - Sets a function to be used to compute constraints.  Tao only handles constraints under certain conditions, see [](ch_tao) for details
348 
349   Logically Collective
350 
351   Input Parameters:
352 + tao - the `Tao` context
353 . ci   - A vector that will be used to store inequality constraint evaluation
354 . func - the bounds computation routine
355 - ctx - [optional] user-defined context for private data for the inequality constraints computation (may be `NULL`)
356 
357   Calling sequence of `func`:
358 $ PetscErrorCode func(Tao tao, Vec x, Vec ci, void *ctx);
359 + tao - the `Tao` solver
360 . x   - point to evaluate inequality constraints
361 . ci   - vector of inequality constraints evaluated at x
362 - ctx - the (optional) user-defined function context
363 
364   Level: intermediate
365 
366 .seealso: [](ch_tao), `Tao, `TaoSetObjective()`, `TaoSetHessian()`, `TaoSetObjectiveAndGradient()`, `TaoSetVariableBounds()`
367 @*/
368 PetscErrorCode TaoSetInequalityConstraintsRoutine(Tao tao, Vec ci, PetscErrorCode (*func)(Tao, Vec, Vec, void *), void *ctx)
369 {
370   PetscFunctionBegin;
371   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
372   if (ci) PetscValidHeaderSpecific(ci, VEC_CLASSID, 2);
373   PetscCall(PetscObjectReference((PetscObject)ci));
374   PetscCall(VecDestroy(&tao->constraints_inequality));
375   tao->constraints_inequality            = ci;
376   tao->ineq_constrained                  = func ? PETSC_TRUE : PETSC_FALSE;
377   tao->user_con_inequalityP              = ctx;
378   tao->ops->computeinequalityconstraints = func;
379   PetscFunctionReturn(PETSC_SUCCESS);
380 }
381 
382 /*@C
383    TaoComputeEqualityConstraints - Compute the variable bounds using the
384    routine set by `TaoSetEqualityConstraintsRoutine()`.
385 
386    Collective
387 
388    Input Parameter:
389 .  tao - the `Tao` context
390 
391    Output Parameters:
392 +  X - point the equality constraints were evaluated on
393 -  CE   - vector of equality constraints evaluated at X
394 
395    Level: developer
396 
397 .seealso: [](ch_tao), `Tao`, `TaoSetEqualityConstraintsRoutine()`, `TaoComputeJacobianEquality()`, `TaoComputeInequalityConstraints()`
398 @*/
399 PetscErrorCode TaoComputeEqualityConstraints(Tao tao, Vec X, Vec CE)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
403   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
404   PetscValidHeaderSpecific(CE, VEC_CLASSID, 3);
405   PetscCheckSameComm(tao, 1, X, 2);
406   PetscCheckSameComm(tao, 1, CE, 3);
407   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, CE, NULL));
408   PetscCallBack("Tao callback equality constraints", (*tao->ops->computeequalityconstraints)(tao, X, CE, tao->user_con_equalityP));
409   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, CE, NULL));
410   tao->nconstraints++;
411   PetscFunctionReturn(PETSC_SUCCESS);
412 }
413 
414 /*@C
415    TaoComputeInequalityConstraints - Compute the variable bounds using the
416    routine set by `TaoSetInequalityConstraintsRoutine()`.
417 
418    Collective
419 
420    Input Parameter:
421 .  tao - the `Tao` context
422 
423    Output Parameters:
424 +  X - point the inequality constraints were evaluated on
425 -  CE   - vector of inequality constraints evaluated at X
426 
427    Level: developer
428 
429 .seealso: [](ch_tao), `Tao`, `TaoSetInequalityConstraintsRoutine()`, `TaoComputeJacobianInequality()`, `TaoComputeEqualityConstraints()`
430 @*/
431 PetscErrorCode TaoComputeInequalityConstraints(Tao tao, Vec X, Vec CI)
432 {
433   PetscFunctionBegin;
434   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
435   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
436   PetscValidHeaderSpecific(CI, VEC_CLASSID, 3);
437   PetscCheckSameComm(tao, 1, X, 2);
438   PetscCheckSameComm(tao, 1, CI, 3);
439   PetscCall(PetscLogEventBegin(TAO_ConstraintsEval, tao, X, CI, NULL));
440   PetscCallBack("Tao callback inequality constraints", (*tao->ops->computeinequalityconstraints)(tao, X, CI, tao->user_con_inequalityP));
441   PetscCall(PetscLogEventEnd(TAO_ConstraintsEval, tao, X, CI, NULL));
442   tao->nconstraints++;
443   PetscFunctionReturn(PETSC_SUCCESS);
444 }
445