Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

Section
Column
width300px
Page Tree
root15DOTs60ia13:Tutorial
h1.

The

Java

Interface

to

CPLEX

The

use

of

CPLEX

in

Java

is

based

around

the

class

IloCplex

(documented

[

here

|http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r5/index.jsp?topic=%2Filog.odms.cplex.help%2Frefjavacplex%2Fhtml%2Filog%2Fcplex%2FIloCplex.html]

).

The

basic

idea

is

that

you

create

an

IloCplex

object

for

your

optimization

problem,

then

add

variables,

the

objective,

and

constraints

using

methods

in

the

class

IloCplex.

The

IloCplex

object

can

produce

[

IloNumVar

|http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r5/index.jsp?topic=%2Filog.odms.cplex.help%2Frefjavacplex%2Fhtml%2Filog%2Fconcert%2FIloNumVar.html]

objects

and

their

subclass

[

IloIntVar

|http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r5/index.jsp?topic=%2Filog.odms.cplex.help%2Frefjavacplex%2Fhtml%2Filog%2Fconcert%2FIloIntVar.html]

objects,

when

are

then

used

as

arguments

to

further

methods

from

IloCplex

to

make

the

objective

and

constraints.

The

IloCplex

interface

is

somewhat

pretty confusing.

It

is

very

large,

has

lots

of

redundant

methods,

and

has lots

of

methods

that

appear

to

be

the

same

but

produce

very

different

results.

We

now

summarize

the

methods

of

IloCplex

which

will

be

of

use

to

us:

||Name||Return Type||Arguments||Description|| |boolVar|IloIntVar| |Creates and returns a new Boolean variable (domain

Column
Wiki Markup

Name

Return Type

Arguments

Description

boolVar

IloIntVar

 

Creates and returns a new Boolean variable (domain 0,1).

| |boolVarArray|

boolVarArray

IloIntVar[]

|

int

n

|

Creates

and

returns

an

array

of

n

new

Boolean

variables

(domain

0,1)

| |linearIntExpr|IloLinearIntExpr| |Creates and returns an integer linear expression initialized as 0

linearIntExpr

IloLinearIntExpr

 

Creates and returns an integer linear expression initialized as 0 (zero).

| |addGe|IloRange|IloNumExpr

addGe

IloRange

IloNumExpr e,

double

v

|

Creates

and

returns

a

range

representing

the

constraint

Mathinline
, and adds constraint to model.

addEq

IloRange

IloNumExpr e, double v

Creates and returns a range representing the constraint

Mathinline
, and adds constraint to model.

ge

IloRange

IloNumExpr e, double v

Creates and returns a range representing the constraint

Mathinline
without adding constraint to model.

addMinimize

IloObjective

IloNumExpr e

Creates and returns an objective to minimize the expression and adds it to the invoking model.

sovle

boolean

 

Solves the active model. Returns true if a feasible solution was found

getValue

double

IloNumVar var

Returns the solution value for var.

getValues

double

IloNumVar[] vars

Returns the solution values for each of vars.

getObjVal

double

 

Returns the objective value of the current solution.

Warning
titleWarning
{mathinline} e \geq v{mathinline}| |addEq|IloRange|IloNumExpr e, double v|Creates and returns a range representing the constraint {mathinline} e = v{mathinline}| |addMinimize|IloObjective|IloNumExpr e|Creates and returns an objective to minimize the expression and adds it to the invoking model.| {warning:title=Warning} For an IloCplex cplex, an IloNumExpr e and a double v, calling

For an IloCplex cplex, an IloNumExpr e and a double v, calling

cplex.addGe(e,v)

and

cplex.addGe(v,e)

are

both

allowed

but

do

not

produce

the

same

result!

The

first

gives

the

constraint

{mathinline} e \geq v{mathinline} while the second gives the constraint {mathinline}v \geq e{mathinline}. {warning} {warning:title=Warning} For an IloCplex cplex, an IloNumExpr e and a double v, calling

Mathinline
while the second gives the constraint
Mathinline
.

Warning
titleWarning

For an IloCplex cplex, an IloNumExpr e and a double v, calling cplex.ge(e,v)

and

cplex.addGe(e,v)

are

both

allowed

but

do

not

produce

the

same

result!

While

both

return

an

object

for

the

constraint

{mathinline} e \geq v{mathinline}, only the latter adds the constraint to the model! We will actually have use

Mathinline
, only the latter adds the constraint to the model. We will actually have use cplex.ge(e,v)

later

when

we

add

constraints

through

callbacks

instead

of

adding

them

directly

to

the

model.

{warning} Notice that the various numeric expressions are arguments for these functions. The inheritance relationship between the different classes of numeric expressions is a little complicated, but well designed. They are summarized in the chart below, with an arrow from interface A to interface B if A implements B (is a subinterface, like a subclass). We will use a few method from IloLinearIntExpr to build up sums. ||Name||Return Type||Arguments||Description|| |addTerm|void|IloIntVar v, int c|Adds the new term {mathinline}c\cdot v{mathinline} to a scalar product. This method can create duplicate terms {mathinline} \cdots + a_i * x + ... + a_k * x + \cdots{mathinline} that could be joined to a single term {mathinline}\cdots + (a_i + a_k) * x + \cdots{mathinline}. Duplicates do not generate errors but require more memory and more running time.| The interface for IloLinearNumExpr is similar.

Notice that the various numeric expressions are arguments for these functions. The inheritance relationship between the different classes of numeric expressions is a little complicated, but well designed. They are summarized in the chart below, with an arrow from interface A to interface B if A implements B (is a subinterface, like a subclass).

Gliffy Diagram
sizeM
namecplexNumericExpressionInheritance

We will use a few methods from IloLinearIntExpr to build up sums.

Name

Return Type

Arguments

Description

addTerm

void

IloIntVar v, int c

Adds the new term

Mathinline
to a scalar product. This method can create duplicate terms
Mathinline
that could be joined to a single term
Mathinline
. Duplicates do not generate errors but require more memory and more running time.

The interface for IloLinearNumExpr is similar.

A Short Example

Suppose we want to solve the following IP in CPLEX:

Mathdisplay
 
\begin{aligned} 
&\min & x + 2y + 3z\\ 
&\text{subject to}& x + y + z &\geq 2\\ 
&& x,y,z &\in\{0,1\}
\end{aligned} 

In the file src/main/WarmUps.java, try to solve the above IP inside the method exerciseOne() and print out the values of the variables and the optimal solution. Then run the code. If you are on Linux or Mac, you will probably need to set a virtual machine argument as you did in the installation assignment. You can also look at the installation assignment if you need to see an example.

Toggle Cloak
idEx1Solution
Solution

Cloak
visiblefalse
idEx1Solution

Reading Integer Variable Values from CPLEX

After solving an LP that is integral or an IP, you often want to query a variable and take some action if the variable has value 1.0, and another action if the variable has value 0.0. However, due to the nature of floating point arithmetic, there are often small rounding errors in the values produced by CPLEX. For example, to test if a variable is equal to zero, do not write

Code Block

IloCplex cplex = new IloCplex();
IloIntVar var = cplex.boolVar();
//...
//solve some problem
//...
double val = cplex.getValue(var);
if(val == 0){
  //take some action
}

Instead, you need to allow for a small error, like so:

Code Block

IloCplex cplex = new IloCplex();
IloIntVar var = cplex.boolVar();
//...
//solve some problem
//...
double val = cplex.getValue(var);
if(Math.abs(val) < 0.00001){
  //take some action
}

The level of numerical tolerance and a variety of methods to extract integer values up to a tolerance are provided for you with the following static methods from Util.java

Name

Return Type

Arguments

Description

doubleToBoolean

boolean

double v

Returns true if

Mathinline
, false if
Mathinline
, and throws an exception otherwise. A static filed in the class Util sets
Mathinline
.

Performance Issues Reading Variable Values from CPLEX

Consider the following piece of code you can find in your WarmUps.java:

Code Block

	public static void testSpeed() throws IloException{
		IloCplex cplex = new IloCplex();
		IloIntVar[] variables = cplex.boolVarArray(2000000);
		cplex.addMaximize(cplex.sum(variables));
		cplex.solve();
		{			
			System.err.println("testing group access");
			long startTime = System.currentTimeMillis();
			double sum = 0;
			double[] vals = cplex.getValues(variables);
			for(int i = 0; i < vals.length; i++){
				sum+= vals[i];
			}
			long endTime = System.currentTimeMillis();
			System.err.println("group: " + (endTime-startTime));
			System.err.println(sum);
		}
		{
			System.err.println("testing individual access");
			long startTime = System.currentTimeMillis();
			double sum = 0;
			for(int i = 0; i < variables.length; i++){
				double val = cplex.getValue(variables[i]);
				sum+=val;
			}
			long endTime = System.currentTimeMillis();
			System.err.println("individual: " + (endTime-startTime));
			System.err.println(sum);
		}		
	}

It solves a very simple IP, then compares the amount of time to query the variables one at a time versus the amount of time needed to query all of the variables at once. Adjust the main method to run testSpeed() instead of exercise1(). The result should be surprising! On my machine, the group access took 23 milliseconds, while the individual access took 282 milliseconds, over ten times as long. If the variables were further wrapped in a BiMap (as suggested in the next section), the running time increases to over 500 milliseconds. If we are going to only read the values of the variables once, we wouldn't really care, as a typical IP with 2,000,000 variables takes much longer than half a second to solve. However, if instead we are querying the values of the variables at every node in the branch and bound tree to test for separation (as we will be soon), then these half seconds add up quickly. Know when to optimize.

Warning
Warning
Warning

The method getValue(IloNumVar var) from class IloCplex is much slower than getValues(IloIntVar[] vars).