# Nonlinear Modeling

More information can be found in the Nonlinear Modeling section of the manual.

## Constraints

JuMP.@NLconstraintMacro
@NLconstraint(model::Model, expr)

Add a constraint described by the nonlinear expression expr. See also @constraint. For example:

julia> model = Model();

julia> @variable(model, x)
x

julia> @NLconstraint(model, sin(x) <= 1)
sin(x) - 1.0 ≤ 0

julia> @NLconstraint(model, [i = 1:3], sin(i * x) <= 1 / i)
3-element Vector{NonlinearConstraintRef{ScalarShape}}:
(sin(1.0 * x) - 1.0 / 1.0) - 0.0 ≤ 0
(sin(2.0 * x) - 1.0 / 2.0) - 0.0 ≤ 0
(sin(3.0 * x) - 1.0 / 3.0) - 0.0 ≤ 0
source
JuMP.@NLconstraintsMacro
@NLconstraints(model, args...)

Adds multiple nonlinear constraints to model at once, in the same fashion as the @NLconstraint macro.

The model must be the first argument, and multiple constraints can be added on multiple lines wrapped in a begin ... end block.

The macro returns a tuple containing the constraints that were defined.

Example

julia> model = Model();

julia> @variable(model, x);

julia> @variable(model, y);

julia> @variable(model, t);

julia> @variable(model, z[1:2]);

julia> a = [4, 5];

julia> @NLconstraints(model, begin
t >= sqrt(x^2 + y^2)
[i = 1:2], z[i] <= log(a[i])
end)
((t - sqrt(x ^ 2.0 + y ^ 2.0)) - 0.0 ≥ 0, NonlinearConstraintRef{ScalarShape}[(z - log(4.0)) - 0.0 ≤ 0, (z - log(5.0)) - 0.0 ≤ 0])
source
JuMP.add_nonlinear_constraintFunction
add_nonlinear_constraint(model::Model, expr::Expr)

Add a nonlinear constraint described by the Julia expression ex to model.

This function is most useful if the expression ex is generated programmatically, and you cannot use @NLconstraint.

Notes

• You must interpolate the variables directly into the expression expr.

Example

julia> model = Model();

julia> @variable(model, x);

julia> add_nonlinear_constraint(model, :($(x) +$(x)^2 <= 1))
(x + x ^ 2.0) - 1.0 ≤ 0
source
JuMP.set_nonlinear_dual_start_valueFunction
set_nonlinear_dual_start_value(
model::Model,
start::Union{Nothing,Vector{Float64}},
)

Set the value of the MOI attribute MOI.NLPBlockDualStart.

The start vector corresponds to the Lagrangian duals of the nonlinear constraints, in the order given by all_nonlinear_constraints. That is, you must pass a single start vector corresponding to all of the nonlinear constraints in a single function call; you cannot set the dual start value of nonlinear constraints one-by-one. The example below demonstrates how to use all_nonlinear_constraints to create a mapping between the nonlinear constraint references and the start vector.

Pass nothing to unset a previous start.

Example

julia> model = Model();

julia> @variable(model, x[1:2]);

julia> nl1 = @NLconstraint(model, x <= sqrt(x));

julia> nl2 = @NLconstraint(model, x >= exp(x));

julia> start = Dict(nl1 => -1.0, nl2 => 1.0);

julia> start_vector = [start[con] for con in all_nonlinear_constraints(model)]
2-element Vector{Float64}:
-1.0
1.0

julia> set_nonlinear_dual_start_value(model, start_vector)

julia> nonlinear_dual_start_value(model)
2-element Vector{Float64}:
-1.0
1.0
source

## Expressions

JuMP.@NLexpressionMacro
@NLexpression(args...)

Efficiently build a nonlinear expression which can then be inserted in other nonlinear constraints and the objective. See also [@expression]. For example:

julia> model = Model();

julia> @variable(model, x)
x

julia> @variable(model, y)
y

julia> @NLexpression(model, my_expr, sin(x)^2 + cos(x^2))
subexpression: sin(x) ^ 2.0 + cos(x ^ 2.0)

julia> @NLconstraint(model, my_expr + y >= 5)
(subexpression + y) - 5.0 ≥ 0

julia> @NLobjective(model, Min, my_expr)

Indexing over sets and anonymous expressions are also supported:

julia> @NLexpression(model, my_expr_1[i=1:3], sin(i * x))
3-element Vector{NonlinearExpression}:
subexpression: sin(1.0 * x)
subexpression: sin(2.0 * x)
subexpression: sin(3.0 * x)

julia> my_expr_2 = @NLexpression(model, log(1 + sum(exp(my_expr_1[i]) for i in 1:2)))
subexpression: log(1.0 + (exp(subexpression) + exp(subexpression)))
source
JuMP.@NLexpressionsMacro
@NLexpressions(model, args...)

Adds multiple nonlinear expressions to model at once, in the same fashion as the @NLexpression macro.

The model must be the first argument, and multiple expressions can be added on multiple lines wrapped in a begin ... end block.

The macro returns a tuple containing the expressions that were defined.

Example

julia> model = Model();

julia> @variable(model, x);

julia> @variable(model, y);

julia> @variable(model, z[1:2]);

julia> a = [4, 5];

julia> @NLexpressions(model, begin
my_expr, sqrt(x^2 + y^2)
my_expr_1[i = 1:2], log(a[i]) - z[i]
end)
(subexpression: sqrt(x ^ 2.0 + y ^ 2.0), NonlinearExpression[subexpression: log(4.0) - z, subexpression: log(5.0) - z])
source
JuMP.add_nonlinear_expressionFunction
add_nonlinear_expression(model::Model, expr::Expr)

Add a nonlinear expression expr to model.

This function is most useful if the expression expr is generated programmatically, and you cannot use @NLexpression.

Notes

• You must interpolate the variables directly into the expression expr.

Example

julia> model = Model();

julia> @variable(model, x);

julia> add_nonlinear_expression(model, :($(x) +$(x)^2))
subexpression: x + x ^ 2.0
source

## Objectives

JuMP.@NLobjectiveMacro
@NLobjective(model, sense, expression)

Add a nonlinear objective to model with optimization sense sense. sense must be Max or Min.

Example

julia> model = Model();

julia> @variable(model, x)
x

julia> @NLobjective(model, Max, 2x + 1 + sin(x))

julia> print(model)
Max 2.0 * x + 1.0 + sin(x)
Subject to
source
JuMP.set_nonlinear_objectiveFunction
set_nonlinear_objective(
model::Model,
sense::MOI.OptimizationSense,
expr::Expr,
)

Set the nonlinear objective of model to the expression expr, with the optimization sense sense.

This function is most useful if the expression expr is generated programmatically, and you cannot use @NLobjective.

Notes

• You must interpolate the variables directly into the expression expr.
• You must use MIN_SENSE or MAX_SENSE instead of Min and Max.

Example

julia> model = Model();

julia> @variable(model, x);

julia> set_nonlinear_objective(model, MIN_SENSE, :($(x) +$(x)^2))
source

## Parameters

JuMP.@NLparameterMacro
@NLparameter(model, param == value)

Create and return a nonlinear parameter param attached to the model model with initial value set to value. Nonlinear parameters may be used only in nonlinear expressions.

Example

julia> model = Model();

julia> @NLparameter(model, x == 10)
x == 10.0

julia> value(x)
10.0
@NLparameter(model, value = param_value)

Create and return an anonymous nonlinear parameter param attached to the model model with initial value set to param_value. Nonlinear parameters may be used only in nonlinear expressions.

Example

julia> model = Model();

julia> x = @NLparameter(model, value = 10)
parameter == 10.0

julia> value(x)
10.0
@NLparameter(model, param_collection[...] == value_expr)

Create and return a collection of nonlinear parameters param_collection attached to the model model with initial value set to value_expr (may depend on index sets). Uses the same syntax for specifying index sets as @variable.

Example

julia> model = Model();

julia> @NLparameter(model, y[i = 1:3] == 2 * i)
3-element Vector{NonlinearParameter}:
parameter == 2.0
parameter == 4.0
parameter == 6.0

julia> value(y)
4.0
@NLparameter(model, [...] == value_expr)

Create and return an anonymous collection of nonlinear parameters attached to the model model with initial value set to value_expr (may depend on index sets). Uses the same syntax for specifying index sets as @variable.

Example

julia> model = Model();

julia> y = @NLparameter(model, [i = 1:3] == 2 * i)
3-element Vector{NonlinearParameter}:
parameter == 2.0
parameter == 4.0
parameter == 6.0

julia> value(y)
4.0
source
JuMP.@NLparametersMacro
 @NLparameters(model, args...)

Create and return multiple nonlinear parameters attached to model model, in the same fashion as @NLparameter macro.

The model must be the first argument, and multiple parameters can be added on multiple lines wrapped in a begin ... end block. Distinct parameters need to be placed on separate lines as in the following example.

The macro returns a tuple containing the parameters that were defined.

Example

julia> model = Model();

julia> @NLparameters(model, begin
x == 10
b == 156
end);

julia> value(x)
10.0
source
JuMP.valueMethod
value(p::NonlinearParameter)

Return the current value stored in the nonlinear parameter p.

Example

julia> model = Model();

julia> @NLparameter(model, p == 10)
p == 10.0

julia> value(p)
10.0
source
JuMP.set_valueMethod
set_value(p::NonlinearParameter, v::Number)

Store the value v in the nonlinear parameter p.

Example

julia> model = Model();

julia> @NLparameter(model, p == 0)
p == 0.0

julia> set_value(p, 5)
5

julia> value(p)
5.0
source

## User-defined functions

JuMP.registerFunction
register(
model::Model,
op::Symbol,
dimension::Integer,
f::Function;
autodiff:Bool = false,
)

Register the user-defined function f that takes dimension arguments in model as the symbol op.

The function f must support all subtypes of Real as arguments. Do not assume that the inputs are Float64.

Notes

• For this method, you must explicitly set autodiff = true, because no user-provided gradient function ∇f is given.
• Second-derivative information is only computed if dimension == 1.
• op does not have to be the same symbol as f, but it is generally more readable if it is.

Example

julia> model = Model();

julia> @variable(model, x)
x

julia> f(x::T) where {T<:Real} = x^2
f (generic function with 1 method)

julia> register(model, :foo, 1, f; autodiff = true)

julia> @NLobjective(model, Min, foo(x))
julia> model = Model();

julia> @variable(model, x[1:2])
2-element Vector{VariableRef}:
x
x

julia> g(x::T, y::T) where {T<:Real} = x * y
g (generic function with 1 method)

julia> register(model, :g, 2, g; autodiff = true)

julia> @NLobjective(model, Min, g(x, x))
source
register(
model::Model,
s::Symbol,
dimension::Integer,
f::Function,
∇f::Function;
autodiff:Bool = false,
)

Register the user-defined function f that takes dimension arguments in model as the symbol s. In addition, provide a gradient function ∇f.

The functions fand ∇f must support all subtypes of Real as arguments. Do not assume that the inputs are Float64.

Notes

• If the function f is univariate (i.e., dimension == 1), ∇f must return a number which represents the first-order derivative of the function f.
• If the function f is multi-variate, ∇f must have a signature matching ∇f(g::AbstractVector{T}, args::T...) where {T<:Real}, where the first argument is a vector g that is modified in-place with the gradient.
• If autodiff = true and dimension == 1, use automatic differentiation to compute the second-order derivative information. If autodiff = false, only first-order derivative information will be used.
• s does not have to be the same symbol as f, but it is generally more readable if it is.

Example

julia> model = Model();

julia> @variable(model, x)
x

julia> f(x::T) where {T<:Real} = x^2
f (generic function with 1 method)

julia> ∇f(x::T) where {T<:Real} = 2 * x
∇f (generic function with 1 method)

julia> register(model, :foo, 1, f, ∇f; autodiff = true)

julia> @NLobjective(model, Min, foo(x))
julia> model = Model();

julia> @variable(model, x[1:2])
2-element Vector{VariableRef}:
x
x

julia> g(x::T, y::T) where {T<:Real} = x * y
g (generic function with 1 method)

julia> function ∇g(g::AbstractVector{T}, x::T, y::T) where {T<:Real}
g = y
g = x
return
end
∇g (generic function with 1 method)

julia> register(model, :g, 2, g, ∇g)

julia> @NLobjective(model, Min, g(x, x))
source
register(
model::Model,
s::Symbol,
dimension::Integer,
f::Function,
∇f::Function,
∇²f::Function,
)

Register the user-defined function f that takes dimension arguments in model as the symbol s. In addition, provide a gradient function ∇f and a hessian function ∇²f.

∇f and ∇²f must return numbers corresponding to the first- and second-order derivatives of the function f respectively.

Notes

• Because automatic differentiation is not used, you can assume the inputs are all Float64.
• This method will throw an error if dimension > 1.
• s does not have to be the same symbol as f, but it is generally more readable if it is.

Example

julia> model = Model();

julia> @variable(model, x)
x

julia> f(x::Float64) = x^2
f (generic function with 1 method)

julia> ∇f(x::Float64) = 2 * x
∇f (generic function with 1 method)

julia> ∇²f(x::Float64) = 2.0
∇²f (generic function with 1 method)

julia> register(model, :foo, 1, f, ∇f, ∇²f)

julia> @NLobjective(model, Min, foo(x))

source

## Derivatives

JuMP.NLPEvaluatorFunction
NLPEvaluator(
model::Model,
_differentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation =
MOI.Nonlinear.SparseReverseMode(),
)

Return an MOI.AbstractNLPEvaluator constructed from model

Warning

Before using, you must initialize the evaluator using MOI.initialize.

Experimental

These features may change or be removed in any future version of JuMP.

Pass _differentiation_backend to specify the differentiation backend used to compute derivatives.

source