From 902064fb7b6dde402a49ece7556cf6b2c2500e5b Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 27 May 2024 20:56:23 +1200 Subject: [PATCH] Add default printing for show(io, ::ModelLike) (#2505) --- docs/src/submodules/Bridges/overview.md | 40 +++-- docs/src/submodules/FileFormats/overview.md | 12 +- docs/src/submodules/Utilities/overview.md | 117 +++++++++----- src/Bridges/Constraint/map.jl | 7 - .../Constraint/single_bridge_optimizer.jl | 11 +- src/Bridges/Objective/map.jl | 7 - .../Objective/single_bridge_optimizer.jl | 10 +- src/Bridges/Variable/map.jl | 7 - .../Variable/single_bridge_optimizer.jl | 10 +- src/Bridges/bridge_optimizer.jl | 13 -- src/Bridges/lazy_bridge_optimizer.jl | 38 ++++- src/MathOptInterface.jl | 38 ++++- src/Test/test_model.jl | 6 + src/Utilities/cachingoptimizer.jl | 23 +-- src/Utilities/model.jl | 4 + src/Utilities/set_dot.jl | 3 +- src/Utilities/universalfallback.jl | 22 --- src/attributes.jl | 4 +- src/sets.jl | 145 ++++++------------ test/Bridges/Constraint/map.jl | 2 - test/Bridges/Objective/map.jl | 4 - test/Bridges/Variable/map.jl | 2 - test/Bridges/bridge_optimizer.jl | 16 -- test/Bridges/lazy_bridge_optimizer.jl | 34 ++-- test/Utilities/cachingoptimizer.jl | 55 ++++--- test/Utilities/print.jl | 13 ++ test/Utilities/universalfallback.jl | 9 -- 27 files changed, 332 insertions(+), 320 deletions(-) diff --git a/docs/src/submodules/Bridges/overview.md b/docs/src/submodules/Bridges/overview.md index a12eaf2c83..2401c4be7e 100644 --- a/docs/src/submodules/Bridges/overview.md +++ b/docs/src/submodules/Bridges/overview.md @@ -104,13 +104,21 @@ in a [`Bridges.full_bridge_optimizer`](@ref). ```jldoctest julia> inner_optimizer = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 julia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64) MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} -with 0 variable bridges -with 0 constraint bridges -with 0 objective bridges -with inner model MOIU.Model{Float64} +├ Variable bridges: none +├ Constraint bridges: none +├ Objective bridges: none +└ model: MOIU.Model{Float64} + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0 ``` Now, use `optimizer` as normal, and bridging will happen lazily behind the @@ -134,13 +142,9 @@ However, this will force the constraint to be bridged, even if the `inner_optimizer` supports it. ```jldoctest -julia> inner_optimizer = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> inner_optimizer = MOI.Utilities.Model{Float64}(); -julia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer) -MOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64}, MOIU.Model{Float64}} -with 0 constraint bridges -with inner model MOIU.Model{Float64} +julia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer); julia> x = MOI.add_variable(optimizer) MOI.VariableIndex(1) @@ -168,13 +172,21 @@ First, wrap an inner optimizer: ```jldoctest lazy_bridge_optimizer julia> inner_optimizer = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 julia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer) MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} -with 0 variable bridges -with 0 constraint bridges -with 0 objective bridges -with inner model MOIU.Model{Float64} +├ Variable bridges: none +├ Constraint bridges: none +├ Objective bridges: none +└ model: MOIU.Model{Float64} + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0 ``` Then use [`Bridges.add_bridge`](@ref) to add individual bridges: diff --git a/docs/src/submodules/FileFormats/overview.md b/docs/src/submodules/FileFormats/overview.md index db6914aecc..4187dd3691 100644 --- a/docs/src/submodules/FileFormats/overview.md +++ b/docs/src/submodules/FileFormats/overview.md @@ -73,8 +73,7 @@ A SemiDefinite Programming Algorithm Format (SDPA) model To write a model `src` to a [MathOptFormat file](https://jump.dev/MathOptFormat/), use: ```jldoctest fileformats -julia> src = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> src = MOI.Utilities.Model{Float64}(); julia> MOI.add_variable(src) MOI.VariableIndex(1) @@ -130,8 +129,7 @@ argument to [`FileFormats.Model`](@ref). This will attempt to automatically guess the format from the file extension. For example: ```jldoctest fileformats -julia> src = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> src = MOI.Utilities.Model{Float64}(); julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz") A Conic Benchmark Format (CBF) model @@ -144,8 +142,7 @@ julia> MOI.write_to_file(dest, "file.cbf.gz") julia> src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz") A Conic Benchmark Format (CBF) model -julia> src = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> src = MOI.Utilities.Model{Float64}(); julia> dest = MOI.FileFormats.Model(filename = "file.cbf.gz") A Conic Benchmark Format (CBF) model @@ -189,8 +186,7 @@ MOI.write_to_file(dest, "my_model.cbf") In addition to [`write_to_file`](@ref) and [`read_from_file`](@ref), you can read and write directly from `IO` streams using `Base.write` and `Base.read!`: ```jldoctest -julia> src = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> src = MOI.Utilities.Model{Float64}(); julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS) A Mathematical Programming System (MPS) model diff --git a/docs/src/submodules/Utilities/overview.md b/docs/src/submodules/Utilities/overview.md index 2e0d9e736e..113e60ae3c 100644 --- a/docs/src/submodules/Utilities/overview.md +++ b/docs/src/submodules/Utilities/overview.md @@ -21,6 +21,10 @@ Create a model as follows: ```jldoctest julia> model = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 ``` ## Utilities.UniversalFallback @@ -36,7 +40,10 @@ fallback and [`Utilities.Model`](@ref) as a generic problem cache: ```jldoctest julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) MOIU.UniversalFallback{MOIU.Model{Float64}} -fallback for MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 ``` !!! warning @@ -87,6 +94,10 @@ MathOptInterface.Utilities.GenericOptimizer{T, MathOptInterface.Utilities.Object julia> model = MyNewModel{Float64}() MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MyNewModelFunctionConstraints{Float64}} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 ``` !!! warning @@ -152,11 +163,19 @@ julia> model = MOI.Utilities.CachingOptimizer( MOI.Utilities.Model{Float64}(), PathOptimizer{Float64}(), ) -MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}} -in state EMPTY_OPTIMIZER -in mode AUTOMATIC -with model cache MOIU.Model{Float64} -with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} +MOIU.CachingOptimizer +├ state: EMPTY_OPTIMIZER +├ mode: AUTOMATIC +├ model_cache: MOIU.Model{Float64} +│ ├ ObjectiveSense: FEASIBILITY_SENSE +│ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +│ ├ NumberOfVariables: 0 +│ └ NumberOfConstraints: 0 +└ optimizer: MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0 ``` A [`Utilities.CachingOptimizer`](@ref) may be in one of three possible states: @@ -175,12 +194,8 @@ Use [`Utilities.attach_optimizer`](@ref) to go from `EMPTY_OPTIMIZER` to ```jldoctest pathoptimizer julia> MOI.Utilities.attach_optimizer(model) -julia> model -MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}} -in state ATTACHED_OPTIMIZER -in mode AUTOMATIC -with model cache MOIU.Model{Float64} -with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} +julia> MOI.Utilities.state(model) +ATTACHED_OPTIMIZER::CachingOptimizerState = 2 ``` !!! info @@ -191,12 +206,8 @@ Use [`Utilities.reset_optimizer`](@ref) to go from `ATTACHED_OPTIMIZER` to ```jldoctest pathoptimizer julia> MOI.Utilities.reset_optimizer(model) -julia> model -MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}} -in state EMPTY_OPTIMIZER -in mode AUTOMATIC -with model cache MOIU.Model{Float64} -with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} +julia> MOI.Utilities.state(model) +EMPTY_OPTIMIZER::CachingOptimizerState = 1 ``` !!! info @@ -208,12 +219,19 @@ Use [`Utilities.drop_optimizer`](@ref) to go from any state to `NO_OPTIMIZER`: ```jldoctest pathoptimizer julia> MOI.Utilities.drop_optimizer(model) +julia> MOI.Utilities.state(model) +NO_OPTIMIZER::CachingOptimizerState = 0 + julia> model -MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}} -in state NO_OPTIMIZER -in mode AUTOMATIC -with model cache MOIU.Model{Float64} -with optimizer nothing +MOIU.CachingOptimizer +├ state: NO_OPTIMIZER +├ mode: AUTOMATIC +├ model_cache: MOIU.Model{Float64} +│ ├ ObjectiveSense: FEASIBILITY_SENSE +│ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +│ ├ NumberOfVariables: 0 +│ └ NumberOfConstraints: 0 +└ optimizer: nothing ``` Pass an empty optimizer to [`Utilities.reset_optimizer`](@ref) to go from @@ -221,12 +239,23 @@ Pass an empty optimizer to [`Utilities.reset_optimizer`](@ref) to go from ```jldoctest pathoptimizer julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}()) +julia> MOI.Utilities.state(model) +EMPTY_OPTIMIZER::CachingOptimizerState = 1 + julia> model -MOIU.CachingOptimizer{MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}}, MOIU.Model{Float64}} -in state EMPTY_OPTIMIZER -in mode AUTOMATIC -with model cache MOIU.Model{Float64} -with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} +MOIU.CachingOptimizer +├ state: EMPTY_OPTIMIZER +├ mode: AUTOMATIC +├ model_cache: MOIU.Model{Float64} +│ ├ ObjectiveSense: FEASIBILITY_SENSE +│ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +│ ├ NumberOfVariables: 0 +│ └ NumberOfConstraints: 0 +└ optimizer: MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0 ``` Deciding when to attach and reset the optimizer is tedious, and you will often @@ -256,20 +285,32 @@ julia> model = MOI.Utilities.CachingOptimizer( MOI.Utilities.Model{Float64}(), MOI.Utilities.MANUAL, ) -MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}} -in state NO_OPTIMIZER -in mode MANUAL -with model cache MOIU.Model{Float64} -with optimizer nothing +MOIU.CachingOptimizer +├ state: NO_OPTIMIZER +├ mode: MANUAL +├ model_cache: MOIU.Model{Float64} +│ ├ ObjectiveSense: FEASIBILITY_SENSE +│ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +│ ├ NumberOfVariables: 0 +│ └ NumberOfConstraints: 0 +└ optimizer: nothing julia> MOI.Utilities.reset_optimizer(model, PathOptimizer{Float64}()) julia> model -MOIU.CachingOptimizer{MOI.AbstractOptimizer, MOIU.Model{Float64}} -in state EMPTY_OPTIMIZER -in mode MANUAL -with model cache MOIU.Model{Float64} -with optimizer MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} +MOIU.CachingOptimizer +├ state: EMPTY_OPTIMIZER +├ mode: MANUAL +├ model_cache: MOIU.Model{Float64} +│ ├ ObjectiveSense: FEASIBILITY_SENSE +│ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +│ ├ NumberOfVariables: 0 +│ └ NumberOfConstraints: 0 +└ optimizer: MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0 ``` ## Printing diff --git a/src/Bridges/Constraint/map.jl b/src/Bridges/Constraint/map.jl index b33fa2902b..370f36c380 100644 --- a/src/Bridges/Constraint/map.jl +++ b/src/Bridges/Constraint/map.jl @@ -32,13 +32,6 @@ struct Map <: AbstractDict{MOI.ConstraintIndex,AbstractBridge} end end -function Base.show(io::IO, B::Map) - indent = " "^get(io, :indent, 0) - n = length(B) - s = n == 1 ? "" : "s" - return print(io, "\n$(indent)with $(n) constraint bridge$s") -end - # Implementation of `AbstractDict` interface. function Base.isempty(map::Map) diff --git a/src/Bridges/Constraint/single_bridge_optimizer.jl b/src/Bridges/Constraint/single_bridge_optimizer.jl index 9fea072667..2a0446d8b9 100644 --- a/src/Bridges/Constraint/single_bridge_optimizer.jl +++ b/src/Bridges/Constraint/single_bridge_optimizer.jl @@ -23,8 +23,10 @@ julia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64 MOI.Utilities.Model{Float64}(), ) MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 constraint bridges -with inner model MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 ``` ## Implementation notes @@ -37,10 +39,7 @@ julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} = ``` This enables users to create bridged models as follows: ```jldoctest con_singlebridgeoptimizer -julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()) -MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 constraint bridges -with inner model MOIU.Model{Float64} +julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()); ``` """ mutable struct SingleBridgeOptimizer{BT<:AbstractBridge,OT<:MOI.ModelLike} <: diff --git a/src/Bridges/Objective/map.jl b/src/Bridges/Objective/map.jl index 961668e3f7..4e457575f8 100644 --- a/src/Bridges/Objective/map.jl +++ b/src/Bridges/Objective/map.jl @@ -17,13 +17,6 @@ end Map() = Map(Dict{MOI.ObjectiveFunction,AbstractBridge}(), nothing) -function Base.show(io::IO, B::Map) - indent = " "^get(io, :indent, 0) - n = length(B) - s = n == 1 ? "" : "s" - return print(io, "\n$(indent)with $(n) objective bridge$s") -end - # Implementation of `AbstractDict` interface. Base.isempty(map::Map) = isempty(map.bridges) diff --git a/src/Bridges/Objective/single_bridge_optimizer.jl b/src/Bridges/Objective/single_bridge_optimizer.jl index c7c33fcdb1..8f93e44efc 100644 --- a/src/Bridges/Objective/single_bridge_optimizer.jl +++ b/src/Bridges/Objective/single_bridge_optimizer.jl @@ -21,10 +21,7 @@ julia> struct MyNewBridge{T} <: MOI.Bridges.Objective.AbstractBridge end julia> bridge = MOI.Bridges.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}}( MOI.Utilities.Model{Float64}(), - ) -MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 objective bridges -with inner model MOIU.Model{Float64} + ); ``` ## Implementation notes @@ -37,10 +34,7 @@ julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} = ``` This enables users to create bridged models as follows: ```jldoctest obj_singlebridgeoptimizer -julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()) -MOIB.Objective.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 objective bridges -with inner model MOIU.Model{Float64} +julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()); ``` """ mutable struct SingleBridgeOptimizer{BT<:AbstractBridge,OT<:MOI.ModelLike} <: diff --git a/src/Bridges/Variable/map.jl b/src/Bridges/Variable/map.jl index eca4290a41..842025107e 100644 --- a/src/Bridges/Variable/map.jl +++ b/src/Bridges/Variable/map.jl @@ -64,13 +64,6 @@ function Map() ) end -function Base.show(io::IO, B::Map) - indent = " "^get(io, :indent, 0) - n = length(B) - s = n == 1 ? "" : "s" - return print(io, "\n$(indent)with $(n) variable bridge$s") -end - # Implementation of `AbstractDict` interface. Base.isempty(map::Map) = all(bridge -> bridge === nothing, map.bridges) diff --git a/src/Bridges/Variable/single_bridge_optimizer.jl b/src/Bridges/Variable/single_bridge_optimizer.jl index 016463117d..6b0b2b77c3 100644 --- a/src/Bridges/Variable/single_bridge_optimizer.jl +++ b/src/Bridges/Variable/single_bridge_optimizer.jl @@ -26,10 +26,7 @@ julia> struct MyNewBridge{T} <: MOI.Bridges.Variable.AbstractBridge end julia> bridge = MOI.Bridges.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}}( MOI.Utilities.Model{Float64}(), - ) -MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 variable bridges -with inner model MOIU.Model{Float64} + ); ``` ## Implementation notes @@ -42,10 +39,7 @@ julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} = ``` This enables users to create bridged models as follows: ```jldoctest var_singlebridgeoptimizer -julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()) -MOIB.Variable.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}} -with 0 variable bridges -with inner model MOIU.Model{Float64} +julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}()); ``` """ mutable struct SingleBridgeOptimizer{BT<:AbstractBridge,OT<:MOI.ModelLike} <: diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index c0ac20bb46..0a17df458e 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -16,19 +16,6 @@ the optimizer must implement [`MOI.optimize!`](@ref). """ abstract type AbstractBridgeOptimizer <: MOI.AbstractOptimizer end -function Base.show(io::IO, B::AbstractBridgeOptimizer) - MOI.Utilities.print_with_acronym(io, summary(B)) - show(io, Variable.bridges(B)) - show(io, Constraint.bridges(B)) - show(io, Objective.bridges(B)) - if :model in propertynames(B) - indent = " "^get(io, :indent, 0) - print(io, "\n$(indent)with inner model ") - show(IOContext(io, :indent => get(io, :indent, 0) + 2), B.model) - end - return -end - # AbstractBridgeOptimizer interface """ diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index 5bfe1ac29c..3804e5523c 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -25,12 +25,7 @@ and [`full_bridge_optimizer`](@ref). ## Example ```jldoctest; setup=:(import MathOptInterface as MOI) -julia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}()) -MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} -with 0 variable bridges -with 0 constraint bridges -with 0 objective bridges -with inner model MOIU.Model{Float64} +julia> model = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.Model{Float64}()); julia> MOI.Bridges.add_bridge(model, MOI.Bridges.Variable.FreeBridge{Float64}) @@ -100,6 +95,37 @@ Constraint.bridges(bridge::LazyBridgeOptimizer) = bridge.constraint_map Objective.bridges(b::LazyBridgeOptimizer) = b.objective_map +function _print_bridges_from_map(io, map) + bridges = values(map) + if isempty(bridges) + println(io, " none") + return + end + println(io) + offset = get(io, :offset, "") + bridge_strings = sort(string.(unique(typeof.(bridges)))) + for (i, bridge) in enumerate(bridge_strings) + tree = ifelse(i == length(bridge_strings), '└', '├') + MOI.Utilities.print_with_acronym(io, "$(offset)│ $tree $bridge\n") + end + return +end + +function Base.show(io::IO, model::LazyBridgeOptimizer) + offset = get(io, :offset, "") + MOI.Utilities.print_with_acronym(io, summary(model)) + println(io) + print(io, offset, "├ Variable bridges:") + _print_bridges_from_map(io, model.variable_map) + print(io, offset, "├ Constraint bridges:") + _print_bridges_from_map(io, model.constraint_map) + print(io, offset, "├ Objective bridges:") + _print_bridges_from_map(io, model.objective_map) + print(io, offset, "└ model: ") + show(IOContext(io, :offset => offset * " "), model.model) + return +end + """ _reset_bridge_graph(b::LazyBridgeOptimizer) diff --git a/src/MathOptInterface.jl b/src/MathOptInterface.jl index b29360f256..514cb9e267 100644 --- a/src/MathOptInterface.jl +++ b/src/MathOptInterface.jl @@ -20,8 +20,44 @@ abstract type ModelLike end # embed it in a `Ref` Base.broadcastable(model::ModelLike) = Ref(model) +function _try_get(model::ModelLike, attr, default) + try + return get(model, attr) + catch + return default + end +end + function Base.show(io::IO, model::ModelLike) - return Utilities.print_with_acronym(io, summary(model)) + offset = Base.get(io, :offset, "") + Utilities.print_with_acronym(io, "$(typeof(model))\n") + # ObjectiveSense + sense = _try_get(model, ObjectiveSense(), "unknown") + println(io, offset, "├ ObjectiveSense: $sense") + # ObjectiveFunctionType + F = _try_get(model, ObjectiveFunctionType(), "unknown") + Utilities.print_with_acronym(io, "$(offset)├ ObjectiveFunctionType: $F\n") + # NumberOfVariables + n = _try_get(model, NumberOfVariables(), "unknown") + println(io, offset, "├ NumberOfVariables: $n") + # NumberOfConstraints + constraint_types = _try_get(model, ListOfConstraintTypesPresent(), nothing) + if constraint_types === nothing + print(io, offset, "└ NumberOfConstraints: unknown") + else + constraint_lines, n_total = String[], 0 + for (i, (F, S)) in enumerate(constraint_types) + m = _try_get(model, NumberOfConstraints{F,S}(), 0) + n_total += m + tree = ifelse(i == length(constraint_types), '└', '├') + push!(constraint_lines, "\n$offset $tree $F in $S: $m") + end + print(io, offset, "└ NumberOfConstraints: $n_total") + for line in constraint_lines + Utilities.print_with_acronym(io, line) + end + end + return end """ diff --git a/src/Test/test_model.jl b/src/Test/test_model.jl index 3778738c67..4c67651198 100644 --- a/src/Test/test_model.jl +++ b/src/Test/test_model.jl @@ -1220,3 +1220,9 @@ function test_model_ListOfConstraintsWithAttributeSet( @test c[2] in ret return end + +function test_model_show(model::MOI.ModelLike, ::Config{T}) where {T} + # We don't enforce any particular output. + @test sprint(show, model) isa String + return +end diff --git a/src/Utilities/cachingoptimizer.jl b/src/Utilities/cachingoptimizer.jl index a63e265ec7..4da7a0a646 100644 --- a/src/Utilities/cachingoptimizer.jl +++ b/src/Utilities/cachingoptimizer.jl @@ -113,15 +113,20 @@ mutable struct CachingOptimizer{O,M<:MOI.ModelLike} <: MOI.AbstractOptimizer end end -function Base.show(io::IO, C::CachingOptimizer) - indent = " "^get(io, :indent, 0) - print_with_acronym(io, summary(C)) - print(io, "\n$(indent)in state $(C.state)") - print(io, "\n$(indent)in mode $(C.mode)") - print(io, "\n$(indent)with model cache ") - show(IOContext(io, :indent => get(io, :indent, 0) + 2), C.model_cache) - print(io, "\n$(indent)with optimizer ") - return show(IOContext(io, :indent => get(io, :indent, 0) + 2), C.optimizer) +function Base.show(io::IO, model::CachingOptimizer) + offset = Base.get(io, :offset, "") + println(io, "MOIU.CachingOptimizer") + println(io, offset, "├ state: $(model.state)") + println(io, offset, "├ mode: $(model.mode)") + print_with_acronym(io, "$(offset)├ model_cache: ") + show(IOContext(io, :offset => offset * "│ "), model.model_cache) + print_with_acronym(io, "\n$(offset)└ optimizer: ") + if model.optimizer === nothing + print(io, "nothing") + else + show(IOContext(io, :offset => offset * " "), model.optimizer) + end + return end function _copy_optimizer_attributes(m::CachingOptimizer) diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 822cbe73c3..0aa4690640 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -833,6 +833,10 @@ julia> import MathOptInterface as MOI julia> model = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} +├ ObjectiveSense: FEASIBILITY_SENSE +├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} +├ NumberOfVariables: 0 +└ NumberOfConstraints: 0 ``` """ Model diff --git a/src/Utilities/set_dot.jl b/src/Utilities/set_dot.jl index 2f4b81a45d..d0f3718083 100644 --- a/src/Utilities/set_dot.jl +++ b/src/Utilities/set_dot.jl @@ -253,8 +253,7 @@ a [`MOI.AbstractVectorFunction`](@ref). ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index e167fcd184..0895206931 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -54,28 +54,6 @@ function UniversalFallback(model::MOI.ModelLike) return UniversalFallback{typeof(model)}(model) end -function Base.show(io::IO, U::UniversalFallback) - s(n) = n == 1 ? "" : "s" - indent = " "^get(io, :indent, 0) - print_with_acronym(io, summary(U)) - !(U.objective === nothing) && print(io, "\n$(indent)with objective") - for (attr, name) in ( - (U.single_variable_constraints, "`VariableIndex` constraint"), - (U.constraints, "constraint"), - (U.optattr, "optimizer attribute"), - (U.modattr, "model attribute"), - (U.varattr, "variable attribute"), - (U.conattr, "constraint attribute"), - ) - n = length(attr) - if n > 0 - print(io, "\n$(indent)with $n $name$(s(n))") - end - end - print(io, "\n$(indent)fallback for ") - return show(IOContext(io, :indent => get(io, :indent, 0) + 2), U.model) -end - function MOI.is_empty(uf::UniversalFallback) return MOI.is_empty(uf.model) && uf.objective === nothing && diff --git a/src/attributes.jl b/src/attributes.jl index f7904c6fef..a7fba17b31 100644 --- a/src/attributes.jl +++ b/src/attributes.jl @@ -2014,9 +2014,7 @@ julia> function ∇²f(H, x...) end ∇²f (generic function with 1 method) -julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) -MOIU.UniversalFallback{MOIU.Model{Float64}} -fallback for MOIU.Model{Float64} +julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()); julia> MOI.set(model, MOI.UserDefinedFunction(:f, 2), (f,)) diff --git a/src/sets.jl b/src/sets.jl index c0fad8239b..534106e9de 100644 --- a/src/sets.jl +++ b/src/sets.jl @@ -157,8 +157,7 @@ The set ``[lower, \\infty) \\subseteq \\mathbb{R}``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -183,8 +182,7 @@ The set ``(-\\infty, upper] \\subseteq \\mathbb{R}``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -209,8 +207,7 @@ The set containing the single point ``\\{value\\} \\subseteq \\mathbb{R}``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -245,8 +242,7 @@ and solvers should declare [`supports_add_constrained_variable`](@ref) and not ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5)) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1)) @@ -276,8 +272,7 @@ as a one-sided interval. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -337,8 +332,7 @@ The set of integers, ``\\mathbb{Z}``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -361,8 +355,7 @@ Variables belonging to the `ZeroOne` set are also known as "binary" variables. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -383,8 +376,7 @@ The set ``\\{0\\} \\cup [lower, upper]``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -416,8 +408,7 @@ the nearest integers. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variable(model) MOI.VariableIndex(1) @@ -446,8 +437,7 @@ dimension `dimension`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -483,8 +473,7 @@ dimension `dimension`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -520,8 +509,7 @@ non-negative dimension `dimension`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -557,8 +545,7 @@ non-negative dimension `dimension`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -596,8 +583,7 @@ The `dimension` must be at least `1`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -639,8 +625,7 @@ The `dimension` must be at least `1`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -682,8 +667,7 @@ The `dimension` must be at least `1`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -725,8 +709,7 @@ The `dimension` must be at least `2`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -775,8 +758,7 @@ The `dimension` must be at least `1`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -828,8 +810,7 @@ where `dimension = n + 1 >= 2`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -869,8 +850,7 @@ The 3-dimensional exponential cone ``\\{ (x,y,z) \\in \\mathbb{R}^3 : y \\exp (x ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -895,8 +875,7 @@ The 3-dimensional dual exponential cone ``\\{ (u,v,w) \\in \\mathbb{R}^3 : -u \\ ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -922,8 +901,7 @@ with parameter `exponent`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -955,8 +933,7 @@ with parameter `exponent`. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -995,8 +972,7 @@ of dimension `dimension```{}=2n+1``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> u = MOI.add_variable(model); @@ -1043,8 +1019,7 @@ Julia's `vec` function. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1099,8 +1074,7 @@ Julia's `vec` function. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1469,8 +1443,7 @@ The non-negative argument `side_dimension` is the side dimension of the matrix ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1523,8 +1496,7 @@ The non-negative argument `side_dimension` is the side dimension of the matrix ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1581,8 +1553,7 @@ The non-negative argument `side_dimension` is the side dimension of the matrix ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1635,8 +1606,7 @@ The non-negative argument `side_dimension` is the side dimension of the matrix ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> t = MOI.add_variable(model) MOI.VariableIndex(1) @@ -1750,8 +1720,7 @@ julia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3)) It can be also used to scale a vector of function ```jldoctest scaling -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -1839,8 +1808,7 @@ not change the set of feasible solutions. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -1879,8 +1847,7 @@ they must be adjacent in the ordering of the set. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3); @@ -1939,8 +1906,7 @@ is defined as ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 2) 2-element Vector{MathOptInterface.VariableIndex}: @@ -2027,8 +1993,7 @@ There are three solutions: ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0)); @@ -2052,8 +2017,7 @@ defines the complementarity problem where `0 <= x_1 ⟂ x_3 >= 0` and ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 4); @@ -2100,8 +2064,7 @@ To enforce `x[1] != x[2]` AND `x[1] != x[3]` AND `x[2] != x[3]`: ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3] 3-element Vector{MathOptInterface.VariableIndex}: @@ -2145,8 +2108,7 @@ This constraint is called `bin_packing` in MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> bins = MOI.add_variables(model, 5) 5-element Vector{MathOptInterface.VariableIndex}: @@ -2228,8 +2190,7 @@ a (potentially sub-optimal) tour in the travelling salesperson problem. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3] 3-element Vector{MathOptInterface.VariableIndex}: @@ -2271,8 +2232,7 @@ To ensure that `3` appears at least once in each of the subsets `{a, b}` and ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> a, _ = MOI.add_constrained_variable(model, MOI.Integer()) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)) @@ -2331,8 +2291,7 @@ This constraint is called `among` by MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer()) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)) @@ -2394,8 +2353,7 @@ To model: ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer()) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)) @@ -2440,8 +2398,7 @@ This constraint is called `count_gt` in MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer()) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)) @@ -2493,8 +2450,7 @@ This constraint is called `cumulative` in MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3] 3-element Vector{MathOptInterface.VariableIndex}: @@ -2553,8 +2509,7 @@ This constraint is called `path` in MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> N, E = 4, 5 (4, 5) @@ -2652,8 +2607,7 @@ This constraint is called `table` in MiniZinc. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3) 3-element Vector{MathOptInterface.VariableIndex}: @@ -2692,8 +2646,7 @@ The set ``\\{x \\in \\bar{\\mathbb{R}}^d: x_i \\in [lower_i, upper_i] \\forall i ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.Model{Float64}() -MOIU.Model{Float64} +julia> model = MOI.Utilities.Model{Float64}(); julia> x = MOI.add_variables(model, 3) 3-element Vector{MathOptInterface.VariableIndex}: @@ -2744,9 +2697,7 @@ only if ``z == 1``, where ``z \\in \\{0, 1\\}``. ```jldoctest julia> import MathOptInterface as MOI -julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) -MOIU.UniversalFallback{MOIU.Model{Float64}} -fallback for MOIU.Model{Float64} +julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()); julia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne()) (MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)) diff --git a/test/Bridges/Constraint/map.jl b/test/Bridges/Constraint/map.jl index 26df06122b..d6d9289a52 100644 --- a/test/Bridges/Constraint/map.jl +++ b/test/Bridges/Constraint/map.jl @@ -108,7 +108,6 @@ function test_map() delete!(map, c1) @test length(map) == 2 - @test sprint(show, map) == "\nwith 2 constraint bridges" @test !isempty(map) @test MOI.Bridges.Constraint.has_bridges(map) @@ -124,7 +123,6 @@ function test_map() delete!(map, c2) @test length(map) == 1 - @test sprint(show, map) == "\nwith 1 constraint bridge" @test !isempty(map) @test MOI.Bridges.Constraint.has_bridges(map) diff --git a/test/Bridges/Objective/map.jl b/test/Bridges/Objective/map.jl index 85e3532e5b..2128e18156 100644 --- a/test/Bridges/Objective/map.jl +++ b/test/Bridges/Objective/map.jl @@ -36,18 +36,14 @@ end function test_Map() map = MOI.Bridges.Objective.Map() _test_empty(map) - @test sprint(show, map) == "\nwith 0 objective bridges" x = MOI.VariableIndex(1) MOI.Bridges.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(1), x) @test MOI.Bridges.Objective.root_bridge(map) == ObjectiveDummyBridge(1) - @test sprint(show, map) == "\nwith 1 objective bridge" func = 1.0x MOI.Bridges.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(2), func) @test MOI.Bridges.Objective.root_bridge(map) == ObjectiveDummyBridge(2) - @test sprint(show, map) == "\nwith 2 objective bridges" empty!(map) _test_empty(map) - @test sprint(show, map) == "\nwith 0 objective bridges" return end diff --git a/test/Bridges/Variable/map.jl b/test/Bridges/Variable/map.jl index 932b01d912..ca28f10642 100644 --- a/test/Bridges/Variable/map.jl +++ b/test/Bridges/Variable/map.jl @@ -119,7 +119,6 @@ function test_map() @test MOI.Bridges.Variable.list_of_constraint_types(map) == Set([(F1, S1), (F2, S2)]) @test length(map) == 2 - @test sprint(show, map) == "\nwith 2 variable bridges" @test !isempty(map) @test MOI.Bridges.Variable.has_bridges(map) @test collect(keys(map)) == [v1; v2] @@ -147,7 +146,6 @@ function test_map() delete!(map, v1) @test MOI.Bridges.Variable.number_of_variables(map) == 4 @test length(map) == 1 - @test sprint(show, map) == "\nwith 1 variable bridge" @test !isempty(map) @test MOI.Bridges.Variable.has_bridges(map) elements = collect(map) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index 50b91fce24..7871eafe1f 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -532,22 +532,6 @@ function test_MOI_Test() return end -function test_show() - mock = MOI.Utilities.MockOptimizer(NoIntervalModel{Float64}()) - bridged_mock = MOI.Bridges.Constraint.LessToGreater{Float64}( - MOI.Bridges.Constraint.SplitInterval{Float64}(mock), - ) - @test_broken sprint(show, bridged_mock) == MOI.Utilities.replace_acronym( - """ -$(MOI.Bridges.Constraint.SingleBridgeOptimizer{MOI.Bridges.Constraint.LessToGreaterBridge{Float64,F,G} where G<:MOI.AbstractScalarFunction where F<:MOI.AbstractScalarFunction,MOI.Bridges.Constraint.SingleBridgeOptimizer{MOI.Bridges.Constraint.SplitIntervalBridge{Float64,F,S,LS,US} where US<:MOI.AbstractSet where LS<:MOI.AbstractSet where S<:MOI.AbstractSet where F<:MOI.AbstractFunction,MOI.Utilities.MockOptimizer{NoIntervalModel{Float64},Float64}}}) -with 1 constraint bridge -with inner model $(MOI.Bridges.Constraint.SingleBridgeOptimizer{MOI.Bridges.Constraint.SplitIntervalBridge{Float64,F,S,LS,US} where US<:MOI.AbstractSet where LS<:MOI.AbstractSet where S<:MOI.AbstractSet where F<:MOI.AbstractFunction,MOI.Utilities.MockOptimizer{NoIntervalModel{Float64},Float64}}) - with 0 constraint bridges - with inner model $(MOI.Utilities.MockOptimizer{NoIntervalModel{Float64},Float64})""", - ) - return -end - MOI.Utilities.@model( AffineOnlyModel, (), diff --git a/test/Bridges/lazy_bridge_optimizer.jl b/test/Bridges/lazy_bridge_optimizer.jl index 85bf1b9e94..f6b4ebb4e1 100644 --- a/test/Bridges/lazy_bridge_optimizer.jl +++ b/test/Bridges/lazy_bridge_optimizer.jl @@ -400,21 +400,33 @@ function test_show_SPDA() model_str = sprint(MOI.Utilities.print_with_acronym, string(typeof(model))) bridged = MOI.Bridges.full_bridge_optimizer(model, Float64) # no bridges - @test sprint(show, bridged) === """ + ret = """ MOIB.LazyBridgeOptimizer{$model_str} - with 0 variable bridges - with 0 constraint bridges - with 0 objective bridges - with inner model $model_str""" - + ├ Variable bridges: none + ├ Constraint bridges: none + ├ Objective bridges: none + └ model: $model_str + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 0 + └ NumberOfConstraints: 0""" + @test sprint(show, bridged) == ret MOI.add_constrained_variable(bridged, MOI.LessThan(1.0)) # add variable bridges - @test sprint(show, bridged) == """ + ret = """ MOIB.LazyBridgeOptimizer{$model_str} - with 2 variable bridges - with 0 constraint bridges - with 0 objective bridges - with inner model $model_str""" + ├ Variable bridges: + │ ├ MOIB.Variable.NonposToNonnegBridge{Float64} + │ └ MOIB.Variable.VectorizeBridge{Float64, MOI.Nonpositives} + ├ Constraint bridges: none + ├ Objective bridges: none + └ model: $model_str + ├ ObjectiveSense: FEASIBILITY_SENSE + ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + ├ NumberOfVariables: 1 + └ NumberOfConstraints: 1 + └ MOI.VectorOfVariables in MOI.Nonnegatives: 1""" + @test sprint(show, bridged) == ret return end diff --git a/test/Utilities/cachingoptimizer.jl b/test/Utilities/cachingoptimizer.jl index 6113ffbf33..fffc051452 100644 --- a/test/Utilities/cachingoptimizer.jl +++ b/test/Utilities/cachingoptimizer.jl @@ -489,12 +489,9 @@ function test_CachingOptimizer_MANUAL_mode() # TODO: test more constraint modifications - @test sprint(show, m) == MOI.Utilities.replace_acronym(""" - $(MOIU.CachingOptimizer{MOI.AbstractOptimizer,MOIU.Model{Float64}}) - in state NO_OPTIMIZER - in mode MANUAL - with model cache $(MOIU.Model{Float64}) - with optimizer nothing""") + show_str = sprint(show, m) + @test occursin("NO_OPTIMIZER", show_str) + @test occursin("MANUAL", show_str) MOI.empty!(s) MOIU.reset_optimizer(m, s) @@ -633,14 +630,7 @@ function test_CachingOptimizer_AUTOMATIC_mode() MOIU.attach_optimizer(m) @test MOIU.state(m) == MOIU.ATTACHED_OPTIMIZER end - - @test sprint(show, m) == MOI.Utilities.replace_acronym(""" - $(MOIU.CachingOptimizer{MOI.AbstractOptimizer,MOIU.Model{Float64}}) - in state ATTACHED_OPTIMIZER - in mode AUTOMATIC - with model cache $(MOIU.Model{Float64}) - with optimizer $(MOIU.MockOptimizer{MOIU.Model{Float64},Float64})""") - + @test occursin("AUTOMATIC", sprint(show, m)) MOI.empty!(m) @test MOIU.state(m) == MOIU.EMPTY_OPTIMIZER return @@ -655,12 +645,8 @@ function test_empty_model_and_optimizer() @test MOIU.state(m) == MOIU.EMPTY_OPTIMIZER @test MOIU.mode(m) == MOIU.AUTOMATIC @test MOI.get(m, MOI.SolverName()) == "Mock" - @test sprint(show, m) == MOI.Utilities.replace_acronym(""" - $(MOIU.CachingOptimizer{MOIU.MockOptimizer{MOIU.Model{Float64},Float64},MOIU.Model{Float64}}) - in state EMPTY_OPTIMIZER - in mode AUTOMATIC - with model cache $(MOIU.Model{Float64}) - with optimizer $(MOIU.MockOptimizer{MOIU.Model{Float64},Float64})""") + @test occursin("EMPTY_OPTIMIZER", sprint(show, m)) + return end function test_empty_model_nonempty_optimizer() @@ -1091,6 +1077,35 @@ function test_multiple_modifications() @test MOI.coefficient.(obj.terms) == [4.0, 10.0, 2.0] end +function test_show() + model = MOI.Utilities.Model{Float64}() + MOI.Utilities.loadfromstring!( + model, + """ + variables: x, y + minobjective: 2.0 * x + c1: x >= 0.0 + c2: 1.0 * x + 2.0 * y <= 3.0 + c2: 1.0 * x + 3.0 * y <= 2.0 + """, + ) + cache = MOI.Utilities.CachingOptimizer(model, MOI.Utilities.MANUAL) + output = """ + MOIU.CachingOptimizer + ├ state: NO_OPTIMIZER + ├ mode: MANUAL + ├ model_cache: MOIU.Model{Float64} + │ ├ ObjectiveSense: MIN_SENSE + │ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} + │ ├ NumberOfVariables: 2 + │ └ NumberOfConstraints: 3 + │ ├ MOI.ScalarAffineFunction{Float64} in MOI.LessThan{Float64}: 2 + │ └ MOI.VariableIndex in MOI.GreaterThan{Float64}: 1 + └ optimizer: nothing""" + @test sprint(show, cache) == output + return +end + end # module TestCachingOptimizer.runtests() diff --git a/test/Utilities/print.jl b/test/Utilities/print.jl index d765f88b39..5f7a085324 100644 --- a/test/Utilities/print.jl +++ b/test/Utilities/print.jl @@ -711,6 +711,19 @@ function test_scalar_nonlinear_function_print() return end +struct TestShow2505 <: MOI.ModelLike end + +function test_show_2505() + model = TestShow2505() + @test sprint(show, model) == """ + $(typeof(model)) + ├ ObjectiveSense: unknown + ├ ObjectiveFunctionType: unknown + ├ NumberOfVariables: unknown + └ NumberOfConstraints: unknown""" + return +end + end TestPrint.runtests() diff --git a/test/Utilities/universalfallback.jl b/test/Utilities/universalfallback.jl index af541629a0..8777c76687 100644 --- a/test/Utilities/universalfallback.jl +++ b/test/Utilities/universalfallback.jl @@ -369,15 +369,6 @@ function test_deterministic_constraint_ordering() return end -function test_show() - model = ModelForUniversalFallback{Float64}() - uf = MOI.Utilities.UniversalFallback(model) - @test sprint(show, uf) == MOI.Utilities.replace_acronym(""" - $(MOI.Utilities.UniversalFallback{ModelForUniversalFallback{Float64}}) - fallback for $(ModelForUniversalFallback{Float64})""") - return -end - function test_missing_attribute() model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) @test MOI.get(model, MOI.Test.UnknownModelAttribute()) === nothing