From 65111b41ef63b8e97c728851877cbd3867581329 Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 2 Mar 2021 16:03:18 +1300 Subject: [PATCH 1/2] Fix inference issue in MOIU.Model --- src/Utilities/model.jl | 44 +++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 20d30ed0f9..4dde80e9e7 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -550,7 +550,7 @@ single_variable_flag(::Type{<:MOI.Semiinteger}) = 0x80 # If a set is added here, a line should be added in # `MOI.delete(::AbstractModel, ::MOI.VariableIndex)` -function flag_to_set_type(flag::UInt8, T::Type) +function flag_to_set_type(flag::UInt8, ::Type{T}) where {T} if flag == 0x1 return MOI.EqualTo{T} elseif flag == 0x2 @@ -565,28 +565,46 @@ function flag_to_set_type(flag::UInt8, T::Type) return MOI.ZeroOne elseif flag == 0x40 return MOI.Semicontinuous{T} - elseif flag == 0x80 - return MOI.Semiinteger{T} else - # $flag would print it in decimal - error("Invalid flag `$(sprint(show, flag))`.") + @assert flag == 0x80 + return MOI.Semiinteger{T} end end +# Julia doesn't infer `S1` correctly, so we use a function barrier to improve +# inference. +function _throw_if_lower_bound_set(variable, S2, mask, T) + S1 = flag_to_set_type(mask, T) + throw(MOI.LowerBoundAlreadySet{S1,S2}(variable)) + return +end + function throw_if_lower_bound_set(variable, S2, mask, T) - flag = single_variable_flag(S2) - if !iszero(flag & LOWER_BOUND_MASK) && !iszero(mask & LOWER_BOUND_MASK) - S1 = flag_to_set_type(mask & LOWER_BOUND_MASK, T) - throw(MOI.LowerBoundAlreadySet{S1,S2}(variable)) + lower_mask = mask & LOWER_BOUND_MASK + if iszero(lower_mask) + return # No lower bound set. + elseif iszero(single_variable_flag(S2) & LOWER_BOUND_MASK) + return # S2 isn't related to the lower bound. end + return _throw_if_lower_bound_set(variable, S2, lower_mask, T) +end + +# Julia doesn't infer `S1` correctly, so we use a function barrier to improve +# inference. +function _throw_if_upper_bound_set(variable, S2, mask, T) + S1 = flag_to_set_type(mask, T) + throw(MOI.UpperBoundAlreadySet{S1,S2}(variable)) + return end function throw_if_upper_bound_set(variable, S2, mask, T) - flag = single_variable_flag(S2) - if !iszero(flag & UPPER_BOUND_MASK) && !iszero(mask & UPPER_BOUND_MASK) - S1 = flag_to_set_type(mask & UPPER_BOUND_MASK, T) - throw(MOI.UpperBoundAlreadySet{S1,S2}(variable)) + upper_mask = mask & UPPER_BOUND_MASK + if iszero(upper_mask) + return # No upper bound set. + elseif iszero(single_variable_flag(S2) & UPPER_BOUND_MASK) + return # S2 isn't related to the upper bound. end + return _throw_if_upper_bound_set(variable, S2, upper_mask, T) end # Sets setting lower bound: From 89cb0a0fb96872ea0b01db435a7e6d4685fa7259 Mon Sep 17 00:00:00 2001 From: odow Date: Tue, 2 Mar 2021 17:32:01 +1300 Subject: [PATCH 2/2] Fix test --- test/Utilities/model.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Utilities/model.jl b/test/Utilities/model.jl index 5c0cabfe72..fa7c24ed80 100644 --- a/test/Utilities/model.jl +++ b/test/Utilities/model.jl @@ -102,9 +102,8 @@ end @testset "Setting lower/upper bound twice" begin @testset "flag_to_set_type" begin - err = ErrorException("Invalid flag `0x11`.") T = Int - @test_throws err MOIU.flag_to_set_type(0x11, T) + @test_throws AssertionError MOIU.flag_to_set_type(0x11, T) @test MOIU.flag_to_set_type(0x10, T) == MOI.Integer @test MOIU.flag_to_set_type(0x20, T) == MOI.ZeroOne end