diff --git a/test/Containers/test_tables.jl b/test/Containers/test_tables.jl index 9496c6370e1..b9c55ac7128 100644 --- a/test/Containers/test_tables.jl +++ b/test/Containers/test_tables.jl @@ -85,7 +85,7 @@ function JuMP.build_variable(::Function, info::VariableInfo, _::_Mock) return _MockVariable(ScalarVariable(info)) end -function JuMP.add_variable(model::Model, x::_MockVariable, name::String) +function JuMP.add_variable(model::GenericModel, x::_MockVariable, name::String) variable = add_variable(model, x.var, name) return _MockVariableRef(variable) end diff --git a/test/test_constraint.jl b/test/test_constraint.jl index a7e114df0ba..0461e39d181 100644 --- a/test/test_constraint.jl +++ b/test/test_constraint.jl @@ -32,19 +32,20 @@ function test_extension_VariableIndex_constraints( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() @variable(m, x) # x <= 10.0 doesn't translate to a SingleVariable constraint because # the LHS is first subtracted to form x - 10.0 <= 0. - @constraint(m, cref, x in MOI.LessThan(10.0)) + @constraint(m, cref, x in MOI.LessThan{T}(10)) c = constraint_object(cref) @test c.func == x - @test c.set == MOI.LessThan(10.0) + @test c.set == MOI.LessThan(T(10)) @variable(m, y[1:2]) - @constraint(m, cref2[i = 1:2], y[i] in MOI.LessThan(float(i))) + @constraint(m, cref2[i = 1:2], y[i] in MOI.LessThan{T}(i)) c = constraint_object(cref2[1]) @test c.func == y[1] - @test c.set == MOI.LessThan(1.0) + @test c.set == MOI.LessThan(T(1)) return end @@ -83,27 +84,29 @@ function test_extension_AffExpr_scalar_constraints( ModelType = Model, VariableRefType = VariableRef, ) + AffExprType = JuMP.GenericAffExpr{value_type(ModelType),VariableRefType} model = ModelType() + T = value_type(ModelType) @variable(model, x) cref = @constraint(model, 2x <= 10) @test "" == @inferred name(cref) set_name(cref, "c") - _test_constraint_name_util(cref, "c", AffExpr, MOI.LessThan{Float64}) + _test_constraint_name_util(cref, "c", AffExprType, MOI.LessThan{Float64}) c = constraint_object(cref) @test isequal_canonical(c.func, 2x) - @test c.set == MOI.LessThan(10.0) + @test c.set == MOI.LessThan(T(10)) cref = @constraint(model, 3x + 1 ≥ 10) c = constraint_object(cref) @test isequal_canonical(c.func, 3x) - @test c.set == MOI.GreaterThan(9.0) + @test c.set == MOI.GreaterThan(T(9)) cref = @constraint(model, 1 == -x) c = constraint_object(cref) - @test isequal_canonical(c.func, 1.0x) - @test c.set == MOI.EqualTo(-1.0) + @test isequal_canonical(c.func, one(T) * x) + @test c.set == MOI.EqualTo(-one(T)) cref = @constraint(model, 2 == 1) c = constraint_object(cref) @test isequal_canonical(c.func, zero(AffExpr)) - @test c.set == MOI.EqualTo(-1.0) + @test c.set == MOI.EqualTo(-one(T)) return end @@ -111,6 +114,7 @@ function test_extension_AffExpr_vectorized_constraints( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) err = ErrorException( @@ -119,16 +123,16 @@ function test_extension_AffExpr_vectorized_constraints( "sides of the constraint must have the same dimension.", ) @test_throws_strip err @constraint(model, [x, 2x] in MOI.EqualTo(1.0)) - T = typeof([x, 2x]) + VT = typeof([x, 2x]) err = ErrorException( - "Operation `sub_mul` between `$T` and `$Int` is not " * + "Operation `sub_mul` between `$VT` and `$Int` is not " * "allowed. This most often happens when you write a constraint like " * "`x >= y` where `x` is an array and `y` is a constant. Use the " * "broadcast syntax `x .- y >= 0` instead.", ) @test_throws err @constraint(model, [x, 2x] == 1) err = ErrorException( - "Operation `sub_mul` between `$Int` and `$T` is not " * + "Operation `sub_mul` between `$Int` and `$VT` is not " * "allowed. This most often happens when you write a constraint like " * "`x >= y` where `x` is a constant and `y` is an array. Use the " * "broadcast syntax `x .- y >= 0` instead.", @@ -140,10 +144,10 @@ function test_extension_AffExpr_vectorized_constraints( end cref = @constraint(model, [x, 2x] .== [1 - x, 3]) c = constraint_object.(cref) - @test isequal_canonical(c[1].func, 2.0x) - @test c[1].set == MOI.EqualTo(1.0) - @test isequal_canonical(c[2].func, 2.0x) - @test c[2].set == MOI.EqualTo(3.0) + @test isequal_canonical(c[1].func, 2x) + @test c[1].set == MOI.EqualTo(T(1)) + @test isequal_canonical(c[2].func, 2x) + @test c[2].set == MOI.EqualTo(T(3)) return end @@ -151,6 +155,7 @@ function test_extension_AffExpr_vectorized_interval_constraints( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:2]) err = ErrorException( @@ -158,12 +163,12 @@ function test_extension_AffExpr_vectorized_interval_constraints( "scalar constraint. Did you mean to use the dot comparison " * "operators `l .<= f(x) .<= u` instead?", ) - b = [5.0, 6.0] + b = T[5, 6] @test_throws_strip err @constraint(model, b <= x <= b) cref = @constraint(model, b .<= x .<= b) c = constraint_object.(cref) for i in 1:2 - @test isequal_canonical(c[i].func, 1.0 * x[i]) + @test isequal_canonical(c[i].func, 1 * x[i]) @test c[i].set == MOI.Interval(b[i], b[i]) end return @@ -173,6 +178,7 @@ function test_extension_AffExpr_vector_constraints( ModelType = Model, VariableRefType = VariableRef, ) + AffExprType = JuMP.GenericAffExpr{value_type(ModelType),VariableRefType} model = ModelType() cref = @constraint(model, [1, 2] in MOI.Zeros(2)) c = constraint_object(cref) @@ -222,19 +228,22 @@ function test_extension_two_sided_constraints( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) + AffExprType = JuMP.GenericAffExpr{T,VariableRefType} m = ModelType() @variable(m, x) @variable(m, y) - @constraint(m, cref, 1.0 <= x + y + 1.0 <= 2.0) - _test_constraint_name_util(cref, "cref", AffExpr, MOI.Interval{Float64}) + @constraint(m, cref, 1 <= x + y + 1 <= 2) + _test_constraint_name_util(cref, "cref", AffExprType, MOI.Interval{T}) c = constraint_object(cref) @test isequal_canonical(c.func, x + y) - @test c.set == MOI.Interval(0.0, 1.0) - cref = @constraint(m, 2x - y + 2.0 ∈ MOI.Interval(-1.0, 1.0)) + @test c.set == + MOI.Interval(zero(value_type(ModelType)), one(value_type(ModelType))) + cref = @constraint(m, 2x - y + T(2) ∈ MOI.Interval(-one(T), one(T))) @test "" == @inferred name(cref) c = constraint_object(cref) @test isequal_canonical(c.func, 2x - y) - @test c.set == MOI.Interval(-3.0, -1.0) + @test c.set == MOI.Interval(-3one(T), -one(T)) return end @@ -242,18 +251,19 @@ function test_extension_broadcasted_constraint_eq( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() @variable(m, x[1:2]) - A = [1.0 2.0; 3.0 4.0] - b = [4.0, 5.0] + A = T[1 2; 3 4] + b = T[4, 5] cref = @constraint(m, A * x .== b) @test (2,) == @inferred size(cref) c1 = constraint_object(cref[1]) @test isequal_canonical(c1.func, x[1] + 2x[2]) - @test c1.set == MOI.EqualTo(4.0) + @test c1.set == MOI.EqualTo(T(4)) c2 = constraint_object(cref[2]) @test isequal_canonical(c2.func, 3x[1] + 4x[2]) - @test c2.set == MOI.EqualTo(5.0) + @test c2.set == MOI.EqualTo(T(5)) return end @@ -261,9 +271,10 @@ function test_extension_broadcasted_constraint_leq( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() @variable(m, x[1:2, 1:2]) - UB = [1.0 2.0; 3.0 4.0] + UB = T[1 2; 3 4] cref = @constraint(m, x .+ 1 .<= UB) @test (2, 2) == @inferred size(cref) for i in 1:2 @@ -280,11 +291,12 @@ function test_extension_broadcasted_two_sided_constraint( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() @variable(m, x[1:2]) @variable(m, y[1:2]) - l = [1.0, 2.0] - u = [3.0, 4.0] + l = T[1, 2] + u = T[3, 4] cref = @constraint(m, l .<= x + y .+ 1 .<= u) @test (2,) == @inferred size(cref) for i in 1:2 @@ -318,6 +330,7 @@ function test_extension_quadexpr_constraints( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) @variable(model, y) @@ -325,12 +338,12 @@ function test_extension_quadexpr_constraints( cref = @constraint(model, x^2 + x <= 1) c = constraint_object(cref) @test isequal_canonical(c.func, x^2 + x) - @test c.set == MOI.LessThan(1.0) + @test c.set == MOI.LessThan(one(T)) - cref = @constraint(model, y * x - 1.0 == 0.0) + cref = @constraint(model, y * x - 1 == 0) c = constraint_object(cref) @test isequal_canonical(c.func, x * y) - @test c.set == MOI.EqualTo(1.0) + @test c.set == MOI.EqualTo(one(T)) cref = @constraint( model, @@ -362,6 +375,7 @@ function test_extension_indicator_constraint( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, a, Bin) @variable(model, b, Bin) @@ -374,7 +388,7 @@ function test_extension_indicator_constraint( ] c = constraint_object(cref) @test c.func == [a, x + 2y] - @test c.set == MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(1.0)) + @test c.set == MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(one(T))) end for cref in [ @constraint(model, !b => {2x + y <= 1}) @@ -385,7 +399,7 @@ function test_extension_indicator_constraint( ] c = constraint_object(cref) @test c.func == [b, 2x + y] - @test c.set == MOI.Indicator{MOI.ACTIVATE_ON_ZERO}(MOI.LessThan(1.0)) + @test c.set == MOI.Indicator{MOI.ACTIVATE_ON_ZERO}(MOI.LessThan(one(T))) end err = ErrorException( "In `@constraint(model, !(a, b) => {x <= 1})`: Invalid binary variable expression `!(a, b)` for indicator constraint.", @@ -414,6 +428,8 @@ function test_extension_SDP_constraint( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) + AffExprType = JuMP.GenericAffExpr{T,VariableRefType} m = ModelType() @variable(m, x) @variable(m, y) @@ -434,7 +450,7 @@ function test_extension_SDP_constraint( _test_constraint_name_util( sym_ref, "sym_ref", - Vector{AffExpr}, + Vector{AffExprType}, MOI.PositiveSemidefiniteConeTriangle, ) c = constraint_object(sym_ref) @@ -448,7 +464,7 @@ function test_extension_SDP_constraint( _test_constraint_name_util( cref, "cref", - Vector{AffExpr}, + Vector{AffExprType}, MOI.PositiveSemidefiniteConeSquare, ) c = constraint_object(cref) @@ -464,7 +480,7 @@ function test_extension_SDP_constraint( _test_constraint_name_util( iref[i], "iref[$i]", - Vector{AffExpr}, + Vector{AffExprType}, MOI.PositiveSemidefiniteConeSquare, ) c = constraint_object(iref[i]) @@ -478,7 +494,7 @@ function test_extension_SDP_constraint( @constraint(m, con_d, 0 <= LinearAlgebra.Diagonal([x, y]), PSDCone()) c = constraint_object(con_d) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test iszero(c.func[2]) @test iszero(c.func[3]) @@ -492,7 +508,7 @@ function test_extension_SDP_constraint( PSDCone() ) c = constraint_object(con_d_sym) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test iszero(c.func[2]) @test isequal_canonical(c.func[3], 1y) @@ -505,7 +521,7 @@ function test_extension_SDP_constraint( PSDCone() ) c = constraint_object(con_td) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test isequal_canonical(c.func[2], 1z) @test isequal_canonical(c.func[3], 1w) @@ -520,7 +536,7 @@ function test_extension_SDP_constraint( PSDCone(), ) c = constraint_object(con_td_sym) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test isequal_canonical(c.func[2], 1w) @test isequal_canonical(c.func[3], 1y) @@ -533,7 +549,7 @@ function test_extension_SDP_constraint( PSDCone() ) c = constraint_object(con_ut) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test iszero(c.func[2]) @test isequal_canonical(c.func[3], 1y) @@ -547,7 +563,7 @@ function test_extension_SDP_constraint( PSDCone() ) c = constraint_object(con_lt) - @test c.func isa Vector{GenericAffExpr{Float64,VariableRefType}} + @test c.func isa Vector{AffExprType} @test isequal_canonical(c.func[1], 1x) @test isequal_canonical(c.func[2], 1z) @test iszero(c.func[3]) @@ -560,12 +576,13 @@ function test_extension_SDP_errors( ModelType = Model, VariableRefType = VariableRef, ) + AffExprType = JuMP.GenericAffExpr{value_type(ModelType),VariableRefType} model = ModelType() @variable(model, x) @variable(model, y) @variable(model, z) @variable(model, w) - aff_str = "$(GenericAffExpr{Float64,VariableRefType})" + aff_str = "$AffExprType" err = ErrorException( "In `@constraint(model, [x 1; 1 -y] >= [1 x; x -2], PSDCone(), unknown_kw = 1)`:" * " Unrecognized constraint building format. Tried to invoke " * @@ -694,6 +711,7 @@ function test_extension_nonsensical_SDP_constraint( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() @test_throws_strip( ErrorException( @@ -705,7 +723,7 @@ function test_extension_nonsensical_SDP_constraint( @test_throws MethodError @variable(m, notone[1:5, 2:6], PSD) @test_throws MethodError @variable(m, oneD[1:5], PSD) @test_throws MethodError @variable(m, threeD[1:5, 1:5, 1:5], PSD) - Y = [1.0 2.0; 2.1 3.0] + Y = T[1 2; 21//10 3] function _ErrorException(m) return ErrorException( "In `$m`: Non-symmetric bounds, integrality or starting values " * @@ -1155,12 +1173,13 @@ function test_extension_abstractarray_vector_constraint( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:2, 1:2]) c = @constraint(model, view(x, 1:4) in SOS1()) obj = constraint_object(c) @test obj.func == x[1:4] - @test obj.set == MOI.SOS1([1.0, 2.0, 3.0, 4.0]) + @test obj.set == MOI.SOS1(T[1, 2, 3, 4]) return end @@ -1168,13 +1187,14 @@ function test_extension_constraint_inference( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) foo(model, x) = @constraint(model, 2x <= 1) c = @inferred foo(model, x) obj = constraint_object(c) @test obj.func == 2x - @test obj.set == MOI.LessThan(1.0) + @test obj.set == MOI.LessThan(one(T)) return end @@ -1469,10 +1489,13 @@ function test_extension_HermitianPSDCone_errors( ModelType = Model, VariableRefType = VariableRef, ) + AffExprType = + JuMP.GenericAffExpr{Complex{value_type(ModelType)},VariableRefType} model = ModelType() + T = value_type(ModelType) @variable(model, x) @variable(model, y) - aff_str = "$(GenericAffExpr{ComplexF64,VariableRefType})" + aff_str = "$AffExprType" err = ErrorException( "In `@constraint(model, H in HermitianPSDCone(), unknown_kw = 1)`:" * " Unrecognized constraint building format. Tried to invoke " * @@ -1597,6 +1620,9 @@ function test_semiinteger() end function test_symmetric_vectorize_allocations() + if VERSION < v"1.8" + return + end model = Model() @variable(model, x[1:2]) C = SparseArrays.sparse([0 1; 0 0]) diff --git a/test/test_expr.jl b/test/test_expr.jl index 9ce7514acbb..f17b977b75b 100644 --- a/test/test_expr.jl +++ b/test/test_expr.jl @@ -195,8 +195,9 @@ function test_extension_linear_terms_empty_AffExpr( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) k = 0 - aff = zero(GenericAffExpr{Float64,VariableRefType}) + aff = zero(GenericAffExpr{T,VariableRefType}) @test length(linear_terms(aff)) == 0 for (coeff, var) in linear_terms(aff) k += 1 @@ -233,14 +234,15 @@ function test_extension_coefficient_QuadExpr_VariableRefType( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() x = @variable(m, x) y = @variable(m, y) z = @variable(m, z) - quad = @expression(m, 6.0 * x^2 + 5.0 * x * y + 2.0 * y + 3.0 * x) - @test coefficient(quad, x) == 3.0 - @test coefficient(quad, y) == 2.0 - @test coefficient(quad, z) == 0.0 + quad = @expression(m, T(6) * x^2 + T(5) * x * y + T(2) * y + T(3) * x) + @test coefficient(quad, x) == T(3) + @test coefficient(quad, y) == T(2) + @test coefficient(quad, z) == T(0) return end @@ -248,15 +250,16 @@ function test_extension_coefficient_QuadExpr_VariableRefType_VariableRefType( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() x = @variable(m, x) y = @variable(m, y) z = @variable(m, z) - quad = @expression(m, 6.0 * x^2 + 5.0 * x * y + 2.0 * y + 3.0 * x) - @test coefficient(quad, x, y) == 5.0 - @test coefficient(quad, x, x) == 6.0 + quad = @expression(m, T(6) * x^2 + T(5) * x * y + T(2) * y + T(3) * x) + @test coefficient(quad, x, y) == T(5) + @test coefficient(quad, x, x) == T(6) @test coefficient(quad, x, y) == coefficient(quad, y, x) - @test coefficient(quad, z, z) == 0.0 + @test coefficient(quad, z, z) == T(0) return end @@ -264,31 +267,32 @@ function test_extension_MA_add_mul( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) @variable(model, y) # MA.add_mul!!(ex::Number, c::Number, x::GenericAffExpr) - aff = MA.add_mul!!(1.0, 2.0, GenericAffExpr(1.0, x => 1.0)) - @test isequal_canonical(aff, GenericAffExpr(3.0, x => 2.0)) + aff = MA.add_mul!!(1, 2, GenericAffExpr(T(1), x => T(1))) + @test isequal_canonical(aff, GenericAffExpr(T(3), x => T(2))) # MA.add_mul!!(ex::Number, c::Number, x::GenericQuadExpr) with c == 0 - QuadExprType = GenericQuadExpr{Float64,VariableRefType} - quad = MA.add_mul!!(2.0, 0.0, QuadExprType()) - @test isequal_canonical(quad, convert(QuadExprType, 2.0)) + QuadExprType = GenericQuadExpr{T,VariableRefType} + quad = MA.add_mul!!(2, 0, QuadExprType()) + @test isequal_canonical(quad, convert(QuadExprType, 2)) # MA.add_mul!!(ex::Number, c::VariableRef, x::VariableRef)" - @test_expression_with_string MA.add_mul(5.0, x, y) "x*y + 5" - @test_expression_with_string MA.add_mul!!(5.0, x, y) "x*y + 5" + @test_expression_with_string MA.add_mul(5, x, y) "x*y + 5" + @test_expression_with_string MA.add_mul!!(5, x, y) "x*y + 5" # MA.add_mul!!(ex::Number, c::T, x::T) where T<:GenericAffExpr" begin - @test_expression_with_string MA.add_mul(1.0, 2x, x + 1) "2 x² + 2 x + 1" - @test_expression_with_string MA.add_mul!!(1.0, 2x, x + 1) "2 x² + 2 x + 1" + @test_expression_with_string MA.add_mul(1, 2x, x + 1) "2 x² + 2 x + 1" + @test_expression_with_string MA.add_mul!!(1, 2x, x + 1) "2 x² + 2 x + 1" # MA.add_mul!!(ex::Number, c::GenericAffExpr{C,V}, x::V) where {C,V}" begin - @test_expression_with_string MA.add_mul(1.0, 2x, x) "2 x² + 1" - @test_expression_with_string MA.add_mul!!(1.0, 2x, x) "2 x² + 1" + @test_expression_with_string MA.add_mul(1, 2x, x) "2 x² + 1" + @test_expression_with_string MA.add_mul!!(1, 2x, x) "2 x² + 1" # MA.add_mul!!(ex::Number, c::GenericQuadExpr, x::Number)" begin - @test_expression_with_string MA.add_mul(0.0, x^2, 1.0) "x²" - @test_expression_with_string MA.add_mul!!(0.0, x^2, 1.0) "x²" + @test_expression_with_string MA.add_mul(0, x^2, 1) "x²" + @test_expression_with_string MA.add_mul!!(0, x^2, 1) "x²" # MA.add_mul!!(ex::Number, c::GenericQuadExpr, x::Number) with c == 0" begin - @test_expression_with_string MA.add_mul(0.0, x^2, 0.0) "0" - @test_expression_with_string MA.add_mul!!(0.0, x^2, 0.0) "0" + @test_expression_with_string MA.add_mul(0, x^2, 0) "0" + @test_expression_with_string MA.add_mul!!(0, x^2, 0) "0" # MA.add_mul!!(aff::AffExpr,c::VariableRef,x::AffExpr)" begin @test_expression_with_string MA.add_mul(2x, x, x + 1) "x² + 3 x" @test_expression_with_string MA.add_mul!!(2x, x, x + 1) "x² + 3 x" diff --git a/test/test_macros.jl b/test/test_macros.jl index 991736357d4..1303adf61c4 100644 --- a/test/test_macros.jl +++ b/test/test_macros.jl @@ -30,12 +30,16 @@ function JuMP.build_variable( return NewVariable(info) end -function JuMP.add_variable(model::Model, v::NewVariable, name::String = "") +function JuMP.add_variable( + model::GenericModel, + v::NewVariable, + name::String = "", +) return add_variable(model, ScalarVariable(v.info), name * "_normal_add") end function JuMP.add_variable( - model::Model, + model::GenericModel, v::VariablesConstrainedOnCreation{ MOI.SecondOrderCone, VectorShape, @@ -103,7 +107,11 @@ end const MyVariableTuple{S,T,U,V} = Tuple{VariableInfo{S,T,U,V},Int,Int} -function JuMP.add_variable(model::Model, v::MyVariableTuple, name::String = "") +function JuMP.add_variable( + model::GenericModel, + v::MyVariableTuple, + name::String = "", +) model.ext[:names][v] = name return v end @@ -346,53 +354,56 @@ function test_extension_check_constraint_basics( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) + AffExprType = GenericAffExpr{T,VariableRefType} m = ModelType() @variable(m, w) @variable(m, x) @variable(m, y) @variable(m, z) - t = 10.0 - cref = @constraint(m, 3x - y == 3.3(w + 2z) + 5) + t = T(10) + α = T(33) / T(10) + cref = @constraint(m, 3x - y == α * (w + 2z) + 5) c = constraint_object(cref) - @test isequal_canonical(c.func, 3 * x - y - 3.3 * w - 6.6 * z) - @test c.set == MOI.EqualTo(5.0) - cref = @constraint(m, 3x - y == (w + 2z) * 3.3 + 5) + @test isequal_canonical(c.func, 3 * x - y - α * w - 2α * z) + @test c.set == MOI.EqualTo(T(5)) + cref = @constraint(m, 3x - y == (w + 2z) * α + 5) c = constraint_object(cref) - @test isequal_canonical(c.func, 3 * x - y - 3.3 * w - 6.6 * z) - @test c.set == MOI.EqualTo(5.0) + @test isequal_canonical(c.func, 3 * x - y - α * w - 2α * z) + @test c.set == MOI.EqualTo(T(5)) cref = @constraint(m, (x + y) / 2 == 1) c = constraint_object(cref) - @test isequal_canonical(c.func, 0.5 * x + 0.5 * y) - @test c.set == MOI.EqualTo(1.0) + @test isequal_canonical(c.func, T(inv(2)) * x + T(inv(2)) * y) + @test c.set == MOI.EqualTo(T(1)) cref = @constraint(m, -1 <= x - y <= t) c = constraint_object(cref) @test isequal_canonical(c.func, x - y) - @test c.set == MOI.Interval(-1.0, t) + @test c.set == MOI.Interval(-T(1), t) cref = @constraint(m, -1 <= x + 1 <= 1) c = constraint_object(cref) @test isequal_canonical(c.func, 1x) - @test c.set == MOI.Interval(-2.0, 0.0) + @test c.set == MOI.Interval(-T(2), T(0)) cref = @constraint(m, -1 <= x <= 1) c = constraint_object(cref) - @test c.func isa GenericAffExpr + @test c.func isa AffExprType @test isequal_canonical(c.func, 1x) - @test c.set == MOI.Interval(-1.0, 1.0) - cref = @constraint(m, -1 <= x <= sum(0.5 for i in 1:2)) + @test c.set == MOI.Interval(-T(1), T(1)) + cref = @constraint(m, -1 <= x <= sum(T(inv(2)) for i in 1:2)) c = constraint_object(cref) - @test c.func isa GenericAffExpr + @test c.func isa AffExprType @test isequal_canonical(c.func, 1x) - @test c.set == MOI.Interval(-1.0, 1.0) + @test c.set == MOI.Interval(-T(1), T(1)) cref = @constraint(m, 1 >= x >= 0) c = constraint_object(cref) - @test c.func isa GenericAffExpr + @test c.func isa AffExprType @test isequal_canonical(c.func, 1x) - @test c.set == MOI.Interval(0.0, 1.0) + @test c.set == MOI.Interval(T(0), T(1)) @test_throws ErrorException @constraint(m, x <= t <= y) @test_throws ErrorException @constraint(m, 0 <= Dict() <= 1) @test_macro_throws ErrorException @constraint(1 <= x <= 2, foo = :bar) @test isequal_canonical( - @expression(m, 3x - y - 3.3(w + 2z) + 5), - 3 * x - y - 3.3 * w - 6.6 * z + 5, + @expression(m, 3x - y - α * (w + 2z) + 5), + 3 * x - y - α * w - T(66) / T(10) * z + 5, ) @test isequal_canonical( @expression(m, quad, (w + 3) * (2x + 1) + 10), @@ -401,7 +412,7 @@ function test_extension_check_constraint_basics( cref = @constraint(m, 3 + 5 * 7 <= 0) c = constraint_object(cref) @test isequal_canonical(c.func, zero(AffExpr)) - @test c.set == MOI.LessThan(-38.0) + @test c.set == MOI.LessThan(-T(38)) return end @@ -409,27 +420,28 @@ function test_extension_Unicode_comparison_operators( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) @variable(model, y) - t = 10.0 + t = T(10) cref = @constraint(model, (x + y) / 2 ≥ 1) c = constraint_object(cref) - @test isequal_canonical(c.func, 0.5 * x + 0.5 * y) - @test c.set == MOI.GreaterThan(1.0) + @test isequal_canonical(c.func, inv(T(2)) * x + inv(T(2)) * y) + @test c.set == MOI.GreaterThan(T(1)) cref = @constraint(model, (x + y) / 2 ≤ 1) c = constraint_object(cref) - @test isequal_canonical(c.func, 0.5 * x + 0.5 * y) - @test c.set == MOI.LessThan(1.0) + @test isequal_canonical(c.func, inv(T(2)) * x + inv(T(2)) * y) + @test c.set == MOI.LessThan(T(1)) cref = @constraint(model, -1 ≤ x - y ≤ t) c = constraint_object(cref) @test isequal_canonical(c.func, x - y) - @test c.set == MOI.Interval(-1.0, t) + @test c.set == MOI.Interval(-T(1), t) cref = @constraint(model, 1 ≥ x ≥ 0) c = constraint_object(cref) @test c.func isa GenericAffExpr @test isequal_canonical(c.func, 1 * x) - @test c.set == MOI.Interval(0.0, 1.0) + @test c.set == MOI.Interval(T(0), T(1)) return end @@ -458,12 +470,13 @@ function test_extension_build_constraint_scalar_inequality( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) con = @build_constraint(3x == 1) @test con isa ScalarConstraint @test isequal_canonical(con.func, 3x) - @test con.set == MOI.EqualTo(1.0) + @test con.set == MOI.EqualTo(T(1)) return end @@ -484,20 +497,21 @@ function test_extension_build_constraint_SOS1( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:3]) con = @build_constraint(x in SOS1()) - con2 = @build_constraint(x in SOS1([4.0, 6.0, 1.0])) + con2 = @build_constraint(x in SOS1(T[4, 6, 1])) @test con isa VectorConstraint @test con.func == x - @test con.set == MOI.SOS1([1.0, 2.0, 3.0]) + @test con.set == MOI.SOS1(T[1, 2, 3]) @test_throws( ErrorException("Weight vector in SOS1 is not of length 3."), - @build_constraint(x in SOS1([1.0])) + @build_constraint(x in SOS1(T[1])) ) @test con2 isa VectorConstraint @test con2.func == x - @test con2.set == MOI.SOS1([4.0, 6.0, 1.0]) + @test con2.set == MOI.SOS1(T[4, 6, 1]) return end @@ -505,20 +519,21 @@ function test_extension_build_constraint_SOS2( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:3]) con = @build_constraint(x in SOS2()) - con2 = @build_constraint(x in SOS2([4.0, 6.0, 1.0])) + con2 = @build_constraint(x in SOS2(T[4, 6, 1])) @test con isa VectorConstraint @test con.func == x - @test con.set == MOI.SOS2([1.0, 2.0, 3.0]) + @test con.set == MOI.SOS2(T[1, 2, 3]) @test_throws( ErrorException("Weight vector in SOS2 is not of length 3."), - @build_constraint(x in SOS2([1.0])) + @build_constraint(x in SOS2(T[1])) ) @test con2 isa VectorConstraint @test con2.func == x - @test con2.set == MOI.SOS2([4.0, 6.0, 1.0]) + @test con2.set == MOI.SOS2(T[4, 6, 1]) return end @@ -526,15 +541,16 @@ function test_extension_build_constraint_broadcast( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:2]) - ub = [1.0, 2.0] + ub = T[1, 2] con = @build_constraint(x .<= ub) @test con isa Vector{<:ScalarConstraint} @test isequal_canonical(con[1].func, 1.0x[1]) @test isequal_canonical(con[2].func, 1.0x[2]) - @test con[1].set == MOI.LessThan(1.0) - @test con[2].set == MOI.LessThan(2.0) + @test con[1].set == MOI.LessThan(T(1)) + @test con[2].set == MOI.LessThan(T(2)) return end diff --git a/test/test_model.jl b/test/test_model.jl index 21e12856b5f..5d495d7cc14 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -554,7 +554,7 @@ function test_set_retrieve_time_limit() end struct DummyExtensionData - model::Model + model::GenericModel end function JuMP.copy_extension_data( data::DummyExtensionData, diff --git a/test/test_objective.jl b/test/test_objective.jl index e2bce0368c4..e5df5a22c08 100644 --- a/test/test_objective.jl +++ b/test/test_objective.jl @@ -92,29 +92,24 @@ function test_extension_objective_affine( ModelType = Model, VariableType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) @objective(model, Min, 2x) @test MIN_SENSE == @inferred objective_sense(model) - @test objective_function_type(model) == GenericAffExpr{Float64,VariableType} + @test objective_function_type(model) == GenericAffExpr{T,VariableType} @test isequal_canonical(objective_function(model), 2x) @test isequal_canonical( 2x, - @inferred objective_function( - model, - GenericAffExpr{Float64,VariableType}, - ) + @inferred objective_function(model, GenericAffExpr{T,VariableType}) ) @objective(model, Max, x + 3x + 1) @test MAX_SENSE == @inferred objective_sense(model) - @test objective_function_type(model) == GenericAffExpr{Float64,VariableType} + @test objective_function_type(model) == GenericAffExpr{T,VariableType} @test isequal_canonical(objective_function(model), 4x + 1) @test isequal_canonical( 4x + 1, - @inferred objective_function( - model, - GenericAffExpr{Float64,VariableType}, - ) + @inferred objective_function(model, GenericAffExpr{T,VariableType}) ) return end @@ -123,23 +118,20 @@ function test_extension_objective_quadratic( ModelType = Model, VariableType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) @objective(model, Min, x^2 + 2x) @test MIN_SENSE == @inferred objective_sense(model) - @test objective_function_type(model) == - GenericQuadExpr{Float64,VariableType} + @test objective_function_type(model) == GenericQuadExpr{T,VariableType} @test isequal_canonical(objective_function(model), x^2 + 2x) @test isequal_canonical( x^2 + 2x, - @inferred objective_function( - model, - GenericQuadExpr{Float64,VariableType}, - ) + @inferred objective_function(model, GenericQuadExpr{T,VariableType}) ) @test_throws InexactError objective_function( model, - GenericAffExpr{Float64,VariableType}, + GenericAffExpr{T,VariableType}, ) return end @@ -158,6 +150,7 @@ function test_extension_objective_sense_as_binnding( ModelType = Model, VariableType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x) sense = MIN_SENSE @@ -165,10 +158,7 @@ function test_extension_objective_sense_as_binnding( @test MIN_SENSE == @inferred objective_sense(model) @test isequal_canonical( 2x, - @inferred objective_function( - model, - GenericAffExpr{Float64,VariableType}, - ) + @inferred objective_function(model, GenericAffExpr{T,VariableType}) ) sense = :Min @test_throws ErrorException @objective(model, sense, 2x) diff --git a/test/test_operator.jl b/test/test_operator.jl index 2a6d3c8fea1..075d8a5d8e8 100644 --- a/test/test_operator.jl +++ b/test/test_operator.jl @@ -70,11 +70,12 @@ function test_extension_promotion( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) m = ModelType() I = Int V = VariableRefType - A = GenericAffExpr{Float64,VariableRefType} - Q = GenericQuadExpr{Float64,VariableRefType} + A = GenericAffExpr{T,VariableRefType} + Q = GenericQuadExpr{T,VariableRefType} @test promote_type(V, I) == A @test promote_type(I, V) == A @test promote_type(A, I) == A @@ -199,7 +200,8 @@ function test_extension_custom_dimension_mismatch( ModelType = Model, VariableRefType = VariableRef, ) - ElemT = MySumType{GenericAffExpr{Float64,VariableRefType}} + T = value_type(ModelType) + ElemT = MySumType{GenericAffExpr{T,VariableRefType}} model = ModelType() @variable(model, Q[1:3, 1:3], PSD) x = [MyType(1), MyType(2), MyType(3)] @@ -211,7 +213,7 @@ function test_extension_custom_dimension_mismatch( @test size(z) == (1, 3) for i in 1:3 # Q is symmetric - a = zero(GenericAffExpr{Float64,VariableRefType}) + a = zero(GenericAffExpr{T,VariableRefType}) a += Q[1, i] a += 2Q[2, i] a += 3Q[3, i] @@ -225,7 +227,8 @@ function test_extension_matrix_multiplication( ModelType = Model, VariableRefType = VariableRef, ) - ElemT = MySumType{GenericAffExpr{Float64,VariableRefType}} + T = value_type(ModelType) + ElemT = MySumType{GenericAffExpr{T,VariableRefType}} model = ModelType() @variable(model, Q[1:3, 1:3], PSD) X = MyType.((1:3)' .+ (1:3)) @@ -350,28 +353,31 @@ function test_extension_basic_operators_variable( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, w) @variable(model, x) @variable(model, y) @variable(model, z) - aff = @inferred 7.1 * x + 2.5 - q = @inferred 2.5 * y * z + aff + β = T(71) / T(10) + aff = @inferred β * x + T(25) / T(10) + q = @inferred T(25) / T(10) * y * z + aff # 2-0 Variable unary @test (+x) === x @test_expression_with_string -x "-x" # 2-1 Variable--Number - @test_expression_with_string w + 4.13 "w + 4.13" - @test_expression_with_string w - 4.13 "w - 4.13" - @test_expression_with_string w * 4.13 "4.13 w" - @test_expression_with_string w / 2.00 "0.5 w" + α = T(413) / T(100) + @test_expression_with_string w + α "w + 4.13" + @test_expression_with_string w - α "w - 4.13" + @test_expression_with_string w * α "4.13 w" + @test_expression_with_string w / T(2) "0.5 w" @test w == w @test_expression_with_string x * y - 1 "x*y - 1" @test_expression_with_string x^2 "x²" @test_expression_with_string x^1 "x" @test_expression_with_string x^0 "1" @test_throws ErrorException x^3 - @test_throws ErrorException x^1.5 + @test_throws ErrorException x^(T(15) / T(10)) # 2-2 Variable--Variable @test_expression_with_string w + x "w + x" @test_expression_with_string w - x "w - x" @@ -385,7 +391,7 @@ function test_extension_basic_operators_variable( @test_expression_with_string z * aff "7.1 z*x + 2.5 z" @test_throws ErrorException z / aff @test_throws MethodError z ≤ aff - @test_expression_with_string 7.1 * x - aff "0 x - 2.5" + @test_expression_with_string β * x - aff "0 x - 2.5" # 2-4 Variable--QuadExpr @test_expression_with_string w + q "2.5 y*z + w + 7.1 x + 2.5" @test_expression_with_string w - q "-2.5 y*z + w - 7.1 x - 2.5" @@ -400,14 +406,15 @@ function test_extension_basic_operators_affexpr( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, w) @variable(model, x) @variable(model, y) @variable(model, z) - aff = @inferred 7.1 * x + 2.5 - aff2 = @inferred 1.2 * y + 1.2 - q = @inferred 2.5 * y * z + aff + aff = @inferred T(71) / T(10) * x + T(25) / T(10) + aff2 = @inferred T(12) / T(10) * y + T(12) / T(10) + q = @inferred T(25) / T(10) * y * z + aff # 3-0 AffExpr unary @test_expression_with_string +aff "7.1 x + 2.5" @test_expression_with_string -aff "-7.1 x - 2.5" diff --git a/test/test_print.jl b/test/test_print.jl index 0bb3ee76d17..42b74c488b8 100644 --- a/test/test_print.jl +++ b/test/test_print.jl @@ -98,7 +98,7 @@ struct CustomIndex end function JuMP.add_constraint( - model::Model, + model::GenericModel, constraint::CustomConstraint, name::String, ) @@ -398,7 +398,7 @@ function test_extension_printing_variable_ref( io_test(MIME("text/latex"), x, "x2") set_name(x, "") @test name(x) == "" - if x isa VariableRef + if x isa GenericVariableRef io_test(MIME("text/plain"), x, "_[1]") io_test(MIME("text/latex"), x, "{\\_}_{1}") else diff --git a/test/test_variable.jl b/test/test_variable.jl index 60d4c3b5e6c..ddb91d39cbf 100644 --- a/test/test_variable.jl +++ b/test/test_variable.jl @@ -51,14 +51,15 @@ function test_extension_variable_no_bound( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, nobounds) @test !has_lower_bound(nobounds) @test !has_upper_bound(nobounds) @test !is_fixed(nobounds) _test_variable_name_util(nobounds, "nobounds") - @test zero(nobounds) isa GenericAffExpr{Float64,VariableRefType} - @test one(nobounds) isa GenericAffExpr{Float64,VariableRefType} + @test zero(nobounds) isa GenericAffExpr{T,VariableRefType} + @test one(nobounds) isa GenericAffExpr{T,VariableRefType} return end @@ -431,17 +432,18 @@ function test_extension_variable_macro_return_type( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() - @variable(model, x[1:3, 1:4, 1:2], start = 0.0) + @variable(model, x[1:3, 1:4, 1:2], start = T(0)) @test typeof(x) == Array{VariableRefType,3} - @test typeof(start_value.(x)) == Array{Float64,3} - @variable(model, y[1:0], start = 0.0) + @test typeof(start_value.(x)) == Array{T,3} + @variable(model, y[1:0], start = T(0)) @test typeof(y) == Vector{VariableRefType} # No type to infer for an empty collection. - @test typeof(start_value.(y)) == Vector{Union{Nothing,Float64}} - @variable(model, z[1:4], start = 0.0) + @test typeof(start_value.(y)) == Vector{Union{Nothing,T}} + @variable(model, z[1:4], start = T(0)) @test typeof(z) == Vector{VariableRefType} - @test typeof(start_value.(z)) == Vector{Float64} + @test typeof(start_value.(z)) == Vector{T} return end @@ -449,12 +451,13 @@ function test_extension_variable_start_value_on_empty( ModelType = Model, VariableRefType = VariableRef, ) + T = value_type(ModelType) model = ModelType() @variable(model, x[1:4, 1:0, 1:3], start = 0) # Array{VariableRef} @variable(model, y[1:4, 2:1, 1:3], start = 0) # DenseAxisArray @variable(model, z[1:4, Set(), 1:3], start = 0) # SparseAxisArray - @test start_value.(x) == Array{Float64}(undef, 4, 0, 3) + @test start_value.(x) == Array{T}(undef, 4, 0, 3) # TODO: Decide what to do here. I don't know if we still need to test this # given broadcast syntax. # @test typeof(start_value(y)) <: DenseAxisArray{Float64}