## Utilities.Model

`MathOptInterface.Utilities.Model`

— Type`MOI.Utilities.Model{T}() where {T}`

An implementation of `ModelLike`

that supports all functions and sets defined in MOI. It is parameterized by the coefficient type.

**Examples**

```
julia> import MathOptInterface as MOI
julia> model = MOI.Utilities.Model{Float64}()
MOIU.Model{Float64}
```

## Utilities.UniversalFallback

`MathOptInterface.Utilities.UniversalFallback`

— Type`UniversalFallback`

The `UniversalFallback`

can be applied on a `MOI.ModelLike`

`model`

to create the model `UniversalFallback(model)`

supporting *any* constraint and attribute. This allows to have a specialized implementation in `model`

for performance critical constraints and attributes while still supporting other attributes with a small performance penalty. Note that `model`

is unaware of constraints and attributes stored by `UniversalFallback`

so this is not appropriate if `model`

is an optimizer (for this reason, `MOI.optimize!`

has not been implemented). In that case, optimizer bridges should be used instead.

## Utilities.@model

`MathOptInterface.Utilities.@model`

— Macro```
macro model(
model_name,
scalar_sets,
typed_scalar_sets,
vector_sets,
typed_vector_sets,
scalar_functions,
typed_scalar_functions,
vector_functions,
typed_vector_functions,
is_optimizer = false
)
```

Creates a type `model_name`

implementing the MOI model interface and supporting all combinations of the provided functions and sets.

Each `typed_`

`scalar`

/`vector`

`sets`

/`functions`

argument is a tuple of types. A type is "typed" if it has a coefficient `{T}`

as the first type parameter.

**Tuple syntax**

To give no set/function, write `()`

. To give one set or function `X`

, write `(X,)`

.

`is_optimizer`

If `is_optimizer = true`

, the resulting struct is a of `GenericOptimizer`

, which is a subtype of `MOI.AbstractOptimizer`

, otherwise, it is a `GenericModel`

, which is a subtype of `MOI.ModelLike`

.

**VariableIndex**

- The function
`MOI.VariableIndex`

must not be given in`scalar_functions`

. - The model supports
`MOI.VariableIndex`

-in-`S`

constraints where`S`

is`MOI.EqualTo`

,`MOI.GreaterThan`

,`MOI.LessThan`

,`MOI.Interval`

,`MOI.Integer`

,`MOI.ZeroOne`

,`MOI.Semicontinuous`

or`MOI.Semiinteger`

. - The sets supported with
`MOI.VariableIndex`

cannot be controlled from the macro; use`UniversalFallback`

to support more sets.

**Examples**

The model describing a linear program would be:

```
@model(
LPModel, # model_name
(), # untyped scalar sets
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), # typed scalar sets
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives), # untyped vector sets
(), # typed vector sets
(), # untyped scalar functions
(MOI.ScalarAffineFunction,), # typed scalar functions
(MOI.VectorOfVariables,), # untyped vector functions
(MOI.VectorAffineFunction,), # typed vector functions
false, # is_optimizer
)
```

`MathOptInterface.Utilities.GenericModel`

— Type`mutable struct GenericModel{T,O,V,C} <: AbstractModelLike{T}`

Implements a model supporting coefficients of type `T`

and:

- An objective function stored in
`.objective::O`

- Variables and
`VariableIndex`

constraints stored in`.variable_bounds::V`

`F`

-in-`S`

constraints (excluding`VariableIndex`

constraints) stored in`.constraints::C`

All interactions take place via the MOI interface, so the types `O`

, `V`

, and `C`

must implement the API as needed for their functionality.

`MathOptInterface.Utilities.GenericOptimizer`

— Type`mutable struct GenericOptimizer{T,O,V,C} <: AbstractOptimizer{T}`

Implements a model supporting coefficients of type `T`

and:

- An objective function stored in
`.objective::O`

- Variables and
`VariableIndex`

constraints stored in`.variable_bounds::V`

`F`

-in-`S`

constraints (excluding`VariableIndex`

constraints) stored in`.constraints::C`

All interactions take place via the MOI interface, so the types `O`

, `V`

, and `C`

must implement the API as needed for their functionality.

`.objective`

`MathOptInterface.Utilities.ObjectiveContainer`

— Type`ObjectiveContainer{T}`

A helper struct to simplify the handling of objective functions in Utilities.Model.

`.variables`

`MathOptInterface.Utilities.VariablesContainer`

— Type```
struct VariablesContainer{T} <: AbstractVectorBounds
set_mask::Vector{UInt16}
lower::Vector{T}
upper::Vector{T}
end
```

A struct for storing variables and VariableIndex-related constraints. Used in `MOI.Utilities.Model`

by default.

`MathOptInterface.Utilities.FreeVariables`

— Type```
mutable struct FreeVariables <: MOI.ModelLike
n::Int64
FreeVariables() = new(0)
end
```

A struct for storing free variables that can be used as the `variables`

field of `GenericModel`

or `GenericModel`

. It represents a model that does not support any constraint nor objective function.

**Example**

The following model type represents a conic model in geometric form. As opposed to `VariablesContainer`

, `FreeVariables`

does not support constraint bounds so they are bridged into an affine constraint in the `MOI.Nonnegatives`

cone as expected for the geometric conic form.

```
julia> MOI.Utilities.@product_of_sets(
Cones,
MOI.Zeros,
MOI.Nonnegatives,
MOI.SecondOrderCone,
MOI.PositiveSemidefiniteConeTriangle,
);
julia> const ConicModel{T} = MOI.Utilities.GenericOptimizer{
T,
MOI.Utilities.ObjectiveContainer{T},
MOI.Utilities.FreeVariables,
MOI.Utilities.MatrixOfConstraints{
T,
MOI.Utilities.MutableSparseMatrixCSC{
T,
Int,
MOI.Utilities.OneBasedIndexing,
},
Vector{T},
Cones{T},
},
};
julia> model = MOI.instantiate(ConicModel{Float64}, with_bridge_type=Float64);
julia> x = MOI.add_variable(model)
MathOptInterface.VariableIndex(1)
julia> c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))
MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.GreaterThan{Float64}}(1)
julia> MOI.Bridges.is_bridged(model, c)
true
julia> bridge = MOI.Bridges.bridge(model, c)
MathOptInterface.Bridges.Constraint.VectorizeBridge{Float64, MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives, MathOptInterface.VariableIndex}(MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1), 1.0)
julia> bridge.vector_constraint
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
julia> MOI.Bridges.is_bridged(model, bridge.vector_constraint)
false
```

`.constraints`

`MathOptInterface.Utilities.VectorOfConstraints`

— Type```
mutable struct VectorOfConstraints{
F<:MOI.AbstractFunction,
S<:MOI.AbstractSet,
} <: MOI.ModelLike
constraints::CleverDicts.CleverDict{
MOI.ConstraintIndex{F,S},
Tuple{F,S},
typeof(CleverDicts.key_to_index),
typeof(CleverDicts.index_to_key),
}
end
```

A struct storing `F`

-in-`S`

constraints as a mapping between the constraint indices to the corresponding tuple of function and set.

`MathOptInterface.Utilities.StructOfConstraints`

— Type`abstract type StructOfConstraints <: MOI.ModelLike end`

A struct storing a subfields other structs storing constraints of different types.

See `Utilities.@struct_of_constraints_by_function_types`

and `Utilities.@struct_of_constraints_by_set_types`

.

`MathOptInterface.Utilities.@struct_of_constraints_by_function_types`

— Macro`Utilities.@struct_of_constraints_by_function_types(name, func_types...)`

Given a vector of `n`

function types `(F1, F2,..., Fn)`

in `func_types`

, defines a subtype of `StructOfConstraints`

of name `name`

and which type parameters `{T, C1, C2, ..., Cn}`

. It contains `n`

field where the `i`

th field has type `Ci`

and stores the constraints of function type `Fi`

.

The expression `Fi`

can also be a union in which case any constraint for which the function type is in the union is stored in the field with type `Ci`

.

`MathOptInterface.Utilities.@struct_of_constraints_by_set_types`

— Macro`Utilities.@struct_of_constraints_by_set_types(name, func_types...)`

Given a vector of `n`

set types `(S1, S2,..., Sn)`

in `func_types`

, defines a subtype of `StructOfConstraints`

of name `name`

and which type parameters `{T, C1, C2, ..., Cn}`

. It contains `n`

field where the `i`

th field has type `Ci`

and stores the constraints of set type `Si`

. The expression `Si`

can also be a union in which case any constraint for which the set type is in the union is stored in the field with type `Ci`

. This can be useful if `Ci`

is a `MatrixOfConstraints`

in order to concatenate the coefficients of constraints of several different set types in the same matrix.

`MathOptInterface.Utilities.struct_of_constraint_code`

— Function`struct_of_constraint_code(struct_name, types, field_types = nothing)`

Given a vector of `n`

`Union{SymbolFun,_UnionSymbolFS{SymbolFun}}`

or `Union{SymbolSet,_UnionSymbolFS{SymbolSet}}`

in `types`

, defines a subtype of `StructOfConstraints`

of name `name`

and which type parameters `{T, F1, F2, ..., Fn}`

if `field_types`

is `nothing`

and a `{T}`

otherwise. It contains `n`

field where the `i`

th field has type `Ci`

if `field_types`

is `nothing`

and type `field_types[i]`

otherwise. If `types`

is vector of `Union{SymbolFun,_UnionSymbolFS{SymbolFun}}`

(resp. `Union{SymbolSet,_UnionSymbolFS{SymbolSet}}`

) then the constraints of that function (resp. set) type are stored in the corresponding field.

This function is used by the macros `@model`

, `@struct_of_constraints_by_function_types`

and `@struct_of_constraints_by_set_types`

.

## Caching optimizer

`MathOptInterface.Utilities.CachingOptimizer`

— Type`CachingOptimizer`

`CachingOptimizer`

is an intermediate layer that stores a cache of the model and links it with an optimizer. It supports incremental model construction and modification even when the optimizer doesn't.

**Constructors**

` CachingOptimizer(cache::MOI.ModelLike, optimizer::AbstractOptimizer)`

Creates a `CachingOptimizer`

in `AUTOMATIC`

mode, with the optimizer `optimizer`

.

The type of the optimizer returned is `CachingOptimizer{typeof(optimizer), typeof(cache)}`

so it does not support the function `reset_optimizer(::CachingOptimizer, new_optimizer)`

if the type of `new_optimizer`

is different from the type of `optimizer`

.

` CachingOptimizer(cache::MOI.ModelLike, mode::CachingOptimizerMode)`

Creates a `CachingOptimizer`

in the `NO_OPTIMIZER`

state and mode `mode`

.

The type of the optimizer returned is `CachingOptimizer{MOI.AbstractOptimizer,typeof(cache)}`

so it *does* support the function `reset_optimizer(::CachingOptimizer, new_optimizer)`

if the type of `new_optimizer`

is different from the type of `optimizer`

.

**About the type**

**States**

A `CachingOptimizer`

may be in one of three possible states (`CachingOptimizerState`

):

`NO_OPTIMIZER`

: The CachingOptimizer does not have any optimizer.`EMPTY_OPTIMIZER`

: The CachingOptimizer has an empty optimizer. The optimizer is not synchronized with the cached model.`ATTACHED_OPTIMIZER`

: The CachingOptimizer has an optimizer, and it is synchronized with the cached model.

**Modes**

A `CachingOptimizer`

has two modes of operation (`CachingOptimizerMode`

):

`MANUAL`

: The only methods that change the state of the`CachingOptimizer`

are`Utilities.reset_optimizer`

,`Utilities.drop_optimizer`

, and`Utilities.attach_optimizer`

. Attempting to perform an operation in the incorrect state results in an error.`AUTOMATIC`

: The`CachingOptimizer`

changes its state when necessary. For example,`optimize!`

will automatically call`attach_optimizer`

(an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to`EMPTY_OPTIMIZER`

mode.

`MathOptInterface.Utilities.attach_optimizer`

— Function`attach_optimizer(model::CachingOptimizer)`

Attaches the optimizer to `model`

, copying all model data into it. Can be called only from the `EMPTY_OPTIMIZER`

state. If the copy succeeds, the `CachingOptimizer`

will be in state `ATTACHED_OPTIMIZER`

after the call, otherwise an error is thrown; see `MOI.copy_to`

for more details on which errors can be thrown.

`MathOptInterface.Utilities.reset_optimizer`

— Function`reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)`

Sets or resets `m`

to have the given empty optimizer `optimizer`

.

Can be called from any state. An assertion error will be thrown if `optimizer`

is not empty.

The `CachingOptimizer`

`m`

will be in state `EMPTY_OPTIMIZER`

after the call.

`reset_optimizer(m::CachingOptimizer)`

Detaches and empties the current optimizer. Can be called from `ATTACHED_OPTIMIZER`

or `EMPTY_OPTIMIZER`

state. The `CachingOptimizer`

will be in state `EMPTY_OPTIMIZER`

after the call.

`MathOptInterface.Utilities.drop_optimizer`

— Function`drop_optimizer(m::CachingOptimizer)`

Drops the optimizer, if one is present. Can be called from any state. The `CachingOptimizer`

will be in state `NO_OPTIMIZER`

after the call.

`MathOptInterface.Utilities.state`

— Function`state(m::CachingOptimizer)::CachingOptimizerState`

Returns the state of the CachingOptimizer `m`

. See `Utilities.CachingOptimizer`

.

`MathOptInterface.Utilities.mode`

— Function`mode(m::CachingOptimizer)::CachingOptimizerMode`

Returns the operating mode of the CachingOptimizer `m`

. See `Utilities.CachingOptimizer`

.

## Mock optimizer

`MathOptInterface.Utilities.MockOptimizer`

— Type`MockOptimizer`

`MockOptimizer`

is a fake optimizer especially useful for testing. Its main feature is that it can store the values that should be returned for each attribute.

## Printing

`MathOptInterface.Utilities.latex_formulation`

— Function`latex_formulation(model::MOI.ModelLike; kwargs...)`

Wrap `model`

in a type so that it can be pretty-printed as `text/latex`

in a notebook like IJulia, or in Documenter.

To render the model, end the cell with `latex_formulation(model)`

, or call `display(latex_formulation(model))`

in to force the display of the model from inside a function.

Possible keyword arguments are:

`simplify_coefficients`

: Simplify coefficients if possible by omitting them or removing trailing zeros.`default_name`

: The name given to variables with an empty name.`print_types`

: Print the MOI type of each function and set for clarity.

## Copy utilities

`MathOptInterface.Utilities.default_copy_to`

— Function`default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)`

A default implementation of `MOI.copy_to(dest, src)`

for models that implement the incremental interface, i.e., `MOI.supports_incremental_interface`

returns `true`

.

`MathOptInterface.Utilities.IndexMap`

— Type`IndexMap()`

The dictionary-like object returned by `MOI.copy_to`

.

`MathOptInterface.Utilities.identity_index_map`

— Function`identity_index_map(model::MOI.ModelLike)`

Return an `IndexMap`

that maps all variable and constraint indices of `model`

to themselves.

`MathOptInterface.Utilities.ModelFilter`

— Type`ModelFilter(filter::Function, model::MOI.ModelLike)`

A layer to filter out various components of `model`

.

The filter function takes a single argument, which is each element from the list returned by the attributes below. It returns `true`

if the element should be visible in the filtered model and `false`

otherwise.

The components that are filtered are:

- Entire constraint types via:
`MOI.ListOfConstraintTypesPresent`

- Individual constraints via:
`MOI.ListOfConstraintIndices{F,S}`

- Specific attributes via:
`MOI.ListOfModelAttributesSet`

`MOI.ListOfConstraintAttributesSet`

`MOI.ListOfVariableAttributesSet`

The list of attributes filtered may change in a future release. You should write functions that are generic and not limited to the five types listed above. Thus, you should probably define a fallback `filter(::Any) = true`

.

See below for examples of how this works.

This layer has a limited scope. It is intended by be used in conjunction with `MOI.copy_to`

.

**Example: copy model excluding integer constraints**

Use the `do`

syntax to provide a single function.

```
filtered_src = MOI.Utilities.ModelFilter(src) do item
return item != (MOI.VariableIndex, MOI.Integer)
end
MOI.copy_to(dest, filtered_src)
```

**Example: copy model excluding names**

Use type dispatch to simplify the implementation:

```
my_filter(::Any) = true # Note the generic fallback!
my_filter(::MOI.VariableName) = false
my_filter(::MOI.ConstraintName) = false
filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
MOI.copy_to(dest, filtered_src)
```

**Example: copy irreducible infeasible subsystem**

```
my_filter(::Any) = true # Note the generic fallback!
function my_filter(ci::MOI.ConstraintIndex)
status = MOI.get(dest, MOI.ConstraintConflictStatus(), ci)
return status != MOI.NOT_IN_CONFLICT
end
filtered_src = MOI.Utilities.ModelFilter(my_filter, src)
MOI.copy_to(dest, filtered_src)
```

`MathOptInterface.Utilities.loadfromstring!`

— Function`loadfromstring!(model, s)`

A utility function to aid writing tests.

This function is not intended for widespread use! It is mainly used as a tool to simplify writing tests in MathOptInterface. Do not use it as an exchange format for storing or transmitting problem instances. Use the FileFormats submodule instead.

**Example**

```
julia> model = MOI.Utilities.Model{Float64}();
julia> MOI.Utilities.loadfromstring!(model, """
variables: x, y, z
constrainedvariable: [a, b, c] in Nonnegatives(3)
minobjective::Float64: 2x + 3y
con1: x + y <= 1.0
con2: [x, y] in Nonnegatives(2)
x >= 0.0
""")
```

**Notes**

Special labels are:

- variables
- minobjective
- maxobjectives

Everything else denotes a constraint with a name.

Append `::T`

to use an element type of `T`

when parsing the function.

Do not name `VariableIndex`

constraints.

**Exceptions**

`x - y`

does NOT currently parse. Instead, write`x + -1.0 * y`

.`x^2`

does NOT currently parse. Instead, write`x * x`

.

## Penalty relaxation

`MathOptInterface.Utilities.PenaltyRelaxation`

— Type```
PenaltyRelaxation(
penalties = Dict{MOI.ConstraintIndex,Float64}();
default::Union{Nothing,T} = 1.0,
)
```

A problem modifier that, when passed to `MOI.modify`

, destructively modifies the model in-place to create a penalized relaxation of the constraints.

This is a destructive routine that modifies the model in-place. If you don't want to modify the original model, use `JuMP.copy_model`

to create a copy before calling `MOI.modify`

.

**Reformulation**

See `Utilities.ScalarPenaltyRelaxation`

for details of the reformulation.

For each constraint `ci`

, the penalty passed to `Utilities.ScalarPenaltyRelaxation`

is `get(penalties, ci, default)`

. If the value is `nothing`

, because `ci`

does not exist in `penalties`

and `default = nothing`

, then the constraint is skipped.

**Return value**

`MOI.modify(model, PenaltyRelaxation())`

returns a `Dict{MOI.ConstraintIndex,MOI.ScalarAffineFunction}`

that maps each constraint index to the corresponding `y + z`

as a `MOI.ScalarAffineFunction`

. In an optimal solution, query the value of these functions to compute the violation of each constraint.

**Relax a subset of constraints**

To relax a subset of constraints, pass a `penalties`

dictionary and set `default = nothing`

.

**Supported constraint types**

The penalty relaxation is currently limited to modifying `MOI.ScalarAffineFunction`

and `MOI.ScalarQuadraticFunction`

constraints in the linear sets `MOI.LessThan`

, `MOI.GreaterThan`

, `MOI.EqualTo`

and `MOI.Interval`

.

It does not include variable bound or integrality constraints, because these cannot be modified in-place.

To modify variable bounds, rewrite them as linear constraints.

**Examples**

```
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> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(default = 2.0));
julia> print(model)
Minimize ScalarAffineFunction{Float64}:
0.0 + 2.0 v[2]
Subject to:
ScalarAffineFunction{Float64}-in-LessThan{Float64}
0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
VariableIndex-in-GreaterThan{Float64}
v[2] >= 0.0
julia> map[c] isa MOI.ScalarAffineFunction{Float64}
true
```

```
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> map = MOI.modify(model, MOI.Utilities.PenaltyRelaxation(Dict(c => 3.0)));
julia> print(model)
Minimize ScalarAffineFunction{Float64}:
0.0 + 3.0 v[2]
Subject to:
ScalarAffineFunction{Float64}-in-LessThan{Float64}
0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
VariableIndex-in-GreaterThan{Float64}
v[2] >= 0.0
julia> map[c] isa MOI.ScalarAffineFunction{Float64}
true
```

`MathOptInterface.Utilities.ScalarPenaltyRelaxation`

— Type`ScalarPenaltyRelaxation(penalty::T) where {T}`

A problem modifier that, when passed to `MOI.modify`

, destructively modifies the constraint in-place to create a penalized relaxation of the constraint.

This is a destructive routine that modifies the constraint in-place. If you don't want to modify the original model, use `JuMP.copy_model`

to create a copy before calling `MOI.modify`

.

**Reformulation**

The penalty relaxation modifies constraints of the form $f(x) \in S$ into $f(x) + y - z \in S$, where $y, z \ge 0$, and then it introduces a penalty term into the objective of $a \times (y + z)$ (if minimizing, else $-a$), where $a$ is `penalty`

When `S`

is `MOI.LessThan`

or `MOI.GreaterThan`

, we omit `y`

or `z`

respectively as a performance optimization.

**Return value**

`MOI.modify(model, ci, ScalarPenaltyRelaxation(penalty))`

returns `y + z`

as a `MOI.ScalarAffineFunction`

. In an optimal solution, query the value of this function to compute the violation of the constraint.

**Examples**

```
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> f = MOI.modify(model, c, MOI.Utilities.ScalarPenaltyRelaxation(2.0));
julia> print(model)
Minimize ScalarAffineFunction{Float64}:
0.0 + 2.0 v[2]
Subject to:
ScalarAffineFunction{Float64}-in-LessThan{Float64}
0.0 + 1.0 v[1] - 1.0 v[2] <= 2.0
VariableIndex-in-GreaterThan{Float64}
v[2] >= 0.0
julia> f isa MOI.ScalarAffineFunction{Float64}
true
```

## MatrixOfConstraints

`MathOptInterface.Utilities.MatrixOfConstraints`

— Type```
mutable struct MatrixOfConstraints{T,AT,BT,ST} <: MOI.ModelLike
coefficients::AT
constants::BT
sets::ST
caches::Vector{Any}
are_indices_mapped::Vector{BitSet}
final_touch::Bool
end
```

Represent `ScalarAffineFunction`

and `VectorAffinefunction`

constraints in a matrix form where the linear coefficients of the functions are stored in the `coefficients`

field, the constants of the functions or sets are stored in the `constants`

field. Additional information about the sets are stored in the `sets`

field.

This model can only be used as the `constraints`

field of a `MOI.Utilities.AbstractModel`

.

When the constraints are added, they are stored in the `caches`

field. They are only loaded in the `coefficients`

and `constants`

fields once `MOI.Utilities.final_touch`

is called. For this reason, `MatrixOfConstraints`

should not be used by an incremental interface. Use `MOI.copy_to`

instead.

The constraints can be added in two different ways:

- With
`add_constraint`

, in which case a canonicalized copy of the function is stored in`caches`

. - With
`pass_nonvariable_constraints`

, in which case the functions and sets are stored themselves in`caches`

without mapping the variable indices. The corresponding index in`caches`

is added in`are_indices_mapped`

. This avoids doing a copy of the function in case the getter of`CanonicalConstraintFunction`

does not make a copy for the source model, e.g., this is the case of`VectorOfConstraints`

.

We illustrate this with an example. Suppose a model is copied from a `src::MOI.Utilities.Model`

to a bridged model with a `MatrixOfConstraints`

. For all the types that are not bridged, the constraints will be copied with `pass_nonvariable_constraints`

. Hence the functions stored in `caches`

are exactly the same as the ones stored in `src`

. This is ok since this is only during the `copy_to`

operation during which `src`

cannot be modified. On the other hand, for the types that are bridged, the functions added may contain duplicates even if the functions did not contain duplicates in `src`

so duplicates are removed with `MOI.Utilities.canonical`

.

**Interface**

The `.coefficients::AT`

type must implement:

`AT()`

`MOI.empty(::AT)!`

`MOI.Utilities.add_column`

`MOI.Utilities.set_number_of_rows`

`MOI.Utilities.allocate_terms`

`MOI.Utilities.load_terms`

`MOI.Utilities.final_touch`

The `.constants::BT`

type must implement:

`BT()`

`Base.empty!(::BT)`

`Base.resize(::BT)`

`MOI.Utilities.load_constants`

`MOI.Utilities.function_constants`

`MOI.Utilities.set_from_constants`

The `.sets::ST`

type must implement:

`ST()`

`MOI.is_empty(::ST)`

`MOI.empty(::ST)`

`MOI.dimension(::ST)`

`MOI.is_valid(::ST, ::MOI.ConstraintIndex)`

`MOI.get(::ST, ::MOI.ListOfConstraintTypesPresent)`

`MOI.get(::ST, ::MOI.NumberOfConstraints)`

`MOI.get(::ST, ::MOI.ListOfConstraintIndices)`

`MOI.Utilities.set_types`

`MOI.Utilities.set_index`

`MOI.Utilities.add_set`

`MOI.Utilities.rows`

`MOI.Utilities.final_touch`

`.coefficients`

`MathOptInterface.Utilities.add_column`

— Function`add_column(coefficients)::Nothing`

Tell `coefficients`

to pre-allocate datastructures as needed to store one column.

`MathOptInterface.Utilities.allocate_terms`

— Function`allocate_terms(coefficients, index_map, func)::Nothing`

Tell `coefficients`

that the terms of the function `func`

where the variable indices are mapped with `index_map`

will be loaded with `load_terms`

.

The function `func`

must be canonicalized before calling `allocate_terms`

. See `is_canonical`

.

`MathOptInterface.Utilities.set_number_of_rows`

— Function`set_number_of_rows(coefficients, n)::Nothing`

Tell `coefficients`

to pre-allocate datastructures as needed to store `n`

rows.

`MathOptInterface.Utilities.load_terms`

— Function`load_terms(coefficients, index_map, func, offset)::Nothing`

Loads the terms of `func`

to `coefficients`

, mapping the variable indices with `index_map`

.

The `i`

th dimension of `func`

is loaded at the `(offset + i)`

th row of `coefficients`

.

The function must be allocated first with `allocate_terms`

.

The function `func`

must be canonicalized, see `is_canonical`

.

`MathOptInterface.Utilities.final_touch`

— Function`final_touch(coefficients)::Nothing`

Informs the `coefficients`

that all functions have been added with `load_terms`

. No more modification is allowed unless `MOI.empty!`

is called.

`final_touch(sets)::Nothing`

Informs the `sets`

that all functions have been added with `add_set`

. No more modification is allowed unless `MOI.empty!`

is called.

`MathOptInterface.Utilities.extract_function`

— Function`extract_function(coefficients, row::Integer, constant::T) where {T}`

Return the `MOI.ScalarAffineFunction{T}`

function corresponding to row `row`

in `coefficients`

.

```
extract_function(
coefficients,
rows::UnitRange,
constants::Vector{T},
) where{T}
```

Return the `MOI.VectorAffineFunction{T}`

function corresponding to rows `rows`

in `coefficients`

.

`MathOptInterface.Utilities.MutableSparseMatrixCSC`

— Type```
mutable struct MutableSparseMatrixCSC{Tv,Ti<:Integer,I<:AbstractIndexing}
indexing::I
m::Int
n::Int
colptr::Vector{Ti}
rowval::Vector{Ti}
nzval::Vector{Tv}
nz_added::Vector{Ti}
end
```

Matrix type loading sparse matrices in the Compressed Sparse Column format. The indexing used is `indexing`

, see `AbstractIndexing`

. The other fields have the same meaning than for `SparseArrays.SparseMatrixCSC`

except that the indexing is different unless `indexing`

is `OneBasedIndexing`

. In addition, `nz_added`

is used to cache the number of non-zero terms that have been added to each column due to the incremental nature of `load_terms`

.

The matrix is loaded in 5 steps:

`MOI.empty!`

is called.`MOI.Utilities.add_column`

and`MOI.Utilities.allocate_terms`

are called in any order.`MOI.Utilities.set_number_of_rows`

is called.`MOI.Utilities.load_terms`

is called for each affine function.`MOI.Utilities.final_touch`

is called.

`MathOptInterface.Utilities.AbstractIndexing`

— Type`abstract type AbstractIndexing end`

Indexing to be used for storing the row and column indices of `MutableSparseMatrixCSC`

. See `ZeroBasedIndexing`

and `OneBasedIndexing`

.

`MathOptInterface.Utilities.ZeroBasedIndexing`

— Type`struct ZeroBasedIndexing <: AbstractIndexing end`

Zero-based indexing: the `i`

th row or column has index `i - 1`

. This is useful when the vectors of row and column indices need to be communicated to a library using zero-based indexing such as C libraries.

`MathOptInterface.Utilities.OneBasedIndexing`

— Type`struct ZeroBasedIndexing <: AbstractIndexing end`

One-based indexing: the `i`

th row or column has index `i`

. This enables an allocation-free conversion of `MutableSparseMatrixCSC`

to `SparseArrays.SparseMatrixCSC`

.

`.constants`

`MathOptInterface.Utilities.load_constants`

— Function`load_constants(constants, offset, func_or_set)::Nothing`

This function loads the constants of `func_or_set`

in `constants`

at an offset of `offset`

. Where `offset`

is the sum of the dimensions of the constraints already loaded. The storage should be preallocated with `resize!`

before calling this function.

This function should be implemented to be usable as storage of constants for `MatrixOfConstraints`

.

The constants are loaded in three steps:

`Base.empty!`

is called.`Base.resize!`

is called with the sum of the dimensions of all constraints.`MOI.Utilities.load_constants`

is called for each function for vector constraint or set for scalar constraint.

`MathOptInterface.Utilities.function_constants`

— Function`function_constants(constants, rows)`

This function returns the function constants that were loaded with `load_constants`

at the rows `rows`

.

This function should be implemented to be usable as storage of constants for `MatrixOfConstraints`

.

`MathOptInterface.Utilities.set_from_constants`

— Function`set_from_constants(constants, S::Type, rows)::S`

This function returns an instance of the set `S`

for which the constants where loaded with `load_constants`

at the rows `rows`

.

This function should be implemented to be usable as storage of constants for `MatrixOfConstraints`

.

`MathOptInterface.Utilities.modify_constants`

— Function```
modify_constants(constants, row::Integer, new_constant::T) where {T}
modify_constants(
constants,
rows::AbstractVector{<:Integer},
new_constants::AbstractVector{T},
) where {T}
```

Modify `constants`

in-place to store `new_constant`

in the `row`

row, or rows `rows`

.

This function must be implemented to enable `MOI.ScalarConstantChange`

and `MOI.VectorConstantChange`

for `MatrixOfConstraints`

.

`MathOptInterface.Utilities.Hyperrectangle`

— Type```
struct Hyperrectangle{T} <: AbstractVectorBounds
lower::Vector{T}
upper::Vector{T}
end
```

A struct for the .constants field in MatrixOfConstraints.

`.sets`

`MathOptInterface.Utilities.set_index`

— Function`set_index(sets, ::Type{S})::Union{Int,Nothing} where {S<:MOI.AbstractSet}`

Return an integer corresponding to the index of the set type in the list given by `set_types`

.

If `S`

is not part of the list, return `nothing`

.

`MathOptInterface.Utilities.set_types`

— Function`set_types(sets)::Vector{Type}`

Return the list of the types of the sets allowed in `sets`

.

`MathOptInterface.Utilities.add_set`

— Function`add_set(sets, i)::Int64`

Add a scalar set of type index `i`

.

`add_set(sets, i, dim)::Int64`

Add a vector set of type index `i`

and dimension `dim`

.

Both methods return a unique `Int64`

of the set that can be used to reference this set.

`MathOptInterface.Utilities.rows`

— Function`rows(sets, ci::MOI.ConstraintIndex)::Union{Int,UnitRange{Int}}`

Return the rows in `1:MOI.dimension(sets)`

corresponding to the set of id `ci.value`

.

For scalar sets, this returns an `Int`

. For vector sets, this returns an `UnitRange{Int}`

.

`MathOptInterface.Utilities.num_rows`

— Function`num_rows(sets::OrderedProductOfSets, ::Type{S}) where {S}`

Return the number of rows corresponding to a set of type `S`

. That is, it is the sum of the dimensions of the sets of type `S`

.

`MathOptInterface.Utilities.set_with_dimension`

— Function`set_with_dimension(::Type{S}, dim) where {S<:MOI.AbstractVectorSet}`

Returns the instance of `S`

of `MOI.dimension`

`dim`

. This needs to be implemented for sets of type `S`

to be useable with `MatrixOfConstraints`

.

`MathOptInterface.Utilities.ProductOfSets`

— Type`abstract type ProductOfSets{T} end`

Represents a cartesian product of sets of given types.

`MathOptInterface.Utilities.MixOfScalarSets`

— Type`abstract type MixOfScalarSets{T} <: ProductOfSets{T} end`

Product of scalar sets in the order the constraints are added, mixing the constraints of different types.

Use `@mix_of_scalar_sets`

to generate a new subtype.

`MathOptInterface.Utilities.@mix_of_scalar_sets`

— Macro`@mix_of_scalar_sets(name, set_types...)`

Generate a new `MixOfScalarSets`

subtype.

**Example**

```
@mix_of_scalar_sets(
MixedIntegerLinearProgramSets,
MOI.GreaterThan{T},
MOI.LessThan{T},
MOI.EqualTo{T},
MOI.Integer,
)
```

`MathOptInterface.Utilities.OrderedProductOfSets`

— Type`abstract type OrderedProductOfSets{T} <: ProductOfSets{T} end`

Product of sets in the order the constraints are added, grouping the constraints of the same types contiguously.

Use `@product_of_sets`

to generate new subtypes.

`MathOptInterface.Utilities.@product_of_sets`

— Macro`@product_of_sets(name, set_types...)`

Generate a new `OrderedProductOfSets`

subtype.

**Example**

```
@product_of_sets(
LinearOrthants,
MOI.Zeros,
MOI.Nonnegatives,
MOI.Nonpositives,
MOI.ZeroOne,
)
```

## Fallbacks

`MathOptInterface.Utilities.get_fallback`

— Function`get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)`

Compute the objective function value using the `VariablePrimal`

results and the `ObjectiveFunction`

value.

`get_fallback(model::MOI.ModelLike, ::MOI.DualObjectiveValue, T::Type)::T`

Compute the dual objective value of type `T`

using the `ConstraintDual`

results and the `ConstraintFunction`

and `ConstraintSet`

values. Note that the nonlinear part of the model is ignored.

```
get_fallback(model::MOI.ModelLike, ::MOI.ConstraintPrimal,
constraint_index::MOI.ConstraintIndex)
```

Compute the value of the function of the constraint of index `constraint_index`

using the `VariablePrimal`

results and the `ConstraintFunction`

values.

```
get_fallback(model::MOI.ModelLike, attr::MOI.ConstraintDual,
ci::MOI.ConstraintIndex{Union{MOI.VariableIndex,
MOI.VectorOfVariables}})
```

Compute the dual of the constraint of index `ci`

using the `ConstraintDual`

of other constraints and the `ConstraintFunction`

values. Throws an error if some constraints are quadratic or if there is one another `MOI.VariableIndex`

-in-`S`

or `MOI.VectorOfVariables`

-in-`S`

constraint with one of the variables in the function of the constraint `ci`

.

## Function utilities

The following utilities are available for functions:

`MathOptInterface.Utilities.eval_variables`

— Function`eval_variables(value_fn::Function, f::MOI.AbstractFunction)`

Returns the value of function `f`

if each variable index `vi`

is evaluated as `value_fn(vi)`

.

Note that `value_fn`

must return a Number. See `substitute_variables`

for a similar function where `value_fn`

returns an `MOI.AbstractScalarFunction`

.

The two-argument version of `eval_variables`

is deprecated and may be removed in MOI v2.0.0. Use the three-argument method `eval_variables(::Function, ::MOI.ModelLike, ::MOI.AbstractFunction)`

instead.

`MathOptInterface.Utilities.map_indices`

— Function`map_indices(index_map::Function, attr::MOI.AnyAttribute, x::X)::X where {X}`

Substitute any `MOI.VariableIndex`

(resp. `MOI.ConstraintIndex`

) in `x`

by the `MOI.VariableIndex`

(resp. `MOI.ConstraintIndex`

) of the same type given by `index_map(x)`

.

**When to implement this method for new types X**

This function is used by implementations of `MOI.copy_to`

on constraint functions, attribute values and submittable values. If you define a new attribute whose values `x::X`

contain variable or constraint indices, you must also implement this function.

```
map_indices(
variable_map::AbstractDict{T,T},
x::X,
)::X where {T<:MOI.Index,X}
```

Shortcut for `map_indices(vi -> variable_map[vi], x)`

.

`MathOptInterface.Utilities.substitute_variables`

— Function`substitute_variables(variable_map::Function, x)`

Substitute any `MOI.VariableIndex`

in `x`

by `variable_map(x)`

. The `variable_map`

function returns either `MOI.VariableIndex`

or `MOI.ScalarAffineFunction`

, see `eval_variables`

for a similar function where `variable_map`

returns a number.

This function is used by bridge optimizers on constraint functions, attribute values and submittable values when at least one variable bridge is used hence it needs to be implemented for custom types that are meant to be used as attribute or submittable value.

When implementing a new method, don't use `substitute_variables(::Function`

, because Julia will not specialize on it. Use instead `substitute_variables(::F, ...) where {F<:Function}`

.

`MathOptInterface.Utilities.filter_variables`

— Function`filter_variables(keep::Function, f::AbstractFunction)`

Return a new function `f`

with the variable `vi`

such that `!keep(vi)`

removed.

WARNING: Don't define `filter_variables(::Function, ...)`

because Julia will not specialize on this. Define instead `filter_variables(::F, ...) where {F<:Function}`

.

`MathOptInterface.Utilities.remove_variable`

— Function`remove_variable(f::AbstractFunction, vi::VariableIndex)`

Return a new function `f`

with the variable vi removed.

```
remove_variable(
f::MOI.AbstractFunction,
s::MOI.AbstractSet,
vi::MOI.VariableIndex,
)
```

Return a tuple `(g, t)`

representing the constraint `f`

-in-`s`

with the variable `vi`

removed. That is, the terms containing the variable `vi`

in the function `f`

are removed and the dimension of the set `s`

is updated if needed (e.g. when `f`

is a `VectorOfVariables`

with `vi`

being one of the variables).

`MathOptInterface.Utilities.all_coefficients`

— Function`all_coefficients(p::Function, f::MOI.AbstractFunction)`

Determine whether predicate `p`

returns `true`

for all coefficients of `f`

, returning `false`

as soon as the first coefficient of `f`

for which `p`

returns `false`

is encountered (short-circuiting). Similar to `all`

.

`MathOptInterface.Utilities.unsafe_add`

— Function`unsafe_add(t1::MOI.ScalarAffineTerm, t2::MOI.ScalarAffineTerm)`

Sums the coefficients of `t1`

and `t2`

and returns an output `MOI.ScalarAffineTerm`

. It is unsafe because it uses the `variable`

of `t1`

as the `variable`

of the output without checking that it is equal to that of `t2`

.

`unsafe_add(t1::MOI.ScalarQuadraticTerm, t2::MOI.ScalarQuadraticTerm)`

Sums the coefficients of `t1`

and `t2`

and returns an output `MOI.ScalarQuadraticTerm`

. It is unsafe because it uses the `variable`

's of `t1`

as the `variable`

's of the output without checking that they are the same (up to permutation) to those of `t2`

.

`unsafe_add(t1::MOI.VectorAffineTerm, t2::MOI.VectorAffineTerm)`

Sums the coefficients of `t1`

and `t2`

and returns an output `MOI.VectorAffineTerm`

. It is unsafe because it uses the `output_index`

and `variable`

of `t1`

as the `output_index`

and `variable`

of the output term without checking that they are equal to those of `t2`

.

`MathOptInterface.Utilities.isapprox_zero`

— Function`isapprox_zero(f::MOI.AbstractFunction, tol)`

Return a `Bool`

indicating whether the function `f`

is approximately zero using `tol`

as a tolerance.

**Important note**

This function assumes that `f`

does not contain any duplicate terms, you might want to first call `canonical`

if that is not guaranteed. For instance, given

`f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1, -1], [x, x]), 0)`

then `isapprox_zero(f)`

is `false`

but `isapprox_zero(MOIU.canonical(f))`

is `true`

.

`MathOptInterface.Utilities.modify_function`

— Function`modify_function(f::AbstractFunction, change::AbstractFunctionModification)`

Return a copy of the function `f`

, modified according to `change`

.

`MathOptInterface.Utilities.zero_with_output_dimension`

— Function`zero_with_output_dimension(::Type{T}, output_dimension::Integer) where {T}`

Create an instance of type `T`

with the output dimension `output_dimension`

.

This is mostly useful in Bridges, when code needs to be agnostic to the type of vector-valued function that is passed in.

The following functions can be used to canonicalize a function:

`MathOptInterface.Utilities.is_canonical`

— Function`is_canonical(f::Union{ScalarAffineFunction, VectorAffineFunction})`

Returns a Bool indicating whether the function is in canonical form. See `canonical`

.

`is_canonical(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})`

Returns a Bool indicating whether the function is in canonical form. See `canonical`

.

`MathOptInterface.Utilities.canonical`

— Function`canonical(f::MOI.AbstractFunction)`

Returns the function in a canonical form, i.e.

- A term appear only once.
- The coefficients are nonzero.
- The terms appear in increasing order of variable where there the order of the variables is the order of their value.
- For a
`AbstractVectorFunction`

, the terms are sorted in ascending order of output index.

The output of `canonical`

can be assumed to be a copy of `f`

, even for `VectorOfVariables`

.

**Examples**

If `x`

(resp. `y`

, `z`

) is `VariableIndex(1)`

(resp. 2, 3). The canonical representation of `ScalarAffineFunction([y, x, z, x, z], [2, 1, 3, -2, -3], 5)`

is `ScalarAffineFunction([x, y], [-1, 2], 5)`

.

`MathOptInterface.Utilities.canonicalize!`

— Function`canonicalize!(f::Union{ScalarAffineFunction, VectorAffineFunction})`

Convert a function to canonical form in-place, without allocating a copy to hold the result. See `canonical`

.

`canonicalize!(f::Union{ScalarQuadraticFunction, VectorQuadraticFunction})`

Convert a function to canonical form in-place, without allocating a copy to hold the result. See `canonical`

.

The following functions can be used to manipulate functions with basic algebra:

`MathOptInterface.Utilities.scalar_type`

— Function`scalar_type(F::Type{<:MOI.AbstractVectorFunction})`

Type of functions obtained by indexing objects obtained by calling `eachscalar`

on functions of type `F`

.

`MathOptInterface.Utilities.scalarize`

— Function`scalarize(func::MOI.VectorOfVariables, ignore_constants::Bool = false)`

Returns a vector of scalar functions making up the vector function in the form of a `Vector{MOI.SingleVariable}`

.

See also `eachscalar`

.

`scalarize(func::MOI.VectorAffineFunction{T}, ignore_constants::Bool = false)`

Returns a vector of scalar functions making up the vector function in the form of a `Vector{MOI.ScalarAffineFunction{T}}`

.

See also `eachscalar`

.

`scalarize(func::MOI.VectorQuadraticFunction{T}, ignore_constants::Bool = false)`

Returns a vector of scalar functions making up the vector function in the form of a `Vector{MOI.ScalarQuadraticFunction{T}}`

.

See also `eachscalar`

.

`MathOptInterface.Utilities.eachscalar`

— Function`eachscalar(f::MOI.AbstractVectorFunction)`

Returns an iterator for the scalar components of the vector function.

See also `scalarize`

.

`eachscalar(f::MOI.AbstractVector)`

Returns an iterator for the scalar components of the vector.

`MathOptInterface.Utilities.promote_operation`

— Function```
promote_operation(
op::Function,
::Type{T},
ArgsTypes::Type{<:Union{T,AbstractVector{T},MOI.AbstractFunction}}...,
) where {T<:Number}
```

Compute the return type of the call `operate(op, T, args...)`

, where the types of the arguments `args`

are `ArgsTypes`

.

One assumption is that the element type `T`

is invariant under each operation. That is, `op(::T, ::T)::T`

where `op`

is a `+`

, `-`

, `*`

, and `/`

.

There are six methods for which we implement `Utilities.promote_operation`

:

`+`

a.`promote_operation(::typeof(+), ::Type{T}, ::Type{F1}, ::Type{F2})`

`-`

a.`promote_operation(::typeof(-), ::Type{T}, ::Type{F})`

b.`promote_operation(::typeof(-), ::Type{T}, ::Type{F1}, ::Type{F2})`

`*`

a.`promote_operation(::typeof(*), ::Type{T}, ::Type{T}, ::Type{F})`

b.`promote_operation(::typeof(*), ::Type{T}, ::Type{F}, ::Type{T})`

c.`promote_operation(::typeof(*), ::Type{T}, ::Type{F1}, ::Type{F2})`

where`F1`

and`F2`

are`VariableIndex`

or`ScalarAffineFunction`

d.`promote_operation(::typeof(*), ::Type{T}, ::Type{<:Diagonal{T}}, ::Type{F}`

`/`

a.`promote_operation(::typeof(/), ::Type{T}, ::Type{F}, ::Type{T})`

`vcat`

a.`promote_operation(::typeof(vcat), ::Type{T}, ::Type{F}...)`

`imag`

a.`promote_operation(::typeof(imag), ::Type{T}, ::Type{F})`

where`F`

is`VariableIndex`

or`VectorOfVariables`

In each case, `F`

(or `F1`

and `F2`

) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define `promote_operation(-, T, F1, F2)`

where `F1`

is a scalar-valued function and `F2`

is a vector-valued function. The ten supported types are:

- ::T
- ::VariableIndex
- ::ScalarAffineFunction{T}
- ::ScalarQuadraticFunction{T}
- ::ScalarNonlinearFunction
- ::AbstractVector{T}
- ::VectorOfVariables
- ::VectorAffineFunction{T}
- ::VectorQuadraticFunction{T}
- ::VectorNonlinearFunction

`MathOptInterface.Utilities.operate`

— Function```
operate(
op::Function,
::Type{T},
args::Union{T,MOI.AbstractFunction}...,
)::MOI.AbstractFunction where {T<:Number}
```

Returns an `MOI.AbstractFunction`

representing the function resulting from the operation `op(args...)`

on functions of coefficient type `T`

.

No argument can be modified.

**Methods**

`+`

a.`operate(::typeof(+), ::Type{T}, ::F1)`

b.`operate(::typeof(+), ::Type{T}, ::F1, ::F2)`

c.`operate(::typeof(+), ::Type{T}, ::F1...)`

`-`

a.`operate(::typeof(-), ::Type{T}, ::F)`

b.`operate(::typeof(-), ::Type{T}, ::F1, ::F2)`

`*`

a.`operate(::typeof(*), ::Type{T}, ::T, ::F)`

b.`operate(::typeof(*), ::Type{T}, ::F, ::T)`

c.`operate(::typeof(*), ::Type{T}, ::F1, ::F2)`

where`F1`

and`F2`

are`VariableIndex`

or`ScalarAffineFunction`

d.`operate(::typeof(*), ::Type{T}, ::Diagonal{T}, ::F)`

`/`

a.`operate(::typeof(/), ::Type{T}, ::F, ::T)`

`vcat`

a.`operate(::typeof(vcat), ::Type{T}, ::F...)`

`imag`

a.`operate(::typeof(imag), ::Type{T}, ::F)`

where`F`

is`VariableIndex`

or`VectorOfVariables`

One assumption is that the element type `T`

is invariant under each operation. That is, `op(::T, ::T)::T`

where `op`

is a `+`

, `-`

, `*`

, and `/`

.

In each case, `F`

(or `F1`

and `F2`

) is one of the ten supported types, with a restriction that the mathematical operation makes sense, for example, we don't define `promote_operation(-, T, F1, F2)`

where `F1`

is a scalar-valued function and `F2`

is a vector-valued function. The ten supported types are:

- ::T
- ::VariableIndex
- ::ScalarAffineFunction{T}
- ::ScalarQuadraticFunction{T}
- ::ScalarNonlinearFunction
- ::AbstractVector{T}
- ::VectorOfVariables
- ::VectorAffineFunction{T}
- ::VectorQuadraticFunction{T}
- ::VectorNonlinearFunction

`MathOptInterface.Utilities.operate!`

— Function```
operate!(
op::Function,
::Type{T},
args::Union{T,MOI.AbstractFunction}...,
)::MOI.AbstractFunction where {T<:Number}
```

Returns an `MOI.AbstractFunction`

representing the function resulting from the operation `op(args...)`

on functions of coefficient type `T`

.

The first argument may be modified, in which case the return value is identical to the first argument. For operations which cannot be implemented in-place, this function returns a new object.

`MathOptInterface.Utilities.operate_output_index!`

— Function```
operate_output_index!(
op::Union{typeof(+),typeof(-)},
::Type{T},
output_index::Integer,
f::Union{AbstractVector{T},MOI.AbstractVectorFunction}
g::Union{T,MOI.AbstractScalarFunction}...
) where {T<:Number}
```

Return an `MOI.AbstractVectorFunction`

in which the scalar function in row `output_index`

is the result of `op(f[output_index], g)`

.

The functions at output index different to `output_index`

are the same as the functions at the same output index in `func`

. The first argument may be modified.

**Methods**

`+`

a.`operate_output_index!(+, ::Type{T}, ::Int, ::VectorF, ::ScalarF)`

`-`

a.`operate_output_index!(-, ::Type{T}, ::Int, ::VectorF, ::ScalarF)`

`MathOptInterface.Utilities.vectorize`

— Function`vectorize(x::AbstractVector{<:Number})`

Returns `x`

.

`vectorize(x::AbstractVector{MOI.VariableIndex})`

Returns the vector of scalar affine functions in the form of a `MOI.VectorAffineFunction{T}`

.

`vectorize(funcs::AbstractVector{MOI.ScalarAffineFunction{T}}) where T`

Returns the vector of scalar affine functions in the form of a `MOI.VectorAffineFunction{T}`

.

`vectorize(funcs::AbstractVector{MOI.ScalarQuadraticFunction{T}}) where T`

Returns the vector of scalar quadratic functions in the form of a `MOI.VectorQuadraticFunction{T}`

.

## Constraint utilities

The following utilities are available for moving the function constant to the set for scalar constraints:

`MathOptInterface.Utilities.shift_constant`

— Function`shift_constant(set::MOI.AbstractScalarSet, offset)`

Returns a new scalar set `new_set`

such that `func`

-in-`set`

is equivalent to `func + offset`

-in-`new_set`

.

Only define this function if it makes sense to!

Use `supports_shift_constant`

to check if the set supports shifting:

```
if supports_shift_constant(typeof(old_set))
new_set = shift_constant(old_set, offset)
f.constant = 0
add_constraint(model, f, new_set)
else
add_constraint(model, f, old_set)
end
```

See also `supports_shift_constant`

.

**Examples**

The call `shift_constant(MOI.Interval(-2, 3), 1)`

is equal to `MOI.Interval(-1, 4)`

.

`MathOptInterface.Utilities.supports_shift_constant`

— Function`supports_shift_constant(::Type{S}) where {S<:MOI.AbstractSet}`

Return `true`

if `shift_constant`

is defined for set `S`

.

See also `shift_constant`

.

`MathOptInterface.Utilities.normalize_and_add_constraint`

— Function```
normalize_and_add_constraint(
model::MOI.ModelLike,
func::MOI.AbstractScalarFunction,
set::MOI.AbstractScalarSet;
allow_modify_function::Bool = false,
)
```

Adds the scalar constraint obtained by moving the constant term in `func`

to the set in `model`

. If `allow_modify_function`

is `true`

then the function `func`

can be modified.

`MathOptInterface.Utilities.normalize_constant`

— Function```
normalize_constant(
func::MOI.AbstractScalarFunction,
set::MOI.AbstractScalarSet;
allow_modify_function::Bool = false,
)
```

Return the `func`

-in-`set`

constraint in normalized form. That is, if `func`

is `MOI.ScalarQuadraticFunction`

or `MOI.ScalarAffineFunction`

, the constant is moved to the set. If `allow_modify_function`

is `true`

then the function `func`

can be modified.

The following utility identifies those constraints imposing bounds on a given variable, and returns those bound values:

`MathOptInterface.Utilities.get_bounds`

— Function`get_bounds(model::MOI.ModelLike, ::Type{T}, x::MOI.VariableIndex)`

Return a tuple `(lb, ub)`

of type `Tuple{T, T}`

, where `lb`

and `ub`

are lower and upper bounds, respectively, imposed on `x`

in `model`

.

```
get_bounds(
model::MOI.ModelLike,
bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
f::MOI.ScalarAffineFunction{T},
) where {T} --> Union{Nothing,NTuple{2,T}}
```

Return the lower and upper bound of `f`

as a tuple. If the domain is not bounded, return `nothing`

.

```
get_bounds(
model::MOI.ModelLike,
bounds_cache::Dict{MOI.VariableIndex,NTuple{2,T}},
x::MOI.VariableIndex,
) where {T} --> Union{Nothing,NTuple{2,T}}
```

Return the lower and upper bound of `x`

as a tuple. If the domain is not bounded, return `nothing`

.

Similar to `get_bounds(::MOI.ModelLike, ::Type{T}, ::MOI.VariableIndex)`

, except that the second argument is a cache which maps variables to their bounds and avoids repeated lookups.

The following utilities are useful when working with symmetric matrix cones.

`MathOptInterface.Utilities.is_diagonal_vectorized_index`

— Function`is_diagonal_vectorized_index(index::Base.Integer)`

Return whether `index`

is the index of a diagonal element in a `MOI.AbstractSymmetricMatrixSetTriangle`

set.

`MathOptInterface.Utilities.side_dimension_for_vectorized_dimension`

— Function`side_dimension_for_vectorized_dimension(n::Integer)`

Return the dimension `d`

such that `MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(d))`

is `n`

.

## Set utilities

The following utilities are available for sets:

`MathOptInterface.Utilities.AbstractDistance`

— Type`abstract type AbstractDistance end`

An abstract type used to enabble dispatch of `Utilities.distance_to_set`

.

`MathOptInterface.Utilities.ProjectionUpperBoundDistance`

— Type`ProjectionUpperBoundDistance() <: AbstractDistance`

An upper bound on the minimum distance between `point`

and the closest feasible point in `set`

.

**Definition of distance**

The minimum distance is computed as:

\[d(x, \mathcal{K}) = \min_{y \in \mathcal{K}} || x - y ||\]

where $x$ is `point`

and $\mathcal{K}$ is `set`

. The norm is computed as:

\[||x|| = \sqrt{f(x, x, \mathcal{K})}\]

where $f$ is `Utilities.set_dot`

.

In the default case, where the set does not have a specialized method for `Utilities.set_dot`

, the norm is equivalent to the Euclidean norm $||x|| = \sqrt{\sum x_i^2}$.

**Why an upper bound?**

In most cases, `distance_to_set`

should return the smallest upper bound, but it may return a larger value if the smallest upper bound is expensive to compute.

For example, given an epigraph from of a conic set, $\{(t, x) | f(x) \le t\}$, it may be simpler to return $\delta$ such that $f(x) \le t + \delta$, rather than computing the nearest projection onto the set.

If the distance is not the smallest upper bound, the docstring of the appropriate `distance_to_set`

method *must* describe the way that the distance is computed.

`MathOptInterface.Utilities.distance_to_set`

— Function```
distance_to_set(
[d::AbstractDistance = ProjectionUpperBoundDistance()],]
point::T,
set::MOI.AbstractScalarSet,
) where {T}
distance_to_set(
[d::AbstractDistance = ProjectionUpperBoundDistance(),]
point::AbstractVector{T},
set::MOI.AbstractVectorSet,
) where {T}
```

Compute the distance between `point`

and `set`

using the distance metric `d`

. If `point`

is in the set `set`

, this function *must* return `zero(T)`

.

If `d`

is omitted, the default distance is `Utilities.ProjectionUpperBoundDistance`

.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RotatedSecondOrderCone)`

Let `(t, u, y...) = x`

. Return the 2-norm of the vector `d`

such that in `x + d`

, `u`

is projected to `1`

if `u <= 0`

, and `t`

is increased such that `x + d`

belongs to the set.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.ExponentialCone)`

Let `(u, v, w) = x`

. If `v > 0`

, return the epigraph distance `d`

such that `(u, v, w + d)`

belongs to the set.

If `v <= 0`

return the 2-norm of the vector `d`

such that `x + d = (u, 1, z)`

where `z`

satisfies the constraints.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualExponentialCone)`

Let `(u, v, w) = x`

. If `u < 0`

, return the epigraph distance `d`

such that `(u, v, w + d)`

belongs to the set.

If `u >= 0`

return the 2-norm of the vector `d`

such that `x + d = (u, -1, z)`

where `z`

satisfies the constraints.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.GeometricMeanCone)`

Let `(t, y...) = x`

. If all `y`

are non-negative, return the epigraph distance `d`

such that `(t + d, y...)`

belongs to the set.

If any `y`

are strictly negative, return the 2-norm of the vector `d`

that projects negative `y`

elements to `0`

and `t`

to `ℝ₋`

.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.PowerCone)`

Let `(a, b, c) = x`

. If `a`

and `b`

are non-negative, return the epigraph distance required to increase `c`

such that the constraint is satisfied.

If `a`

or `b`

is strictly negative, return the 2-norm of the vector `d`

such that in the vector `x + d`

: `c`

, and any negative `a`

and `b`

are projected to `0`

.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.DualPowerCone)`

Let `(a, b, c) = x`

. If `a`

and `b`

are non-negative, return the epigraph distance required to increase `c`

such that the constraint is satisfied.

If `a`

or `b`

is strictly negative, return the 2-norm of the vector `d`

such that in the vector `x + d`

: `c`

, and any negative `a`

and `b`

are projected to `0`

.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormOneCone)`

Let `(t, y...) = x`

. Return the epigraph distance `d`

such that `(t + d, y...)`

belongs to the set.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.NormInfinityCone)`

Let `(t, y...) = x`

. Return the epigraph distance `d`

such that `(t + d, y...)`

belongs to the set.

`distance_to_set(::ProjectionUpperBoundDistance, x, ::MOI.RelativeEntropyCone)`

Let `(u, v..., w...) = x`

. If `v`

and `w`

are strictly positive, return the epigraph distance required to increase `u`

such that the constraint is satisfied.

If any elements in `v`

or `w`

are non-positive, return the 2-norm of the vector `d`

such that in the vector `x + d`

: any non-positive elements in `v`

and `w`

are projected to `1`

, and `u`

is projected such that the epigraph constraint holds.

`distance_to_set(::ProjectionUpperBoundDistance, x, set::MOI.NormCone)`

Let `(t, y...) = x`

. Return the epigraph distance `d`

such that `(t + d, y...)`

belongs to the set.

`MathOptInterface.Utilities.set_dot`

— Function`set_dot(x::AbstractVector, y::AbstractVector, set::AbstractVectorSet)`

Return the scalar product between a vector `x`

of the set `set`

and a vector `y`

of the dual of the set `s`

.

`set_dot(x, y, set::AbstractScalarSet)`

Return the scalar product between a number `x`

of the set `set`

and a number `y`

of the dual of the set `s`

.

## DoubleDicts

`MathOptInterface.Utilities.DoubleDicts.DoubleDict`

— Type`DoubleDict{V}`

An optimized dictionary to map `MOI.ConstraintIndex`

to values of type `V`

.

Works as a `AbstractDict{MOI.ConstraintIndex,V}`

with minimal differences.

If `V`

is also a `MOI.ConstraintIndex`

, use `IndexDoubleDict`

.

Note that `MOI.ConstraintIndex`

is not a concrete type, opposed to `MOI.ConstraintIndex{MOI.VariableIndex, MOI.Integers}`

, which is a concrete type.

When looping through multiple keys of the same Function-in-Set type, use

`inner = dict[F, S]`

to return a type-stable `DoubleDictInner`

.

`MathOptInterface.Utilities.DoubleDicts.DoubleDictInner`

— Type`DoubleDictInner{F,S,V}`

A type stable inner dictionary of `DoubleDict`

.

`MathOptInterface.Utilities.DoubleDicts.IndexDoubleDict`

— Type`IndexDoubleDict`

A specialized version of [`DoubleDict`

] in which the values are of type `MOI.ConstraintIndex`

When looping through multiple keys of the same Function-in-Set type, use

`inner = dict[F, S]`

to return a type-stable `IndexDoubleDictInner`

.

`MathOptInterface.Utilities.DoubleDicts.IndexDoubleDictInner`

— Type`IndexDoubleDictInner{F,S}`

A type stable inner dictionary of `IndexDoubleDict`

.

`MathOptInterface.Utilities.DoubleDicts.outer_keys`

— Function`outer_keys(d::AbstractDoubleDict)`

Return an iterator over the outer keys of the `AbstractDoubleDict`

`d`

. Each outer key is a `Tuple{Type,Type}`

so that a double loop can be easily used:

```
for (F, S) in DoubleDicts.outer_keys(dict)
for (k, v) in dict[F, S]
# ...
end
end
```

For performance, it is recommended that the inner loop lies in a separate function to gurantee type-stability. Some outer keys `(F, S)`

might lead to an empty `dict[F, S]`

. If you want only nonempty `dict[F, S]`

, use `nonempty_outer_keys`

.

`MathOptInterface.Utilities.DoubleDicts.nonempty_outer_keys`

— Function`nonempty_outer_keys(d::AbstractDoubleDict)`

Return a vector of outer keys of the `AbstractDoubleDict`

`d`

.

Only outer keys that have a nonempty set of inner keys will be returned.

Each outer key is a `Tuple{Type,Type}`

so that a double loop can be easily used

```
for (F, S) in DoubleDicts.nonempty_outer_keys(dict)
for (k, v) in dict[F, S]
# ...
end
end
For performance, it is recommended that the inner loop lies in a separate
function to gurantee type-stability.
If you want an iterator of all current outer keys, use [`outer_keys`](@ref).
```