ILOG CPLEX 11.0 Getting Started > Tutorials > Concert Technology Tutorial for C++ Users > The Anatomy of an ILOG Concert Technology C++ Application > Creating a Model: IloModel

After creating the environment, a Concert application is ready to create one or more optimization models. Doing so consists of creating a set of modeling objects to define each optimization model.

Modeling objects, like IloEnv objects, are handles to implementation objects. Though you will be dealing only with the handle objects, it is the implementation objects that contain the data that specifies the optimization model. If you need to remove an implementation object from memory, you need to call the end method for one of its handle objects.

Modeling objects are also known as extractables because it is the individual modeling objects that are extracted one by one when you extract an optimization model to IloCplex. So, extractables are characterized by the possibility of being extracted to algorithms such as IloCplex. In fact, they all are inherited from the class IloExtractable. In other words, IloExtractable is the base class of all classes of extractables or modeling objects.

The most fundamental extractable class is IloModel. Objects of this class are used to define a complete optimization model that can later be extracted to an IloCplex object. You create a model by constructing an object of type IloModel. For example, to construct a modeling object named model, within an existing environment named env, you would do the following:

IloModel model(env);

At this point, it is important to note that the environment is passed as an argument to the constructor. There is also a constructor that does not use the environment argument, but this constructor creates an empty handle, the handle corresponding to a NULL pointer. Empty handles cannot be used for anything but for assigning other handles to them. Unfortunately, it is a common mistake to try to use empty handles for other things.

After an IloModel object has been constructed, it is populated with the extractables that define the optimization model. The most important classes here are:

representing modeling variables; 
defining constraints of the form l <= expr <= u, where expr is a linear expression; and 
representing an objective function. 

You create objects of these classes for each variable, constraint, and objective function of your optimization problem. Then you add the objects to the model by calling

model.add(object);

for each extractable object. There is no need to explicitly add the variable objects to a model, as they are implicitly added when they are used in the range constraints (instances of IloRange) or the objective. At most one objective can be used in a model with IloCplex.

Modeling variables are constructed as objects of class IloNumVar, by defining variables of type IloNumVar. Concert Technology provides several constructors for doing this; the most flexible form is:

IloNumVar x1(env, 0.0, 40.0, ILOFLOAT);

This definition creates the modeling variable x1 with lower bound 0.0, upper bound 40.0 and type ILOFLOAT, which indicates the variable is continuous. Other possible variable types include ILOINT for integer variables and ILOBOOL for Boolean variables.

For each variable in the optimization model a corresponding object of class IloNumVar must be created. Concert Technology provides a wealth of ways to help you construct all the IloNumVar objects.

After all the modeling variables have been constructed, they can be used to build expressions, which in turn are used to define objects of class IloObjective and IloRange. For example,

IloObjective obj = IloMinimize(env, x1 + 2*x2 + 3*x3);

This creates the extractable obj of type IloObjective which represents the objective function of the example presented in Introducing ILOG CPLEX.

Consider in more detail what this line does. The function IloMinimize takes the environment and an expression as arguments, and constructs a new IloObjective object from it that defines the objective function to minimize the expression. This new object is returned and assigned to the new handle obj.

After an objective extractable is created, it must be added to the model. As noted above this is done with the add method of IloModel. If this is all that the variable obj is needed for, it can be written more compactly, like this:

model.add(IloMinimize(env, x1 + 2*x2 + 3*x3));

This way there is no need for the program variable obj and the program is shorter. If in contrast, the objective function is needed later, for example, to change it and reoptimize the model when doing scenario analysis, the variable obj must be created in order to refer to the objective function. (From the standpoint of algorithmic efficiency, the two approaches are comparable.)

Creating constraints and adding them to the model can be done just as easily with the following statement:

model.add(-x1 + x2 + x3 <= 20);

The part -x1 + x2 + x3 <= 20 creates an object of class IloRange that is immediately added to the model by passing it to the method IloModel::add. Again, if a reference to the IloRange object is needed later, an IloRange handle object must be stored for it. Concert Technology provides flexible array classes for storing data, such as these IloRange objects. As with variables, Concert Technology provides a variety of constructors that help create range constraints.

While those examples use expressions with modeling variables directly for modeling, it should be pointed out that such expressions are themselves represented by yet another Concert Technology class, IloExpr. Like most Concert Technology objects, IloExpr objects are handles. Consequently, the method end must be called when the object is no longer needed. The only exceptions are implicit expressions, where the user does not create an IloExpr object, such as when writing (for example) x1 + 2*x2. For such implicit expressions, the method end should not be called. The importance of the class IloExpr becomes clear when expressions can no longer be fully spelled out in the source code but need instead to be built up in a loop. Operators like += provide an efficient way to do this.