From aee9ec2dd1258b6c36302831370cb0249ca1b3d0 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 4 Sep 2025 09:02:29 +1200 Subject: [PATCH 1/3] Add nospecialize to some very highly specialized methods --- src/Bridges/Constraint/bridge.jl | 2 ++ src/Bridges/lazy_bridge_optimizer.jl | 14 +++++++++++++- src/Test/Test.jl | 2 ++ src/Utilities/model.jl | 2 ++ src/constraints.jl | 2 ++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridge.jl b/src/Bridges/Constraint/bridge.jl index 0320db5e1f..037f45d551 100644 --- a/src/Bridges/Constraint/bridge.jl +++ b/src/Bridges/Constraint/bridge.jl @@ -19,6 +19,7 @@ additionally implement: """ abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end +@nospecialize """ MOI.supports_constraint( BT::Type{<:AbstractBridge}, @@ -42,6 +43,7 @@ function MOI.supports_constraint( ) return false end +@specialize """ concrete_bridge_type( diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index cc4387467f..f20530cbee 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -149,6 +149,7 @@ function _reset_bridge_graph(b::LazyBridgeOptimizer) return end +@nospecialize """ _variable_nodes(b::LazyBridgeOptimizer, ::Type{BT}) where {BT} @@ -162,7 +163,9 @@ function _variable_nodes( return node(b, S)::VariableNode end end +@specialize +@nospecialize """ _constraint_nodes(b::LazyBridgeOptimizer, ::Type{BT}) where {BT} @@ -176,7 +179,9 @@ function _constraint_nodes( node(b, F, S) for (F, S) in added_constraint_types(BT) ] end +@specialize +@nospecialize """ _edge(b::LazyBridgeOptimizer, index::Int, BT::Type{<:AbstractBridge}) @@ -191,6 +196,7 @@ function _edge(b::LazyBridgeOptimizer, index::Int, BT::Type{<:AbstractBridge}) bridging_cost(BT), ) end +@specialize # Method for objective bridges because they produce ObjectiveEdge. function _edge( @@ -376,12 +382,14 @@ function _bridge_types( return b.variable_bridge_types end +@nospecialize function _bridge_types( b::LazyBridgeOptimizer, ::Type{<:Constraint.AbstractBridge}, ) return b.constraint_bridge_types end +@specialize function _bridge_types( b::LazyBridgeOptimizer, @@ -390,6 +398,7 @@ function _bridge_types( return b.objective_bridge_types end +@nospecialize """ add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) @@ -402,6 +411,7 @@ function add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) end return end +@specialize """ remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) @@ -422,14 +432,16 @@ function remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) return end +@nospecialize """ has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) Return a `Bool` indicating whether the bridges of type `BT` are used by `b`. """ -function has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) +function has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})::Bool return findfirst(isequal(BT), _bridge_types(b, BT)) !== nothing end +@specialize # It only bridges when the constraint is not supporting, hence the name "Lazy" function is_bridged(b::LazyBridgeOptimizer, S::Type{<:MOI.AbstractScalarSet}) diff --git a/src/Test/Test.jl b/src/Test/Test.jl index 3332e3cc3c..7bf33793db 100644 --- a/src/Test/Test.jl +++ b/src/Test/Test.jl @@ -499,6 +499,7 @@ function _test_attribute_value_type( return end +@nospecialize function _test_attribute_value_type( model::MOI.ModelLike, attribute::MOI.AbstractConstraintAttribute, @@ -508,6 +509,7 @@ function _test_attribute_value_type( @test @inferred(T, MOI.get(model, attribute, ci)) isa T return end +@specialize function _test_attribute_value_type( model::MOI.ModelLike, diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 184488c3b8..170e69ef5e 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -302,6 +302,7 @@ function MOI.is_valid(model::AbstractModel, ci::MOI.ConstraintIndex) return MOI.is_valid(constraints(model, ci), ci) end +@nospecialize function MOI.supports_constraint( model::AbstractModel, ::Type{F}, @@ -309,6 +310,7 @@ function MOI.supports_constraint( ) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet} return MOI.supports_constraint(model.constraints, F, S) end +@specialize function MOI.add_constraint( model::AbstractModel, diff --git a/src/constraints.jl b/src/constraints.jl index 081b4235d2..bf29723a31 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -4,6 +4,7 @@ # Use of this source code is governed by an MIT-style license that can be found # in the LICENSE.md file or at https://opensource.org/licenses/MIT. +@nospecialize """ supports_constraint( model::ModelLike, @@ -24,6 +25,7 @@ function supports_constraint( ) return false end +@specialize """ struct UnsupportedConstraint{F<:AbstractFunction,S<:AbstractSet} <: UnsupportedError From 4ca120b8b6985af1ece4e989b2b09ae1d15ae009 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 4 Sep 2025 10:37:50 +1200 Subject: [PATCH 2/3] Update --- src/Bridges/Constraint/bridge.jl | 8 ++- .../Constraint/single_bridge_optimizer.jl | 6 +-- src/Bridges/lazy_bridge_optimizer.jl | 50 +++++++++---------- src/Test/Test.jl | 8 ++- src/Utilities/model.jl | 10 ++-- src/constraints.jl | 8 ++- 6 files changed, 40 insertions(+), 50 deletions(-) diff --git a/src/Bridges/Constraint/bridge.jl b/src/Bridges/Constraint/bridge.jl index 037f45d551..4337336b03 100644 --- a/src/Bridges/Constraint/bridge.jl +++ b/src/Bridges/Constraint/bridge.jl @@ -19,7 +19,6 @@ additionally implement: """ abstract type AbstractBridge <: MOI.Bridges.AbstractBridge end -@nospecialize """ MOI.supports_constraint( BT::Type{<:AbstractBridge}, @@ -37,13 +36,12 @@ Return a `Bool` indicating whether the bridges of type `BT` support bridging constraint types that the bridge implements. """ function MOI.supports_constraint( - ::Type{<:AbstractBridge}, - ::Type{<:MOI.AbstractFunction}, - ::Type{<:MOI.AbstractSet}, + @nospecialize(BT::Type{<:AbstractBridge}), + @nospecialize(F::Type{<:MOI.AbstractFunction}), + @nospecialize(S::Type{<:MOI.AbstractSet}), ) return false end -@specialize """ concrete_bridge_type( diff --git a/src/Bridges/Constraint/single_bridge_optimizer.jl b/src/Bridges/Constraint/single_bridge_optimizer.jl index 5839ac7c1a..496447f25e 100644 --- a/src/Bridges/Constraint/single_bridge_optimizer.jl +++ b/src/Bridges/Constraint/single_bridge_optimizer.jl @@ -105,9 +105,9 @@ function MOI.Bridges.supports_bridging_constrained_variable( end function MOI.Bridges.supports_bridging_constraint( - ::SingleBridgeOptimizer{BT}, - F::Type{<:MOI.AbstractFunction}, - S::Type{<:MOI.AbstractSet}, + @nospecialize(b::SingleBridgeOptimizer{BT}), + @nospecialize(F::Type{<:MOI.AbstractFunction}), + @nospecialize(S::Type{<:MOI.AbstractSet}), ) where {BT} return MOI.supports_constraint(BT, F, S) end diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index f20530cbee..8061bafbd2 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -149,46 +149,45 @@ function _reset_bridge_graph(b::LazyBridgeOptimizer) return end -@nospecialize """ _variable_nodes(b::LazyBridgeOptimizer, ::Type{BT}) where {BT} Return the list of `VariableNode` that would be added if `BT` is used in `b`. """ function _variable_nodes( - b::LazyBridgeOptimizer, - ::Type{BT}, -) where {BT<:AbstractBridge} + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(BT::Type{<:AbstractBridge}), +) return map(added_constrained_variable_types(BT)) do (S,) return node(b, S)::VariableNode end end -@specialize -@nospecialize """ _constraint_nodes(b::LazyBridgeOptimizer, ::Type{BT}) where {BT} Return the list of `ConstraintNode` that would be added if `BT` is used in `b`. """ function _constraint_nodes( - b::LazyBridgeOptimizer, - ::Type{BT}, -) where {BT<:AbstractBridge} + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(BT::Type{<:AbstractBridge}), +) return ConstraintNode[ node(b, F, S) for (F, S) in added_constraint_types(BT) ] end -@specialize -@nospecialize """ _edge(b::LazyBridgeOptimizer, index::Int, BT::Type{<:AbstractBridge}) Return the `Edge` or `ObjectiveEdge` in the hyper-graph associated with the bridge `BT`, where `index` is the index of `BT` in the list of bridges. """ -function _edge(b::LazyBridgeOptimizer, index::Int, BT::Type{<:AbstractBridge}) +function _edge( + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(index::Int), + @nospecialize(BT::Type{<:AbstractBridge}), +) return Edge( index, _variable_nodes(b, BT), @@ -196,7 +195,6 @@ function _edge(b::LazyBridgeOptimizer, index::Int, BT::Type{<:AbstractBridge}) bridging_cost(BT), ) end -@specialize # Method for objective bridges because they produce ObjectiveEdge. function _edge( @@ -310,9 +308,9 @@ end Return the `ConstraintNode` associated with constraint `F`-in-`S` in `b`. """ function node( - b::LazyBridgeOptimizer, - F::Type{<:MOI.AbstractFunction}, - S::Type{<:MOI.AbstractSet}, + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(F::Type{<:MOI.AbstractFunction}), + @nospecialize(S::Type{<:MOI.AbstractSet}), ) # If we support the constraint type, the node is 0. if MOI.supports_constraint(b.model, F, S) @@ -382,14 +380,12 @@ function _bridge_types( return b.variable_bridge_types end -@nospecialize function _bridge_types( - b::LazyBridgeOptimizer, - ::Type{<:Constraint.AbstractBridge}, + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(BT::Type{<:Constraint.AbstractBridge}), ) return b.constraint_bridge_types end -@specialize function _bridge_types( b::LazyBridgeOptimizer, @@ -398,20 +394,21 @@ function _bridge_types( return b.objective_bridge_types end -@nospecialize """ add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) Enable the use of the bridges of type `BT` by `b`. """ -function add_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) +function add_bridge( + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(BT::Type{<:AbstractBridge}), +) if !has_bridge(b, BT) push!(_bridge_types(b, BT), BT) _reset_bridge_graph(b) end return end -@specialize """ remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) @@ -432,16 +429,17 @@ function remove_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) return end -@nospecialize """ has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge}) Return a `Bool` indicating whether the bridges of type `BT` are used by `b`. """ -function has_bridge(b::LazyBridgeOptimizer, BT::Type{<:AbstractBridge})::Bool +function has_bridge( + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(BT::Type{<:AbstractBridge}), +)::Bool return findfirst(isequal(BT), _bridge_types(b, BT)) !== nothing end -@specialize # It only bridges when the constraint is not supporting, hence the name "Lazy" function is_bridged(b::LazyBridgeOptimizer, S::Type{<:MOI.AbstractScalarSet}) diff --git a/src/Test/Test.jl b/src/Test/Test.jl index 7bf33793db..18e8d5d0a2 100644 --- a/src/Test/Test.jl +++ b/src/Test/Test.jl @@ -499,17 +499,15 @@ function _test_attribute_value_type( return end -@nospecialize function _test_attribute_value_type( - model::MOI.ModelLike, - attribute::MOI.AbstractConstraintAttribute, - ci::MOI.ConstraintIndex, + @nospecialize(model::MOI.ModelLike), + @nospecialize(attribute::MOI.AbstractConstraintAttribute), + @nospecialize(ci::MOI.ConstraintIndex), ) T = MOI.attribute_value_type(attribute) @test @inferred(T, MOI.get(model, attribute, ci)) isa T return end -@specialize function _test_attribute_value_type( model::MOI.ModelLike, diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 170e69ef5e..62125a41eb 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -302,15 +302,13 @@ function MOI.is_valid(model::AbstractModel, ci::MOI.ConstraintIndex) return MOI.is_valid(constraints(model, ci), ci) end -@nospecialize function MOI.supports_constraint( - model::AbstractModel, - ::Type{F}, - ::Type{S}, -) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet} + @nospecialize(model::AbstractModel), + @nospecialize(F::Type{<:MOI.AbstractFunction}), + @nospecialize(S::Type{<:MOI.AbstractSet}), +) return MOI.supports_constraint(model.constraints, F, S) end -@specialize function MOI.add_constraint( model::AbstractModel, diff --git a/src/constraints.jl b/src/constraints.jl index bf29723a31..e98ad116b4 100644 --- a/src/constraints.jl +++ b/src/constraints.jl @@ -4,7 +4,6 @@ # Use of this source code is governed by an MIT-style license that can be found # in the LICENSE.md file or at https://opensource.org/licenses/MIT. -@nospecialize """ supports_constraint( model::ModelLike, @@ -19,13 +18,12 @@ supported in specific circumstances, for example, `F`-in-`S` constraints cannot combined with another type of constraint, it should still return `true`. """ function supports_constraint( - ::ModelLike, - ::Type{<:AbstractFunction}, - ::Type{<:AbstractSet}, + @nospecialize(::ModelLike), + @nospecialize(F::Type{<:AbstractFunction}), + @nospecialize(S::Type{<:AbstractSet}), ) return false end -@specialize """ struct UnsupportedConstraint{F<:AbstractFunction,S<:AbstractSet} <: UnsupportedError From a2f9b6e422e997262fae072d045232f197f52800 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Sat, 6 Sep 2025 15:28:07 +1200 Subject: [PATCH 3/3] Update --- src/Bridges/lazy_bridge_optimizer.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index 8061bafbd2..62041b3d90 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -156,7 +156,7 @@ Return the list of `VariableNode` that would be added if `BT` is used in `b`. """ function _variable_nodes( @nospecialize(b::LazyBridgeOptimizer), - @nospecialize(BT::Type{<:AbstractBridge}), + @nospecialize(BT), ) return map(added_constrained_variable_types(BT)) do (S,) return node(b, S)::VariableNode @@ -170,7 +170,7 @@ Return the list of `ConstraintNode` that would be added if `BT` is used in `b`. """ function _constraint_nodes( @nospecialize(b::LazyBridgeOptimizer), - @nospecialize(BT::Type{<:AbstractBridge}), + @nospecialize(BT), ) return ConstraintNode[ node(b, F, S) for (F, S) in added_constraint_types(BT) @@ -251,7 +251,10 @@ end Return the `VariableNode` associated with set `S` in `b`. """ -function node(b::LazyBridgeOptimizer, S::Type{<:MOI.AbstractSet}) +function node( + @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(S::Type{<:MOI.AbstractSet}), +) # If we support the set, the node is 0. if ( S <: MOI.AbstractScalarSet && @@ -400,7 +403,7 @@ end Enable the use of the bridges of type `BT` by `b`. """ function add_bridge( - @nospecialize(b::LazyBridgeOptimizer), + @nospecialize(b::LazyBridgeOptimizer), @nospecialize(BT::Type{<:AbstractBridge}), ) if !has_bridge(b, BT)