# Models

More information can be found in the Models section of the manual.

## Constructors

`JuMP.Model`

— Type`Model`

A mathematical model of an optimization problem.

`JuMP.direct_model`

— Function`direct_model(backend::MOI.ModelLike)`

Return a new JuMP model using `backend`

to store the model and solve it.

As opposed to the `Model`

constructor, no cache of the model is stored outside of `backend`

and no bridges are automatically applied to `backend`

.

**Notes**

The absence of a cache reduces the memory footprint but, it is important to bear in mind the following implications of creating models using this *direct* mode:

- When
`backend`

does not support an operation, such as modifying constraints or adding variables/constraints after solving, an error is thrown. For models created using the`Model`

constructor, such situations can be dealt with by storing the modifications in a cache and loading them into the optimizer when`optimize!`

is called. - No constraint bridging is supported by default.
- The optimizer used cannot be changed the model is constructed.
- The model created cannot be copied.

`direct_model(factory::MOI.OptimizerWithAttributes)`

Create a `direct_model`

using `factory`

, a `MOI.OptimizerWithAttributes`

object created by `optimizer_with_attributes`

.

**Example**

```
model = direct_model(
optimizer_with_attributes(
Gurobi.Optimizer,
"Presolve" => 0,
"OutputFlag" => 1,
)
)
```

is equivalent to:

```
model = direct_model(Gurobi.Optimizer())
set_optimizer_attribute(model, "Presolve", 0)
set_optimizer_attribute(model, "OutputFlag", 1)
```

## Enums

`JuMP.ModelMode`

— Type`ModelMode`

An enum to describe the state of the CachingOptimizer inside a JuMP model.

`JuMP.AUTOMATIC`

— Constant`moi_backend`

field holds a CachingOptimizer in AUTOMATIC mode.

`JuMP.MANUAL`

— Constant`moi_backend`

field holds a CachingOptimizer in MANUAL mode.

`JuMP.DIRECT`

— Constant`moi_backend`

field holds an AbstractOptimizer. No extra copy of the model is stored. The `moi_backend`

must support `add_constraint`

etc.

## Basic functions

`JuMP.backend`

— Function`backend(model::Model)`

Return the lower-level MathOptInterface model that sits underneath JuMP. This model depends on which operating mode JuMP is in (see `mode`

).

- If JuMP is in
`DIRECT`

mode (i.e., the model was created using`direct_model`

), the backend will be the optimizer passed to`direct_model`

. - If JuMP is in
`MANUAL`

or`AUTOMATIC`

mode, the backend is a`MOI.Utilities.CachingOptimizer`

.

**This function should only be used by advanced users looking to access low-level MathOptInterface or solver-specific functionality.**

**Notes**

If JuMP is not in `DIRECT`

mode, the type returned by `backend`

may change between any JuMP releases. Therefore, only use the public API exposed by MathOptInterface, and do not access internal fields. If you require access to the innermost optimizer, see `unsafe_backend`

. Alternatively, use `direct_model`

to create a JuMP model in `DIRECT`

mode.

See also: `unsafe_backend`

.

`JuMP.unsafe_backend`

— Function`unsafe_backend(model::Model)`

Return the innermost optimizer associated with the JuMP model `model`

.

**This function should only be used by advanced users looking to access low-level solver-specific functionality. It has a high-risk of incorrect usage. We strongly suggest you use the alternative suggested below.**

See also: `backend`

.

**Unsafe behavior**

This function is unsafe for two main reasons.

First, the formulation and order of variables and constraints in the unsafe backend may be different to the variables and constraints in `model`

. This can happen because of bridges, or because the solver requires the variables or constraints in a specific order. In addition, the variable or constraint index returned by `index`

at the JuMP level may be different to the index of the corresponding variable or constraint in the `unsafe_backend`

. There is no solution to this. Use the alternative suggested below instead.

Second, the `unsafe_backend`

may be empty, or lack some modifications made to the JuMP model. Thus, before calling `unsafe_backend`

you should first call `MOI.Utilities.attach_optimizer`

to ensure that the backend is synchronized with the JuMP model.

```
MOI.Utilities.attach_optimizer(model)
inner = unsafe_backend(model)
```

Moreover, if you modify the JuMP model, the reference you have to the backend (i.e., `inner`

in the example above) may be out-dated, and you should call `MOI.Utilities.attach_optimizer`

again.

This function is also unsafe in the reverse direction: if you modify the unsafe backend, e.g., by adding a new constraint to `inner`

, the changes may be silently discarded by JuMP when the JuMP `model`

is modified or solved.

**Alternative**

Instead of `unsafe_backend`

, create a model using `direct_model`

and call `backend`

instead.

For example, instead of:

```
model = Model(HiGHS.Optimizer)
@variable(model, x >= 0)
MOI.Utilities.attach_optimizer(model)
highs = unsafe_backend(model)
```

Use:

```
model = direct_model(HiGHS.Optimizer())
@variable(model, x >= 0)
highs = backend(model) # No need to call `attach_optimizer`.
```

`JuMP.name`

— Method`JuMP.solver_name`

— Function`solver_name(model::Model)`

If available, returns the `SolverName`

property of the underlying optimizer.

Returns `"No optimizer attached"`

in `AUTOMATIC`

or `MANUAL`

modes when no optimizer is attached.

Returns `"SolverName() attribute not implemented by the optimizer."`

if the attribute is not implemented.

`Base.empty!`

— Method`empty!(model::Model)::Model`

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

Note: removes extensions data.

`Base.isempty`

— Method`isempty(model::Model)`

Verifies whether the model is empty, that is, whether the MOI backend is empty and whether the model is in the same state as at its creation apart from optimizer attributes.

`JuMP.mode`

— Function`JuMP.object_dictionary`

— Function`object_dictionary(model::Model)`

Return the dictionary that maps the symbol name of a variable, constraint, or expression to the corresponding object.

Objects are registered to a specific symbol in the macros. For example, `@variable(model, x[1:2, 1:2])`

registers the array of variables `x`

to the symbol `:x`

.

This method should be defined for any subtype of `AbstractModel`

.

`JuMP.unregister`

— Function`unregister(model::Model, key::Symbol)`

Unregister the name `key`

from `model`

so that a new variable, constraint, or expression can be created with the same key.

Note that this will not delete the object `model[key]`

; it will just remove the reference at `model[key]`

. To delete the object, use

```
delete(model, model[key])
unregister(model, key)
```

See also: `object_dictionary`

.

**Examples**

```
julia> @variable(model, x)
x
julia> @variable(model, x)
ERROR: An object of name x is already attached to this model. If
this is intended, consider using the anonymous construction syntax,
e.g., `x = @variable(model, [1:N], ...)` where the name of the object
does not appear inside the macro.
Alternatively, use `unregister(model, :x)` to first unregister the
existing name from the model. Note that this will not delete the object;
it will just remove the reference at `model[:x]`.
[...]
julia> num_variables(model)
1
julia> unregister(model, :x)
julia> @variable(model, x)
x
julia> num_variables(model)
2
```

`JuMP.latex_formulation`

— Function`latex_formulation(model::AbstractModel)`

Wrap `model`

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

in a notebook like IJulia, or in Documenter.

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

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

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

`JuMP.set_string_names_on_creation`

— Function`set_string_names_on_creation(model::Model, value::Bool)`

Set the default argument of the `set_string_name`

keyword in the `@variable`

and `@constraint`

macros to `value`

. This is used to determine whether to assign `String`

names to all variables and constraints in `model`

.

By default, `value`

is `true`

. However, for larger models calling `set_string_names_on_creation(model, false)`

can improve performance at the cost of reducing the readability of printing and solver log messages.

## Working with attributes

`JuMP.set_optimizer`

— Function```
set_optimizer(
model::Model,
optimizer_factory;
add_bridges::Bool = true,
)
```

Creates an empty `MathOptInterface.AbstractOptimizer`

instance by calling `optimizer_factory()`

and sets it as the optimizer of `model`

. Specifically, `optimizer_factory`

must be callable with zero arguments and return an empty `MathOptInterface.AbstractOptimizer`

.

If `add_bridges`

is true, constraints and objectives that are not supported by the optimizer are automatically bridged to equivalent supported formulation. Passing `add_bridges = false`

can improve performance if the solver natively supports all of the elements in `model`

.

See `set_optimizer_attributes`

and `set_optimizer_attribute`

for setting solver-specific parameters of the optimizer.

**Examples**

```
model = Model()
set_optimizer(model, HiGHS.Optimizer)
set_optimizer(model, HiGHS.Optimizer; add_bridges = false)
```

`JuMP.optimizer_with_attributes`

— Function`optimizer_with_attributes(optimizer_constructor, attrs::Pair...)`

Groups an optimizer constructor with the list of attributes `attrs`

. Note that it is equivalent to `MOI.OptimizerWithAttributes`

.

When provided to the `Model`

constructor or to `set_optimizer`

, it creates an optimizer by calling `optimizer_constructor()`

, and then sets the attributes using `set_optimizer_attribute`

.

**Example**

```
model = Model(
optimizer_with_attributes(
Gurobi.Optimizer, "Presolve" => 0, "OutputFlag" => 1
)
)
```

is equivalent to:

```
model = Model(Gurobi.Optimizer)
set_optimizer_attribute(model, "Presolve", 0)
set_optimizer_attribute(model, "OutputFlag", 1)
```

**Note**

The string names of the attributes are specific to each solver. One should consult the solver's documentation to find the attributes of interest.

See also: `set_optimizer_attribute`

, `set_optimizer_attributes`

, `get_optimizer_attribute`

.

`JuMP.get_optimizer_attribute`

— Function`get_optimizer_attribute(model, name::String)`

Return the value associated with the solver-specific attribute named `name`

.

Note that this is equivalent to `get_optimizer_attribute(model, MOI.RawOptimizerAttribute(name))`

.

**Example**

`get_optimizer_attribute(model, "SolverSpecificAttributeName")`

See also: `set_optimizer_attribute`

, `set_optimizer_attributes`

.

```
get_optimizer_attribute(
model::Model, attr::MOI.AbstractOptimizerAttribute
)
```

Return the value of the solver-specific attribute `attr`

in `model`

.

**Example**

`get_optimizer_attribute(model, MOI.Silent())`

See also: `set_optimizer_attribute`

, `set_optimizer_attributes`

.

`JuMP.set_optimizer_attribute`

— Function`set_optimizer_attribute(model::Model, name::String, value)`

Sets solver-specific attribute identified by `name`

to `value`

.

Note that this is equivalent to `set_optimizer_attribute(model, MOI.RawOptimizerAttribute(name), value)`

.

**Example**

`set_optimizer_attribute(model, "SolverSpecificAttributeName", true)`

See also: `set_optimizer_attributes`

, `get_optimizer_attribute`

.

```
set_optimizer_attribute(
model::Model,
attr::MOI.AbstractOptimizerAttribute,
value,
)
```

Set the solver-specific attribute `attr`

in `model`

to `value`

.

**Example**

`set_optimizer_attribute(model, MOI.Silent(), true)`

See also: `set_optimizer_attributes`

, `get_optimizer_attribute`

.

`JuMP.set_optimizer_attributes`

— Function`set_optimizer_attributes(model::Model, pairs::Pair...)`

Given a list of `attribute => value`

pairs, calls `set_optimizer_attribute(model, attribute, value)`

for each pair.

**Example**

```
model = Model(Ipopt.Optimizer)
set_optimizer_attributes(model, "tol" => 1e-4, "max_iter" => 100)
```

is equivalent to:

```
model = Model(Ipopt.Optimizer)
set_optimizer_attribute(model, "tol", 1e-4)
set_optimizer_attribute(model, "max_iter", 100)
```

See also: `set_optimizer_attribute`

, `get_optimizer_attribute`

.

`JuMP.set_silent`

— Function`set_silent(model::Model)`

Takes precedence over any other attribute controlling verbosity and requires the solver to produce no output.

See also: `unset_silent`

.

`JuMP.unset_silent`

— Function`unset_silent(model::Model)`

Neutralize the effect of the `set_silent`

function and let the solver attributes control the verbosity.

See also: `set_silent`

.

`JuMP.set_time_limit_sec`

— Function`set_time_limit_sec(model::Model, limit::Float64)`

Set the time limit (in seconds) of the solver.

Can be unset using `unset_time_limit_sec`

or with `limit`

set to `nothing`

.

See also: `unset_time_limit_sec`

, `time_limit_sec`

.

`JuMP.unset_time_limit_sec`

— Function`unset_time_limit_sec(model::Model)`

Unset the time limit of the solver.

See also: `set_time_limit_sec`

, `time_limit_sec`

.

`JuMP.time_limit_sec`

— Function`time_limit_sec(model::Model)`

Return the time limit (in seconds) of the `model`

.

Returns `nothing`

if unset.

See also: `set_time_limit_sec`

, `unset_time_limit_sec`

.

## Copying

`JuMP.ReferenceMap`

— Type`ReferenceMap`

Mapping between variable and constraint reference of a model and its copy. The reference of the copied model can be obtained by indexing the map with the reference of the corresponding reference of the original model.

`JuMP.copy_model`

— Function`copy_model(model::Model; filter_constraints::Union{Nothing, Function}=nothing)`

Return a copy of the model `model`

and a `ReferenceMap`

that can be used to obtain the variable and constraint reference of the new model corresponding to a given `model`

's reference. A `Base.copy(::AbstractModel)`

method has also been implemented, it is similar to `copy_model`

but does not return the reference map.

If the `filter_constraints`

argument is given, only the constraints for which this function returns `true`

will be copied. This function is given a constraint reference as argument.

**Note**

Model copy is not supported in `DIRECT`

mode, i.e. when a model is constructed using the `direct_model`

constructor instead of the `Model`

constructor. Moreover, independently on whether an optimizer was provided at model construction, the new model will have no optimizer, i.e., an optimizer will have to be provided to the new model in the `optimize!`

call.

**Examples**

In the following example, a model `model`

is constructed with a variable `x`

and a constraint `cref`

. It is then copied into a model `new_model`

with the new references assigned to `x_new`

and `cref_new`

.

```
model = Model()
@variable(model, x)
@constraint(model, cref, x == 2)
new_model, reference_map = copy_model(model)
x_new = reference_map[x]
cref_new = reference_map[cref]
```

`JuMP.copy_extension_data`

— Function`copy_extension_data(data, new_model::AbstractModel, model::AbstractModel)`

Return a copy of the extension data `data`

of the model `model`

to the extension data of the new model `new_model`

.

A method should be added for any JuMP extension storing data in the `ext`

field.

Do not engage in type piracy by implementing this method for types of `data`

that you did not define! JuMP extensions should store types that they define in `model.ext`

, rather than regular Julia types.

`Base.copy`

— Method`copy(model::AbstractModel)`

Return a copy of the model `model`

. It is similar to `copy_model`

except that it does not return the mapping between the references of `model`

and its copy.

**Note**

Model copy is not supported in `DIRECT`

mode, i.e. when a model is constructed using the `direct_model`

constructor instead of the `Model`

constructor. Moreover, independently on whether an optimizer was provided at model construction, the new model will have no optimizer, i.e., an optimizer will have to be provided to the new model in the `optimize!`

call.

**Examples**

In the following example, a model `model`

is constructed with a variable `x`

and a constraint `cref`

. It is then copied into a model `new_model`

with the new references assigned to `x_new`

and `cref_new`

.

```
model = Model()
@variable(model, x)
@constraint(model, cref, x == 2)
new_model = copy(model)
x_new = model[:x]
cref_new = model[:cref]
```

## I/O

`JuMP.write_to_file`

— Function```
write_to_file(
model::Model,
filename::String;
format::MOI.FileFormats.FileFormat = MOI.FileFormats.FORMAT_AUTOMATIC,
kwargs...,
)
```

Write the JuMP model `model`

to `filename`

in the format `format`

.

If the filename ends in `.gz`

, it will be compressed using Gzip. If the filename ends in `.bz2`

, it will be compressed using BZip2.

Other `kwargs`

are passed to the `Model`

constructor of the chosen format.

`Base.write`

— Method```
Base.write(
io::IO,
model::Model;
format::MOI.FileFormats.FileFormat = MOI.FileFormats.FORMAT_MOF,
kwargs...,
)
```

Write the JuMP model `model`

to `io`

in the format `format`

.

Other `kwargs`

are passed to the `Model`

constructor of the chosen format.

`JuMP.read_from_file`

— Function```
read_from_file(
filename::String;
format::MOI.FileFormats.FileFormat = MOI.FileFormats.FORMAT_AUTOMATIC,
kwargs...,
)
```

Return a JuMP model read from `filename`

in the format `format`

.

If the filename ends in `.gz`

, it will be uncompressed using Gzip. If the filename ends in `.bz2`

, it will be uncompressed using BZip2.

Other `kwargs`

are passed to the `Model`

constructor of the chosen format.

`Base.read`

— Method```
Base.read(
io::IO,
::Type{Model};
format::MOI.FileFormats.FileFormat,
kwargs...,
)
```

Return a JuMP model read from `io`

in the format `format`

.

Other `kwargs`

are passed to the `Model`

constructor of the chosen format.

## Caching Optimizer

`MathOptInterface.Utilities.reset_optimizer`

— Method`MOIU.reset_optimizer(model::Model)`

Call `MOIU.reset_optimizer`

on the backend of `model`

.

Cannot be called in direct mode.

`MathOptInterface.Utilities.drop_optimizer`

— Method`MOIU.drop_optimizer(model::Model)`

Call `MOIU.drop_optimizer`

on the backend of `model`

.

Cannot be called in direct mode.

`MathOptInterface.Utilities.attach_optimizer`

— Method`MOIU.attach_optimizer(model::Model)`

Call `MOIU.attach_optimizer`

on the backend of `model`

.

Cannot be called in direct mode.

## Bridge tools

`JuMP.bridge_constraints`

— Function`bridge_constraints(model::Model)`

When in direct mode, return `false`

. When in manual or automatic mode, return a `Bool`

indicating whether the optimizer is set and unsupported constraints are automatically bridged to equivalent supported constraints when an appropriate transformation is available.

`JuMP.print_bridge_graph`

— Function` print_bridge_graph([io::IO,] model::Model)`

Print the hyper-graph containing all variable, constraint, and objective types that could be obtained by bridging the variables, constraints, and objectives that are present in the model.

Each node in the hyper-graph corresponds to a variable, constraint, or objective type.

- Variable nodes are indicated by
`[ ]`

- Constraint nodes are indicated by
`( )`

- Objective nodes are indicated by
`| |`

The number inside each pair of brackets is an index of the node in the hyper-graph.

Note that this hyper-graph is the full list of possible transformations. When the bridged model is created, we select the shortest hyper-path(s) from this graph, so many nodes may be un-used.

For more information, see Legat, B., Dowson, O., Garcia, J., and Lubin, M. (2020). "MathOptInterface: a data structure for mathematical optimization problems." URL: https://arxiv.org/abs/2002.03447

## Extension tools

`JuMP.AbstractModel`

— Type`AbstractModel`

An abstract type that should be subtyped for users creating JuMP extensions.

`JuMP.operator_warn`

— Function```
operator_warn(model::AbstractModel)
operator_warn(model::Model)
```

This function is called on the model whenever two affine expressions are added together without using `destructive_add!`

, and at least one of the two expressions has more than 50 terms.

For the case of `Model`

, if this function is called more than 20,000 times then a warning is generated once.

`JuMP.error_if_direct_mode`

— Function`error_if_direct_mode(model::Model, func::Symbol)`

Errors if `model`

is in direct mode during a call from the function named `func`

.

Used internally within JuMP, or by JuMP extensions who do not want to support models in direct mode.

`JuMP.set_optimize_hook`

— Function`set_optimize_hook(model::Model, f::Union{Function,Nothing})`

Set the function `f`

as the optimize hook for `model`

.

`f`

should have a signature `f(model::Model; kwargs...)`

, where the `kwargs`

are those passed to `optimize!`

.

**Notes**

- The optimize hook should generally modify the model, or some external state in some way, and then call
`optimize!(model; ignore_optimize_hook = true)`

to optimize the problem, bypassing the hook. - Use
`set_optimize_hook(model, nothing)`

to unset an optimize hook.

**Examples**

```
model = Model()
function my_hook(model::Model; kwargs...)
print(kwargs)
return optimize!(model; ignore_optimize_hook = true)
end
set_optimize_hook(model, my_hook)
optimize!(model; test_arg = true)
```