Skip to content

Commit 9ce17c4

Browse files
committed
detailed comments on example
1 parent b5c56d0 commit 9ce17c4

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

examples/chainrules.jl

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ function unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs; mo
3535
Cnl = Dict(1 => noload_costs[1], 2 => noload_costs[2]) # No-load cost ($)
3636

3737
## Variables
38+
# Note: u represents the activation of generation units.
39+
# Would be binary in the typical UC problem, relaxed here to u ∈ [0,1]
40+
# for a linear relaxation.
3841
@variable(model, 0 <= u[g in unit_codes, t in 1:n_periods] <= 1) # Commitment
39-
@variable(model, p[g in unit_codes, t in 1:n_periods] >= 0) # Power output
42+
@variable(model, p[g in unit_codes, t in 1:n_periods] >= 0) # Power output (pu)
4043

4144
## Constraints
4245

@@ -75,21 +78,33 @@ end
7578
# Forward differentiation rule for the solution map of the unit commitment problem
7679
# taking in input perturbations on the input parameters and returning perturbations propagated to the result
7780
function ChainRulesCore.frule((_, Δload1_demand, Δload2_demand, Δgen_costs, Δnoload_costs), ::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs)
81+
# creating the UC model with a DiffOpt optimizer wrapper around Clp
7882
model = Model(() -> diff_optimizer(Clp.Optimizer))
83+
# building and solving the main model
7984
pv = unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs, model=model)
8085
energy_balance_cons = model[:energy_balance_cons]
81-
MOI.set.(model, DiffOpt.ForwardIn{DiffOpt.ConstraintConstant}(), energy_balance_cons, [d1 + d2 for (d1, d2) in zip(Δload1_demand, Δload1_demand)])
86+
87+
# Setting some perturbation of the right-hand side of the energy balance constraints
88+
# the RHS is equal to the sum of load demands at each period.
89+
# the corresponding perturbation are set accordingly as the set of perturbations of the two loads
90+
MOI.set.(
91+
model,
92+
DiffOpt.ForwardIn{DiffOpt.ConstraintConstant}(), energy_balance_cons,
93+
[d1 + d2 for (d1, d2) in zip(Δload1_demand, Δload1_demand)],
94+
)
8295

8396
p = model[:p]
8497
u = model[:u]
8598

99+
# setting the perturbation of the linear objective
86100
for t in size(p, 2)
87101
MOI.set(model, DiffOpt.ForwardIn{DiffOpt.LinearObjective}(), p[1,t], Δgen_costs[1])
88102
MOI.set(model, DiffOpt.ForwardIn{DiffOpt.LinearObjective}(), p[2,t], Δgen_costs[2])
89103
MOI.set(model, DiffOpt.ForwardIn{DiffOpt.LinearObjective}(), u[1,t], Δnoload_costs[1])
90104
MOI.set(model, DiffOpt.ForwardIn{DiffOpt.LinearObjective}(), u[2,t], Δnoload_costs[2])
91105
end
92106
DiffOpt.forward(JuMP.backend(model))
107+
# querying the corresponding perturbation of the decision
93108
Δp = MOI.get.(model, DiffOpt.ForwardOut{MOI.VariablePrimal}(), p)
94109
return (pv, Δp.data)
95110
end
@@ -110,6 +125,7 @@ noload_costs = [500.0, 1000.0]
110125
# The computed pullback takes a seed for the optimal solution `̄p` and returns
111126
# derivatives wrt each input parameter.
112127
function ChainRulesCore.rrule(::typeof(unit_commitment), load1_demand, load2_demand, gen_costs, noload_costs; model = Model(() -> diff_optimizer(Clp.Optimizer)))
128+
# solve the forward UC problem
113129
pv = unit_commitment(load1_demand, load2_demand, gen_costs, noload_costs, model=model)
114130
function pullback_unit_commitment(pb)
115131
p = model[:p]
@@ -119,6 +135,7 @@ function ChainRulesCore.rrule(::typeof(unit_commitment), load1_demand, load2_dem
119135
MOI.set.(model, DiffOpt.BackwardIn{MOI.VariablePrimal}(), p, pb)
120136
DiffOpt.backward(JuMP.backend(model))
121137

138+
# computing derivative wrt linear objective costs
122139
dgen_costs = similar(gen_costs)
123140
dgen_costs[1] = sum(MOI.get.(model, DiffOpt.BackwardOut{DiffOpt.LinearObjective}(), p[1,:]))
124141
dgen_costs[2] = sum(MOI.get.(model, DiffOpt.BackwardOut{DiffOpt.LinearObjective}(), p[2,:]))
@@ -127,6 +144,7 @@ function ChainRulesCore.rrule(::typeof(unit_commitment), load1_demand, load2_dem
127144
dnoload_costs[1] = sum(MOI.get.(model, DiffOpt.BackwardOut{DiffOpt.LinearObjective}(), u[1,:]))
128145
dnoload_costs[2] = sum(MOI.get.(model, DiffOpt.BackwardOut{DiffOpt.LinearObjective}(), u[2,:]))
129146

147+
# computing derivative wrt constraint constant
130148
dload1_demand = MOI.get.(model, DiffOpt.BackwardOut{DiffOpt.ConstraintConstant}(), energy_balance_cons)
131149
dload2_demand = copy(dload1_demand)
132150
return (dload1_demand, dload2_demand, dgen_costs, dnoload_costs)

0 commit comments

Comments
 (0)