SciPy optimizer does redundant function evaluations e.g. for AMICI objectives
Problem/Bug description
The scipy optimizer calls fun and grad via object via objective.get_fun and objective.get_grad, see
https://github.com/ICB-DCM/pyPESTO/blob/4c30abfca56ba714c302141cd44a9dd366bff4bb/pypesto/optimize/optimizer.py#L420
and for the function/gradient definition see (and line below) https://github.com/ICB-DCM/pyPESTO/blob/4c30abfca56ba714c302141cd44a9dd366bff4bb/pypesto/optimize/optimizer.py#L399
The get_grad function is defined here (not. overwritten in the AmiciObjective...)
https://github.com/ICB-DCM/pyPESTO/blob/4c30abfca56ba714c302141cd44a9dd366bff4bb/pypesto/objective/base.py#L351
and therefore the ODE is evaluated twice, once for fun, once implicitly for grad.
Solution
If one defines fun to return a tuple (f_val, grad_val), and sets jac=True, scipy is able to deal with objectives, that return both simultaneously, see
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html