Environments#

An environment is a multi-purpose data structure in Gurobi. It is typically the first Gurobi object you create and the last one you destroy. While the workings of environments are actually quite simple, the breadth of uses can sometimes cause confusion. This section lays out the different usage scenarios to make this clearer.

At the highest level, environments provide three basic functions: (i) to capture a set of parameter settings, (ii) to delineate a (single-threaded) Gurobi session, and (iii) to hold a Gurobi license. Things only get interesting once you consider the many different ways these capabilities are used throughout the product:

  • Session boundaries: Environments indicate when your program starts and stops using Gurobi.

  • Configuration parameters: Environments allow you to configure your session (whether you will run locally or on a Compute Server or on the Instant Cloud, your login credentials, etc.).

  • Algorithmic parameters: Environments enable you to modify algorithmic parameters, which influence how the solver solves your model.

  • Concurrent environments: When using a concurrent algorithm, concurrent environments allow you to control the algorithmic parameters used in each independent solve.

  • Multi-objective environments: When solving a multi-objective model, multi-objective environments allow you to control the algorithmic parameters used for each objective.

Session boundaries#

One of the main purposes of an environment is to indicate when your program will start to use Gurobi, and when it is done. When Gurobi is running on your own machine, creating an environment will obtain a license, and disposing of the environment will release that license. When you are a client of a Gurobi Compute Server, starting an environment will start a job on the server (or place the job in the queue if the server is fully occupied). Disposing of the environment will end that job, allowing the next job in the queue to start. On Gurobi Instant Cloud, creating an environment will launch a cloud instance (if it hasn’t been launched already). Disposing of the environment will end that session, which may result in the cloud instance being shut down (depending on the policy you’ve set in your Instant Cloud configuration).

If your program repeatedly creates, solves, and destroys optimization models, we strongly recommend that you do so within a single Gurobi environment. Creating a Gurobi environment incurs overhead, ranging anywhere from a quick local license check all the way to spinning up a machine on the cloud. By reusing a single environment, you avoid paying this overhead multiple times.

We also recommend that you dispose of your environment as soon as your program is done using Gurobi. Doing so releases all resources associated with that session, which in many cases can make those resources available to other users. You should pay particular attention to this topic when using programming languages that perform garbage-collection. While it is true that environments will be disposed of eventually by automated garbage-collection, that will often happen much earlier if you dispose of them explicitly.

The actual steps for disposing of an environment will depend on the API you are using:

Call GRBfreemodel() for each model, then call GRBfreeenv() for the Gurobi environment. For example:

GRBenv   *env   = NULL;
GRBmodel *model = NULL;
int       error = 0;

/* Create environment */
error = GRBloadenv(&env, "example.log");;
if (error) goto QUIT;

/* Create an empty model */
error = GRBnewmodel(env, &model, "example", 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;

/* Create and add variable, constraints, objective; solve model */

QUIT:
 /* Clean up model and environment */
 GRBfreemodel(model);
 GRBfreeenv(env);

Note that the boundaries established by an environment are for a single thread. Gurobi environments are not thread-safe, so you can’t have more than one thread of control within a single environment. You can however have a single program that launches multiple threads, each with its own environment.

Configuration parameters#

When you start a Gurobi session, you often have to provides details about your configuration. You may need to indicate whether you want to use a license on your local machine, a license from a Token Server, or perhaps you want to offload your computation to a Compute Server or to Gurobi Instant Cloud. In the case of a Token Server or a Compute Server, you have to provide the name of the server. For Compute Server and Instant Cloud, you also need to provide login credentials.

In many situations, the configuration information you need is already stored in your license file (gurobi.lic) or in your environment file (gurobi.env). These files are read automatically, so you can simply create a standard Gurobi environment object (using GRBloadenv in C, or through the appropriate GRBEnv constructor in the object-oriented interfaces).

What if you need to provide configuration information from your application at runtime instead? You can use an empty environment to split environment creation into a few steps (as opposed to the standard, single-step approach mentioned above). In the first step, you would create an empty environment object (using GRBemptyenv in C, or through the appropriate GRBEnv constructor in the object-oriented interfaces). You would then set configuration parameters on this environment using the standard parameter API. Finally, you would start the environment (using GRBstartenv in C, or using the env.start() method in the object-oriented interfaces), which will use the configuration parameters you just set.

Empty environment example#

To give a simple example, if you want your program to use a specific license, you could do the following:

To use a Cluster Manager you need to provide the URL and your credentials in order to launch an instance on the Cluster Manager. The URL to the Cluster Manager (CSManager) must always be specified. It usually includes a port number. In addition, and depending on the type of credentials you want to use, you must provide either:

The example code will feature CSAPIAccessID and CSAPISecret.

#include "gurobi_c.h"

int main(void) {
   GRBenv   *env   = NULL;
   GRBmodel *model = NULL;

   int error = 0;

   /* Create empty environment, set options and start */
   error = GRBemptyenv(&env);
   if (error) goto QUIT;
   error = GRBsetstrparam(env, GRB_STR_PAR_CSMANAGER, "server1:61080");
   if (error) goto QUIT;
   error = GRBsetstrparam(env, GRB_STR_PAR_CSAPIACCESSID, "12345-678990");
   if (error) goto QUIT;
   error = GRBsetstrparam(env, GRB_STR_PAR_CSAPISECRET, "abcdef-abcdef");
   if (error) goto QUIT;
   error = GRBstartenv(env);
   if (error) goto QUIT;

   /* Load model and optimize */
   error = GRBreadmodel(env, "misc07.mps", &model);
   if (error) goto QUIT;
   error = GRBoptimize(model);
   if (error) goto QUIT;

QUIT:

   /* Clean up model and environment */
   GRBfreemodel(model);
   GRBfreeenv(env);

   return error;
}

Note

Configuration parameters must be set before you start the Gurobi environment. Changes have no effect once the environment has been started.

Note

In Python you can also provide such configuration parameters directly as a dict argument to the environment constructor, without creating an empty environment first. Please refer to the Env constructor documentation for an example.

Algorithmic parameters#

Environments can also be used to set algorithmic parameters - parameters that control the behavior of the optimization solver. To give a few examples, the TimeLimit parameter indicates the maximum allowed runtime for any solve, while the Method parameter chooses the algorithm used to solve continuous optimization models.

Having said that, we actually recommend that you set algorithmic parameters on the model rather than on the environment. The object-oriented APIs all include model.set methods that enable you to do so. What’s the difference between setting parameters on the environment versus on the model? Parameter values are copied from the environment when the model is created, so changes to parameter values in the environment have no effect on models that have already been created. This is a frequent source of confusion.

In the C API, there is no method to set parameters on the model directly. Instead, the model environment can be retrieved by calling GRBgetenv.

Please see the Parameter Examples section for examples on how parameters are set.

Concurrent environments#

One algorithmic option available in Gurobi is concurrent optimization, where multiple independent solves are performed in parallel and Gurobi takes care of collecting and combining the results. Concurrent optimization can be quite powerful; it is actually the default approach for solving linear programming models.

The power of concurrent optimization comes from the fact that different approaches to solving a model may have different performance characteristics, and performing them in parallel allows you to stop when the first one finishes. All of our concurrent schemes have default choices for determining the strategy that each independent solve uses. However, it is also possible for you to pick different strategies. This is done through concurrent environments. By creating two or more concurrent environments for a model, and setting parameters on these environments, you can control exactly what each concurrent solve does.

Concurrent environments are created via API routines (in C, C++, Java, .NET, or Python). You set parameters on these environments as you would with any other environment, but in this case they only affect one of the several independent solves.

To give a simple example, you could do the following:

/* Create concurrent environments */
GRBenv *env0 = GRBgetconcurrentenv(model, 0);
GRBenv *env1 = GRBgetconcurrentenv(model, 1);

/* Set parameters on concurrent environments
(for ease of readability, errors are not checked here) */
error = GRBsetintparam(env0, "MIPFocus", 1);
error = GRBsetintparam(env1, "MIPFocus", 2);

/* Perform concurrent optimization */
error = GRBoptimize(model);

This would launch two concurrent solves on your model, one with the MIPFocus parameter set to 1 and the other with it set to 2.

Please note that parameter values are copied from the model when the concurrent environment is created. Therefore, changes to parameter values on the model have no effect on concurrent environments that have already been created. This is a frequent source of confusion.

Users of our command-line interface can set concurrent optimization parameters with .prm files using the ConcurrentSettings parameter.

Multi-objective environments#

When solving a multi-objective model, the solution process typically proceeds in phases, where each phase solves for one objective. The standard algorithmic parameters influence the strategy used to solve the overall multi-objective model. However, in some cases you may want finer-grain control over the strategies used in each phase. The solver enables this through multi-objective environments.

Multi-objective environments are created via API routines (in C, C++, Java, .NET, or Python). You set parameters on these environments as you would with any other environment, but in this case they only affect one of the several objective solves.

To give a simple example, you could do the following:

/* Create multi-objective environments */
GRBenv *env0 = GRBgetmultiobjenv(model, 0);
GRBenv *env1 = GRBgetmultiobjenv(model, 1);

/* Set parameters on multi-objective environments
(for ease of readability, errors are not checked here) */
error = GRBsetintparam(env0, "Method", 2);
error = GRBsetintparam(env1, "Method", 1);
error = GRBsetintparam(env1, "Presolve", 0);

/* Perform multi-objective optimization */
error = GRBoptimize(model);

This would use the barrier solver (Method=2) for the first objective, and the dual simplex solver (Method=1) with no presolve (Presolve=0) for the second. Note that you don’t need a multi-objective environment for each objective - only for those where you want parameters to take different values from those of the model itself.

Please note that parameter values are copied from the model when the multi-objective environment is created. Therefore, changes to parameter values on the model have no effect on multi-objective environments that have already been created. This is a frequent source of confusion.