Loading...
Searching...
No Matches
The Optimization Environment

Describes what is an optimization environment and how it is used.

What is an Optimization Environment

Any optimization object, such as variables, constraints and models, are managed through a central entity called an "optimization environment". This environment is represented by the Env class. It acts as a container and controller for all optimization-related objects created within its scope.

The environment has two primary responsibilities:

  • Lifecycle Management. When an environment is destroyed, all objects created by this environment are automatically deleted. This eliminates the need for manual memory management. Also, once an object is no longer referenced, it is safely cleaned up by the environment, i.e., you do not need to manually delete objects.
  • Version Tracking. During the execution of an optimization program, objects like variables and constraints may appear in different models with model-specific changes. These different versions of a single object are all stored and managed in the environment.

Typically, a single environment should suffice for your application. While idol technically allows the creation of multiple environments, this is strongly discouraged because this is a source of error. Objects created in one environment must not be mixed with those from another. For example, adding a variable from one environment to a model created by a different environment will lead to an undefined behavior, often resulting in a segmentation fault and a program crash.

Creating an environment is straightforward.

Env env; // Creates a new optimization environment.

Once initialized, the environment can be used to create models, variables, and constraints. All such objects are associated with env and are managed by it throughout their lifetime.

Handling of Default Tolerances and Parameters

Another role of the optimization environment is to store default values for parameters and tolerances used by underlying methods. In practice, however, it is often more relevant to modify these parameters at the optimizer level.

For instance, the following code snippet sets the default tolerance for checking that the optimality gap is closed at the environment level. Unless specified otherwise, all methods used to solve problems created with this environment will use this value.

Env env;
env.set_tol_mip_relative_gap(1e-3);

On the other hand, the following code snippet modifies the gap tolerance only for one given optimizer.

auto glpk = GLPK();
glpk.with_tol_mip_relative_gap(1e-3);
model.use(glpk);

Here is a list of tolerances that can be adjusted at an environment level.

Name Description
tol_mip_relative_gap Relative optimality gap tolerance
tol_mip_absolute_gap Absolute optimality gap tolerance
tol_integer Integrality tolerance
tol_feasibility Feasibility tolerance for constraints
tol_optimality Optimality tolerance (used for reduced cost testing)

Here is a list of parameters that can be adjusted at an environment level.

Name Description
param_logs Enable or disable solver logs
param_presolve Enable or disable presolve
param_time_limit Time limit (in seconds)
param_thread_limit Maximum number of threads
param_best_bound_stop Stop when a given bound is reached
param_best_obj_stop Stop when a given objective value is reached
param_iteration_limit Maximum number of iterations
param_infeasible_or_unbounded_info Enable detailed infeasible/unbounded information

To modify one of these, simply use the corresponding the Env::set_* method. Similarly, reading it is done with the corresponding Env::get_* method.

Here is an example to impose a thread limit of one on all underlying methods.

env.set_thread_limit(5);
std::cout << "Using at most " << env.get_thread_limit(); << " threads." << std::endl;