API Reference

[Some introduction to API. List basic standalone methods.]

Attributes

List of attribute categories.

MathOptInterface.AbstractOptimizerAttributeType
AbstractOptimizerAttribute

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

Note

The difference between AbstractOptimizerAttribute and AbstractModelAttribute lies in the behavior of is_empty, empty! and copy_to. Typically optimizer attributes only affect how the model is solved.

source

Attributes can be set in different ways:

The following functions allow to distinguish between some of these different categories:

MathOptInterface.is_set_by_optimizeFunction
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!.

source
MathOptInterface.is_copyableFunction
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:

source

Functions for getting and setting attributes.

MathOptInterface.getFunction
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}})

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<:AbstractFunction,S<:AbstractSet}

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.

Examples

get(model, ObjectiveValue())
get(model, VariablePrimal(), ref)
get(model, VariablePrimal(5), [ref1, ref2])
get(model, OtherAttribute("something specific to cplex"))
get(model, VariableIndex, "var1")
get(model, ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}}, "con1")
get(model, ConstraintIndex, "con1")
source
MathOptInterface.get!Function
get!(output, model::ModelLike, args...)

An in-place version of get. The signature matches that of get except that the the result is placed in the vector output.

source
MathOptInterface.setFunction
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)

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.

Replace set in a constraint

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

Change the set of constraint c to the new set set which should be of the same type as the original set.

Examples

If c is a ConstraintIndex{F,Interval}

set(model, ConstraintSet(), c, Interval(0, 5))
set(model, ConstraintSet(), c, GreaterThan(0.0))  # Error

Replace function in a constraint

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

Replace the function in constraint c with func. F must match the original function type used to define the constraint.

Note

Setting the constraint function is not allowed if F is SingleVariable, it throws a SettingSingleVariableFunctionNotAllowed error. Indeed, it would require changing the index c as the index of SingleVariable constraints should be the same as the index of the variable.

Examples

If c is a ConstraintIndex{ScalarAffineFunction,S} and v1 and v2 are VariableIndex objects,

set(model, ConstraintFunction(), c,
    ScalarAffineFunction(ScalarAffineTerm.([1.0, 2.0], [v1, v2]), 5.0))
set(model, ConstraintFunction(), c, SingleVariable(v1)) # Error
source
MathOptInterface.supportsFunction
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.

source

Fallbacks

The value of some attributes can be inferred from the value of other attributes. For instance, the value of ObjectiveValue can be computed using ObjectiveFunction and VariablePrimal. When a solver gives access to the objective value, it is better to return this value but otherwise, Utilities.get_fallback can be used.

function MOI.get(optimizer::Optimizer, attr::MOI.ObjectiveValue)
    return MOI.Utilities.get_fallback(optimizer, attr)
end
MathOptInterface.Utilities.get_fallbackFunction
get_fallback(model::MOI.ModelLike, ::MOI.ObjectiveValue)

Compute the objective function value using the VariablePrimal results and the ObjectiveFunction value.

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

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

source
get_fallback(model::MOI.ModelLike, attr::MOI.ConstraintDual,
             ci::MOI.ConstraintIndex{Union{MOI.SingleVariable,
                                           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.SingleVariable-in-S or MOI.VectorOfVariables-in-S constraint with one of the variables in the function of the constraint ci.

source

Submit

Objects may be submitted to an optimizer using submit.

MathOptInterface.submitFunction
submit(optimizer::AbstractOptimizer, sub::AbstractSubmittable,
       values...)::Nothing

Submit values to the submittable sub of the optimizer optimizer.

An UnsupportedSubmittable error is thrown if model does not support the attribute attr (see supports) and a SubmitNotAllowed error is thrown if it supports the submittable sub but it cannot be submitted.

source

List of submittables

MathOptInterface.LazyConstraintType
LazyConstraint(callback_data)

Lazy constraint func-in-set submitted as func, set. The optimal solution returned by VariablePrimal will satisfy all lazy constraints that have been submitted.

This can be submitted only from the LazyConstraintCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the feasible solution callback.

Examples

Suppose fx = MOI.SingleVariable(x) and fx = MOI.SingleVariable(y) where x and y are VariableIndexs of optimizer. To add a LazyConstraint for 2x + 3y <= 1, write

func = 2.0fx + 3.0fy
set = MOI.LessThan(1.0)
MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)

inside a LazyConstraintCallback of data callback_data.

source
MathOptInterface.HeuristicSolutionStatusType
HeuristicSolutionStatus

An Enum of possible return values for submit with HeuristicSolution. This informs whether the heuristic solution was accepted or rejected. Possible values are:

  • HEURISTIC_SOLUTION_ACCEPTED: The heuristic solution was accepted.
  • HEURISTIC_SOLUTION_REJECTED: The heuristic solution was rejected.
  • HEURISTIC_SOLUTION_UNKNOWN: No information available on the acceptance.
source
MathOptInterface.HeuristicSolutionType
HeuristicSolution(callback_data)

Heuristically obtained feasible solution. The solution is submitted as variables, values where values[i] gives the value of variables[i], similarly to set. The submit call returns a HeuristicSolutionStatus indicating whether the provided solution was accepted or rejected.

This can be submitted only from the HeuristicCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the heuristic callback.

Some solvers require a complete solution, others only partial solutions.

source
MathOptInterface.UserCutType
UserCut(callback_data)

Constraint func-to-set suggested to help the solver detect the solution given by CallbackVariablePrimal as infeasible. The cut is submitted as func, set. Typically CallbackVariablePrimal will violate integrality constraints, and a cut would be of the form ScalarAffineFunction-in-LessThan or ScalarAffineFunction-in-GreaterThan. Note that, as opposed to LazyConstraint, the provided constraint cannot modify the feasible set, the constraint should be redundant, e.g., it may be a consequence of affine and integrality constraints.

This can be submitted only from the UserCutCallback. The field callback_data is a solver-specific callback type that is passed as the argument to the infeasible solution callback.

Note that the solver may silently ignore the provided constraint.

source

Model Interface

Base.isemptyFunction
isempty(collection) -> Bool

Determine whether a collection is empty (has no elements).

Examples

julia> isempty([])
true

julia> isempty([1 2 3])
false
source
MathOptInterface.empty!Function
empty!(model::ModelLike)

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

source
MathOptInterface.write_to_fileFunction
write_to_file(model::ModelLike, filename::String)

Writes the current model data to the given file. Supported file types depend on the model type.

source
MathOptInterface.read_from_fileFunction
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, users should look up each variable index by name: get(model, VariableIndex, "name").

source

Copying

MathOptInterface.copy_toFunction
copy_to(dest::ModelLike, src::ModelLike; copy_names=true, warn_attributes=true)

Copy the model from src into dest. The target dest is emptied, and all previous indices to variables or constraints in dest are invalidated. Returns a dictionary-like object that translates variable and constraint indices from the src model to the corresponding indices in the dest model.

If copy_names is false, the Name, VariableName and ConstraintName attributes are not copied even if they are set in src. If a constraint that is copied from src is not supported by dest then an UnsupportedConstraint error is thrown. Similarly, if a model, variable or constraint attribute that is copied from src is not supported by dest then an UnsupportedAttribute error is thrown. Unsupported optimizer attributes are treated differently:

  • If warn_attributes is true, a warning is displayed, otherwise,
  • the attribute is silently ignored.

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
source

List of model attributes

MathOptInterface.NameType
Name()

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

source
MathOptInterface.ObjectiveSenseType
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.

source
MathOptInterface.ListOfVariableIndicesType
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.

source
MathOptInterface.ListOfConstraintsType
ListOfConstraints()

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 value greater than zero.

source
MathOptInterface.ListOfConstraintIndicesType
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.

source
MathOptInterface.ListOfModelAttributesSetType
ListOfModelAttributesSet()

A model attribute for the Vector{AbstractModelAttribute} of all model attributes attr such that 1) is_copyable(attr) returns true and 2) the attribute was set to the model.

source
MathOptInterface.ListOfVariableAttributesSetType
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.

source

Optimizers

MathOptInterface.AbstractOptimizerType
AbstractOptimizer

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.

source
MathOptInterface.instantiateFunction
instantiate(optimizer_constructor,
            with_bridge_type::Union{Nothing, Type}=nothing,
            with_names::Bool=false)

Creates an instance of optimizer either by calling optimizer_constructor.optimizer_constructor() and setting the parameters in optimizer_constructor.params if optimizer_constructor is a OptimizerWithAttributes or by calling optimizer_constructor() if optimizer_constructor is callable.

If with_bridge_type is not nothing, it enables all the bridges defined in the MathOptInterface.Bridges submodule with coefficient type with_bridge_type.

If the optimizer created by optimizer_constructor does not support loading the problem incrementally or does not support names and with_names is true (see Utilities.supports_default_copy_to) then a Utilities.CachingOptimizer is added to store a cache of the bridged model. Hence set with_names to true if names might be set.

source

List of optimizers attributes

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

source
MathOptInterface.TimeLimitSecType
TimeLimitSec()

An optimizer attribute for setting a time limit for an optimization. When set to nothing, it deactivates the solver time limit. The default value is nothing. The time limit is in seconds.

source
MathOptInterface.RawParameterType
RawParameter(name)

An optimizer attribute for the solver-specific parameter identified by name which is typically an Enum or a String.

source
MathOptInterface.NumberOfThreadsType
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.

source
MathOptInterface.AbstractCallbackType
abstract type AbstractCallback <: AbstractModelAttribute end

Abstract type for a model attribute representing a callback function. The value set to subtypes of AbstractCallback is a function that may be called during optimize!. As optimize! is in progress, the result attributes (i.e, the attributes attr such that is_set_by_optimize(attr)) may not be accessible from the callback, hence trying to get result attributes might throw a OptimizeInProgress error.

At most one callback of each type can be registered. If an optimizer already has a function for a callback type, and the user registers a new function, then the old one is replaced.

The value of the attribute should be a function taking only one argument, commonly called callback_data, that can be used for instance in LazyConstraintCallback, HeuristicCallback and UserCutCallback.

source
MathOptInterface.LazyConstraintCallbackType
LazyConstraintCallback() <: AbstractCallback

The callback can be used to reduce the feasible set given the current primal solution by submitting a LazyConstraint. For instance, it may be called at an incumbent of a mixed-integer problem. Note that there is no guarantee that the callback is called at every feasible primal solution.

The feasible primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
MOI.set(optimizer, MOI.LazyConstraintCallback(), callback_data -> begin
    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
    if # should add a lazy constraint
        func = # computes function
        set = # computes set
        MOI.submit(optimizer, MOI.LazyConstraint(callback_data), func, set)
    end
end
source
MathOptInterface.HeuristicCallbackType
HeuristicCallback() <: AbstractCallback

The callback can be used to submit HeuristicSolution given the current primal solution. For instance, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.

The current primal solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
MOI.set(optimizer, MOI.HeuristicCallback(), callback_data -> begin
    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
    if # can find a heuristic solution
        values = # computes heuristic solution
        MOI.submit(optimizer, MOI.HeuristicSolution(callback_data), x,
                   values)
    end
end
source
MathOptInterface.UserCutCallbackType
UserCutCallback() <: AbstractCallback

The callback can be used to submit UserCut given the current primal solution. For instance, it may be called at fractional (i.e., non-integer) nodes in the branch and bound tree of a mixed-integer problem. Note that there is not guarantee that the callback is called everytime the solver has an infeasible solution.

The infeasible solution is accessed through CallbackVariablePrimal. Trying to access other result attributes will throw OptimizeInProgress as discussed in AbstractCallback.

Examples

x = MOI.add_variables(optimizer, 8)
MOI.set(optimizer, MOI.UserCutCallback(), callback_data -> begin
    sol = MOI.get(optimizer, MOI.CallbackVariablePrimal(callback_data), x)
    if # can find a user cut
        func = # computes function
        set = # computes set
        MOI.submit(optimizer, MOI.UserCut(callback_data), func, set)
    end
end
source

List of attributes useful for optimizers

MathOptInterface.ObjectiveFunctionType
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}.

source
MathOptInterface.ObjectiveFunctionTypeType
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.SingleVariable:

x = MOI.add_variable(model)
MOI.set(model, MOI.ObjectiveFunction{MOI.SingleVariable}(),
         MOI.SingleVariable(x))
attr = MOI.get(model, MOI.ObjectiveFunctionType())
source
MathOptInterface.RelativeGapType
RelativeGap()

A model attribute for the final relative optimality gap, defined as $\frac{|b-f|}{|f|}$, where $b$ is the best bound and $f$ is the best feasible objective value.

source
MathOptInterface.SimplexIterationsType
SimplexIterations()

A model attribute for the cumulative number of simplex iterations during the optimization process. In particular, for a mixed-integer program (MIP), the total simplex iterations for all nodes.

source
MathOptInterface.NodeCountType
NodeCount()

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

source
MathOptInterface.PrimalStatusType
PrimalStatus(N)
PrimalStatus()

A model attribute for the ResultStatusCode of the primal result N. If N is omitted, it defaults to 1. If N is larger than the value of ResultCount then NO_SOLUTION is returned.

source
MathOptInterface.DualStatusType
DualStatus(N)
DualStatus()

A model attribute for the ResultStatusCode of the dual result N. If N is omitted, it defaults to 1. If N is larger than the value of ResultCount then NO_SOLUTION is returned.

source

Termination Status

The TerminationStatus attribute indicates why the optimizer stopped executing. The value of the attribute is of type TerminationStatusCode.

MathOptInterface.TerminationStatusCodeType
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 algorthm 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.
source

Result Status

The PrimalStatus and DualStatus attributes indicate how to interpret the result returned by the solver. The value of the attribute is of type ResultStatusCode.

MathOptInterface.ResultStatusCodeType
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.
source

Variables and Constraints

Basis Status

The BasisStatus attribute of a constraint describes its status with respect to a basis, if one is known. The value of the attribute is of type BasisStatusCode.

MathOptInterface.BasisStatusCodeType
BasisStatusCode

An Enum of possible values for the ConstraintBasisStatus attribute. This explains the status of a given element with respect to an optimal solution basis. Possible values are:

  • BASIC: element is in the basis
  • NONBASIC: element is not in the basis
  • NONBASIC_AT_LOWER: element is not in the basis and is at its lower bound
  • NONBASIC_AT_UPPER: element is not in the basis and is at its upper bound
  • SUPER_BASIC: element is not in the basis but is also not at one of its bounds

Note: NONBASIC_AT_LOWER and NONBASIC_AT_UPPER should be used only for constraints with the Interval. In this case cases they are necessary to distinguish which side of the constraint. One-sided constraints (e.g., LessThan and GreaterThan) should use NONBASIC instead of the NONBASIC_AT_* values.

source

Index types

MathOptInterface.VariableIndexType
VariableIndex

A type-safe wrapper for Int64 for use in referencing variables in a model. To allow for deletion, indices need not be consecutive.

source
MathOptInterface.ConstraintIndexType
ConstraintIndex{F, S}

A type-safe wrapper for Int64 for use in referencing F-in-S constraints in a model. The parameter F is the type of the function in the constraint, and the parameter S is the type of set in the constraint. To allow for deletion, indices need not be consecutive. Indices within a constraint type (i.e. F-in-S) must be unique, but non-unique indices across different constraint types are allowed. If F is SingleVariable then the index is equal to the index of the variable. That is for an index::ConstraintIndex{SingleVariable}, we always have

index.value == MOI.get(model, MOI.ConstraintFunction(), index).variable.value
source
MathOptInterface.is_validFunction
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.deleteMethod
delete(model::ModelLike, index::Index)

Delete the referenced object from the model. Throw DeleteNotAllowed if if index cannot be deleted.

The following modifications also take effect if Index is VariableIndex:

  • If index used in the objective function, it is removed from the function, i.e., it is substituted for zero.
  • For each func-in-set constraint of the model:
    • If func isa SingleVariable and func.variable == index then the constraint is deleted.
    • If func isa VectorOfVariables and index in func.variable then
      • if length(func.variable) == 1 is one, the constraint is deleted;
      • if length(func.variable) > 1 and supports_dimension_update(set) then then the variable is removed from func and set is replaced by update_dimension(set, MOI.dimension(set) - 1).
      • Otherwise, a DeleteNotAllowed error is thrown.
    • Otherwise, the variable is removed from func, i.e., it is substituted for zero.
source
MathOptInterface.deleteMethod
delete(model::ModelLike, indices::Vector{R<:Index}) where {R}

Delete the referenced objects in the vector indices from the model. It may be assumed that R is a concrete type. The default fallback sequentially deletes the individual items in indices, although specialized implementations may be more efficient.

source

Variables

Free variables are the variables created with add_variable or add_variables while constrained variables are the variables created with add_constrained_variable or add_constrained_variables. Adding constrained variables instead of constraining free variables with add_constraint allows variable bridges to be used. Note further that free variables that are constrained with add_constraint may be copied by copy_to with add_constrained_variable or add_constrained_variables by the Utilities.CachingOptimizer. More precisely, the attributes do not distinguish constraints on variables created with add_constrained_variable(s) or add_variable(s)/add_constraint. When the model is copied, if a variable is constrained in several sets, the implementation of copy_to can determine whether it is added using add_variable or add_constrained_variable with one of the sets. The rest of the constraints on the variables are added with add_constraint. For deleting, see Index types.

MathOptInterface.add_variablesFunction
add_variables(model::ModelLike, n::Int)::Vector{VariableIndex}

Add n scalar variables to the model, returning a vector of variable indices.

A AddVariableNotAllowed error is thrown if adding variables cannot be done in the current state of the model model.

source
MathOptInterface.add_constrained_variableFunction
add_constrained_variable(
    model::ModelLike,
    set::AbstractScalarSet
)::Tuple{MOI.VariableIndex,
         MOI.ConstraintIndex{MOI.SingleVariable, typeof(set)}}

Add to model a scalar variable constrained to belong to set, returning the index of the variable created and the index of the constraint constraining the variable to belong to set.

By default, this function falls back to creating a free variable with add_variable and then constraining it to belong to set with add_constraint.

source
MathOptInterface.add_constrained_variablesFunction
add_constrained_variables(
    model::ModelLike,
    sets:AbstractVector{<:AbstractScalarSet}
)::Tuple{Vector{MOI.VariableIndex},
         Vector{MOI.ConstraintIndex{MOI.SingleVariable, eltype(sets)}}}

Add to model scalar variables constrained to belong to sets, returning the indices of the variables created and the indices of the constraints constraining the variables to belong to each set in sets. That is, if it returns variables and constraints, constraints[i] is the index of the constraint constraining variable[i] to belong to sets[i].

By default, this function falls back to calling add_constrained_variable on each set.

source
add_constrained_variables(
    model::ModelLike,
    set::AbstractVectorSet
)::Tuple{Vector{MOI.VariableIndex},
         MOI.ConstraintIndex{MOI.VectorOfVariables, typeof(set)}}

Add to model a vector of variables constrained to belong to set, returning the indices of the variables created and the index of the constraint constraining the vector of variables to belong to set.

By default, this function falls back to creating free variables with add_variables and then constraining it to belong to set with add_constraint.

source
MathOptInterface.supports_add_constrained_variableFunction
supports_add_constrained_variable(
    model::ModelLike,
    S::Type{<:AbstractScalarSet}
)::Bool

Return a Bool indicating whether model supports constraining a variable to belong to a set of type S either on creation of the variable with add_constrained_variable or after the variable is created with add_constraint.

By default, this function falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.SingleVariable, S) which is the correct definition for most models.

Example

Suppose that a solver supports only two kind of variables: binary variables and continuous variables with a lower bound. If the solver decides not to support SingleVariable-in-Binary and SingleVariable-in-GreaterThan constraints, it only has to implement add_constrained_variable for these two sets which prevents the user to add both a binary constraint and a lower bound on the same variable. Moreover, if the user adds a SingleVariable-in-GreaterThan constraint, implementing this interface (i.e., supports_add_constrained_variables) enables the constraint to be transparently bridged into a supported constraint.

source
MathOptInterface.supports_add_constrained_variablesFunction
supports_add_constrained_variables(
    model::ModelLike,
    S::Type{<:AbstractVectorSet}
)::Bool

Return a Bool indicating whether model supports constraining a vector of variables to belong to a set of type S either on creation of the vector of variables with add_constrained_variables or after the variable is created with add_constraint.

By default, if S is Reals then this function returns true and otherwise, it falls back to supports_add_constrained_variables(model, Reals) && supports_constraint(model, MOI.VectorOfVariables, S) which is the correct definition for most models.

Example

In the standard conic form (see Duals), the variables are grouped into several cones and the constraints are affine equality constraints. If Reals is not one of the cones supported by the solvers then it needs to implement supports_add_constrained_variables(::Optimizer, ::Type{Reals}) = false as free variables are not supported. The solvers should then implement supports_add_constrained_variables(::Optimizer, ::Type{<:SupportedCones}) = true where SupportedCones is the union of all cone types that are supported; it does not have to implement the method supports_constraint(::Type{VectorOfVariables}, Type{<:SupportedCones}) as it should return false and it's the default. This prevents the user to constrain the same variable in two different cones. When a VectorOfVariables-in-S is added, the variables of the vector have already been created so they already belong to given cones. If bridges are enabled, the constraint will therefore be bridged by adding slack variables in S and equality constraints ensuring that the slack variables are equal to the corresponding variables of the given constraint function.

Note that there may also be sets for which !supports_add_constrained_variables(model, S) and supports_constraint(model, MOI.VectorOfVariables, S). For instance, suppose a solver supports positive semidefinite variable constraints and two types of variables: binary variables and nonnegative variables. Then the solver should support adding VectorOfVariables-in-PositiveSemidefiniteConeTriangle constraints, but it should not support creating variables constrained to belong to the PositiveSemidefiniteConeTriangle because the variables in PositiveSemidefiniteConeTriangle should first be created as either binary or non-negative.

source

List of attributes associated with variables. [category AbstractVariableAttribute] Calls to get and set should include as an argument a single VariableIndex or a vector of VariableIndex objects.

MathOptInterface.VariableNameType
VariableName()

A variable attribute for a string identifying the variable. It is valid for two variables to have the same name; however, variables with duplicate names cannot be looked up using get. It has a default value of "" if not set`.

source
MathOptInterface.VariablePrimalType
VariablePrimal(N)
VariablePrimal()

A variable attribute for the assignment to some primal variable's value in result N. If N is omitted, it is 1 by default.

source

Constraints

Functions for adding and modifying constraints.

MathOptInterface.is_validMethod
is_valid(model::ModelLike, index::Index)::Bool

Return a Bool indicating whether this index refers to a valid object in the model model.

source
MathOptInterface.add_constraintFunction
add_constraint(model::ModelLike, func::F, set::S)::ConstraintIndex{F,S} where {F,S}

Add the constraint $f(x) \in \mathcal{S}$ where $f$ is defined by func, and $\mathcal{S}$ is defined by set.

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

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

source
MathOptInterface.add_constraintsFunction
add_constraints(model::ModelLike, funcs::Vector{F}, sets::Vector{S})::Vector{ConstraintIndex{F,S}} where {F,S}

Add the set of constraints specified by each function-set pair in funcs and sets. F and S should be concrete types. This call is equivalent to add_constraint.(model, funcs, sets) but may be more efficient.

source
MathOptInterface.transformFunction

Transform Constraint Set

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

Replace the set in constraint c with newset. The constraint index c will no longer be valid, and the function returns a new constraint index with the correct type.

Solvers may only support a subset of constraint transforms that they perform efficiently (for example, changing from a LessThan to GreaterThan set). In addition, set modification (where S1 = S2) should be performed via the modify function.

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

Examples

If c is a ConstraintIndex{ScalarAffineFunction{Float64},LessThan{Float64}},

c2 = transform(model, c, GreaterThan(0.0))
transform(model, c, LessThan(0.0)) # errors
source
MathOptInterface.supports_constraintFunction
MOI.supports_constraint(BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet})::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

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

Return a Bool indicating whether model supports F-in-S constraints, that is, copy_to(model, src) does not throw UnsupportedConstraint when src contains F-in-S constraints. If F-in-S constraints are only not supported in specific circumstances, e.g. F-in-S constraints cannot be combined with another type of constraint, it should still return true.

supports_constraint(model::ModelLike, ::Type{VectorOfVariables}, ::Type{Reals})::Bool

Return a Bool indicating whether model supports free variables. That is, copy_to(model, src) does not error when src contains variables that are not constrained by any SingleVariable or VectorOfVariables constraint. By default, this method returns true so it should only be implemented if model does not support free variables. For instance, if a solver requires all variables to be nonnegative, it should implement this method and return false because free variables cannot be copied to the solver.

Note that free variables are not explicitly set to be free by calling add_constraint with the set Reals, instead, free variables are created with add_variable and add_variables. If model does not support free variables, it should not implement add_variable nor add_variables but should implement this method and return false. This allows free variables to be bridged as the sum of a nonnegative and a nonpositive variables.

source

List of attributes associated with constraints. [category AbstractConstraintAttribute] Calls to get and set should include as an argument a single ConstraintIndex or a vector of ConstraintIndex{F,S} objects.

MathOptInterface.ConstraintNameType
ConstraintName()

A constraint attribute for a string identifying the constraint. It is valid for constraints variables to have the same name; however, constraints with duplicate names cannot be looked up using get regardless of if they have the same F-in-S type. It has a default value of "" if not set.

source
MathOptInterface.ConstraintPrimalType
ConstraintPrimal(N)
ConstraintPrimal()

A constraint attribute for the assignment to some constraint's primal value(s) in result N. If N is omitted, it is 1 by default.

Given a constraint function-in-set, the ConstraintPrimal is the value of the function evaluated at the primal solution of the variables. For example, given the constraint ScalarAffineFunction([x,y], [1, 2], 3)-in-Interval(0, 20) and a primal solution of (x,y) = (4,5), the ConstraintPrimal solution of the constraint is 1 * 4 + 2 * 5 + 3 = 17.

source
MathOptInterface.ConstraintDualType
ConstraintDual(N)
ConstraintDual()

A constraint attribute for the assignment to some constraint's dual value(s) in result N. If N is omitted, it is 1 by default.

source
MathOptInterface.ConstraintBasisStatusType
ConstraintBasisStatus(result_index)
ConstraintBasisStatus()

A constraint attribute for the BasisStatusCode of some constraint in result result_index, with respect to an available optimal solution basis. If result_index is omitted, it is 1 by default.

For the basis status of a variable, query the corresponding SingleVariable constraint that enforces the variable's bounds.

source
MathOptInterface.ConstraintFunctionType
ConstraintFunction()

A constraint attribute for the AbstractFunction object used to define the constraint. It is guaranteed to be equivalent but not necessarily identical to the function provided by the user.

source

Note that setting the ConstraintFunction of a [SingleVariable] constraint is not allowed:

Functions and function modifications

List of recognized functions.

MathOptInterface.SingleVariableType
SingleVariable(variable)

The function that extracts the scalar variable referenced by variable, a VariableIndex. This function is naturally be used for single variable bounds or integrality constraints.

source
MathOptInterface.VectorOfVariablesType
VectorOfVariables(variables)

The function that extracts the vector of variables referenced by variables, a Vector{VariableIndex}. This function is naturally be used for constraints that apply to groups of variables, such as an "all different" constraint, an indicator constraint, or a complementarity constraint.

source
MathOptInterface.ScalarAffineTermType
struct ScalarAffineTerm{T}
    coefficient::T
    variable_index::VariableIndex
end

Represents $c x_i$ where $c$ is coefficient and $x_i$ is the variable identified by variable_index.

source
MathOptInterface.ScalarAffineFunctionType
ScalarAffineFunction{T}(terms, constant)

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

  • $a$ is a sparse vector specified by a list of ScalarAffineTerm structs.
  • $b$ is a scalar specified by constant::T

Duplicate variable indices in terms are accepted, and the corresponding coefficients are summed together.

source
MathOptInterface.VectorAffineTermType
struct VectorAffineTerm{T}
    output_index::Int64
    scalar_term::ScalarAffineTerm{T}
end

A ScalarAffineTerm plus its index of the output component of a VectorAffineFunction or VectorQuadraticFunction. output_index can also be interpreted as a row index into a sparse matrix, where the scalar_term contains the column index and coefficient.

source
MathOptInterface.VectorAffineFunctionType
VectorAffineFunction{T}(terms, constants)

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

  • $A$ is a sparse matrix specified by a list of VectorAffineTerm objects.
  • $b$ is a vector specified by constants

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

source
MathOptInterface.ScalarQuadraticTermType
struct ScalarQuadraticTerm{T}
    coefficient::T
    variable_index_1::VariableIndex
    variable_index_2::VariableIndex
end

Represents $c x_i x_j$ where $c$ is coefficient, $x_i$ is the variable identified by variable_index_1 and $x_j$ is the variable identified by variable_index_2.

source
MathOptInterface.ScalarQuadraticFunctionType
ScalarQuadraticFunction{T}(affine_terms, quadratic_terms, constant)

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

  • $a$ is a sparse vector specified by a list of ScalarAffineTerm structs.
  • $b$ is a scalar specified by constant.
  • $Q$ is a symmetric matrix specified by a list of ScalarQuadraticTerm structs.

Duplicate indices in $a$ or $Q$ are accepted, and the corresponding coefficients are summed together. "Mirrored" indices (q,r) and (r,q) (where r and q are VariableIndexes) are considered duplicates; only one need be specified.

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

source
MathOptInterface.VectorQuadraticFunctionType
VectorQuadraticFunction{T}(affine_terms, quadratic_terms, constant)

The vector-valued quadratic function with ith component ("output index") defined as $\frac{1}{2}x^TQ_ix + a_i^T x + b_i$, where:

  • $a_i$ is a sparse vector specified by the VectorAffineTerms with output_index == i.
  • $b_i$ is a scalar specified by constants[i]
  • $Q_i$ is a symmetric matrix specified by the VectorQuadraticTerm with output_index == i.

Duplicate indices in $a_i$ or $Q_i$ are accepted, and the corresponding coefficients are summed together. "Mirrored" indices (q,r) and (r,q) (where r and q are VariableIndexes) are considered duplicates; only one need be specified.

source

Functions for getting and setting properties of functions.

MathOptInterface.constantMethod
constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction})

Returns the constant term of the scalar function

source
MathOptInterface.constantMethod
constant(f::Union{VectorAffineFunction, VectorQuadraticFunction})

Returns the vector of constant terms of the vector function

source
MathOptInterface.constantMethod
constant(f::SingleVariable, T::DataType)

The constant term of a SingleVariable function is the zero value of the specified type T.

source
MathOptInterface.constantMethod
constant(f::VectorOfVariables, T::DataType)

The constant term of a VectorOfVariables function is a vector of zero values of the specified type T.

source

Sets

All sets are subtypes of AbstractSet and they should either be scalar or vector sets.

Functions for getting properties of sets.

MathOptInterface.dual_setFunction
dual_set(s::AbstractSet)

Return the dual set of s, that is the dual cone of the set. This follows the definition of duality discussed in Duals. See Dual cone for more information. If the dual cone is not defined it returns an error.

Examples

julia> dual_set(Reals(4))
Zeros(4)

julia> dual_set(SecondOrderCone(5))
SecondOrderCone(5)

julia> dual_set(ExponentialCone())
DualExponentialCone()
source
MathOptInterface.dual_set_typeFunction
dual_set_type(S::Type{<:AbstractSet})

Return the type of dual set of sets of type S, as returned by dual_set. If the dual cone is not defined it returns an error.

Examples

julia> dual_set_type(Reals)
Zeros

julia> dual_set_type(SecondOrderCone)
SecondOrderCone

julia> dual_set_type(ExponentialCone)
DualExponentialCone
source
MathOptInterface.supports_dimension_updateFunction
supports_dimension_update(S::Type{<:MOI.AbstractVectorSet})

Return a Bool indicating whether the elimination of any dimension of n-dimensional sets of type S give an n-1-dimensional set S. By default, this function returns false so it should only be implemented for sets that supports dimension update.

For instance, supports_dimension_update(MOI.Nonnegatives} is true because the elimination of any dimension of the n-dimensional nonnegative orthant gives the n-1-dimensional nonnegative orthant. However supports_dimension_update(MOI.ExponentialCone} is false.

source

Scalar sets

List of recognized scalar sets.

MathOptInterface.EqualToType
EqualTo{T <: Number}(value::T)

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

source
MathOptInterface.IntervalType
Interval{T <: Real}(lower::T,upper::T)

The interval $[lower, upper] \subseteq \mathbb{R}$. If lower or upper is -Inf or Inf, respectively, the set is interpreted as a one-sided interval.

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

Construct a (right-unbounded) Interval equivalent to the given GreaterThan set.

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

Construct a (left-unbounded) Interval equivalent to the given LessThan set.

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

Construct a (degenerate) Interval equivalent to the given EqualTo set.

source

Vector sets

List of recognized vector sets.

MathOptInterface.NormInfinityConeType
NormInfinityCone(dimension)

The $\ell_\infty$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}$ of dimension dimension.

source
MathOptInterface.NormOneConeType
NormOneCone(dimension)

The $\ell_1$-norm cone $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}$ of dimension dimension.

source
MathOptInterface.SecondOrderConeType
SecondOrderCone(dimension)

The second-order cone (or Lorenz cone or $\ell_2$-norm cone) $\{ (t,x) \in \mathbb{R}^{dimension} : t \ge \lVert x \rVert_2 \}$ of dimension dimension.

source
MathOptInterface.GeometricMeanConeType
GeometricMeanCone(dimension)

The geometric mean cone $\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}$ of dimension dimension${}=n+1$.

Duality note

The dual of the geometric mean cone is $\{ (u, v) \in \mathbb{R}^{n+1} : u \le 0, v \ge 0, -u \le n \sqrt[n]{\prod_i v_i} \}$ of dimension dimension${}=n+1$.

source
MathOptInterface.PowerConeType
PowerCone{T <: Real}(exponent::T)

The 3-dimensional power cone $\{ (x,y,z) \in \mathbb{R}^3 : x^{exponent} y^{1-exponent} \ge |z|, x \ge 0, y \ge 0 \}$ with parameter exponent.

source
MathOptInterface.DualPowerConeType
DualPowerCone{T <: Real}(exponent::T)

The 3-dimensional power cone $\{ (u,v,w) \in \mathbb{R}^3 : (\frac{u}{exponent})^{exponent} (\frac{v}{1-exponent})^{1-exponent} \ge |w|, u \ge 0, v \ge 0 \}$ with parameter exponent.

source
MathOptInterface.RelativeEntropyConeType
RelativeEntropyCone(dimension)

The relative entropy cone $\{ (u, v, w) \in \mathbb{R}^{1+2n} : u \ge \sum_{i=1}^n w_i \log (\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}$ of dimension dimension${}=2n+1$.

Duality note

The dual of the relative entropy cone is $\{ (u, v, w) \in \mathbb{R}^{1+2n} : \forall i, -u \exp (w_i/u) \le \exp(1) v_i, u < 0 \}$ of dimension dimension${}=2n+1$. Note that the inequality is rewritten in terms of $\log$ as follows: $w_i \le u (\log(v_i/-u) + 1)$.

source
MathOptInterface.NormSpectralConeType
NormSpectralCone(row_dim, column_dim)

The epigraph of the matrix spectral norm (maximum singular value function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sigma_1(X) \}$ where $\sigma_i$ is the $i$th singular value of the matrix $X$ of row dimension row_dim and column dimension column_dim. The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

source
MathOptInterface.NormNuclearConeType
NormNuclearCone(row_dim, column_dim)

The epigraph of the matrix nuclear norm (sum of singular values function) $\{ (t, X) \in \mathbb{R}^{1 + row_dim \times column_dim} : t \ge \sum_i \sigma_i(X) \}$ where $\sigma_i$ is the $i$th singular value of the matrix $X$ of row dimension row_dim and column dimension column_dim. The matrix X is vectorized by stacking the columns, matching the behavior of Julia's vec function.

source
MathOptInterface.SOS1Type
SOS1{T <: Real}(weights::Vector{T})

The set corresponding to the special ordered set (SOS) constraint of type 1. Of the variables in the set, at most one can be nonzero. The weights induce an ordering of the variables; as such, they should be unique values. The kth element in the set corresponds to the kth weight in weights. See here for a description of SOS constraints and their potential uses.

source
MathOptInterface.SOS2Type
SOS2{T <: Real}(weights::Vector{T})

The set corresponding to the special ordered set (SOS) constraint of type 2. Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set. The weights induce an ordering of the variables; as such, they should be unique values. The kth element in the set corresponds to the kth weight in weights. See here for a description of SOS constraints and their potential uses.

source
MathOptInterface.IndicatorSetType
IndicatorSet{A, S <: AbstractScalarSet}(set::S)

$\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 0 \implies x \in set\}$ when A is ACTIVATE_ON_ZERO and $\{(y, x) \in \{0, 1\} \times \mathbb{R}^n : y = 1 \implies x \in set\}$ when A is ACTIVATE_ON_ONE.

S has to be a sub-type of AbstractScalarSet. A is one of the value of the ActivationCond enum. IndicatorSet is used with a VectorAffineFunction holding the indicator variable first.

Example: $\{(y, x) \in \{0, 1\} \times \mathbb{R}^2 : y = 1 \implies x_1 + x_2 \leq 9 \}$

f = MOI.VectorAffineFunction(
    [MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, z)),
     MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(0.2, x1)),
     MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x2)),
    ],
    [0.0, 0.0],
)

indicator_set = MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(9.0))

MOI.add_constraint(model, f, indicator_set)
source
MathOptInterface.ComplementsType
Complements(dimension::Int)

The set corresponding to a mixed complementarity constraint.

Complementarity constraints should be specified with an AbstractVectorFunction-in-Complements(dimension) constraint.

The dimension of the vector-valued function F must be 2 * dimension. This defines a complementarity constraint between the scalar function F[i] and the variable in F[i + dimension]. Thus, F[i + dimension] must be interpretable as a single variable x_i (e.g., 1.0 * x + 0.0).

The mixed complementarity problem consists of finding x_i in the interval [lb, ub] (i.e., in the set Interval(lb, ub)), such that the following holds:

  1. F_i(x) == 0 if lb_i < x_i < ub_i
  2. F_i(x) >= 0 if lb_i == x_i
  3. F_i(x) <= 0 if x_i == ub_i

Classically, the bounding set for x_i is Interval(0, Inf), which recovers: 0 <= F_i(x) ⟂ x_i >= 0, where the operator implies F_i(x) * x_i = 0.

Examples

The problem:

x -in- Interval(-1, 1)
[-4 * x - 3, x] -in- Complements(1)

defines the mixed complementarity problem where the following holds:

  1. -4 * x - 3 == 0 if -1 < x < 1
  2. -4 * x - 3 >= 0 if x == -1
  3. -4 * x - 3 <= 0 if x == 1

There are three solutions:

  1. x = -3/4 with F(x) = 0
  2. x = -1 with F(x) = 1
  3. x = 1 with F(x) = -7

The function F can also be defined in terms of single variables. For example, the problem:

[x_3, x_4] -in- Nonnegatives(2)
[x_1, x_2, x_3, x_4] -in- Complements(2)

defines the complementarity problem where 0 <= x_1 ⟂ x_3 >= 0 and 0 <= x_2 ⟂ x_4 >= 0.

source

Matrix sets

Matrix sets are vectorized in order to be subtypes of AbstractVectorSet. For sets of symmetric matrices, storing both the (i, j) and (j, i) elements is redundant so there exists the AbstractSymmetricMatrixSetTriangle set to represent only the vectorization of the upper triangular part of the matrix. When the matrix of expressions constrained to be in the set is not symmetric and hence the (i, j) and (j, i) elements should be constrained to be symmetric, the AbstractSymmetricMatrixSetSquare set can be used. The Bridges.Constraint.SquareBridge can transform a set from the square form to the triangular_form by adding appropriate constraints if the (i, j) and (j, i) expressions are different.

MathOptInterface.AbstractSymmetricMatrixSetTriangleType
abstract type AbstractSymmetricMatrixSetTriangle <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row). A vectorized cone of dimension $n$ corresponds to a square matrix with side dimension $\sqrt{1/4 + 2 n} - 1/2$. (Because a $d \times d$ matrix has $d(d + 1) / 2$ elements in the upper or lower triangle.)

Examples

The matrix

\[\begin{bmatrix} 1 & 2 & 4\\ 2 & 3 & 5\\ 4 & 5 & 6 \end{bmatrix}\]

has side_dimension 3 and vectorization $(1, 2, 3, 4, 5, 6)$.

Note

Two packed storage formats exist for symmetric matrices, the respective orders of the entries are:

  • upper triangular column by column (or lower triangular row by row);
  • lower triangular column by column (or upper triangular row by row).

The advantage of the first format is the mapping between the (i, j) matrix indices and the k index of the vectorized form. It is simpler and does not depend on the side dimension of the matrix. Indeed,

  • the entry of matrix indices (i, j) has vectorized index k = div((j - 1) * j, 2) + i if $i \leq j$ and k = div((i - 1) * i, 2) + j if $j \leq i$;
  • and the entry with vectorized index k has matrix indices i = div(1 + isqrt(8k - 7), 2) and j = k - div((i - 1) * i, 2) or j = div(1 + isqrt(8k - 7), 2) and i = k - div((j - 1) * j, 2).

Duality note

The scalar product for the symmetric matrix in its vectorized form is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries; see [p. 634, 1]. This has important consequence for duality.

Consider for example the following problem (PositiveSemidefiniteConeTriangle is a subtype of AbstractSymmetricMatrixSetTriangle)

\[\begin{align*} & \max_{x \in \mathbb{R}} & x \\ & \;\;\text{s.t.} & (1, -x, 1) & \in \text{PositiveSemidefiniteConeTriangle}(2). \end{align*}\]

The dual is the following problem

\[\begin{align*} & \min_{x \in \mathbb{R}^3} & y_1 + y_3 \\ & \;\;\text{s.t.} & 2y_2 & = 1\\ & & y & \in \text{PositiveSemidefiniteConeTriangle}(2). \end{align*}\]

Why do we use $2y_2$ in the dual constraint instead of $y_2$ ? The reason is that $2y_2$ is the scalar product between $y$ and the symmetric matrix whose vectorized form is $(0, 1, 0)$. Indeed, with our modified scalar products we have

\[\langle (0, 1, 0), (y_1, y_2, y_3) \rangle = \mathrm{trace} \begin{pmatrix} 0 & 1\\ 1 & 0 \end{pmatrix} \begin{pmatrix} y_1 & y_2\\ y_2 & y_3 \end{pmatrix} = 2y_2.\]

References

[1] Boyd, S. and Vandenberghe, L.. Convex optimization. Cambridge university press, 2004.

source
MathOptInterface.AbstractSymmetricMatrixSetSquareType
abstract type AbstractSymmetricMatrixSetSquare <: AbstractVectorSet end

Abstract supertype for subsets of the (vectorized) cone of symmetric matrices, with side_dimension rows and columns. The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to have its triangular_form belong to the corresponding set. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Examples

PositiveSemidefiniteConeSquare is a subtype of AbstractSymmetricMatrixSetSquare and constraining the matrix

\[\begin{bmatrix} 1 & -y\\ -z & 0\\ \end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2), since triangular_form(PositiveSemidefiniteConeSquare) is PositiveSemidefiniteConeTriangle.

source
MathOptInterface.side_dimensionFunction
side_dimension(set::Union{AbstractSymmetricMatrixSetTriangle,
                          AbstractSymmetricMatrixSetSquare})

Side dimension of the matrices in set. By convention, it should be stored in the side_dimension field but if it is not the case for a subtype of AbstractSymmetricMatrixSetTriangle, the method should be implemented for this subtype.

source

List of recognized matrix sets.

MathOptInterface.PositiveSemidefiniteConeSquareType
PositiveSemidefiniteConeSquare(side_dimension) <: AbstractSymmetricMatrixSetSquare

The cone of symmetric positive semidefinite matrices, with side length side_dimension. See AbstractSymmetricMatrixSetSquare for more details on the vectorized form.

The entries of the matrix are given column by column (or equivalently, row by row). The matrix is both constrained to be symmetric and to be positive semidefinite. That is, if the functions in entries $(i, j)$ and $(j, i)$ are different, then a constraint will be added to make sure that the entries are equal.

Examples

Constraining the matrix

\[\begin{bmatrix} 1 & -y\\ -z & 0\\ \end{bmatrix}\]

to be symmetric positive semidefinite can be achieved by constraining the vector $(1, -z, -y, 0)$ (or $(1, -y, -z, 0)$) to belong to the PositiveSemidefiniteConeSquare(2). It both constrains $y = z$ and $(1, -y, 0)$ (or $(1, -z, 0)$) to be in PositiveSemidefiniteConeTriangle(2).

source
MathOptInterface.LogDetConeTriangleType
LogDetConeTriangle(side_dimension)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d(d+1)/2} : t \le u \log(\det(X/u)), u > 0 \}$ where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle. The argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

source
MathOptInterface.LogDetConeSquareType
LogDetConeSquare(side_dimension)

The log-determinant cone $\{ (t, u, X) \in \mathbb{R}^{2 + d^2} : t \le u \log(\det(X/u)), X \text{ symmetric}, u > 0 \}$ where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare. Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensures that X is symmetric. The argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

source
MathOptInterface.RootDetConeTriangleType
RootDetConeTriangle(side_dimension)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d(d+1)/2} : t \le \det(X)^{1/d} \}$ where the matrix X is represented in the same symmetric packed format as in the PositiveSemidefiniteConeTriangle. The argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

source
MathOptInterface.RootDetConeSquareType
RootDetConeSquare(side_dimension)

The root-determinant cone $\{ (t, X) \in \mathbb{R}^{1 + d^2} : t \le \det(X)^{1/d}, X \text{ symmetric} \}$ where the matrix X is represented in the same format as in the PositiveSemidefiniteConeSquare. Similarly to PositiveSemidefiniteConeSquare, constraints are added to ensure that X is symmetric. The argument side_dimension is the side dimension of the matrix X, i.e., its number of rows or columns.

source

Modifications

Functions for modifying objective and constraint functions.

MathOptInterface.modifyFunction

Constraint Function

modify(model::ModelLike, ci::ConstraintIndex, change::AbstractFunctionModification)

Apply the modification specified by change to the function of constraint ci.

An ModifyConstraintNotAllowed error is thrown if modifying constraints is not supported by the model model.

Examples

modify(model, ci, ScalarConstantChange(10.0))

Objective Function

modify(model::ModelLike, ::ObjectiveFunction, change::AbstractFunctionModification)

Apply the modification specified by change to the objective function of model. To change the function completely, call set instead.

An ModifyObjectiveNotAllowed error is thrown if modifying objectives is not supported by the model model.

Examples

modify(model, ObjectiveFunction{ScalarAffineFunction{Float64}}(), ScalarConstantChange(10.0))
source
MathOptInterface.AbstractFunctionModificationType
AbstractFunctionModification

An abstract supertype for structs which specify partial modifications to functions, to be used for making small modifications instead of replacing the functions entirely.

source
MathOptInterface.ScalarConstantChangeType
ScalarConstantChange{T}(new_constant::T)

A struct used to request a change in the constant term of a scalar-valued function. Applicable to ScalarAffineFunction and ScalarQuadraticFunction.

source
MathOptInterface.VectorConstantChangeType
VectorConstantChange{T}(new_constant::Vector{T})

A struct used to request a change in the constant vector of a vector-valued function. Applicable to VectorAffineFunction and VectorQuadraticFunction.

source
MathOptInterface.ScalarCoefficientChangeType
ScalarCoefficientChange{T}(variable::VariableIndex, new_coefficient::T)

A struct used to request a change in the linear coefficient of a single variable in a scalar-valued function. Applicable to ScalarAffineFunction and ScalarQuadraticFunction.

source
MathOptInterface.MultirowChangeType
MultirowChange{T}(variable::VariableIndex, new_coefficients::Vector{Tuple{Int64, T}})

A struct used to request a change in the linear coefficients of a single variable in a vector-valued function. New coefficients are specified by (output_index, coefficient) tuples. Applicable to VectorAffineFunction and VectorQuadraticFunction.

source

Nonlinear programming (NLP)

Attributes

MathOptInterface.NLPBlockType
NLPBlock()

Holds the NLPBlockData that represents a set of nonlinear constraints, and optionally a nonlinear objective.

source
MathOptInterface.NLPBoundsPairType
NLPBoundsPair(lower,upper)

A struct holding a pair of lower and upper bounds. -Inf and Inf can be used to indicate no lower or upper bound, respectively.

source
MathOptInterface.NLPBlockDataType
struct NLPBlockData
    constraint_bounds::Vector{NLPBoundsPair}
    evaluator::AbstractNLPEvaluator
    has_objective::Bool
end

A struct encoding a set of nonlinear constraints of the form $lb \le g(x) \le ub$ and, if has_objective == true, a nonlinear objective function $f(x)$. constraint_bounds holds the pairs of $lb$ and $ub$ elements. Nonlinear objectives override any objective set by using the ObjectiveFunction attribute. The evaluator is a callback object that is used to query function values, derivatives, and expression graphs. If has_objective == false, then it is an error to query properties of the objective function, and in Hessian-of-the-Lagrangian queries, σ must be set to zero. Throughout the evaluator, all variables are ordered according to ListOfVariableIndices().

source
MathOptInterface.NLPBlockDualType
NLPBlockDual(N)
NLPBlockDual()

The Lagrange multipliers on the constraints from the NLPBlock in result N. If N is omitted, it is 1 by default.

source
MathOptInterface.NLPBlockDualStartType
NLPBlockDualStart()

An initial assignment of the Lagrange multipliers on the constraints from the NLPBlock that the solver may use to warm-start the solve.

source

NLP evaluator methods

MathOptInterface.initializeFunction
initialize(d::AbstractNLPEvaluator, requested_features::Vector{Symbol})

Must be called before any other methods. The vector requested_features lists features requested by the solver. These may include :Grad for gradients of $f$, :Jac for explicit Jacobians of $g$, :JacVec for Jacobian-vector products, :HessVec for Hessian-vector and Hessian-of-Lagrangian-vector products, :Hess for explicit Hessians and Hessian-of-Lagrangians, and :ExprGraph for expression graphs.

source
MathOptInterface.features_availableFunction
features_available(d::AbstractNLPEvaluator)

Returns the subset of features available for this problem instance, as a list of symbols in the same format as in initialize.

source
MathOptInterface.eval_constraintFunction
eval_constraint(d::AbstractNLPEvaluator, g, x)

Evaluate the constraint function $g(x)$, storing the result in the vector g which must be of the appropriate size.

source
MathOptInterface.jacobian_structureFunction
jacobian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}

Returns the sparsity structure of the Jacobian matrix $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right]$ where $g_i$ is the $i\text{th}$ component of $g$. The sparsity structure is assumed to be independent of the point $x$. Returns a vector of tuples, (row, column), where each indicates the position of a structurally nonzero element. These indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together.

source
MathOptInterface.hessian_lagrangian_structureFunction
hessian_lagrangian_structure(d::AbstractNLPEvaluator)::Vector{Tuple{Int64,Int64}}

Returns the sparsity structure of the Hessian-of-the-Lagrangian matrix $\nabla^2 f + \sum_{i=1}^m \nabla^2 g_i$ as a vector of tuples, where each indicates the position of a structurally nonzero element. These indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together. Any mix of lower and upper-triangular indices is valid. Elements (i,j) and (j,i), if both present, should be treated as duplicates.

source
MathOptInterface.eval_constraint_jacobianFunction
eval_constraint_jacobian(d::AbstractNLPEvaluator, J, x)

Evaluates the sparse Jacobian matrix $J_g(x) = \left[ \begin{array}{c} \nabla g_1(x) \\ \nabla g_2(x) \\ \vdots \\ \nabla g_m(x) \end{array}\right]$. The result is stored in the vector J in the same order as the indices returned by jacobian_structure.

source
MathOptInterface.eval_hessian_lagrangianFunction
eval_hessian_lagrangian(d::AbstractNLPEvaluator, H, x, σ, μ)

Given scalar weight σ and vector of constraint weights μ, computes the sparse Hessian-of-the-Lagrangian matrix $\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)$, storing the result in the vector H in the same order as the indices returned by hessian_lagrangian_structure.

source
MathOptInterface.eval_hessian_lagrangian_productFunction
eval_hessian_lagrangian_product(d::AbstractNLPEvaluator, h, x, v, σ, μ)

Given scalar weight σ and vector of constraint weights μ, computes the Hessian-of-the-Lagrangian-vector product $\left(\sigma\nabla^2 f(x) + \sum_{i=1}^m \mu_i \nabla^2 g_i(x)\right)v$, storing the result in the vector h.

source
MathOptInterface.objective_exprFunction
objective_expr(d::AbstractNLPEvaluator)

Returns an expression graph for the objective function as a standard Julia Expr object. All sums and products are flattened out as simple Expr(:+,...) and Expr(:*,...) objects. The symbol x is used as a placeholder for the vector of decision variables. No other undefined symbols are permitted; coefficients are embedded as explicit values. For example, the expression $x_1+\sin(x_2/\exp(x_3))$ would be represented as the Julia object :(x[1] + sin(x[2]/exp(x[3]))). Each integer index is wrapped in a VariableIndex. See the Julia manual for more information on the structure of Expr objects. There are currently no restrictions on recognized functions; typically these will be built-in Julia functions like ^, exp, log, cos, tan, sqrt, etc., but modeling interfaces may choose to extend these basic functions.

source
MathOptInterface.constraint_exprFunction
constraint_expr(d::AbstractNLPEvaluator, i)

Returns an expression graph for the $i\text{th}$ constraint in the same format as described above, with an additional comparison operator indicating the sense of and bounds on the constraint. The right-hand side of the comparison must be a constant; that is, :(x[1]^3 <= 1) is allowed, while :(1 <= x[1]^3) is not valid. Double-sided constraints are allowed, in which case both the lower bound and upper bounds should be constants; for example, :(-1 <= cos(x[1]) + sin(x[2]) <= 1) is valid.

source

Errors

When an MOI call fails on a model, precise errors should be thrown when possible instead of simply calling error with a message. The docstrings for the respective methods describe the errors that the implementation should thrown in certain situations. This error-reporting system allows code to distinguish between internal errors (that should be shown to the user) and unsupported operations which may have automatic workarounds.

When an invalid index is used in an MOI call, an InvalidIndex should be thrown:

As discussed in JuMP mapping, for scalar constraint with a nonzero function constant, a ScalarFunctionConstantNotZero exception may be thrown:

Some SingleVariable constraints cannot be combined on the same variable:

As discussed in AbstractCallback, trying to get attributes inside a callback may throw:

MathOptInterface.OptimizeInProgressType
struct OptimizeInProgress{AttrType<:AnyAttribute} <: Exception
    attr::AttrType
end

Error thrown from optimizer when MOI.get(optimizer, attr) is called inside an AbstractCallback while it is only defined once optimize! has completed. This can only happen when is_set_by_optimize(attr) is true.

source

Trying to submit the wrong type of AbstractSubmittable inside an AbstractCallback (e.g., a UserCut inside a LazyConstraintCallback) will throw:

The rest of the errors defined in MOI fall in two categories represented by the following two abstract types:

MathOptInterface.NotAllowedErrorType
NotAllowedError <: Exception

Abstract type for error thrown when an operation is supported but cannot be applied in the current state of the model.

source

The different UnsupportedError and NotAllowedError are the following errors:

MathOptInterface.SetAttributeNotAllowedType
struct SetAttributeNotAllowed{AttrType} <: NotAllowedError
    attr::AttrType
    message::String # Human-friendly explanation why the attribute cannot be set
end

An error indicating that the attribute attr is supported (see supports) but cannot be set for some reason (see the error string).

source
MathOptInterface.AddVariableNotAllowedType
struct AddVariableNotAllowed <: NotAllowedError
    message::String # Human-friendly explanation why the attribute cannot be set
end

An error indicating that variables cannot be added to the model.

source
MathOptInterface.UnsupportedConstraintType
struct UnsupportedConstraint{F<:AbstractFunction, S<:AbstractSet} <: UnsupportedError
    message::String # Human-friendly explanation why the attribute cannot be set
end

An error indicating that constraints of type F-in-S are not supported by the model, i.e. that supports_constraint returns false.

source
MathOptInterface.AddConstraintNotAllowedType
struct AddConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet} <: NotAllowedError
    message::String # Human-friendly explanation why the attribute cannot be set
end

An error indicating that constraints of type F-in-S are supported (see supports_constraint) but cannot be added.

source
MathOptInterface.ModifyConstraintNotAllowedType
struct ModifyConstraintNotAllowed{F<:AbstractFunction, S<:AbstractSet,
                                  C<:AbstractFunctionModification} <: NotAllowedError
    constraint_index::ConstraintIndex{F, S}
    change::C
    message::String
end

An error indicating that the constraint modification change cannot be applied to the constraint of index ci.

source
MathOptInterface.ModifyObjectiveNotAllowedType
struct ModifyObjectiveNotAllowed{C<:AbstractFunctionModification} <: NotAllowedError
    change::C
    message::String
end

An error indicating that the objective modification change cannot be applied to the objective.

source
MathOptInterface.DeleteNotAllowedType
struct DeleteNotAllowed{IndexType <: Index} <: NotAllowedError
    index::IndexType
    message::String
end

An error indicating that the index index cannot be deleted.

source
MathOptInterface.SubmitNotAllowedType
struct SubmitNotAllowed{SubmitTyp<:AbstractSubmittable} <: NotAllowedError
    sub::SubmitType
    message::String # Human-friendly explanation why the attribute cannot be set
end

An error indicating that the submittable sub is supported (see supports) but cannot be added for some reason (see the error string).

source

Models

Utilities.Model provides an implementation of a ModelLike that efficiently supports all functions and sets defined within MOI. However, given the extensibility of MOI, this might not over all use cases.

Utilities.UniversalFallback is a layer that sits on top of any ModelLike and provides non-specialized (slower) fallbacks for constraints and attributes that the underlying ModeLike does not support.

For advanced use cases that need efficient support for functions and sets defined outside of MOI (but still known at compile time), we provide the Utilities.@model macro.

MathOptInterface.Utilities.ModelType

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

Examples

model = Model{Float64}()
x = add_variable(model)
source
MathOptInterface.Utilities.UniversalFallbackType
UniversalFallback

The UniversalFallback can be applied on a MathOptInterface.ModelLike model to create the model UniversalFallback(model) supporting any constaint 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, MathOptInterface.optimize! has not been implemented). In that case, optimizer bridges should be used instead.

source
MathOptInterface.Utilities.@modelMacro
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 containing scalar_sets scalar sets typed_scalar_sets typed scalar sets, vector_sets vector sets, typed_vector_sets typed vector sets, scalar_functions scalar functions, typed_scalar_functions typed scalar functions, vector_functions vector functions and typed_vector_functions typed vector functions. To give no set/function, write (), to give one set S, write (S,).

The function MathOptInterface.SingleVariable should not be given in scalar_functions. The model supports MathOptInterface.SingleVariable-in-F constraints where F is MathOptInterface.EqualTo, MathOptInterface.GreaterThan, MathOptInterface.LessThan, MathOptInterface.Interval, MathOptInterface.Integer, MathOptInterface.ZeroOne, MathOptInterface.Semicontinuous or MathOptInterface.Semiinteger. The sets supported with the MathOptInterface.SingleVariable cannot be controlled from the macro, use the UniversalFallback to support more sets.

This macro creates a model specialized for specific types of constraint, by defining specialized structures and methods. To create a model that, in addition to be optimized for specific constraints, also support arbitrary constraints and attributes, use UniversalFallback.

This implementation of the MOI model certifies that the constraint indices, in addition to being different between constraints F-in-S for the same types F and S, are also different between constraints for different types F and S. This means that for constraint indices ci1, ci2 of this model, ci1 == ci2 if and only if ci1.value == ci2.value. This fact can be used to use the the value of the index directly in a dictionary representing a mapping between constraint indices and something else.

If is_optimizer = true, the resulting struct is a subtype of of MOIU.AbstractOptimizer, which is a subtype of MathOptInterface.AbstractOptimizer, otherwise, it is a subtype of MOIU.AbstractModelLike, which is a subtype of MathOptInterface.ModelLike.

Examples

The model describing an linear program would be:

@model(LPModel,                                                   # Name of model
      (),                                                         # 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
    )

Let MOI denote MathOptInterface, MOIU denote MOI.Utilities and MOIU.ConstraintEntry{F, S} be defined as MOI.Tuple{MOI.ConstraintIndex{F, S}, F, S}. The macro would create the types:

struct LPModelScalarConstraints{T, F <: MOI.AbstractScalarFunction} <: MOIU.Constraints{F}
    equalto::Vector{MOIU.ConstraintEntry{F, MOI.EqualTo{T}}}
    greaterthan::Vector{MOIU.ConstraintEntry{F, MOI.GreaterThan{T}}}
    lessthan::Vector{MOIU.ConstraintEntry{F, MOI.LessThan{T}}}
    interval::Vector{MOIU.ConstraintEntry{F, MOI.Interval{T}}}
end
struct LPModelVectorConstraints{T, F <: MOI.AbstractVectorFunction} <: MOIU.Constraints{F}
    zeros::Vector{MOIU.ConstraintEntry{F, MOI.Zeros}}
    nonnegatives::Vector{MOIU.ConstraintEntry{F, MOI.Nonnegatives}}
    nonpositives::Vector{MOIU.ConstraintEntry{F, MOI.Nonpositives}}
end
mutable struct LPModel{T} <: MOIU.AbstractModel{T}
    name::String
    sense::MOI.OptimizationSense
    objective::Union{MOI.SingleVariable, MOI.ScalarAffineFunction{T}, MOI.ScalarQuadraticFunction{T}}
    num_variables_created::Int64
    # If nothing, no variable has been deleted so the indices of the
    # variables are VI.(1:num_variables_created)
    variable_indices::Union{Nothing, Set{MOI.VariableIndex}}
    # Union of flags of `S` such that a `SingleVariable`-in-`S`
    # constraint was added to the model and not deleted yet.
    single_variable_mask::Vector{UInt8}
    # Lower bound set by `SingleVariable`-in-`S` where `S`is
    # `GreaterThan{T}`, `EqualTo{T}` or `Interval{T}`.
    lower_bound::Vector{T}
    # Lower bound set by `SingleVariable`-in-`S` where `S`is
    # `LessThan{T}`, `EqualTo{T}` or `Interval{T}`.
    upper_bound::Vector{T}
    var_to_name::Dict{MOI.VariableIndex, String}
    # If `nothing`, the dictionary hasn't been constructed yet.
    name_to_var::Union{Dict{String, MOI.VariableIndex}, Nothing}
    nextconstraintid::Int64
    con_to_name::Dict{MOI.ConstraintIndex, String}
    name_to_con::Union{Dict{String, MOI.ConstraintIndex}, Nothing}
    constrmap::Vector{Int}
    scalaraffinefunction::LPModelScalarConstraints{T, MOI.ScalarAffineFunction{T}}
    vectorofvariables::LPModelVectorConstraints{T, MOI.VectorOfVariables}
    vectoraffinefunction::LPModelVectorConstraints{T, MOI.VectorAffineFunction{T}}
end

The type LPModel implements the MathOptInterface API except methods specific to solver models like optimize! or getattribute with VariablePrimal.

source

Bridges

Bridges can be used for automatic reformulation of constrained variables (i.e. variables added with add_constrained_variable/add_constrained_variables) or constraints into equivalent formulations using constrained variables and constraints of different types. There are two important concepts to distinguish:

MathOptInterface.Bridges.AbstractBridgeType
AbstractBridge

Represents a bridged constraint or variable in a MathOptInterface.Bridges.AbstractBridgeOptimizer. It contains the indices of the variables and constraints that it has created in the model. These can be obtained using MathOptInterface.NumberOfVariables, MathOptInterface.ListOfVariableIndices, MathOptInterface.NumberOfConstraints and MathOptInterface.ListOfConstraintIndices using MathOptInterface.get with the bridge in place of the MathOptInterface.ModelLike. Attributes of the bridged model such as MathOptInterface.ConstraintDual and MathOptInterface.ConstraintPrimal, can be obtained using MathOptInterface.get with the bridge in place of the constraint index. These calls are used by the MathOptInterface.Bridges.AbstractBridgeOptimizer to communicate with the bridge so they should be implemented by the bridge.

source
MathOptInterface.Bridges.AbstractBridgeOptimizerType
AbstractBridgeOptimizer

A bridge optimizer applies given constraint bridges to a given optimizer thus extending the types of supported constraints. The attributes of the inner optimizer are automatically transformed to make the bridges transparent, e.g. the variables and constraints created by the bridges are hidden.

By convention, the inner optimizer should be stored in a model field and the dictionary mapping constraint indices to bridges should be stored in a bridges field. If a bridge optimizer deviates from these conventions, it should implement the functions MOI.optimize! and bridge respectively.

source
MathOptInterface.Bridges.LazyBridgeOptimizerType
LazyBridgeOptimizer{OT<:MOI.ModelLike} <: AbstractBridgeOptimizer

The LazyBridgeOptimizer combines several bridges, which are added using the add_bridge function. Whenever a constraint is added, it only attempts to bridge it if it is not supported by the internal model (hence its name Lazy). When bridging a constraint, it selects the minimal number of bridges needed. For instance, a constraint F-in-S can be bridged into a constraint F1-in-S1 (supported by the internal model) using bridge 1 or bridged into a constraint F2-in-S2 (unsupported by the internal model) using bridge 2 which can then be bridged into a constraint F3-in-S3 (supported by the internal model) using bridge 3, it will choose bridge 1 as it allows to bridge F-in-S using only one bridge instead of two if it uses bridge 2 and 3.

source

Variable bridges

When variables are added, either free with add_variable/add_variables, or constrained with add_constrained_variable/add_constrained_variables, variable bridges allow to return bridged variables that do not correspond to variables of the underlying model. These variables are parametrized by variables of the underlying model and this parametrization can be obtained with Bridges.bridged_variable_function. Similarly, the variables of the underlying model that were created by the bridge can be expressed in terms of the bridged variables and this expression can be obtained with Bridges.unbridged_variable_function. For instance, consider a model bridged by the Bridges.Variable.VectorizeBridge:

model = MOI.Utilities.Model{Float64}()
bridged_model = MOI.Bridges.Variable.Vectorize{Float64}(model)
bridged_variable, bridged_constraint = MOI.add_constrained_variable(bridged_model, MOI.GreaterThan(1.0))

# output

(MOI.VariableIndex(-1), MOI.ConstraintIndex{MOI.SingleVariable,MOI.GreaterThan{Float64}}(-1))

The constrained variable in MOI.GreaterThan(1.0) returned is a bridged variable as its index in negative. In model, a constrained variable in MOI.Nonnegatives is created:

inner_variables = MOI.get(model, MOI.ListOfVariableIndices())

# output

1-element Array{MOI.VariableIndex,1}:
 MOI.VariableIndex(1)

In the functions used for adding constraints or setting the objective to bridged_model, bridged_variable is substituted for inner_variables[1] plus 1:

MOI.Bridges.bridged_variable_function(bridged_model, bridged_variable)

# output

MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(1))], 1.0)

When getting ConstraintFunction or ObjectiveFunction, inner_variables[1] is substituted for bridged_variable minus 1:

MOI.Bridges.unbridged_variable_function(bridged_model, inner_variables[1])

# output

MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(-1))], -1.0)
Note

A notable exception is with Bridges.Variable.ZerosBridge where no variable is created in the underlying model as the variables are simply transformed to zeros. When this bridge is used, it is not possible to recover functions with bridged variables from functions of the inner model. Consider for instance that we create two zero variables:

model = MOI.Utilities.Model{Float64}()
bridged_model = MOI.Bridges.Variable.Zeros{Float64}(model)
bridged_variables, bridged_constraint = MOI.add_constrained_variables(bridged_model, MOI.Zeros(2))

# output

(MOI.VariableIndex[VariableIndex(-1), VariableIndex(-2)], MOI.ConstraintIndex{MOI.VectorOfVariables,MOI.Zeros}(-1))

Consider the following functions in the variables of bridged_model:

func = MOI.Utilities.operate(+, Float64, MOI.SingleVariable.(bridged_variables)...)

# output

MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(-1)), ScalarAffineTerm{Float64}(1.0, VariableIndex(-2))], 0.0)

We can obtain the equivalent function in the variables of model as follows:

inner_func = MOI.Bridges.bridged_function(bridged_model, func)

# output

MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[], 0.0)

However, it's not possible to invert this operation. Indeed, since the bridged variables are substituted for zeros, we cannot deduce whether they were present in the initial function.

MOI.Bridges.unbridged_function(bridged_model, inner_func)

# output

ERROR: Cannot unbridge function because some variables are bridged by variable bridges that do not support reverse mapping, e.g., `ZerosBridge`.
Stacktrace:
 [1] error(::String, ::String, ::String) at ./error.jl:42
 [2] throw_if_cannot_unbridge at /home/blegat/.julia/dev/MathOptInterface/src/Bridges/Variable/map.jl:343 [inlined]
 [3] unbridged_function(::MOI.Bridges.Variable.SingleBridgeOptimizer{MOI.Bridges.Variable.ZerosBridge{Float64},MOI.Utilities.Model{Float64}}, ::MOI.ScalarAffineFunction{Float64}) at /home/blegat/.julia/dev/MOI/src/Bridges/bridge_optimizer.jl:920
 [4] top-level scope at none:0
MathOptInterface.Bridges.bridged_variable_functionFunction
bridged_variable_function(b::AbstractBridgeOptimizer,
                          vi::MOI.VariableIndex)

Return a MOI.AbstractScalarFunction of variables of b.model that equals vi. That is, if the variable vi is bridged, it returns its expression in terms of the variables of b.model. Otherwise, it returns MOI.SingleVariable(vi).

source
MathOptInterface.Bridges.unbridged_variable_functionFunction
unbridged_variable_function(b::AbstractBridgeOptimizer,
                            vi::MOI.VariableIndex)

Return a MOI.AbstractScalarFunction of variables of b that equals vi. That is, if the variable vi is an internal variable of b.model created by a but not visible to the user, it returns its expression in terms of the variables of bridged variables. Otherwise, it returns MOI.SingleVariable(vi).

source

Below is the list of variable bridges implemented in this package.

MathOptInterface.Bridges.Variable.ZerosBridgeType
ZerosBridge{T} <: Bridges.Variable.AbstractBridge

Transforms constrained variables in MathOptInterface.Zeros to zeros, which ends up creating no variables in the underlying model. The bridged variables are therefore similar to parameters with zero values. Parameters with non-zero value can be created with constrained variables in MOI.EqualTo by combining a VectorizeBridge and this bridge. The functions cannot be unbridged, given a function, we cannot determine, if the bridged variables were used. The dual values cannot be determined by the bridge but they can be determined by the bridged optimizer using MathOptInterface.Utilities.get_fallback if a CachingOptimizer is used (since ConstraintFunction cannot be got as functions cannot be unbridged).

source
MathOptInterface.Bridges.Variable.NonposToNonnegBridgeType
NonposToNonnegBridge{T, F<:MOI.AbstractVectorFunction, G<:MOI.AbstractVectorFunction} <:
    FlipSignBridge{T, MOI.Nonpositives, MOI.Nonnegatives, F, G}

Transforms constrained variables in Nonpositives into constrained variables in Nonnegatives.

source
MathOptInterface.Bridges.Variable.VectorizeBridgeType
VectorizeBridge{T, S}

Transforms a constrained variable in scalar_set_type(S, T) where S <: VectorLinearSet into a constrained vector of one variable in S. For instance, VectorizeBridge{Float64, MOI.Nonnegatives} transforms a constrained variable in MOI.GreaterThan{Float64} into a constrained vector of one variable in MOI.Nonnegatives.

source

For each bridge defined in this package, a corresponding Bridges.Variable.SingleBridgeOptimizer is available with the same name without the "Bridge" suffix, e.g., SplitInterval is a SingleBridgeOptimizer for the SplitIntervalBridge. Moreover, they are all added in the Bridges.LazyBridgeOptimizer returned by Bridges.full_bridge_optimizer as it calls Bridges.Variable.add_all_bridges.

MathOptInterface.Bridges.Variable.SingleBridgeOptimizerType
SingleBridgeOptimizer{BT<:AbstractBridge, OT<:MOI.ModelLike} <: AbstractBridgeOptimizer

The SingleBridgeOptimizer bridges any constrained variables supported by the bridge BT. This is in contrast with the MathOptInterface.Bridges.LazyBridgeOptimizer which only bridges the constrained variables that are unsupported by the internal model, even if they are supported by one of its bridges.

Note

Two bridge optimizers using variable bridges cannot be used together as both of them assume that the underlying model only returns variable indices with nonnegative values.

source

Constraint bridges

When constraints are added with add_constraint, constraint bridges allow to return bridged constraints that do not correspond to constraints of the underlying model. These constraints were enforced by an equivalent formulation that added constraints (and possibly also variables) in the underlying model. For instance, consider a model bridged by the Bridges.Constraint.SplitIntervalBridge:

model = MOI.Utilities.Model{Float64}()
bridged_model = MOI.Bridges.Constraint.SplitInterval{Float64}(model)
x, y = MOI.add_variables(bridged_model, 2)
func = MOI.Utilities.operate(+, Float64, MOI.SingleVariable(x), MOI.SingleVariable(y))
c = MOI.add_constraint(bridged_model, func, MOI.Interval(1.0, 2.0))

# output

MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},MOI.Interval{Float64}}(1)

We can see the constraint was bridged to two constraints, one for each bound, in the inner model.

MOI.get(model, MOI.ListOfConstraints())

# output

2-element Array{Tuple{DataType,DataType},1}:
 (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64})
 (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64})

However, bridged_model transparently hides these constraints and creates the illusion that an interval constraint was created.

MOI.get(bridged_model, MOI.ListOfConstraints())

# output

1-element Array{Tuple{DataType,DataType},1}:
 (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64})

It is nevertheless possible to differentiate this constraint from a constraint added to the inner model by asking whether it is bridged:

MOI.Bridges.is_bridged(bridged_model, c)

# output

true

Below is the list of constraint bridges implemented in this package.

MathOptInterface.Bridges.Constraint.ScalarSlackBridgeType
ScalarSlackBridge{T, F, S}

The ScalarSlackBridge converts a constraint G-in-S where G is a function different from SingleVariable into the constraints F-in-EqualTo{T} and SingleVariable-in-S. F is the result of subtracting a SingleVariable from G. Tipically G is the same as F, but that is not mandatory.

source
MathOptInterface.Bridges.Constraint.VectorSlackBridgeType
VectorSlackBridge{T, F, S}

The VectorSlackBridge converts a constraint G-in-S where G is a function different from VectorOfVariables into the constraints Fin-Zeros and VectorOfVariables-in-S. F is the result of subtracting a VectorOfVariables from G. Tipically G is the same as F, but that is not mandatory.

source
MathOptInterface.Bridges.Constraint.SplitIntervalBridgeType
SplitIntervalBridge{T, F, S, LS, US}

The SplitIntervalBridge splits a F-in-S constraint into a F-in-LS and a F-in-US constraint where we have either:

  • F = MOI.Interval{T}, LS = MOI.GreaterThan{T} and US = MOI.LessThan{T},
  • F = MOI.EqualTo{T}, LS = MOI.GreaterThan{T} and US = MOI.LessThan{T}, or
  • F = MOI.Zeros, LS = MOI.Nonnegatives and US = MOI.Nonpositives.

For instance, if F is MOI.ScalarAffineFunction and S is MOI.Interval, it transforms the constraint $l ≤ ⟨a, x⟩ + α ≤ u$ into the constraints $⟨a, x⟩ + α ≥ l$ and $⟨a, x⟩ + α ≤ u$.

source
MathOptInterface.Bridges.Constraint.RSOCBridgeType
RSOCBridge{T, F, G}

The RotatedSecondOrderCone is SecondOrderCone representable; see [1, p. 104]. Indeed, we have $2tu = (t/√2 + u/√2)^2 - (t/√2 - u/√2)^2$ hence

\[2tu \ge || x ||_2^2\]

is equivalent to

\[(t/√2 + u/√2)^2 \ge || x ||_2^2 + (t/√2 - u/√2)^2.\]

We can therefore use the transformation $(t, u, x) \mapsto (t/√2+u/√2, t/√2-u/√2, x)$. Note that the linear transformation is a symmetric involution (i.e. it is its own transpose and its own inverse). That means in particular that the norm is of constraint primal and duals are preserved by the tranformation.

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.QuadtoSOCBridgeType
QuadtoSOCBridge{T}

The set of points x satisfying the constraint

\[\frac{1}{2}x^T Q x + a^T x + b \le 0\]

is a convex set if Q is positive semidefinite and is the union of two convex cones if a and b are zero (i.e. homogeneous case) and Q has only one negative eigenvalue. Currently, only the non-homogeneous transformation is implemented, see the Note section below for more details.

Non-homogeneous case

If Q is positive semidefinite, there exists U such that $Q = U^T U$, the inequality can then be rewritten as

\[\|U x\|_2^2 \le 2 (-a^T x - b)\]

which is equivalent to the membership of (1, -a^T x - b, Ux) to the rotated second-order cone.

Homogeneous case

If Q has only one negative eigenvalue, the set of x such that $x^T Q x \le 0$ is the union of a convex cone and its opposite. We can choose which one to model by checking the existence of bounds on variables as shown below.

Second-order cone

If Q is diagonal and has eigenvalues (1, 1, -1), the inequality $x^2 + x^2 \le z^2$ combined with $z \ge 0$ defines the Lorenz cone (i.e. the second-order cone) but when combined with $z \le 0$, it gives the opposite of the second order cone. Therefore, we need to check if the variable z has a lower bound 0 or an upper bound 0 in order to determine which cone is

Rotated second-order cone

The matrix Q corresponding to the inequality $x^2 \le 2yz$ has one eigenvalue 1 with eigenvectors (1, 0, 0) and (0, 1, -1) and one eigenvalue -1 corresponding to the eigenvector (0, 1, 1). Hence if we intersect this union of two convex cone with the halfspace $x + y \ge 0$, we get the rotated second-order cone and if we intersect it with the halfspace $x + y \le 0$ we get the opposite of the rotated second-order cone. Note that y and z have the same sign since yz is nonnegative hence $x + y \ge 0$ is equivalent to $x \ge 0$ and $y \ge 0$.

Note

The check for existence of bound can be implemented (but inefficiently) with the current interface but if bound is removed or transformed (e.g. ≤ 0 transformed into ≥ 0) then the bridge is no longer valid. For this reason the homogeneous version of the bridge is not implemented yet.

source
MathOptInterface.Bridges.Constraint.NormOneBridgeType
NormOneBridge{T}

The NormOneCone is representable with LP constraints, since $t \ge \sum_i \lvert x_i \rvert$ if and only if there exists a vector y such that $t \ge \sum_i y_i$ and $y_i \ge x_i$, $y_i \ge -x_i$ for all $i$.

source
MathOptInterface.Bridges.Constraint.GeoMeanBridgeType
GeoMeanBridge{T, F, G, H}

The GeometricMeanCone is SecondOrderCone representable; see [1, p. 105]. The reformulation is best described in an example. Consider the cone of dimension 4

\[t \le \sqrt[3]{x_1 x_2 x_3}\]

This can be rewritten as $\exists x_{21} \ge 0$ such that

\[\begin{align*} t & \le x_{21},\\ x_{21}^4 & \le x_1 x_2 x_3 x_{21}. \end{align*}\]

Note that we need to create $x_{21}$ and not use $t^4$ directly as $t$ is allowed to be negative. Now, this is equivalent to

\[\begin{align*} t & \le x_{21}/\sqrt{4},\\ x_{21}^2 & \le 2x_{11} x_{12},\\ x_{11}^2 & \le 2x_1 x_2, & x_{12}^2 & \le 2x_3(x_{21}/\sqrt{4}). \end{align*}\]

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.RelativeEntropyBridgeType
RelativeEntropyBridge{T}

The RelativeEntropyCone is representable with exponential cone and LP constraints, since $u \ge \sum_{i=1}^n w_i \log (\frac{w_i}{v_i})$ if and only if there exists a vector $y$ such that $u \ge \sum_i y_i$ and $y_i \ge w_i \log (\frac{w_i}{v_i})$ or equivalently $v_i \ge w_i \exp (\frac{-y_i}{w_i})$ or equivalently $(-y_i, w_i, v_i) \in ExponentialCone$, for all $i$.

source
MathOptInterface.Bridges.Constraint.NormNuclearBridgeType
NormNuclearBridge{T}

The NormNuclearCone is representable with an SDP constraint and extra variables, since $t \ge \sum_i \sigma_i (X)$ if and only if there exists symmetric matrices $U, V$ such that $[U X^\top; X V] \succ 0$ and $t \ge (tr(U) + tr(V)) / 2$.

source
MathOptInterface.Bridges.Constraint.SquareBridgeType
SquareBridge{T, F<:MOI.AbstractVectorFunction,
             G<:MOI.AbstractScalarFunction,
             TT<:MOI.AbstractSymmetricMatrixSetTriangle,
             ST<:MOI.AbstractSymmetricMatrixSetSquare} <: AbstractBridge

The SquareBridge reformulates the constraint of a square matrix to be in ST to a list of equality constraints for pair or off-diagonal entries with different expressions and a TT constraint the upper triangular part of the matrix.

For instance, the constraint for the matrix

\[\begin{pmatrix} 1 & 1 + x & 2 - 3x\\ 1 + x & 2 + x & 3 - x\\ 2 - 3x & 2 + x & 2x \end{pmatrix}\]

to be PSD can be broken down to the constraint of the symmetric matrix

\[\begin{pmatrix} 1 & 1 + x & 2 - 3x\\ \cdot & 2 + x & 3 - x\\ \cdot & \cdot & 2x \end{pmatrix}\]

and the equality constraint between the off-diagonal entries (2, 3) and (3, 2) $2x == 1$. Note that now symmetrization constraint need to be added between the off-diagonal entries (1, 2) and (2, 1) or between (1, 3) and (3, 1) since the expressions are the same.

source
MathOptInterface.Bridges.Constraint.RootDetBridgeType
RootDetBridge{T}

The RootDetConeTriangle is representable by a PositiveSemidefiniteConeTriangle and an GeometricMeanCone constraints; see [1, p. 149]. Indeed, $t \le \det(X)^{1/n}$ if and only if there exists a lower triangular matrix $Δ$ such that

\[\begin{align*} \begin{pmatrix} X & Δ\\ Δ^\top & \mathrm{Diag}(Δ) \end{pmatrix} & \succeq 0\\ t & \le (Δ_{11} Δ_{22} \cdots Δ_{nn})^{1/n} \end{align*}\]

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001.

source
MathOptInterface.Bridges.Constraint.LogDetBridgeType
LogDetBridge{T}

The LogDetConeTriangle is representable by a PositiveSemidefiniteConeTriangle and ExponentialCone constraints. Indeed, $\log\det(X) = \log(\delta_1) + \cdots + \log(\delta_n)$ where $\delta_1$, ..., $\delta_n$ are the eigenvalues of $X$. Adapting the method from [1, p. 149], we see that $t \le u \log(\det(X/u))$ for $u > 0$ if and only if there exists a lower triangular matrix $Δ$ such that

\[\begin{align*} \begin{pmatrix} X & Δ\\ Δ^\top & \mathrm{Diag}(Δ) \end{pmatrix} & \succeq 0\\ t & \le u \log(Δ_{11}/u) + u \log(Δ_{22}/u) + \cdots + u \log(Δ_{nn}/u) \end{align*}\]

[1] Ben-Tal, Aharon, and Arkadi Nemirovski. Lectures on modern convex optimization: analysis, algorithms, and engineering applications. Society for Industrial and Applied Mathematics, 2001. ```

source
MathOptInterface.Bridges.Constraint.SOCtoPSDBridgeType

The SOCtoPSDBridge transforms the second order cone constraint $\lVert x \rVert \le t$ into the semidefinite cone constraints

\[\begin{pmatrix} t & x^\top\\ x & tI \end{pmatrix} \succeq 0\]

Indeed by the Schur Complement, it is positive definite iff

\[\begin{align*} tI & \succ 0\\ t - x^\top (tI)^{-1} x & \succ 0 \end{align*}\]

which is equivalent to

\[\begin{align*} t & > 0\\ t^2 & > x^\top x \end{align*}\]

This bridge is not added by default by MOI.Bridges.full_bridge_optimizer as bridging second order cone constraints to semidefinite constraints can be achieved by the SOCRBridge followed by the RSOCtoPSDBridge while creating a smaller semidefinite constraint.

source
MathOptInterface.Bridges.Constraint.RSOCtoPSDBridgeType

The RSOCtoPSDBridge transforms the second order cone constraint $\lVert x \rVert \le 2tu$ with $u \ge 0$ into the semidefinite cone constraints

\[\begin{pmatrix} t & x^\top\\ x & 2uI \end{pmatrix} \succeq 0\]

Indeed by the Schur Complement, it is positive definite iff

\[\begin{align*} uI & \succ 0\\ t - x^\top (2uI)^{-1} x & \succ 0 \end{align*}\]

which is equivalent to

\[\begin{align*} u & > 0\\ 2tu & > x^\top x \end{align*}\]
source
MathOptInterface.Bridges.Constraint.IndicatorActiveOnFalseBridgeType
IndicatorActiveOnFalseBridge{T}

The IndicatorActiveOnFalseBridge replaces an indicator constraint activated on 0 with a variable $z_0$ with the constraint activated on 1, with a variable $z_1$. It stores the added variable_index and added constraints:

  • $z_1 \in \mathbb{B}$ in zero_one_cons
  • $z_0 + z_1 == 1$ in `indisjunction_cons`
  • The added ACTIVATE_ON_ONE indicator constraint in indicator_cons_index.
source

For each bridge defined in this package, a corresponding Bridges.Constraint.SingleBridgeOptimizer is available with the same name without the "Bridge" suffix, e.g., SplitInterval is a SingleBridgeOptimizer for the SplitIntervalBridge. Moreover, they are all added in the Bridges.LazyBridgeOptimizer returned by Bridges.full_bridge_optimizer as it calls Bridges.Constraint.add_all_bridges.

Objective bridges

When an objective is set with set, objective bridges allow to set a bridged objective to the underlying model that do not correspond to the objective set by the user. This equivalent formulation may add constraints (and possibly also variables) in the underlying model in addition to setting an objective function.

Below is the list of objective bridges implemented in this package.

MathOptInterface.Bridges.Objective.SlackBridgeType
SlackBridge{T, F, G}

The SlackBridge converts an objective function of type G into a MOI.SingleVariable objective by creating a slack variable and a F-in-MOI.LessThan constraint for minimization or F-in-MOI.LessThan constraint for maximization where F is MOI.Utilities.promote_operation(-, T, G, MOI.SingleVariable}. Note that when using this bridge, changing the optimization sense is not supported. Set the sense to MOI.FEASIBILITY_SENSE first to delete the bridge in order to change the sense, then re-add the objective.

source

For each bridge defined in this package, a corresponding Bridges.Objective.SingleBridgeOptimizer is available with the same name without the "Bridge" suffix, e.g., Slack is a SingleBridgeOptimizer for the SlackBridge. Moreover, they are all added in the Bridges.LazyBridgeOptimizer returned by Bridges.full_bridge_optimizer as it calls Bridges.Objective.add_all_bridges.

Bridge interface

A bridge should implement the following functions to be usable by a bridge optimizer:

Additionally, variable bridges should implement:

MathOptInterface.Bridges.Variable.concrete_bridge_typeFunction
concrete_bridge_type(BT::Type{<:AbstractBridge},
                     S::Type{<:MOI.AbstractSet})::DataType

Return the concrete type of the bridge supporting variables in S constraints. This function can only be called if MOI.supports_constrained_variable(BT, S) is true.

Examples

As a variable in MathOptInterface.GreaterThan is bridged into variables in MathOptInterface.Nonnegatives by the VectorizeBridge,

BT = MOI.Bridges.Variable.VectorizeBridge{Float64}
S = MOI.GreaterThan{Float64}
MOI.Bridges.Variable.concrete_bridge_type(BT, S)

# output

MOI.Bridges.Variable.VectorizeBridge{Float64,MOI.Nonnegatives}
source
MathOptInterface.Bridges.Variable.bridge_constrained_variableFunction
bridge_constrained_variable(BT::Type{<:AbstractBridge}, model::MOI.ModelLike,
                            set::MOI.AbstractSet)

Bridge the constrained variable in set using bridge BT to model and returns a bridge object of type BT. The bridge type BT should be a concrete type, that is, all the type parameters of the bridge should be set. Use concrete_bridge_type to obtain a concrete type for given set types.

source

constraint bridges should implement:

MathOptInterface.supports_constraintMethod
MOI.supports_constraint(BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet})::Bool

Return a Bool indicating whether the bridges of type BT support bridging F-in-S constraints.

source
MathOptInterface.Bridges.Constraint.concrete_bridge_typeFunction
concrete_bridge_type(BT::Type{<:AbstractBridge},
                     F::Type{<:MOI.AbstractFunction},
                     S::Type{<:MOI.AbstractSet})::DataType

Return the concrete type of the bridge supporting F-in-S constraints. This function can only be called if MOI.supports_constraint(BT, F, S) is true.

Examples

As a MathOptInterface.SingleVariable-in-MathOptInterface.Interval constraint is bridged into a MathOptInterface.SingleVariable-in-MathOptInterface.GreaterThan and a MathOptInterface.SingleVariable-in-MathOptInterface.LessThan by the SplitIntervalBridge,

BT = MOI.Bridges.Constraint.SplitIntervalBridge{Float64}
F = MOI.SingleVariable
S = MOI.Interval{Float64}
MOI.Bridges.Constraint.concrete_bridge_type(BT, F, S)

# output

MOI.Bridges.Constraint.SplitIntervalBridge{Float64,MOI.SingleVariable}
source
MathOptInterface.Bridges.Constraint.bridge_constraintFunction
bridge_constraint(BT::Type{<:AbstractBridge}, model::MOI.ModelLike,
                  func::AbstractFunction, set::MOI.AbstractSet)

Bridge the constraint func-in-set using bridge BT to model and returns a bridge object of type BT. The bridge type BT should be a concrete type, that is, all the type parameters of the bridge should be set. Use concrete_bridge_type to obtain a concrete type for given function and set types.

source

and objective bridges should implement:

MathOptInterface.Bridges.Objective.concrete_bridge_typeFunction
concrete_bridge_type(BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
                     F::Type{<:MOI.AbstractScalarFunction})::DataType

Return the concrete type of the bridge supporting objective functions of type F. This function can only be called if MOI.supports_objective_function(BT, F) is true.

source
MathOptInterface.Bridges.Objective.bridge_objectiveFunction
bridge_objective(BT::Type{<:MOI.Bridges.Objective.AbstractBridge},
                 model::MOI.ModelLike,
                 func::MOI.AbstractScalarFunction)

Bridge the objective function func using bridge BT to model and returns a bridge object of type BT. The bridge type BT should be a concrete type, that is, all the type parameters of the bridge should be set. Use concrete_bridge_type to obtain a concrete type for a given function type.

source

When querying the NumberOfVariables, NumberOfConstraints and ListOfConstraintIndices, the variables and constraints created by the bridges in the underlying model are hidden by the bridge optimizer. For this purpose, the bridge should provide access to the variables and constraints it has creates by implemented the following methods of get:

MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)

The number of variables created by the bridge b in the model.

source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfVariables)

The list of variables created by the bridge b in the model.

source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.NumberOfConstraints{F, S}) where {F, S}

The number of constraints of the type F-in-S created by the bridge b in the model.

source
MathOptInterface.getMethod
MOI.get(b::AbstractBridge, ::MOI.ListOfConstraintIndices{F, S}) where {F, S}

A Vector{ConstraintIndex{F,S}} with indices of all constraints of type F-inS created by the bride b in the model (i.e., of length equal to the value of NumberOfConstraints{F,S}()).

source

Copy utilities

The following utilities can be used to implement copy_to. See Implementing copy for more details.

MathOptInterface.Utilities.default_copy_toFunction
default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike, copy_names::Bool)

Implements MOI.copy_to(dest, src) by adding the variables and then the constraints and attributes incrementally. The function supports_default_copy_to can be used to check whether dest supports the copying a model incrementally.

source
MathOptInterface.Utilities.supports_default_copy_toFunction
supports_default_copy_to(model::ModelLike, copy_names::Bool)

Return a Bool indicating whether the model model supports default_copy_to(model, src, copy_names=copy_names) if all the attributes set to src and constraints added to src are supported by model.

This function can be used to determine whether a model can be loaded into model incrementally or whether it should be cached and copied at once instead. This is used by JuMP to determine whether to add a cache or not in two situations:

  1. A first cache can be used to store the model as entered by the user as well as the names of variables and constraints. This cache is created if this function returns false when copy_names is true.
  2. If bridges are used, then a second cache can be used to store the bridged model with unnamed variables and constraints. This cache is created if this function returns false when copy_names is false.

Examples

If MathOptInterface.set, MathOptInterface.add_variable and MathOptInterface.add_constraint are implemented for a model of type MyModel and names are supported, then MathOptInterface.copy_to can be implemented as

MOI.Utilities.supports_default_copy_to(model::MyModel, copy_names::Bool) = true
function MOI.copy_to(dest::MyModel, src::MOI.ModelLike; kws...)
    return MOI.Utilities.automatic_copy_to(dest, src; kws...)
end

The Utilities.automatic_copy_to function automatically redirects to Utilities.default_copy_to.

If names are not supported, simply change the first line by

MOI.supports_default_copy_to(model::MyModel, copy_names::Bool) = !copy_names

The Utilities.default_copy_to function automatically throws an helpful error in case copy_to is called with copy_names equal to true.

source

Allocate-Load API

The Allocate-Load API allows solvers that do not support loading the problem incrementally to implement copy_to in a way that still allows transformations to be applied in the copy between the cache and the model if the transformations are implemented as MOI layers implementing the Allocate-Load API, see Implementing copy for more details.

Loading a model using the Allocate-Load interface consists of two passes through the model data:

  1. the allocate pass where the model typically records the necessary information about the constraints and attributes such as their number and size. This information may be used by the solver to allocate datastructures of appropriate size.
  2. the load pass where the model typically loads the constraint and attribute data to the model.

The description above only gives a suggestion of what to achieve in each pass. In fact the exact same constraint and attribute data is provided to each pass, so an implementation of the Allocate-Load API is free to do whatever is more convenient in each pass.

The main difference between each pass, apart from the fact that one is executed before the other during a copy, is that the allocate pass needs to create and return new variable and constraint indices, while during the load pass the appropriate constraint indices are provided.

The Allocate-Load API is not meant to be used outside a copy operation, that is, the interface is not meant to be used to create new constraints with Utilities.allocate_constraint followed by Utilities.load_constraint after a solve. This means that the order in which the different functions of the API are called is fixed by Utilities.allocate_load and models implementing the API can rely on the fact that functions will be called in this order. That is, it can be assumed that the different functions will the called in the following order:

  1. Utilities.allocate_variables
  2. Utilities.allocate and Utilities.allocate_constraint
  3. Utilities.load_variables
  4. Utilities.load and Utilities.load_constraint
MathOptInterface.Utilities.allocateFunction
allocate(model::ModelLike, attr::ModelLikeAttribute, value)
allocate(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)
allocate(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex, value)

Informs model that load will be called with the same arguments after load_variables is called.

source
MathOptInterface.Utilities.allocate_constraintFunction
allocate_constraint(model::MOI.ModelLike, f::MOI.AbstractFunction, s::MOI.AbstractSet)

Returns the index for the constraint to be used in load_constraint that will be called after load_variables is called.

source
MathOptInterface.Utilities.loadFunction
load(model::ModelLike, attr::ModelLikeAttribute, value)
load(model::ModelLike, attr::AbstractVariableAttribute, v::VariableIndex, value)
load(model::ModelLike, attr::AbstractConstraintAttribute, c::ConstraintIndex, value)

This has the same effect that set with the same arguments except that allocate should be called first before load_variables.

source

Caching optimizer

Some solvers do not support incremental definition of optimization models. Nevertheless, you are still able to build incrementally an optimization model with such solvers. MathOptInterface provides a utility, Utilities.CachingOptimizer, that will store in a ModelLike the optimization model during its incremental definition. Once the model is completely defined, the CachingOptimizer specifies all problem information to the underlying solver, all at once.

The function Utilities.state allows to query the state of the optimizer cached inside a CachingOptimizer. The state could be:

  • NO_OPTIMIZER, if no optimizer is attached;
  • EMPTY_OPTIMIZER, if the attached optimizer is empty;
  • ATTACHED_OPTIMIZER, if the attached optimizer is synchronized with the cached model defined in CachingOptimizer.

The following methods modify the state of the attached optimizer:

  • Utilities.attach_optimizer attachs a new optimizer to a cached_optimizer with state EMPTY_OPTIMIZER. The state of cached_optimizer is set to ATTACHED_OPTIMIZER after the call.
  • Utilities.drop_optimizer drops the underlying optimizer from cached_optimizer, without emptying it. The state of cached_optimizer is set to NO_OPTIMIZER after the call.
  • Utilities.reset_optimizer empties optimizer inside cached_optimizer, without droping it. The state of cached_optimizer is set to EMPTY_OPTIMIZER after the call.

The way to operate a CachingOptimizer depends whether the mode is set to AUTOMATIC or to MANUAL.

  • In MANUAL mode, the state of the CachingOptimizer changes only if the methods Utilities.attach_optimizer, Utilities.reset_optimizer or Utilities.drop_optimizer are being called. Any unattended operation results in an error.
  • In AUTOMATIC mode, the state of the CachingOptimizer changes when necessary. Any modification not supported by the solver (e.g. dropping a constraint) results in a drop to the state EMPTY_OPTIMIZER.

When calling Utilities.attach_optimizer, the CachingOptimizer copies the cached model to the optimizer with copy_to. We refer to Implementing copy for more details.

MathOptInterface.Utilities.CachingOptimizerType
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.

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.

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.
source
MathOptInterface.Utilities.attach_optimizerFunction
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 MathOptInterface.copy_to for more details on which errors can be thrown.

source
MathOptInterface.Utilities.reset_optimizerFunction
reset_optimizer(m::CachingOptimizer, optimizer::MOI.AbstractOptimizer)

Sets or resets m to have the given empty optimizer. Can be called from any state. The CachingOptimizer will be in state EMPTY_OPTIMIZER after the call.

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

source

Function utilities

The following utilities are available for functions:

MathOptInterface.Utilities.substitute_variablesFunction
substitute_variables(variable_map::Function, x)

Substitute any MOI.VariableIndex in x by variable_map(x). The variable_map function returns either MOI.SingleVariable 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.

source
MathOptInterface.Utilities.remove_variableFunction
remove_variable(f::AbstractFunction, vi::VariableIndex)

Return a new function f with the variable vi removed.

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

source
MathOptInterface.Utilities.all_coefficientsFunction
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.

source
MathOptInterface.Utilities.unsafe_addFunction
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_index of t1 as the variable_index of the output without checking that it is equal to that of t2.

source
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_index's of t1 as the variable_index's of the output without checking that they are the same (up to permutation) to those of t2.

source
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_index of t1 as the output_index and variable_index of the output term without checking that they are equal to those of t2.

source
MathOptInterface.Utilities.isapprox_zeroFunction
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.

source

The following functions can be used to canonicalize a function:

MathOptInterface.Utilities.canonicalFunction
canonical(f::Union{ScalarAffineFunction, VectorAffineFunction,
                   ScalarQuadraticFunction, VectorQuadraticFunction})

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.

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

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

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

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

source

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

MathOptInterface.Utilities.promote_operationFunction
promote_operation(op::Function, ::Type{T},
                  ArgsTypes::Type{<:Union{T, MOI.AbstractFunction}}...) where T

Returns the type of the MOI.AbstractFunction returned to the call operate(op, T, args...) where the types of the arguments args are ArgsTypes.

source
MathOptInterface.Utilities.operateFunction
operate(op::Function, ::Type{T},
        args::Union{T, MOI.AbstractFunction}...)::MOI.AbstractFunction where T

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T. No argument can be modified.

source
MathOptInterface.Utilities.operate!Function
operate!(op::Function, ::Type{T},
         args::Union{T, MOI.AbstractFunction}...)::MOI.AbstractFunction where T

Returns an MOI.AbstractFunction representing the function resulting from the operation op(args...) on functions of coefficient type T. The first argument can be modified. The return type is the same than the method operate(op, T, args...) without !.

source
MathOptInterface.Utilities.operate_output_index!Function
operate_output_index!(
    op::Function, ::Type{T}, output_index::Integer,
    func::MOI.AbstractVectorFunction
    args::Union{T, MOI.AbstractScalarFunction}...)::MOI.AbstractFunction where T

Returns an MOI.AbstractVectorFunction where the function at output_index is the result of the operation op applied to the function at output_index of func and args. 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 can be modified.

source
MathOptInterface.Utilities.vectorizeFunction
vectorize(funcs::AbstractVector{MOI.SingleVariable})

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

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

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

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

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

source

Constraint utilities

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

MathOptInterface.Utilities.shift_constantFunction
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.

Examples

The call shift_constant(MOI.Interval(-2, 3), 1) is equal to MOI.Interval(-1, 4).

source
MathOptInterface.Utilities.normalize_and_add_constraintFunction
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.

source

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

MathOptInterface.Utilities.get_boundsFunction
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.

source

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

Benchmarks

Functions to help benchmark the performance of solver wrappers. See Benchmarking for more details.

MathOptInterface.Benchmarks.suiteFunction
suite(
    new_model::Function;
    exclude::Vector{Regex} = Regex[]
)

Create a suite of benchmarks. new_model should be a function that takes no arguments, and returns a new instance of the optimizer you wish to benchmark.

Use exclude to exclude a subset of benchmarks.

Examples

suite() do
    GLPK.Optimizer()
end
suite(exclude = [r"delete"]) do
    Gurobi.Optimizer(OutputFlag=0)
end
source
MathOptInterface.Benchmarks.create_baselineFunction
create_baseline(suite, name::String; directory::String = ""; kwargs...)

Run all benchmarks in suite and save to files called name in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
create_baseline(my_suite, "glpk_master"; directory = "/tmp", verbose = true)
source
MathOptInterface.Benchmarks.compare_against_baselineFunction
compare_against_baseline(
    suite, name::String; directory::String = "",
    report_filename::String = "report.txt"
)

Run all benchmarks in suite and compare against files called name in directory that were created by a call to create_baseline.

A report summarizing the comparison is written to report_filename in directory.

Extra kwargs are based to BenchmarkTools.run.

Examples

my_suite = suite(() -> GLPK.Optimizer())
compare_against_baseline(
    my_suite, "glpk_master"; directory = "/tmp", verbose = true
)
source

File Formats

Functions to help read and write MOI models to/from various file formats. See File Formats for more details.

MathOptInterface.FileFormats.ModelFunction
Model(
    ;
    format::FileFormat = FORMAT_AUTOMATIC,
    filename::Union{Nothing, String} = nothing,
    kwargs...
)

Return model corresponding to the FileFormat format, or, if format == FORMAT_AUTOMATIC, guess the format from filename.

The filename argument is only needed if format == FORMAT_AUTOMATIC.

kwargs are passed to the underlying model constructor.

source
MathOptInterface.FileFormats.FileFormatType
FileFormat

List of accepted export formats.

  • FORMAT_AUTOMATIC: try to detect the file format based on the file name
  • FORMAT_CBF: the Conic Benchmark format
  • FORMAT_LP: the LP file format
  • FORMAT_MOF: the MathOptFormat file format
  • FORMAT_MPS: the MPS file format
  • FORMAT_SDPA: the SemiDefinite Programming Algorithm format
source