Mimi Framework

Optimizing MimiDICE

Hey there,

I am trying to optimize the welfare in MimiDICE2016 using the mitigation rate with OptiMimi and stayed closely to the description of OptiMimi here:

This is the code I used (m_opti is the DICE2016 model):

using OptiMimi

setting up the optimization problem

function objective(model::Model)
m_opti[:welfare, :CUMCEMUTOTPER]

constraint = [model → sum(model.components[:emissions].Parameters.MIU) - 1]

optprob = problem(m_opti, [:emissions], [:MIU], [0.], [1.], objective, constraints=constraint)

solving the optimization problem

(maxf, maxx) = solution(optprob, () → [0. for i in 1:100])

I get an error about the constraint that I am unsure how to solve:
TypeError: in keyword argument constraints, expected Array{Function,1}, got a value of type Array{var"#83#84",1}

And when I leave out the constraint, I get this error:
Cannot set parameter :MIU, the model already has an external parameter with this name. Use update_param(m, param_name, value) to change the value, or use set_param(m, comp_name, param_name, unique_param_name, value) to set a value for only this component.

I would be glad if you could help me with this, probably it’s just a minor problem.
Or could you guide me to a paper or so where you optimized a Mimi Model possibly also with another package than OptiMimi?

Thanks again for your awesome work on making these models open source usable!

Hello @MalinW thank you for your interest and question! The Mimi.jl team does not directly oversee OptiMimi.jl, so I may suggest you reach out to @jrising on his repo with a Github Issue (you could just link to this post so you don’t have to retype it :slight_smile: ). That said, I can also reach out to him myself and I’ll take some time today to dig into this, it might be that I can solve the issue if it is an underlying problem with OptiMimi.jl being updated to the latest Mimi.jl version.

@MalinW Thanks for reaching out! I recognize this error from recent(ish) changes to Mimi. The standard optimization mechanism in OptiMimi has not be fully updated for the most recent version of Mimi, which requires that set_param only be used once, and then only update_param from then on.

I’ve been advocating for removing this restriction on the use of set_param, and it would be useful to know when this might be able to happen from @lrennels as I make changes.

But I also want to make sure that OptiMimi is useable for this case. @MalinW, do you have any other code that goes with the code you posted above, so I can run your use case?

Thanks for your answers @lrennels and @jrising. I wasn’t working the last few days, so I didn’t get to answer faster to this.

So this is the full code (the part of adding packages is commented out):

#add Mimi registry (registry with the Mimi models), Mimi, MimiDICE2016 and OptiMimi
#] registry add https://github.com/mimiframework/MimiRegistry.git
#] add Mimi
#] add https://github.com/AlexandrePavlov/MimiDICE2016.jl
#] add OptiMimi

#or update packages
#] update

# use the model
using MimiDICE2016
# access the public API of MimiDICE2016 with MimiDICE2016.get_model, which returns a copy of the default model
m_opti = MimiDICE2016.get_model() 
# run the model

using Mimi
using OptiMimi

# setting up the optimization problem

function objective(model::Model)
    m_opti[:welfare, :CUMCEMUTOTPER]

constraint = [model -> sum(model.components[:emissions].Parameters.MIU) - 1]
optprob = problem(m_opti, [:emissions], [:MIU], [0.], [1.], objective
#    , constraints=constraint

# solving the optimization problem

(maxf, maxx) = solution(optprob, () -> [0. for i in 1:100])

setparameters(m_opti, [:emissions], [:MIU], maxx)

and as I already said there seems to be problem with my constraint (thats why it’s commented out in the optimization problem), but also with the set_param function.

Thanks @MalinW, @jrising and I will look at this, I see two probable issues although I don’t know OptiMimi very well.

First of all, the following way to dive into the parameter values isn’t going to work anymore, it accesses internal storage that isn’t organized like this anymore.


Is there a reason the example doesn’t use the public API version ie. something like the following?

sum(model[:emissions, :MIU])

Second of all, as you already pointed out, the second issue is specific to calling set_param! using an existing parameter name. I can’t promise right now that we are fully getting rid of the distinction between update and set parameter, but David and I are meeting Monday to discuss how to make this easier for users since I know you’ve expressed frustration about that, so I’ll try to keep you looped in to that conversation which will be worked on here.

That said (as you probably know) in I think in the case above with the current framework one needs to make only calls to update_param! in the internals since

using MimiDICE2016
m_opti = MimiDICE2016.get_model() 

has set MIU from within get_model().

Okay, I think I’ve got it working, but it’s a lot of parameters to optimize, so I haven’t gotten a result yet.

First, there were a couple changes needed to OptiMimi:

  • I’ve currently fixed the set_param! vs. update_param! by assuming that the external parameter matches the parameter name. This means that the current fix will not work well if there are multiple components that define the same parameter-- but I don’t think that’s a problem for your case.
  • The -> operator, used in defining constraints, returns a subclass of Function, so I needed to change the expected argument there. No problem, now fixed. So you should be able to use constraints.

I haven’t published these changes to the Mimi package repository yet, but I think you can use

] develop OptiMimi

to check out the master branch. If it works for you, we’ll push it out.

There were also a couple changes needed to your objective function. I’ve defined it as:

function objective(model::Model)
    model[:welfare, :CUMCEMUTOTPER][100]

So, you want to use model, not m_opti, and you need to return a single value. I think that should just be the last value in this case.

Let me know how that works for you!

@jrising if you’ve pushed to the master branch but just haven’t tagged, @MalinW you may want to just use

julia >  ]
pkg  > add OptiMimi#master

that way you can use the master branch code without pulling in the whole repository as if you’re going to develop it! Or of course just wait for @jrising to tag the new version and then just call

julia> ]
pkg> up

to update all packages including OptiMimi.jl.

I’m monitoring the forum closely these days so both of you do feel free to keep commenting here if there are issues or questions I’m happy to help!

Just to follow up on @lrennels’s comment: Yes, it’s on the master branch, so definitely use the add OptiMimi#master syntax. I was planning on waiting until you (@MalinW) have a chance to test it before tagging a new release.

1 Like