added ChainRules examples with forward and backward#91
Conversation
Codecov Report
@@ Coverage Diff @@
## master #91 +/- ##
==========================================
+ Coverage 81.50% 81.82% +0.32%
==========================================
Files 5 5
Lines 865 864 -1
==========================================
+ Hits 705 707 +2
+ Misses 160 157 -3
Continue to review full report at Codecov.
|
|
this is great. i've been stuck at finding the difference b/t frules and rrules in implementation. now its much clear |
|
@oxinabox if you want to take a look |
|
Looks good. |
raphaelsaavedra
left a comment
There was a problem hiding this comment.
Thanks for the work, looks really nice. Left some minor comments and a question.
examples/chainrules.jl
Outdated
| model = Model(() -> diff_optimizer(Clp.Optimizer)) | ||
| pv = unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs, model=model) | ||
| energy_balance_cons = model[:energy_balance_cons] | ||
| MOI.set.(model, DiffOpt.ForwardIn{DiffOpt.ConstraintConstant}(), energy_balance_cons, [d1 + d2 for (d1, d2) in zip(Δload1_demand, Δload1_demand)]) |
There was a problem hiding this comment.
This might be a dumb question because I'm not familiar with DiffOpt and AD in general, but what are we doing here exactly and why is it specifically for the energy balance constraint?
There was a problem hiding this comment.
would it be too much to put a comment before each of these about what it does?
Not something that one would do in normal code, but since this is a tutorial it might be suitable.
There was a problem hiding this comment.
we are setting the perturbation for the right-hand-side of the energy balance constraints, which is the sum of perturbations of each of the quantities in the RHS (in that case sum of load demands)
Co-authored-by: Raphael Saavedra <raphael.saavedra93@gmail.com>
| - `noload_costs` is the vector of fixed activation costs of the generators, | ||
| and returning the optimal output power `p`. | ||
| """ | ||
| function unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs; model = Model(() -> diff_optimizer(Clp.Optimizer))) |
There was a problem hiding this comment.
I think we can just do
| function unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs; model = Model(() -> diff_optimizer(Clp.Optimizer))) | |
| function unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs; model = Model(Clp.Optimizer)) |
| function ChainRulesCore.frule((_, Δload1_demand, Δload2_demand, Δgen_costs, Δnoload_costs), ::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs) | ||
| # creating the UC model with a DiffOpt optimizer wrapper around Clp | ||
| model = Model(() -> diff_optimizer(Clp.Optimizer)) |
There was a problem hiding this comment.
We need to also pass the kwargs in: so probably can do:
| function ChainRulesCore.frule((_, Δload1_demand, Δload2_demand, Δgen_costs, Δnoload_costs), ::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs) | |
| # creating the UC model with a DiffOpt optimizer wrapper around Clp | |
| model = Model(() -> diff_optimizer(Clp.Optimizer)) | |
| function ChainRulesCore.frule((_, Δload1_demand, Δload2_demand, Δgen_costs, Δnoload_costs), ::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs; model=Model(Clp.Optimizer)) | |
| # creating the UC model with a DiffOpt optimizer wrapper around Clp | |
| model = Model(() -> diff_optimizer(optimizer(model))) |
There was a problem hiding this comment.
one issue here is that backend(.) only gives you the top-most backend layer, so you add two layers of CachingOptimizer
| # Reverse-mode differentiation of the solution map | ||
| # The computed pullback takes a seed for the optimal solution `̄p` and returns | ||
| # derivatives wrt each input parameter. | ||
| function ChainRulesCore.rrule(::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs; model = Model(() -> diff_optimizer(Clp.Optimizer))) |
There was a problem hiding this comment.
we should write this assuming the Model they use isn't a diff_optimizer model.
And we should unwrap and rewrap the model
There was a problem hiding this comment.
unwrapping and rewrapping the model results in the same issue as above
Copying the unit commitment example with ChainRules.
We depend on ChainRulesCore through SetDistances, so I added it as a dependency