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