QuantumControl.jl icon indicating copy to clipboard operation
QuantumControl.jl copied to clipboard

Optimizer options interface

Open FHoltorf opened this issue 2 years ago • 3 comments

Hey,

I would like to solve some quantum control problems via GRAPE but I need high precision with regard to stationarity. Unfortunately, I can't use Optim.jl because I have bounds on the control drives and it seems I am also not able to strengthen the convergence criteria in the L-BFGS-B default flexibly enough. I think that is the case at least? The GrapeResult object does not carry gradient information so I assume cannot use that to define my own convergence criterion and the corresponding LBFGSB.jl optionpgtol = 1e-5 appears to be hardcoded (see https://github.com/JuliaQuantumControl/GRAPE.jl/blob/83295ce48621430db739ce2cdee4afba5b9ee41e/src/backend_lbfgsb.jl#L8).

Am I missing a way to set the convergence criterion? If not, what's the better way to address that issue? Support bounds for Optim.jl optimizers, pass gradient information to the result object, or admit kwargs to set options for the default optimizer?

Thanks! Flemming

FHoltorf avatar Dec 07 '23 18:12 FHoltorf

I need high precision with regard to stationarity

I'm not sure what that means. What's "stationarity"?

define my own convergence criterion

There's infohook for that, in principle, which gets the GrapeWrk object which has access to lots of internal data, including gradient information, although not the LBFGSB optimizer, which might be nice to have. These internals need a pretty major overhaul at some point.

the corresponding LBFGSB.jl option pgtol = 1e-5 appears to be hardcoded

There's no particular reason this has to be hardcoded, except that I haven't really looked at what these parameters do or how they might go into a coherent interface for the GRAPE package. If being able to set pgtol (the same way you can set g_tol for Optim) solves your problem, I can just make that an option. Same for the hardcoded factr and m.

Support bounds for Optim.jl optimizers

That would be something on the long-term TODO list

pass gradient information to the result object

Probably not… Stuff like that should generally be in the internal "workplace" object (GrapeWrk). How would having it in the result object help you?

admit kwargs to set options for the default optimizer?

Yes, definitely. I can do that this weekend if that helps you, as an "experimental feature" (subject to change in future versions if I can make the API more coherent)

goerz avatar Dec 07 '23 18:12 goerz

Thanks for the quick reply!

I'm not sure what that means. What's "stationarity"?

Stationarity is just jargon for a condition that encodes if a point is a stationary point for the underlying optimization problem (so in the simplest setting: a condition that encodes how close the gradient is to vanishing) which is of course often used as part of convergence criterion. Here, the default L-BFGS-B method declares convergence when the norm of the projected gradient is < pgtol (=1e-5) but I would like for it to keep going to higher precision in this sense. Sorry, I didn't explain well what my problem was in practice :).

If being able to set pgtol (the same way you can set g_tol for Optim) solves your problem, I can just make that an option. Same for the hardcoded factr and m.

I personally only need pgtol right now but I think it could generally be useful to expose all (or at least the common) solver options (since different choices for them can in principle matter a lot). It might not be worth the effort if no-one else uses it, though.

How would having it in the result object help you? My (possibly incorrect) understanding is that you allow a user to define their own convergence criteria through the check_covergence kwarg by defining a function on result object.

If the gradient was carried by this object I thought I would just be able to define my convergence criterion accordingly. Something along the lines ofres -> norm(res.gradient) < 1e-9. That would only work, however, if this would not be overwritten by the solver internal convergence checks.

There's infohook for that, in principle, which gets the GrapeWrk object which has access to lots of internal data, including gradient information, although not the LBFGSB optimizer, which might be nice to have. These internals need a pretty major overhaul at some point.

Together with what I wrote above, maybe this could already solve my problem? I will look into that.

Thanks! Flemming

FHoltorf avatar Dec 07 '23 20:12 FHoltorf

Stationarity is just jargon for a condition that encodes if a point is a stationary point for the underlying optimization problem (so in the simplest setting: a condition that encodes how close the gradient is to vanishing) which is of course often used as part of convergence criterion. Here, the default L-BFGS-B method declares convergence when the norm of the projected gradient is < pgtol (=1e-5) but I would like for it to keep going to higher precision in this sense. Sorry, I didn't explain well what my problem was in practice :).

Makes sense now!

If being able to set pgtol (the same way you can set g_tol for Optim) solves your problem, I can just make that an option. Same for the hardcoded factr and m.

I personally only need pgtol right now but I think it could generally be useful to expose all (or at least the common) solver options (since different choices for them can in principle matter a lot). It might not be worth the effort if no-one else uses it, though.

GRAPE is still very much at a pre-1.0 stage of development, so there's a very low bar both for ad-hoc changes and for breaking changes later on to clean up those ad-hoc changes. So I'll just push out a minor release that makes those parameters accessible.

How would having it in the result object help you? My (possibly incorrect) understanding is that you allow a user to define their own convergence criteria through the check_covergence kwarg by defining a function on result object.

You're totally right (and I kinda forgot). That makes total sense, and is a very good argument for including the gradient in the result object. So I'll probably end up doing that (at some point)

There's infohook for that, in principle, which gets the GrapeWrk object which has access to lots of internal data, including gradient information, although not the LBFGSB optimizer, which might be nice to have. These internals need a pretty major overhaul at some point.

You can definitely abuse the infohook to set convergence. You're not officially supposed to mutate stuff in the infohook, but as long as you understand the internals, you can (like, setting wrk.result.converged to true). So it can be a more powerful replacement for the check_convergence function.

goerz avatar Dec 07 '23 21:12 goerz