Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve test coverage #3870

Merged
merged 2 commits into from
Nov 5, 2024
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
7 changes: 3 additions & 4 deletions src/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -465,11 +465,10 @@ function constraint_by_name end

function constraint_by_name(model::GenericModel, name::String)
index = MOI.get(backend(model), MOI.ConstraintIndex, name)
if index isa Nothing
if index === nothing
return nothing
else
return constraint_ref_with_index(model, index)
end
return constraint_ref_with_index(model, index)
end

function constraint_by_name(
Expand All @@ -479,7 +478,7 @@ function constraint_by_name(
::Type{S},
) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
index = MOI.get(backend(model), MOI.ConstraintIndex{F,S}, name)
if index isa Nothing
if index === nothing
return nothing
end
return constraint_ref_with_index(model, index)
Expand Down
6 changes: 2 additions & 4 deletions src/nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -632,15 +632,13 @@ function jump_function(model::GenericModel, expr::MOI.Nonlinear.Expression)
)
elseif node.type == MOI.Nonlinear.NODE_MOI_VARIABLE
V(model, MOI.VariableIndex(node.index))
elseif node.type == MOI.Nonlinear.NODE_PARAMETER
NonlinearParameter(model, node.index)
elseif node.type == MOI.Nonlinear.NODE_SUBEXPRESSION
NonlinearExpression(model, node.index)
elseif node.type == MOI.Nonlinear.NODE_VALUE
expr.values[node.index]
else
# node.type == MOI.Nonlinear.NODE_COMPARISON
# node.type == MOI.Nonlinear.NODE_LOGIC
# node.type == MOI.Nonlinear.NODE_PARAMETER
# node.type == MOI.Nonlinear.NODE_SUBEXPRESSION
error("Unsupported node")
end
end
Expand Down
11 changes: 8 additions & 3 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,15 @@ Base.transpose(x::AbstractJuMPScalar) = x
Base.conj(x::GenericVariableRef) = x
# Can remove the following code once == overloading is removed

function LinearAlgebra.issymmetric(x::Matrix{T}) where {T<:_JuMPTypes}
(n = size(x, 1)) == size(x, 2) || return false
function LinearAlgebra.issymmetric(x::Matrix{<:_JuMPTypes})
n = size(x, 1)
if n != size(x, 2)
return false
end
for i in 1:n, j in (i+1):n
isequal(x[i, j], x[j, i]) || return false
if !isequal(x[i, j], x[j, i])
return false
end
end
return true
end
Expand Down
18 changes: 16 additions & 2 deletions test/test_constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ function _test_constraint_name_util(ModelType, VariableRefType)
MOI.EqualTo{Float64},
)
set_name(con, "kon")
@test constraint_by_name(model, "con") isa Nothing
@test constraint_by_name(model, "con") === nothing
_test_constraint_name_util(
con,
"kon",
Expand All @@ -646,7 +646,7 @@ function _test_constraint_name_util(ModelType, VariableRefType)
)
set_name(con, "con")
@test_throws err("con") constraint_by_name(model, "con")
@test constraint_by_name(model, "kon") isa Nothing
@test constraint_by_name(model, "kon") === nothing
set_name(kon, "kon")
_test_constraint_name_util(
con,
Expand Down Expand Up @@ -2157,4 +2157,18 @@ function test_hermitian_shape()
return
end

function test_constraint_by_name()
model = Model()
@variable(model, x)
@constraint(model, c, 2x <= 1)
@test constraint_by_name(model, "c") === c
@test constraint_by_name(model, "d") === nothing
F, S1, S2 = AffExpr, MOI.LessThan{Float64}, MOI.GreaterThan{Float64}
@test constraint_by_name(model, "c", F, S1) === c
@test constraint_by_name(model, "c", F, S2) === nothing
@test constraint_by_name(model, "d", F, S1) === nothing
@test constraint_by_name(model, "d", F, S2) === nothing
return
end

end # module
16 changes: 16 additions & 0 deletions test/test_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,7 @@ function test_optimize_not_called_warning()
end
@variable(model, x >= 0)
@constraint(model, c, 2x <= 1)
@test_throws OptimizeNotCalled value(x)
optimize!(model)
set_start_value(x, 0.0)
@test_logs (:warn,) (@test_throws OptimizeNotCalled objective_value(model))
Expand Down Expand Up @@ -1348,4 +1349,19 @@ function test_iterate_scalar()
return
end

function test_optimizer_index()
model = Model() do
inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
return MOI.Utilities.MockOptimizer(inner)
end
@variable(model, x)
@test_throws(
ErrorException(
"There is no `optimizer_index` as the optimizer is not synchronized with the cached model. Call `MOIU.attach_optimizer(model)` to synchronize it.",
),
optimizer_index(x),
)
return
end

end # module TestModels
12 changes: 12 additions & 0 deletions test/test_nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1122,4 +1122,16 @@ function test_error_legacy_parameter_constructor()
return
end

function test_promote_type()
F = GenericNonlinearExpr{GenericVariableRef{Int}}
G = GenericNonlinearExpr{GenericVariableRef{Float64}}
@test_throws(
ErrorException(
"Unable to promote two different types of nonlinear expression",
),
MA.promote_operation(+, F, G),
)
return
end

end # module
29 changes: 24 additions & 5 deletions test/test_operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,21 @@ function test_extension_operator_warn(
if ModelType <: Model
@test model.operator_counter == 0
end
# Triggers the increment of operator_counter since sum(x) has more than 50 terms
@test_expression(sum(x) + 2x[1])
if ModelType <: Model
# The following check verifies that this test covers the code incrementing `operator_counter`
@test model.operator_counter == 1
lhs = sum(x)
rhs = 2 * x[1]
for i in 1:20_001
# Triggers the increment of operator_counter since lhs has more than
# 50 terms
if i == 20_001 && ModelType <: Model
@test_logs (:warn,) lhs + rhs
else
lhs + rhs
end
if ModelType <: Model
# The following check verifies that this test covers the code
# incrementing `operator_counter`
@test model.operator_counter == i
end
end
return
end
Expand Down Expand Up @@ -723,4 +733,13 @@ function test_hermitian_and_symmetric()
return
end

function test_is_symmetric()
model = Model()
@variable(model, x[1:3])
@test !LinearAlgebra.issymmetric([x[1] x[2]; x[3] x[3]])
@test !LinearAlgebra.issymmetric([x[1] x[2]])
@test LinearAlgebra.issymmetric([x[1] x[2]; x[2] x[3]])
return
end

end
4 changes: 2 additions & 2 deletions test/test_variable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ function test_extension_variable_name(
@variable(model, x)
_test_variable_name_util(x, "x")
set_name(x, "y")
@test variable_by_name(model, "x") isa Nothing
@test variable_by_name(model, "x") === nothing
_test_variable_name_util(x, "y")
y = @variable(model, base_name = "y")
err(name) = ErrorException("Multiple variables have the name $name.")
Expand All @@ -386,7 +386,7 @@ function test_extension_variable_name(
_test_variable_name_util(y, "x")
set_name(x, "x")
@test_throws err("x") variable_by_name(model, "x")
@test variable_by_name(model, "y") isa Nothing
@test variable_by_name(model, "y") === nothing
set_name(y, "y")
_test_variable_name_util(x, "x")
_test_variable_name_util(y, "y")
Expand Down
Loading