You are on page 1of 31

Linear Programming

MS-E2140

Short introduction to CPLEX® studio

Disclaimer: This tutorial is not a complete introduction to the full features and
potentiality of CPLEX® Optimization Studio. More detailed documentation is
available at http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r5/index.jsp
Features
CPLEX studio is an optimization package which includes
• A modeling development tool: IBM ILOG OPL
• A powerful optimization package: IBM ILOG CPLEX
OPL is a modeling language for optimization problems with intutitive syntax that
facilitates the implementation of mathematical models
CPLEX is one of the state-of-the-art commercial solvers for various types of
optimization problems including:
• Linear programming problems
• Integer and mixed integer prgramming problems
• Quadratic programming problems
CPLEX studio provides a development environment that facilitates the creation
and solution of mathematical programming models and the analysis of the results
Models are independent of the data they use meaning, e.g., that the model code
needs not be changed for solving different instances of the same problem
Resources
A full version of CPLEX studio is installed in the lab machines
A free trial version (90 days evaluation period and with limitations on the
maximum size of solvable problems) is available through the IBM website
http://www-01.ibm.com/software/websphere/products/optimization/cplex-
studio-preview-edition/
Full official documentation is available at
http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r5/index.jsp
Examples. Several examples of projects can be opened and explored within
CPLEX studio. To load them from the start window main menu click:
”File -> Import -> Example...“ (then double click “IBM ILOG CPLEX Examples”)
OPL keywords. From the start window: ”Help -> Search” (type OPL keywords)
OPL functions. From the start window: ”Help -> Search” (type OPL functions)
Creating an empty project
The main working unit in CPLEX studio is the ”project” which groups one or
more models together with data. It is composed of three types of files
• Model files (.mod): data declarations, model definition (decision variables,
objective function, constraints);
• Data files (.dat): Actual values for the data declared in model files;
• Settings files (.ops): Specify changes to the default settings in OPL,
(parameters for the solution algorithm, display options, ...)
To create a new project select ”File -> New -> OPL Project” from the main
window’s menu. Then choose a name and location folder and click ”Finish”.
A project contains one or more ”run configurations” each specifying a model
instance by linking the model with a particular set of data (and, optionally,
settings)
Project name To create new model or data
Run configuration files in a project right-click on
the project name and then
Model file select ”new -> model” or ”new
-> data”
Data file

To create an empty run


configuration right-click on the
”Run Configurations” icon and
then select ”New -> Run
configuration”

To add a file to a run


configuration right-click on the
file name, then select ”Add to
Run Configuration” and
choose the configuration

To remove a file from a


configuration right-click on its
name inside the configuration
and select ”Delete”
A simple project
This section guides you to create a simple project, and to solve the
corresponding optimization problem
We will implement and solve part (b) of Exercise 1.1 from the first
exercise session
Create the project
Start by creating a project with a model file, a data file, and one run
configuration
Data declarations
The first step is to define the data needed by the model in the model
file.
First recall the model to be implemented
𝑀𝑎𝑥𝑖𝑚𝑖𝑧𝑒 𝑧 = 150 𝑥1 + 75𝑥2 − 80 𝑦1 − 125 𝑦2 − 20 𝑦3
s.t.
1.00 𝑥1 + 0.35 𝑥2 ≤ 100 + 𝑦1 Production time of Department A
0.30 𝑥1 + 0.20 𝑥2 ≤ 36 + 𝑦2 Production time of Department B
0.20 𝑥1 + 0.50 𝑥2 ≤ 50 + 𝑦3 Production time of Department C
𝑦1 ≤ 10 Max. overtime of Department A
𝑦2 ≤ 6 Max. overtime of Department B
𝑦3 ≤ 8 Max. overtime of Department C
𝑥1 , 𝑥2 ≥ 0 , 𝑦1 , 𝑦2 , 𝑦3 ≥ 0 Non-negativity
𝑥1 , 𝑥2 integer Integrality

where
𝑦𝑖 : Total number of overtime hours for department 𝑖
𝑥𝑗 : Total number of units produced of product 𝑗
A data specification is called data item and consists of a ”data type”
• Integer (OPL keyword int)
• Real (OPL keyword float)
• String (OPL keyword string)
and a ”data structure” ( scalar, range, set, array, or tuple)
In our model we will need to specify the following data items
Model data Data Data OPL Syntax
type struct.
Set of department names string Set {string} Departments = ...;
Set of product names string Set {string} Products = ...;
Departments manufacturing float 2-d array float Manuf_Time[ ][ ] = ...;
time for each product (matrix)
Departments time capacity float 1-d array float Time_Capacity[ ] = ...;
Products unit revenue float 1-d array float Revenue[ ] = ...;
Max. Departments overtime float 1-d array float Max_Overtime[ ] = ...;
Overtime cost for each Dept. float 1-d array float Overtime_Cost[ ] = ...;
Set data structures
The following is the declaration of the Departments set
{string} Departments = ...;
The curly brackets { } indicate that the structure ”Departments” is a set, and the
keyword string specifies the type of its elements
Array data structures
The following is the declaration of the structure specifying the manufacturing
time for each product
float Manuf_Time[Departments][Products] = ...;
The double brackets [][] indicate that the structure ”Manuf_Time” is a matrix, and
the keyword float specifies the type of its elements
The sets ”Departments” and ”Products” are used to index the array. With this
declaration each element 𝑖, 𝑗 of ”Manuf_Time” is associated with element 𝑖 of the
set ”Departments”, and element 𝑗 of set ”Products”
To define a one dimensional array just put one single pair of brackets []
Note: All declarations (and other instructions) must end with a ”;”
Note that all data declarations ended with the syntax ” = ⋯ ; ”
This indicates that the actual values of the elements in the data item
are not specified in the declaration, but somewhere else (e.g., in the
data file)
-> Double-click on the model file and type the following declarations:
Data initializations
Data items whose declaration ends with the syntax ” = ⋯ ; ” in the
model file can be initialized in the data file
Alternatively data items can be intialized directly in the model file by
replacing ” = ⋯ ; ” with the initialization when they are declared
Set intialization
The following is the initialization of the ”Departments” set
Departments = {”A”, ”B”, ”C”};
The initialization just specifies the element values within the brackets.
Note that the value types must match those defined in the declaration.
In this case, elements are strings, and must be enclosed in ” ”, i.e. the
syntax for any element s of type string is ”s”.
Similarly, we intialize the set Products:
Products = {"Prod_1", "Prod_2"};
Array initialization
For 1-d arrays values of the elements can be simply inserted
inside the brackets separated by commas
The following is the initialization of the ” Time_Capacity” array
Time_Capacity = [100, 36, 50];

Since in the initialization of ”Departments” its elements are


listed in the order A, B, C, the value 100 will be associated with
A, 36 with B, and 50 with C.
For 2-d arrays each row is inserted as it was a 1-d array, and rows
are separated by commas.
The following is the initialization of the ”Manuf_Time” array

Manuf_Time = [[1.00, 0.35], [0.30, 0.20], [0.20, 0.50]];


-> Double-click on the data file and type the following definitions:
Decision variables
Decision variable declarations are similar to those of data items, but do
not require initialization. Variables can be of type:
• Integer (OPL keyword int)
• Real (OPL keyword float)
• Boolean (0 − 1 values, OPL keyword boolean)
In our model we need the following variables
Model decision variable Var. Type Data OPL Syntax
struct.
Total number of overtime hours for float Array dvar float+
each department 𝑖 (𝑦𝑖 ) Overtime_h[Departments];
Total number of manufactured units int Array dvar Int+ Production[Products];
for each product 𝑗 (𝑥𝑗 )

Declaration of variables is similar to that of data items and requires:


a type, a data structure, a name, optionally a domain (range of values)
Declaration of a single variable (a variable 𝑧 not part of our model)
dvar float+ z in 0..100;
• dvar is the keyword used to identify variable declarations,
• the variable type is specified by the keyword float; the optional sign ”+”
indicates that the variable can take only non-negative values
• “in 0..100” specifies that the variable can have only values between 0 and
100 (instead of numbers like 0 and 100 data items can also be used)
Declaration of an array of variables (variables 𝑦𝑖 of our model)
dvar float+ Overtime_h[Departments];

• ”Overtime_h” is the name of the array of variables


• The variable data structure is defined by the brackets as for data items. In
this case, ”Overtime_h” is an array of float variables
• The argument ”Departments” inside the brackets specifies that each
variable in the array is associated with an element of ”Departments”
Note: the keyword ”infinity” specifies the largest possible float number, and
similarly does ”maxint” for integers
-> Add the variable declarations to the model file:
Variable expressions and operators
Decision variables and data items can be combined to define more
complex expressions, constraints, or objective functions
For this we need operators and aggregators to combine different
variables and data items
For example in our model we may want to define the total profit
𝑧 = 150 𝑥1 + 75𝑥2 − 80 𝑦1 − 125 𝑦2 − 20 𝑦3
To do this we can first define the following variable expressions
• dexpr float revenue = sum (j in Products) (150 𝑥1 + 75𝑥2 )
Production[j]*Revenue[j];
• dexpr float cost = sum (i in Departments) (80 𝑦1 + 125 𝑦2 + 20 𝑦3 )
Overtime_h[i]*Overtime_cost[i];
Note: Variable expressions can then be used to defined constraints or
the objective function
Consider the first of the two expressions above:
• dexpr is the OPL keyword used to declare decision expressions
• float is the type of the new decision expression
• The aggregator “sum( ) expression” returns the sum over all the
elements indexed in parenthesis of the following expression
• ”(j in Products)” indexes all items of the set Products,
“Production[j]*Revenue[j]” is the expression summed over all items
• Note that this works because in the their declaration, the arrays
Production and Revenue have both been defined over the set
”Products” (e.g., dvar int+ Production [Products];)
Using the two expressions just defined, we can define the profit
dexpr float profit = revenue - cost;
Note: Don’t multiply two variables in a dexpr as that would yield a
non-linear model! Also, you can’t use the syntax type+ for a dexpr
Indexing with filtering
When indexing the items of a set it is also possible to restrict the
selection according to some criteria. The following are two examples:
sum (i in Departments : Overtime_Cost[i] < 60) Filtering condition
Overtime_h[i]*Overtime _Cost[i];
sum (j in Products : j > “Prod_1”) // selects only elements coming after
Production[j]*Revenue[j]; “Prod_1” in the declaration of Products

Note the use of the sintax ”:” to separate the filtering condition from
the indexing expession inside the parentheses
Common aggregators for integer and float expressions
• sum (summations)
• prod (products)
• minima (min of a collection of related expressions)
• maxima (max of a collection of related expressions)
Objective function
An obj. function consists of a keyword ”maximize” or ”minimize”
followed by an expression to optimize
Since in our model we are maximizing the profit, which we already
defined as a dexpr, we can just write
maximize profit;

Note: It is optional to define an objective function. If you don’t, you


can still solve the model to find just a feasible solution
Constraints
All constraints must be put inside a block starting with the syntax
“subject to {“ and ending with “}”
The quantifier “forall( )” can be used to specify multiple constraints
compactly, each associated with one element indexed in parenthesis.
In our model, we have two types of constraints
Constraints on the maximum production time for each Department
In mathematical notation these could be written compactly as
𝑗∈𝑃 𝑡𝑖𝑗 𝑥𝑗 ≤ 𝑇𝑖 + 𝑦𝑖 , ∀𝑖 ∈ 𝐷

where 𝐷 denotes the set of Departments, 𝑃 the set of products, 𝑡𝑖𝑗 is


the manufacturing time of Dept. 𝑖 for product 𝑗, and 𝑇𝑖 denotes the
time capacity of Dept. 𝑖
In OPL we can translate the above using quantifiers and aggregators:
forall(i in Departments)
sum(j in Products) Manuf_Time[i][j]*Production[j]
<= Time_Capacity[i] + Overtime_h[i];

Constraints on the maximum overtime for each Department


Similarly as above we can write:
forall(i in Departments) Overtime_h[i] <= Max_Overtime[i];
Note: The last constraints on the max. overtime for each Department
actually only express a maximum value each variable 𝑦𝑖 can assume
As mentioned when describing decision variable, the same can be
imposed by specifying a domain when declaring the variables 𝑦
For variables 𝑦 this can be done by changing their declaration to
dvar float+ Overtime_h[i in Departments] in 0.. Max_Overtime[i];

If variables 𝑦 are declared in this way, then the constraints on the max.
overtime for each Department of the previous slide are not needed
-> This is generally a preferable way of specifying maximum (or
minimum) values for a set of variables
Recall that each constraint definition ends with ”;”, and that all
constraints have to be included inside a block like this
subject to{ ... }
-> Add the objective function and constraints to the model file
The model can now be solved
-> Right-click on the run configuration icon and select ”Run this”

Righ-click here and select ”Run this” to solve the model

After the problem is solved the obj. function value will be displayed here

The values of the decision variables and expressions are displayed here,
or alternatively you can click here

The optimal solution is 𝑥1 = 82, 𝑥2 = 80, 𝑦1 = 10, 𝑦2 = 4.6, 𝑦3 = 6.4 with profit 16,797
Other useful commands
Here we briefly examine some other useful features and structures of OPL
that were not used in the previous example

Range data structures


Integer ranges are often used in arrays and decision variable declarations, in
aggregate operators, queries, and quantifiers
An integer range is specified by using the keyword range, and by giving its
lower and upper bounds, as in the example below
range Rows = 1..10;

The above declares a range named “Rows” with bounds 1 and 10 (i.e., the
interval [1, … , 10]). The lower and upper bounds can also be expressions
int n = 8;
range Rows = n+1..2*n+1;
Typical uses of ranges are
as an array index in an array declaration
For example, in our model we could define Departments as a range
rather than a set, and still use it in the declaration of the arrays
range Departments = 1..3;
float Time_Capacity[Departments];
equivalently
float Time_Capacity[1..3];
One advantage over using sets, is that CPLEX does not store explicitly
all the elements of the range, but it does store all elements of a set
to define the domain of a variable
We already discussed how to define the domain of a variable or an
array of variables
as an iteration range
For example, for defining constraints
range Departments = 1..3;
range Products = 1..2;
forall(i in Departments)
sum(j in Products) Manuf_Time[i][j]*Production[j] –
Overtime_h[i] <= Time_Capacity[i];
The syntax is the same as if Departments and Products were sets
One advantage is that now Departments and Products are numbers,
and we can use arithmetic operators in the filtering condition. Example
For a description of operators see the summary at
forall(i in Departments : i mod 2 == 0) the end or official CPLEX studio documentation
sum(j in Products : j < 2 )
Manuf_Time[i][j]*Production[j] –
Overtime_h[i] <= Time_Capacity[i];
More ways of initializing sets
Ranges can be converted into sets by using the keyword ”asSet”
For example, the following declarations (in the model file)
range Departments = 1..3
{int} Departments_Sets = asSet(Departments)

define Departments as the interval [1,...,3] and then a corresponding


set Departments_Sets = {1, 2, 3}
Sets can be initialized as subsets of other sets (in the model file). The
following are two examples:
{string} Departments = {”Dep1”, ”Dep2”, ”Dep3”};
{string} Sub_Departments = {i | i in Departments : i != ”Dep1”};

{int} Departments = asSet(1..3);


{int} Sub_Departments = {i | i in Departments : i > 1};
Some operators (Arithmetic)
Type Operator Description
+,-, * , / Usual math operators
infinity Represents the infinite
abs(f) The absolute value of f
ceil(f) The smallest integer greater than or equal to f
float
floor(f) The largest integer less than or equal to f
trunc(f) The integer part of f
frac(f) The fractional part of f
round(f) The nearest integer to f

Type Operator Description


+,-, * , / Usual math operators
x mod y or x % y The integer remainder of x divided by y
int
abs(f) The absolute value of f
maxint The greatest integer
Some operators (Symbolic)
Type Operator Description
first, last First (last) element in the set list
item The n-th element in the set
card Number of elements in the set
set next, prev Next (previous) element in the set list
a inter b Intersection
a union b Union
a diff b Difference

Type Operator Description


== Equivalent to
string
!= Different from
Some operators (Symbolic)
Type Operator Description
&& Conjunction (logical "and")
|| Disjunction (logical "or")
boolean == Equivalence
!= Difference (exclusive "or")
! Negation (logical "not")

Important
Get used to the help system included in CPLEX studio:
-> Click Help from the main menu and then select ”Search” or
”Help Contents”

You might also like