Models

The Model class is used to represent a (standard) optimization model, i.e., a mathematical program of the form

\[\begin{split}\begin{align} \min_x \ & c^\top x + x^\top D x + c_0 \\ \text{s.t.} \ & a_{(i)}^\top x + x^\top Q^i x \le b_i \quad i=1,\dotsc,m \\ & x_j \in \mathbb Z \quad j=1,\dotsc,p \end{align}\end{split}\]

Here, \(x_j\) are the decision variables of this optimization problem while matrices \(c, D, A\) and \(Q^i\) are given input parameters for this model. Additionally, variables \(x_j\) having \(j\in\{ 1,\dotsc,p \}\) have to be integer-valued.

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.

Reading a Model from a File

A Model can also be created by reading a model from a file (typically, an 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 = some_function_creating_my_model(env); // this is assumed to create the desired optimization model

model.use(Gurobi()); // We will use Gurobi as the optimizer

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;