From 69779418aad7fd9089007495dc3d86fa47c72d4d Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 14 May 2021 12:15:41 +1200 Subject: [PATCH 1/2] Ensure bridges return vectors that can be modified by the user, and remove redundant copy in bridge_optimizer --- src/Bridges/Constraint/det.jl | 4 ++-- src/Bridges/Constraint/geomean.jl | 4 ++-- src/Bridges/Constraint/norm_to_lp.jl | 2 +- src/Bridges/Constraint/relentr_to_exp.jl | 8 ++++++-- src/Bridges/Constraint/scalarize.jl | 2 +- src/Bridges/Constraint/slack.jl | 2 +- src/Bridges/Constraint/soc_to_nonconvex_quad.jl | 2 +- src/Bridges/Variable/flip_sign.jl | 2 +- src/Bridges/Variable/rsoc_to_psd.jl | 6 +++--- src/Bridges/Variable/rsoc_to_soc.jl | 2 +- src/Bridges/Variable/soc_to_rsoc.jl | 2 +- src/Bridges/bridge_optimizer.jl | 3 +-- 12 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Bridges/Constraint/det.jl b/src/Bridges/Constraint/det.jl index 3b98160f22..f6e1ec4fad 100644 --- a/src/Bridges/Constraint/det.jl +++ b/src/Bridges/Constraint/det.jl @@ -255,7 +255,7 @@ function MOI.get( MOI.ExponentialCone, }, ) where {T} - return b.lcindex + return copy(b.lcindex) end function MOI.get( @@ -409,7 +409,7 @@ end # Attributes, Bridge acting as a model MOI.get(b::RootDetBridge, ::MOI.NumberOfVariables) = length(b.Δ) -MOI.get(b::RootDetBridge, ::MOI.ListOfVariableIndices) = b.Δ +MOI.get(b::RootDetBridge, ::MOI.ListOfVariableIndices) = copy(b.Δ) function MOI.get( ::RootDetBridge{T}, diff --git a/src/Bridges/Constraint/geomean.jl b/src/Bridges/Constraint/geomean.jl index 47f35d4d97..cdb06bda08 100644 --- a/src/Bridges/Constraint/geomean.jl +++ b/src/Bridges/Constraint/geomean.jl @@ -170,7 +170,7 @@ end # Attributes, Bridge acting as a model MOI.get(b::GeoMeanBridge, ::MOI.NumberOfVariables) = length(b.xij) -MOI.get(b::GeoMeanBridge, ::MOI.ListOfVariableIndices) = b.xij +MOI.get(b::GeoMeanBridge, ::MOI.ListOfVariableIndices) = copy(b.xij) function MOI.get( ::GeoMeanBridge{T,F}, @@ -204,7 +204,7 @@ function MOI.get( b::GeoMeanBridge{T,F,G}, ::MOI.ListOfConstraintIndices{G,MOI.RotatedSecondOrderCone}, ) where {T,F,G} - return b.socrc + return copy(b.socrc) end function MOI.get( diff --git a/src/Bridges/Constraint/norm_to_lp.jl b/src/Bridges/Constraint/norm_to_lp.jl index 41e8559ebc..120045cb5a 100644 --- a/src/Bridges/Constraint/norm_to_lp.jl +++ b/src/Bridges/Constraint/norm_to_lp.jl @@ -144,7 +144,7 @@ end # Attributes, Bridge acting as a model MOI.get(b::NormOneBridge, ::MOI.NumberOfVariables) = length(b.y) -MOI.get(b::NormOneBridge, ::MOI.ListOfVariableIndices) = b.y +MOI.get(b::NormOneBridge, ::MOI.ListOfVariableIndices) = copy(b.y) function MOI.get( b::NormOneBridge{T,F}, ::MOI.NumberOfConstraints{F,MOI.Nonnegatives}, diff --git a/src/Bridges/Constraint/relentr_to_exp.jl b/src/Bridges/Constraint/relentr_to_exp.jl index 14f367c7d5..0db07a87f3 100644 --- a/src/Bridges/Constraint/relentr_to_exp.jl +++ b/src/Bridges/Constraint/relentr_to_exp.jl @@ -84,7 +84,11 @@ end function MOI.get(bridge::RelativeEntropyBridge, ::MOI.NumberOfVariables) return length(bridge.y) end -MOI.get(bridge::RelativeEntropyBridge, ::MOI.ListOfVariableIndices) = bridge.y + +function MOI.get(bridge::RelativeEntropyBridge, ::MOI.ListOfVariableIndices) + return copy(bridge.y) +end + function MOI.get( bridge::RelativeEntropyBridge{T,F}, ::MOI.NumberOfConstraints{F,MOI.GreaterThan{T}}, @@ -110,7 +114,7 @@ function MOI.get( bridge::RelativeEntropyBridge{T,F,G}, ::MOI.ListOfConstraintIndices{G,MOI.ExponentialCone}, ) where {T,F,G} - return bridge.exp_indices + return copy(bridge.exp_indices) end # References diff --git a/src/Bridges/Constraint/scalarize.jl b/src/Bridges/Constraint/scalarize.jl index bfc73b3b62..eb376b5187 100644 --- a/src/Bridges/Constraint/scalarize.jl +++ b/src/Bridges/Constraint/scalarize.jl @@ -66,7 +66,7 @@ function MOI.get( bridge::ScalarizeBridge{T,F,S}, ::MOI.ListOfConstraintIndices{F,S}, ) where {T,F,S} - return bridge.scalar_constraints + return copy(bridge.scalar_constraints) end # References diff --git a/src/Bridges/Constraint/slack.jl b/src/Bridges/Constraint/slack.jl index 919935fe29..8bf57e35a0 100644 --- a/src/Bridges/Constraint/slack.jl +++ b/src/Bridges/Constraint/slack.jl @@ -313,7 +313,7 @@ end # Attributes, Bridge acting as a model MOI.get(b::VectorSlackBridge, ::MOI.NumberOfVariables) = length(b.slack) -MOI.get(b::VectorSlackBridge, ::MOI.ListOfVariableIndices) = b.slack +MOI.get(b::VectorSlackBridge, ::MOI.ListOfVariableIndices) = copy(b.slack) # Attributes, Bridge acting as a constraint function MOI.set( diff --git a/src/Bridges/Constraint/soc_to_nonconvex_quad.jl b/src/Bridges/Constraint/soc_to_nonconvex_quad.jl index ac20291343..c336bbc750 100644 --- a/src/Bridges/Constraint/soc_to_nonconvex_quad.jl +++ b/src/Bridges/Constraint/soc_to_nonconvex_quad.jl @@ -200,7 +200,7 @@ function MOI.get( MOI.GreaterThan{T}, }, ) where {T} - return bridge.var_pos + return copy(bridge.var_pos) end # References diff --git a/src/Bridges/Variable/flip_sign.jl b/src/Bridges/Variable/flip_sign.jl index e2cf917f06..d679458ab3 100644 --- a/src/Bridges/Variable/flip_sign.jl +++ b/src/Bridges/Variable/flip_sign.jl @@ -32,7 +32,7 @@ function MOI.get(bridge::FlipSignBridge, ::MOI.NumberOfVariables) end function MOI.get(bridge::FlipSignBridge, ::MOI.ListOfVariableIndices) - return bridge.flipped_variables + return copy(bridge.flipped_variables) end function MOI.get( diff --git a/src/Bridges/Variable/rsoc_to_psd.jl b/src/Bridges/Variable/rsoc_to_psd.jl index d8d062c308..168b2fa1cb 100644 --- a/src/Bridges/Variable/rsoc_to_psd.jl +++ b/src/Bridges/Variable/rsoc_to_psd.jl @@ -91,7 +91,7 @@ function MOI.get(bridge::RSOCtoPSDBridge, ::MOI.NumberOfVariables) end function MOI.get(bridge::RSOCtoPSDBridge, ::MOI.ListOfVariableIndices) - return bridge.variables + return copy(bridge.variables) end function MOI.get( @@ -123,7 +123,7 @@ function MOI.get( bridge::RSOCtoPSDBridge{T}, ::MOI.ListOfConstraintIndices{MOI.SingleVariable,MOI.EqualTo{T}}, ) where {T} - return bridge.off_diag + return copy(bridge.off_diag) end function MOI.get( @@ -137,7 +137,7 @@ function MOI.get( bridge::RSOCtoPSDBridge{T}, ::MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{T},MOI.EqualTo{T}}, ) where {T} - return bridge.diag + return copy(bridge.diag) end # References diff --git a/src/Bridges/Variable/rsoc_to_soc.jl b/src/Bridges/Variable/rsoc_to_soc.jl index 2f6da50d51..4c0bd02ba5 100644 --- a/src/Bridges/Variable/rsoc_to_soc.jl +++ b/src/Bridges/Variable/rsoc_to_soc.jl @@ -109,7 +109,7 @@ function MOI.get(bridge::RSOCtoSOCBridge, ::MOI.NumberOfVariables) end function MOI.get(bridge::RSOCtoSOCBridge, ::MOI.ListOfVariableIndices) - return bridge.variables + return copy(bridge.variables) end function MOI.get( diff --git a/src/Bridges/Variable/soc_to_rsoc.jl b/src/Bridges/Variable/soc_to_rsoc.jl index 230b052038..46c3618121 100644 --- a/src/Bridges/Variable/soc_to_rsoc.jl +++ b/src/Bridges/Variable/soc_to_rsoc.jl @@ -44,7 +44,7 @@ function MOI.get(bridge::SOCtoRSOCBridge, ::MOI.NumberOfVariables) end function MOI.get(bridge::SOCtoRSOCBridge, ::MOI.ListOfVariableIndices) - return bridge.variables + return copy(bridge.variables) end function MOI.get( diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index d7cbfcb26f..5cf4025a5b 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -632,8 +632,7 @@ function get_all_including_bridged( ) list = MOI.get(b.model, attr) if !isempty(Variable.bridges(b)) - # TODO(odow): Fix this! - list = append!(copy(list), keys(Variable.bridges(b))) + return vcat(list, keys(Variable.bridges(b))) end return list end From 1b3f6df6a2d7f8c2335d17bf5b6273ac69868de0 Mon Sep 17 00:00:00 2001 From: odow Date: Fri, 14 May 2021 13:08:38 +1200 Subject: [PATCH 2/2] Fix --- src/Bridges/Variable/free.jl | 2 +- src/Bridges/bridge_optimizer.jl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bridges/Variable/free.jl b/src/Bridges/Variable/free.jl index 5c22dbb7ab..0bbb8b70da 100644 --- a/src/Bridges/Variable/free.jl +++ b/src/Bridges/Variable/free.jl @@ -39,7 +39,7 @@ function MOI.get(bridge::FreeBridge, ::MOI.NumberOfVariables) end function MOI.get(bridge::FreeBridge, ::MOI.ListOfVariableIndices) - return vcat(bridge.variables) + return copy(bridge.variables) end function MOI.get( diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 5cf4025a5b..a0022a87c9 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -632,7 +632,8 @@ function get_all_including_bridged( ) list = MOI.get(b.model, attr) if !isempty(Variable.bridges(b)) - return vcat(list, keys(Variable.bridges(b))) + # The conversion from `keys` into a `Vector` happens inside `append!`. + append!(list, keys(Variable.bridges(b))) end return list end