Variables

Variables are the decision variables of an optimization problem. They are the objects that we want to find the best values for, with respect to some objective function given the specified constraints.

Creating Variables

There are mainly two ways to create variables in idol. The first one is to use the Var class directly, and the second one is to use the Model::add_var method.

Using the Var class directly creates a variable that is not associated to any model. We will there need to add it explicitly to a model. This is done by calling the Model::add method. See for instance the following code which creates a continuous variable \(x\), with bounds \([0,\infty)\), and adds it to the model.

Var x(env, 0., Inf, Continuous, "x");

model.add(x); // Variable x is added to the model

Note that a variable may belong to several models at the same time. Each version of the variable in each model is then independent. For instance, one could do the following.

Var x(env, 0., Inf, Continuous, "x");

model.add(x);

Model model2(env);
model2.add(x);
model2.set_var_ub(x, 10.);

In this example, the variable \(x\) is added to two different models. The upper bound of \(x\) in the second model is then set to 10. The upper bound of \(x\) in the first model is not affected by this change.

A more straightforward way to create variables is to call the add_var method of the Model class. For instance, one can do:

const auto x = model.add_var(0, Inf, Continuous, "x");

Here, we do not need to repeat the environment since the model’s environment is used by default. Moreover, we do not need to explicitly add the variable to the model since it is done automatically by the add_var method.

Again, a variable may belong to several models at the same time. And we can do as follows.

const auto x = model.add_var(0, Inf, Continuous, "x");

Model model2(env);
model2.add(x);
model2.set_var_ub(x, 10.);

Note that an even more compact version of the previous code is obtained by using the Model::add method with additional parameters. For instance, the following code is equivalent to the previous one.

const auto x = model.add(0, Inf, Continuous, "x");

Model model2(env);
model2.add(x, TempVar(0, 10, Continuous));

Here, we used the class TempVar to create a temporary variable. A temporary variable is a variable which has not been instantiate yet. It is only a “template” of a variable specifying its bounds and type. Here, we therefore add the variable \(x\) to the second model and directly set its attributes (bounds and type) accordingly.

Creating Several Variables at Once

Sometimes, you will find it convenient to create several variables at once. This can be done by calling the Var::make_vector function, or the Model::add_vars method. These functions require an extra parameter specifying the dimension of the new variable.

For instance, the following code creates variables \(y_{ij}\) with \(i=1,...,K\) and \(j=1,...,T\).

const auto y = Var::make_vector(env, Dim<2>(K, T), 0., Inf, Continuous, "y");

model.add_vector<Var, 2>(y);

std::cout << y[0][0] << std::endl; // "y_0_0"

Similarly, one could use the more direct Model::add_vars method.

const auto y = model.add_vars(Dim<2>(K, T), 0., Inf, Continuous, "y");

std::cout << y[0][0] << std::endl; // "y_0_0"

Integer and binary variables can be created by setting the type of the variable to Integer and Binary respectively.

Accessing Variables

Information about a given variable in a model can be accessed by calling the corresponding methods of the model. For instance, one can access the lower bound of a variable by calling the Model::get_var_lb method. Similarly, the upper bound of a variable can be accessed by calling the Model::get_var_ub method. The type of a variable can be accessed by calling the Model::get_var_type method. The column of a variable in the model can be accessed by calling the Model::get_var_column method.

If a given model has been solved and feasibility could be proved (or better, optimality), the value of a variable can be accessed by calling the Model::get_var_primal method. When applicable, its reduced cost can be accessed by calling the Model::get_var_reduced_cost method. Similarly, for unbounded models, a primal ray can be accessed by calling the Model::get_var_ray method.

The Model::has method can be used to check if a given variable is in the model.

The current index of a variable in the model can be accessed by calling the Model::get_var_index method. Beware, however, that the index may change if the model is modified.

For more details, see the Model class.

Modifying Variables

The bounds of a variable can be modified by calling the Model::set_var_lb and Model::set_var_ub methods. The type of a variable can be modified by calling the Model::set_var_type method.

The column of a variable in the model can be modified by calling the Model::set_var_column method. For instance.

Column column(objective_coefficient_for_x);
column.linear().set(constraint1, constraint1_coefficient_for_x);
column.linear().set(constraint2, constraint2_coefficient_for_x);

model.set_var_column(x, column);

For more details, see the Model class.

Removing Variables

A variable can be removed from a model by calling the Model::remove method.