Standard form

Functions

MathOptInterface.AbstractFunctionType
AbstractFunction

Abstract supertype for function objects.

Required methods

All functions must implement:

Abstract subtypes of AbstractFunction may require additional methods to be implemented.

MathOptInterface.constantFunction
constant(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.VariableIndexType
VariableIndex

A type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.

MathOptInterface.ScalarAffineTermType
ScalarAffineTerm{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.ScalarAffineFunctionType
ScalarAffineFunction{T}(terms::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 ScalarAffineTerms
  • $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.ScalarQuadraticTermType
ScalarQuadraticTerm{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.ScalarQuadraticFunctionType
ScalarQuadraticFunction{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:

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 VariableIndexes, 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)

Vector functions

MathOptInterface.VectorOfVariablesType
VectorOfVariables(variables::Vector{VariableIndex}) <: AbstractVectorFunction

The vector-valued function f(x) = variables, where variables is a subset of VariableIndexes 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.VectorAffineTermType
VectorAffineTerm{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.VectorAffineFunctionType
VectorAffineFunction{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 VectorAffineTerms
  • $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.VectorQuadraticTermType
VectorQuadraticTerm{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.VectorQuadraticFunctionType
VectorQuadraticFunction{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 in quadratic_terms with output_index == i
  • $a_i^\top x$ is the sparse vector given by the VectorAffineTerm elements in affine_terms with output_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

Sets

MathOptInterface.AbstractSetType
AbstractSet

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.AbstractVectorSetType
AbstractVectorSet

Abstract supertype for subsets of $\mathbb{R}^n$ for some $n$.

Required methods

All AbstractVectorSets of type S must implement:

  • dimension, unless the dimension is stored in the set.dimension field
  • Utilities.set_dot, unless the dot product between two vectors in the set is equivalent to LinearAlgebra.dot.

Utilities

MathOptInterface.dimensionFunction
dimension(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_setFunction
dual_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_typeFunction
dual_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.constantMethod
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
MathOptInterface.supports_dimension_updateFunction
supports_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.

Scalar sets

List of recognized scalar sets.

MathOptInterface.GreaterThanType
GreaterThan{T<:Real}(lower::T)

The set $[lower, \infty) \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.LessThanType
LessThan{T<:Real}(upper::T)

The set $(-\infty, upper] \subseteq \mathbb{R}$.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.EqualToType
EqualTo{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}()
MOIU.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.IntervalType
Interval{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}()
MOIU.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.IntegerType
Integer()

The set of integers, $\mathbb{Z}$.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.ZeroOneType
ZeroOne()

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}()
MOIU.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.SemicontinuousType
Semicontinuous{T<:Real}(lower::T, upper::T)

The set $\{0\} \cup [lower, upper]$.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.SemiintegerType
Semiinteger{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}()
MOIU.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.ParameterType
Parameter{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}()
MOIU.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.RealsType
Reals(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}()
MOIU.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.ZerosType
Zeros(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}()
MOIU.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.NonnegativesType
Nonnegatives(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}()
MOIU.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.NonpositivesType
Nonpositives(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}()
MOIU.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.NormInfinityConeType
NormInfinityCone(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}()
MOIU.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.NormOneConeType
NormOneCone(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}()
MOIU.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.NormConeType
NormCone(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}()
MOIU.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.SecondOrderConeType
SecondOrderCone(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}()
MOIU.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.RotatedSecondOrderConeType
RotatedSecondOrderCone(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}()
MOIU.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.GeometricMeanConeType
GeometricMeanCone(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}()
MOIU.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.ExponentialConeType
ExponentialCone()

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}()
MOIU.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.DualExponentialConeType
DualExponentialCone()

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}()
MOIU.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.PowerConeType
PowerCone{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}()
MOIU.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.DualPowerConeType
DualPowerCone{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}()
MOIU.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.RelativeEntropyConeType
RelativeEntropyCone(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}()
MOIU.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.NormSpectralConeType
NormSpectralCone(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}()
MOIU.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.NormNuclearConeType
NormNuclearCone(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}()
MOIU.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.SOS1Type
SOS1{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}()
MOIU.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.SOS2Type
SOS2{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}()
MOIU.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.IndicatorType
Indicator{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 (e.g., 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}()
MOIU.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.ComplementsType
Complements(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 (e.g., 1.0 * x + 0.0), and dimension must be even.

The mixed complementarity problem consists of finding x_i in the interval [lb, ub] (i.e., in the set Interval(lb, ub)), such that the following holds:

  1. F_i(x) == 0 if lb_i < x_i < ub_i
  2. F_i(x) >= 0 if lb_i == x_i
  3. F_i(x) <= 0 if x_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:

  1. -4 * x - 3 == 0 if -1 < x < 1
  2. -4 * x - 3 >= 0 if x == -1
  3. -4 * x - 3 <= 0 if x == 1

There are three solutions:

  1. x = -3/4 with F(x) = 0
  2. x = -1 with F(x) = 1
  3. x = 1 with F(x) = -7
julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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}()
MOIU.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.HyperRectangleType
HyperRectangle(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}()
MOIU.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)

Constraint programming sets

MathOptInterface.AllDifferentType
AllDifferent(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}()
MOIU.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.BinPackingType
BinPacking(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}()
MOIU.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.CircuitType
Circuit(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}()
MOIU.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.CountAtLeastType
CountAtLeast(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}()
MOIU.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.CountBelongsType
CountBelongs(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}()
MOIU.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.CountDistinctType
CountDistinct(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, then
    • x[1] == x[2] != x[3] or
    • x[1] != x[2] == x[3] or
    • x[1] == x[3] != x[2]
  • if n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]
julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.CountGreaterThanType
CountGreaterThan(dimension::Int)

The set $\{(c, y, x) \in \mathbb{Z}^{1+1+d}\}$, such that c is strictly greater than the number of occurances 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}()
MOIU.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.CumulativeType
Cumulative(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}()
MOIU.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.PathType
Path(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}()
MOIU.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.ReifiedType
Reified(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}())
MOIU.UniversalFallback{MOIU.Model{Float64}}
fallback for MOIU.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.TableType
Table(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}()
MOIU.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.AbstractSymmetricMatrixSetTriangleType
abstract 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 index k = div((j - 1) * j, 2) + i if $i \leq j$ and k = div((i - 1) * i, 2) + j if $j \leq i$;
  • and the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = 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.AbstractSymmetricMatrixSetSquareType
abstract 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_dimensionFunction
side_dimension(
    set::Union{
        ScaledPositiveSemidefiniteConeTriangle,
        AbstractSymmetricMatrixSetTriangle,
        AbstractSymmetricMatrixSetSquare,
    },
)

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, you must implement this method.

List of recognized matrix sets.

MathOptInterface.PositiveSemidefiniteConeSquareType
PositiveSemidefiniteConeSquare(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.HermitianPositiveSemidefiniteConeTriangleType
HermitianPositiveSemidefiniteConeTriangle(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.ScaledPositiveSemidefiniteConeTriangleType
ScaledPositiveSemidefiniteConeTriangle(side_dimension::Int) <: AbstractVectorSet

The scaled (vectorized) cone of symmetric positive semidefinite matrices, with non-negative side_dimension rows and columns.

Compared to the PositiveSemidefiniteConeTriangle, the off-diagonal entries are scaled by √2. Thanks to this scaling, Utilities.set_dot is the simply the sum of the pairwise product, while for PositiveSemidefiniteConeTriangle, the pairwise product additionally have to be multiplied by 2.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.Model{Float64}

julia> x = MOI.add_variables(model, 3);

julia> MOI.add_constraint(
           model,
           MOI.VectorOfVariables(x),
           MOI.ScaledPositiveSemidefiniteConeTriangle(2),
       )
MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables, MathOptInterface.ScaledPositiveSemidefiniteConeTriangle}(1)
MathOptInterface.LogDetConeTriangleType
LogDetConeTriangle(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, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.LogDetConeSquareType
LogDetConeSquare(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, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.RootDetConeTriangleType
RootDetConeTriangle(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, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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.RootDetConeSquareType
RootDetConeSquare(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, i.e., its number of rows or columns.

Example

julia> import MathOptInterface as MOI

julia> model = MOI.Utilities.Model{Float64}()
MOIU.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)