From 353eacf4eaa1dba2185651de1bfda4171abf63a3 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Fri, 29 Nov 2024 12:46:19 +1300 Subject: [PATCH 1/2] [Bridges] fix querying result attributes with result_index != 1 --- src/Bridges/Constraint/bridges/det.jl | 2 +- src/Bridges/Constraint/bridges/norm_spec_nuc_to_psd.jl | 10 +++++----- src/Bridges/Objective/bridges/slack.jl | 7 +++++-- src/Bridges/Objective/bridges/vector_slack.jl | 6 +++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Bridges/Constraint/bridges/det.jl b/src/Bridges/Constraint/bridges/det.jl index 0614cdbcc5..d74036028d 100644 --- a/src/Bridges/Constraint/bridges/det.jl +++ b/src/Bridges/Constraint/bridges/det.jl @@ -232,7 +232,7 @@ function MOI.get( bridge::LogDetBridge, ) d = length(bridge.lcindex) - Δ = MOI.get(model, MOI.VariablePrimal(), bridge.Δ) + Δ = MOI.get(model, MOI.VariablePrimal(attr.result_index), bridge.Δ) t = MOI.get(model, attr, bridge.tlindex) + sum(MOI.get(model, attr, ci)[1] for ci in bridge.lcindex) diff --git a/src/Bridges/Constraint/bridges/norm_spec_nuc_to_psd.jl b/src/Bridges/Constraint/bridges/norm_spec_nuc_to_psd.jl index 42c4027b5e..838b0a67d0 100644 --- a/src/Bridges/Constraint/bridges/norm_spec_nuc_to_psd.jl +++ b/src/Bridges/Constraint/bridges/norm_spec_nuc_to_psd.jl @@ -200,10 +200,10 @@ end # constraint is (tr(U) + tr(V), 2X) in NormNuclearCone. function MOI.get( model::MOI.ModelLike, - ::MOI.ConstraintDual, + attr::MOI.ConstraintDual, bridge::NormSpectralBridge, ) - dual = MOI.get(model, MOI.ConstraintDual(), bridge.psd_index) + dual = MOI.get(model, attr, bridge.psd_index) column_dim = bridge.column_dim side_dim = bridge.row_dim + column_dim t = sum(dual[MOI.Utilities.trimap(i, i)] for i in 1:side_dim) @@ -450,11 +450,11 @@ end function MOI.get( model::MOI.ModelLike, - ::MOI.ConstraintPrimal, + attr::MOI.ConstraintPrimal, bridge::NormNuclearBridge, ) - ge_primal = MOI.get(model, MOI.ConstraintPrimal(), bridge.ge_index) - psd_primal = MOI.get(model, MOI.ConstraintPrimal(), bridge.psd_index) + ge_primal = MOI.get(model, attr, bridge.ge_index) + psd_primal = MOI.get(model, attr, bridge.psd_index) side_dim = bridge.row_dim + bridge.column_dim t = ge_primal + diff --git a/src/Bridges/Objective/bridges/slack.jl b/src/Bridges/Objective/bridges/slack.jl index 1b9a1c56be..9413f65c02 100644 --- a/src/Bridges/Objective/bridges/slack.jl +++ b/src/Bridges/Objective/bridges/slack.jl @@ -155,8 +155,11 @@ function MOI.get( # value of `bridge.slack`. Since `bridge.constraint` is `g - slack`, we can # get the value of the original objective by summing the value of `slack` # with the `ConstraintPrimal` of the constraint. - obj_slack_constant = - MOI.get(model, MOI.ConstraintPrimal(), bridge.constraint) + obj_slack_constant = MOI.get( + model, + MOI.ConstraintPrimal(attr.result_index), + bridge.constraint, + ) return obj_slack_constant + slack + bridge.constant end diff --git a/src/Bridges/Objective/bridges/vector_slack.jl b/src/Bridges/Objective/bridges/vector_slack.jl index 82efe8d7b1..9a8d979e39 100644 --- a/src/Bridges/Objective/bridges/vector_slack.jl +++ b/src/Bridges/Objective/bridges/vector_slack.jl @@ -159,7 +159,11 @@ function MOI.get( N = attr_g.result_index attr_f = MOI.Bridges.ObjectiveFunctionValue{MOI.VectorOfVariables}(N) objective_value = MOI.get(model, attr_f) - con_primal = MOI.get(model, MOI.ConstraintPrimal(), bridge.constraint) + con_primal = MOI.get( + model, + MOI.ConstraintPrimal(attr_g.result_index), + bridge.constraint, + ) sense = MOI.get(model, MOI.ObjectiveSense()) if sense == MOI.MIN_SENSE # con_primal = objective_value - f(x) From 782f84b113cb197c62f2b1cdb96186de292e45e5 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Fri, 29 Nov 2024 14:14:45 +1300 Subject: [PATCH 2/2] Update --- src/Bridges/Constraint/bridges/det.jl | 2 -- test/Bridges/Objective/slack.jl | 28 ++++++++++++++++++++++++++ test/Bridges/Objective/vector_slack.jl | 28 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/Bridges/Constraint/bridges/det.jl b/src/Bridges/Constraint/bridges/det.jl index d74036028d..c35a643395 100644 --- a/src/Bridges/Constraint/bridges/det.jl +++ b/src/Bridges/Constraint/bridges/det.jl @@ -231,8 +231,6 @@ function MOI.get( attr::Union{MOI.ConstraintPrimal,MOI.ConstraintPrimalStart}, bridge::LogDetBridge, ) - d = length(bridge.lcindex) - Δ = MOI.get(model, MOI.VariablePrimal(attr.result_index), bridge.Δ) t = MOI.get(model, attr, bridge.tlindex) + sum(MOI.get(model, attr, ci)[1] for ci in bridge.lcindex) diff --git a/test/Bridges/Objective/slack.jl b/test/Bridges/Objective/slack.jl index b52891c56f..68fb70e2e7 100644 --- a/test/Bridges/Objective/slack.jl +++ b/test/Bridges/Objective/slack.jl @@ -208,6 +208,34 @@ function test_SlackBridge_ObjectiveFunctionValue() return end +function test_SlackBridge_ObjectiveFunctionValue_2() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + MOI.add_constraint(model, x, MOI.GreaterThan(1.0)) + f = 1.1 * x - 1.2 + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.Utilities.set_mock_optimize!( + inner, + mock -> begin + MOI.set(mock, MOI.ResultCount(), 2) + MOI.set(mock, MOI.TerminationStatus(), MOI.OPTIMAL) + MOI.set(mock, MOI.PrimalStatus(1), MOI.FEASIBLE_POINT) + MOI.set(mock, MOI.PrimalStatus(2), MOI.FEASIBLE_POINT) + y = MOI.get(mock, MOI.ListOfVariableIndices()) + MOI.set.(mock, MOI.VariablePrimal(1), y, [1.0, -0.1]) + MOI.set.(mock, MOI.VariablePrimal(2), y, [2.0, 1.0]) + end, + ) + MOI.optimize!(model) + @test MOI.get(model, MOI.ObjectiveValue(1)) ≈ -0.1 + @test MOI.get(model, MOI.VariablePrimal(1), x) ≈ 1.0 + @test MOI.get(model, MOI.ObjectiveValue(2)) ≈ 1.0 + @test MOI.get(model, MOI.VariablePrimal(2), x) ≈ 2.0 + return +end + function test_original() mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) bridged_mock = MOI.Bridges.Objective.Slack{Float64}(mock) diff --git a/test/Bridges/Objective/vector_slack.jl b/test/Bridges/Objective/vector_slack.jl index 14320162d0..142007c4fa 100644 --- a/test/Bridges/Objective/vector_slack.jl +++ b/test/Bridges/Objective/vector_slack.jl @@ -166,6 +166,34 @@ function test_modify_vector_constant_change() return end +function test_SlackBridge_ObjectiveFunctionValue_2() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.VectorSlack{Float64}(inner) + x = MOI.add_variable(model) + MOI.add_constraint(model, x, MOI.GreaterThan(1.0)) + f = MOI.Utilities.operate(vcat, Float64, 1.1 * x - 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.Utilities.set_mock_optimize!( + inner, + mock -> begin + MOI.set(mock, MOI.ResultCount(), 2) + MOI.set(mock, MOI.TerminationStatus(), MOI.OPTIMAL) + MOI.set(mock, MOI.PrimalStatus(1), MOI.FEASIBLE_POINT) + MOI.set(mock, MOI.PrimalStatus(2), MOI.FEASIBLE_POINT) + y = MOI.get(mock, MOI.ListOfVariableIndices()) + MOI.set.(mock, MOI.VariablePrimal(1), y, [1.0, -0.1]) + MOI.set.(mock, MOI.VariablePrimal(2), y, [2.0, 1.0]) + end, + ) + MOI.optimize!(model) + @test MOI.get(model, MOI.ObjectiveValue(1)) ≈ [-0.1] + @test MOI.get(model, MOI.VariablePrimal(1), x) ≈ 1.0 + @test MOI.get(model, MOI.ObjectiveValue(2)) ≈ [1.0] + @test MOI.get(model, MOI.VariablePrimal(2), x) ≈ 2.0 + return +end + end # module TestObjectiveVectorSlack.runtests()