Nonlinear Modeling
More information can be found in the Nonlinear section of the manual.
MathOptInterface.Nonlinear
— ModuleNonlinear
The Nonlinear submodule is experimental. Until this message is removed, breaking changes may be introduced in any minor or patch release of MathOptInterface.
MathOptInterface.Nonlinear.Model
— TypeModel()
The core datastructure for representing a nonlinear optimization problem.
It has the following fields:
objective::Union{Nothing,Expression}
: holds the nonlinear objective function, if one exists, otherwisenothing
.expressions::Vector{Expression}
: a vector of expressions in the model.constraints::OrderedDict{ConstraintIndex,Constraint}
: a map fromConstraintIndex
to the correspondingConstraint
. AnOrderedDict
is used instead of aVector
to support constraint deletion.parameters::Vector{Float64}
: holds the current values of the parameters.operators::OperatorRegistry
: stores the operators used in the model.
Expressions
MathOptInterface.Nonlinear.ExpressionIndex
— TypeExpressionIndex
An index to a nonlinear expression that is returned by add_expression
.
Given data::Model
and ex::ExpressionIndex
, use data[ex]
to retrieve the corresponding Expression
.
MathOptInterface.Nonlinear.add_expression
— Functionadd_expression(model::Model, expr)::ExpressionIndex
Parse expr
into a Expression
and add to model
. Returns an ExpressionIndex
that can be interpolated into other input expressions.
expr
must be a type that is supported by parse_expression
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model();
julia> x = MOI.VariableIndex(1);
julia> ex = MOI.Nonlinear.add_expression(model, :($x^2 + 1))
MathOptInterface.Nonlinear.ExpressionIndex(1)
julia> MOI.Nonlinear.set_objective(model, :(sqrt($ex)))
Parameters
MathOptInterface.Nonlinear.ParameterIndex
— TypeParameterIndex
An index to a nonlinear parameter that is returned by add_parameter
. Given data::Model
and p::ParameterIndex
, use data[p]
to retrieve the current value of the parameter and data[p] = value
to set a new value.
MathOptInterface.Nonlinear.add_parameter
— Functionadd_parameter(model::Model, value::Float64)::ParameterIndex
Add a new parameter to model
with the default value value
. Returns a ParameterIndex
that can be interpolated into other input expressions and used to modify the value of the parameter.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model()
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
0 constraints
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> p = MOI.Nonlinear.add_parameter(model, 1.2)
MathOptInterface.Nonlinear.ParameterIndex(1)
julia> c = MOI.Nonlinear.add_constraint(model, :($x^2 - $p), MOI.LessThan(0.0))
MathOptInterface.Nonlinear.ConstraintIndex(1)
Objectives
MathOptInterface.Nonlinear.set_objective
— Functionset_objective(model::Model, obj)::Nothing
Parse obj
into a Expression
and set as the objective function of model
.
obj
must be a type that is supported by parse_expression
.
To remove the objective, pass nothing
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model()
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
0 constraints
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> MOI.Nonlinear.set_objective(model, :($x^2 + 1))
julia> MOI.Nonlinear.set_objective(model, x)
julia> MOI.Nonlinear.set_objective(model, nothing)
Constraints
MathOptInterface.Nonlinear.ConstraintIndex
— TypeConstraintIndex
An index to a nonlinear constraint that is returned by add_constraint
.
Given data::Model
and c::ConstraintIndex
, use data[c]
to retrieve the corresponding Constraint
.
MathOptInterface.Nonlinear.add_constraint
— Functionadd_constraint(
model::Model,
func,
set::Union{
MOI.GreaterThan{Float64},
MOI.LessThan{Float64},
MOI.Interval{Float64},
MOI.EqualTo{Float64},
},
)
Parse func
and set
into a Constraint
and add to model
. Returns a ConstraintIndex
that can be used to delete the constraint or query solution information.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model();
julia> x = MOI.VariableIndex(1);
julia> c = MOI.Nonlinear.add_constraint(model, :($x^2), MOI.LessThan(1.0))
MathOptInterface.Nonlinear.ConstraintIndex(1)
MathOptInterface.Nonlinear.delete
— Functiondelete(model::Model, c::ConstraintIndex)::Nothing
Delete the constraint index c
from model
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model()
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
0 constraints
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> c = MOI.Nonlinear.add_constraint(model, :($x^2), MOI.LessThan(1.0))
MathOptInterface.Nonlinear.ConstraintIndex(1)
julia> model
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
1 constraint
julia> MOI.Nonlinear.delete(model, c)
julia> model
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
0 constraints
User-defined operators
MathOptInterface.Nonlinear.OperatorRegistry
— TypeOperatorRegistry()
Create a new OperatorRegistry
to store and evaluate univariate and multivariate operators.
MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS
— ConstantDEFAULT_UNIVARIATE_OPERATORS
The list of univariate operators that are supported by default.
Example
julia> import MathOptInterface as MOI
julia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS
73-element Vector{Symbol}:
:+
:-
:abs
:sign
:sqrt
:cbrt
:abs2
:inv
:log
:log10
⋮
:airybi
:airyaiprime
:airybiprime
:besselj0
:besselj1
:bessely0
:bessely1
:erfcx
:dawson
MathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS
— ConstantDEFAULT_MULTIVARIATE_OPERATORS
The list of multivariate operators that are supported by default.
Example
julia> import MathOptInterface as MOI
julia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS
9-element Vector{Symbol}:
:+
:-
:*
:^
:/
:ifelse
:atan
:min
:max
MathOptInterface.Nonlinear.register_operator
— Functionregister_operator(
model::Model,
op::Symbol,
nargs::Int,
f::Function,
[∇f::Function],
[∇²f::Function],
)
Register the user-defined operator op
with nargs
input arguments in model
.
Univariate functions
f(x::T)::T
must be a function that takes a single input argumentx
and returns the function evaluated atx
. If∇f
and∇²f
are not provided,f
must support anyReal
input typeT
.∇f(x::T)::T
is a function that takes a single input argumentx
and returns the first derivative off
with respect tox
. If∇²f
is not provided,∇f
must support anyReal
input typeT
.∇²f(x::T)::T
is a function that takes a single input argumentx
and returns the second derivative off
with respect tox
.
Multivariate functions
f(x::T...)::T
must be a function that takes anargs
input argumentsx
and returns the function evaluated atx
. If∇f
and∇²f
are not provided,f
must support anyReal
input typeT
.∇f(g::AbstractVector{T}, x::T...)::T
is a function that takes a cache vectorg
of lengthlength(x)
, and fills each elementg[i]
with the partial derivative off
with respect tox[i]
.∇²f(H::AbstractMatrix, x::T...)::T
is a function that takes a matrixH
and fills the lower-triangular componentsH[i, j]
with the Hessian off
with respect tox[i]
andx[j]
fori >= j
.
Notes for multivariate Hessians
H
hassize(H) == (length(x), length(x))
, but you must not access elementsH[i, j]
fori > j
.H
is dense, but you do not need to fill structural zeros.
MathOptInterface.Nonlinear.register_operator_if_needed
— Functionregister_operator_if_needed(
registry::OperatorRegistry,
op::Symbol,
nargs::Int,
f::Function;
)
Similar to register_operator
, but this function warns if the function is not registered, and skips silently if it already is.
MathOptInterface.Nonlinear.assert_registered
— Functionassert_registered(registry::OperatorRegistry, op::Symbol, nargs::Int)
Throw an error if op
is not registered in registry
with nargs
arguments.
MathOptInterface.Nonlinear.check_return_type
— Functioncheck_return_type(::Type{T}, ret::S) where {T,S}
Overload this method for new types S
to throw an informative error if a user-defined function returns the type S
instead of T
.
MathOptInterface.Nonlinear.eval_univariate_function
— Functioneval_univariate_function(
registry::OperatorRegistry,
op::Symbol,
x::T,
) where {T}
Evaluate the operator op(x)::T
, where op
is a univariate function in registry
.
MathOptInterface.Nonlinear.eval_univariate_gradient
— Functioneval_univariate_gradient(
registry::OperatorRegistry,
op::Symbol,
x::T,
) where {T}
Evaluate the first-derivative of the operator op(x)::T
, where op
is a univariate function in registry
.
MathOptInterface.Nonlinear.eval_univariate_hessian
— Functioneval_univariate_hessian(
registry::OperatorRegistry,
op::Symbol,
x::T,
) where {T}
Evaluate the second-derivative of the operator op(x)::T
, where op
is a univariate function in registry
.
MathOptInterface.Nonlinear.eval_multivariate_function
— Functioneval_multivariate_function(
registry::OperatorRegistry,
op::Symbol,
x::AbstractVector{T},
) where {T}
Evaluate the operator op(x)::T
, where op
is a multivariate function in registry
.
MathOptInterface.Nonlinear.eval_multivariate_gradient
— Functioneval_multivariate_gradient(
registry::OperatorRegistry,
op::Symbol,
g::AbstractVector{T},
x::AbstractVector{T},
) where {T}
Evaluate the gradient of operator g .= ∇op(x)
, where op
is a multivariate function in registry
.
MathOptInterface.Nonlinear.eval_multivariate_hessian
— Functioneval_multivariate_hessian(
registry::OperatorRegistry,
op::Symbol,
H::AbstractMatrix,
x::AbstractVector{T},
) where {T}
Evaluate the Hessian of operator ∇²op(x)
, where op
is a multivariate function in registry
.
The Hessian is stored in the lower-triangular part of the matrix H
.
Implementations of the Hessian operators will not fill structural zeros. Therefore, before calling this function you should pre-populate the matrix H
with 0
.
MathOptInterface.Nonlinear.eval_logic_function
— Functioneval_logic_function(
registry::OperatorRegistry,
op::Symbol,
lhs::T,
rhs::T,
)::Bool where {T}
Evaluate (lhs op rhs)::Bool
, where op
is a logic operator in registry
.
MathOptInterface.Nonlinear.eval_comparison_function
— Functioneval_comparison_function(
registry::OperatorRegistry,
op::Symbol,
lhs::T,
rhs::T,
)::Bool where {T}
Evaluate (lhs op rhs)::Bool
, where op
is a comparison operator in registry
.
Automatic-differentiation backends
MathOptInterface.Nonlinear.Evaluator
— TypeEvaluator(
model::Model,
backend::AbstractAutomaticDifferentiation,
ordered_variables::Vector{MOI.VariableIndex},
)
Create Evaluator
, a subtype of MOI.AbstractNLPEvaluator
, from Model
.
MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation
— TypeAbstractAutomaticDifferentiation
An abstract type for extending Evaluator
.
MathOptInterface.Nonlinear.ExprGraphOnly
— TypeExprGraphOnly() <: AbstractAutomaticDifferentiation
The default implementation of AbstractAutomaticDifferentiation
. The only supported feature is :ExprGraph
.
MathOptInterface.Nonlinear.SparseReverseMode
— TypeSparseReverseMode() <: AbstractAutomaticDifferentiation
An implementation of AbstractAutomaticDifferentiation
that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.
Data-structure
MathOptInterface.Nonlinear.Node
— Typestruct Node
type::NodeType
index::Int
parent::Int
end
A single node in a nonlinear expression tree. Used by Expression
.
See the MathOptInterface documentation for information on how the nodes and values form an expression tree.
MathOptInterface.Nonlinear.NodeType
— TypeNodeType
An enum describing the possible node types. Each Node
has a .index
field, which should be interpreted as follows:
NODE_CALL_MULTIVARIATE
: the index intooperators.multivariate_operators
NODE_CALL_UNIVARIATE
: the index intooperators.univariate_operators
NODE_LOGIC
: the index intooperators.logic_operators
NODE_COMPARISON
: the index intooperators.comparison_operators
NODE_MOI_VARIABLE
: the value ofMOI.VariableIndex(index)
in the user's space of the model.NODE_VARIABLE
: the 1-based index of the internal vectorNODE_VALUE
: the index into the.values
field ofExpression
NODE_PARAMETER
: the index intodata.parameters
NODE_SUBEXPRESSION
: the index intodata.expressions
MathOptInterface.Nonlinear.Expression
— Typestruct Expression
nodes::Vector{Node}
values::Vector{Float64}
end
The core type that represents a nonlinear expression. See the MathOptInterface documentation for information on how the nodes and values form an expression tree.
MathOptInterface.Nonlinear.Constraint
— Typestruct Constraint
expression::Expression
set::Union{
MOI.LessThan{Float64},
MOI.GreaterThan{Float64},
MOI.EqualTo{Float64},
MOI.Interval{Float64},
}
end
A type to hold information relating to the nonlinear constraint f(x) in S
, where f(x)
is defined by .expression
, and S
is .set
.
MathOptInterface.Nonlinear.adjacency_matrix
— Functionadjacency_matrix(nodes::Vector{Node})
Compute the sparse adjacency matrix describing the parent-child relationships in nodes
.
The element (i, j)
is true
if there is an edge from node[j]
to node[i]
. Since we get a column-oriented matrix, this gives us a fast way to look up the edges leaving any node (that is, the children).
MathOptInterface.Nonlinear.parse_expression
— Functionparse_expression(data::Model, input)::Expression
Parse input
into a Expression
.
parse_expression(
data::Model,
expr::Expression,
input::Any,
parent_index::Int,
)::Expression
Parse input
into a Expression
, and add it to expr
as a child of expr.nodes[parent_index]
. Existing subexpressions and parameters are stored in data
.
You can extend parsing support to new types of objects by overloading this method with a different type on input::Any
.
MathOptInterface.Nonlinear.convert_to_expr
— Functionconvert_to_expr(data::Model, expr::Expression)
Convert the Expression
expr
into a Julia Expr
.
- subexpressions are represented by a
ExpressionIndex
object. - parameters are represented by a
ParameterIndex
object. - variables are represented by an
MOI.VariableIndex
object.
convert_to_expr(
evaluator::Evaluator,
expr::Expression;
moi_output_format::Bool,
)
Convert the Expression
expr
into a Julia Expr
.
If moi_output_format = true
:
- subexpressions will be converted to Julia
Expr
and substituted into the output expression. - the current value of each parameter will be interpolated into the expression
- variables will be represented in the form
x[MOI.VariableIndex(i)]
If moi_output_format = false
:
- subexpressions will be represented by a
ExpressionIndex
object. - parameters will be represented by a
ParameterIndex
object. - variables will be represented by an
MOI.VariableIndex
object.
To use moi_output_format = true
, you must have first called MOI.initialize
with :ExprGraph
as a requested feature.
MathOptInterface.Nonlinear.ordinal_index
— Functionordinal_index(evaluator::Evaluator, c::ConstraintIndex)::Int
Return the 1-indexed value of the constraint index c
in evaluator
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Nonlinear.Model()
A Nonlinear.Model with:
0 objectives
0 parameters
0 expressions
0 constraints
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> c1 = MOI.Nonlinear.add_constraint(model, :($x^2), MOI.LessThan(1.0))
MathOptInterface.Nonlinear.ConstraintIndex(1)
julia> c2 = MOI.Nonlinear.add_constraint(model, :($x^2), MOI.LessThan(1.0))
MathOptInterface.Nonlinear.ConstraintIndex(2)
julia> evaluator = MOI.Nonlinear.Evaluator(model)
Nonlinear.Evaluator with available features:
* :ExprGraph
julia> MOI.initialize(evaluator, Symbol[])
julia> MOI.Nonlinear.ordinal_index(evaluator, c2) # Returns 2
2
julia> MOI.Nonlinear.delete(model, c1)
julia> evaluator = MOI.Nonlinear.Evaluator(model)
Nonlinear.Evaluator with available features:
* :ExprGraph
julia> MOI.initialize(evaluator, Symbol[])
julia> MOI.Nonlinear.ordinal_index(evaluator, c2) # Returns 1
1