# Standard form

## Functions

`MathOptInterface.AbstractFunction`

— Type`AbstractFunction`

Abstract supertype for function objects.

`MathOptInterface.AbstractScalarFunction`

— Type`AbstractScalarFunction`

Abstract supertype for scalar-valued function objects.

`MathOptInterface.AbstractVectorFunction`

— Type`AbstractVectorFunction`

Abstract supertype for vector-valued function objects.

`MathOptInterface.VariableIndex`

— Type`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.VectorOfVariables`

— Type`VectorOfVariables(variables)`

The function that extracts the vector of variables referenced by `variables`

, a `Vector{VariableIndex}`

. This function is naturally be used for constraints that apply to groups of variables, such as an "all different" constraint, an indicator constraint, or a complementarity constraint.

`MathOptInterface.ScalarAffineTerm`

— Type```
struct ScalarAffineTerm{T}
coefficient::T
variable::VariableIndex
end
```

Represents $c x_i$ where $c$ is `coefficient`

and $x_i$ is the variable identified by `variable`

.

`MathOptInterface.ScalarAffineFunction`

— Type`ScalarAffineFunction{T}(terms, constant)`

The scalar-valued affine function $a^T x + b$, where:

- $a$ is a sparse vector specified by a list of
`ScalarAffineTerm`

structs. - $b$ is a scalar specified by
`constant::T`

Duplicate variable indices in `terms`

are accepted, and the corresponding coefficients are summed together.

`MathOptInterface.VectorAffineTerm`

— Type```
struct VectorAffineTerm{T}
output_index::Int64
scalar_term::ScalarAffineTerm{T}
end
```

A `ScalarAffineTerm`

plus its index of the output component of a `VectorAffineFunction`

or `VectorQuadraticFunction`

. `output_index`

can also be interpreted as a row index into a sparse matrix, where the `scalar_term`

contains the column index and coefficient.

`MathOptInterface.VectorAffineFunction`

— Type`VectorAffineFunction{T}(terms, constants)`

The vector-valued affine function $A x + b$, where:

- $A$ is a sparse matrix specified by a list of
`VectorAffineTerm`

objects. - $b$ is a vector specified by
`constants`

Duplicate indices in the $A$ are accepted, and the corresponding coefficients are summed together.

`MathOptInterface.ScalarQuadraticTerm`

— Type```
struct ScalarQuadraticTerm{T}
coefficient::T
variable_1::VariableIndex
variable_2::VariableIndex
end
```

Represents $c x_i x_j$ where $c$ is `coefficient`

, $x_i$ is the variable identified by `variable_1`

and $x_j$ is the variable identified by `variable_2`

.

`MathOptInterface.ScalarQuadraticFunction`

— Type`ScalarQuadraticFunction{T}(quadratic_terms, affine_terms, constant)`

The scalar-valued quadratic function $\frac{1}{2}x^TQx + a^T x + b$, where:

- $a$ is a sparse vector specified by a list of
`ScalarAffineTerm`

structs. - $b$ is a scalar specified by
`constant`

. - $Q$ is a symmetric matrix specified by a list of
`ScalarQuadraticTerm`

structs.

Duplicate indices in $a$ or $Q$ are accepted, and the corresponding coefficients are summed together. "Mirrored" indices `(q,r)`

and `(r,q)`

(where `r`

and `q`

are `VariableIndex`

es) are considered duplicates; only one need be specified.

For example, for two scalar variables $y, z$, the quadratic expression $yz + y^2$ is represented by the terms `ScalarQuadraticTerm.([1.0, 2.0], [y, y], [z, y])`

.

`MathOptInterface.VectorQuadraticTerm`

— Type```
struct VectorQuadraticTerm{T}
output_index::Int64
scalar_term::ScalarQuadraticTerm{T}
end
```

A `ScalarQuadraticTerm`

plus its index of the output component of a `VectorQuadraticFunction`

. Each output component corresponds to a distinct sparse matrix $Q_i$.

`MathOptInterface.VectorQuadraticFunction`

— Type`VectorQuadraticFunction{T}(quadratic_terms, affine_terms, constants)`

The vector-valued quadratic function with i`th`

component ("output index") defined as $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$, where:

- $a_i$ is a sparse vector specified by the
`VectorAffineTerm`

s with`output_index == i`

. - $b_i$ is a scalar specified by
`constants[i]`

- $Q_i$ is a symmetric matrix specified by the
`VectorQuadraticTerm`

with`output_index == i`

.

Duplicate indices in $a_i$ or $Q_i$ are accepted, and the corresponding coefficients are summed together. "Mirrored" indices `(q,r)`

and `(r,q)`

(where `r`

and `q`

are `VariableIndex`

es) are considered duplicates; only one need be specified.

### Utilities

`MathOptInterface.output_dimension`

— Function`output_dimension(f::AbstractFunction)`

Return 1 if `f`

has a scalar output and the number of output components if `f`

has a vector output.

`MathOptInterface.constant`

— Method`constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction})`

Returns the constant term of the scalar function

`MathOptInterface.constant`

— Method`constant(f::Union{VectorAffineFunction, VectorQuadraticFunction})`

Returns the vector of constant terms of the vector function

`MathOptInterface.constant`

— Method`constant(f::VariableIndex, ::Type{T}) where {T}`

The constant term of a `VariableIndex`

function is the zero value of the specified type `T`

.

`MathOptInterface.constant`

— Method`constant(f::VectorOfVariables, ::Type{T}) where {T}`

The constant term of a `VectorOfVariables`

function is a vector of zero values of the specified type `T`

.

## Sets

`MathOptInterface.AbstractSet`

— Type`AbstractSet`

Abstract supertype for set objects used to encode constraints. A set object should not contain any `VariableIndex`

or `ConstraintIndex`

as the set is passed unmodifed during `copy_to`

.

`MathOptInterface.AbstractScalarSet`

— Type`AbstractScalarSet`

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

`MathOptInterface.AbstractVectorSet`

— Type`AbstractVectorSet`

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

### Utilities

`MathOptInterface.dimension`

— Function`dimension(s::AbstractSet)`

Return the `output_dimension`

that an `AbstractFunction`

should have to be used with the set `s`

.

**Examples**

```
julia> dimension(Reals(4))
4
julia> dimension(LessThan(3.0))
1
julia> dimension(PositiveSemidefiniteConeTriangle(2))
3
```

`MathOptInterface.dual_set`

— Function`dual_set(s::AbstractSet)`

Return the dual set of `s`

, 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.

**Examples**

```
julia> dual_set(Reals(4))
Zeros(4)
julia> dual_set(SecondOrderCone(5))
SecondOrderCone(5)
julia> dual_set(ExponentialCone())
DualExponentialCone()
```

`MathOptInterface.dual_set_type`

— Function`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.

**Examples**

```
julia> dual_set_type(Reals)
Zeros
julia> dual_set_type(SecondOrderCone)
SecondOrderCone
julia> dual_set_type(ExponentialCone)
DualExponentialCone
```

`MathOptInterface.constant`

— Method`constant(s::Union{EqualTo, GreaterThan, LessThan})`

Returns the constant of the set.

`MathOptInterface.supports_dimension_update`

— Function`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`

.

`MathOptInterface.update_dimension`

— Function`update_dimension(s::AbstractVectorSet, new_dim)`

Returns a set with the dimension modified to `new_dim`

.

## Scalar sets

List of recognized scalar sets.

`MathOptInterface.GreaterThan`

— Type`GreaterThan{T <: Real}(lower::T)`

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

`MathOptInterface.LessThan`

— Type`LessThan{T <: Real}(upper::T)`

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

`MathOptInterface.EqualTo`

— Type`EqualTo{T <: Number}(value::T)`

The set containing the single point $x \in \mathbb{R}$ where $x$ is given by `value`

.

`MathOptInterface.Interval`

— Type`Interval{T <: Real}(lower::T,upper::T)`

The interval $[lower, upper] \subseteq \mathbb{R}$. If `lower`

or `upper`

is `-Inf`

or `Inf`

, respectively, the set is interpreted as a one-sided interval.

`Interval(s::GreaterThan{<:AbstractFloat})`

Construct a (right-unbounded) `Interval`

equivalent to the given `GreaterThan`

set.

`Interval(s::LessThan{<:AbstractFloat})`

Construct a (left-unbounded) `Interval`

equivalent to the given `LessThan`

set.

`Interval(s::EqualTo{<:Real})`

Construct a (degenerate) `Interval`

equivalent to the given `EqualTo`

set.

`MathOptInterface.Integer`

— Type`Integer()`

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

`MathOptInterface.ZeroOne`

— Type`ZeroOne()`

The set $\{ 0, 1 \}$.

`MathOptInterface.Semicontinuous`

— Type`Semicontinuous{T <: Real}(lower::T,upper::T)`

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

`MathOptInterface.Semiinteger`

— Type`Semiinteger{T <: Real}(lower::T,upper::T)`

The set $\{0\} \cup \{lower,lower+1,\ldots,upper-1,upper\}$.

## Vector sets

List of recognized vector sets.

`MathOptInterface.Reals`

— Type`Reals(dimension)`

The set $\mathbb{R}^{dimension}$ (containing all points) of dimension `dimension`

.

`MathOptInterface.Zeros`

— Type`Zeros(dimension)`

The set $\{ 0 \}^{dimension}$ (containing only the origin) of dimension `dimension`

.

`MathOptInterface.Nonnegatives`

— Type`Nonnegatives(dimension)`

The nonnegative orthant $\{ x \in \mathbb{R}^{dimension} : x \ge 0 \}$ of dimension `dimension`

.

`MathOptInterface.Nonpositives`

— Type`Nonpositives(dimension)`

The nonpositive orthant $\{ x \in \mathbb{R}^{dimension} : x \le 0 \}$ of dimension `dimension`

.

`MathOptInterface.NormInfinityCone`

— Type`NormInfinityCone(dimension)`

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`

.

`MathOptInterface.NormOneCone`

— Type`NormOneCone(dimension)`

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`

.

`MathOptInterface.SecondOrderCone`

— Type`SecondOrderCone(dimension)`

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`

.

`MathOptInterface.RotatedSecondOrderCone`

— Type`RotatedSecondOrderCone(dimension)`

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`

.

`MathOptInterface.GeometricMeanCone`

— Type`GeometricMeanCone(dimension)`

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`

.

`MathOptInterface.ExponentialCone`

— Type`ExponentialCone()`

The 3-dimensional exponential cone $\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}$.

`MathOptInterface.DualExponentialCone`

— Type`DualExponentialCone()`

The 3-dimensional dual exponential cone $\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le \exp(1) w, u < 0 \}$.

`MathOptInterface.PowerCone`

— Type`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`

.

`MathOptInterface.DualPowerCone`

— Type`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`

.

`MathOptInterface.RelativeEntropyCone`

— Type`RelativeEntropyCone(dimension)`

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$.

`MathOptInterface.NormSpectralCone`

— Type`NormSpectralCone(row_dim, column_dim)`

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

`MathOptInterface.NormNuclearCone`

— Type`NormNuclearCone(row_dim, column_dim)`

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

`MathOptInterface.SOS1`

— Type`SOS1{T <: Real}(weights::Vector{T})`

The set corresponding to the special ordered set (SOS) constraint of type 1. Of the variables in the set, at most one can be nonzero. The `weights`

induce an ordering of the variables; as such, they should be unique values. The *k*th element in the set corresponds to the *k*th weight in `weights`

. See here for a description of SOS constraints and their potential uses.

`MathOptInterface.SOS2`

— Type`SOS2{T <: Real}(weights::Vector{T})`

The set corresponding to the special ordered set (SOS) constraint of type 2. 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. The `weights`

induce an ordering of the variables; as such, they should be unique values. The *k*th element in the set corresponds to the *k*th weight in `weights`

. See here for a description of SOS constraints and their potential uses.

`MathOptInterface.Indicator`

— Type`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

```
f = MOI.VectorAffineFunction(
[
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, y)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x1)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x2)),
],
[0.0, 0.0],
)
s = MOI.Indicator{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))
MOI.add_constraint(model, f, s)
```

`MathOptInterface.Complements`

— Type`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:

`F_i(x) == 0`

if`lb_i < x_i < ub_i`

`F_i(x) >= 0`

if`lb_i == x_i`

`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`

.

**Examples**

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`

if`x == -1`

`-4 * x - 3 <= 0`

if`x == 1`

There are three solutions:

`x = -3/4`

with`F(x) = 0`

`x = -1`

with`F(x) = 1`

`x = 1`

with`F(x) = -7`

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`

.

`MathOptInterface.HyperRectangle`

— Type`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**

```
model = Utilities.Model{Float64}()
x = add_variables(model, 3)
add_constraint(model, VectorOfVariables(x), HyperRectangle(zeros(3), ones(3)))
```

## Constraint programming sets

`MathOptInterface.AllDifferent`

— Type`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**

```
model = Utilities.Model{Float64}()
x = [add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
add_constraint(model, VectorOfVariables(x), AllDifferent(3))
# enforces `x[1] != x[2]` AND `x[1] != x[3]` AND `x[2] != x[3]`.
```

`MathOptInterface.BinPacking`

— Type`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**

```
model = Utilities.Model{Float64}()
bins = add_variables(model, 5)
weights = [1, 1, 2, 2, 3]
add_constraint.(model, bins, MOI.Integer())
# Available bins are #4, #5, and #6.
add_constraint.(model, bins, MOI.Interval(4, 6))
add_constraint(model, VectorOfVariables(bins), BinPacking(3, weights))
```

`MathOptInterface.Circuit`

— Type`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**

```
model = Utilities.Model{Float64}()
x = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
add_constraint(model, VectorOfVariables(x), Circuit(3))
```

`MathOptInterface.CountAtLeast`

— Type`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**

```
model = Utilities.Model{Float64}()
a, _ = add_constrained_variable(model, Integer())
b, _ = add_constrained_variable(model, Integer())
c, _ = add_constrained_variable(model, Integer())
# To ensure that `3` appears at least once in each of the subsets {a, b}, {b, c}
x, d, set = [a, b, b, c], [2, 2], [3]
add_constraint(model, VectorOfVariables(x), CountAtLeast(1, d, Set(set)))
```

`MathOptInterface.CountBelongs`

— Type`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**

```
model = Utilities.Model{Float64}()
n = add_constrained_variable(model, MOI.Integer())
x = [add_constrained_variable(model, MOI.Integer())[1] for _ in 1:3]
set = Set([3, 4, 5])
add_constraint(model, VectorOfVariables([n; x]), CountBelongs(4, set))
```

`MathOptInterface.CountDistinct`

— Type`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**

```
model = Utilities.Model{Float64}()
n = add_constrained_variable(model, Integer())
x = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
add_constraint(model, VectorOfVariables(vcat(n, x)), CountDistinct(4))
# if n == 1, then x[1] == x[2] == x[3]
# if n == 2, then
# x[1] == x[2] != x[3] ||
# x[1] != x[2] == x[3] ||
# x[1] == x[3] != x[2]
# if n == 3, then x[1] != x[2], x[2] != x[3] and x[3] != x[1]
```

**Relationship to AllDifferent**

When the first element is `d`

, `CountDistinct`

is equivalent to an `AllDifferent`

constraint.

```
model = Utilities.Model{Float64}()
x = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
add_constraint(model, VectorOfVariables(vcat(3, x)), CountDistinct(4))
# equivalent to
add_constraint(model, VectorOfVariables(x), AllDifferent(3))
```

`MathOptInterface.CountGreaterThan`

— Type`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**

```
model = Utilities.Model{Float64}()
c, _ = add_constrained_variable(model, Integer())
y, _ = add_constrained_variable(model, Integer())
x = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
add_constraint(model, VectorOfVariables([c; y; x]), CountGreaterThan(5))
```

`MathOptInterface.Cumulative`

— Type`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**

```
model = Utilities.Model{Float64}()
s = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
d = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
r = [add_constrained_variable(model, Integer())[1] for _ in 1:3]
b, _ = add_constrained_variable(model, Integer())
add_constraint(model, VectorOfVariables([s; d; r; b]), Cumulative(10))
```

`MathOptInterface.Path`

— Type`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**

```
model = Utilities.Model{Float64}()
from = [1, 1, 2, 2, 3]
to = [2, 3, 3, 4, 4]
s, _ = add_constrained_variable(model, Integer())
t, _ = add_constrained_variable(model, Integer())
ns = add_variables(model, N)
add_constraint.(model, ns, ZeroOne())
es = add_variables(model, E)
add_constraint.(model, es, ZeroOne())
add_constraint(model, VectorOfVariables([s; t; ns; es]), Path(from, to))
```

`MathOptInterface.Reified`

— Type`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\}$.

`MathOptInterface.Table`

— Type`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**

```
model = Utilities.Model{Float64}()
x = add_variables(model, 3)
table = [1 1 0; 0 1 1; 1 0 1; 1 1 1]
add_constraint(model, VectorOfVariables(x), Table(table))
```

## Matrix sets

Matrix sets are vectorized in order 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`

— Type`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.)

**Examples**

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.AbstractSymmetricMatrixSetSquare`

— Type`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.

**Examples**

`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`

— Function```
side_dimension(set::Union{AbstractSymmetricMatrixSetTriangle,
AbstractSymmetricMatrixSetSquare})
```

Side dimension of the matrices in `set`

. By convention, it should be stored in the `side_dimension`

field but if it is not the case for a subtype of `AbstractSymmetricMatrixSetTriangle`

, the method should be implemented for this subtype.

`MathOptInterface.triangular_form`

— Function```
triangular_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`

— Type`PositiveSemidefiniteConeTriangle(side_dimension) <: AbstractSymmetricMatrixSetTriangle`

The (vectorized) cone of symmetric positive semidefinite matrices, with `side_dimension`

rows and columns.

See `AbstractSymmetricMatrixSetTriangle`

for more details on the vectorized form.

`MathOptInterface.PositiveSemidefiniteConeSquare`

— Type`PositiveSemidefiniteConeSquare(side_dimension) <: AbstractSymmetricMatrixSetSquare`

The cone of symmetric positive semidefinite matrices, with 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.

**Examples**

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`

— Type`HermitianPositiveSemidefiniteConeTriangle(side_dimension) <: AbstractVectorSet`

The (vectorized) cone of Hermitian positive semidefinite matrices, with `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`

— Type`LogDetConeTriangle(side_dimension)`

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 argument `side_dimension`

is the side dimension of the matrix `X`

, i.e., its number of rows or columns.

`MathOptInterface.LogDetConeSquare`

— Type`LogDetConeSquare(side_dimension)`

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 argument `side_dimension`

is the side dimension of the matrix `X`

, i.e., its number of rows or columns.

`MathOptInterface.RootDetConeTriangle`

— Type`RootDetConeTriangle(side_dimension)`

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 argument `side_dimension`

is the side dimension of the matrix `X`

, i.e., its number of rows or columns.

`MathOptInterface.RootDetConeSquare`

— Type`RootDetConeSquare(side_dimension)`

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.

`side_dimension`

is the side dimension of the matrix `X`

, i.e., its number of rows or columns.