Nonlinear Modeling
More information can be found in the Nonlinear Modeling section of the manual.
Models
JuMP.nonlinear_model
— Functionnonlinear_model(
model::Model;
force::Bool = false,
)::Union{MOI.Nonlinear.Model,Nothing}
If model
has nonlinear components, return a MOI.Nonlinear.Model
, otherwise return nothing
.
If force
, always return a MOI.Nonlinear.Model
, and if one does not exist for the model, create an empty one.
Constraints
JuMP.@NLconstraint
— Macro@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
JuMP.@NLconstraints
— Macro@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[1] - log(4.0)) - 0.0 ≤ 0, (z[2] - log(5.0)) - 0.0 ≤ 0])
JuMP.num_nonlinear_constraints
— Functionnum_nonlinear_constraints(model::Model)
Returns the number of nonlinear constraints associated with the model
.
JuMP.add_nonlinear_constraint
— Functionadd_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
JuMP.all_nonlinear_constraints
— Functionall_nonlinear_constraints(model::Model)
Return a vector of all nonlinear constraint references in the model in the order they were added to the model.
JuMP.nonlinear_dual_start_value
— Functionnonlinear_dual_start_value(model::Model)
Return the current value of the MOI attribute MOI.NLPBlockDualStart
.
JuMP.set_nonlinear_dual_start_value
— Functionset_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[1] <= sqrt(x[2]));
julia> nl2 = @NLconstraint(model, x[1] >= exp(x[2]));
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
Expressions
JuMP.@NLexpression
— Macro@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[1]: sin(x) ^ 2.0 + cos(x ^ 2.0)
julia> @NLconstraint(model, my_expr + y >= 5)
(subexpression[1] + 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[2]: sin(1.0 * x)
subexpression[3]: sin(2.0 * x)
subexpression[4]: sin(3.0 * x)
julia> my_expr_2 = @NLexpression(model, log(1 + sum(exp(my_expr_1[i]) for i in 1:2)))
subexpression[5]: log(1.0 + (exp(subexpression[2]) + exp(subexpression[3])))
JuMP.@NLexpressions
— Macro@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[1]: sqrt(x ^ 2.0 + y ^ 2.0), NonlinearExpression[subexpression[2]: log(4.0) - z[1], subexpression[3]: log(5.0) - z[2]])
JuMP.NonlinearExpression
— TypeNonlinearExpression <: AbstractJuMPScalar
A struct to represent a nonlinear expression.
Create an expression using @NLexpression
.
JuMP.add_nonlinear_expression
— Functionadd_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[1]: x + x ^ 2.0
Objectives
JuMP.@NLobjective
— Macro@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
JuMP.set_nonlinear_objective
— Functionset_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
orMAX_SENSE
instead ofMin
andMax
.
Example
julia> model = Model();
julia> @variable(model, x);
julia> set_nonlinear_objective(model, MIN_SENSE, :($(x) + $(x)^2))
Parameters
JuMP.@NLparameter
— Macro@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[1] == 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[1] == 2.0
parameter[2] == 4.0
parameter[3] == 6.0
julia> value(y[2])
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[1] == 2.0
parameter[2] == 4.0
parameter[3] == 6.0
julia> value(y[2])
4.0
JuMP.@NLparameters
— Macro @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
JuMP.NonlinearParameter
— TypeNonlinearParameter <: AbstractJuMPScalar
A struct to represent a nonlinear parameter.
Create a parameter using @NLparameter
.
JuMP.value
— Methodvalue(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
JuMP.set_value
— Methodset_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
User-defined functions
JuMP.register
— Functionregister(
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 asf
, 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[1]
x[2]
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[1], x[2]))
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 f
and ∇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 functionf
. - 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 vectorg
that is modified in-place with the gradient. - If
autodiff = true
anddimension == 1
, use automatic differentiation to compute the second-order derivative information. Ifautodiff = false
, only first-order derivative information will be used. s
does not have to be the same symbol asf
, 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[1]
x[2]
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[1] = y
g[2] = x
return
end
∇g (generic function with 1 method)
julia> register(model, :g, 2, g, ∇g)
julia> @NLobjective(model, Min, g(x[1], x[2]))
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 asf
, 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))
Derivatives
JuMP.NLPEvaluator
— FunctionNLPEvaluator(
model::Model,
_differentiation_backend::MOI.Nonlinear.AbstractAutomaticDifferentiation =
MOI.Nonlinear.SparseReverseMode(),
)
Return an MOI.AbstractNLPEvaluator
constructed from model
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.