From 30fa61dd62f0ade19aac7633d7aeb02e79caec25 Mon Sep 17 00:00:00 2001 From: Joaquim Dias Garcia Date: Wed, 27 May 2026 16:31:54 -0300 Subject: [PATCH] update the get/set syntax --- README.md | 14 +- .../Mean_Variance_Portfolio_Example.jl | 4 +- docs/src/examples/Planar_Arm_Example.jl | 12 +- ...Thermal_Generation_Dispatch_Example_new.jl | 8 +- .../Thermal_Generation_Dispatch_sweep.jl | 10 +- docs/src/examples/autotuning-ridge_new.jl | 4 +- docs/src/examples/chainrules_unit_new.jl | 37 +- docs/src/examples/custom-relu_new.jl | 4 +- .../examples/matrix-inversion-manual_new.jl | 4 +- docs/src/examples/nearest_correlation_new.jl | 4 +- docs/src/examples/polyhedral_project_new.jl | 12 +- .../examples/sensitivity-analysis-ridge.jl | 2 +- .../sensitivity-analysis-ridge_new.jl | 10 +- .../examples/sensitivity-analysis-svm_new.jl | 8 +- src/ConicProgram/ConicProgram.jl | 6 +- src/NonLinearProgram/NonLinearProgram.jl | 4 +- src/NonLinearProgram/nlp_utilities.jl | 2 +- src/QuadraticProgram/QuadraticProgram.jl | 6 +- src/diff_opt.jl | 42 +- src/jump_moi_overloads.jl | 84 ++- src/jump_wrapper.jl | 167 +++--- src/moi_wrapper.jl | 4 +- test/conic_program.jl | 54 +- test/data/nlp_problems.jl | 22 +- test/jump.jl | 39 +- test/jump_wrapper.jl | 129 +++-- test/nlp_program.jl | 105 ++-- test/parameters.jl | 486 +++++++----------- test/solver_native_diff.jl | 9 +- 29 files changed, 653 insertions(+), 639 deletions(-) diff --git a/README.md b/README.md index 5913411db..ab22a7853 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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: diff --git a/docs/src/examples/Mean_Variance_Portfolio_Example.jl b/docs/src/examples/Mean_Variance_Portfolio_Example.jl index e68ad90eb..abbd5312d 100644 --- a/docs/src/examples/Mean_Variance_Portfolio_Example.jl +++ b/docs/src/examples/Mean_Variance_Portfolio_Example.jl @@ -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 diff --git a/docs/src/examples/Planar_Arm_Example.jl b/docs/src/examples/Planar_Arm_Example.jl index debe631ea..8a550f05f 100644 --- a/docs/src/examples/Planar_Arm_Example.jl +++ b/docs/src/examples/Planar_Arm_Example.jl @@ -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] @@ -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 = [ diff --git a/docs/src/examples/Thermal_Generation_Dispatch_Example_new.jl b/docs/src/examples/Thermal_Generation_Dispatch_Example_new.jl index 391f3f2f3..b0f68b964 100644 --- a/docs/src/examples/Thermal_Generation_Dispatch_Example_new.jl +++ b/docs/src/examples/Thermal_Generation_Dispatch_Example_new.jl @@ -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] @@ -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 diff --git a/docs/src/examples/Thermal_Generation_Dispatch_sweep.jl b/docs/src/examples/Thermal_Generation_Dispatch_sweep.jl index 64ee21bf3..205e37269 100644 --- a/docs/src/examples/Thermal_Generation_Dispatch_sweep.jl +++ b/docs/src/examples/Thermal_Generation_Dispatch_sweep.jl @@ -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) @@ -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) diff --git a/docs/src/examples/autotuning-ridge_new.jl b/docs/src/examples/autotuning-ridge_new.jl index b7fa24a76..ebe0df3b9 100644 --- a/docs/src/examples/autotuning-ridge_new.jl +++ b/docs/src/examples/autotuning-ridge_new.jl @@ -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 diff --git a/docs/src/examples/chainrules_unit_new.jl b/docs/src/examples/chainrules_unit_new.jl index aa012e4a2..b8be40d1f 100644 --- a/docs/src/examples/chainrules_unit_new.jl +++ b/docs/src/examples/chainrules_unit_new.jl @@ -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 @@ -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) diff --git a/docs/src/examples/custom-relu_new.jl b/docs/src/examples/custom-relu_new.jl index 160bde4f5..5fb511bf9 100644 --- a/docs/src/examples/custom-relu_new.jl +++ b/docs/src/examples/custom-relu_new.jl @@ -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 diff --git a/docs/src/examples/matrix-inversion-manual_new.jl b/docs/src/examples/matrix-inversion-manual_new.jl index 9400d42a8..a438044ed 100644 --- a/docs/src/examples/matrix-inversion-manual_new.jl +++ b/docs/src/examples/matrix-inversion-manual_new.jl @@ -136,7 +136,7 @@ dual.(cons) # set sensitivitity -DiffOpt.set_forward_parameter.(model, y, 1.0) +set_attribute.(y, DiffOpt.ForwardParameterValue(), 1.0) # Compute derivatives @@ -144,7 +144,7 @@ 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 diff --git a/docs/src/examples/nearest_correlation_new.jl b/docs/src/examples/nearest_correlation_new.jl index d22bdd0e9..d6c8852e8 100644 --- a/docs/src/examples/nearest_correlation_new.jl +++ b/docs/src/examples/nearest_correlation_new.jl @@ -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 diff --git a/docs/src/examples/polyhedral_project_new.jl b/docs/src/examples/polyhedral_project_new.jl index 746be0184..a89f9ab04 100644 --- a/docs/src/examples/polyhedral_project_new.jl +++ b/docs/src/examples/polyhedral_project_new.jl @@ -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, @@ -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 diff --git a/docs/src/examples/sensitivity-analysis-ridge.jl b/docs/src/examples/sensitivity-analysis-ridge.jl index a4d3c0465..e8e245d55 100644 --- a/docs/src/examples/sensitivity-analysis-ridge.jl +++ b/docs/src/examples/sensitivity-analysis-ridge.jl @@ -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) diff --git a/docs/src/examples/sensitivity-analysis-ridge_new.jl b/docs/src/examples/sensitivity-analysis-ridge_new.jl index aa41f80a2..7f8368a9b 100644 --- a/docs/src/examples/sensitivity-analysis-ridge_new.jl +++ b/docs/src/examples/sensitivity-analysis-ridge_new.jl @@ -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) @@ -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. diff --git a/docs/src/examples/sensitivity-analysis-svm_new.jl b/docs/src/examples/sensitivity-analysis-svm_new.jl index a61f75cf5..54ebee16e 100644 --- a/docs/src/examples/sensitivity-analysis-svm_new.jl +++ b/docs/src/examples/sensitivity-analysis-svm_new.jl @@ -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 diff --git a/src/ConicProgram/ConicProgram.jl b/src/ConicProgram/ConicProgram.jl index 415ad9683..ee5492b07 100644 --- a/src/ConicProgram/ConicProgram.jl +++ b/src/ConicProgram/ConicProgram.jl @@ -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 diff --git a/src/NonLinearProgram/NonLinearProgram.jl b/src/NonLinearProgram/NonLinearProgram.jl index 9b1bf3134..9d813b8b1 100644 --- a/src/NonLinearProgram/NonLinearProgram.jl +++ b/src/NonLinearProgram/NonLinearProgram.jl @@ -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) @@ -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 diff --git a/src/NonLinearProgram/nlp_utilities.jl b/src/NonLinearProgram/nlp_utilities.jl index 12e639fac..0aa97c099 100644 --- a/src/NonLinearProgram/nlp_utilities.jl +++ b/src/NonLinearProgram/nlp_utilities.jl @@ -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 diff --git a/src/QuadraticProgram/QuadraticProgram.jl b/src/QuadraticProgram/QuadraticProgram.jl index b52901da8..8273308e5 100644 --- a/src/QuadraticProgram/QuadraticProgram.jl +++ b/src/QuadraticProgram/QuadraticProgram.jl @@ -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 diff --git a/src/diff_opt.jl b/src/diff_opt.jl index e018b7917..b61884420 100644 --- a/src/diff_opt.jl +++ b/src/diff_opt.jl @@ -156,6 +156,23 @@ Currently, this only works for the set `MOI.Parameter`. """ struct ForwardConstraintSet <: MOI.AbstractConstraintAttribute end +""" + ForwardParameterValue <: MOI.AbstractVariableAttribute + +A JuMP-level shortcut for forward differentiation with respect to a parameter +variable. Equivalent to setting +`ForwardConstraintSet()` on `ParameterRef(p)` with a wrapped `MOI.Parameter`: + +```julia +set_attribute(p, DiffOpt.ForwardParameterValue(), value) +# same as +set_attribute( + ParameterRef(p), DiffOpt.ForwardConstraintSet(), MOI.Parameter(value), +) +``` +""" +struct ForwardParameterValue <: MOI.AbstractVariableAttribute end + """ ForwardVariablePrimal <: MOI.AbstractVariableAttribute @@ -201,7 +218,7 @@ MOI.set(model, DiffOpt.ReverseConstraintDual(), ci, value) struct ReverseConstraintDual <: MOI.AbstractConstraintAttribute end """ - ReverseObjectiveSensitivity <: MOI.AbstractModelAttribute + ReverseObjectiveValue <: MOI.AbstractModelAttribute A `MOI.AbstractModelAttribute` to set input data for reverse differentiation. @@ -209,10 +226,12 @@ For instance, to set the sensitivity of the parameter perturbation with respect objective function perturbation, do the following: ```julia -MOI.set(model, DiffOpt.ReverseObjectiveSensitivity(), value) +MOI.set(model, DiffOpt.ReverseObjectiveValue(), value) ``` """ -struct ReverseObjectiveSensitivity <: MOI.AbstractModelAttribute end +struct ReverseObjectiveValue <: MOI.AbstractModelAttribute end + +Base.@deprecate_binding ReverseObjectiveSensitivity ReverseObjectiveValue """ ForwardConstraintDual <: MOI.AbstractConstraintAttribute @@ -310,6 +329,23 @@ struct ReverseConstraintSet <: MOI.AbstractConstraintAttribute end MOI.is_set_by_optimize(::ReverseConstraintSet) = true +""" + ReverseParameterValue <: MOI.AbstractVariableAttribute + +A JuMP-level shortcut for reverse differentiation output with respect to a +parameter variable. Equivalent to reading `ReverseConstraintSet()` on +`ParameterRef(p)` and unwrapping `MOI.Parameter`: + +```julia +get_attribute(p, DiffOpt.ReverseParameterValue()) +# same as +get_attribute(ParameterRef(p), DiffOpt.ReverseConstraintSet()).value +``` +""" +struct ReverseParameterValue <: MOI.AbstractVariableAttribute end + +MOI.is_set_by_optimize(::ReverseParameterValue) = true + """ DifferentiateTimeSec() diff --git a/src/jump_moi_overloads.jl b/src/jump_moi_overloads.jl index 3d13a6809..f0d220085 100644 --- a/src/jump_moi_overloads.jl +++ b/src/jump_moi_overloads.jl @@ -12,7 +12,6 @@ # done after the model is optimized, so we add function to bypass the # dirty state. -# DEPRECATE function MOI.set( model::JuMP.Model, attr::ForwardObjectiveFunction, @@ -38,7 +37,6 @@ function MOI.set( return MOI.set(JuMP.backend(model), attr, allow) end -# DEPRECATE function MOI.set( model::JuMP.Model, attr::ForwardObjectiveFunction, @@ -47,28 +45,71 @@ function MOI.set( return MOI.set(model, attr, JuMP.AffExpr(func)) end -# DEPRECATE function MOI.set( model::JuMP.Model, attr::ForwardConstraintFunction, - con_ref::JuMP.ConstraintRef, + con_ref::JuMP.ConstraintRef{ + <:JuMP.AbstractModel, + <:MOI.ConstraintIndex{<:MOI.AbstractScalarFunction}, + }, func::JuMP.AbstractJuMPScalar, ) + JuMP.check_belongs_to_model(con_ref, model) JuMP.check_belongs_to_model(func, model) - return MOI.set(model, attr, con_ref, JuMP.moi_function(func)) + return MOI.set( + JuMP.backend(model), + attr, + JuMP.index(con_ref), + JuMP.moi_function(func), + ) end -# DEPRECATE function MOI.set( model::JuMP.Model, attr::ForwardConstraintFunction, - con_ref::JuMP.ConstraintRef, + con_ref::JuMP.ConstraintRef{ + <:JuMP.AbstractModel, + <:MOI.ConstraintIndex{<:MOI.AbstractScalarFunction}, + }, func::Number, ) return MOI.set(model, attr, con_ref, JuMP.AffExpr(func)) end -# DEPRECATE - then modify +# Similar to `JuMP.set_start_value` for vector `ConstraintRef` in +# JuMP/src/constraints.jl +function MOI.set( + model::JuMP.Model, + attr::ForwardConstraintFunction, + con_ref::JuMP.ConstraintRef{ + <:JuMP.AbstractModel, + <:MOI.ConstraintIndex{<:MOI.AbstractVectorFunction}, + }, + value::AbstractArray{<:JuMP.AbstractJuMPScalar}, +) + JuMP.check_belongs_to_model(con_ref, model) + JuMP.check_belongs_to_model.(value, model) + v = JuMP.vectorize(value, con_ref.shape) + return MOI.set( + JuMP.backend(model), + attr, + JuMP.index(con_ref), + JuMP.moi_function(v), + ) +end + +function MOI.set( + model::JuMP.Model, + attr::ForwardConstraintFunction, + con_ref::JuMP.ConstraintRef{ + <:JuMP.AbstractModel, + <:MOI.ConstraintIndex{<:MOI.AbstractVectorFunction}, + }, + value::AbstractArray{<:Number}, +) + return MOI.set(model, attr, con_ref, JuMP.AffExpr.(value)) +end + function MOI.get( model::JuMP.Model, attr::ForwardConstraintDual, @@ -79,13 +120,11 @@ function MOI.get( return JuMP.jump_function(model, moi_func) end -# DEPRECATE - then modify function MOI.get(model::JuMP.Model, attr::ReverseObjectiveFunction) func = MOI.get(JuMP.backend(model), attr) return JuMP.jump_function(model, func) end -# DEPRECATE - then modify function MOI.get( model::JuMP.Model, attr::ReverseConstraintFunction, @@ -113,7 +152,6 @@ function _moi_get_result(model::MOI.Utilities.CachingOptimizer, args...) return MOI.get(model, args...) end -# DEPRECATE function MOI.get( model::JuMP.Model, attr::ForwardVariablePrimal, @@ -123,7 +161,6 @@ function MOI.get( return _moi_get_result(JuMP.backend(model), attr, JuMP.index(var_ref)) end -# REVIEW function MOI.get( model::JuMP.Model, attr::ReverseConstraintSet, @@ -143,9 +180,30 @@ function MOI.set( return MOI.set(JuMP.backend(model), attr, JuMP.index(con_ref), set) end +function MOI.set( + model::JuMP.Model, + ::ForwardParameterValue, + p::JuMP.VariableRef, + value::Number, +) + return MOI.set( + model, + ForwardConstraintSet(), + JuMP.ParameterRef(p), + MOI.Parameter(value), + ) +end + +function MOI.get( + model::JuMP.Model, + ::ReverseParameterValue, + p::JuMP.VariableRef, +) + return MOI.get(model, ReverseConstraintSet(), JuMP.ParameterRef(p)).value +end + # there is no set_forward_constraint_set because there is set_forward_parameter -# DEPRECATE function MOI.set( model::JuMP.Model, attr::ForwardConstraintSet, diff --git a/src/jump_wrapper.jl b/src/jump_wrapper.jl index eacd12ccf..8222e891b 100644 --- a/src/jump_wrapper.jl +++ b/src/jump_wrapper.jl @@ -99,114 +99,140 @@ end set_forward_parameter(model::JuMP.Model, variable::JuMP.VariableRef, value::Number) Set the value of a parameter input sensitivity for forward mode. + +Equivalent to `set_attribute(variable, DiffOpt.ForwardParameterValue(), value)`, +which is the preferred form going forward. """ function set_forward_parameter( model::JuMP.Model, variable::JuMP.VariableRef, value::Number, ) - JuMP.check_belongs_to_model(variable, model) - return MOI.set( - JuMP.backend(model), - ForwardConstraintSet(), - JuMP.index(ParameterRef(variable)), - MOI.Parameter(value), + Base.depwarn( + "`DiffOpt.set_forward_parameter(model, variable, value)` is deprecated; use `set_attribute(variable, DiffOpt.ForwardParameterValue(), value)`.", + :set_forward_parameter, ) + return JuMP.set_attribute(variable, ForwardParameterValue(), value) end """ get_reverse_parameter(model::JuMP.Model, variable::JuMP.VariableRef) Get the value of a parameter output sensitivity for reverse mode. + +Equivalent to `get_attribute(variable, DiffOpt.ReverseParameterValue())`, +which is the preferred form going forward. """ function get_reverse_parameter(model::JuMP.Model, variable::JuMP.VariableRef) - JuMP.check_belongs_to_model(variable, model) - return MOI.get( - JuMP.backend(model), - ReverseConstraintSet(), - JuMP.index(ParameterRef(variable)), - ).value + Base.depwarn( + "`DiffOpt.get_reverse_parameter(model, variable)` is deprecated; use `get_attribute(variable, DiffOpt.ReverseParameterValue())`.", + :get_reverse_parameter, + ) + return JuMP.get_attribute(variable, ReverseParameterValue()) end """ set_reverse_variable(model::JuMP.Model, variable::JuMP.VariableRef, value::Number) Set the value of a variable input sensitivity for reverse mode. + +Equivalent to `set_attribute(variable, DiffOpt.ReverseVariablePrimal(), value)`, +which is the preferred form going forward. """ function set_reverse_variable( model::JuMP.Model, variable::JuMP.VariableRef, value::Number, ) - JuMP.check_belongs_to_model(variable, model) - return MOI.set( - JuMP.backend(model), - ReverseVariablePrimal(), - JuMP.index(variable), - value, + Base.depwarn( + "`DiffOpt.set_reverse_variable(model, variable, value)` is deprecated; use `set_attribute(variable, DiffOpt.ReverseVariablePrimal(), value)`.", + :set_reverse_variable, ) + return JuMP.set_attribute(variable, ReverseVariablePrimal(), value) end """ get_forward_variable(model::JuMP.Model, variable::JuMP.VariableRef) Get the value of a variable output sensitivity for forward mode. + +Equivalent to `get_attribute(variable, DiffOpt.ForwardVariablePrimal())`, +which is the preferred form going forward. """ function get_forward_variable(model::JuMP.Model, variable::JuMP.VariableRef) - JuMP.check_belongs_to_model(variable, model) - return _moi_get_result( - JuMP.backend(model), - ForwardVariablePrimal(), - JuMP.index(variable), + Base.depwarn( + "`DiffOpt.get_forward_variable(model, variable)` is deprecated; use `get_attribute(variable, DiffOpt.ForwardVariablePrimal())`.", + :get_forward_variable, ) + return JuMP.get_attribute(variable, ForwardVariablePrimal()) end """ set_reverse_objective(model::JuMP.Model, value::Number) Set the value of the objective input sensitivity for reverse mode. + +Equivalent to `set_attribute(model, DiffOpt.ReverseObjectiveValue(), value)`, +which is the preferred form going forward. """ function set_reverse_objective(model::JuMP.Model, value::Number) - return MOI.set(model, ReverseObjectiveSensitivity(), value) + Base.depwarn( + "`DiffOpt.set_reverse_objective(model, value)` is deprecated; use `set_attribute(model, DiffOpt.ReverseObjectiveValue(), value)`.", + :set_reverse_objective, + ) + return JuMP.set_attribute(model, ReverseObjectiveValue(), value) end """ get_forward_objective(model::JuMP.Model) Get the value of the objective output sensitivity for forward mode. + +Equivalent to `get_attribute(model, DiffOpt.ForwardObjectiveSensitivity())`, +which is the preferred form going forward. """ function get_forward_objective(model::JuMP.Model) - return MOI.get(model, ForwardObjectiveSensitivity()) + Base.depwarn( + "`DiffOpt.get_forward_objective(model)` is deprecated; use `get_attribute(model, DiffOpt.ForwardObjectiveSensitivity())`.", + :get_forward_objective, + ) + return JuMP.get_attribute(model, ForwardObjectiveSensitivity()) end """ set_forward_objective_function(model::JuMP.Model, func) Set the function to be used for forward mode differentiation of the objective. + +Equivalent to `set_attribute(model, DiffOpt.ForwardObjectiveFunction(), func)`, +which is the preferred form going forward. """ function set_forward_objective_function( model::JuMP.Model, func::JuMP.AbstractJuMPScalar, ) - return MOI.set( - JuMP.backend(model), - ForwardObjectiveFunction(), - JuMP.moi_function(func), + Base.depwarn( + "`DiffOpt.set_forward_objective_function(model, func)` is deprecated; use `set_attribute(model, DiffOpt.ForwardObjectiveFunction(), func)`.", + :set_forward_objective_function, ) + return JuMP.set_attribute(model, ForwardObjectiveFunction(), func) end function set_forward_objective_function(model::JuMP.Model, value::Number) - return MOI.set( - JuMP.backend(model), - ForwardObjectiveFunction(), - JuMP.moi_function(JuMP.AffExpr(value)), + Base.depwarn( + "`DiffOpt.set_forward_objective_function(model, value)` is deprecated; use `set_attribute(model, DiffOpt.ForwardObjectiveFunction(), value)`.", + :set_forward_objective_function, ) + return JuMP.set_attribute(model, ForwardObjectiveFunction(), value) end """ set_forward_constraint_function(model::JuMP.Model, con_ref::JuMP.ConstraintRef, func) Set the function to be used for forward mode differentiation of a constraint. + +Equivalent to `set_attribute(con_ref, DiffOpt.ForwardConstraintFunction(), func)`, +which is the preferred form going forward. """ function set_forward_constraint_function( model::JuMP.Model, @@ -216,14 +242,11 @@ function set_forward_constraint_function( }, func::JuMP.AbstractJuMPScalar, ) where {M} - JuMP.check_belongs_to_model(con_ref, model) - JuMP.check_belongs_to_model(func, model) - return MOI.set( - JuMP.backend(model), - ForwardConstraintFunction(), - JuMP.index(con_ref), - JuMP.moi_function(func), + Base.depwarn( + "`DiffOpt.set_forward_constraint_function(model, con_ref, func)` is deprecated; use `set_attribute(con_ref, DiffOpt.ForwardConstraintFunction(), func)`.", + :set_forward_constraint_function, ) + return JuMP.set_attribute(con_ref, ForwardConstraintFunction(), func) end function set_forward_constraint_function( @@ -234,11 +257,13 @@ function set_forward_constraint_function( }, value::Number, ) where {M} - return set_forward_constraint_function(model, con_ref, JuMP.AffExpr(value)) + Base.depwarn( + "`DiffOpt.set_forward_constraint_function(model, con_ref, value)` is deprecated; use `set_attribute(con_ref, DiffOpt.ForwardConstraintFunction(), value)`.", + :set_forward_constraint_function, + ) + return JuMP.set_attribute(con_ref, ForwardConstraintFunction(), value) end -# Similar to `JuMP.set_start_value` for vector `ConstraintRef` in -# JuMP/src/constraints.jl function set_forward_constraint_function( model::JuMP.Model, con_ref::JuMP.ConstraintRef{ @@ -247,19 +272,13 @@ function set_forward_constraint_function( }, value::AbstractArray{<:JuMP.AbstractJuMPScalar}, ) - JuMP.check_belongs_to_model(con_ref, model) - JuMP.check_belongs_to_model.(value, model) - v = JuMP.vectorize(value, con_ref.shape) - return MOI.set( - JuMP.backend(model), - ForwardConstraintFunction(), - JuMP.index(con_ref), - JuMP.moi_function(v), + Base.depwarn( + "`DiffOpt.set_forward_constraint_function(model, con_ref, value)` is deprecated; use `set_attribute(con_ref, DiffOpt.ForwardConstraintFunction(), value)`.", + :set_forward_constraint_function, ) + return JuMP.set_attribute(con_ref, ForwardConstraintFunction(), value) end -# Similar to `JuMP.set_start_value` for vector `ConstraintRef` in -# JuMP/src/constraints.jl function set_forward_constraint_function( model::JuMP.Model, con_ref::JuMP.ConstraintRef{ @@ -268,51 +287,63 @@ function set_forward_constraint_function( }, value::AbstractArray{<:Number}, ) - return set_forward_constraint_function(model, con_ref, JuMP.AffExpr.(value)) + Base.depwarn( + "`DiffOpt.set_forward_constraint_function(model, con_ref, value)` is deprecated; use `set_attribute(con_ref, DiffOpt.ForwardConstraintFunction(), value)`.", + :set_forward_constraint_function, + ) + return JuMP.set_attribute(con_ref, ForwardConstraintFunction(), value) end """ get_forward_constraint_dual(model::JuMP.Model, con_ref::JuMP.ConstraintRef) Get the value of a constraint dual output sensitivity for forward mode. + +Equivalent to `get_attribute(con_ref, DiffOpt.ForwardConstraintDual())`, +which is the preferred form going forward. """ function get_forward_constraint_dual( model::JuMP.Model, con_ref::JuMP.ConstraintRef, ) - JuMP.check_belongs_to_model(con_ref, model) - moi_func = MOI.get( - JuMP.backend(model), - ForwardConstraintDual(), - JuMP.index(con_ref), + Base.depwarn( + "`DiffOpt.get_forward_constraint_dual(model, con_ref)` is deprecated; use `get_attribute(con_ref, DiffOpt.ForwardConstraintDual())`.", + :get_forward_constraint_dual, ) - return JuMP.jump_function(model, moi_func) + return JuMP.get_attribute(con_ref, ForwardConstraintDual()) end """ get_reverse_objective_function(model::JuMP.Model) Get the function to be used for reverse mode differentiation of the objective. + +Equivalent to `get_attribute(model, DiffOpt.ReverseObjectiveFunction())`, +which is the preferred form going forward. """ function get_reverse_objective_function(model::JuMP.Model) - func = MOI.get(JuMP.backend(model), ReverseObjectiveFunction()) - return JuMP.jump_function(model, func) + Base.depwarn( + "`DiffOpt.get_reverse_objective_function(model)` is deprecated; use `get_attribute(model, DiffOpt.ReverseObjectiveFunction())`.", + :get_reverse_objective_function, + ) + return JuMP.get_attribute(model, ReverseObjectiveFunction()) end """ get_reverse_constraint_function(model::JuMP.Model, con_ref::JuMP.ConstraintRef) Get the function to be used for reverse mode differentiation of a constraint. + +Equivalent to `get_attribute(con_ref, DiffOpt.ReverseConstraintFunction())`, +which is the preferred form going forward. """ function get_reverse_constraint_function( model::JuMP.Model, con_ref::JuMP.ConstraintRef, ) - JuMP.check_belongs_to_model(con_ref, model) - moi_func = MOI.get( - JuMP.backend(model), - ReverseConstraintFunction(), - JuMP.index(con_ref), + Base.depwarn( + "`DiffOpt.get_reverse_constraint_function(model, con_ref)` is deprecated; use `get_attribute(con_ref, DiffOpt.ReverseConstraintFunction())`.", + :get_reverse_constraint_function, ) - return JuMP.jump_function(model, moi_func) + return JuMP.get_attribute(con_ref, ReverseConstraintFunction()) end diff --git a/src/moi_wrapper.jl b/src/moi_wrapper.jl index 022e38150..d46c3f7a6 100644 --- a/src/moi_wrapper.jl +++ b/src/moi_wrapper.jl @@ -588,7 +588,7 @@ function MOI.set(model::Optimizer, attr::ReverseDifferentiate, value) end if !iszero(model.input_cache.dobj) try - MOI.set(diff, ReverseObjectiveSensitivity(), model.input_cache.dobj) + MOI.set(diff, ReverseObjectiveValue(), model.input_cache.dobj) catch e if e isa MOI.UnsupportedAttribute _fallback_set_reverse_objective_sensitivity( @@ -1006,7 +1006,7 @@ function MOI.set( return end -function MOI.set(model::Optimizer, ::ReverseObjectiveSensitivity, val) +function MOI.set(model::Optimizer, ::ReverseObjectiveValue, val) model.input_cache.dobj = val return end diff --git a/test/conic_program.jl b/test/conic_program.jl index a45b1a461..315b3d470 100644 --- a/test/conic_program.jl +++ b/test/conic_program.jl @@ -410,7 +410,7 @@ function _build_simple_sdp() @constraint(model, c1, sum(x[i] for i in 1:3) == 4) - @constraint(model, c2[i=1:3], x[i] ≥ 0) + @constraint(model, c2[i = 1:3], x[i] ≥ 0) @constraint(model, x[1] == 2) @@ -843,7 +843,7 @@ function test_jump_psd_cone_with_parameter_pv_v_pv() @objective(model, Min, x) optimize!(model) direction_p = 2.0 - DiffOpt.set_forward_parameter(model, p, direction_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) dx = MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) @test dx ≈ -direction_p * 3 * sqrt(3) / (2 + sqrt(3) * 1)^2 atol = 1e-4 rtol = @@ -864,13 +864,13 @@ function test_psd_cone_with_parameter_pp_terms() @objective(model, Min, x) optimize!(model) @test value(x) ≈ 1.0 atol = ATOL - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - dx = DiffOpt.get_forward_variable(model, x) + dx = get_attribute(x, DiffOpt.ForwardVariablePrimal()) @test dx ≈ -2.0 atol = ATOL - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) - dp = DiffOpt.get_reverse_parameter(model, p) + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test dp ≈ -2.0 atol = ATOL return end @@ -892,14 +892,14 @@ function test_psd_cone_with_parameter_pv_and_p_terms() @test value(x) ≈ 1.0 atol = ATOL # Forward: pv terms in vector quadratic forward give ~0 # (known upstream issue: parameter sensitivities for pv terms not propagated in forward) - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - dx = DiffOpt.get_forward_variable(model, x) + dx = get_attribute(x, DiffOpt.ForwardVariablePrimal()) @test dx ≈ 0.0 atol = ATOL # Reverse: verify gradient value - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) - dp = DiffOpt.get_reverse_parameter(model, p) + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test dp ≈ 0.5 atol = ATOL return end @@ -974,14 +974,14 @@ function test_square_bridge_forward_psd() optimize!(model) @test value(t) ≈ 1.0 atol = ATOL # Perturb the off-diagonal entries - DiffOpt.set_forward_constraint_function(model, cons, [0.0 1.0; 1.0 0.0]) + set_attribute(cons, DiffOpt.ForwardConstraintFunction(), [0.0 1.0; 1.0 0.0]) DiffOpt.forward_differentiate!(model) - dt = DiffOpt.get_forward_variable(model, t) + dt = get_attribute(t, DiffOpt.ForwardVariablePrimal()) @test dt ≈ 0.5 atol = ATOL # Perturb the diagonal entries - DiffOpt.set_forward_constraint_function(model, cons, [1.0 0.0; 0.0 1.0]) + set_attribute(cons, DiffOpt.ForwardConstraintFunction(), [1.0 0.0; 0.0 1.0]) DiffOpt.forward_differentiate!(model) - dt2 = DiffOpt.get_forward_variable(model, t) + dt2 = get_attribute(t, DiffOpt.ForwardVariablePrimal()) @test dt2 ≈ -1.0 atol = ATOL return end @@ -1045,10 +1045,10 @@ function test_square_bridge_asymmetric_sym() @test value(x) ≈ -2.0 atol = ATOL @test value(y) ≈ -2.0 atol = ATOL # Forward: perturb diagonal by 1 → dx/dε = dy/dε = -1 - DiffOpt.set_forward_constraint_function(model, cpsd, [1.0 0.0; 0.0 1.0]) + set_attribute(cpsd, DiffOpt.ForwardConstraintFunction(), [1.0 0.0; 0.0 1.0]) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_variable(model, x) ≈ -1.0 atol = ATOL - @test DiffOpt.get_forward_variable(model, y) ≈ -1.0 atol = ATOL + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ -1.0 atol = ATOL + @test get_attribute(y, DiffOpt.ForwardVariablePrimal()) ≈ -1.0 atol = ATOL # Reverse: seed dx=1, dy=1 → d(loss)/d(diag) = 1*(-1) + 1*(-1) = -2 DiffOpt.empty_input_sensitivities!(model) MOI.set( @@ -1101,26 +1101,26 @@ function test_square_bridge_asymmetric_sym_parametric() @test value(x) ≈ -2.0 atol = ATOL @test value(y) ≈ -2.0 atol = ATOL # Forward: dp = 1 → dx = dy = -1 - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_variable(model, x) ≈ -1.0 atol = ATOL - @test DiffOpt.get_forward_variable(model, y) ≈ -1.0 atol = ATOL + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ -1.0 atol = ATOL + @test get_attribute(y, DiffOpt.ForwardVariablePrimal()) ≈ -1.0 atol = ATOL # Reverse: seed dx=1 → dp = -1 DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ -1.0 atol = ATOL + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ -1.0 atol = ATOL # Reverse: seed dy=1 → dp = -1 DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_reverse_variable(model, y, 1.0) + set_attribute(y, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ -1.0 atol = ATOL + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ -1.0 atol = ATOL # Reverse: seed dx=1, dy=1 → dp = -2 DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_reverse_variable(model, x, 1.0) - DiffOpt.set_reverse_variable(model, y, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) + set_attribute(y, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ -2.0 atol = ATOL + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ -2.0 atol = ATOL return end diff --git a/test/data/nlp_problems.jl b/test/data/nlp_problems.jl index 6ce4fa675..2769ae82c 100644 --- a/test/data/nlp_problems.jl +++ b/test/data/nlp_problems.jl @@ -14,7 +14,7 @@ function create_nonlinear_jump_model(; ismin = true) @variable(model, p ∈ MOI.Parameter(1.0)) @variable(model, p2 ∈ MOI.Parameter(2.0)) @variable(model, p3 ∈ MOI.Parameter(100.0)) - @variable(model, x[i=1:2], start = -i) + @variable(model, x[i = 1:2], start = -i) @constraint(model, g_1, x[1]^2 <= p) @constraint(model, g_2, p * (x[1] + x[2])^2 <= p2) if ismin @@ -38,7 +38,7 @@ function create_nonlinear_jump_model_sipopt(; ismin = true) set_silent(model) @variable(model, p1 ∈ MOI.Parameter(4.5)) @variable(model, p2 ∈ MOI.Parameter(1.0)) - @variable(model, x[i=1:3] >= 0, start = -i) + @variable(model, x[i = 1:3] >= 0, start = -i) @constraint(model, g_1, 6 * x[1] + 3 * x[2] + 2 * x[3] - p1 == 0) @constraint(model, g_2, p2 * x[1] + x[2] - x[3] - 1 == 0) if ismin @@ -158,14 +158,14 @@ function create_jump_model_6(p_a = collect(1.0:0.1:2.0)) set_silent(model) # Parameters - @variable(model, x[i=1:length(p_a)] ∈ MOI.Parameter.(p_a)) + @variable(model, x[i = 1:length(p_a)] ∈ MOI.Parameter.(p_a)) # Variables @variable(model, y[1:length(p_a)] >= 0.0) # Constraints @constraint(model, con1, sum(y) == 1) - @constraint(model, con2[i=1:length(x)], y[i] <= 1) + @constraint(model, con2[i = 1:length(x)], y[i] <= 1) # Objective @objective(model, Max, dot(x, y) + h(y)) @@ -203,7 +203,7 @@ function create_nonlinear_jump_model_1(p_val = [1.0; 2.0; 100]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:3] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:3] ∈ MOI.Parameter.(p_val)) # Variables @variable(model, x) @@ -228,7 +228,7 @@ function create_nonlinear_jump_model_2(p_val = [3.0; 2.0; 10]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:3] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:3] ∈ MOI.Parameter.(p_val)) # Variables @variable(model, x <= 10) @@ -253,7 +253,7 @@ function create_nonlinear_jump_model_3(p_val = [3.0; 2.0; 10]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:3] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:3] ∈ MOI.Parameter.(p_val)) # Variables @variable(model, x <= 10) @@ -277,7 +277,7 @@ function create_nonlinear_jump_model_4(p_val = [1.0; 2.0; 100]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:3] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:3] ∈ MOI.Parameter.(p_val)) # Variables @variable(model, x) @@ -303,7 +303,7 @@ function create_nonlinear_jump_model_5(p_val = [1.0; 2.0; 100]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:3] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:3] ∈ MOI.Parameter.(p_val)) # Variables @variable(model, x) @@ -330,10 +330,10 @@ function create_nonlinear_jump_model_6(p_val = [100.0; 200.0]; ismin = true) set_silent(model) # Parameters - @variable(model, p[i=1:2] ∈ MOI.Parameter.(p_val)) + @variable(model, p[i = 1:2] ∈ MOI.Parameter.(p_val)) # Variables - @variable(model, x[i=1:2]) + @variable(model, x[i = 1:2]) @variable(model, z) # >= 2.0) @variable(model, w) # <= 3.0) # @variable(model, f[1:2]) diff --git a/test/jump.jl b/test/jump.jl index b4db4a68a..4cc068216 100644 --- a/test/jump.jl +++ b/test/jump.jl @@ -46,7 +46,7 @@ function test_single_variable_objective_forward() ) @objective(model, Max, x[7]) optimize!(model) - DiffOpt.set_forward_objective_function(model, sum(x)) + set_attribute(model, DiffOpt.ForwardObjectiveFunction(), sum(x)) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x[7]) ≈ 0 atol = ATOL return @@ -69,7 +69,7 @@ function test_single_variable_objective_reverse() optimize!(model) MOI.set(model, DiffOpt.ReverseVariablePrimal(), x[7], 1.0) DiffOpt.reverse_differentiate!(model) - func = DiffOpt.get_reverse_objective_function(model) + func = get_attribute(model, DiffOpt.ReverseObjectiveFunction()) @test JuMP.coefficient(func, x[7]) ≈ 0.0 atol = ATOL rtol = RTOL return end @@ -112,11 +112,12 @@ function test_differentiating_trivial_qp_1() MOI.set.(model, DiffOpt.ReverseVariablePrimal(), x, 1.0) DiffOpt.reverse_differentiate!(model) DiffOpt.reverse_differentiate!(model) - grad_constraint = - JuMP.constant(DiffOpt.get_reverse_constraint_function(model, ctr_le[1])) + grad_constraint = JuMP.constant( + get_attribute(ctr_le[1], DiffOpt.ReverseConstraintFunction()), + ) @test grad_constraint ≈ -1.0 atol = ATOL rtol = RTOL # Test some overloads from https://github.com/jump-dev/DiffOpt.jl/issues/211 - grad_obj = DiffOpt.get_reverse_objective_function(model) + grad_obj = get_attribute(model, DiffOpt.ReverseObjectiveFunction()) @test JuMP.coefficient(grad_obj, x[1], x[2]) ≈ DiffOpt.quad_sym_half.(grad_obj, x[1], x[2]) atol = ATOL rtol = RTOL @test DiffOpt.quad_sym_half(grad_obj, x[1], x[1]) ≈ @@ -712,7 +713,7 @@ function test_conic_feasibility() optimize!(model) - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) return end @@ -732,15 +733,18 @@ function test_psd_square() @test is_solved_and_feasible(model) @test value(x) ≈ 1.0 atol = ATOL rtol = RTOL - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_variable(model, x) ≈ 1.0 atol = ATOL rtol = RTOL - @test DiffOpt.get_forward_objective(model) ≈ -1.0 atol = ATOL rtol = RTOL + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ 1.0 atol = ATOL rtol = + RTOL + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ -1.0 atol = + ATOL rtol = RTOL DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_reverse_objective(model, 1.0) + set_attribute(model, DiffOpt.ReverseObjectiveValue(), 1.0) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ -1.0 atol = ATOL rtol = RTOL + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ -1.0 atol = ATOL rtol = + RTOL return end @@ -761,13 +765,16 @@ function test_nlp_forward_constraint_dual() @test value(x) ≈ 0.25 atol = ATOL rtol = RTOL @test value(y) ≈ 0.75 atol = ATOL rtol = RTOL - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_variable(model, x) ≈ 0.25 atol = ATOL rtol = RTOL - @test DiffOpt.get_forward_variable(model, y) ≈ 0.75 atol = ATOL rtol = RTOL - @test DiffOpt.get_forward_constraint_dual(model, c1) ≈ 1.75 atol = ATOL rtol = + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ 0.25 atol = ATOL rtol = + RTOL + @test get_attribute(y, DiffOpt.ForwardVariablePrimal()) ≈ 0.75 atol = ATOL rtol = + RTOL + @test get_attribute(c1, DiffOpt.ForwardConstraintDual()) ≈ 1.75 atol = ATOL rtol = RTOL - @test DiffOpt.get_forward_objective(model) ≈ 2.75 atol = ATOL rtol = RTOL + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ 2.75 atol = + ATOL rtol = RTOL return end diff --git a/test/jump_wrapper.jl b/test/jump_wrapper.jl index 97302999d..abdcbcf6d 100644 --- a/test/jump_wrapper.jl +++ b/test/jump_wrapper.jl @@ -60,16 +60,16 @@ function test_obj_simple() DiffOpt.empty_input_sensitivities!(model) direction_obj = 2.0 - DiffOpt.set_reverse_objective(model, direction_obj) + set_attribute(model, DiffOpt.ReverseObjectiveValue(), direction_obj) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ sign_p * sign * 6 * direction_obj atol = ATOL rtol = RTOL DiffOpt.empty_input_sensitivities!(model) direction_p = 3.0 - DiffOpt.set_forward_parameter(model, p, direction_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_objective(model) ≈ + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ sign_p * sign * 6 * direction_p atol = ATOL rtol = RTOL end end @@ -121,17 +121,17 @@ function test_obj_simple_quad() DiffOpt.empty_input_sensitivities!(model) direction_obj = 2.0 - DiffOpt.set_reverse_objective(model, direction_obj) + set_attribute(model, DiffOpt.ReverseObjectiveValue(), direction_obj) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ sign_p * sign * 3 * (4 * value(x) + 7) * direction_obj atol = ATOL rtol = RTOL DiffOpt.empty_input_sensitivities!(model) direction_p = 3.0 - DiffOpt.set_forward_parameter(model, p, direction_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_objective(model) ≈ + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ sign_p * sign * 3 * (4 * value(x) + 7) * direction_p atol = ATOL rtol = RTOL end @@ -173,20 +173,20 @@ function _test_obj(MODEL, SOLVER; ineq, _min, flip, with_bridge_type) DiffOpt.empty_input_sensitivities!(model) direction_obj = 2.0 - DiffOpt.set_reverse_objective(model, direction_obj) + set_attribute(model, DiffOpt.ReverseObjectiveValue(), direction_obj) DiffOpt.reverse_differentiate!(model) - @test DiffOpt.get_reverse_parameter(model, p) ≈ + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ dir * sign * obj_coef * direction_obj * 3 / pc_val atol = ATOL rtol = RTOL - @test DiffOpt.get_reverse_parameter(model, pc) ≈ + @test get_attribute(pc, DiffOpt.ReverseParameterValue()) ≈ -dir * sign * obj_coef * direction_obj * 3 * p_val / (pc_val^2) atol = ATOL rtol = RTOL DiffOpt.empty_input_sensitivities!(model) direction_p = 3.0 - DiffOpt.set_forward_parameter(model, p, direction_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_objective(model) ≈ + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ dir * sign * obj_coef * direction_p * 3 / pc_val atol = ATOL rtol = RTOL @@ -194,9 +194,9 @@ function _test_obj(MODEL, SOLVER; ineq, _min, flip, with_bridge_type) 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) - @test DiffOpt.get_forward_objective(model) ≈ + @test get_attribute(model, DiffOpt.ForwardObjectiveSensitivity()) ≈ -dir * sign * obj_coef * direction_pc * 3 * p_val / pc_val^2 atol = ATOL rtol = RTOL end @@ -302,9 +302,9 @@ function test_jump_api() # 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) - @test DiffOpt.get_forward_variable(model, x) ≈ + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ direction_p * 3 / pc_val atol = ATOL rtol = RTOL # update p and pc @@ -321,20 +321,20 @@ function test_jump_api() 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) - @test DiffOpt.get_forward_variable(model, x) ≈ + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ -direction_pc * 3 * p_val / pc_val^2 atol = ATOL rtol = RTOL # 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) - @test DiffOpt.get_reverse_parameter(model, p) ≈ + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ direction_x * 3 / pc_val atol = ATOL rtol = RTOL - @test DiffOpt.get_reverse_parameter(model, pc) ≈ + @test get_attribute(pc, DiffOpt.ReverseParameterValue()) ≈ -direction_x * 3 * p_val / pc_val^2 atol = ATOL rtol = RTOL end end @@ -342,9 +342,8 @@ function test_jump_api() return end -function test_forward_wrappers_non_parametric() - # Tests set_forward_objective_function and set_forward_constraint_function - # overloads on a non-parametric model. +function test_forward_non_parametric() + # set_attribute on ForwardObjectiveFunction / ForwardConstraintFunction on a non-parametric model. # # min x s.t. x + y == 1, x >= 0, y >= 0 # Solution: x=0, y=1 @@ -361,22 +360,22 @@ function test_forward_wrappers_non_parametric() @test value(x) ≈ 0.0 atol = ATOL @test value(y) ≈ 1.0 atol = ATOL - DiffOpt.set_forward_objective_function(model, 0.0) - DiffOpt.set_forward_constraint_function(model, c1, 1.0) + set_attribute(model, DiffOpt.ForwardObjectiveFunction(), 0.0) + set_attribute(c1, DiffOpt.ForwardConstraintFunction(), 1.0) DiffOpt.forward_differentiate!(model) - dy = DiffOpt.get_forward_variable(model, y) + dy = get_attribute(y, DiffOpt.ForwardVariablePrimal()) @test dy ≈ -1.0 atol = ATOL DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_forward_constraint_function(model, c1, 0.0 * x + 1.0) + set_attribute(c1, DiffOpt.ForwardConstraintFunction(), 0.0 * x + 1.0) DiffOpt.forward_differentiate!(model) - dy2 = DiffOpt.get_forward_variable(model, y) + dy2 = get_attribute(y, DiffOpt.ForwardVariablePrimal()) @test dy2 ≈ dy atol = ATOL return end -function test_forward_vector_constraint_wrappers() - # Tests set_forward_constraint_function overloads for vector constraints +function test_forward_vector_constraint() + # set_attribute on ForwardConstraintFunction for a vector (Nonnegatives) constraint # using conic_diff_model (direct_model + diff_optimizer bridges differently). model = DiffOpt.conic_diff_model(SCS.Optimizer) set_silent(model) @@ -389,25 +388,25 @@ function test_forward_vector_constraint_wrappers() @test value(x) ≈ 0.0 atol = ATOL @test value(y) ≈ 1.0 atol = ATOL - DiffOpt.set_forward_constraint_function(model, c_nn, [0.0, 0.0]) - DiffOpt.set_forward_constraint_function(model, c_eq, 1.0) + set_attribute(c_nn, DiffOpt.ForwardConstraintFunction(), [0.0, 0.0]) + set_attribute(c_eq, DiffOpt.ForwardConstraintFunction(), 1.0) DiffOpt.forward_differentiate!(model) - dy = DiffOpt.get_forward_variable(model, y) + dy = get_attribute(y, DiffOpt.ForwardVariablePrimal()) @test dy ≈ -1.0 atol = ATOL DiffOpt.empty_input_sensitivities!(model) - DiffOpt.set_forward_constraint_function(model, c_nn, [0.0 * x, 0.0 * x]) - DiffOpt.set_forward_constraint_function(model, c_eq, 1.0) + set_attribute(c_nn, DiffOpt.ForwardConstraintFunction(), [0.0 * x, 0.0 * x]) + set_attribute(c_eq, DiffOpt.ForwardConstraintFunction(), 1.0) DiffOpt.forward_differentiate!(model) - dy2 = DiffOpt.get_forward_variable(model, y) + dy2 = get_attribute(y, DiffOpt.ForwardVariablePrimal()) @test dy2 ≈ dy atol = ATOL return end -function test_forward_psd_matrix_wrapper() - # Tests set_forward_constraint_function with AbstractMatrix{<:AbstractJuMPScalar} - # for PSD cone constraints. Uses a non-parametric model since - # ForwardConstraintFunction is blocked on parametric models. +function test_forward_psd_matrix() + # set_attribute on ForwardConstraintFunction with an AbstractMatrix{<:AbstractJuMPScalar} + # for a PSD cone constraint. Non-parametric model since ForwardConstraintFunction + # is blocked on parametric models. model = Model(() -> DiffOpt.diff_optimizer(SCS.Optimizer)) set_silent(model) @variable(model, x) @@ -421,9 +420,51 @@ function test_forward_psd_matrix_wrapper() @test value(x) ≈ 1.0 atol = ATOL perturbation = [1.0+0.0*x 0.0*x; 0.0*x 0.0*x] - DiffOpt.set_forward_constraint_function(model, con, perturbation) + set_attribute(con, DiffOpt.ForwardConstraintFunction(), perturbation) DiffOpt.forward_differentiate!(model) - @test DiffOpt.get_forward_variable(model, x) ≈ 1.0 atol = ATOL + @test get_attribute(x, DiffOpt.ForwardVariablePrimal()) ≈ 1.0 atol = ATOL + return +end + +function test_wrapper_deprecation_smoke() + # Smoke test that each deprecated JuMP wrapper still executes. Canonical + # usage is via `set_attribute` / `get_attribute` on DiffOpt MOI attributes; + # these wrappers will be deprecated in a follow-up PR. + model = DiffOpt.diff_model(HiGHS.Optimizer) + set_silent(model) + @variable(model, x) + @variable(model, p in Parameter(1.0)) + @constraint(model, c, x == 2 * p) + @objective(model, Min, x) + optimize!(model) + + DiffOpt.empty_input_sensitivities!(model) + DiffOpt.set_forward_parameter(model, p, 1.0) + DiffOpt.forward_differentiate!(model) + @test DiffOpt.get_forward_variable(model, x) ≈ 2.0 atol = ATOL + @test DiffOpt.get_forward_objective(model) ≈ 2.0 atol = ATOL + + DiffOpt.empty_input_sensitivities!(model) + DiffOpt.set_reverse_variable(model, x, 1.0) + DiffOpt.reverse_differentiate!(model) + @test DiffOpt.get_reverse_parameter(model, p) ≈ 2.0 atol = ATOL + + DiffOpt.empty_input_sensitivities!(model) + DiffOpt.set_reverse_objective(model, 1.0) + DiffOpt.reverse_differentiate!(model) + @test DiffOpt.get_reverse_parameter(model, p) ≈ 2.0 atol = ATOL + + direct = JuMP.direct_model(DiffOpt.diff_optimizer(HiGHS.Optimizer)) + set_silent(direct) + @variable(direct, x2 >= 0) + @variable(direct, y2 >= 0) + @constraint(direct, c2, x2 + y2 == 1) + @objective(direct, Min, 1.0 * x2) + optimize!(direct) + DiffOpt.set_forward_objective_function(direct, 0.0) + DiffOpt.set_forward_constraint_function(direct, c2, 1.0) + DiffOpt.forward_differentiate!(direct) + @test DiffOpt.get_forward_variable(direct, y2) ≈ -1.0 atol = ATOL return end diff --git a/test/nlp_program.jl b/test/nlp_program.jl index cc208a0a9..05210665e 100644 --- a/test/nlp_program.jl +++ b/test/nlp_program.jl @@ -139,12 +139,7 @@ function test_analytical_simple(; P = 2) # Number of parameters # Set pertubations Δp = [0.1 for _ in 1:P] - MOI.set.( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(p), - Parameter.(Δp), - ) + set_attribute.(p, DiffOpt.ForwardParameterValue(), Δp) # Test fetch sensitivities before computing @test_throws ErrorException MOI.get( @@ -216,12 +211,7 @@ function test_analytical_simple(; P = 2) # Number of parameters # Set pertubations Δp = [0.1 for _ in 1:P] - MOI.set.( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(p), - Parameter.(Δp), - ) + set_attribute.(p, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(m) @@ -256,12 +246,7 @@ function test_analytical_simple(; P = 2) # Number of parameters # Set pertubations Δp = [0.1 for _ in 1:P] - MOI.set.( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(p), - Parameter.(Δp), - ) + set_attribute.(p, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(m) @@ -296,12 +281,7 @@ function test_analytical_simple(; P = 2) # Number of parameters # Set pertubations Δp = [0.1 for _ in 1:P] - MOI.set.( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(p), - Parameter.(Δp), - ) + set_attribute.(p, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(m) @@ -412,21 +392,16 @@ function test_compute_derivatives_Analytical(; DICT_PROBLEMS = DICT_PROBLEMS_Analytical_no_cc, ) @testset "Compute Derivatives Analytical: $problem_name" for ( - problem_name, - (p_a, Δp, Δx, Δy, Δvu, Δvl, model_generator), - ) in DICT_PROBLEMS + problem_name, + (p_a, Δp, Δx, Δy, Δvu, Δvl, model_generator), + ) in DICT_PROBLEMS # OPT Problem model, primal_vars, cons, params = model_generator() set_parameter_value.(params, p_a) optimize!(model) @assert is_solved_and_feasible(model) # Set pertubations - MOI.set.( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(params), - Parameter.(Δp), - ) + set_attribute.(params, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(model) # Test sensitivities primal_vars @@ -606,12 +581,7 @@ function test_compute_derivatives_Finite_Diff(; optimize!(model) @assert is_solved_and_feasible(model) # Set pertubations - MOI.set.( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(params), - Parameter.(Δp), - ) + set_attribute.(params, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(model) Δx = [ @@ -663,7 +633,7 @@ function test_ObjectiveSensitivity_model1() # Set pertubations Δp = 0.1 - DiffOpt.set_forward_parameter(model, p, Δp) + set_attribute(p, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(model) @@ -678,7 +648,7 @@ function test_ObjectiveSensitivity_model1() # Test both obj and solution inputs Δf = 0.5 - MOI.set(model, DiffOpt.ReverseObjectiveSensitivity(), Δf) + MOI.set(model, DiffOpt.ReverseObjectiveValue(), Δf) MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, Δp) msg = "Computing reverse differentiation with both solution sensitivities and objective sensitivities. Set `DiffOpt.AllowObjectiveAndSolutionInput()` to `true` to silence this warning." @@ -686,8 +656,7 @@ function test_ObjectiveSensitivity_model1() MOI.set(model, DiffOpt.AllowObjectiveAndSolutionInput(), true) @test_nowarn DiffOpt.reverse_differentiate!(model) - dp_combined = - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)).value + dp_combined = get_attribute(p, DiffOpt.ReverseParameterValue()) ε = 1e-6 df_dp_fdpos = begin @@ -711,13 +680,13 @@ function test_ObjectiveSensitivity_model1() # Set Reverse Objective Sensitivity Δf = 0.5 - MOI.set(model, DiffOpt.ReverseObjectiveSensitivity(), Δf) + MOI.set(model, DiffOpt.ReverseObjectiveValue(), Δf) # Compute derivatives DiffOpt.reverse_differentiate!(model) # Test Objective Sensitivity wrt parameters - dp = MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)).value + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test isapprox(dp, df * Δf; atol = 1e-4) end @@ -743,7 +712,7 @@ function test_ObjectiveSensitivity_model2() # Set pertubations Δp = 0.1 - DiffOpt.set_forward_parameter(model, p, Δp) + set_attribute(p, DiffOpt.ForwardParameterValue(), Δp) # Compute derivatives DiffOpt.forward_differentiate!(model) @@ -757,13 +726,13 @@ function test_ObjectiveSensitivity_model2() # Set Reverse Objective Sensitivity Δf = 0.5 - MOI.set(model, DiffOpt.ReverseObjectiveSensitivity(), Δf) + MOI.set(model, DiffOpt.ReverseObjectiveValue(), Δf) # Compute derivatives DiffOpt.reverse_differentiate!(model) # Test Objective Sensitivity wrt parameters - dp = MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)).value + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test isapprox(dp, -1.5; atol = 1e-4) end @@ -781,7 +750,7 @@ function test_ObjectiveSensitivity_direct_param_contrib() @assert is_solved_and_feasible(model) Δp = 0.1 - DiffOpt.set_forward_parameter(model, p, Δp) + set_attribute(p, DiffOpt.ForwardParameterValue(), Δp) DiffOpt.forward_differentiate!(model) df_dp = MOI.get(model, DiffOpt.ForwardObjectiveSensitivity()) @@ -814,7 +783,7 @@ function test_ObjectiveSensitivity_subset_parameters() @variable(model, x[1:10]) # Constraints (decouple by index; gives us per-parameter duals) - @constraint(model, c[i=1:10], x[i] * sin(p[i]) == 1) + @constraint(model, c[i = 1:10], x[i] * sin(p[i]) == 1) @objective(model, Min, sum(x)) optimize!(model) @@ -823,8 +792,8 @@ function test_ObjectiveSensitivity_subset_parameters() # Set perturbations only for indices 3 and 7 Δp3 = 0.1 Δp7 = -0.2 - DiffOpt.set_forward_parameter(model, p[3], Δp3) - DiffOpt.set_forward_parameter(model, p[7], Δp7) + set_attribute(p[3], DiffOpt.ForwardParameterValue(), Δp3) + set_attribute(p[7], DiffOpt.ForwardParameterValue(), Δp7) # Compute forward derivatives DiffOpt.forward_differentiate!(model) @@ -883,20 +852,12 @@ function test_differentiating_non_trivial_convex_qp_jump() db = grads_actual[6] for (i, ci) in enumerate(c_le) - @test -dh[i] ≈ - -MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p_le[i]), - ).value atol = 1e-2 rtol = 1e-2 + @test -dh[i] ≈ -get_attribute(p_le[i], DiffOpt.ReverseParameterValue()) atol = + 1e-2 rtol = 1e-2 end for (i, ci) in enumerate(c_eq) - @test -db[i] ≈ - -MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p_eq[i]), - ).value atol = 1e-2 rtol = 1e-2 + @test -db[i] ≈ -get_attribute(p_eq[i], DiffOpt.ReverseParameterValue()) atol = + 1e-2 rtol = 1e-2 end return @@ -929,10 +890,7 @@ function test_ReverseConstraintDual() # Test sensitivities ReverseConstraintSet @test all( isapprox( - [ - MOI.get(m, DiffOpt.ReverseConstraintSet(), ParameterRef(p[i])).value - for i in 1:2 - ], + [get_attribute(p[i], DiffOpt.ReverseParameterValue()) for i in 1:2], zeros(2); atol = 1e-8, ), @@ -1000,12 +958,7 @@ function test_changing_factorization() # Set pertubations Δp = [0.1 for _ in 1:P] - MOI.set.( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef.(p), - Parameter.(Δp), - ) + set_attribute.(p, DiffOpt.ForwardParameterValue(), Δp) # wrong type @test_throws MethodError MOI.set( @@ -1107,7 +1060,7 @@ function test_reverse_bounds_lower() optimize!(model) MOI.set(model, DiffOpt.ReverseConstraintDual(), LowerBoundRef(x[3]), 1.0) DiffOpt.reverse_differentiate!(model) - dp = MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)).value + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test isapprox(dp, -2.88888; atol = 1e-4) end @@ -1122,7 +1075,7 @@ function test_reverse_bounds_upper() optimize!(model) MOI.set(model, DiffOpt.ReverseConstraintDual(), UpperBoundRef(x[3]), 1.0) DiffOpt.reverse_differentiate!(model) - dp = MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)).value + dp = get_attribute(p, DiffOpt.ReverseParameterValue()) @test isapprox(dp, 2.88888; atol = 1e-4) end diff --git a/test/parameters.jl b/test/parameters.jl index 2b3d74345..dc00e1fb4 100644 --- a/test/parameters.jl +++ b/test/parameters.jl @@ -41,21 +41,11 @@ function test_diff_rhs() # the function is # x(p) = 3p, hence x'(p) = 3 # differentiate w.r.t. p - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(1.0), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 3 # again with different "direction" - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(2.0), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), 2.0) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 6 # @@ -63,21 +53,11 @@ function test_diff_rhs() optimize!(model) @test value(x) ≈ 6 # differentiate w.r.t. p - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(1.0), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 3 # again with different "direction" - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(2.0), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), 2.0) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 6 # @@ -85,13 +65,11 @@ function test_diff_rhs() # MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, 1) DiffOpt.reverse_differentiate!(model) - @test MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)) ≈ - MOI.Parameter(3.0) + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ 3.0 # again with different "direction" MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, 2) DiffOpt.reverse_differentiate!(model) - @test MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)) ≈ - MOI.Parameter(6.0) + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ 6.0 return end @@ -116,12 +94,7 @@ function test_diff_vector_rhs() optimize!(model) @test isapprox(value(x), 3 * p_val, atol = 1e-3) for direction in 0.0:3.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction) DiffOpt.forward_differentiate!(model) @test isapprox( MOI.get(model, DiffOpt.ForwardVariablePrimal(), x), @@ -132,8 +105,8 @@ function test_diff_vector_rhs() MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, direction) DiffOpt.reverse_differentiate!(model) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)), - MOI.Parameter(direction * 3), + get_attribute(p, DiffOpt.ReverseParameterValue()), + direction * 3, atol = 1e-3, ) end @@ -157,12 +130,7 @@ function test_affine_changes() # x(p, pc) = 3p / pc, hence dx/dp = 3 / pc, dx/dpc = -3p / pc^2 # differentiate w.r.t. p for direction_p in 1.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ direction_p * 3 / pc_val @@ -174,12 +142,7 @@ function test_affine_changes() @test value(x) ≈ 3 * p_val / pc_val # differentiate w.r.t. p for direction_p in 1.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ direction_p * 3 / pc_val @@ -187,19 +150,9 @@ function test_affine_changes() # differentiate w.r.t. pc # stop differentiating with respect to p direction_p = 0.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) for direction_pc in 1.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pc), - Parameter(direction_pc), - ) + set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ -direction_pc * 3 * p_val / pc_val^2 @@ -210,30 +163,15 @@ function test_affine_changes() optimize!(model) @test value(x) ≈ 3 * p_val / pc_val for direction_pc in 1.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pc), - Parameter(direction_pc), - ) + set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ -direction_pc * 3 * p_val / pc_val^2 end # test combines directions for direction_pc in 1:2, direction_p in 1:2 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pc), - Parameter(direction_pc), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) + set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ -direction_pc * 3 * p_val / pc_val^2 + direction_p * 3 / pc_val @@ -259,18 +197,8 @@ function test_affine_changes_compact() optimize!(model) @test value(x) ≈ 3 * p_val / pc_val for direction_pc in 0.0:2.0, direction_p in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pc), - Parameter(direction_pc), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) + set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ -direction_pc * 3 * p_val / pc_val^2 + @@ -279,16 +207,10 @@ function test_affine_changes_compact() for direction_x in 0:2 MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, direction_x) DiffOpt.reverse_differentiate!(model) - @test MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p), - ) ≈ MOI.Parameter(direction_x * 3 / pc_val) - @test MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(pc), - ) ≈ MOI.Parameter(-direction_x * 3 * p_val / pc_val^2) + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ + direction_x * 3 / pc_val + @test get_attribute(pc, DiffOpt.ReverseParameterValue()) ≈ + -direction_x * 3 * p_val / pc_val^2 end end return @@ -336,36 +258,11 @@ function test_quadratic_rhs_changes() dir_s in 0.0:2.0, dir_t in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(dir_p), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(q), - Parameter(dir_q), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(r), - Parameter(dir_r), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(s), - Parameter(dir_s), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(t), - Parameter(dir_t), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), dir_p) + set_attribute(q, DiffOpt.ForwardParameterValue(), dir_q) + set_attribute(r, DiffOpt.ForwardParameterValue(), dir_r) + set_attribute(s, DiffOpt.ForwardParameterValue(), dir_s) + set_attribute(t, DiffOpt.ForwardParameterValue(), dir_t) DiffOpt.forward_differentiate!(model) @test isapprox( MOI.get(model, DiffOpt.ForwardVariablePrimal(), x), @@ -384,32 +281,30 @@ function test_quadratic_rhs_changes() MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, dir_x) DiffOpt.reverse_differentiate!(model) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(p)), - MOI.Parameter(dir_x * 3 * q_val / (11 * t_val)), + get_attribute(p, DiffOpt.ReverseParameterValue()), + dir_x * 3 * q_val / (11 * t_val), atol = 1e-10, ) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(q)), - MOI.Parameter(dir_x * 3 * p_val / (11 * t_val)), + get_attribute(q, DiffOpt.ReverseParameterValue()), + dir_x * 3 * p_val / (11 * t_val), atol = 1e-10, ) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(r)), - MOI.Parameter(dir_x * 10 * r_val / (11 * t_val)), + get_attribute(r, DiffOpt.ReverseParameterValue()), + dir_x * 10 * r_val / (11 * t_val), atol = 1e-10, ) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(s)), - MOI.Parameter(dir_x * 7 / (11 * t_val)), + get_attribute(s, DiffOpt.ReverseParameterValue()), + dir_x * 7 / (11 * t_val), atol = 1e-10, ) @test isapprox( - MOI.get(model, DiffOpt.ReverseConstraintSet(), ParameterRef(t)), - MOI.Parameter( - dir_x * ( - -(1 + 3 * p_val * q_val + 5 * r_val^2 + 7 * s_val) / - (11 * t_val^2) - ), + get_attribute(t, DiffOpt.ReverseParameterValue()), + dir_x * ( + -(1 + 3 * p_val * q_val + 5 * r_val^2 + 7 * s_val) / + (11 * t_val^2) ), atol = 1e-10, ) @@ -436,18 +331,8 @@ function test_affine_changes_compact_max() optimize!(model) @test value(x) ≈ 3 * p_val / pc_val for direction_pc in 0.0:2.0, direction_p in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pc), - Parameter(direction_pc), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) + set_attribute(pc, DiffOpt.ForwardParameterValue(), direction_pc) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ -direction_pc * 3 * p_val / pc_val^2 + @@ -471,22 +356,13 @@ function test_diff_affine_objective() optimize!(model) @test value(x) ≈ 3 for direction_p in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 0.0 # reverse mode MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, direction_p) DiffOpt.reverse_differentiate!(model) - @test MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p), - ) ≈ MOI.Parameter(0.0) + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ 0.0 end end return @@ -506,22 +382,13 @@ function test_diff_quadratic_objective() optimize!(model) @test value(x) ≈ 3 for direction_p in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ 0.0 # reverse mode MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, direction_p) DiffOpt.reverse_differentiate!(model) - @test MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p), - ) ≈ MOI.Parameter(0.0) + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ 0.0 end end return @@ -542,23 +409,15 @@ function test_quadratic_objective_qp() optimize!(model) @test value(x) ≈ -3p_val / 2 atol = 1e-4 for direction_p in 0.0:2.0 - MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(p), - Parameter(direction_p), - ) + set_attribute(p, DiffOpt.ForwardParameterValue(), direction_p) DiffOpt.forward_differentiate!(model) @test MOI.get(model, DiffOpt.ForwardVariablePrimal(), x) ≈ direction_p * (-3 / 2) atol = 1e-4 # reverse mode MOI.set(model, DiffOpt.ReverseVariablePrimal(), x, direction_p) DiffOpt.reverse_differentiate!(model) - @test MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(p), - ) ≈ MOI.Parameter(direction_p * (-3 / 2)) atol = 1e-4 + @test get_attribute(p, DiffOpt.ReverseParameterValue()) ≈ + direction_p * (-3 / 2) atol = 1e-4 end end return @@ -574,11 +433,10 @@ function test_diff_errors_POI() optimize!(model) @test value(x) ≈ 9 - @test_throws ErrorException MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(x), - Parameter(1.0), + @test_throws ErrorException set_attribute( + x, + DiffOpt.ForwardParameterValue(), + 1.0, ) @test_throws ErrorException MOI.set( model, @@ -591,10 +449,9 @@ function test_diff_errors_POI() DiffOpt.ForwardVariablePrimal(), p, ) - @test_throws ErrorException MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(x), + @test_throws ErrorException get_attribute( + x, + DiffOpt.ReverseParameterValue(), ) @test_throws ErrorException MOI.set( @@ -631,11 +488,10 @@ function test_diff_errors() optimize!(model) @test value(x) ≈ 9 - @test_throws ErrorException MOI.set( - model, - DiffOpt.ForwardConstraintSet(), - ParameterRef(x), - Parameter(1.0), + @test_throws ErrorException set_attribute( + x, + DiffOpt.ForwardParameterValue(), + 1.0, ) # Not easily tested because hard to check if variable is a parameter # @test_throws ErrorException MOI.set( @@ -649,10 +505,9 @@ function test_diff_errors() DiffOpt.ForwardVariablePrimal(), p, ) - @test_throws ErrorException MOI.get( - model, - DiffOpt.ReverseConstraintSet(), - ParameterRef(x), + @test_throws ErrorException get_attribute( + x, + DiffOpt.ReverseParameterValue(), ) @test_throws ErrorException MOI.get( model, @@ -692,12 +547,7 @@ function test_empty_cache() !isnothing(unsafe_backend(m).diff.optimizer.model.input_cache) @test is_empty(unsafe_backend(m).diff.optimizer.model.input_cache) end - MOI.set( - m, - DiffOpt.ForwardConstraintSet(), - ParameterRef(pᵢ), - Parameter(1.0), - ) + set_attribute(pᵢ, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(m) return MOI.get(m, DiffOpt.ForwardVariablePrimal(), xᵢ) end @@ -729,19 +579,19 @@ function test_cubic_obj_pvv_nonbinding() optimize!(model) @test isapprox(value(x), -1 / (2 * p_val), atol = 1e-6) for dir_p in [1.0, 2.0] - DiffOpt.set_forward_parameter(model, p, dir_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), dir_p) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), dir_p / (2 * p_val^2), atol = 1e-5, ) end for dir_x in [1.0, 2.0] - DiffOpt.set_reverse_variable(model, x, dir_x) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), dir_x) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), dir_x / (2 * p_val^2), atol = 1e-5, ) @@ -770,26 +620,26 @@ function test_cubic_obj_pvv_two_vars() @test isapprox(value(x), expected_xy, atol = 1e-5) @test isapprox(value(y), expected_xy, atol = 1e-5) for dir_p in [1.0, 2.0] - DiffOpt.set_forward_parameter(model, p, dir_p) + set_attribute(p, DiffOpt.ForwardParameterValue(), dir_p) DiffOpt.forward_differentiate!(model) dx_dp = dir_p / (2 + p_val)^2 @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), dx_dp, atol = 1e-5, ) @test isapprox( - DiffOpt.get_forward_variable(model, y), + get_attribute(y, DiffOpt.ForwardVariablePrimal()), dx_dp, atol = 1e-5, ) end for dir_x in [1.0, 2.0] - DiffOpt.set_reverse_variable(model, x, dir_x) - DiffOpt.set_reverse_variable(model, y, 0.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), dir_x) + set_attribute(y, DiffOpt.ReverseVariablePrimal(), 0.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), dir_x / (2 + p_val)^2, atol = 1e-5, ) @@ -811,13 +661,17 @@ function test_cubic_obj_pvv_binding() set_parameter_value(p, p_val) optimize!(model) @test isapprox(value(x), 1.0, atol = 1e-6) - DiffOpt.set_forward_parameter(model, p, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) - DiffOpt.set_reverse_variable(model, x, 1.0) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @@ -842,33 +696,33 @@ function test_cubic_obj_ppv() optimize!(model) @test isapprox(value(x), -p_val * q_val / 2, atol = 1e-5) # Forward dx/dp - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -q_val / 2, atol = 1e-5, ) # Forward dx/dq - DiffOpt.set_forward_parameter(model, p, 0.0) - DiffOpt.set_forward_parameter(model, q, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -p_val / 2, atol = 1e-5, ) # Reverse - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), -q_val / 2, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), -p_val / 2, atol = 1e-5, ) @@ -895,44 +749,48 @@ function test_cubic_obj_mixed() optimize!(model) @test isapprox(value(x), -q_val / (2 * p_val), atol = 1e-5) # dx/dp - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), q_val / (2 * p_val^2), atol = 1e-5, ) # dx/dq - DiffOpt.set_forward_parameter(model, p, 0.0) - DiffOpt.set_forward_parameter(model, q, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -1 / (2 * p_val), atol = 1e-5, ) # dx/dr = 0 - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Reverse - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), q_val / (2 * p_val^2), atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), -1 / (2 * p_val), atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, r), + get_attribute(r, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @@ -961,26 +819,30 @@ function test_cubic_obj_multi_pvv() @test isapprox(value(x), -1 / (2 * p_val), atol = 1e-5) @test isapprox(value(y), -1 / (2 * q_val), atol = 1e-5) # dx/dp - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), 1 / (2 * p_val^2), atol = 1e-5, ) - @test isapprox(DiffOpt.get_forward_variable(model, y), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(y, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Reverse: ∇x=1, ∇y=0 - DiffOpt.set_reverse_variable(model, x, 1.0) - DiffOpt.set_reverse_variable(model, y, 0.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) + set_attribute(y, DiffOpt.ReverseVariablePrimal(), 0.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), 1 / (2 * p_val^2), atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @@ -1008,58 +870,58 @@ function test_cubic_obj_ppv_and_pv() optimize!(model) @test isapprox(value(x), -(p_val * q_val + r_val) / 2, atol = 1e-5) # Forward dx/dp - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -q_val / 2, atol = 1e-5, ) # Forward dx/dq - DiffOpt.set_forward_parameter(model, p, 0.0) - DiffOpt.set_forward_parameter(model, q, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -p_val / 2, atol = 1e-5, ) # Forward dx/dr - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -1 / 2, atol = 1e-5, ) # Forward combined direction: Δp=1, Δq=1, Δr=1 - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 1.0) - DiffOpt.set_forward_parameter(model, r, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -(q_val + p_val + 1) / 2, atol = 1e-5, ) # Reverse - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), -q_val / 2, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), -p_val / 2, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, r), + get_attribute(r, DiffOpt.ReverseParameterValue()), -1 / 2, atol = 1e-5, ) @@ -1087,40 +949,48 @@ function test_cubic_obj_pvv_pp() optimize!(model) @test isapprox(value(x), -1 / (2 * p_val), atol = 1e-5) # Forward Δp=1, others=0: dx*/dp = 1/(2p^2) (from pvv) - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), 1 / (2 * p_val^2), atol = 1e-5, ) # Forward Δq=1: dx*/dq = 0 (pp is constant, no variable coupling) - DiffOpt.set_forward_parameter(model, p, 0.0) - DiffOpt.set_forward_parameter(model, q, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Forward Δr=1: dx*/dr = 0 - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Reverse - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), 1 / (2 * p_val^2), atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, r), + get_attribute(r, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @@ -1149,40 +1019,48 @@ function test_cubic_obj_ppp() optimize!(model) @test isapprox(value(x), -p_val / 2, atol = 1e-5) # Forward Δp=1, others 0: dx/dp = -1/2 - DiffOpt.set_forward_parameter(model, p, 1.0) - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 0.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 0.0) DiffOpt.forward_differentiate!(model) @test isapprox( - DiffOpt.get_forward_variable(model, x), + get_attribute(x, DiffOpt.ForwardVariablePrimal()), -1 / 2, atol = 1e-5, ) # Forward Δq=1: dx/dq = 0 (ppp constant, no variable coupling) - DiffOpt.set_forward_parameter(model, p, 0.0) - DiffOpt.set_forward_parameter(model, q, 1.0) + set_attribute(p, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Forward Δr=1: dx/dr = 0 - DiffOpt.set_forward_parameter(model, q, 0.0) - DiffOpt.set_forward_parameter(model, r, 1.0) + set_attribute(q, DiffOpt.ForwardParameterValue(), 0.0) + set_attribute(r, DiffOpt.ForwardParameterValue(), 1.0) DiffOpt.forward_differentiate!(model) - @test isapprox(DiffOpt.get_forward_variable(model, x), 0.0, atol = 1e-5) + @test isapprox( + get_attribute(x, DiffOpt.ForwardVariablePrimal()), + 0.0, + atol = 1e-5, + ) # Reverse - DiffOpt.set_reverse_variable(model, x, 1.0) + set_attribute(x, DiffOpt.ReverseVariablePrimal(), 1.0) DiffOpt.reverse_differentiate!(model) @test isapprox( - DiffOpt.get_reverse_parameter(model, p), + get_attribute(p, DiffOpt.ReverseParameterValue()), -1 / 2, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, q), + get_attribute(q, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) @test isapprox( - DiffOpt.get_reverse_parameter(model, r), + get_attribute(r, DiffOpt.ReverseParameterValue()), 0.0, atol = 1e-5, ) diff --git a/test/solver_native_diff.jl b/test/solver_native_diff.jl index 87239860e..76055cc88 100644 --- a/test/solver_native_diff.jl +++ b/test/solver_native_diff.jl @@ -287,7 +287,7 @@ function MOI.get(s::EqQPSolver, ::MOI.ConstraintFunction, ci::EQ_CI) row = ci.value terms = [ MOI.ScalarAffineTerm(s.A[row, j], MOI.VariableIndex(j)) for - j in 1:s.n_vars if !iszero(s.A[row, j]) + j in 1:(s.n_vars) if !iszero(s.A[row, j]) ] return MOI.ScalarAffineFunction(terms, 0.0) end @@ -306,7 +306,7 @@ function MOI.get( ) terms = [ MOI.ScalarAffineTerm(s.c[j], MOI.VariableIndex(j)) for - j in 1:s.n_vars if !iszero(s.c[j]) + j in 1:(s.n_vars) if !iszero(s.c[j]) ] return MOI.ScalarAffineFunction(terms, 0.0) end @@ -438,7 +438,8 @@ end # Reverse output: results function MOI.get(s::EqQPSolver, ::DiffOpt.ReverseObjectiveFunction) terms = [ - MOI.ScalarAffineTerm(s.dc[j], MOI.VariableIndex(j)) for j in 1:s.n_vars + MOI.ScalarAffineTerm(s.dc[j], MOI.VariableIndex(j)) for + j in 1:(s.n_vars) ] return MOI.ScalarAffineFunction(terms, 0.0) end @@ -447,7 +448,7 @@ function MOI.get(s::EqQPSolver, ::DiffOpt.ReverseConstraintFunction, ci::EQ_CI) row = ci.value terms = [ MOI.ScalarAffineTerm(s.dA[row, j], MOI.VariableIndex(j)) for - j in 1:s.n_vars + j in 1:(s.n_vars) ] return MOI.ScalarAffineFunction(terms, -s.db[row]) end