> Languages and APIs > ILOG Concert Technology for C++ Users > Modeling an Optimization Problem with Concert Technology > Modeling Classes

A Concert Technology model consists of a set of C++ objects. Each variable, each constraint, each special ordered set (SOS), and the objective function in a model are all represented by objects of the appropriate Concert Technology class. These objects are known as modeling objects.

Creating the Environment: IloEnv

Before you create modeling objects, you must construct an object of the class IloEnv. This object known as the environment. It is constructed with the statement:

IloEnv env;

That statement is usually the first Concert Technology statement in an application. At the end, you must close the environment by calling:

env.end();

That statement is usually the last Concert Technology statement in an application. The end method must be called because, like most Concert Technology classes, the class IloEnv is a handle class. That is, an IloEnv object is really only a pointer to an implementation object. Implementation objects are destroyed by calling the end method. Failing to call the end method can result in memory leaks.

Users familiar with the ILOG CPLEX Callable Library are cautioned not to confuse the Concert Technology environment object with the ILOG CPLEX environment object of type CPXENVptr, used for setting ILOG CPLEX parameters. Such an object is not needed with Concert Technology, as parameters are handled directly by each instance of the class IloCplex. In other words, the environment in Concert Technology always refers to the object of class IloEnv required for all other Concert Technology objects.

Defining Variables and Expressions: IloNumVar

Probably the first modeling class you will need is IloNumVar. Objects of this class represent decision variables in a model. They are defined by the lower and upper bound for the variable, and a type which can be one of ILOFLOAT, ILOINT, or ILOBOOL for continuous, integer, or Boolean variables, respectively. The following constructor creates an integer variable with bounds -1 and 10:

IloNumVar myIntVar(env, -1, 10, ILOINT);

The class IloNumVar provides methods that allow querying of the data needed to specify a variable. However, only bounds can be modified. Concert Technology provides a modeling object class IloConversion to change the type of a variable. This conversion allows you to use the same variable with different types in different models.

Variables are usually used to build up expressions, which in turn are used to define the objective or constraints of the optimization problem. An expression can be explicitly written, as in

1*x[1] + 2*x[2] + 3*x[3]

where x is assumed to be an array of variables (IloNumVarArray). Expressions can also be created piece by piece, with a loop:

IloExpr expr(env);
for (int i = 0; i < x.getSize(); ++i)
expr += data[i] * x[i];

Whenever possible, build your expressions in terms of data that is either integer or double-precision (64-bit) floating point. Single-precision (32-bit) floating point data should be avoided, as it can result in unnecessarily ill conditioned problems. For more information, refer to Numerical Difficulties.

While Concert Technology supports very general expressions, only linear, quadratic, piecewise-linear, and logical expressions can be used in models to be solved with IloCplex. For more about each of those possibilities, see these chapters of this manual:

When you have finished using an expression (that is, you created a constraint with it) you need to delete it by calling its method end, for example:

expr.end();

Declaring the Objective: IloObjective

Objects of class IloObjective represent objective functions in optimization models. IloCplex may only handle models with at most one objective function, though the modeling API provided by Concert Technology does not impose this restriction. An objective function is specified by creating an instance of IloObjective. For example:

IloObjective obj(env,
1*x[1] + 2*x[2] + 3*x[3],
IloObjective::Minimize);

defines the objective to minimize the expression 1*x[1] + 2*x[2] + 3*x[3].

Adding Constraints: IloConstraint and IloRange

Similarly, objects of the class IloConstraint represents constraints in your model. Most constraints will belong to the subclass IloRange, derived from IloConstraint, and thus inherit its constructors and methods. IloRange represent constraints of the form lower bound expression upper bound. In other words, an instance of IloRange is a convenient way to express a ranged constraint, that is, a constraint with explicit upper or lower bounds. Any floating-point value or +IloInfinity or -IloInfinity can be used for the bounds. For example:

IloRange r1(env, 3.0, x[1] + x[2], 3.0);

defines the constraint x[1] + x[2] == 3.0.

Formulating a Problem: IloModel

To formulate a full optimization problem, the objects that are part of it need to be selected. This is done by adding them to an instance of IloModel, the class used to represent optimization problems. For example:

IloModel model(env);
model.add(obj);
model.add(r1);

defines a model consisting of the objective obj, constraint r1, and all the variables they use. Notice that variables need not be added to a model explicitly, as they are implicitly considered if any of the other modeling objects in the model use them. However, variables may be explicitly added to a model if you want.

For convenience, Concert Technology provides the functions IloMinimize and IloMaximize to define minimization and maximization objective functions. Also, operators <=, ==, and >= are overloaded to create IloRange constraints. This allows you to rewrite the above examples in a more compact and readable way, like this:

IloModel model(env);
model.add(IloMinimize(env, 1*x[1] + 2*x[2] + 3*x[3]);
model.add(x[1] + x[2] == 3.0);

With this notation, the C++ variables obj and r1 need not be created.

The class IloModel is itself a class of modeling objects. Thus, one model can be added to another. A possible use of this feature is to capture different scenarios in different models, all of which are extensions of a core model. The core model could be represented as an IloModel object itself and added to the IloModel objects that represent the individual scenarios.