From 0f0094b5f5ebd6fb573a94ebd9d03c04efc60216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 15 Jul 2021 23:14:35 -0400 Subject: [PATCH 1/7] Remove SingleVariable --- src/FileFormats/NL/NLExpr.jl | 2 -- src/MathOptInterface.jl | 16 ++++++++++++++++ src/Utilities/functions.jl | 4 ---- src/Utilities/print.jl | 8 -------- src/functions.jl | 26 +++++++++----------------- src/indextypes.jl | 2 +- 6 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/FileFormats/NL/NLExpr.jl b/src/FileFormats/NL/NLExpr.jl index e8ce2e58d3..e18e26ca50 100644 --- a/src/FileFormats/NL/NLExpr.jl +++ b/src/FileFormats/NL/NLExpr.jl @@ -296,8 +296,6 @@ end _NLExpr(x::MOI.VariableIndex) = _NLExpr(true, _NLTerm[], Dict(x => 1.0), 0.0) -_NLExpr(x::MOI.SingleVariable) = _NLExpr(x.variable) - function _add_or_set(dict, key, value) if haskey(dict, key) dict[key] += value diff --git a/src/MathOptInterface.jl b/src/MathOptInterface.jl index f5475b130f..18b888957f 100644 --- a/src/MathOptInterface.jl +++ b/src/MathOptInterface.jl @@ -159,6 +159,22 @@ is_valid(dest, index_map[x]) # true """ function copy_to end +import MutableArithmetics + +""" + AbstractFunction + +Abstract supertype for function objects. +""" +abstract type AbstractFunction <: MutableArithmetics.AbstractMutable end + +""" + AbstractScalarFunction + +Abstract supertype for scalar-valued function objects. +""" +abstract type AbstractScalarFunction <: AbstractFunction end + include("error.jl") include("indextypes.jl") include("functions.jl") diff --git a/src/Utilities/functions.jl b/src/Utilities/functions.jl index 16095898fa..831cf0eef7 100644 --- a/src/Utilities/functions.jl +++ b/src/Utilities/functions.jl @@ -156,10 +156,6 @@ end # Functions -function map_indices(index_map::F, f::MOI.SingleVariable) where {F<:Function} - return MOI.SingleVariable(index_map(f.variable)) -end - function map_indices(index_map::F, f::MOI.VectorOfVariables) where {F<:Function} return MOI.VectorOfVariables(index_map.(f.variables)) end diff --git a/src/Utilities/print.jl b/src/Utilities/print.jl index dc8580b265..44f30f6d6d 100644 --- a/src/Utilities/print.jl +++ b/src/Utilities/print.jl @@ -111,14 +111,6 @@ function _shorten(options::_PrintOptions, x::Float64) return string(x) end -function _to_string( - options::_PrintOptions, - model::MOI.ModelLike, - f::MOI.SingleVariable, -) - return _to_string(options, model, f.variable) -end - """ _to_string(options::_PrintOptions, c::Float64, x::String) diff --git a/src/functions.jl b/src/functions.jl index c306eafc47..288fb5d9ba 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -1,14 +1,5 @@ # Functions -import MutableArithmetics - -""" - AbstractFunction - -Abstract supertype for function objects. -""" -abstract type AbstractFunction <: MutableArithmetics.AbstractMutable end - """ output_dimension(f::AbstractFunction) @@ -17,12 +8,6 @@ has a vector output. """ function output_dimension end -""" - AbstractScalarFunction - -Abstract supertype for scalar-valued function objects. -""" -abstract type AbstractScalarFunction <: AbstractFunction end output_dimension(::AbstractScalarFunction) = 1 Base.broadcastable(f::AbstractScalarFunction) = Ref(f) @@ -42,8 +27,15 @@ abstract type AbstractVectorFunction <: AbstractFunction end The function that extracts the scalar variable referenced by `variable`, a `VariableIndex`. This function is naturally be used for single variable bounds or integrality constraints. """ -struct SingleVariable <: AbstractScalarFunction - variable::VariableIndex +const SingleVariable = VariableIndex +VariableIndex(vi::VariableIndex) = vi +function Base.getproperty(vi::VariableIndex, s::Symbol) + if s == :value + return getfield(vi, s) + else + @assert s == :variable + return vi + end end """ diff --git a/src/indextypes.jl b/src/indextypes.jl index 4b026a59cc..44f0abe5fc 100644 --- a/src/indextypes.jl +++ b/src/indextypes.jl @@ -27,7 +27,7 @@ index_value(ci::ConstraintIndex) = ci.value A type-safe wrapper for `Int64` for use in referencing variables in a model. To allow for deletion, indices need not be consecutive. """ -struct VariableIndex +struct VariableIndex <: AbstractScalarFunction value::Int64 end index_value(vi::VariableIndex) = vi.value From a4f147b16909e52f5d29506614fcf01ab6f14e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 16 Jul 2021 09:57:01 -0400 Subject: [PATCH 2/7] Remove shorthand --- src/constraints.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/constraints.jl b/src/constraints.jl index d2aab39815..8f65137ad6 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -207,13 +207,6 @@ function correct_throw_add_constraint_error_fallback( end # convenient shorthands TODO: document -function add_constraint( - model::ModelLike, - v::VariableIndex, - set::AbstractScalarSet, -) - return add_constraint(model, SingleVariable(v), set) -end function add_constraint( model::ModelLike, v::Vector{VariableIndex}, From fd10189b90a368874982a6c32019c108bb5ac261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 17 Jul 2021 08:48:17 -0400 Subject: [PATCH 3/7] Update error message in test --- test/errors.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/errors.jl b/test/errors.jl index 20420c1d9a..0240f6ec90 100644 --- a/test/errors.jl +++ b/test/errors.jl @@ -52,7 +52,7 @@ function _test_errors_UnsupportedConstraint(f) catch err @test sprint(showerror, err) == "$(MOI.UnsupportedConstraint{MOI.SingleVariable,MOI.EqualTo{Int}}):" * - " `$MOI.SingleVariable`-in-`$MOI.EqualTo{$Int}` constraint is" * + " `$MOI.VariableIndex`-in-`$MOI.EqualTo{$Int}` constraint is" * " not supported by the model." end return @@ -90,7 +90,7 @@ function test_errors_add_constraint() catch err @test sprint(showerror, err) == "$(MOI.AddConstraintNotAllowed{MOI.SingleVariable,MOI.EqualTo{Float64}}):" * - " Adding `$MOI.SingleVariable`-in-`$MOI.EqualTo{Float64}`" * + " Adding `$MOI.VariableIndex`-in-`$MOI.EqualTo{Float64}`" * " constraints cannot be performed. You may want to use a" * " `CachingOptimizer` in `AUTOMATIC` mode or you may need to call" * " `reset_optimizer` before doing this operation if the" * From 78934aefc07e1135ba4f2a561dc6efdd19f89594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 17 Jul 2021 08:49:00 -0400 Subject: [PATCH 4/7] Use === in getproperty --- src/functions.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/functions.jl b/src/functions.jl index 288fb5d9ba..93c16ac37e 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -30,10 +30,10 @@ This function is naturally be used for single variable bounds or integrality con const SingleVariable = VariableIndex VariableIndex(vi::VariableIndex) = vi function Base.getproperty(vi::VariableIndex, s::Symbol) - if s == :value + if s === :value return getfield(vi, s) else - @assert s == :variable + @assert s === :variable return vi end end From c8e944ebd71988c3696dd284f72b9b8d423a1e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 17 Jul 2021 13:27:40 -0400 Subject: [PATCH 5/7] Fix --- src/Utilities/results.jl | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Utilities/results.jl b/src/Utilities/results.jl index 8a9c09735e..9db41425af 100644 --- a/src/Utilities/results.jl +++ b/src/Utilities/results.jl @@ -444,21 +444,12 @@ end """ variable_dual(model::MOI.ModelLike, attr::MOI.ConstraintDual, - ci::MOI.ConstraintIndex{F}, - func::F) where F <: Union{MOI.SingleVariable, - MOI.VectorOfVariables} + ci::MOI.ConstraintIndex{MOI.VectorOfVariables}, + func::MOI.VectorOfVariables) Return the dual of the constraint of index `ci` for which the value of the `MOI.ConstraintFunction` attribute is `func`. """ -function variable_dual( - model::MOI.ModelLike, - attr::MOI.ConstraintDual, - ci::MOI.ConstraintIndex{MOI.SingleVariable}, - func::MOI.SingleVariable, -) - return variable_dual(model, attr, ci, func.variable) -end function variable_dual( model::MOI.ModelLike, attr::MOI.ConstraintDual, From ea9ce6cd13bbae7d8b0ad9d4878118dde54dd74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 17 Jul 2021 14:00:56 -0400 Subject: [PATCH 6/7] Update printing in tests --- test/Bridges/lazy_bridge_optimizer.jl | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/Bridges/lazy_bridge_optimizer.jl b/test/Bridges/lazy_bridge_optimizer.jl index 99e702fa56..e46c175e25 100644 --- a/test/Bridges/lazy_bridge_optimizer.jl +++ b/test/Bridges/lazy_bridge_optimizer.jl @@ -930,8 +930,8 @@ Objective function of type `MOI.ScalarQuadraticFunction{$T}` is not supported an Cannot use `$(MOI.Bridges.Objective.SlackBridge{T,MOI.ScalarQuadraticFunction{T},MOI.ScalarQuadraticFunction{T}})` because: (1) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.GreaterThan{$T}` constraints are not supported (2) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.LessThan{$T}` constraints are not supported - |2| objective function of type `MOI.SingleVariable` is not supported - |2| objective function of type `MOI.SingleVariable` is not supported because no added bridge supports bridging it. + |2| objective function of type `MOI.VariableIndex` is not supported + |2| objective function of type `MOI.VariableIndex` is not supported because no added bridge supports bridging it. """, ) MOI.Bridges.add_bridge( @@ -1021,14 +1021,14 @@ Objective function of type `MOI.ScalarQuadraticFunction{$T}` is not supported an MOI.Utilities.replace_acronym( """ Bridge graph with 1 variable nodes, 5 constraint nodes and 2 objective nodes. - [1] constrained variables in `MOI.RotatedSecondOrderCone` are bridged (distance 2) by $(MOI.Bridges.Variable.RSOCtoPSDBridge{T}). - (1) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.GreaterThan{$T}` constraints are bridged (distance 5) by $(MOI.Bridges.Constraint.QuadtoSOCBridge{T}). - (2) `MOI.VectorAffineFunction{$T}`-in-`MOI.RotatedSecondOrderCone` constraints are bridged (distance 4) by $(MOI.Bridges.Constraint.VectorSlackBridge{T,MOI.VectorAffineFunction{T},MOI.RotatedSecondOrderCone}). - (3) `MOI.SingleVariable`-in-`MOI.EqualTo{$T}` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.ScalarFunctionizeBridge{T,MOI.EqualTo{T}}). - (4) `MOI.VectorAffineFunction{$T}`-in-`MOI.Zeros` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.ScalarizeBridge{T,MOI.ScalarAffineFunction{T},MOI.EqualTo{T}}). - (5) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.LessThan{$T}` constraints are bridged (distance 5) by $(MOI.Bridges.Constraint.QuadtoSOCBridge{T}). - |1| objective function of type `MOI.ScalarQuadraticFunction{$T}` is bridged (distance 12) by $(MOI.Bridges.Objective.SlackBridge{T,MOI.ScalarQuadraticFunction{T},MOI.ScalarQuadraticFunction{T}}). - |2| objective function of type `MOI.SingleVariable` is bridged (distance 1) by $(MOI.Bridges.Objective.FunctionizeBridge{T}). + [1] constrained variables in `MOI.RotatedSecondOrderCone` are bridged (distance 2) by $(MOIB.Variable.RSOCtoPSDBridge{T}). + (1) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.GreaterThan{$T}` constraints are bridged (distance 5) by $(MOIB.Constraint.QuadtoSOCBridge{T}). + (2) `MOI.VectorAffineFunction{$T}`-in-`MOI.RotatedSecondOrderCone` constraints are bridged (distance 4) by $(MOIB.Constraint.VectorSlackBridge{T,MOI.VectorAffineFunction{T},MOI.RotatedSecondOrderCone}). + (3) `MOI.VariableIndex`-in-`MOI.EqualTo{$T}` constraints are bridged (distance 1) by $(MOIB.Constraint.ScalarFunctionizeBridge{T,MOI.EqualTo{T}}). + (4) `MOI.VectorAffineFunction{$T}`-in-`MOI.Zeros` constraints are bridged (distance 1) by $(MOIB.Constraint.ScalarizeBridge{T,MOI.ScalarAffineFunction{T},MOI.EqualTo{T}}). + (5) `MOI.ScalarQuadraticFunction{$T}`-in-`MOI.LessThan{$T}` constraints are bridged (distance 5) by $(MOIB.Constraint.QuadtoSOCBridge{T}). + |1| objective function of type `MOI.ScalarQuadraticFunction{$T}` is bridged (distance 12) by $(MOIB.Objective.SlackBridge{T,MOI.ScalarQuadraticFunction{T},MOI.ScalarQuadraticFunction{T}}). + |2| objective function of type `MOI.VariableIndex` is bridged (distance 1) by $(MOIB.Objective.FunctionizeBridge{T}). """, ) end @@ -1273,12 +1273,12 @@ Bridge graph with 5 variable nodes, 11 constraint nodes and 0 objective nodes. (3) `MOI.VectorOfVariables`-in-`MOI.RotatedSecondOrderCone` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.RSOCtoSOCBridge{T,MOI.VectorAffineFunction{T},MOI.VectorOfVariables}). (4) `MOI.VectorAffineFunction{$T}`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported (5) `MOI.VectorOfVariables`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported - (6) `MOI.VectorOfVariables`-in-`MOI.Nonnegatives` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.NonnegToNonposBridge{T,MOI.VectorAffineFunction{T},MOI.VectorOfVariables}). - (7) `MOI.SingleVariable`-in-`MOI.GreaterThan{$T}` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.GreaterToLessBridge{T,MOI.ScalarAffineFunction{T},MOI.SingleVariable}). - (8) `MOI.SingleVariable`-in-`MOI.Interval{$T}` constraints are bridged (distance 2) by $(MOI.Bridges.Constraint.ScalarFunctionizeBridge{T,MOI.Interval{T}}). - (9) `MOI.ScalarAffineFunction{$T}`-in-`MOI.Interval{$T}` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.SplitIntervalBridge{T,MOI.ScalarAffineFunction{T},MOI.Interval{T},MOI.GreaterThan{T},MOI.LessThan{T}}). - (10) `MOI.SingleVariable`-in-`MOI.LessThan{$T}` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.LessToGreaterBridge{T,MOI.ScalarAffineFunction{T},MOI.SingleVariable}). - (11) `MOI.SingleVariable`-in-`MOI.EqualTo{$T}` constraints are bridged (distance 1) by $(MOI.Bridges.Constraint.VectorizeBridge{T,MOI.VectorAffineFunction{T},MOI.Zeros,MOI.SingleVariable}). + (6) `MOI.VectorOfVariables`-in-`MOI.Nonnegatives` constraints are bridged (distance 1) by $(MOIB.Constraint.NonnegToNonposBridge{T,MOI.VectorAffineFunction{T},MOI.VectorOfVariables}). + (7) `MOI.VariableIndex`-in-`MOI.GreaterThan{$T}` constraints are bridged (distance 1) by $(MOIB.Constraint.GreaterToLessBridge{T,MOI.ScalarAffineFunction{T},MOI.SingleVariable}). + (8) `MOI.VariableIndex`-in-`MOI.Interval{$T}` constraints are bridged (distance 2) by $(MOIB.Constraint.ScalarFunctionizeBridge{T,MOI.Interval{T}}). + (9) `MOI.ScalarAffineFunction{$T}`-in-`MOI.Interval{$T}` constraints are bridged (distance 1) by $(MOIB.Constraint.SplitIntervalBridge{T,MOI.ScalarAffineFunction{T},MOI.Interval{T},MOI.GreaterThan{T},MOI.LessThan{T}}). + (10) `MOI.VariableIndex`-in-`MOI.LessThan{$T}` constraints are bridged (distance 1) by $(MOIB.Constraint.LessToGreaterBridge{T,MOI.ScalarAffineFunction{T},MOI.SingleVariable}). + (11) `MOI.VariableIndex`-in-`MOI.EqualTo{$T}` constraints are bridged (distance 1) by $(MOIB.Constraint.VectorizeBridge{T,MOI.VectorAffineFunction{T},MOI.Zeros,MOI.SingleVariable}). """, ) return From 306f11b7e9eac2d1d719547230a54bdb16e33373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 18 Jul 2021 20:29:42 -0400 Subject: [PATCH 7/7] Update printing in tests --- test/Utilities/print.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/Utilities/print.jl b/test/Utilities/print.jl index 51e411f8a1..9f565e9e37 100644 --- a/test/Utilities/print.jl +++ b/test/Utilities/print.jl @@ -212,7 +212,7 @@ function test_min() model = MOIU.Model{Float64}() MOIU.loadfromstring!(model, "variables: x\nminobjective: x") @test sprint(print, model) == """ - Minimize SingleVariable: + Minimize VariableIndex: x Subject to: @@ -232,7 +232,7 @@ function test_max() model = MOIU.Model{Float64}() MOIU.loadfromstring!(model, "variables: x\nmaxobjective: x") @test sprint(print, model) == """ - Maximize SingleVariable: + Maximize VariableIndex: x Subject to: @@ -312,13 +312,13 @@ function test_model() │0.0 + 1.0 y │ └ ┘ $(IN) ExponentialCone() - SingleVariable-in-GreaterThan{Float64} + VariableIndex-in-GreaterThan{Float64} x >= 0.1 - SingleVariable-in-Integer + VariableIndex-in-Integer z $(IN) ℤ - SingleVariable-in-ZeroOne + VariableIndex-in-ZeroOne x $(IN) {0, 1} y $(IN) {0, 1} """ @@ -379,11 +379,11 @@ function test_latex() 1.0\\ 0.0 + 1.0 x^2\\ 0.0 + 1.0 y\end{bmatrix} \in \text{ExponentialCone()} \\ - & \text{SingleVariable-in-GreaterThan{Float64}} \\ + & \text{VariableIndex-in-GreaterThan{Float64}} \\ & x \ge 0.1 \\ - & \text{SingleVariable-in-Integer} \\ + & \text{VariableIndex-in-Integer} \\ & z \in \mathbb{Z} \\ - & \text{SingleVariable-in-ZeroOne} \\ + & \text{VariableIndex-in-ZeroOne} \\ & x \in \{0, 1\} \\ & y \in \{0, 1\} \\ \end{aligned} $$""", @@ -544,13 +544,13 @@ function test_nlp() Subject to: - SingleVariable-in-GreaterThan{Float64} + VariableIndex-in-GreaterThan{Float64} x[1] >= 1.1 x[2] >= 1.2 x[3] >= 1.3 x[4] >= 1.4 - SingleVariable-in-LessThan{Float64} + VariableIndex-in-LessThan{Float64} x[1] <= 5.1 x[2] <= 5.2 x[3] <= 5.3 @@ -566,12 +566,12 @@ function test_nlp() $$ \begin{aligned} \min\quad & x_{1} \times x_{4} \times (x_{1} + x_{2} + x_{3}) + x_{3} \\ \text{Subject to}\\ - & \text{SingleVariable-in-GreaterThan{Float64}} \\ + & \text{VariableIndex-in-GreaterThan{Float64}} \\ & x_{1} \ge 1.1 \\ & x_{2} \ge 1.2 \\ & x_{3} \ge 1.3 \\ & x_{4} \ge 1.4 \\ - & \text{SingleVariable-in-LessThan{Float64}} \\ + & \text{VariableIndex-in-LessThan{Float64}} \\ & x_{1} \le 5.1 \\ & x_{2} \le 5.2 \\ & x_{3} \le 5.3 \\