Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coherent & concise JuMPification of MARGO? #18

Open
hdrake opened this issue Jun 20, 2020 · 7 comments
Open

Coherent & concise JuMPification of MARGO? #18

hdrake opened this issue Jun 20, 2020 · 7 comments
Assignees
Labels
enhancement New feature or request priority

Comments

@hdrake
Copy link
Collaborator

hdrake commented Jun 20, 2020

As mentioned in #14, it would be nice to reduce the JuMP implementation of MARGO to a few single-line statements like:

for i in N; @constraint{ T(M,R,G,A) < Tstar }; end
@NLobjective( model_optimizer, Min, net_present_cost(M,R,G,A) );

which reuse the diagnostic functions such as T which fully describe the model (see https://github.com/hdrake/ClimateMARGO.jl/tree/updating-structure) but are complicated functions of both the four controls {M,R,G,A} as well as a number of prescribed inputs functions and parameters. In the current implementation af16f49, these optimization constraints are hard-coded from scratch, span many lines, and are repeated several times over.

@hdrake hdrake self-assigned this Jun 20, 2020
@hdrake hdrake added the enhancement New feature or request label Jun 20, 2020
@hdrake
Copy link
Collaborator Author

hdrake commented Jun 20, 2020

The first thing to do is set up some very simple tests of JuMP and see how far we can push the use of functions to simplify the optimization before we break JuMP.

@hdrake
Copy link
Collaborator Author

hdrake commented Aug 26, 2020

Looks like some of this is possible with the user-defined functions API in JuMP. I'm a bit nervous about whether this will extend to the cumsum implementation of the Green's functions kernels in the energy balance model, since it's not just a combination of elementary functions...

@hdrake hdrake added this to the v1.0 release milestone Sep 16, 2020
@fonsp
Copy link
Member

fonsp commented Dec 17, 2020

Hey Henri!
With only a small modifcation, we can use diagnostic functions like control cost, damages, and final temperature inside JuMP. These are Vector -> scalar functions, and there’s a trick for that: https://jump.dev/JuMP.jl/v0.21.1/nlp/#User-defined-functions-with-vector-inputs-1

Using this trick, we can minimize control costs subject to temp[2200] <= T_max (i.e. overshoot allowed), all using MARGO's diagnostic functions.

But we won’t be able to use Vector -> Vector functions, which is needed for the global temperature constraint. You need to write out the cumsum behaviour like we currently do, but I think it can still be made more concise by partially reusing the diagnostic code.

I wrote a more detailed notebook about it here, which is just the mitigation optimization. To run the notebook, you need to checkout the forward-diffable branch of ClimateMARGO, so I also made a PDF.

Have a look at "Conclusions" on page 6
🎈 jump test margo.jl ⚡ Pluto.jl ⚡.pdf

https://github.com/fonsp/disorganised-mess/blob/master/jump%20test%20margo.jl

@hdrake
Copy link
Collaborator Author

hdrake commented Dec 17, 2020

Awesome progress @fonsp! I'll take a look at it in the next couple of days!

@hdrake
Copy link
Collaborator Author

hdrake commented Dec 17, 2020

I feel like there should be some trick to generalize the clunky cumsum formulation we have now, even if it has to be done separately for individual Vector -> Vector operators...

@fonsp
Copy link
Member

fonsp commented Dec 17, 2020

To add to this: JuMP uses forward mode automatic differentiation (dual numbers). This means that it can automatically differentiate our diagnostic functions 🎉, and also user-defined functions 🎊, even though they are a 'black box' from the perspective of ClimateMARGO.jl. As long as they are not 'too complex' (not sure what that means yet), and as long as they accept the more general Real type instead of the Float64 type, it will work.

If we ever have a user whose custom functions are not auto-diffable, JuMP does not include finite differencing by default, but it seems like we can add that functionality later, either by supplying a finite difference method as the 'derivative', or by switching packages.

@fonsp
Copy link
Member

fonsp commented May 22, 2021

In the end, I was able to also use Vector->Vector functions with an additional wrapper function, but the performance impact is very large (~ 10x - 500x slower). I tried lots of things, but I can't figure out exactly why it is this much slower...

If anyone is interested, I can document what I tried. Code is here, here and here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request priority
Projects
None yet
Development

No branches or pull requests

2 participants