# Constraints

## Types

`MathOptInterface.ConstraintIndex`

— Type`ConstraintIndex{F,S}`

A type-safe wrapper for `Int64`

for use in referencing `F`

-in-`S`

constraints in a model.

The parameter `F`

is the type of the function in the constraint, and the parameter `S`

is the type of set in the constraint.

To allow for deletion, indices need not be consecutive.

Indices within a constraint type (that is, `F`

-in-`S`

) must be unique, but non-unique indices across different constraint types are allowed.

If `F`

is `VariableIndex`

then the index is equal to the index of the variable. That is for an `index::ConstraintIndex{VariableIndex}`

, we always have

`index.value == MOI.get(model, MOI.ConstraintFunction(), index).value`

## Functions

`MathOptInterface.is_valid`

— Method`is_valid(model::ModelLike, index::Index)::Bool`

Return a `Bool`

indicating whether this index refers to a valid object in the model `model`

.

`MathOptInterface.add_constraint`

— Function`add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}`

Add the constraint $f(x) \in \mathcal{S}$ where $f$ is defined by `func`

, and $\mathcal{S}$ is defined by `set`

.

```
add_constraint(model::ModelLike, v::VariableIndex, set::S)::ConstraintIndex{VariableIndex,S} where {S}
add_constraint(model::ModelLike, vec::Vector{VariableIndex}, set::S)::ConstraintIndex{VectorOfVariables,S} where {S}
```

Add the constraint $v \in \mathcal{S}$ where $v$ is the variable (or vector of variables) referenced by `v`

and $\mathcal{S}$ is defined by `set`

.

- An
`UnsupportedConstraint`

error is thrown if`model`

does not support`F`

-in-`S`

constraints, - a
`AddConstraintNotAllowed`

error is thrown if it supports`F`

-in-`S`

constraints but it cannot add the constraint in its current state and - a
`ScalarFunctionConstantNotZero`

error may be thrown if`func`

is an`AbstractScalarFunction`

with nonzero constant and`set`

is`EqualTo`

,`GreaterThan`

,`LessThan`

or`Interval`

. - a
`LowerBoundAlreadySet`

error is thrown if`F`

is a`VariableIndex`

and a constraint was already added to this variable that sets a lower bound. - a
`UpperBoundAlreadySet`

error is thrown if`F`

is a`VariableIndex`

and a constraint was already added to this variable that sets an upper bound.

`MOI.add_constraint(map::Map, vi::MOI.VariableIndex, set::MOI.AbstractScalarSet)`

Record that a constraint `vi`

-in-`set`

is added and throws if a lower or upper bound is set by this constraint and such bound has already been set for `vi`

.

`MathOptInterface.add_constraints`

— Function`add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}`

Add the set of constraints specified by each function-set pair in `funcs`

and `sets`

. `F`

and `S`

should be concrete types. This call is equivalent to `add_constraint.(model, funcs, sets)`

but may be more efficient.

`MathOptInterface.transform`

— Function```
transform(
model::ModelLike,
c::ConstraintIndex{F,S1},
newset::S2,
)::ConstraintIndex{F,S2}
```

Replace the set in constraint `c`

with `newset`

.

The constraint index `c`

will no longer be valid, and the function returns a new constraint index with the correct type.

Solvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a `LessThan`

to `GreaterThan`

set). In addition, set modification (where `S1 = S2`

) should be performed via the `modify`

function.

Typically, the user should delete the constraint and add a new one.

**Example**

```
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model);
julia> c = MOI.add_constraint(model, 1.0 * x, MOI.LessThan(2.0));
julia> print(model)
Feasibility
Subject to:
ScalarAffineFunction{Float64}-in-LessThan{Float64}
0.0 + 1.0 v[1] <= 2.0
julia> c2 = MOI.transform(model, c, MOI.GreaterThan(0.0))
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.GreaterThan{Float64}}(1)
julia> print(model)
Feasibility
Subject to:
ScalarAffineFunction{Float64}-in-GreaterThan{Float64}
0.0 + 1.0 v[1] >= 0.0
julia> MOI.is_valid(model, c)
false
```

`MathOptInterface.supports_constraint`

— Function```
MOI.supports_constraint(
BT::Type{<:AbstractBridge},
F::Type{<:MOI.AbstractFunction},
S::Type{<:MOI.AbstractSet},
)::Bool
```

Return a `Bool`

indicating whether the bridges of type `BT`

support bridging `F`

-in-`S`

constraints.

**Implementation notes**

- This method depends only on the type of the inputs, not the runtime values.
- There is a default fallback, so you need only implement this method for constraint types that the bridge implements.

```
supports_constraint(
model::ModelLike,
::Type{F},
::Type{S},
)::Bool where {F<:AbstractFunction,S<:AbstractSet}
```

Return a `Bool`

indicating whether `model`

supports `F`

-in-`S`

constraints, that is, `copy_to(model, src)`

does not throw `UnsupportedConstraint`

when `src`

contains `F`

-in-`S`

constraints. If `F`

-in-`S`

constraints are only not supported in specific circumstances, for example, `F`

-in-`S`

constraints cannot be combined with another type of constraint, it should still return `true`

.

## Attributes

`MathOptInterface.AbstractConstraintAttribute`

— Type`AbstractConstraintAttribute`

Abstract supertype for attribute objects that can be used to set or get attributes (properties) of constraints in the model.

`MathOptInterface.ConstraintName`

— Type`ConstraintName()`

A constraint attribute for a string identifying the constraint.

It is *valid* for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using `get`

, regardless of whether they have the same `F`

-in-`S`

type.

`ConstraintName`

has a default value of `""`

if not set.

**Notes**

You should *not* implement `ConstraintName`

for `VariableIndex`

constraints.

`MathOptInterface.ConstraintPrimalStart`

— Type`ConstraintPrimalStart()`

A constraint attribute for the initial assignment to some constraint's `ConstraintPrimal`

that the optimizer may use to warm-start the solve.

May be `nothing`

(unset), a number for `AbstractScalarFunction`

, or a vector for `AbstractVectorFunction`

.

`MathOptInterface.ConstraintDualStart`

— Type`ConstraintDualStart()`

A constraint attribute for the initial assignment to some constraint's `ConstraintDual`

that the optimizer may use to warm-start the solve.

May be `nothing`

(unset), a number for `AbstractScalarFunction`

, or a vector for `AbstractVectorFunction`

.

`MathOptInterface.ConstraintPrimal`

— Type`ConstraintPrimal(result_index::Int = 1)`

A constraint attribute for the assignment to some constraint's primal value in result `result_index`

.

If the constraint is `f(x) in S`

, then in most cases the `ConstraintPrimal`

is the value of `f`

, evaluated at the corresponding `VariablePrimal`

solution.

However, some conic solvers reformulate `b - Ax in S`

to `s = b - Ax, s in S`

. These solvers may return the value of `s`

for `ConstraintPrimal`

, rather than `b - Ax`

. (Although these are constrained by an equality constraint, due to numerical tolerances they may not be identical.)

If the solver does not have a primal value for the constraint because the `result_index`

is beyond the available solutions (whose number is indicated by the `ResultCount`

attribute), getting this attribute must throw a `ResultIndexBoundsError`

. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check `PrimalStatus`

before accessing the `ConstraintPrimal`

attribute.

If `result_index`

is omitted, it is 1 by default. See `ResultCount`

for information on how the results are ordered.

`MathOptInterface.ConstraintDual`

— Type`ConstraintDual(result_index::Int = 1)`

A constraint attribute for the assignment to some constraint's dual value in result `result_index`

. If `result_index`

is omitted, it is 1 by default.

If the solver does not have a dual value for the variable because the `result_index`

is beyond the available solutions (whose number is indicated by the `ResultCount`

attribute), getting this attribute must throw a `ResultIndexBoundsError`

. Otherwise, if the result is unavailable for another reason (for instance, only a primal solution is available), the result is undefined. Users should first check `DualStatus`

before accessing the `ConstraintDual`

attribute.

See `ResultCount`

for information on how the results are ordered.

`MathOptInterface.ConstraintBasisStatus`

— Type`ConstraintBasisStatus(result_index::Int = 1)`

A constraint attribute for the `BasisStatusCode`

of some constraint in result `result_index`

, with respect to an available optimal solution basis. If `result_index`

is omitted, it is 1 by default.

If the solver does not have a basis status for the constraint because the `result_index`

is beyond the available solutions (whose number is indicated by the `ResultCount`

attribute), getting this attribute must throw a `ResultIndexBoundsError`

. Otherwise, if the result is unavailable for another reason (for instance, only a dual solution is available), the result is undefined. Users should first check `PrimalStatus`

before accessing the `ConstraintBasisStatus`

attribute.

See `ResultCount`

for information on how the results are ordered.

**Notes**

For the basis status of a variable, query `VariableBasisStatus`

.

`ConstraintBasisStatus`

does not apply to `VariableIndex`

constraints. You can infer the basis status of a `VariableIndex`

constraint by looking at the result of `VariableBasisStatus`

.

`MathOptInterface.ConstraintFunction`

— Type`ConstraintFunction()`

A constraint attribute for the `AbstractFunction`

object used to define the constraint.

It is guaranteed to be equivalent but not necessarily identical to the function provided by the user.

`MathOptInterface.CanonicalConstraintFunction`

— Type`CanonicalConstraintFunction()`

A constraint attribute for a canonical representation of the `AbstractFunction`

object used to define the constraint.

Getting this attribute is guaranteed to return a function that is equivalent but not necessarily identical to the function provided by the user.

By default, `MOI.get(model, MOI.CanonicalConstraintFunction(), ci)`

fallbacks to `MOI.Utilities.canonical(MOI.get(model, MOI.ConstraintFunction(), ci))`

. However, if `model`

knows that the constraint function is canonical then it can implement a specialized method that directly return the function without calling `Utilities.canonical`

. Therefore, the value returned **cannot** be assumed to be a copy of the function stored in `model`

. Moreover, `Utilities.Model`

checks with `Utilities.is_canonical`

whether the function stored internally is already canonical and if it's the case, then it returns the function stored internally instead of a copy.

`MathOptInterface.ConstraintSet`

— Type`ConstraintSet()`

A constraint attribute for the `AbstractSet`

object used to define the constraint.

`MathOptInterface.BasisStatusCode`

— Type`BasisStatusCode`

An Enum of possible values for the `ConstraintBasisStatus`

and `VariableBasisStatus`

attributes, explaining the status of a given element with respect to an optimal solution basis.

**Notes**

`NONBASIC_AT_LOWER`

and`NONBASIC_AT_UPPER`

should be used only for constraints with the`Interval`

set. In this case, they are necessary to distinguish which side of the constraint is active. One-sided constraints (for example,`LessThan`

and`GreaterThan`

) should use`NONBASIC`

instead of the`NONBASIC_AT_*`

values. This restriction does not apply to`VariableBasisStatus`

, which should return`NONBASIC_AT_*`

regardless of whether the alternative bound exists.In linear programs,

`SUPER_BASIC`

occurs when a variable with no bounds is not in the basis.

**Values**

Possible values are:

`BASIC`

: element is in the basis`NONBASIC`

: element is not in the basis`NONBASIC_AT_LOWER`

: element is not in the basis and is at its lower bound`NONBASIC_AT_UPPER`

: element is not in the basis and is at its upper bound`SUPER_BASIC`

: element is not in the basis but is also not at one of its bounds

`MathOptInterface.BASIC`

— Constant`MathOptInterface.NONBASIC`

— Constant`NONBASIC::BasisStatusCode`

An instance of the `BasisStatusCode`

enum.

`NONBASIC`

: element is not in the basis

`MathOptInterface.NONBASIC_AT_LOWER`

— Constant`NONBASIC_AT_LOWER::BasisStatusCode`

An instance of the `BasisStatusCode`

enum.

`NONBASIC_AT_LOWER`

: element is not in the basis and is at its lower bound

`MathOptInterface.NONBASIC_AT_UPPER`

— Constant`NONBASIC_AT_UPPER::BasisStatusCode`

An instance of the `BasisStatusCode`

enum.

`NONBASIC_AT_UPPER`

: element is not in the basis and is at its upper bound

`MathOptInterface.SUPER_BASIC`

— Constant`SUPER_BASIC::BasisStatusCode`

An instance of the `BasisStatusCode`

enum.

`SUPER_BASIC`

: element is not in the basis but is also not at one of its bounds