Constraints
Types
MathOptInterface.ConstraintIndex
— TypeConstraintIndex{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
— Methodis_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
— Functionadd_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 ifmodel
does not supportF
-in-S
constraints, - a
AddConstraintNotAllowed
error is thrown if it supportsF
-in-S
constraints but it cannot add the constraint in its current state and - a
ScalarFunctionConstantNotZero
error may be thrown iffunc
is anAbstractScalarFunction
with nonzero constant andset
isEqualTo
,GreaterThan
,LessThan
orInterval
. - a
LowerBoundAlreadySet
error is thrown ifF
is aVariableIndex
and a constraint was already added to this variable that sets a lower bound. - a
UpperBoundAlreadySet
error is thrown ifF
is aVariableIndex
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
— Functionadd_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
— Functiontransform(
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
— Functionsupports_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
.
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.
Attributes
MathOptInterface.AbstractConstraintAttribute
— TypeAbstractConstraintAttribute
Abstract supertype for attribute objects that can be used to set or get attributes (properties) of constraints in the model.
MathOptInterface.ConstraintName
— TypeConstraintName()
An AbstractConstraintAttribute
for a String
identifying the constraint.
The default name is ""
if not set by the user.
Duplicate names
Two constraints may 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.
VariableIndex connstraints
You should not implement ConstraintName
for VariableIndex
constraints.
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.EqualTo(1.0));
julia> MOI.supports(model, MOI.ConstraintName(), typeof(c))
true
julia> MOI.get(model, MOI.ConstraintName(), c)
""
julia> MOI.set(model, MOI.ConstraintName(), c, "c")
julia> MOI.get(model, MOI.ConstraintName(), c)
"c"
julia> MOI.get(model, MOI.ConstraintIndex, "c")
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> F, S = MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64};
julia> MOI.get(model, MOI.ConstraintIndex{F,S}, "c")
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
Implementation
Optimizers should implement the following methods:
MOI.get(::Optimizer, ::MOI.ConstraintName, ::MOI.ConstraintIndex)::String
MOI.set(::Optimizer, ::MOI.ConstraintName, ::MOI.ConstraintIndex, ::String)::Nothing
MOI.supports(::Optimizer, ::MOI.ConstraintName, ::Type{<:MOI.ConstraintIndex})::Bool
MOI.get(::Optimizer, ::MOI.ConstraintIndex, ::MOI.ConstraintIndex, ::String)::MOI.ConstraintIndex
MathOptInterface.ConstraintPrimalStart
— TypeConstraintPrimalStart()
An AbstractConstraintAttribute
for the initial assignment to the 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
— TypeConstraintDualStart()
An AbstractConstraintAttribute
for the initial assignment to the 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
— TypeConstraintPrimal(result_index::Int = 1)
An AbstractConstraintAttribute
for the constraint's primal value in result result_index
.
Definition
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$ and $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.)
PrimalStatus
Before quering this attribute you should first check PrimalStatus
to confirm that a primal solution is avaiable.
If the PrimalStatus
is NO_SOLUTION
the result of querying this attribute is undefined.
result_index
The optimizer may return multiple primal solutions. See ResultCount
for information on how the results are ordered.
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
.
Implementation
Optimizers should implement the following methods:
MOI.get(
::Optimizer,
::MOI.ConstraintPrimal,
::MOI.ConstraintIndex{<:MOI.AbstractScalarFunction}
)::T
MOI.get(
::Optimizer,
::MOI.ConstraintPrimal,
::MOI.ConstraintIndex{<:MOI.AbstractVectorFunction}
)::Vector{T}
MathOptInterface.ConstraintDual
— TypeConstraintDual(result_index::Int = 1)
An AbstractConstraintAttribute
for the constraint's dual value in result result_index
.
DualStatus
Before quering this attribute you should first check DualStatus
to confirm that a dual solution is avaiable.
If the DualStatus
is NO_SOLUTION
the result of querying this attribute is undefined.
result_index
The optimizer may return multiple dual solutions. See ResultCount
for information on how the results are ordered.
If the solver does not have a dual 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
.
Implementation
Optimizers should implement the following methods:
MOI.get(
::Optimizer,
::MOI.ConstraintDual,
::MOI.ConstraintIndex{<:MOI.AbstractScalarFunction}
)::T
MOI.get(
::Optimizer,
::MOI.ConstraintDual,
::MOI.ConstraintIndex{<:MOI.AbstractVectorFunction}
)::Vector{T}
MathOptInterface.ConstraintBasisStatus
— TypeConstraintBasisStatus(result_index::Int = 1)
An AbstractConstraintAttribute
for the BasisStatusCode
of the constraint in result result_index
, with respect to a basic solution.
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
— TypeConstraintFunction()
An AbstractConstraintAttribute
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.
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.GreaterThan(0.0));
julia> MOI.get(model, MOI.ConstraintFunction(), c)
0.0 + 1.0 MOI.VariableIndex(1)
julia> MOI.set(model, MOI.ConstraintFunction(), c, 2.0 * x)
julia> MOI.get(model, MOI.ConstraintFunction(), c)
0.0 + 2.0 MOI.VariableIndex(1)
Implementation
Optimizers should implement the following methods:
MOI.get(
::Optimizer,
::MOI.ConstraintFunction,
::MOI.ConstraintIndex{F,S},
)::F where {F,S}
If the optimizer supports modifying an existing function, it should implement:
MOI.set(
::Optimizer,
::MOI.ConstraintFunction,
::MOI.ConstraintIndex{F,S},
::F,
)::Nothing where {F,S}
It should not implement supports
.
MathOptInterface.CanonicalConstraintFunction
— TypeCanonicalConstraintFunction()
An AbstractConstraintAttribute
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.
Fallback
By default, MOI.get(model, MOI.CanonicalConstraintFunction(), ci)
falls back 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.
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 + 1.0 * x, MOI.GreaterThan(0.0));
julia> MOI.get(model, MOI.CanonicalConstraintFunction(), c)
0.0 + 2.0 MOI.VariableIndex(1)
Implementation
Optimizers should implement the following methods:
MOI.get(
::Optimizer,
::MOI.CanonicalConstraintFunction,
::MOI.ConstraintIndex{F,S},
)::F where {F,S}
MathOptInterface.ConstraintSet
— TypeConstraintSet()
An AbstractConstraintAttribute
for the AbstractSet
object used to define the constraint.
Example
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variable(model);
julia> c = MOI.add_constraint(model, x, MOI.GreaterThan(0.0));
julia> MOI.get(model, MOI.ConstraintSet(), c)
MathOptInterface.GreaterThan{Float64}(0.0)
julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(1.0))
julia> MOI.get(model, MOI.ConstraintSet(), c)
MathOptInterface.GreaterThan{Float64}(1.0)
Implementation
Optimizers should implement the following methods:
MOI.get(
::Optimizer,
::MOI.ConstraintSet,
::MOI.ConstraintIndex{F,S},
)::S where {F,S}
If the optimizer supports modifying an existing set, it should implement:
MOI.set(
::Optimizer,
::MOI.ConstraintSet,
::MOI.ConstraintIndex{F,S},
::S,
)::Nothing where {F,S}
It should not implement supports
.
MathOptInterface.BasisStatusCode
— TypeBasisStatusCode
An Enum for the value of the ConstraintBasisStatus
and VariableBasisStatus
attributes, explaining the status of a given element with respect to an optimal solution basis.
Notes
When queried as part of ConstraintBasisStatus
, NONBASIC_AT_LOWER
and NONBASIC_AT_UPPER
should be returned 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.
Values
The element is in the basis.
The element is not in the basis.
The element is not in the basis and is at its lower bound.
The element is not in the basis and is at its upper bound.
The element is not in the basis but is also not at one of its bounds.
In a linear program, this status occurs when a variable with no bounds is not in the basis, for example, because it takes the value 0.0
.
MathOptInterface.BASIC
— ConstantMathOptInterface.NONBASIC
— ConstantNONBASIC::BasisStatusCode
An instance of the BasisStatusCode
enum.
About
The element is not in the basis.
MathOptInterface.NONBASIC_AT_LOWER
— ConstantNONBASIC_AT_LOWER::BasisStatusCode
An instance of the BasisStatusCode
enum.
About
The element is not in the basis and is at its lower bound.
MathOptInterface.NONBASIC_AT_UPPER
— ConstantNONBASIC_AT_UPPER::BasisStatusCode
An instance of the BasisStatusCode
enum.
About
The element is not in the basis and is at its upper bound.
MathOptInterface.SUPER_BASIC
— ConstantSUPER_BASIC::BasisStatusCode
An instance of the BasisStatusCode
enum.
About
The element is not in the basis but is also not at one of its bounds.
In a linear program, this status occurs when a variable with no bounds is not in the basis, for example, because it takes the value 0.0
.