Nonlinear Modeling
More information can be found in the Nonlinear section of the manual.
MathOptInterface.Nonlinear.Model — Type
Model()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 fromConstraintIndexto the correspondingConstraint. AnOrderedDictis used instead of aVectorto 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 — Type
ExpressionIndexAn 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 — Function
add_expression(model::Model, expr)::ExpressionIndexParse 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> 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 — Type
ParameterIndexAn 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 — Function
add_parameter(model::Model, value::Float64)::ParameterIndexAdd 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> model = MOI.Nonlinear.Model()A Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 0 constraintsjulia> 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 — Function
set_objective(model::Model, obj)::NothingParse 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> model = MOI.Nonlinear.Model()A Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 0 constraintsjulia> 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 — Type
ConstraintIndexAn 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 — Function
add_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> 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 — Function
delete(model::Model, c::ConstraintIndex)::NothingDelete the constraint index c from model.
Example
julia> model = MOI.Nonlinear.Model()A Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 0 constraintsjulia> 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> modelA Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 1 constraintjulia> MOI.Nonlinear.delete(model, c)julia> modelA Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 0 constraintsUser-defined operators
MathOptInterface.Nonlinear.OperatorRegistry — Type
OperatorRegistry()Create a new OperatorRegistry to store and evaluate univariate and multivariate operators.
MathOptInterface.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS — Constant
DEFAULT_UNIVARIATE_OPERATORSThe list of univariate operators that are supported by default.
Example
julia> MOI.Nonlinear.DEFAULT_UNIVARIATE_OPERATORS73-element Vector{Symbol}: :+ :- :abs :sign :sqrt :cbrt :abs2 :inv :log :log10 ⋮ :airybi :airyaiprime :airybiprime :besselj0 :besselj1 :bessely0 :bessely1 :erfcx :dawsonMathOptInterface.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS — Constant
DEFAULT_MULTIVARIATE_OPERATORSThe list of multivariate operators that are supported by default.
Example
julia> MOI.Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS9-element Vector{Symbol}: :+ :- :* :^ :/ :ifelse :atan :min :maxMathOptInterface.Nonlinear.register_operator — Function
register_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)::Tmust be a function that takes a single input argumentxand returns the function evaluated atx. If∇fand∇²fare not provided,fmust support anyRealinput typeT.∇f(x::T)::Tis a function that takes a single input argumentxand returns the first derivative offwith respect tox. If∇²fis not provided,∇fmust support anyRealinput typeT.∇²f(x::T)::Tis a function that takes a single input argumentxand returns the second derivative offwith respect tox.
Multivariate functions
f(x::T...)::Tmust be a function that takes anargsinput argumentsxand returns the function evaluated atx. If∇fand∇²fare not provided,fmust support anyRealinput typeT.∇f(g::AbstractVector{T}, x::T...)::Tis a function that takes a cache vectorgof lengthlength(x), and fills each elementg[i]with the partial derivative offwith respect tox[i].∇²f(H::AbstractMatrix, x::T...)::Tis a function that takes a matrixHand fills the lower-triangular componentsH[i, j]with the Hessian offwith respect tox[i]andx[j]fori >= j.
Notes for multivariate Hessians
Hhassize(H) == (length(x), length(x)), but you must not access elementsH[i, j]fori > j.His dense, but you do not need to fill structural zeros.
MathOptInterface.Nonlinear.register_operator_if_needed — Function
register_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 — Function
assert_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 — Function
check_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 — Function
eval_univariate_function(
registry::OperatorRegistry,
op::Union{Symbol,Integer},
x::T,
) where {T}Evaluate the operator op(x)::T, where op is a univariate function in registry.
If op isa Integer, then op is the index in registry.univariate_operators[op].
Example
julia> r = MOI.Nonlinear.OperatorRegistry();julia> MOI.Nonlinear.eval_univariate_function(r, :abs, -1.2)1.2julia> r.univariate_operators[3]:absjulia> MOI.Nonlinear.eval_univariate_function(r, 3, -1.2)1.2MathOptInterface.Nonlinear.eval_univariate_gradient — Function
eval_univariate_gradient(
registry::OperatorRegistry,
op::Union{Symbol,Integer},
x::T,
) where {T}Evaluate the first-derivative of the operator op(x)::T, where op is a univariate function in registry.
If op isa Integer, then op is the index in registry.univariate_operators[op].
Example
julia> r = MOI.Nonlinear.OperatorRegistry();julia> MOI.Nonlinear.eval_univariate_gradient(r, :abs, -1.2)-1.0julia> r.univariate_operators[3]:absjulia> MOI.Nonlinear.eval_univariate_gradient(r, 3, -1.2)-1.0MathOptInterface.Nonlinear.eval_univariate_function_and_gradient — Function
eval_univariate_function_and_gradient(
registry::OperatorRegistry,
op::Union{Symbol,Integer},
x::T,
)::Tuple{T,T} where {T}Evaluate the function and first-derivative of the operator op(x)::T, where op is a univariate function in registry.
If op isa Integer, then op is the index in registry.univariate_operators[op].
Example
julia> r = MOI.Nonlinear.OperatorRegistry();julia> MOI.Nonlinear.eval_univariate_function_and_gradient(r, :abs, -1.2)(1.2, -1.0)julia> r.univariate_operators[3]:absjulia> MOI.Nonlinear.eval_univariate_function_and_gradient(r, 3, -1.2)(1.2, -1.0)MathOptInterface.Nonlinear.eval_univariate_hessian — Function
eval_univariate_hessian(
registry::OperatorRegistry,
op::Union{Symbol,Integer},
x::T,
) where {T}Evaluate the second-derivative of the operator op(x)::T, where op is a univariate function in registry.
If op isa Integer, then op is the index in registry.univariate_operators[op].
Example
julia> r = MOI.Nonlinear.OperatorRegistry();julia> MOI.Nonlinear.eval_univariate_hessian(r, :sin, 1.0)-0.8414709848078965julia> r.univariate_operators[16]:sinjulia> MOI.Nonlinear.eval_univariate_hessian(r, 16, 1.0)-0.8414709848078965julia> -sin(1.0)-0.8414709848078965MathOptInterface.Nonlinear.eval_multivariate_function — Function
eval_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 — Function
eval_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 — Function
eval_multivariate_hessian(
registry::OperatorRegistry,
op::Symbol,
H::AbstractMatrix,
x::AbstractVector{T},
)::Bool 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.
Returns a Bool indicating whether non-zeros were stored in the matrix.
MathOptInterface.Nonlinear.eval_logic_function — Function
eval_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 — Function
eval_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 — Type
Evaluator(
model::Model,
backend::AbstractAutomaticDifferentiation,
ordered_variables::Vector{MOI.VariableIndex},
)Create Evaluator, a subtype of MOI.AbstractNLPEvaluator, from Model.
MathOptInterface.Nonlinear.AbstractAutomaticDifferentiation — Type
AbstractAutomaticDifferentiationAn abstract type for extending Evaluator.
MathOptInterface.Nonlinear.ExprGraphOnly — Type
ExprGraphOnly() <: AbstractAutomaticDifferentiationThe default implementation of AbstractAutomaticDifferentiation. The only supported feature is :ExprGraph.
MathOptInterface.Nonlinear.SparseReverseMode — Type
SparseReverseMode() <: AbstractAutomaticDifferentiationAn implementation of AbstractAutomaticDifferentiation that uses sparse reverse-mode automatic differentiation to compute derivatives. Supports all features in the MOI nonlinear interface.
MathOptInterface.Nonlinear.SymbolicMode — Type
SymbolicMode() <: AbstractAutomaticDifferentiationA type for setting as the value of the MOI.AutomaticDifferentiationBackend() attribute to enable symbolic automatic differentiation.
Data-structure
MathOptInterface.Nonlinear.Node — Type
struct Node
type::NodeType
index::Int
parent::Int
endA 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 — Type
NodeTypeAn 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_operatorsNODE_CALL_UNIVARIATE: the index intooperators.univariate_operatorsNODE_LOGIC: the index intooperators.logic_operatorsNODE_COMPARISON: the index intooperators.comparison_operatorsNODE_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.valuesfield ofExpressionNODE_PARAMETER: the index intodata.parametersNODE_SUBEXPRESSION: the index intodata.expressions
MathOptInterface.Nonlinear.Expression — Type
struct Expression
nodes::Vector{Node}
values::Vector{Float64}
endThe 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 — Type
struct Constraint
expression::Expression
set::Union{
MOI.LessThan{Float64},
MOI.GreaterThan{Float64},
MOI.EqualTo{Float64},
MOI.Interval{Float64},
}
endA 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 — Function
adjacency_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 — Function
parse_expression(data::Model, input)::ExpressionParse input into a Expression.
parse_expression(
data::Model,
expr::Expression,
input::Any,
parent_index::Int,
)::ExpressionParse 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 — Function
convert_to_expr(data::Model, expr::Expression)Convert the Expression expr into a Julia Expr.
- subexpressions are represented by a
ExpressionIndexobject. - parameters are represented by a
ParameterIndexobject. - variables are represented by an
MOI.VariableIndexobject.
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
Exprand 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
ExpressionIndexobject. - parameters will be represented by a
ParameterIndexobject. - variables will be represented by an
MOI.VariableIndexobject.
To use moi_output_format = true, you must have first called MOI.initialize with :ExprGraph as a requested feature.
MathOptInterface.Nonlinear.ordinal_index — Function
ordinal_index(evaluator::Evaluator, c::ConstraintIndex)::IntReturn the 1-indexed value of the constraint index c in evaluator.
Example
julia> model = MOI.Nonlinear.Model()A Nonlinear.Model with: 0 objectives 0 parameters 0 expressions 0 constraintsjulia> 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: * :ExprGraphjulia> MOI.initialize(evaluator, Symbol[])julia> MOI.Nonlinear.ordinal_index(evaluator, c2) # Returns 22julia> MOI.Nonlinear.delete(model, c1)julia> evaluator = MOI.Nonlinear.Evaluator(model)Nonlinear.Evaluator with available features: * :ExprGraphjulia> MOI.initialize(evaluator, Symbol[])julia> MOI.Nonlinear.ordinal_index(evaluator, c2) # Returns 11SymbolicAD
MathOptInterface.Nonlinear.SymbolicAD.simplify — Function
simplify(f)Return a simplified copy of the function f.
Example
julia> x = MOI.VariableIndex(1)MOI.VariableIndex(1)julia> f = MOI.ScalarNonlinearFunction(:^, Any[x, 1])^(MOI.VariableIndex(1), (1))julia> MOI.Nonlinear.SymbolicAD.simplify(f)MOI.VariableIndex(1)MathOptInterface.Nonlinear.SymbolicAD.simplify! — Function
simplify!(f)Simplify the function f in-place and return either the function f or a new object if f can be represented in a simpler type.
Example
julia> x = MOI.VariableIndex(1)MOI.VariableIndex(1)julia> f = MOI.ScalarNonlinearFunction( :+, Any[MOI.ScalarNonlinearFunction(:+, Any[1.0, x]), 2.0 * x + 3.0], )+(+(1.0, MOI.VariableIndex(1)), 3.0 + 2.0 MOI.VariableIndex(1))julia> MOI.Nonlinear.SymbolicAD.simplify!(f)4.0 + 3.0 MOI.VariableIndex(1)julia> f+(1.0, MOI.VariableIndex(1), 3.0 + 2.0 MOI.VariableIndex(1))simplify!(::Val{head}, f::MOI.ScalarNonlinearFunction)Simplify the function f in-place and return either the function f or a new object if f can be represented in a simpler type.
Val
The head in Val{head} is taken from f.head. This function should be called as:
f = simplify!(Val(f.head), f)Implementing a method that dispatches on head enables custom simplification rules for different operators without needing a giant switch statement.
Note
It is important that this function does not recursively call simplify!. Deal only with the immediate operator. The children arguments will already be simplified.
MathOptInterface.Nonlinear.SymbolicAD.variables — Function
variables(f::Union{Real,MOI.AbstractScalarFunction})Return a sorted list of the MOI.VariableIndex present in the function f.
Example
julia> x = MOI.VariableIndex.(1:3)3-element Vector{MathOptInterface.VariableIndex}: MOI.VariableIndex(1) MOI.VariableIndex(2) MOI.VariableIndex(3)julia> f = MOI.ScalarNonlinearFunction(:atan, Any[x[3], 2.0 * x[1]])atan(MOI.VariableIndex(3), 0.0 + 2.0 MOI.VariableIndex(1))julia> MOI.Nonlinear.SymbolicAD.variables(f)2-element Vector{MathOptInterface.VariableIndex}: MOI.VariableIndex(1) MOI.VariableIndex(3)MathOptInterface.Nonlinear.SymbolicAD.derivative — Function
derivative(f::Union{Real,MOI.AbstractScalarFunction}, x::MOI.VariableIndex)Return an expression representing the partial derivative of f with respect to x.
Expression swelling
With few exceptions, the algorithm used to compute the derivative does not perform simplications. As a result, the returned expression may contain terms like *(false, g) that can be trivially simplified to false.
In most cases, you should call simplify!(derivative(f, x)) to return a simplified expression of the derivative.
Example
julia> x = MOI.VariableIndex(1)MOI.VariableIndex(1)julia> f = MOI.ScalarNonlinearFunction(:sin, Any[x])sin(MOI.VariableIndex(1))julia> df_dx = MOI.Nonlinear.SymbolicAD.derivative(f, x)cos(MOI.VariableIndex(1))MathOptInterface.Nonlinear.SymbolicAD.gradient_and_hessian — Function
gradient_and_hessian(
[filter_fn::Function = x -> true,]
f::MOI.AbstractScalarFunction,
)Compute the symbolic gradient and Hessian of f, and return the result as a tuple of four elements:
x::Vector{MOI.VariableIndex}: the list of variables that appear inf∇f::Vector{Any}: a vector for the first partial derivative offwith respect to each element inxH::Vector{Tuple{Int,Int}}: a vector of(row, column)tuples that list the non-zero entries in the Hessian off∇²f::Vector{Any}: a vector of expressions, in the same order asH, for the non-zero entries in the Hessian off
filter_fn
This argument is a function, filter_fn(::MOI.VariableIndex)::Bool that returns true if the gradient and Hessian of f should be computed with respect to it.
Use this argument to filter out constant parameters from decision variables.