Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ optimize!(model)

# differentiate w.r.t. p
direction_p = 3.0
DiffOpt.set_forward_parameter(model, p, direction_p)
set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p)
DiffOpt.forward_differentiate!(model)
@show DiffOpt.get_forward_variable(model, x) == direction_p * 3 / pc_val
@show get_attribute(x, DiffOpt.ForwardVariablePrimal()) == direction_p * 3 / pc_val

# update p and pc
p_val = 2.0
Expand All @@ -79,19 +79,19 @@ optimize!(model)
DiffOpt.empty_input_sensitivities!(model)
# differentiate w.r.t. pc
direction_pc = 10.0
DiffOpt.set_forward_parameter(model, pc, direction_pc)
set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc)
DiffOpt.forward_differentiate!(model)
@show abs(DiffOpt.get_forward_variable(model, x) -
@show abs(get_attribute(x, DiffOpt.ForwardVariablePrimal()) -
-direction_pc * 3 * p_val / pc_val^2) < 1e-5

# always a good practice to clear previously set sensitivities
DiffOpt.empty_input_sensitivities!(model)
# Now, reverse model AD
direction_x = 10.0
DiffOpt.set_reverse_variable(model, x, direction_x)
set_attribute(x, DiffOpt.ReverseVariablePrimal(), direction_x)
DiffOpt.reverse_differentiate!(model)
@show DiffOpt.get_reverse_parameter(model, p) == direction_x * 3 / pc_val
@show DiffOpt.get_reverse_parameter(model, pc) == -direction_x * 3 * p_val / pc_val^2
@show get_attribute(p, DiffOpt.ReverseParameterValue()) == direction_x * 3 / pc_val
@show get_attribute(pc, DiffOpt.ReverseParameterValue()) == -direction_x * 3 * p_val / pc_val^2
```

Available models:
Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples/Mean_Variance_Portfolio_Example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ for (k, σ_val) in enumerate(σ_grid)
## -------- reverse differentiation wrt σ_max --------
DiffOpt.empty_input_sensitivities!(model)
## ∂L/∂x (adjoint) = -μ_test
DiffOpt.set_reverse_variable.(model, x, μ_test)
set_attribute.(x, DiffOpt.ReverseVariablePrimal(), μ_test)
DiffOpt.reverse_differentiate!(model)
dL_dσ[k] = DiffOpt.get_reverse_parameter(model, σ_max)
dL_dσ[k] = get_attribute(σ_max, DiffOpt.ReverseParameterValue())
end

# ## Results with Plot graphs
Expand Down
12 changes: 6 additions & 6 deletions docs/src/examples/Planar_Arm_Example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ for (i, x_t) in enumerate(xs), (j, y_t) in enumerate(ys)

## ---- forward diff wrt xt (∂θ/∂x) ----
DiffOpt.empty_input_sensitivities!(model)
DiffOpt.set_forward_parameter(model, xt, 0.01)
set_attribute(xt, DiffOpt.ForwardParameterValue(), 0.01)
DiffOpt.forward_differentiate!(model)
dθ1_dx = DiffOpt.get_forward_variable(model, θ1)
dθ2_dx = DiffOpt.get_forward_variable(model, θ2)
dθ1_dx = get_attribute(θ1, DiffOpt.ForwardVariablePrimal())
dθ2_dx = get_attribute(θ2, DiffOpt.ForwardVariablePrimal())

## check first order approximation keeps solution close to target withing tolerance
θ_approx = [θ1̂ + dθ1_dx, θ1̂ + dθ2_dx]
Expand All @@ -101,10 +101,10 @@ for (i, x_t) in enumerate(xs), (j, y_t) in enumerate(ys)

## ---- forward diff wrt yt (∂θ/∂y) ----
DiffOpt.empty_input_sensitivities!(model)
DiffOpt.set_forward_parameter(model, yt, 0.01)
set_attribute(yt, DiffOpt.ForwardParameterValue(), 0.01)
DiffOpt.forward_differentiate!(model)
dθ1_dy = DiffOpt.get_forward_variable(model, θ1)
dθ2_dy = DiffOpt.get_forward_variable(model, θ2)
dθ1_dy = get_attribute(θ1, DiffOpt.ForwardVariablePrimal())
dθ2_dy = get_attribute(θ2, DiffOpt.ForwardVariablePrimal())

## 2-norm of inverse Jacobian
Jinv = [
Expand Down
8 changes: 4 additions & 4 deletions docs/src/examples/Thermal_Generation_Dispatch_Example_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ function diff_forward(model::Model, ϵ::Float64 = 1.0)
DiffOpt.empty_input_sensitivities!(model)

## Pass the perturbation to the DiffOpt Framework
DiffOpt.set_forward_parameter(model, model[:d], ϵ)
set_attribute(model[:d], DiffOpt.ForwardParameterValue(), ϵ)

## Compute the derivatives with the Forward Mode
DiffOpt.forward_differentiate!(model)

## Get the derivative of the model
dvect = DiffOpt.get_forward_variable.(model, vect_ref)
dvect = get_attribute.(vect_ref, DiffOpt.ForwardVariablePrimal())

## Return the values as a vector
return [vect; dvect]
Expand All @@ -106,13 +106,13 @@ function diff_reverse(model::Model, ϵ::Float64 = 1.0)
DiffOpt.empty_input_sensitivities!(model)

## Pass the perturbation to the DiffOpt Framework
DiffOpt.set_reverse_variable.(model, vect_ref[i], ϵ)
set_attribute.(vect_ref[i], DiffOpt.ReverseVariablePrimal(), ϵ)

## Compute the derivatives with the Forward Mode
DiffOpt.reverse_differentiate!(model)

## Get the derivative of the model
dvect[i] = DiffOpt.get_reverse_parameter(model, model[:d])
dvect[i] = get_attribute(model[:d], DiffOpt.ReverseParameterValue())
end

## Return the values as a vector
Expand Down
10 changes: 5 additions & 5 deletions docs/src/examples/Thermal_Generation_Dispatch_sweep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ for (k, d_val) in enumerate(d_range)

@variable(model, d in Parameter(d_val)) # parameter
@variables(model, begin # decisions
0 <= g[i=1:2] <= G[i]
0 <= g[i = 1:2] <= G[i]
φ >= 0
end)

Expand All @@ -66,12 +66,12 @@ for (k, d_val) in enumerate(d_range)

## ---------- forward sensitivities ----------
DiffOpt.empty_input_sensitivities!(model)
DiffOpt.set_forward_parameter(model, d, 1.0)
set_attribute(d, DiffOpt.ForwardParameterValue(), 1.0)
DiffOpt.forward_differentiate!(model)

dg1_dd[k] = DiffOpt.get_forward_variable(model, g[1])
dg2_dd[k] = DiffOpt.get_forward_variable(model, g[2])
dφ_dd[k] = DiffOpt.get_forward_variable(model, φ)
dg1_dd[k] = get_attribute(g[1], DiffOpt.ForwardVariablePrimal())
dg2_dd[k] = get_attribute(g[2], DiffOpt.ForwardVariablePrimal())
dφ_dd[k] = get_attribute(φ, DiffOpt.ForwardVariablePrimal())

## marginal cost λ
dJ_dd[k] = dual.(con)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples/autotuning-ridge_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ Plots.title!("Normalized MSE on training and testing sets")
function compute_dw_dα(model, w)
D = length(w)
dw_dα = zeros(D)
DiffOpt.set_forward_parameter(model, model[:α], 1.0)
set_attribute(model[:α], DiffOpt.ForwardParameterValue(), 1.0)
DiffOpt.forward_differentiate!(model)
for i in 1:D
dw_dα[i] = DiffOpt.get_forward_variable(model, w[i])
dw_dα[i] = get_attribute(w[i], DiffOpt.ForwardVariablePrimal())
end
return dw_dα
end
Expand Down
37 changes: 25 additions & 12 deletions docs/src/examples/chainrules_unit_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,22 @@ function ChainRulesCore.frule(
model = model,
)
## Setting perturbations in the parameters
DiffOpt.set_forward_parameter.(model, model[:load1_demand], Δload1_demand)
DiffOpt.set_forward_parameter.(model, model[:load2_demand], Δload2_demand)
DiffOpt.set_forward_parameter.(model, model[:Cp], Δgen_costs)
DiffOpt.set_forward_parameter.(model, model[:Cnl], Δnoload_costs)
set_attribute.(
model[:load1_demand],
DiffOpt.ForwardParameterValue(),
Δload1_demand,
)
set_attribute.(
model[:load2_demand],
DiffOpt.ForwardParameterValue(),
Δload2_demand,
)
set_attribute.(model[:Cp], DiffOpt.ForwardParameterValue(), Δgen_costs)
set_attribute.(model[:Cnl], DiffOpt.ForwardParameterValue(), Δnoload_costs)
## computing the forward differentiation
DiffOpt.forward_differentiate!(model)
## querying the corresponding perturbation of the decision
Δp = DiffOpt.get_forward_variable.(model, model[:p])
Δp = get_attribute.(model[:p], DiffOpt.ForwardVariablePrimal())
return (pv, Δp.data)
end

Expand Down Expand Up @@ -252,16 +260,21 @@ function ChainRulesCore.rrule(
)
function pullback_unit_commitment(pb)
## set sensitivities
DiffOpt.set_reverse_variable.(model, model[:p], pb)
set_attribute.(model[:p], DiffOpt.ReverseVariablePrimal(), pb)
## compute the gradients
DiffOpt.reverse_differentiate!(model)
## retrieve the gradients with respect to the parameters
dload1_demand =
DiffOpt.get_reverse_parameter.(model, model[:load1_demand])
dload2_demand =
DiffOpt.get_reverse_parameter.(model, model[:load2_demand])
dgen_costs = DiffOpt.get_reverse_parameter.(model, model[:Cp])
dnoload_costs = DiffOpt.get_reverse_parameter.(model, model[:Cnl])
dload1_demand = get_attribute.(
model[:load1_demand],
DiffOpt.ReverseParameterValue(),
)
dload2_demand = get_attribute.(
model[:load2_demand],
DiffOpt.ReverseParameterValue(),
)
dgen_costs = get_attribute.(model[:Cp], DiffOpt.ReverseParameterValue())
dnoload_costs =
get_attribute.(model[:Cnl], DiffOpt.ReverseParameterValue())
return (dload1_demand, dload2_demand, dgen_costs, dnoload_costs)
end
return (pv, pullback_unit_commitment)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples/custom-relu_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ function ChainRulesCore.rrule(
y = model[:y]::Matrix{JuMP.VariableRef} # load parameter variable `y` into scope
## set sensitivities (dl/dx)
for i in eachindex(x)
DiffOpt.set_reverse_variable(model, x[i], dl_dx[i])
set_attribute(x[i], DiffOpt.ReverseVariablePrimal(), dl_dx[i])
end
## compute grad (dx/dy)
DiffOpt.reverse_differentiate!(model)
## return gradient (dl/dy = dl/dx * dx/dy)
dl_dy = DiffOpt.get_reverse_parameter.(model, y)
dl_dy = get_attribute.(y, DiffOpt.ReverseParameterValue())
return (ChainRulesCore.NoTangent(), dl_dy)
end
return pv, pullback_matrix_relu
Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples/matrix-inversion-manual_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ dual.(cons)

# set sensitivitity

DiffOpt.set_forward_parameter.(model, y, 1.0)
set_attribute.(y, DiffOpt.ForwardParameterValue(), 1.0)

# Compute derivatives

DiffOpt.forward_differentiate!(model)

# Query derivative

dx = DiffOpt.get_forward_variable.(model, x)
dx = get_attribute.(x, DiffOpt.ForwardVariablePrimal())

using Test #src
@test dx ≈ [0.25, 0.75] atol = 1e-4 rtol = 1e-4 #src
4 changes: 2 additions & 2 deletions docs/src/examples/nearest_correlation_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ function proj(A, dH = Diagonal(ones(size(A, 1))), H_data = ones(size(A)))
@constraint(model, E .== (H .* (X .- A)))
@objective(model, Min, sum(E .^ 2))
for i in 1:n
DiffOpt.set_forward_parameter(model, H[i, i], dH[i, i])
set_attribute(H[i, i], DiffOpt.ForwardParameterValue(), dH[i, i])
end
optimize!(model)
DiffOpt.forward_differentiate!(model)
dX = DiffOpt.get_forward_variable.(model, X)
dX = get_attribute.(X, DiffOpt.ForwardVariablePrimal())
return value.(X), dX
end

Expand Down
12 changes: 6 additions & 6 deletions docs/src/examples/polyhedral_project_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ function (polytope::Polytope{N})(
set_silent(model)
@variable(model, x[1:layer_size, 1:batch_size])
@variable(model, y[1:layer_size, 1:batch_size] in Parameter.(y_data))
@variable(model, b[idx=1:N] in Parameter.(polytope.b[idx]))
@variable(model, b[idx = 1:N] in Parameter.(polytope.b[idx]))
@variable(
model,
w[idx=1:N, i=1:layer_size] in Parameter(polytope.w[idx][i])
w[idx = 1:N, i = 1:layer_size] in Parameter(polytope.w[idx][i])
)
@constraint(
model,
Expand Down Expand Up @@ -90,19 +90,19 @@ function ChainRulesCore.rrule(
layer_size, batch_size = size(x)
## set sensitivities
for i in eachindex(x)
DiffOpt.set_reverse_variable(model, x[i], dl_dx[i])
set_attribute(x[i], DiffOpt.ReverseVariablePrimal(), dl_dx[i])
end
## compute grad
DiffOpt.reverse_differentiate!(model)
## compute gradient wrt objective function parameter y
dl_dy = DiffOpt.get_reverse_parameter.(model, y)
dl_dy = get_attribute.(y, DiffOpt.ReverseParameterValue())
## compute gradient wrt objective function parameter w and b
_dl_dw = DiffOpt.get_reverse_parameter.(model, w)
_dl_dw = get_attribute.(w, DiffOpt.ReverseParameterValue())
dl_dw = zero.(polytope.w)
for idx in 1:N
dl_dw[idx] .= _dl_dw[idx, :]
end
dl_db = DiffOpt.get_reverse_parameter.(model, b)
dl_db = get_attribute.(b, DiffOpt.ReverseParameterValue())
dself = ChainRulesCore.Tangent{Polytope{N}}(; w = dl_dw, b = dl_db)
return (dself, dl_dy)
end
Expand Down
2 changes: 1 addition & 1 deletion docs/src/examples/sensitivity-analysis-ridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function fit_ridge(X, Y, alpha = 0.1)
@variable(model, w) # angular coefficient
@variable(model, b) # linear coefficient
## expression defining approximation error
@expression(model, e[i=1:N], Y[i] - w * X[i] - b)
@expression(model, e[i = 1:N], Y[i] - w * X[i] - b)
## objective minimizing squared error and ridge penalty
@objective(model, Min, 1 / N * dot(e, e) + alpha * (w^2))
optimize!(model)
Expand Down
10 changes: 5 additions & 5 deletions docs/src/examples/sensitivity-analysis-ridge_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function build_fit_ridge(X_data, Y_data, alpha = 0.1)
@variable(model, X[1:N] in Parameter.(X_data))
@variable(model, Y[1:N] in Parameter.(Y_data))
## expression defining approximation error
@expression(model, e[i=1:N], Y[i] - w * X[i] - b)
@expression(model, e[i = 1:N], Y[i] - w * X[i] - b)
## objective minimizing squared error and ridge penalty
@objective(model, Min, 1 / N * dot(e, e) + α * (w^2))
optimize!(model)
Expand Down Expand Up @@ -120,14 +120,14 @@ b̂ = value(b)
for i in 1:N
## X[i] sensitivity
DiffOpt.empty_input_sensitivities!(model)
DiffOpt.set_forward_parameter(model, model[:X][i], 1.0)
set_attribute(model[:X][i], DiffOpt.ForwardParameterValue(), 1.0)
DiffOpt.forward_differentiate!(model)
∇x[i] = DiffOpt.get_forward_variable(model, w)
∇x[i] = get_attribute(w, DiffOpt.ForwardVariablePrimal())
## Y[i] sensitivity
DiffOpt.empty_input_sensitivities!(model)
DiffOpt.set_forward_parameter(model, model[:Y][i], 1.0)
set_attribute(model[:Y][i], DiffOpt.ForwardParameterValue(), 1.0)
DiffOpt.forward_differentiate!(model)
∇y[i] = DiffOpt.get_forward_variable(model, w)
∇y[i] = get_attribute(w, DiffOpt.ForwardVariablePrimal())
end

# Visualize point sensitivities with respect to regression points.
Expand Down
8 changes: 4 additions & 4 deletions docs/src/examples/sensitivity-analysis-svm_new.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ for i in 1:N
for j in 1:N
if i == j
## we consider identical perturbations on all x_i coordinates
DiffOpt.set_forward_parameter.(model, X[i, :], 1.0)
set_attribute.(X[i, :], DiffOpt.ForwardParameterValue(), 1.0)
else
DiffOpt.set_forward_parameter.(model, X[i, :], 0.0)
set_attribute.(X[i, :], DiffOpt.ForwardParameterValue(), 0.0)
end
end
DiffOpt.forward_differentiate!(model)
dw = DiffOpt.get_forward_variable.(model, w)
db = DiffOpt.get_forward_variable.(model, b)
dw = get_attribute.(w, DiffOpt.ForwardVariablePrimal())
db = get_attribute.(b, DiffOpt.ForwardVariablePrimal())
∇[i] = LinearAlgebra.norm(dw) + LinearAlgebra.norm(db)
end

Expand Down
6 changes: 2 additions & 4 deletions src/ConicProgram/ConicProgram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -477,10 +477,8 @@ end
Method not supported for `DiffOpt.ConicProgram.Model` directly.
However, a fallback is provided in `DiffOpt`.
"""
function MOI.set(::Model, ::DiffOpt.ReverseObjectiveSensitivity, val)
return throw(
MOI.UnsupportedAttribute(DiffOpt.ReverseObjectiveSensitivity()),
)
function MOI.set(::Model, ::DiffOpt.ReverseObjectiveValue, val)
return throw(MOI.UnsupportedAttribute(DiffOpt.ReverseObjectiveValue()))
end

end
4 changes: 2 additions & 2 deletions src/NonLinearProgram/NonLinearProgram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ function _lu_with_inertia_correction(
return K
end

_all_variables(form::Form) = MOI.VariableIndex.(1:form.num_variables)
_all_variables(form::Form) = MOI.VariableIndex.(1:(form.num_variables))
_all_variables(model::Model) = _all_variables(model.model)
_all_params(form::Form) = collect(keys(form.var2param))
_all_params(model::Model) = _all_params(model.model)
Expand Down Expand Up @@ -650,7 +650,7 @@ function MOI.get(model::Model, ::DiffOpt.ForwardObjectiveSensitivity)
return model.forw_grad_cache.objective_sensitivity_p
end

function MOI.set(model::Model, ::DiffOpt.ReverseObjectiveSensitivity, val)
function MOI.set(model::Model, ::DiffOpt.ReverseObjectiveValue, val)
model.input_cache.dobj = val
return
end
Expand Down
2 changes: 1 addition & 1 deletion src/NonLinearProgram/nlp_utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function _create_evaluator(form::Form)
evaluator = MOI.Nonlinear.Evaluator(
nlp,
backend,
MOI.VariableIndex.(1:form.num_variables),
MOI.VariableIndex.(1:(form.num_variables)),
)
MOI.initialize(evaluator, [:Hess, :Jac, :Grad])
return evaluator
Expand Down
6 changes: 2 additions & 4 deletions src/QuadraticProgram/QuadraticProgram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -519,10 +519,8 @@ end
Method not supported for `DiffOpt.QuadraticProgram.Model` directly.
However, a fallback is provided in `DiffOpt`.
"""
function MOI.set(::Model, ::DiffOpt.ReverseObjectiveSensitivity, val)
return throw(
MOI.UnsupportedAttribute(DiffOpt.ReverseObjectiveSensitivity()),
)
function MOI.set(::Model, ::DiffOpt.ReverseObjectiveValue, val)
return throw(MOI.UnsupportedAttribute(DiffOpt.ReverseObjectiveValue()))
end

end
Loading
Loading