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

Fix error message if NonlinearExpression is mixed with new NL API #3741

Merged
merged 6 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
18 changes: 18 additions & 0 deletions src/nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct GenericNonlinearExpr{V<:AbstractVariableRef} <: AbstractJuMPScalar
) where {V<:AbstractVariableRef}
for arg in args
_throw_if_not_real(arg)
_throw_if_legacy(arg)
end
return new{V}(head, Any[a for a in args])
end
Expand All @@ -97,11 +98,28 @@ struct GenericNonlinearExpr{V<:AbstractVariableRef} <: AbstractJuMPScalar
) where {V<:AbstractVariableRef}
for arg in args
_throw_if_not_real(arg)
_throw_if_legacy(arg)
end
return new{V}(head, args)
end
end

_throw_if_legacy(::Any) = nothing

function _throw_if_legacy(arg::Union{NonlinearExpression,NonlinearParameter})
return error(
"Cannot create a nonlinear expression that mixes features from " *
"both the legacy (macros beginning with `@NL`) and new " *
"(`NonlinearExpr`) nonlinear interfaces. You must use one or " *
"the other. Got: $arg",
)
end

# This method is necessary to catch errors in an expression like p * x where
# p is a nonlinear parameter.
variable_ref_type(::NonlinearParameter) = GenericVariableRef{Float64}
variable_ref_type(::NonlinearExpression) = GenericVariableRef{Float64}

variable_ref_type(::Type{GenericNonlinearExpr}, ::Any) = nothing

function variable_ref_type(::Type{GenericNonlinearExpr}, x::AbstractJuMPScalar)
Expand Down
68 changes: 36 additions & 32 deletions test/test_nlp_expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -371,26 +371,6 @@ function test_extension_recursion_stackoverflow(
return
end

function test_nlparameter_interaction()
model = Model()
@variable(model, x)
@NLparameter(model, p == 1)
e = x + p
@test e isa GenericNonlinearExpr
@test string(e) == "x + ($p)"
return
end

function test_nlexpression_interaction()
model = Model()
@variable(model, x)
@NLexpression(model, expr, sin(x))
e = x + expr
odow marked this conversation as resolved.
Show resolved Hide resolved
@test e isa GenericNonlinearExpr
@test string(e) == "x + ($expr)"
return
end

function test_nlobjective_with_nlexpr()
model = Model()
@variable(model, x)
Expand All @@ -414,18 +394,6 @@ function test_nlconstraint_with_nlexpr()
return
end

function test_jump_function_nonlinearexpr()
model = Model()
@variable(model, x)
@NLparameter(model, p == 1)
@NLexpression(model, expr1, sin(p + x))
@NLexpression(model, expr2, sin(expr1))
nlp = nonlinear_model(model)
@test string(jump_function(model, nlp[index(expr1)])) == "sin(($p) + $x)"
@test string(jump_function(model, nlp[index(expr2)])) == "sin($expr1)"
return
end

function test_constraint_object()
model = Model()
@variable(model, x)
Expand Down Expand Up @@ -1092,4 +1060,40 @@ function test_error_nonlinear_expr_complex_constructor()
return
end

function test_error_legacy_expression_constructor()
model = Model()
@variable(model, x)
@NLexpression(model, arg, x^3)
err = ErrorException(
"Cannot create a nonlinear expression that mixes features from " *
"both the legacy (macros beginning with `@NL`) and new " *
"(`NonlinearExpr`) nonlinear interfaces. You must use one or " *
"the other. Got: $arg",
)
@test_throws err GenericNonlinearExpr(:*, Any[x, arg])
@test_throws err GenericNonlinearExpr(:*, x, arg)
@test_throws err (x * arg)
@test_throws err (arg * x)
return
end

function test_error_legacy_parameter_constructor()
model = Model()
@variable(model, x)
@NLparameter(model, p == 1)
err = ErrorException(
"Cannot create a nonlinear expression that mixes features from " *
"both the legacy (macros beginning with `@NL`) and new " *
"(`NonlinearExpr`) nonlinear interfaces. You must use one or " *
"the other. Got: $p",
)
@test_throws err GenericNonlinearExpr(:*, Any[x, p])
@test_throws err GenericNonlinearExpr(:*, Any[p, x])
@test_throws err GenericNonlinearExpr(:*, x, p)
@test_throws err GenericNonlinearExpr(:*, p, x)
@test_throws err (x * p)
@test_throws err (p * x)
return
end

end # module
Loading