Hello,

Thanks for your response, Hong. I see that all cost functionals are evaluated 
in a single backward run. However, I want to do it separately. I want to 
isolate the evaluation of the gradients for each cost functional. Can you 
please elaborate on how to reuse the trajectory for multiple calls? 
Specifically, how to set the trajectory back to the end so I can call 
TSAdjoint() again?

Miguel
From: "Zhang, Hong" <[email protected]>
Date: Monday, December 28, 2020 at 6:16 PM
To: "Salazar De Troya, Miguel" <[email protected]>
Cc: "Salazar De Troya, Miguel via petsc-users" <[email protected]>
Subject: Re: [petsc-users] Calculating adjoint of more than one cost function 
separately




On Dec 27, 2020, at 5:01 PM, Salazar De Troya, Miguel via petsc-users 
<[email protected]<mailto:[email protected]>> wrote:

Hello,

I am interested in calculating the gradients of an optimization problem with 
one goal and one constraint functions which need TSAdjoint for their adjoints. 
I’d like to call each of their adjoints in different calls, but it does not 
seem to be possible without making compromises.

If you are calculating the derivatives to the same set of parameters, the 
adjoints of all cost functionals can be done with a single backward run.


For instance, one could set TSCreateQuadratureTS() and TSSetCostGradients() 
with different quadratures (and their gradients) for each adjoint call (one at 
a time). This would evaluate the cost functions in the backwards run though, 
whereas one typically computes the cost functions in a different routine than 
the adjoint call (like in line searches evaluations)

The second argument of TSCreateQuadratureTS() allows you to choose if the 
quadrature is evaluated in the forward run or in the backward run.  The choice 
typically depends on the optimization algorithms. Some optimization algorithms 
may expect users to provide an objective function and its gradient as a bundle; 
in this case, the choice does not make a difference. Some other algorithms may 
occasionally evaluate the objective function without evaluating its gradient, 
then evaluating the quadrature in the forward run is definitely a better choice.


One could also set TSCreateQuadratureTS() with the goal and the constraint 
functions to be evaluated at the forward run (as typically done when computing 
the cost function). The problem would be that the adjoint call now requires two 
sets of gradients for TSSetCostGradients() and their adjoint are calculated 
together, costing twice if your routines for the cost and the constraint 
gradients are separated.

You can put the two sets of gradients in vector arrays and pass them to 
TSSetCostGradients() together. Only one call to TSAdjointSolve() is needed. See 
the example src/ts/tutorials/ex20adj.c, where we have two independent cost 
functionals, and their adjoints correspond to lambda[0]/mup[0] and 
lambda[1]/mup[1] respectively. After performing a TSAdjontSolve, you will get 
the gradients for both cost functionals.



The only solution I can think of is to set TSCreateQuadratureTS() with both the 
goal and constraint functions in the forward run. Then, in the adjoint calls, 
reset TSCreateQuadratureTS() with just the cost function I am interested in 
(either the goal or the constraint) and set just a single TSSetCostGradients(). 
Will this work? Are there better alternatives?

TSCreateQuadratureTS() is needed only when you have integral terms in the cost 
functionals. It has nothing to do with the procedure to compute the adjoints 
for multiple cost functionals simultaneously. Do you have integrals in both the 
goal and the constraint? If so, you can create one quadrature TS and evaluate 
both integrals together. For example, you may have r[0] (the first element of 
the output vector in your cost integrand) for the goal and r[1] for the 
constraint. Just be careful that the adjoint variables (array lambda[]/mup[]) 
should be organized in the same order.



Even if successful, there is the problem that the trajectory goes back to the 
beginning when we perform a TSAdjointSolve() call. Subsequent calls to 
TSAdjointSolve() (for instance for another cost function) are invalid because 
the trajectory is not set at the end of the simulation. One needs to call the 
forward problem to bring it back to the end. Is there a quick way to set the 
trajectory state to the last time step without having to run the forward 
problem? I am attaching an example to illustrate this issue. One can uncomment 
lines 120-122 to obtain the right value of the derivative.

Most likely you need only one call to TSAdjointSolve(). Reusing the trajectory 
for multiple calls is also doable. But I doubt you would need it.

Hong (Mr.)



Thanks
Miguel

Miguel A. Salazar de Troya
Postdoctoral Researcher, Lawrence Livermore National Laboratory
B141
Rm: 1085-5
Ph: 1(925) 422-6411
<simple-ode.py>


Reply via email to