# Models

## Attribute interface

`MathOptInterface.is_set_by_optimize`

— Function`is_set_by_optimize(::AnyAttribute)`

Return a `Bool`

indicating whether the value of the attribute is modified during an `optimize!`

call, that is, the attribute is used to query the result of the optimization.

**Important note when defining new attributes**

This function returns `false`

by default so it should be implemented for attributes that are modified by `optimize!`

.

`MathOptInterface.is_copyable`

— Function`is_copyable(::AnyAttribute)`

Return a `Bool`

indicating whether the value of the attribute may be copied during `copy_to`

using `set`

.

**Important note when defining new attributes**

By default `is_copyable(attr)`

returns `!is_set_by_optimize(attr)`

. A specific method should be defined for attributes which are copied indirectly during `copy_to`

. For instance, both `is_copyable`

and `is_set_by_optimize`

return `false`

for the following attributes:

`ListOfOptimizerAttributesSet`

,`ListOfModelAttributesSet`

,`ListOfConstraintAttributesSet`

and`ListOfVariableAttributesSet`

.`SolverName`

and`RawSolver`

: these attributes cannot be set.`NumberOfVariables`

and`ListOfVariableIndices`

: these attributes are set indirectly by`add_variable`

and`add_variables`

.`ObjectiveFunctionType`

: this attribute is set indirectly when setting the`ObjectiveFunction`

attribute.`NumberOfConstraints`

,`ListOfConstraintIndices`

,`ListOfConstraintTypesPresent`

,`CanonicalConstraintFunction`

,`ConstraintFunction`

and`ConstraintSet`

: these attributes are set indirectly by`add_constraint`

and`add_constraints`

.

`MathOptInterface.get`

— Function`MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)::Int64`

Return the number of variables created by the bridge `b`

in the model.

See also `MOI.NumberOfConstraints`

.

**Implementation notes**

- There is a default fallback, so you need only implement this if the bridge adds new variables.

`MOI.get(b::AbstractBridge, ::MOI.ListOfVariableIndices)`

Return the list of variables created by the bridge `b`

.

See also `MOI.ListOfVariableIndices`

.

**Implementation notes**

- There is a default fallback, so you need only implement this if the bridge adds new variables.

`MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F,S})::Int64 where {F,S}`

Return the number of constraints of the type `F`

-in-`S`

created by the bridge `b`

.

See also `MOI.NumberOfConstraints`

.

**Implementation notes**

- There is a default fallback, so you need only implement this for the constraint types returned by
`added_constraint_types`

.

`MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F,S}) where {F,S}`

Return a `Vector{ConstraintIndex{F,S}}`

with indices of all constraints of type `F`

-in-`S`

created by the bride `b`

.

See also `MOI.ListOfConstraintIndices`

.

**Implementation notes**

- There is a default fallback, so you need only implement this for the constraint types returned by
`added_constraint_types`

.

```
function MOI.get(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
bridge::AbstractBridge,
)
```

Return the value of the attribute `attr`

of the model `model`

for the constraint bridged by `bridge`

.

`get(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute)`

Return an attribute `attr`

of the optimizer `optimizer`

.

`get(model::ModelLike, attr::AbstractModelAttribute)`

Return an attribute `attr`

of the model `model`

.

`get(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex)`

If the attribute `attr`

is set for the variable `v`

in the model `model`

, return its value, return `nothing`

otherwise. If the attribute `attr`

is not supported by `model`

then an error should be thrown instead of returning `nothing`

.

`get(model::ModelLike, attr::AbstractVariableAttribute, v::Vector{VariableIndex})`

Return a vector of attributes corresponding to each variable in the collection `v`

in the model `model`

.

`get(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex)`

If the attribute `attr`

is set for the constraint `c`

in the model `model`

, return its value, return `nothing`

otherwise. If the attribute `attr`

is not supported by `model`

then an error should be thrown instead of returning `nothing`

.

```
get(
model::ModelLike,
attr::AbstractConstraintAttribute,
c::Vector{ConstraintIndex{F,S}},
) where {F,S}
```

Return a vector of attributes corresponding to each constraint in the collection `c`

in the model `model`

.

`get(model::ModelLike, ::Type{VariableIndex}, name::String)`

If a variable with name `name`

exists in the model `model`

, return the corresponding index, otherwise return `nothing`

. Errors if two variables have the same name.

```
get(
model::ModelLike,
::Type{ConstraintIndex{F,S}},
name::String,
) where {F,S}
```

If an `F`

-in-`S`

constraint with name `name`

exists in the model `model`

, return the corresponding index, otherwise return `nothing`

. Errors if two constraints have the same name.

`get(model::ModelLike, ::Type{ConstraintIndex}, name::String)`

If *any* constraint with name `name`

exists in the model `model`

, return the corresponding index, otherwise return `nothing`

. This version is available for convenience but may incur a performance penalty because it is not type stable. Errors if two constraints have the same name.

`get(model::Model, attr::MathOptInterface.AbstractOptimizerAttribute)`

Return the value of the attribute `attr`

from the model's MOI backend.

`get(model::Model, attr::MathOptInterface.AbstractModelAttribute)`

Return the value of the attribute `attr`

from the model's MOI backend.

`MathOptInterface.get!`

— Function`MathOptInterface.set`

— Function```
function MOI.set(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
bridge::AbstractBridge,
value,
)
```

Set the value of the attribute `attr`

of the model `model`

for the constraint bridged by `bridge`

.

`set(optimizer::AbstractOptimizer, attr::AbstractOptimizerAttribute, value)`

Assign `value`

to the attribute `attr`

of the optimizer `optimizer`

.

`set(model::ModelLike, attr::AbstractModelAttribute, value)`

Assign `value`

to the attribute `attr`

of the model `model`

.

`set(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)`

Assign `value`

to the attribute `attr`

of variable `v`

in model `model`

.

```
set(
model::ModelLike,
attr::AbstractVariableAttribute,
v::Vector{VariableIndex},
vector_of_values,
)
```

Assign a value respectively to the attribute `attr`

of each variable in the collection `v`

in model `model`

.

```
set(
model::ModelLike,
attr::AbstractConstraintAttribute,
c::ConstraintIndex,
value,
)
```

Assign a value to the attribute `attr`

of constraint `c`

in model `model`

.

```
set(
model::ModelLike,
attr::AbstractConstraintAttribute,
c::Vector{ConstraintIndex{F,S}},
vector_of_values,
) where {F,S}
```

Assign a value respectively to the attribute `attr`

of each constraint in the collection `c`

in model `model`

.

An `UnsupportedAttribute`

error is thrown if `model`

does not support the attribute `attr`

(see `supports`

) and a `SetAttributeNotAllowed`

error is thrown if it supports the attribute `attr`

but it cannot be set.

```
set(
model::ModelLike,
::ConstraintSet,
c::ConstraintIndex{F,S},
set::S,
) where {F,S}
```

Change the set of constraint `c`

to the new set `set`

which should be of the same type as the original set.

```
set(
model::ModelLike,
::ConstraintFunction,
c::ConstraintIndex{F,S},
func::F,
) where {F,S}
```

Replace the function in constraint `c`

with `func`

. `F`

must match the original function type used to define the constraint.

Setting the constraint function is not allowed if `F`

is `VariableIndex`

; a `SettingVariableIndexNotAllowed`

error is thrown instead. This is because, it would require changing the index `c`

since the index of `VariableIndex`

constraints must be the same as the index of the variable.

`MathOptInterface.supports`

— Function```
MOI.supports(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
BT::Type{<:AbstractBridge},
)
```

Return a `Bool`

indicating whether `BT`

supports setting `attr`

to `model`

.

`supports(model::ModelLike, sub::AbstractSubmittable)::Bool`

Return a `Bool`

indicating whether `model`

supports the submittable `sub`

.

`supports(model::ModelLike, attr::AbstractOptimizerAttribute)::Bool`

Return a `Bool`

indicating whether `model`

supports the optimizer attribute `attr`

. That is, it returns `false`

if `copy_to(model, src)`

shows a warning in case `attr`

is in the `ListOfOptimizerAttributesSet`

of `src`

; see `copy_to`

for more details on how unsupported optimizer attributes are handled in copy.

`supports(model::ModelLike, attr::AbstractModelAttribute)::Bool`

Return a `Bool`

indicating whether `model`

supports the model attribute `attr`

. That is, it returns `false`

if `copy_to(model, src)`

cannot be performed in case `attr`

is in the `ListOfModelAttributesSet`

of `src`

.

```
supports(
model::ModelLike,
attr::AbstractVariableAttribute,
::Type{VariableIndex},
)::Bool
```

Return a `Bool`

indicating whether `model`

supports the variable attribute `attr`

. That is, it returns `false`

if `copy_to(model, src)`

cannot be performed in case `attr`

is in the `ListOfVariableAttributesSet`

of `src`

.

```
supports(
model::ModelLike,
attr::AbstractConstraintAttribute,
::Type{ConstraintIndex{F,S}},
)::Bool where {F,S}
```

Return a `Bool`

indicating whether `model`

supports the constraint attribute `attr`

applied to an `F`

-in-`S`

constraint. That is, it returns `false`

if `copy_to(model, src)`

cannot be performed in case `attr`

is in the `ListOfConstraintAttributesSet`

of `src`

.

For all five methods, if the attribute is only not supported in specific circumstances, it should still return `true`

.

Note that `supports`

is only defined for attributes for which `is_copyable`

returns `true`

as other attributes do not appear in the list of attributes set obtained by `ListOf...AttributesSet`

.

`MathOptInterface.attribute_value_type`

— Function## Model interface

`MathOptInterface.ModelLike`

— Type`ModelLike`

Abstract supertype for objects that implement the "Model" interface for defining an optimization problem.

`MathOptInterface.is_empty`

— Function`is_empty(model::ModelLike)`

Returns `false`

if the `model`

has any model attribute set or has any variables or constraints.

Note that an empty model can have optimizer attributes set.

`MathOptInterface.empty!`

— Function`empty!(model::ModelLike)`

Empty the model, that is, remove all variables, constraints and model attributes but not optimizer attributes.

`MathOptInterface.write_to_file`

— Function`write_to_file(model::ModelLike, filename::String)`

Write the current model to the file at `filename`

.

Supported file types depend on the model type.

`MathOptInterface.read_from_file`

— Function`read_from_file(model::ModelLike, filename::String)`

Read the file `filename`

into the model `model`

. If `model`

is non-empty, this may throw an error.

Supported file types depend on the model type.

**Note**

Once the contents of the file are loaded into the model, users can query the variables via `get(model, ListOfVariableIndices())`

. However, some filetypes, such as LP files, do not maintain an explicit ordering of the variables. Therefore, the returned list may be in an arbitrary order.

To avoid depending on the order of the indices, look up each variable index by name using `get(model, VariableIndex, "name")`

.

`MathOptInterface.supports_incremental_interface`

— Function`supports_incremental_interface(model::ModelLike)`

Return a `Bool`

indicating whether `model`

supports building incrementally via `add_variable`

and `add_constraint`

.

The main purpose of this function is to determine whether a model can be loaded into `model`

incrementally or whether it should be cached and copied at once instead.

`MathOptInterface.copy_to`

— Function`copy_to(dest::ModelLike, src::ModelLike)::IndexMap`

Copy the model from `src`

into `dest`

.

The target `dest`

is emptied, and all previous indices to variables and constraints in `dest`

are invalidated.

Returns an `IndexMap`

object that translates variable and constraint indices from the `src`

model to the corresponding indices in the `dest`

model.

**Notes**

- If a constraint that in
`src`

is not supported by`dest`

, then an`UnsupportedConstraint`

error is thrown. - If an
`AbstractModelAttribute`

,`AbstractVariableAttribute`

, or`AbstractConstraintAttribute`

is set in`src`

but not supported by`dest`

, then an`UnsupportedAttribute`

error is thrown.

`AbstractOptimizerAttribute`

s are *not* copied to the `dest`

model.

**IndexMap**

Implementations of `copy_to`

must return an `IndexMap`

. For technical reasons, this type is defined in the Utilities submodule as `MOI.Utilities.IndexMap`

. However, since it is an integral part of the MOI API, we provide `MOI.IndexMap`

as an alias.

**Example**

```
# Given empty `ModelLike` objects `src` and `dest`.
x = add_variable(src)
is_valid(src, x) # true
is_valid(dest, x) # false (`dest` has no variables)
index_map = copy_to(dest, src)
is_valid(dest, x) # false (unless index_map[x] == x)
is_valid(dest, index_map[x]) # true
```

`MathOptInterface.IndexMap`

— Type`IndexMap()`

The dictionary-like object returned by `copy_to`

.

**IndexMap**

Implementations of `copy_to`

must return an `IndexMap`

. For technical reasons, the `IndexMap`

type is defined in the Utilities submodule as `MOI.Utilities.IndexMap`

. However, since it is an integral part of the MOI API, we provide this `MOI.IndexMap`

as an alias.

## Model attributes

`MathOptInterface.AbstractModelAttribute`

— Type`AbstractModelAttribute`

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

`MathOptInterface.Name`

— Type`Name()`

A model attribute for the string identifying the model. It has a default value of `""`

if not set`.

`MathOptInterface.ObjectiveFunction`

— Type`ObjectiveFunction{F<:AbstractScalarFunction}()`

A model attribute for the objective function which has a type `F<:AbstractScalarFunction`

.

`F`

should be guaranteed to be equivalent but not necessarily identical to the function type provided by the user.

Throws an `InexactError`

if the objective function cannot be converted to `F`

, e.g., the objective function is quadratic and `F`

is `ScalarAffineFunction{Float64}`

or it has non-integer coefficient and `F`

is `ScalarAffineFunction{Int}`

.

`MathOptInterface.ObjectiveFunctionType`

— Type`ObjectiveFunctionType()`

A model attribute for the type `F`

of the objective function set using the `ObjectiveFunction{F}`

attribute.

**Examples**

In the following code, `attr`

should be equal to `MOI.VariableIndex`

:

```
x = MOI.add_variable(model)
MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), x)
attr = MOI.get(model, MOI.ObjectiveFunctionType())
```

`MathOptInterface.ObjectiveSense`

— Type`ObjectiveSense()`

A model attribute for the objective sense of the objective function, which must be an `OptimizationSense`

: `MIN_SENSE`

, `MAX_SENSE`

, or `FEASIBILITY_SENSE`

. The default is `FEASIBILITY_SENSE`

.

**Interaction with ObjectiveFunction**

Setting the sense to `FEASIBILITY_SENSE`

unsets the `ObjectiveFunction`

attribute. That is, if you first set `ObjectiveFunction`

and then set `ObjectiveSense`

to be `FEASIBILITY_SENSE`

, no objective function will be passed to the solver.

In addition, some reformulations of `ObjectiveFunction`

via bridges rely on the value of `ObjectiveSense`

. Therefore, you should set `ObjectiveSense`

before setting `ObjectiveFunction`

.

`MathOptInterface.NumberOfVariables`

— Type`NumberOfVariables()`

A model attribute for the number of variables in the model.

`MathOptInterface.ListOfVariableIndices`

— Type`ListOfVariableIndices()`

A model attribute for the `Vector{VariableIndex}`

of all variable indices present in the model (i.e., of length equal to the value of `NumberOfVariables`

in the order in which they were added.

`MathOptInterface.ListOfConstraintTypesPresent`

— Type`ListOfConstraintTypesPresent()`

A model attribute for the list of tuples of the form `(F,S)`

, where `F`

is a function type and `S`

is a set type indicating that the attribute `NumberOfConstraints{F,S}`

has a value greater than zero.

`MathOptInterface.NumberOfConstraints`

— Type`NumberOfConstraints{F,S}()`

A model attribute for the number of constraints of the type `F`

-in-`S`

present in the model.

`MathOptInterface.ListOfConstraintIndices`

— Type`ListOfConstraintIndices{F,S}()`

A model attribute for the `Vector{ConstraintIndex{F,S}}`

of all constraint indices of type `F`

-in-`S`

in the model (i.e., of length equal to the value of `NumberOfConstraints{F,S}`

) in the order in which they were added.

`MathOptInterface.ListOfOptimizerAttributesSet`

— Type`ListOfOptimizerAttributesSet()`

An optimizer attribute for the `Vector{AbstractOptimizerAttribute}`

of all optimizer attributes that were set.

`MathOptInterface.ListOfModelAttributesSet`

— Type`ListOfModelAttributesSet()`

A model attribute for the `Vector{AbstractModelAttribute}`

of all model attributes `attr`

such that:

`is_copyable(attr)`

returns`true`

, and- the attribute was set to the model

`MathOptInterface.ListOfVariableAttributesSet`

— Type`ListOfVariableAttributesSet()`

A model attribute for the `Vector{AbstractVariableAttribute}`

of all variable attributes `attr`

such that 1) `is_copyable(attr)`

returns `true`

and 2) the attribute was set to variables.

`MathOptInterface.ListOfConstraintAttributesSet`

— Type`ListOfConstraintAttributesSet{F, S}()`

A model attribute for the `Vector{AbstractConstraintAttribute}`

of all constraint attributes `attr`

such that:

`is_copyable(attr)`

returns`true`

and- the attribute was set to
`F`

-in-`S`

constraints.

**Note**

The attributes `ConstraintFunction`

and `ConstraintSet`

should not be included in the list even if then have been set with `set`

.

## Optimizer interface

`MathOptInterface.AbstractOptimizer`

— Type`AbstractOptimizer <: ModelLike`

Abstract supertype for objects representing an instance of an optimization problem tied to a particular solver. This is typically a solver's in-memory representation. In addition to `ModelLike`

, `AbstractOptimizer`

objects let you solve the model and query the solution.

`MathOptInterface.OptimizerWithAttributes`

— Type```
struct OptimizerWithAttributes
optimizer_constructor
params::Vector{Pair{AbstractOptimizerAttribute,<:Any}}
end
```

Object grouping an optimizer constructor and a list of optimizer attributes. Instances are created with `instantiate`

.

`MathOptInterface.optimize!`

— Function`optimize!(optimizer::AbstractOptimizer)`

Optimize the problem contained in `optimizer`

.

Before calling `optimize!`

, the problem should first be constructed using the incremental interface (see `supports_incremental_interface`

) or `copy_to`

.

`MathOptInterface.optimize!`

— Method`optimize!(dest::AbstractOptimizer, src::ModelLike)::Tuple{IndexMap,Bool}`

A "one-shot" call that copies the problem from `src`

into `dest`

and then uses `dest`

to optimize the problem.

Returns a tuple of an `IndexMap`

and a `Bool`

`copied`

.

- The
`IndexMap`

object translates variable and constraint indices from the`src`

model to the corresponding indices in the`dest`

optimizer. See`copy_to`

for details. - If
`copied == true`

,`src`

was copied to`dest`

and then cached, allowing incremental modification if supported by the solver. - If
`copied == false`

, a cache of the model was*not*kept in`dest`

. Therefore, only the solution information (attributes for which`is_set_by_optimize`

is true) is available to query.

The main purpose of `optimize!`

method with two arguments is for use in `Utilities.CachingOptimizer`

.

**Relationship to the single-argument optimize!**

The default fallback of `optimize!(dest::AbstractOptimizer, src::ModelLike)`

is

```
function optimize!(dest::AbstractOptimizer, src::ModelLike)
index_map = copy_to(dest, src)
optimize!(dest)
return index_map, true
end
```

Therefore, subtypes of `AbstractOptimizer`

should either implement this two-argument method, or implement both `copy_to(::Optimizer, ::ModelLike)`

and `optimize!(::Optimizer)`

.

`MathOptInterface.instantiate`

— Function```
instantiate(
optimizer_constructor,
with_cache_type::Union{Nothing,Type} = nothing,
with_bridge_type::Union{Nothing,Type} = nothing,
)
```

Create an instance of an optimizer by either:

- calling
`optimizer_constructor.optimizer_constructor()`

and setting the parameters in`optimizer_constructor.params`

if`optimizer_constructor`

is a`OptimizerWithAttributes`

- calling
`optimizer_constructor()`

if`optimizer_constructor`

is callable.

**with cachetype**

If `with_cache_type`

is not `nothing`

, then the optimizer is wrapped in a `Utilities.CachingOptimizer`

to store a cache of the model. This is most useful if the optimizer you are constructing does not support the incremental interface (see `supports_incremental_interface`

).

**with bridgetype**

If `with_bridge_type`

is not `nothing`

, the optimizer is wrapped in a `Bridges.full_bridge_optimizer`

, enabling all the bridges defined in the MOI.Bridges submodule with coefficient type `with_bridge_type`

.

In addition, if the optimizer created by `optimizer_constructor`

does not support the incremental interface (see `supports_incremental_interface`

), then, irrespective of `with_cache_type`

, the optimizer is wrapped in a `Utilities.CachingOptimizer`

to store a cache of the bridged model.

If `with_cache_type`

and `with_bridge_type`

are both not `nothing`

, then they must be the same type.

`MathOptInterface.default_cache`

— Function`default_cache(optimizer::ModelLike, ::Type{T}) where {T}`

Return a new instance of the default model type to be used as cache for `optimizer`

in a `Utilities.CachingOptimizer`

for holding constraints of coefficient type `T`

. By default, this returns `Utilities.UniversalFallback(Utilities.Model{T}())`

. If copying from a instance of a given model type is faster for `optimizer`

then a new method returning an instance of this model type should be defined.

## Optimizer attributes

`MathOptInterface.AbstractOptimizerAttribute`

— Type`AbstractOptimizerAttribute`

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

**Notes**

The difference between `AbstractOptimizerAttribute`

and `AbstractModelAttribute`

lies in the behavior of `is_empty`

, `empty!`

and `copy_to`

. Typically optimizer attributes affect only how the model is solved.

`MathOptInterface.SolverName`

— Type`SolverName()`

An optimizer attribute for the string identifying the solver/optimizer.

`MathOptInterface.SolverVersion`

— Type`SolverVersion()`

An optimizer attribute for the string identifying the version of the solver.

For solvers supporting semantic versioning, the `SolverVersion`

should be a string of the form "vMAJOR.MINOR.PATCH", so that it can be converted to a Julia `VersionNumber`

(e.g., `VersionNumber("v1.2.3")).

We do not require Semantic Versioning because some solvers use alternate versioning systems. For example, CPLEX uses Calendar Versioning, so `SolverVersion`

will return a string like `"202001"`

.

`MathOptInterface.Silent`

— Type`Silent()`

An optimizer attribute for silencing the output of an optimizer. When `set`

to `true`

, it takes precedence over any other attribute controlling verbosity and requires the solver to produce no output. The default value is `false`

which has no effect. In this case the verbosity is controlled by other attributes.

**Note**

Every optimizer should have verbosity on by default. For instance, if a solver has a solver-specific log level attribute, the MOI implementation should set it to `1`

by default. If the user sets `Silent`

to `true`

, then the log level should be set to `0`

, even if the user specifically sets a value of log level. If the value of `Silent`

is `false`

then the log level set to the solver is the value given by the user for this solver-specific parameter or `1`

if none is given.

`MathOptInterface.TimeLimitSec`

— Type`TimeLimitSec()`

An optimizer attribute for setting a time limit (in seconnds) for an optimization. When `set`

to `nothing`

, it deactivates the solver time limit. The default value is `nothing`

.

`MathOptInterface.RawOptimizerAttribute`

— Type`RawOptimizerAttribute(name::String)`

An optimizer attribute for the solver-specific parameter identified by `name`

.

`MathOptInterface.NumberOfThreads`

— Type`NumberOfThreads()`

An optimizer attribute for setting the number of threads used for an optimization. When set to `nothing`

uses solver default. Values are positive integers. The default value is `nothing`

.

`MathOptInterface.RawSolver`

— Type`RawSolver()`

A model attribute for the object that may be used to access a solver-specific API for this optimizer.

`MathOptInterface.AbsoluteGapTolerance`

— Type`AbsoluteGapTolerance()`

An optimizer attribute for setting the absolute gap tolerance for an optimization. This is an *optimizer* attribute, and should be set before calling `optimize!`

. When set to `nothing`

(if supported), uses solver default.

To set a *relative* gap tolerance, see `RelativeGapTolerance`

.

The mathematical definition of "absolute gap", and its treatment during the optimization, are solver-dependent. However, assuming no other limit nor issue is encountered during the optimization, most solvers that implement this attribute will stop once $|f - b| ≤ g_{abs}$, where $b$ is the best bound, $f$ is the best feasible objective value, and $g_{abs}$ is the absolute gap.

`MathOptInterface.RelativeGapTolerance`

— Type`RelativeGapTolerance()`

An optimizer attribute for setting the relative gap tolerance for an optimization. This is an *optimizer* attribute, and should be set before calling `optimize!`

. When set to `nothing`

(if supported), uses solver default.

If you are looking for the relative gap of the current best solution, see `RelativeGap`

. If no limit nor issue is encountered during the optimization, the value of `RelativeGap`

should be at most as large as `RelativeGapTolerance`

.

```
# Before optimizing: set relative gap tolerance
# set 0.1% relative gap tolerance
MOI.set(model, MOI.RelativeGapTolerance(), 1e-3)
MOI.optimize!(model)
# After optimizing (assuming all went well)
# The relative gap tolerance has not changed...
MOI.get(model, MOI.RelativeGapTolerance()) # returns 1e-3
# ... and the relative gap of the obtained solution is smaller or equal to the
# tolerance
MOI.get(model, MOI.RelativeGap()) # should return something ≤ 1e-3
```

The mathematical definition of "relative gap", and its allowed range, are solver-dependent. Typically, solvers expect a value between `0.0`

and `1.0`

.

List of attributes useful for optimizers

`MathOptInterface.TerminationStatus`

— Type`TerminationStatus()`

A model attribute for the `TerminationStatusCode`

explaining why the optimizer stopped.

`MathOptInterface.TerminationStatusCode`

— Type`TerminationStatusCode`

An Enum of possible values for the `TerminationStatus`

attribute. This attribute is meant to explain the reason why the optimizer stopped executing in the most recent call to `optimize!`

.

If no call has been made to `optimize!`

, then the `TerminationStatus`

is:

`OPTIMIZE_NOT_CALLED`

: The algorithm has not started.

**OK**

These are generally OK statuses, i.e., the algorithm ran to completion normally.

`OPTIMAL`

: The algorithm found a globally optimal solution.`INFEASIBLE`

: The algorithm concluded that no feasible solution exists.`DUAL_INFEASIBLE`

: The algorithm concluded that no dual bound exists for the problem. If, additionally, a feasible (primal) solution is known to exist, this status typically implies that the problem is unbounded, with some technical exceptions.`LOCALLY_SOLVED`

: The algorithm converged to a stationary point, local optimal solution, could not find directions for improvement, or otherwise completed its search without global guarantees.`LOCALLY_INFEASIBLE`

: The algorithm converged to an infeasible point or otherwise completed its search without finding a feasible solution, without guarantees that no feasible solution exists.`INFEASIBLE_OR_UNBOUNDED`

: The algorithm stopped because it decided that the problem is infeasible or unbounded; this occasionally happens during MIP presolve.

**Solved to relaxed tolerances**

`ALMOST_OPTIMAL`

: The algorithm found a globally optimal solution to relaxed tolerances.`ALMOST_INFEASIBLE`

: The algorithm concluded that no feasible solution exists within relaxed tolerances.`ALMOST_DUAL_INFEASIBLE`

: The algorithm concluded that no dual bound exists for the problem within relaxed tolerances.`ALMOST_LOCALLY_SOLVED`

: The algorithm converged to a stationary point, local optimal solution, or could not find directions for improvement within relaxed tolerances.

**Limits**

The optimizer stopped because of some user-defined limit.

`ITERATION_LIMIT`

: An iterative algorithm stopped after conducting the maximum number of iterations.`TIME_LIMIT`

: The algorithm stopped after a user-specified computation time.`NODE_LIMIT`

: A branch-and-bound algorithm stopped because it explored a maximum number of nodes in the branch-and-bound tree.`SOLUTION_LIMIT`

: The algorithm stopped because it found the required number of solutions. This is often used in MIPs to get the solver to return the first feasible solution it encounters.`MEMORY_LIMIT`

: The algorithm stopped because it ran out of memory.`OBJECTIVE_LIMIT`

: The algorithm stopped because it found a solution better than a minimum limit set by the user.`NORM_LIMIT`

: The algorithm stopped because the norm of an iterate became too large.`OTHER_LIMIT`

: The algorithm stopped due to a limit not covered by one of the above.

**Problematic**

This group of statuses means that something unexpected or problematic happened.

`SLOW_PROGRESS`

: The algorithm stopped because it was unable to continue making progress towards the solution.`NUMERICAL_ERROR`

: The algorithm stopped because it encountered unrecoverable numerical error.`INVALID_MODEL`

: The algorithm stopped because the model is invalid.`INVALID_OPTION`

: The algorithm stopped because it was provided an invalid option.`INTERRUPTED`

: The algorithm stopped because of an interrupt signal.`OTHER_ERROR`

: The algorithm stopped because of an error not covered by one of the statuses defined above.

`MathOptInterface.PrimalStatus`

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

A model attribute for the `ResultStatusCode`

of the primal result `result_index`

. If `result_index`

is omitted, it defaults to 1.

See `ResultCount`

for information on how the results are ordered.

If `result_index`

is larger than the value of `ResultCount`

then `NO_SOLUTION`

is returned.

`MathOptInterface.DualStatus`

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

A model attribute for the `ResultStatusCode`

of the dual result `result_index`

. If `result_index`

is omitted, it defaults to 1.

See `ResultCount`

for information on how the results are ordered.

If `result_index`

is larger than the value of `ResultCount`

then `NO_SOLUTION`

is returned.

`MathOptInterface.ResultStatusCode`

— Type`ResultStatusCode`

An Enum of possible values for the `PrimalStatus`

and `DualStatus`

attributes. The values indicate how to interpret the result vector.

`NO_SOLUTION`

: the result vector is empty.`FEASIBLE_POINT`

: the result vector is a feasible point.`NEARLY_FEASIBLE_POINT`

: the result vector is feasible if some constraint tolerances are relaxed.`INFEASIBLE_POINT`

: the result vector is an infeasible point.`INFEASIBILITY_CERTIFICATE`

: the result vector is an infeasibility certificate. If the`PrimalStatus`

is`INFEASIBILITY_CERTIFICATE`

, then the primal result vector is a certificate of dual infeasibility. If the`DualStatus`

is`INFEASIBILITY_CERTIFICATE`

, then the dual result vector is a proof of primal infeasibility.`NEARLY_INFEASIBILITY_CERTIFICATE`

: the result satisfies a relaxed criterion for a certificate of infeasibility.`REDUCTION_CERTIFICATE`

: the result vector is an ill-posed certificate; see this article for details. If the`PrimalStatus`

is`REDUCTION_CERTIFICATE`

, then the primal result vector is a proof that the dual problem is ill-posed. If the`DualStatus`

is`REDUCTION_CERTIFICATE`

, then the dual result vector is a proof that the primal is ill-posed.`NEARLY_REDUCTION_CERTIFICATE`

: the result satisfies a relaxed criterion for an ill-posed certificate.`UNKNOWN_RESULT_STATUS`

: the result vector contains a solution with an unknown interpretation.`OTHER_RESULT_STATUS`

: the result vector contains a solution with an interpretation not covered by one of the statuses defined above.

`MathOptInterface.RawStatusString`

— Type`RawStatusString()`

A model attribute for a solver specific string explaining why the optimizer stopped.

`MathOptInterface.ResultCount`

— Type`ResultCount()`

A model attribute for the number of results available.

**Order of solutions**

A number of attributes contain an index, `result_index`

, which is used to refer to one of the available results. Thus, `result_index`

must be an integer between `1`

and the number of available results.

As a general rule, the first result (`result_index=1`

) is the most important result (e.g., an optimal solution or an infeasibility certificate). Other results will typically be alternate solutions that the solver found during the search for the first result.

If a (local) optimal solution is available, i.e., `TerminationStatus`

is `OPTIMAL`

or `LOCALLY_SOLVED`

, the first result must correspond to the (locally) optimal solution. Other results may be alternative optimal solutions, or they may be other suboptimal solutions; use `ObjectiveValue`

to distingiush between them.

If a primal or dual infeasibility certificate is available, i.e., `TerminationStatus`

is `INFEASIBLE`

or `DUAL_INFEASIBLE`

and the corresponding `PrimalStatus`

or `DualStatus`

is `INFEASIBILITY_CERTIFICATE`

, then the first result must be a certificate. Other results may be alternate certificates, or infeasible points.

`MathOptInterface.ObjectiveValue`

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

A model attribute for the objective value of the primal solution `result_index`

.

If the solver does not have a primal value for the objective 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 `ObjectiveValue`

attribute.

See `ResultCount`

for information on how the results are ordered.

`MathOptInterface.DualObjectiveValue`

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

A model attribute for the value of the objective function of the dual problem for the `result_index`

th dual result.

If the solver does not have a dual value for the objective 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 `DualObjectiveValue`

attribute.

See `ResultCount`

for information on how the results are ordered.

`MathOptInterface.ObjectiveBound`

— Type`ObjectiveBound()`

A model attribute for the best known bound on the optimal objective value.

`MathOptInterface.RelativeGap`

— Type`RelativeGap()`

A model attribute for the final relative optimality gap.

The definition of this gap is solver-dependent. However, most solvers implementing this attribute define the relative gap as some variation of $\frac{|b-f|}{|f|}$, where $b$ is the best bound and $f$ is the best feasible objective value.

`MathOptInterface.SolveTimeSec`

— Type`SolveTimeSec()`

A model attribute for the total elapsed solution time (in seconds) as reported by the optimizer.

`MathOptInterface.SimplexIterations`

— Type`SimplexIterations()`

A model attribute for the cumulative number of simplex iterations during the optimization process.

For a mixed-integer program (MIP), the return value is the total simplex iterations for all nodes.

`MathOptInterface.BarrierIterations`

— Type`BarrierIterations()`

A model attribute for the cumulative number of barrier iterations while solving a problem.

`MathOptInterface.NodeCount`

— Type`NodeCount()`

A model attribute for the total number of branch-and-bound nodes explored while solving a mixed-integer program (MIP).

### Conflict Status

`MathOptInterface.compute_conflict!`

— Function`compute_conflict!(optimizer::AbstractOptimizer)`

Computes a minimal subset of constraints such that the model with the other constraint removed is still infeasible.

Some solvers call a set of conflicting constraints an Irreducible Inconsistent Subsystem (IIS).

See also `ConflictStatus`

and `ConstraintConflictStatus`

.

**Note**

If the model is modified after a call to `compute_conflict!`

, the implementor is not obliged to purge the conflict. Any calls to the above attributes may return values for the original conflict without a warning. Similarly, when modifying the model, the conflict can be discarded.

`MathOptInterface.ConflictStatus`

— Type`ConflictStatus()`

A model attribute for the `ConflictStatusCode`

explaining why the conflict refiner stopped when computing the conflict.

`MathOptInterface.ConflictStatusCode`

— Type`ConflictStatusCode`

An Enum of possible values for the `ConflictStatus`

attribute. This attribute is meant to explain the reason why the conflict finder stopped executing in the most recent call to `compute_conflict!`

.

Possible values are:

`COMPUTE_CONFLICT_NOT_CALLED`

: the function`compute_conflict!`

has not yet been called`NO_CONFLICT_EXISTS`

: there is no conflict because the problem is feasible`NO_CONFLICT_FOUND`

: the solver could not find a conflict`CONFLICT_FOUND`

: at least one conflict could be found

`MathOptInterface.ConstraintConflictStatus`

— Type`ConstraintConflictStatus()`

A constraint attribute indicating whether the constraint participates in the conflict. Its type is `ConflictParticipationStatusCode`

.

`MathOptInterface.ConflictParticipationStatusCode`

— Type`ConflictParticipationStatusCode`

An Enum of possible values for the `ConstraintConflictStatus`

attribute. This attribute is meant to indicate whether a given constraint participates or not in the last computed conflict.

Possible values are:

`NOT_IN_CONFLICT`

: the constraint does not participate in the conflict`IN_CONFLICT`

: the constraint participates in the conflict`MAYBE_IN_CONFLICT`

: the constraint may participate in the conflict, the solver was not able to prove that the constraint can be excluded from the conflict