Modeling by columns
Java methods support modeling by columns in this example of a Java application of CPLEX.
While for many examples population by rows may seem most
straightforward and natural, there are some models where population
by columns is a more natural or more efficient approach to implement.
For example, problems with network structure typically lend themselves
well to modeling by column. Readers familiar with matrix algebra may
view the method populateByColumn as producing
the transpose of what is produced by the method populateByRow .
In contrast to modeling by rows, modeling by columns means that the
coefficients of the constraint matrix are given in a column-wise way.
As each column represents the constraint coefficients for a given
variable in the linear program, this modeling approach is most natural
where it is easy to access the matrix coefficients by iterating through
all the variables, such as in network flow problems.
Range objects are created for modeling by column with only their lower and upper bound. No expressions are given; building them at this point would be impossible since the variables have not been created yet. Similarly, the objective function is created only with its intended optimization sense, and without any expression.
Next the variables are created and installed in the existing ranges and objective. These newly created variables are introduced into the ranges and the objective by means of column objects, which are implemented in the class IloColumn. Objects of this class are created with the methods IloCplex.column(ilog.concert.IloLPMatrix lp), and can be linked together with the method IloColumn.and(ilog.concert.IloColumn column) to form aggregate IloColumn objects.
An instance of IloColumn created with the method IloCplex.column(ilog.concert.IloLPMatrix
lp) contains information about how to use this column to introduce a new variable into an
existing modeling object. For example, if obj is an instance of a class that
implements the interface IloObjective, then cplex.column(obj, 2.0) creates an instance of IloColumn containing the information to install a new variable in the expression of the IloObjective object obj with a linear coefficient of 2.0.
Similarly, for rng, a constraint that is an instance of a class that implements the
interface IloRange, the invocation of the method cplex.column(rng, -1.0) creates an IloColumn object containing the information to install a new variable into the expression
of rng , as a linear term with coefficient -1.0.
When you use the approach of modeling by column, new columns are created and installed as
variables in all existing modeling objects where they are needed. To do this with Concert
Technology, you create an IloColumn object for every modeling object in which you want to install a new variable, and
link them together with the method IloColumn.and(ilog.concert.IloColumn column).
For example, the first variable in populateByColumn is created like this:
The three methods model.column create IloColumn objects for
installing a new variable in the objective obj and
in the constraints r0 and r1,
with linear coefficients 1.0 , -1.0,
and 1.0, respectively. They are all linked
to an aggregate column object by the method and.
This aggregate column object is passed as the first argument to the
method numVar, along with the bounds 0.0 and 40.0 as
the other two arguments. The method numVar now
creates a new variable and immediately installs it in the modeling
objects obj, r0,
and r1 as defined by the aggregate column
object. After it has been installed, the new variable is returned
and stored in var[0][0].