CPLEX Studio, Engine & OPL Kickstart for Optimization

Introduction to CPLEX Studio, Engines and OPL

We will hear different terms for CPLEX Studio. The official name of the product that we download and install is IBM ILOG CPLEX Studio. CPLEX Studio is an integrated development environment (IDE) that enables us to develop, run, analyze and test the models. The IDE also contains utilities for file management, information on the models, reporting, and other useful functions.

To download and install CPLEX Studio, please check the end of this blog: IBM ILOG CPLEX Optimization Studio Setup.

Within this IDE, we will write our mathematical model in the modeling language called OPL (Optimization Programming Language). Other examples of modeling language are AMPL, Mosel and GAMS. OPL is a modeling language for describing (and solving) optimization problems. It is a syntax that is close to the mathematical formulation, thus making it easier to make the transition from the mathematical formulation to something that can be solved by the computer.

When we hit the Run button, the model compiles and is sent to an optimization engine for solving. This engine is called the CPLEX Optimizer engine, that finds solutions to models that require mathematical programming techniques (the linear or integer programming calculations). CPLEX was originally named as the Simplex method implemented on the C Language. The Simplex Optimizer available in CPLEX Studio uses the revived Simplex algorithm, with a number of improvements. Besides the CPLEX Optimizer engine, CPLEX Studio includes CP Optimizer engine, (CPO), to find solutions to models that require constraint programming techniques. It can actually do more calculations, but that is beyond this tutorial.

Problem 1 Revisted with CPLEX/OPL

The Problem 1 is a simple example with only 2 variables, which are 2 kinds of trucks. In reality, real business problems in real companies can contain up to thousands or more variables. Solving it graphically is totally impossible. With modern tools, like CPLEX, companies can tackle more complex real-world problems and the return of investment would not be just RM 100 as in our toy truck problem but millions of dollars.

Create New OPL Project

Create New OPL Project

The first step to solve optimization problems in CPLEX studio is to create a project. To create a new project, go to

File > New > OPL Project

The New Project wizard is displayed. Enter a project name and specify the project location. A folder with the project name is then created in this directory. We can enter a description for the project.

Even though the only mandatory component in a project is a model file, we will check all the options (Add a default Run Configuration, Create Model, Create Settings, and Create Data) and click “Finish” button. Don’t worry about these yet. We’ll explain them later.

TICK “Add a default Run Configuration” TICK “Create Model” TICK “Create Settings” TICK “Create Data”

The project is created and your project folder with various files appears in the OPL Projects Navigator (left panel).

A CPLEX project consists of:

  • model files (.mod): where we build our model.
  • data files (.dat): Although some data might be initialized internally in the model file, data files are necessary to load data from an external data source, such as an Excel spreadsheet.
  • setting files (.ops): to specify changes to the default settings.

Workspace with comments

Once a project is created, you can still add new .mod files, .dat files, .ops files and run configurations by going to the main menu and choosing File > New > …. This allows us to test for example multiple models on one data set. After creating a new run configuration, you can drag the relevant model file and any data file or setting file to the new run configuration in the OPL Projects Navigator.

OPL Model

Building a model in OPL is similar to building models in other programming languages. You first declare the variables and then define functions for those variables. OPL is a language for building optimization models, so it is not surprising that it is structured to set up mathematical optimization problems. You can declare sets, input variables, and decision variables. These three different types of variables need to be declared in different ways. You then set up the objective function, followed by the constraints.

For a reference, here is the mathematical formulation of this problem.

Minimize: Cost = 500(truck40) + 400(truck30) Subject to:

  1. Boxes: 40(truck40) + 30(truck30) $\geq$ 300
  2. truck40 $\geq$ 0, truck30 $\geq$ 0

This can be translated to the following OPL model file (.mod):

/*********************************************
 * OPL 12.9.0.0 Model
 * Author: kafechew
 * Creation Date: 25 Aug 2019 at 8:28:14 PM
 *********************************************/

// Decision Variables
dvar int+ truck40;
dvar int+ truck30; 

// Objective Function
minimize 500 * truck40 + 400 * truck30;

// Constraints
subject to {
    MinimumCapacityforBoxes:
    40 * truck40 + 30 * truck30 >= 300;
}

Comments

On the main panel, you will see the workspace with the .mod file opened. CPLEX Studio automatically creates comments at the top of this file (Lines 1-5). The comments start with a / and end with a /. The asterisks * at the start of each of the lines are optional and just make the comments look nicer.

// can also be used for single row comment. It is always a good practice to add comments to help us remember what the model is meant to do.

Declaring the Decision Variables

First, we need to define the two decision variables (Lines 8 and 9). To do this, we use the OPL designsted term dvar to indicate that this is a decision variable. Decision variables can be of type integer (int), real (float) or boolean (boolean). We set both of these variables to int+, declaring a non-negative integer for each decision variable. It is possible to create arrays of decision variables for a specific set.

Since the decision variables are the best values to solve a problem, still unknown, we do not specify the values for these variables, there is no = (equal to) sign after the names. The optimization engine will determine the values for these variables and return them as outputs. We give these variables readable names to help making our code more understandable.

Model file are terminated by a semicolon (;), called Statement Terminator.

Objective Function

The objective function (Line 12) is executed as a single command. That is, it starts with the keyword of either minimize or maximize, includes the formulas, and ends with a semicolon (;). The formulas can be complicated, sometimes we will write the objective function over several lines, to make it readable.

Constraints

The constraints (Lines 15-18) start with the keywords subject to {...}. We place all the different constraints within the curly brackets. Each single constraint or constraint family ends with a semicolon. We can name the constraint for post processing purpose.

We do not list the second constraint because we took care of this when we specified the variables.

Launch a Run Configuration

Once we have completed the model, be sure to click on the Save button. To launch a particular run configuration, right-click on the run configuration name in the OPL Projects Navigator and select Run this. When we created the model, a run configuration called Configuration1 was already set up for us.

We can observe that the run configuration consists of our .mod and other files. The little arrows on the .mod and other files indicate that these files just point to the main files. These files are not copies, we are just telling OPL to use the .mod and other files for this run configuration.

An alternative is to use the run button in the execution toolbar on top. It is worth to note that the run button in the execution toolbar always launches the most recently launched run configuration, so pay attention if we have created multiple run configurations.

Once our run configuration has the correct .mod and other files, we are ready to run. Here are some ways:

  • Right click on “run configuration” > New > Run Configuration
  • Drag the model (.mod) into the Configuration
  • Right click on the Configuration > Run this

We can watch the progress at the very bottom right of the window. This model should solve very fast.

When it is done solving, CPLEX Studio displays the optimal solution and the values of decision variables in the Solution tab, at the bottom of the screen. The Problem Browser tab (panel on the bottom left) also displays the data that was input and the solution values of the decision variables. The value of the objective function is shown in the gray bar at the top of this corner. It should show Solution with objective 3,800. If you click on a variable in the Problem Browser tab, an icon appears with the text Show Data View.... If you click on this icon, the values of the variable appear in the main panel. The screenshot below gives an idea of how CPLEX Studio looks like after a run configuration has been launched.

OPL Model and Run Configuration

Separate Data from Model

CPLEX Studio can separate the model (.mod) from the data (.dat). OPL enables a clean separation between the model and the accompanying data. We have put all the coefficients (Line 12 and 17) into the model. However, this would kill the value of a programming language.

First, we extract all the coefficients out of the mathematical equations. This can be translated to the following OPL model file (.mod):

/*********************************************
 * OPL 12.9.0.0 Model
 * Author: kafechew
 * Creation Date: 25 Aug 2019 at 8:28:14 PM
 *********************************************/

// Parameters
int nBoxes = 300;
int capacityTruck40 = 40;
int capacityTruck30 = 30;
float costTruck40 = 500;
float costTruck30 = 400;

// Decision Variables
dvar int+ truck40;
dvar int+ truck30; 

// Objective Function
minimize costTruck40 * truck40 + costTruck30 * truck30;

// Constraints
subject to {
    MinimumCapacityforBoxes: // name of the constraint
    capacityTruck40 * truck40 + capacityTruck30 * truck30 >= nBoxes;
}

We will get the same result with a cost of RM 3800. We can change the number of boxes, capacities and the cost of the two trucks near the Parameters section (Lines 8-12) to solve the same model.

Since it can be reused many times, especially sometimes we will deal with other trucks with different capacities and costs, we should change the names of parameters to be more general. For example, we can change the name of Truck40, originally for the capacity of 40 boxes, into TruckX. Same with Truck30 into TruckY. This can be translated to the following OPL model file (.mod):

/*********************************************
 * OPL 12.9.0.0 Model
 * Author: kafechew
 * Creation Date: 25 Aug 2019 at 8:28:14 PM
 *********************************************/

// Parameters
int nBoxes = 300;
int capacityTruckX = 40;
int capacityTruckY = 30;
float costTruckX = 500;
float costTruckY = 400;

// Decision Variables
dvar int+ truckX;
dvar int+ truckY; 

// Objective Function
minimize costTruckX * truckX + costTruckY * truckY;

// Constraints
subject to {
    MinimumCapacityforBoxes: // name of the constraint
    capacityTruckX * truckX + capacityTruckY * truckY >= nBoxes;
}

So far, we have built the model without any reference to the data. We want to separate the model from the data, so without changing the same model can be solved by swapping different input data near .dat file with little extra effort.

We use ellipsis points ... to indicate that we will define the input values of the parameters somewhere else. This tells the model to look in the .dat file for the values for these variables. The model should look like this now:

/*********************************************
 * OPL 12.9.0.0 Model
 * Author: kafechew
 * Creation Date: 25 Aug 2019 at 8:28:14 PM
 *********************************************/

// Parameters
int nBoxes = ...;
int capacityTruckX = ...;
int capacityTruckY = ...;
float costTruckX = ...;
float costTruckY = ...;

// Decision Variables
dvar int+ truckX;
dvar int+ truckY; 

// Objective Function
minimize costTruckX * truckX + costTruckY * truckY;

// Constraints
subject to {
    MinimumCapacityforBoxes: // name of the constraint
    capacityTruckX * truckX + capacityTruckY * truckY >= nBoxes;
}

In the .dat file, we can directly copy the parameters section, but remove the variable types, and put into it. The syntax is to state the variable name, use the equal to symbol =, specify the data, and then close the statement with the semicolon ;.

/*********************************************
 * OPL 12.9.0.0 Data
 * Author: kafechew
 * Creation Date: 25 Aug 2019 at 8:28:14 PM
 *********************************************/

nBoxes = 300;
capacityTruckX = 40;
capacityTruckY = 30;
costTruckX = 500;
costTruckY = 400;

We can rerun the Configuration1 and get the same result. We can now solve the same model with different parameters without touching the model file (.mod).

Separate Data from Model

Debugging

Since it is nearly impossible to write a model without making a mistake, we need to be familiar with the debugging capability of OPL. Just below the workspace we write the model, we can see a series of tabs. The Problems tab shows any issues with the model real-time. Our current model should show no problems. However, if we change the nBoxes to nBoxes2 (Line 8), we will see an error.

Debugging CPLEX OPL Model

It marks the line with the error and provides a description below. In this case, it tells us that no such variable nBoxes has been defined. It is a good practice to understand how to debug a model. A model shows no syntax errors just means that the model has no OPL errors, but we still need to confirm that the model does what we want it to do.

Next, we will discuss about pulling data from external data sources, such as an Excel spreadsheet or an Access database. As well as using ILOG Script for pre-processing (preparing data) and post-processing (working on the solutions returned by CPLEX) purposes.