Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions src/Bridges/debug.jl
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,9 @@ Print the set of bridges that are active in the model `b`.
"""
function print_active_bridges(io::IO, b::MOI.Bridges.LazyBridgeOptimizer)
F = MOI.get(b, MOI.ObjectiveFunctionType())
print_active_bridges(io, b, F)
if F !== nothing
print_active_bridges(io, b, F)
end
types = MOI.get(b, MOI.ListOfConstraintTypesPresent())
# We add a sort here to make the order reproducible, and to group similar
# constraints together.
Expand Down Expand Up @@ -639,6 +641,11 @@ function print_active_bridges(
offset::String = "",
) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
if !MOI.supports_constraint(b, F, S)
if F == MOI.VariableIndex || F == MOI.VectorOfVariables
# Okay. If you don't support the constraint, maybe you support
# adding as a constrained variable.
return print_active_bridges(io, b, S, offset)
end
throw(
MOI.UnsupportedConstraint{F,S}(
"The constraint cannot be bridged using the set of available " *
Expand All @@ -651,35 +658,31 @@ function print_active_bridges(
_print_supported(io, "Supported constraint: $F-in-$S\n")
return
end
is_constraint_bridged = true
c_node = b.constraint_node[(F, S)]
if F == MOI.VariableIndex || F == MOI.VectorOfVariables
# Call `MOI.supports_` here to build the necessary nodes in the bridging
# graph.
if F == MOI.VariableIndex
MOI.supports_add_constrained_variable(b, S)
if is_bridged(b, S)
# The constraint can be both variable bridged and constraint
# bridged. Which is cheaper?
v_node = b.variable_node[(S,)]
if bridging_cost(b.graph, v_node) <= bridging_cost(b.graph, c_node)
return print_active_bridges(io, b, S, offset)
end
else
MOI.supports_add_constrained_variables(b, S)
# The constraint is bridged via add_constraint, and not via
# add_constrained_variable(s).
return print_active_bridges(io, b, S, offset)
end
v_node = b.variable_node[(S,)]
if bridging_cost(b.graph, v_node) <= bridging_cost(b.graph, c_node)
is_constraint_bridged = false
end
end
if is_constraint_bridged
index = MOI.Bridges.bridge_index(b.graph, c_node)
B = b.constraint_bridge_types[index]
BT = MOI.Bridges.Constraint.concrete_bridge_type(B, F, S)
print(io, offset, " * ")
_print_unsupported(io, "Unsupported constraint: $F-in-$S\n")
println(io, offset, " | bridged by:")
print(io, offset, " | ")
MOI.Utilities.print_with_acronym(io, "$BT\n")
println(io, offset, " | may introduce:")
_print_bridge(io, b, BT, offset)
else
print_active_bridges(io, b, S, offset)
end
index = MOI.Bridges.bridge_index(b.graph, c_node)
B = b.constraint_bridge_types[index]
BT = MOI.Bridges.Constraint.concrete_bridge_type(B, F, S)
print(io, offset, " * ")
_print_unsupported(io, "Unsupported constraint: $F-in-$S\n")
println(io, offset, " | bridged by:")
print(io, offset, " | ")
MOI.Utilities.print_with_acronym(io, "$BT\n")
println(io, offset, " | may introduce:")
_print_bridge(io, b, BT, offset)
return
end

Expand Down
110 changes: 110 additions & 0 deletions test/Bridges/General/test_debug.jl
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,116 @@ function test_print_graph_stdout()
return
end

struct ModelPOIIssue201{T} <: MOI.ModelLike
supports_equal_to::Bool
supports_parameter::Bool
parameter::Vector{T}
equal_to::Vector{T}
function ModelPOIIssue201{T}(;
supports_equal_to::Bool = true,
supports_parameter::Bool = true,
) where {T}
return new{T}(supports_equal_to, supports_parameter, T[], T[])
end
end

function MOI.supports_add_constrained_variable(
model::ModelPOIIssue201{T},
::Type{MOI.Parameter{T}},
) where {T}
return model.supports_parameter
end

function MOI.supports_add_constrained_variable(
model::ModelPOIIssue201{T},
::Type{MOI.EqualTo{T}},
) where {T}
return model.supports_equal_to
end

function MOI.supports_constraint(
model::ModelPOIIssue201{T},
::Type{MOI.ScalarAffineFunction{T}},
::Type{MOI.EqualTo{T}},
) where {T}
return model.supports_equal_to
end

MOI.get(::ModelPOIIssue201, ::MOI.ObjectiveFunctionType) = nothing

function MOI.get(
model::ModelPOIIssue201{T},
::MOI.ListOfConstraintTypesPresent,
) where {T}
ret = Tuple{Type,Type}[]
if !isempty(model.parameter)
push!(ret, (MOI.VariableIndex, MOI.Parameter{T}))
end
if !isempty(model.equal_to)
push!(ret, (MOI.VariableIndex, MOI.EqualTo{T}))
end
return ret
end

function MOI.get(
model::ModelPOIIssue201{T},
::MOI.NumberOfConstraints{MOI.VariableIndex,MOI.Parameter{T}},
) where {T}
return length(model.parameter)
end

function MOI.get(
model::ModelPOIIssue201{T},
::MOI.NumberOfConstraints{MOI.VariableIndex,MOI.EqualTo{T}},
) where {T}
return length(model.equal_to)
end

function MOI.add_constrained_variable(
model::ModelPOIIssue201{T},
set::MOI.Parameter{T},
) where {T}
push!(model.parameter, set.value)
x = MOI.VariableIndex(length(model.parameter))
return x, MOI.ConstraintIndex{MOI.VariableIndex,typeof(set)}(x.value)
end

function MOI.add_constrained_variable(
model::ModelPOIIssue201{T},
set::MOI.EqualTo{T},
) where {T}
push!(model.equal_to, set.value)
x = MOI.VariableIndex(length(model.equal_to))
return x, MOI.ConstraintIndex{MOI.VariableIndex,typeof(set)}(x.value)
end

function test_parametricoptinterface_issue_201_case_1()
model = ModelPOIIssue201{Float64}(; supports_equal_to = false)
model = MOI.Bridges.full_bridge_optimizer(model, Float64)
p, _ = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
@test sprint(MOI.Bridges.print_active_bridges, model) ==
" * Supported variable: MOI.Parameter{Float64}\n"
return
end

function test_parametricoptinterface_issue_201_case_2()
model = ModelPOIIssue201{Float64}(; supports_equal_to = true)
model = MOI.Bridges.full_bridge_optimizer(model, Float64)
p, _ = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
@test sprint(MOI.Bridges.print_active_bridges, model) ==
" * Supported variable: MOI.Parameter{Float64}\n"
return
end

function test_parametricoptinterface_issue_201_case_3()
model = ModelPOIIssue201{Float64}(; supports_parameter = false)
model = MOI.Bridges.full_bridge_optimizer(model, Float64)
p, _ = MOI.add_constrained_variable(model, MOI.Parameter(1.0))
@test sprint(MOI.Bridges.print_active_bridges, model) ==
" * Unsupported variable: MOI.Parameter{Float64}\n | bridged by:\n | MOIB.Variable.ParameterToEqualToBridge{Float64}\n | may introduce:\n | * Supported variable: MOI.EqualTo{Float64}\n"
return
end

end

TestBridgesDebug.runtests()
Loading