Standard form
Functions
MathOptInterface.AbstractFunction
— TypeAbstractFunction
Abstract supertype for function objects.
Required methods
All functions must implement:
Base.copy
Base.isapprox
constant
Abstract subtypes of AbstractFunction
may require additional methods to be implemented.
MathOptInterface.output_dimension
— Functionoutput_dimension(f::AbstractFunction)
Return 1 if f
is an AbstractScalarFunction
, or the number of output components if f
is an AbstractVectorFunction
.
MathOptInterface.constant
— Functionconstant(f::AbstractFunction[, ::Type{T}]) where {T}
Returns the constant term of a scalar-valued function, or the constant vector of a vector-valued function.
If f
is untyped and T
is provided, returns zero(T)
.
constant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})
Returns the constant term of the set set
.
Example
julia> import MathOptInterface as MOI
julia> MOI.constant(MOI.GreaterThan(1.0))
1.0
julia> MOI.constant(MOI.LessThan(2.5))
2.5
julia> MOI.constant(MOI.EqualTo(3))
3
julia> MOI.constant(MOI.Parameter(4.5))
4.5
Scalar functions
MathOptInterface.AbstractScalarFunction
— Typeabstract type AbstractScalarFunction <: AbstractFunction
Abstract supertype for scalar-valued AbstractFunction
s.
MathOptInterface.VariableIndex
— TypeVariableIndex
A type-safe wrapper for Int64
for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.
MathOptInterface.ScalarAffineTerm
— TypeScalarAffineTerm{T}(coefficient::T, variable::VariableIndex) where {T}
Represents the scalar-valued term coefficient * variable
.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> MOI.ScalarAffineTerm(2.0, x)
MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
MathOptInterface.ScalarAffineFunction
— TypeScalarAffineFunction{T}(
terms::Vector{ScalarAffineTerm{T}},
constant::T,
) where {T}
Represents the scalar-valued affine function $a^\top x + b$, where:
- $a^\top x$ is represented by the vector of
ScalarAffineTerm
s - $b$ is a scalar
constant::T
Duplicates
Duplicate variable indices in terms
are accepted, and the corresponding coefficients are summed together.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> terms = [MOI.ScalarAffineTerm(2.0, x), MOI.ScalarAffineTerm(3.0, x)]
2-element Vector{MathOptInterface.ScalarAffineTerm{Float64}}:
MathOptInterface.ScalarAffineTerm{Float64}(2.0, MOI.VariableIndex(1))
MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1))
julia> f = MOI.ScalarAffineFunction(terms, 4.0)
4.0 + 2.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)
MathOptInterface.ScalarQuadraticTerm
— TypeScalarQuadraticTerm{T}(
coefficient::T,
variable_1::VariableIndex,
variable_2::VariableIndex,
) where {T}
Represents the scalar-valued term $c x_i x_j$ where $c$ is coefficient
, $x_i$ is variable_1
and $x_j$ is variable_2
.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> MOI.ScalarQuadraticTerm(2.0, x, x)
MathOptInterface.ScalarQuadraticTerm{Float64}(2.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
MathOptInterface.ScalarQuadraticFunction
— TypeScalarQuadraticFunction{T}(
quadratic_terms::Vector{ScalarQuadraticTerm{T}},
affine_terms::Vector{ScalarAffineTerm{T}},
constant::T,
) wher {T}
The scalar-valued quadratic function $\frac{1}{2}x^\top Q x + a^\top x + b$, where:
- $Q$ is the symmetric matrix given by the vector of
ScalarQuadraticTerm
s - $a^\top x$ is a sparse vector given by the vector of
ScalarAffineTerm
s - $b$ is the scalar
constant::T
.
Duplicates
Duplicate indices in quadratic_terms
or affine_terms
are accepted, and the corresponding coefficients are summed together.
In quadratic_terms
, "mirrored" indices, (q, r)
and (r, q)
where r
and q
are VariableIndex
es, are considered duplicates; only one needs to be specified.
The 0.5 factor
Coupled with the interpretation of mirrored indices, the 0.5
factor in front of the $Q$ matrix is a common source of bugs.
As a rule, to represent $a * x^2 + b * x * y$:
- The coefficient $a$ in front of squared variables (diagonal elements in $Q$) must be doubled when creating a
ScalarQuadraticTerm
- The coefficient $b$ in front of off-diagonal elements in $Q$ should be left as $b$, be cause the mirrored index $b * y * x$ will be implicitly added.
Example
To represent the function $f(x, y) = 2 * x^2 + 3 * x * y + 4 * x + 5$, do:
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1);
julia> y = MOI.VariableIndex(2);
julia> constant = 5.0;
julia> affine_terms = [MOI.ScalarAffineTerm(4.0, x)];
julia> quadratic_terms = [
MOI.ScalarQuadraticTerm(4.0, x, x), # Note the changed coefficient
MOI.ScalarQuadraticTerm(3.0, x, y),
]
2-element Vector{MathOptInterface.ScalarQuadraticTerm{Float64}}:
MathOptInterface.ScalarQuadraticTerm{Float64}(4.0, MOI.VariableIndex(1), MOI.VariableIndex(1))
MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(2))
julia> f = MOI.ScalarQuadraticFunction(quadratic_terms, affine_terms, constant)
5.0 + 4.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(1)² + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)
MathOptInterface.ScalarNonlinearFunction
— TypeScalarNonlinearFunction(head::Symbol, args::Vector{Any})
The scalar-valued nonlinear function head(args...)
, represented as a symbolic expression tree, with the call operator head
and ordered arguments in args
.
head
The head::Symbol
must be an operator supported by the model.
The default list of supported univariate operators is given by:
and the default list of supported multivariate operators is given by:
Additional operators can be registered by setting a UserDefinedFunction
attribute.
See the full list of operators supported by a ModelLike
by querying ListOfSupportedNonlinearOperators
.
args
The vector args
contains the arguments to the nonlinear function. If the operator is univariate, it must contain one element. Otherwise, it may contain multiple elements.
Each element must be one of the following:
- A constant value of type
T<:Real
- A
VariableIndex
- A
ScalarAffineFunction
- A
ScalarQuadraticFunction
- A
ScalarNonlinearFunction
Unsupported operators
If the optimizer does not support head
, an UnsupportedNonlinearOperator
error will be thrown.
There is no guarantee about when this error will be thrown; it may be thrown when the function is first added to the model, or it may be thrown when optimize!
is called.
Example
To represent the function $f(x) = sin(x)^2$, do:
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> MOI.ScalarNonlinearFunction(
:^,
Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2],
)
^(sin(MOI.VariableIndex(1)), (2))
Vector functions
MathOptInterface.AbstractVectorFunction
— Typeabstract type AbstractVectorFunction <: AbstractFunction
Abstract supertype for vector-valued AbstractFunction
s.
Required methods
All subtypes of AbstractVectorFunction
must implement:
MathOptInterface.VectorOfVariables
— TypeVectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction
The vector-valued function f(x) = variables
, where variables
is a subset of VariableIndex
es in the model.
The list of variables
may contain duplicates.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex.(1:2)
2-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
julia> f = MOI.VectorOfVariables([x[1], x[2], x[1]])
┌ ┐
│MOI.VariableIndex(1)│
│MOI.VariableIndex(2)│
│MOI.VariableIndex(1)│
└ ┘
julia> MOI.output_dimension(f)
3
MathOptInterface.VectorAffineTerm
— TypeVectorAffineTerm{T}(
output_index::Int64,
scalar_term::ScalarAffineTerm{T},
) where {T}
A VectorAffineTerm
is a scalar_term
that appears in the output_index
row of the vector-valued VectorAffineFunction
or VectorQuadraticFunction
.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1);
julia> MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x))
MathOptInterface.VectorAffineTerm{Float64}(2, MathOptInterface.ScalarAffineTerm{Float64}(3.0, MOI.VariableIndex(1)))
MathOptInterface.VectorAffineFunction
— TypeVectorAffineFunction{T}(
terms::Vector{VectorAffineTerm{T}},
constants::Vector{T},
) where {T}
The vector-valued affine function $A x + b$, where:
- $A x$ is the sparse matrix given by the vector of
VectorAffineTerm
s - $b$ is the vector
constants
Duplicates
Duplicate indices in the $A$ are accepted, and the corresponding coefficients are summed together.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1);
julia> terms = [
MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
];
julia> f = MOI.VectorAffineFunction(terms, [4.0, 5.0])
┌ ┐
│4.0 + 2.0 MOI.VariableIndex(1)│
│5.0 + 3.0 MOI.VariableIndex(1)│
└ ┘
julia> MOI.output_dimension(f)
2
MathOptInterface.VectorQuadraticTerm
— TypeVectorQuadraticTerm{T}(
output_index::Int64,
scalar_term::ScalarQuadraticTerm{T},
) where {T}
A VectorQuadraticTerm
is a ScalarQuadraticTerm
scalar_term
that appears in the output_index
row of the vector-valued VectorQuadraticFunction
.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1);
julia> MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, x))
MathOptInterface.VectorQuadraticTerm{Float64}(2, MathOptInterface.ScalarQuadraticTerm{Float64}(3.0, MOI.VariableIndex(1), MOI.VariableIndex(1)))
MathOptInterface.VectorQuadraticFunction
— TypeVectorQuadraticFunction{T}(
quadratic_terms::Vector{VectorQuadraticTerm{T}},
affine_terms::Vector{VectorAffineTerm{T}},
constants::Vector{T},
) where {T}
The vector-valued quadratic function with ith
component ("output index") defined as $\frac{1}{2}x^\top Q_i x + a_i^\top x + b_i$, where:
- $\frac{1}{2}x^\top Q_i x$ is the symmetric matrix given by the
VectorQuadraticTerm
elements inquadratic_terms
withoutput_index == i
- $a_i^\top x$ is the sparse vector given by the
VectorAffineTerm
elements inaffine_terms
withoutput_index == i
- $b_i$ is a scalar given by
constants[i]
Duplicates
Duplicate indices in quadratic_terms
and affine_terms
with the same output_index
are handled in the same manner as duplicates in ScalarQuadraticFunction
.
Example
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1);
julia> y = MOI.VariableIndex(2);
julia> constants = [4.0, 5.0];
julia> affine_terms = [
MOI.VectorAffineTerm(Int64(1), MOI.ScalarAffineTerm(2.0, x)),
MOI.VectorAffineTerm(Int64(2), MOI.ScalarAffineTerm(3.0, x)),
];
julia> quad_terms = [
MOI.VectorQuadraticTerm(Int64(1), MOI.ScalarQuadraticTerm(2.0, x, x)),
MOI.VectorQuadraticTerm(Int64(2), MOI.ScalarQuadraticTerm(3.0, x, y)),
];
julia> f = MOI.VectorQuadraticFunction(quad_terms, affine_terms, constants)
┌ ┐
│4.0 + 2.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(1)² │
│5.0 + 3.0 MOI.VariableIndex(1) + 3.0 MOI.VariableIndex(1)*MOI.VariableIndex(2)│
└ ┘
julia> MOI.output_dimension(f)
2
MathOptInterface.VectorNonlinearFunction
— TypeVectorNonlinearFunction(args::Vector{ScalarNonlinearFunction})
The vector-valued nonlinear function composed of a vector of ScalarNonlinearFunction
.
args
The vector args
contains the scalar elements of the nonlinear function. Each element must be a ScalarNonlinearFunction
, but if you pass a Vector{Any}
, the elements can be automatically converted from one of the following:
- A constant value of type
T<:Real
- A
VariableIndex
- A
ScalarAffineFunction
- A
ScalarQuadraticFunction
- A
ScalarNonlinearFunction
Example
To represent the function $f(x) = [sin(x)^2, x]$, do:
julia> import MathOptInterface as MOI
julia> x = MOI.VariableIndex(1)
MOI.VariableIndex(1)
julia> g = MOI.ScalarNonlinearFunction(
:^,
Any[MOI.ScalarNonlinearFunction(:sin, Any[x]), 2.0],
)
^(sin(MOI.VariableIndex(1)), 2.0)
julia> MOI.VectorNonlinearFunction([g, x])
┌ ┐
│^(sin(MOI.VariableIndex(1)), 2.0)│
│+(MOI.VariableIndex(1)) │
└ ┘
Note the automatic conversion from x
to +(x)
.
Sets
MathOptInterface.AbstractSet
— TypeAbstractSet
Abstract supertype for set objects used to encode constraints.
Required methods
For sets of type S
with isbitstype(S) == false
, you must implement:
Base.copy(set::S)
Base.:(==)(x::S, y::S)
Subtypes of AbstractSet
such as AbstractScalarSet
and AbstractVectorSet
may prescribe additional required methods.
Optional methods
You may optionally implement:
Note for developers
When creating a new set, the set struct must not contain any VariableIndex
or ConstraintIndex
objects.
MathOptInterface.AbstractScalarSet
— TypeAbstractScalarSet
Abstract supertype for subsets of $\mathbb{R}$.
MathOptInterface.AbstractVectorSet
— TypeAbstractVectorSet
Abstract supertype for subsets of $\mathbb{R}^n$ for some $n$.
Required methods
All AbstractVectorSet
s of type S
must implement:
dimension
, unless the dimension is stored in theset.dimension
fieldUtilities.set_dot
, unless the dot product between two vectors in the set is equivalent toLinearAlgebra.dot
.
Utilities
MathOptInterface.dimension
— Functiondimension(set::AbstractSet)
Return the output_dimension
that an AbstractFunction
should have to be used with the set set
.
Example
julia> import MathOptInterface as MOI
julia> MOI.dimension(MOI.Reals(4))
4
julia> MOI.dimension(MOI.LessThan(3.0))
1
julia> MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2))
3
MathOptInterface.dual_set
— Functiondual_set(set::AbstractSet)
Return the dual set of set
, that is the dual cone of the set. This follows the definition of duality discussed in Duality.
See Dual cone for more information.
If the dual cone is not defined it returns an error.
Example
julia> import MathOptInterface as MOI
julia> MOI.dual_set(MOI.Reals(4))
MathOptInterface.Zeros(4)
julia> MOI.dual_set(MOI.SecondOrderCone(5))
MathOptInterface.SecondOrderCone(5)
julia> MOI.dual_set(MOI.ExponentialCone())
MathOptInterface.DualExponentialCone()
MathOptInterface.dual_set_type
— Functiondual_set_type(S::Type{<:AbstractSet})
Return the type of dual set of sets of type S
, as returned by dual_set
. If the dual cone is not defined it returns an error.
Example
julia> import MathOptInterface as MOI
julia> MOI.dual_set_type(MOI.Reals)
MathOptInterface.Zeros
julia> MOI.dual_set_type(MOI.SecondOrderCone)
MathOptInterface.SecondOrderCone
julia> MOI.dual_set_type(MOI.ExponentialCone)
MathOptInterface.DualExponentialCone
MathOptInterface.constant
— Methodconstant(set::Union{EqualTo,GreaterThan,LessThan,Parameter})
Returns the constant term of the set set
.
Example
julia> import MathOptInterface as MOI
julia> MOI.constant(MOI.GreaterThan(1.0))
1.0
julia> MOI.constant(MOI.LessThan(2.5))
2.5
julia> MOI.constant(MOI.EqualTo(3))
3
julia> MOI.constant(MOI.Parameter(4.5))
4.5
MathOptInterface.supports_dimension_update
— Functionsupports_dimension_update(S::Type{<:MOI.AbstractVectorSet})
Return a Bool
indicating whether the elimination of any dimension of n
-dimensional sets of type S
give an n-1
-dimensional set S
. By default, this function returns false
so it should only be implemented for sets that supports dimension update.
For instance, supports_dimension_update(MOI.Nonnegatives)
is true
because the elimination of any dimension of the n
-dimensional nonnegative orthant gives the n-1
-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone)
is false
.
MathOptInterface.update_dimension
— Functionupdate_dimension(s::AbstractVectorSet, new_dim::Int)
Returns a set with the dimension modified to new_dim
.
Scalar sets
List of recognized scalar sets.
MathOptInterface.GreaterThan
— TypeGreaterThan{T<:Real}(lower::T)
The set $[lower, \infty) \subseteq \mathbb{R}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.GreaterThan(0.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
MathOptInterface.LessThan
— TypeLessThan{T<:Real}(upper::T)
The set $(-\infty, upper] \subseteq \mathbb{R}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.LessThan(2.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.LessThan{Float64}}(1)
MathOptInterface.EqualTo
— TypeEqualTo{T<:Number}(value::T)
The set containing the single point $\{value\} \subseteq \mathbb{R}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.EqualTo(2.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}}(1)
MathOptInterface.Interval
— TypeInterval{T<:Real}(lower::T, upper::T)
The interval $[lower, upper] \subseteq \mathbb{R} \cup \{-\infty, +\infty\}$.
If lower
or upper
is -Inf
or Inf
, respectively, the set is interpreted as a one-sided interval.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.Interval(1.0, 2.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
MathOptInterface.Integer
— TypeInteger()
The set of integers, $\mathbb{Z}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.Integer())
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
MathOptInterface.ZeroOne
— TypeZeroOne()
The set $\{0, 1\}$.
Variables belonging to the ZeroOne
set are also known as "binary" variables.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.ZeroOne())
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1)
MathOptInterface.Semicontinuous
— TypeSemicontinuous{T<:Real}(lower::T, upper::T)
The set $\{0\} \cup [lower, upper]$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.Semicontinuous(2.0, 3.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semicontinuous{Float64}}(1)
MathOptInterface.Semiinteger
— TypeSemiinteger{T<:Real}(lower::T, upper::T)
The set $\{0\} \cup \{lower, lower+1, \ldots, upper-1, upper\}$.
Note that if lower
and upper
are not equivalent to an integer, then the solver may throw an error, or it may round up lower
and round down upper
to the nearest integers.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> MOI.add_constraint(model, x, MOI.Semiinteger(2.0, 3.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Semiinteger{Float64}}(1)
MathOptInterface.Parameter
— TypeParameter{T<:Number}(value::T)
The set containing the single point $\{value\} \subseteq \mathbb{R}$.
The Parameter
set is conceptually similar to the EqualTo
set, except that a variable constrained to the Parameter
set cannot have other constraints added to it, and the Parameter
set can never be deleted. Thus, solvers are free to treat the variable as a constant, and they need not add it as a decision variable to the model.
Because of this behavior, you must add parameters using add_constrained_variable
, and solvers should declare supports_add_constrained_variable
and not supports_constraint
for the Parameter
set.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> p, ci = MOI.add_constrained_variable(model, MOI.Parameter(2.5))
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Parameter{Float64}}(1))
julia> MOI.set(model, MOI.ConstraintSet(), ci, MOI.Parameter(3.0))
julia> MOI.get(model, MOI.ConstraintSet(), ci)
MathOptInterface.Parameter{Float64}(3.0)
Vector sets
List of recognized vector sets.
MathOptInterface.Reals
— TypeReals(dimension::Int)
The set $\mathbb{R}^{dimension}$ (containing all points) of non-negative dimension dimension
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Reals(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Reals}(1)
MathOptInterface.Zeros
— TypeZeros(dimension::Int)
The set $\{ 0 \}^{dimension}$ (containing only the origin) of non-negative dimension dimension
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Zeros(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Zeros}(1)
MathOptInterface.Nonnegatives
— TypeNonnegatives(dimension::Int)
The nonnegative orthant $\{ x \in \mathbb{R}^{dimension} : x \ge 0 \}$ of non-negative dimension dimension
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
MathOptInterface.Nonpositives
— TypeNonpositives(dimension::Int)
The nonpositive orthant $\{ x \in \mathbb{R}^{dimension} : x \le 0 \}$ of non-negative dimension dimension
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonpositives(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonpositives}(1)
MathOptInterface.NormInfinityCone
— TypeNormInfinityCone(dimension::Int)
The $\ell_\infty$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}$ of dimension dimension
.
The dimension
must be at least 1
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormInfinityCone(4))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormInfinityCone}(1)
MathOptInterface.NormOneCone
— TypeNormOneCone(dimension::Int)
The $\ell_1$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}$ of dimension dimension
.
The dimension
must be at least 1
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormOneCone(4))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormOneCone}(1)
MathOptInterface.NormCone
— TypeNormCone(p::Float64, dimension::Int)
The $\ell_p$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \left(\sum\limits_i |x_i|^p\right)^{\frac{1}{p}} \}$ of dimension dimension
.
The dimension
must be at least 1
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.NormCone(3, 4))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormCone}(1)
MathOptInterface.SecondOrderCone
— TypeSecondOrderCone(dimension::Int)
The second-order cone (or Lorenz cone or $\ell_2$-norm cone) $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_2 \}$ of dimension dimension
.
The dimension
must be at least 1
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables([t; x]), MOI.SecondOrderCone(4))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SecondOrderCone}(1)
MathOptInterface.RotatedSecondOrderCone
— TypeRotatedSecondOrderCone(dimension::Int)
The rotated second-order cone $\{ (t,u,x) \in \mathbb{R}^{dimension} : 2tu \ge \lVert x \rVert_2^2, t,u \ge 0 \}$ of dimension dimension
.
The dimension
must be at least 2
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> u = MOI.add_variable(model)
MOI.VariableIndex(2)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; u; x]),
MOI.RotatedSecondOrderCone(5),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RotatedSecondOrderCone}(1)
MathOptInterface.GeometricMeanCone
— TypeGeometricMeanCone(dimension::Int)
The geometric mean cone $\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$, where dimension = n + 1 >= 2
.
Duality note
The dual of the geometric mean cone is $\{ (u, v) \in \mathbb{R}^{n+1} : u \le 0, v \ge 0, -u \le n \sqrt[n]{\prod_i v_i} \}$, where dimension = n + 1 >= 2
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; x]),
MOI.GeometricMeanCone(4),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.GeometricMeanCone}(1)
MathOptInterface.ExponentialCone
— TypeExponentialCone()
The 3-dimensional exponential cone $\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.ExponentialCone())
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ExponentialCone}(1)
MathOptInterface.DualExponentialCone
— TypeDualExponentialCone()
The 3-dimensional dual exponential cone $\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualExponentialCone())
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualExponentialCone}(1)
MathOptInterface.PowerCone
— TypePowerCone{T<:Real}(exponent::T)
The 3-dimensional power cone $\{ (x,y,z) \in \mathbb{R}^3 : x^{exponent} y^{1-exponent} \ge |z|, x \ge 0, y \ge 0 \}$ with parameter exponent
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.PowerCone(0.5))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.PowerCone{Float64}}(1)
MathOptInterface.DualPowerCone
— TypeDualPowerCone{T<:Real}(exponent::T)
The 3-dimensional power cone $\{ (u,v,w) \in \mathbb{R}^3 : (\frac{u}{exponent})^{exponent} (\frac{v}{1-exponent})^{1-exponent} \ge |w|, u \ge 0, v \ge 0 \}$ with parameter exponent
.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.DualPowerCone(0.5))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.DualPowerCone{Float64}}(1)
MathOptInterface.RelativeEntropyCone
— TypeRelativeEntropyCone(dimension::Int)
The relative entropy cone $\{ (u, v, w) \in \mathbb{R}^{1+2n} : u \ge \sum_{i=1}^n w_i \log(\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$, where dimension = 2n + 1 >= 1
.
Duality note
The dual of the relative entropy cone is $\{ (u, v, w) \in \mathbb{R}^{1+2n} : \forall i, w_i \ge u (\log (\frac{u}{v_i}) - 1), v_i \ge 0, u > 0 \}$ of dimension dimension
${}=2n+1$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> u = MOI.add_variable(model);
julia> v = MOI.add_variables(model, 3);
julia> w = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([u; v; w]),
MOI.RelativeEntropyCone(7),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RelativeEntropyCone}(1)
MathOptInterface.NormSpectralCone
— TypeNormSpectralCone(row_dim::Int, column_dim::Int)
The epigraph of the matrix spectral norm (maximum singular value function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sigma_1(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim
and column dimension column_dim
.
The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec
function.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
2×3 Matrix{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)
MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; vec(X)]),
MOI.NormSpectralCone(2, 3),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormSpectralCone}(1)
MathOptInterface.NormNuclearCone
— TypeNormNuclearCone(row_dim::Int, column_dim::Int)
The epigraph of the matrix nuclear norm (sum of singular values function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sum_i \sigma_i(X) \}$, where $\sigma_i$ is the $i$th singular value of the matrix $X$ of non-negative row dimension row_dim
and column dimension column_dim
.
The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec
function.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = reshape(MOI.add_variables(model, 6), 2, 3)
2×3 Matrix{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2) MOI.VariableIndex(4) MOI.VariableIndex(6)
MOI.VariableIndex(3) MOI.VariableIndex(5) MOI.VariableIndex(7)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; vec(X)]),
MOI.NormNuclearCone(2, 3),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.NormNuclearCone}(1)
MathOptInterface.SOS1
— TypeSOS1{T<:Real}(weights::Vector{T})
The set corresponding to the Special Ordered Set (SOS) constraint of Type I.
Of the variables in the set, at most one can be nonzero.
The weights
induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights
. Solvers may use these weights to improve the efficiency of the solution process, but the ordering does not change the set of feasible solutions.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables(x),
MOI.SOS1([1.0, 3.0, 2.5]),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS1{Float64}}(1)
MathOptInterface.SOS2
— TypeSOS2{T<:Real}(weights::Vector{T})
The set corresponding to the Special Ordered Set (SOS) constraint of Type II.
The weights
induce an ordering of the variables such that the kth element in the set corresponds to the kth weight in weights
. Therefore, the weights must be unique.
Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables(x),
MOI.SOS2([1.0, 3.0, 2.5]),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.SOS2{Float64}}(1)
MathOptInterface.Indicator
— TypeIndicator{A<:ActivationCondition,S<:AbstractScalarSet}(set::S)
The set corresponding to an indicator constraint.
When A
is ACTIVATE_ON_ZERO
, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 0 \implies x \in set\}$
When A
is ACTIVATE_ON_ONE
, this means: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 1 \implies x \in set\}$
Notes
Most solvers expect that the first row of the function is interpretable as a variable index x_i
(for example, 1.0 * x + 0.0
). An error will be thrown if this is not the case.
Example
The constraint $\{(y, x) \in \{0, 1\} \times \mathbb{R}^2 : y = 1 \implies x_1 + x_2 \leq 9 \}$ is defined as
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 2)
2-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
julia> y, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3))
julia> f = MOI.VectorAffineFunction(
[
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[1])),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x[2])),
],
[0.0, 0.0],
)
┌ ┐
│0.0 + 1.0 MOI.VariableIndex(3) │
│0.0 + 1.0 MOI.VariableIndex(1) + 1.0 MOI.VariableIndex(2)│
└ ┘
julia> s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))
MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}(MathOptInterface.LessThan{Float64}(9.0))
julia> MOI.add_constraint(model, f, s)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Indicator{MathOptInterface.ACTIVATE_ON_ONE, MathOptInterface.LessThan{Float64}}}(1)
MathOptInterface.Complements
— TypeComplements(dimension::Base.Integer)
The set corresponding to a mixed complementarity constraint.
Complementarity constraints should be specified with an AbstractVectorFunction
-in-Complements(dimension)
constraint.
The dimension of the vector-valued function F
must be dimension
. This defines a complementarity constraint between the scalar function F[i]
and the variable in F[i + dimension/2]
. Thus, F[i + dimension/2]
must be interpretable as a single variable x_i
(for example, 1.0 * x + 0.0
), and dimension
must be even.
The mixed complementarity problem consists of finding x_i
in the interval [lb, ub]
(that is, in the set Interval(lb, ub)
), such that the following holds:
F_i(x) == 0
iflb_i < x_i < ub_i
F_i(x) >= 0
iflb_i == x_i
F_i(x) <= 0
ifx_i == ub_i
Classically, the bounding set for x_i
is Interval(0, Inf)
, which recovers: 0 <= F_i(x) ⟂ x_i >= 0
, where the ⟂
operator implies F_i(x) * x_i = 0
.
Example
The problem:
x -in- Interval(-1, 1)
[-4 * x - 3, x] -in- Complements(2)
defines the mixed complementarity problem where the following holds:
-4 * x - 3 == 0
if-1 < x < 1
-4 * x - 3 >= 0
ifx == -1
-4 * x - 3 <= 0
ifx == 1
There are three solutions:
x = -3/4
withF(x) = 0
x = -1
withF(x) = 1
x = 1
withF(x) = -7
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x, _ = MOI.add_constrained_variable(model, MOI.Interval(-1.0, 1.0));
julia> MOI.add_constraint(
model,
MOI.Utilities.vectorize([-4.0 * x - 3.0, x]),
MOI.Complements(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Complements}(1)
The function F
can also be defined in terms of single variables. For example, the problem:
[x_3, x_4] -in- Nonnegatives(2)
[x_1, x_2, x_3, x_4] -in- Complements(4)
defines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0
and 0 <= x_2 ⟂ x_4 >= 0
.
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 4);
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x[3:4]), MOI.Nonnegatives(2))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Nonnegatives}(1)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables(x),
MOI.Complements(4),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Complements}(1)
MathOptInterface.HyperRectangle
— TypeHyperRectangle(lower::Vector{T}, upper::Vector{T}) where {T}
The set $\{x \in \bar{\mathbb{R}}^d: x_i \in [lower_i, upper_i] \forall i=1,\ldots,d\}$.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3)
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables(x),
MOI.HyperRectangle(zeros(3), ones(3)),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.HyperRectangle{Float64}}(1)
MathOptInterface.Scaled
— Typestruct Scaled{S<:AbstractVectorSet} <: AbstractVectorSet
set::S
end
Given a vector $a \in \mathbb{R}^d$ and a set
representing the set $\mathcal{S} \in \mathbb{R}^d$ such that Utilities.set_dot
for $x \in \mathcal{S}$ and $y \in \mathcal{S}^*$ is
\[\sum_{i=1}^d a_i x_i y_i\]
the set Scaled(set)
is defined as
\[\{ (\sqrt{a_1} x_1, \sqrt{a_2} x_2, \ldots, \sqrt{a_d} x_d) : x \in S \}\]
Example
This can be used to scale a vector of numbers
julia> import MathOptInterface as MOI
julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
MathOptInterface.PositiveSemidefiniteConeTriangle(2)
julia> a = MOI.Utilities.SetDotScalingVector{Float64}(set)
3-element MathOptInterface.Utilities.SetDotScalingVector{Float64, MathOptInterface.PositiveSemidefiniteConeTriangle}:
1.0
1.4142135623730951
1.0
julia> using LinearAlgebra
julia> MOI.Utilities.operate(*, Float64, Diagonal(a), ones(3))
3-element Vector{Float64}:
1.0
1.4142135623730951
1.0
It can be also used to scale a vector of function
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3);
julia> func = MOI.VectorOfVariables(x)
┌ ┐
│MOI.VariableIndex(1)│
│MOI.VariableIndex(2)│
│MOI.VariableIndex(3)│
└ ┘
julia> set = MOI.PositiveSemidefiniteConeTriangle(2)
MathOptInterface.PositiveSemidefiniteConeTriangle(2)
julia> MOI.Utilities.operate(*, Float64, Diagonal(a), func)
┌ ┐
│0.0 + 1.0 MOI.VariableIndex(1) │
│0.0 + 1.4142135623730951 MOI.VariableIndex(2)│
│0.0 + 1.0 MOI.VariableIndex(3) │
└ ┘
Constraint programming sets
MathOptInterface.AllDifferent
— TypeAllDifferent(dimension::Int)
The set $\{x \in \mathbb{Z}^{d}\}$ such that no two elements in $x$ take the same value and dimension = d
.
Also known as
This constraint is called all_different
in MiniZinc, and is sometimes also called distinct
.
Example
To enforce x[1] != x[2]
AND x[1] != x[3]
AND x[2] != x[3]
:
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.AllDifferent(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.AllDifferent}(1)
MathOptInterface.BinPacking
— TypeBinPacking(c::T, w::Vector{T}) where {T}
The set $\{x \in \mathbb{Z}^d\}$ where d = length(w)
, such that each item i
in 1:d
of weight w[i]
is put into bin x[i]
, and the total weight of each bin does not exceed c
.
There are additional assumptions that the capacity, c
, and the weights, w
, must all be non-negative.
The bin numbers depend on the bounds of x
, so they may be something other than the integers 1:d
.
Also known as
This constraint is called bin_packing
in MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> bins = MOI.add_variables(model, 5)
5-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
MOI.VariableIndex(4)
MOI.VariableIndex(5)
julia> weights = Float64[1, 1, 2, 2, 3]
5-element Vector{Float64}:
1.0
1.0
2.0
2.0
3.0
julia> MOI.add_constraint.(model, bins, MOI.Integer())
5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}}:
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(4)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(5)
julia> MOI.add_constraint.(model, bins, MOI.Interval(4.0, 6.0))
5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}}:
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(1)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(2)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(3)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(4)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Interval{Float64}}(5)
julia> MOI.add_constraint(model, MOI.VectorOfVariables(bins), MOI.BinPacking(3.0, weights))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.BinPacking{Float64}}(1)
MathOptInterface.Circuit
— TypeCircuit(dimension::Int)
The set $\{x \in \{1..d\}^d\}$ that constraints $x$ to be a circuit, such that $x_i = j$ means that $j$ is the successor of $i$, and dimension = d
.
Graphs with multiple independent circuits, such as [2, 1, 3]
and [2, 1, 4, 3]
, are not valid.
Also known as
This constraint is called circuit
in MiniZinc, and it is equivalent to forming a (potentially sub-optimal) tour in the travelling salesperson problem.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Circuit(3))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Circuit}(1)
MathOptInterface.CountAtLeast
— TypeCountAtLeast(n::Int, d::Vector{Int}, set::Set{Int})
The set $\{x \in \mathbb{Z}^{d_1 + d_2 + \ldots d_N}\}$, where x
is partitioned into N
subsets ($\{x_1, \ldots, x_{d_1}\}$, $\{x_{d_1 + 1}, \ldots, x_{d_1 + d_2}\}$ and so on), and at least $n$ elements of each subset take one of the values in set
.
Also known as
This constraint is called at_least
in MiniZinc.
Example
To ensure that 3
appears at least once in each of the subsets {a, b}
and {b, c}
:
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> a, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(3), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(3))
julia> x, d, set = [a, b, b, c], [2, 2], [3]
(MathOptInterface.VariableIndex[MOI.VariableIndex(1), MOI.VariableIndex(2), MOI.VariableIndex(2), MOI.VariableIndex(3)], [2, 2], [3])
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.CountAtLeast(1, d, Set(set)))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountAtLeast}(1)
MathOptInterface.CountBelongs
— TypeCountBelongs(dimenson::Int, set::Set{Int})
The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that n
elements of the vector x
take on of the values in set
and dimension = 1 + d
.
Also known as
This constraint is called among
by MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2)
MOI.VariableIndex(3)
MOI.VariableIndex(4)
julia> set = Set([3, 4, 5])
Set{Int64} with 3 elements:
5
4
3
julia> MOI.add_constraint(model, MOI.VectorOfVariables([n; x]), MOI.CountBelongs(4, set))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountBelongs}(1)
MathOptInterface.CountDistinct
— TypeCountDistinct(dimension::Int)
The set $\{(n, x) \in \mathbb{Z}^{1+d}\}$, such that the number of distinct values in x
is n
and dimension = 1 + d
.
Also known as
This constraint is called nvalues
in MiniZinc.
Example
To model:
- if
n == 1
, thenx[1] == x[2] == x[3]
- if
n == 2
, thenx[1] == x[2] != x[3]
orx[1] != x[2] == x[3]
orx[1] == x[3] != x[2]
- if
n == 3
, thenx[1] != x[2]
,x[2] != x[3]
andx[3] != x[1]
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> n, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2)
MOI.VariableIndex(3)
MOI.VariableIndex(4)
julia> MOI.add_constraint(model, MOI.VectorOfVariables(vcat(n, x)), MOI.CountDistinct(4))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountDistinct}(1)
Relationship to AllDifferent
When the first element is d
, CountDistinct
is equivalent to an AllDifferent
constraint.
MathOptInterface.CountGreaterThan
— TypeCountGreaterThan(dimension::Int)
The set $\{(c, y, x) \in \mathbb{Z}^{1+1+d}\}$, such that c
is strictly greater than the number of occurences of y
in x
and dimension = 1 + 1 + d
.
Also known as
This constraint is called count_gt
in MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> c, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
julia> y, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
julia> x = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(3)
MOI.VariableIndex(4)
MOI.VariableIndex(5)
julia> MOI.add_constraint(model, MOI.VectorOfVariables([c; y; x]), MOI.CountGreaterThan(5))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.CountGreaterThan}(1)
MathOptInterface.Cumulative
— TypeCumulative(dimension::Int)
The set $\{(s, d, r, b) \in \mathbb{Z}^{3n+1}\}$, representing the cumulative
global constraint, where n == length(s) == length(r) == length(b)
and dimension = 3n + 1
.
Cumulative
requires that a set of tasks given by start times $s$, durations $d$, and resource requirements $r$, never requires more than the global resource bound $b$ at any one time.
Also known as
This constraint is called cumulative
in MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> s = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
julia> d = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(4)
MOI.VariableIndex(5)
MOI.VariableIndex(6)
julia> r = [MOI.add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(7)
MOI.VariableIndex(8)
MOI.VariableIndex(9)
julia> b, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(10), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(10))
julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; d; r; b]), MOI.Cumulative(10))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Cumulative}(1)
MathOptInterface.Path
— TypePath(from::Vector{Int}, to::Vector{Int})
Given a graph comprised of a set of nodes 1..N
and a set of arcs 1..E
represented by an edge from node from[i]
to node to[i]
, Path
constrains the set $(s, t, ns, es) \in (1..N)\times(1..E)\times\{0,1\}^N\times\{0,1\}^E$, to form subgraph that is a path from node s
to node t
, where node n
is in the path if ns[n]
is 1
, and edge e
is in the path if es[e]
is 1
.
The path must be acyclic, and it must traverse all nodes n
for which ns[n]
is 1
, and all edges e
for which es[e]
is 1
.
Also known as
This constraint is called path
in MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> N, E = 4, 5
(4, 5)
julia> from = [1, 1, 2, 2, 3]
5-element Vector{Int64}:
1
1
2
2
3
julia> to = [2, 3, 3, 4, 4]
5-element Vector{Int64}:
2
3
3
4
4
julia> s, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(1))
julia> t, _ = MOI.add_constrained_variable(model, MOI.Integer())
(MOI.VariableIndex(2), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.Integer}(2))
julia> ns = MOI.add_variables(model, N)
4-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(3)
MOI.VariableIndex(4)
MOI.VariableIndex(5)
MOI.VariableIndex(6)
julia> MOI.add_constraint.(model, ns, MOI.ZeroOne())
4-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(3)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(4)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(5)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(6)
julia> es = MOI.add_variables(model, E)
5-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(7)
MOI.VariableIndex(8)
MOI.VariableIndex(9)
MOI.VariableIndex(10)
MOI.VariableIndex(11)
julia> MOI.add_constraint.(model, es, MOI.ZeroOne())
5-element Vector{MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}}:
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(7)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(8)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(9)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(10)
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(11)
julia> MOI.add_constraint(model, MOI.VectorOfVariables([s; t; ns; es]), MOI.Path(from, to))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Path}(1)
MathOptInterface.Reified
— TypeReified(set::AbstractSet)
The constraint $[z; f(x)] \in Reified(S)$ ensures that $f(x) \in S$ if and only if $z == 1$, where $z \in \{0, 1\}$.
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());
julia> z, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
(MOI.VariableIndex(1), MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.ZeroOne}(1))
julia> x = MOI.add_variable(model)
MOI.VariableIndex(2)
julia> MOI.add_constraint(
model,
MOI.Utilities.vectorize([z, 2.0 * x]),
MOI.Reified(MOI.GreaterThan(1.0)),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Reified{MathOptInterface.GreaterThan{Float64}}}(1)
MathOptInterface.Table
— TypeTable(table::Matrix{T}) where {T}
The set $\{x \in \mathbb{R}^d\}$ where d = size(table, 2)
, such that x
belongs to one row of table
. That is, there exists some j
in 1:size(table, 1)
, such that x[i] = table[j, i]
for all i=1:size(table, 2)
.
Also known as
This constraint is called table
in MiniZinc.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 3)
3-element Vector{MathOptInterface.VariableIndex}:
MOI.VariableIndex(1)
MOI.VariableIndex(2)
MOI.VariableIndex(3)
julia> table = Float64[1 1 0; 0 1 1; 1 0 1; 1 1 1]
4×3 Matrix{Float64}:
1.0 1.0 0.0
0.0 1.0 1.0
1.0 0.0 1.0
1.0 1.0 1.0
julia> MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Table(table))
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.Table{Float64}}(1)
Matrix sets
Matrix sets are vectorized to be subtypes of AbstractVectorSet
.
For sets of symmetric matrices, storing both the (i, j)
and (j, i)
elements is redundant. Use the AbstractSymmetricMatrixSetTriangle
set to represent only the vectorization of the upper triangular part of the matrix.
When the matrix of expressions constrained to be in the set is not symmetric, and hence additional constraints are needed to force the equality of the (i, j)
and (j, i)
elements, use the AbstractSymmetricMatrixSetSquare
set.
The Bridges.Constraint.SquareBridge
can transform a set from the square form to the triangular_form
by adding appropriate constraints if the (i, j)
and (j, i)
expressions are different.
MathOptInterface.AbstractSymmetricMatrixSetTriangle
— Typeabstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end
Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension
rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension
$n$ corresponds to a square matrix with side dimension $\sqrt{1/4 + 2 n} - 1/2$. (Because a $d \times d$ matrix has $d(d + 1) / 2$ elements in the upper or lower triangle.)
Example
The matrix
\[\begin{bmatrix} 1 & 2 & 4\\ 2 & 3 & 5\\ 4 & 5 & 6 \end{bmatrix}\]
has side_dimension
3 and vectorization $(1, 2, 3, 4, 5, 6)$.
Note
Two packed storage formats exist for symmetric matrices, the respective orders of the entries are:
- upper triangular column by column (or lower triangular row by row);
- lower triangular column by column (or upper triangular row by row).
The advantage of the first format is the mapping between the (i, j)
matrix indices and the k
index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,
- the entry of matrix indices
(i, j)
has vectorized indexk = div((j - 1) * j, 2) + i
if $i \leq j$ andk = div((i - 1) * i, 2) + j
if $j \leq i$; - and the entry with vectorized index
k
has matrix indicesi = div(1 + isqrt(8k - 7), 2)
andj = k - div((i - 1) * i, 2)
orj = div(1 + isqrt(8k - 7), 2)
andi = k - div((j - 1) * j, 2)
.
Duality note
The scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.
Consider for example the following problem (PositiveSemidefiniteConeTriangle
is a subtype of AbstractSymmetricMatrixSetTriangle
)
\[\begin{align*} & \max_{x \in \mathbb{R}} & x \\ & \;\;\text{s.t.} & (1, -x, 1) & \in \text{PositiveSemidefiniteConeTriangle}(2). \end{align*}\]
The dual is the following problem
\[\begin{align*} & \min_{x \in \mathbb{R}^3} & y_1 + y_3 \\ & \;\;\text{s.t.} & 2y_2 & = 1\\ & & y & \in \text{PositiveSemidefiniteConeTriangle}(2). \end{align*}\]
Why do we use $2y_2$ in the dual constraint instead of $y_2$ ? The reason is that $2y_2$ is the scalar product between $y$ and the symmetric matrix whose vectorized form is $(0, 1, 0)$. Indeed, with our modified scalar products we have
\[\langle (0, 1, 0), (y_1, y_2, y_3) \rangle = \mathrm{trace} \begin{pmatrix} 0 & 1\\ 1 & 0 \end{pmatrix} \begin{pmatrix} y_1 & y_2\\ y_2 & y_3 \end{pmatrix} = 2y_2.\]
References
[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.
MathOptInterface.AbstractSymmetricMatrixSetSquare
— Typeabstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end
Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension
rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form
belong to the corresponding set. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.
Example
PositiveSemidefiniteConeSquare
is a subtype of AbstractSymmetricMatrixSetSquare
and constraining the matrix
\[\begin{bmatrix} 1 & -y\\ -z & 0\\ \end{bmatrix}\]
to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2)
. It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2)
, since triangular_form(PositiveSemidefiniteConeSquare)
is PositiveSemidefiniteConeTriangle
.
MathOptInterface.side_dimension
— Functionside_dimension(
set::Union{
AbstractSymmetricMatrixSetTriangle,
AbstractSymmetricMatrixSetSquare,
HermitianPositiveSemidefiniteConeTriangle,
},
)
Side dimension of the matrices in set
.
Convention
By convention, the side dimension should be stored in the side_dimension
field. If this is not the case for a subtype of AbstractSymmetricMatrixSetTriangle
, or AbstractSymmetricMatrixSetSquare
you must implement this method.
MathOptInterface.triangular_form
— Functiontriangular_form(S::Type{<:AbstractSymmetricMatrixSetSquare})
triangular_form(set::AbstractSymmetricMatrixSetSquare)
Return the AbstractSymmetricMatrixSetTriangle
corresponding to the vectorization of the upper triangular part of matrices in the AbstractSymmetricMatrixSetSquare
set.
List of recognized matrix sets.
MathOptInterface.PositiveSemidefiniteConeTriangle
— TypePositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractSymmetricMatrixSetTriangle
The (vectorized) cone of symmetric positive semidefinite matrices, with non-negative side_dimension
rows and columns.
See AbstractSymmetricMatrixSetTriangle
for more details on the vectorized form.
MathOptInterface.PositiveSemidefiniteConeSquare
— TypePositiveSemidefiniteConeSquare(side_dimension::Int) <: AbstractSymmetricMatrixSetSquare
The cone of symmetric positive semidefinite matrices, with non-negative side length side_dimension
.
See AbstractSymmetricMatrixSetSquare
for more details on the vectorized form.
The entries of the matrix are given column by column (or equivalently, row by row).
The matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.
Example
Constraining the matrix
\[\begin{bmatrix} 1 & -y\\ -z & 0\\ \end{bmatrix}\]
to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2)
.
It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2)
.
MathOptInterface.HermitianPositiveSemidefiniteConeTriangle
— TypeHermitianPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet
The (vectorized) cone of Hermitian positive semidefinite matrices, with non-negative side_dimension
rows and columns.
Becaue the matrix is Hermitian, the diagonal elements are real, and the complex-valued lower triangular entries are obtained as the conjugate of corresponding upper triangular entries.
Vectorization format
The vectorized form starts with real part of the entries of the upper triangular part of the matrix, given column by column as explained in AbstractSymmetricMatrixSetSquare
.
It is then followed by the imaginary part of the off-diagonal entries of the upper triangular part, also given column by column.
For example, the matrix
\[\begin{bmatrix} 1 & 2 + 7im & 4 + 8im\\ 2 - 7im & 3 & 5 + 9im\\ 4 - 8im & 5 - 9im & 6 \end{bmatrix}\]
has side_dimension
3 and is represented as the vector $[1, 2, 3, 4, 5, 6, 7, 8, 9]$.
MathOptInterface.LogDetConeTriangle
— TypeLogDetConeTriangle(side_dimension::Int)
The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d(d+1)/2} : t \le u \log(\det(X/u)), u > 0 \}$, where the matrix X
is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle
.
The non-negative argument side_dimension
is the side dimension of the matrix X
, that is, its number of rows or columns.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; X]),
MOI.LogDetConeTriangle(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeTriangle}(1)
MathOptInterface.LogDetConeSquare
— TypeLogDetConeSquare(side_dimension::Int)
The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d^2} : t \le u \log(\det(X/u)), X \text{ symmetric}, u > 0 \}$, where the matrix X
is represented in the same format as in the PositiveSemidefiniteConeSquare
.
Similarly to PositiveSemidefiniteConeSquare
, constraints are added to ensure that X
is symmetric.
The non-negative argument side_dimension
is the side dimension of the matrix X
, that is, its number of rows or columns.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
2×2 Matrix{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2) MOI.VariableIndex(4)
MOI.VariableIndex(3) MOI.VariableIndex(5)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; vec(X)]),
MOI.LogDetConeSquare(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.LogDetConeSquare}(1)
MathOptInterface.RootDetConeTriangle
— TypeRootDetConeTriangle(side_dimension::Int)
The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d(d+1)/2} : t \le \det(X)^{1/d} \}$, where the matrix X
is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle
.
The non-negative argument side_dimension
is the side dimension of the matrix X
, that is, its number of rows or columns.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = MOI.add_variables(model, 3);
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; X]),
MOI.RootDetConeTriangle(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeTriangle}(1)
MathOptInterface.RootDetConeSquare
— TypeRootDetConeSquare(side_dimension::Int)
The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d^2} : t \le \det(X)^{1/d}, X \text{ symmetric} \}$, where the matrix X
is represented in the same format as PositiveSemidefiniteConeSquare
.
Similarly to PositiveSemidefiniteConeSquare
, constraints are added to ensure that X
is symmetric.
The non-negative argument side_dimension
is the side dimension of the matrix X
, that is, its number of rows or columns.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> t = MOI.add_variable(model)
MOI.VariableIndex(1)
julia> X = reshape(MOI.add_variables(model, 4), 2, 2)
2×2 Matrix{MathOptInterface.VariableIndex}:
MOI.VariableIndex(2) MOI.VariableIndex(4)
MOI.VariableIndex(3) MOI.VariableIndex(5)
julia> MOI.add_constraint(
model,
MOI.VectorOfVariables([t; vec(X)]),
MOI.RootDetConeSquare(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.RootDetConeSquare}(1)