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/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 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( diff --git a/test/Tests/test_JuMP_dualize.jl b/test/Tests/test_JuMP_dualize.jl index 47c1c9a..5118256 100644 --- a/test/Tests/test_JuMP_dualize.jl +++ b/test/Tests/test_JuMP_dualize.jl @@ -128,4 +128,21 @@ 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 diff --git a/test/Tests/test_partial_dual_linear.jl b/test/Tests/test_partial_dual_linear.jl index 9a3a5db..3cd4c71 100644 --- a/test/Tests/test_partial_dual_linear.jl +++ b/test/Tests/test_partial_dual_linear.jl @@ -99,6 +99,44 @@ ) 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