diff --git a/src/nlp.jl b/src/nlp.jl index 53e72f23438..64f87b75a08 100644 --- a/src/nlp.jl +++ b/src/nlp.jl @@ -3,6 +3,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. +_throw_if_legacy_error(::Any) = nothing + """ nonlinear_model( model::GenericModel; @@ -209,6 +211,33 @@ struct NonlinearParameter <: AbstractJuMPScalar index::Int end +function check_belongs_to_model(arg::NonlinearParameter, model::AbstractModel) + return arg.model === model +end + +variable_ref_type(arg::NonlinearParameter) = variable_ref_type(arg.model) + +function _throw_if_legacy_error(p::NonlinearParameter) + return error( + """ + Cannot mix a legacy NonlinearParameter with the new nonlinear API. + + Got: $p + + To update, replace calls to: + ```julia + @NLparameter(model, p == 1) + ``` + with + ```julia + @variable(model, p in Parameter(1)) + ``` + """, + ) +end + +moi_function(p::NonlinearParameter) = _throw_if_legacy_error(p) + function MOI.Nonlinear.parse_expression( model::MOI.Nonlinear.Model, expr::MOI.Nonlinear.Expression, @@ -313,6 +342,26 @@ struct NonlinearExpression <: AbstractJuMPScalar index::Int end +function check_belongs_to_model(arg::NonlinearExpression, model::AbstractModel) + return arg.model === model +end + +variable_ref_type(arg::NonlinearExpression) = variable_ref_type(arg.model) + +function _throw_if_legacy_error(arg::NonlinearExpression) + return error( + """ + Cannot mix a legacy NonlinearExpression with the new nonlinear API. + + Got: $arg + + To update, replace all calls to `@NLexpression` with `@expression`. + """, + ) +end + +moi_function(arg::NonlinearExpression) = _throw_if_legacy_error(arg) + function MOI.Nonlinear.parse_expression( model::MOI.Nonlinear.Model, expr::MOI.Nonlinear.Expression, diff --git a/src/nlp_expr.jl b/src/nlp_expr.jl index bbbdf6c11ee..53e62fc8110 100644 --- a/src/nlp_expr.jl +++ b/src/nlp_expr.jl @@ -87,6 +87,7 @@ struct GenericNonlinearExpr{V<:AbstractVariableRef} <: AbstractJuMPScalar ) where {V<:AbstractVariableRef} for arg in args _throw_if_not_real(arg) + _throw_if_legacy_error(arg) end return new{V}(head, Any[a for a in args]) end @@ -97,6 +98,7 @@ struct GenericNonlinearExpr{V<:AbstractVariableRef} <: AbstractJuMPScalar ) where {V<:AbstractVariableRef} for arg in args _throw_if_not_real(arg) + _throw_if_legacy_error(arg) end return new{V}(head, args) end diff --git a/test/test_nlp_expr.jl b/test/test_nlp_expr.jl index 23ba19c781e..a92d624462e 100644 --- a/test/test_nlp_expr.jl +++ b/test/test_nlp_expr.jl @@ -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 - @test e isa GenericNonlinearExpr - @test string(e) == "x + ($expr)" - return -end - function test_nlobjective_with_nlexpr() model = Model() @variable(model, x) @@ -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) @@ -1092,4 +1060,55 @@ 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 mix a legacy NonlinearExpression with the new nonlinear API. + + Got: $arg + + To update, replace all calls to `@NLexpression` with `@expression`. + """, + ) + @test_throws err @objective(model, Min, arg) + @test_throws err @constraint(model, arg <= 0) + @test_throws err @constraint(model, arg in MOI.LessThan(0.0)) + @test_throws err moi_function(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 mix a legacy NonlinearParameter with the new nonlinear API. + + Got: $p + + To update, replace calls to: + ```julia + @NLparameter(model, p == 1) + ``` + with + ```julia + @variable(model, p in Parameter(1)) + ``` + """, + ) + @test_throws err @objective(model, Min, p) + @test_throws err @constraint(model, p <= 0) + @test_throws err @constraint(model, p in MOI.LessThan(0.0)) + @test_throws err moi_function(p) + @test_throws err x * p + @test_throws err p * x + return +end + end # module