From fc4cdbb3f84b198f48b868db033bfaf19233a248 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sat, 7 Jun 2025 13:27:44 -0400 Subject: [PATCH 1/5] fix param name --- src/dual_model_variables.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dual_model_variables.jl b/src/dual_model_variables.jl index 53358b6..980fb65 100644 --- a/src/dual_model_variables.jl +++ b/src/dual_model_variables.jl @@ -142,7 +142,7 @@ function _add_primal_parameter_vars( prefix = dual_names.parameter_name_prefix == "" ? "param_" : dual_names.parameter_name_prefix - MOI.set(dual_model, MOI.VariableName(), vi, prefix * vi_name) + MOI.set(dual_model, MOI.VariableName(), vis[i], prefix * vi_name) end end return From ccc8003858297324d6d0f1a4e024500f61f666d2 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sat, 7 Jun 2025 20:18:58 -0400 Subject: [PATCH 2/5] 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 7999a961215727b1f6d09638e248e88a12bed492 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sun, 8 Jun 2025 15:30:14 -0400 Subject: [PATCH 3/5] add test --- test/Tests/test_partial_dual_linear.jl | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/Tests/test_partial_dual_linear.jl b/test/Tests/test_partial_dual_linear.jl index 9a3a5db..2601fbe 100644 --- a/test/Tests/test_partial_dual_linear.jl +++ b/test/Tests/test_partial_dual_linear.jl @@ -99,6 +99,41 @@ ) end + @testset "lp1_test - parameter name" begin + #= + primal + min -4x_2 - 1 + s.t. + x_1 >= 3 :y_2 + x_1 + 2x_2 <= 3 :y_3 + ignore x_2 during dualization + dual + + s.t. + y_2 >= 0 + y_3 <= 0 + y_2 + y_3 == 0 :x_1 + =# + primal_model = lp1_test() + MOI.add_constraint( + primal_model, + MOI.VariableIndex(2), + MOI.Parameter{Float64}(0.0), + ) + dual = Dualization.dualize( + primal_model, + dual_names=Dualization.DualNames("", "", "parameter_", "") + ) + dual_model = dual.dual_model + primal_dual_map = dual.primal_dual_map + primal_parameter_to_dual_parameter = primal_dual_map.primal_parameter_to_dual_parameter + @test MOI.get( + dual_model, + MOI.VariableName(), + primal_parameter_to_dual_parameter[MOI.VariableIndex(2)], + ) == "parameter_" * MOI.get(primal_model, MOI.VariableName(), MOI.VariableIndex(2)) + end + @testset "lp7_test - x_1 ignored" begin #= primal From f0ee9161cbffeaa2a67adbc9afdf324afad7fc59 Mon Sep 17 00:00:00 2001 From: "Klamkin, Michael" Date: Sun, 8 Jun 2025 15:41:50 -0400 Subject: [PATCH 4/5] 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 From 4b6781cfd31d383e2a4ece024468e718c8407a0d Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 11 Jun 2025 16:19:10 +1200 Subject: [PATCH 5/5] Fix formatting --- test/Tests/test_JuMP_dualize.jl | 5 +++-- test/Tests/test_partial_dual_linear.jl | 11 +++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/Tests/test_JuMP_dualize.jl b/test/Tests/test_JuMP_dualize.jl index 4058ef0..5118256 100644 --- a/test/Tests/test_JuMP_dualize.jl +++ b/test/Tests/test_JuMP_dualize.jl @@ -134,7 +134,7 @@ end @variable(model, p ∈ Parameter(2.0)) @constraint(model, c, x <= p) @objective(model, Max, 3x + x^2) - dual_model = dualize(model, dual_names=DualNames()) + 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 @@ -142,6 +142,7 @@ end 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" + @test MOI.get(dual_model, MOI.VariableName(), quadslack) == + "quadslack_x" end end diff --git a/test/Tests/test_partial_dual_linear.jl b/test/Tests/test_partial_dual_linear.jl index 2601fbe..3cd4c71 100644 --- a/test/Tests/test_partial_dual_linear.jl +++ b/test/Tests/test_partial_dual_linear.jl @@ -108,7 +108,7 @@ x_1 + 2x_2 <= 3 :y_3 ignore x_2 during dualization dual - + s.t. y_2 >= 0 y_3 <= 0 @@ -122,16 +122,19 @@ ) dual = Dualization.dualize( primal_model, - dual_names=Dualization.DualNames("", "", "parameter_", "") + dual_names = Dualization.DualNames("", "", "parameter_", ""), ) dual_model = dual.dual_model primal_dual_map = dual.primal_dual_map - primal_parameter_to_dual_parameter = primal_dual_map.primal_parameter_to_dual_parameter + primal_parameter_to_dual_parameter = + primal_dual_map.primal_parameter_to_dual_parameter @test MOI.get( dual_model, MOI.VariableName(), primal_parameter_to_dual_parameter[MOI.VariableIndex(2)], - ) == "parameter_" * MOI.get(primal_model, MOI.VariableName(), MOI.VariableIndex(2)) + ) == + "parameter_" * + MOI.get(primal_model, MOI.VariableName(), MOI.VariableIndex(2)) end @testset "lp7_test - x_1 ignored" begin