Models

The Model class is used to represent a (standard) optimization model of the form

\[\begin{split}\begin{align} \min_{x} \quad & c^\top x + x^\top D x + c_0 \\ \text{s.t.} \quad & a_{i\cdot}^\top x + x^\top Q^i x \le b_i, \quad i = 1, \ldots, m, \\ & x_j \in \mathbb{Z}, \quad j \in I \subseteq \{ 1, \dotsc, n \}. \end{align}\end{split}\]

Here, \(x\) are the decision variables, while \(c\), \(D\), \(c_0\), \(a_i\), \(Q^i\), and \(b_i\) are given data. Some of the decision variables are required to be integer-valued and are indexed by \(I\).

In what follows, we will dive into the Model class and see how to create, read, and write models to files.

Creating a Model

A Model is created by calling the constructor of the Model class. Note that it is necessary to pass an environment to the constructor.

The following code creates a new optimization model.

Env env;
Model model(env);

We can now define our decision variables and constraints, and add an objective function to our model. This is detailed in the Variables, Constraints and Objective sections, respectively.

Reading a Model from a File

A Model can also be created by reading a model from a file (typically, a .mps or an .lp file). To do this, idol relies on an external solver. The following code reads a model from a file using Gurobi.

Env env;
auto model = Gurobi::read_from_file(env, "/path/to/model.mps");
// auto model = GLPK::read_from_file(env, "/path/to/model.mps");

Writing a Model to a File

To write an optimization model to a file, the easiest way is again to rely on an external solver. This is done by attaching a solver to a model, then by calling the Model::write method.

Env env;
Model model(env);

// Add variables and constraints HERE...

model.use(Gurobi()); // Set the optimizer as Gurobi

model.write("instance.lp"); // Creates a new file "instance.lp" storing the model

Iterating over the Variables and Constraints

The Model class provides methods to iterate over the variables and constraints of the model. See for instance, the following example.

for (const auto& var : model.vars()) {
    std::cout << "Variable " << var.name() << " belongs to the model." << std::endl;
}

for (const auto& ctr : model.ctrs()) {
    std::cout << "Constraint " << ctr.name() << " belongs to the model." << std::endl;
}

The number of variables and constraints can be obtained by doing the following.

std::cout << "Nb. of variables: " << model.vars().size() << std::endl;
std::cout << "Nb. of constraints: " << model.ctrs().size() << std::endl;