From ccc8003858297324d6d0f1a4e024500f61f666d2 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sat, 7 Jun 2025 20:18:58 -0400 Subject: [PATCH 1/2] add getter for dual slack variable from quadratic objective --- ext/DualizationJuMPExt/DualizationJuMPExt.jl | 10 ++++++++++ src/structures.jl | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/ext/DualizationJuMPExt/DualizationJuMPExt.jl b/ext/DualizationJuMPExt/DualizationJuMPExt.jl index b59ec67..a42ce06 100644 --- a/ext/DualizationJuMPExt/DualizationJuMPExt.jl +++ b/ext/DualizationJuMPExt/DualizationJuMPExt.jl @@ -146,4 +146,14 @@ function Dualization._get_dual_parameter( return JuMP.VariableRef(dual_model, moi_dual_vi) end +function Dualization._get_dual_slack_variable( + dual_model::JuMP.Model, + primal_ref::JuMP.VariableRef, +) + map = _get_primal_dual_map(dual_model) + moi_primal_vi = JuMP.index(primal_ref) + moi_dual_vi = Dualization._get_dual_slack_variable(map, moi_primal_vi) + return JuMP.VariableRef(dual_model, moi_dual_vi) +end + end # module DualizationJuMPExt diff --git a/src/structures.jl b/src/structures.jl index 6fc5914..3063a81 100644 --- a/src/structures.jl +++ b/src/structures.jl @@ -184,6 +184,10 @@ function _get_dual_parameter(m::PrimalDualMap, vi::MOI.VariableIndex) return m.primal_parameter_to_dual_parameter[vi] end +function _get_dual_slack_variable(m::PrimalDualMap, vi::MOI.VariableIndex) + return m.primal_var_in_quad_obj_to_dual_slack_var[vi] +end + function Base.getproperty(m::PrimalDualMap{T}, name::Symbol) where {T} if name === :constrained_var_idx error( From f0ee9161cbffeaa2a67adbc9afdf324afad7fc59 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sun, 8 Jun 2025 15:41:50 -0400 Subject: [PATCH 2/2] add test --- test/Tests/test_JuMP_dualize.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/Tests/test_JuMP_dualize.jl b/test/Tests/test_JuMP_dualize.jl index 47c1c9a..4058ef0 100644 --- a/test/Tests/test_JuMP_dualize.jl +++ b/test/Tests/test_JuMP_dualize.jl @@ -128,4 +128,20 @@ end con = Dualization._get_dual_constraint(dual_model, cv) @test con isa ConstraintRef end + @testset "JuMP parametric quadratic" begin + model = Model() + @variable(model, x) + @variable(model, p ∈ Parameter(2.0)) + @constraint(model, c, x <= p) + @objective(model, Max, 3x + x^2) + dual_model = dualize(model, dual_names=DualNames()) + param = Dualization._get_dual_parameter(dual_model, p) + @test param isa VariableRef + @test owner_model(param) === dual_model + @test MOI.get(dual_model, MOI.VariableName(), param) == "param_p" + quadslack = Dualization._get_dual_slack_variable(dual_model, x) + @test quadslack isa VariableRef + @test owner_model(quadslack) === dual_model + @test MOI.get(dual_model, MOI.VariableName(), quadslack) == "quadslack_x" + end end