Cplex is a mathematical optimization technique. Primarily used to increase efficiency, implement strategies quickly and increase profitability. Cplex provides flexible high-performance optimization procedures to solve linear programming (Linear Programming), quadratic programming (Quadratic Programming), quadratically constrained programming (Quadratically Constrained Programming) and mixed integer programming (Mixed Integer Programming) problems.
Configure Cplex environment reference under Eclipse: Call Cplex environment configuration under Ecplise
Getting started with Java-based Cplex
I. Introduction
At present, there are not many articles or tutorials on solving planning problems based on Java-based Cplex, and beginners can only summarize and explore through official documents and a small number of other programs. I am also working on planning-related projects recently, and here I will share some of my learning experience and coding skills with you.
The interface of the official website is shown in the figure below. You can select the corresponding version of the tutorial on the left according to your Cplex version. When you get started, you can start from Getting Started with CPLEX
the beginning, and then you can browse it casually, but I think the most important part is the following CPLEX Java Reference Manual
, which contains the usage methods and instructions of all APIs:
The ilog.concert
library includes things related to the definition of variables, such as the definition of optimization variables, the definition of expressions, etc.; the ilog.cplex
library includes things related to models, such as the definitions of various models, algorithms, etc. There are many APIs given in the document, but those are the ones that are commonly used. Next, I will introduce the general process and common interfaces of Cplex programming.
2. Getting Started with Cplex
2.1 Program template
The template of the Cplex program is usually as follows, we only need to fill in the corresponding position:
import ilog.concert.*;
import ilog.cplex.*;
public class Cplex{
//类的名字必须跟.java的名字一样
public static void main(String[] args) {
try {
// 1. 创建模型
// 2. 定义优化参数
// 3. 设置目标函数
// 4. 设置约束
// 5. 模型求解及输出
} catch (IloException e) {
System.err.println("Concert exception caught: " + e);
}
}
}
2.2 Create a model
IloCplex cplex = new IloCplex(); // creat a model
2.3 Define optimization parameters
The optimization parameters to be solved are defined here, and the parameter types include single variable, one-dimensional and two-dimensional array types.
//1.单个变量
//1.1 实数型变量
IloNumVar x= cplex.numVar(0, 5);
//1.2 整型变量
IloIntVar x= cplex.intVar(0, 5);
/*括号中的参数表示变量的取值范围,例如该变量的取值范围为0≤x≤5,若不想定义范围可以设置为-Double.MAX_VALUE和Double.MAX_VALUE,表示负无穷到正无穷*/
//2. 一维数组
// 2.1 实数型变量
IloNumVar[] x = cplex.numVarArray(3, 0.0, 5.0);
// 2.2 整型变量
IloIntVar[] x = cplex.intVarArray(3, 0, 5);
/*括号中的参数表示数组的大小、最小值和最大值*/
// 2.3 每个变量设置不同的范围
double[] rg = {
0,5,1,2,4,5}; //每个变量的最小值和最大值
IloNumVar[] a = new IloNumVar[3];
for(int i=0;i<3;i++)
{
a[i] = cplex.numVar(rg[2*i], rg[2*i+1]);
}
/*这种方式就将数组中的三个变量设置了不同的取值范围,分别为0-5,1-2,4-5*/
//3. 二维数组
//3.1 实数型变量
IloNumVar[][] x = new IloNumVar[2][];
for (int i=0; i<2; i++)
{
x[i] = cplex.numVarArray(2, 0.0, 5.0);
}
//3.2 整型变量
IloIntVar[][] x = new IloIntVar[2][];
for (int i=0; i<2; i++)
{
x[i] = cplex.intVarArray(2, 0, 5);
}
/*以上这种方式定义了2行2列的变量,变量范围为0-5,若像设置不同的取值范围,按照一维数组的方式修改即可
2.4 Setting the objective function and constraints
The objective function generally takes the maximum or minimum value of an expression, and the constraint generally sets the value range of an expression. They have one thing in common that they all need to define the expression first, and the way they define the expression is exactly the same.
2.4.1 Defining expressions
As shown in the figure, Expr
the method with the last four letters is the expression type that can be defined:
The official provides different interfaces according to different expression types, including:
interface | describe |
---|---|
PleasureIntExpr/PleasureNumExpr | Base public interface for integer/real expressions |
IloLinearIntExpr/IloLinearNumExpr | Interface for linear expressions of integer/real type variables |
IloLQIntExpr/IloLQNumExpr | General expressions with linear and quadratic terms |
IloQuadIntExpr/IloQuadNumExpr | Quadratic numeric expression of integer/real number type |
You can choose the interface form that suits you according to the type of your expression. For example, my expression x1+2*x2+3*x3
is a linear type, so you can use the interface of a linear expression:
//定义变量
IloNumVar[] x = cplex.numVarArray(3, -5, 5);
IloLinearNumExpr cs= cplex.linearNumExpr();
cs.addTerm(1, x[0]);
cs.addTerm(2, x[1]);
cs.addTerm(3, x[2]);
Each interface provides a lot of methods. You can check the usage and description of each interface in the official documentation.
Although the official provides different interfaces for expressions of different forms, there are certain problems, such as you cannot add quadratic terms to a linear expression, and when the expression is more complex, there is usually more than one type. Therefore, I am more accustomed to using the most basic formula interface IloNumExpr
, in which you can use the addition, subtraction, multiplication, and division in the cplex model library to add any form of expression.
After creating the model first IloCplex cplex = new IloCplex();
, you can cplex.XXX
use various calculation methods in the model. The commonly used methods include:
method | illustrate | method | illustrate |
---|---|---|---|
sum | to sum | diff | Find the difference |
prod | product | abs | absolute value |
With the above four methods, you can basically deal with most of the expressions. For example, the expression above is x1+2*x2+3*x3
represented by the basic public interface as:
IloNumVar[] x = cplex.numVarArray(3, -5.0, 5.0);
double[] a = {
1,2,3};
IloNumExpr cs = cplex.numExpr();
for(int i=0;i<3;i++)
{
cs = cplex.sum(cs,cplex.prod(x[i], a[i]));
}
Although this method increases the amount of code, the readability of the code is enhanced, so I prefer to define expressions in this way.
Let me give another example to find the sum of squares and absolute values of variable x:
IloNumVar[] x = cplex.numVarArray(3, -5.0, 5.0);
IloNumExpr cs1 = cplex.numExpr();
IloNumExpr cs2 = cplex.numExpr();
for(int i=0;i<3;i++)
{
cs1= cplex.sum(cs1,cplex.abs(x[i])); //绝对值之和
cs2= cplex.sum(cs2,cplex.prod(x[i], x[i])); //平方和
}
After the expression is defined, the objective function and constraints can be added.
2.4.2 Define the objective function
Suppose the expression of the objective function after definition is represented by obj:
function | meaning |
---|---|
cplex.addMinimize(obj) | Find the minimum value of obj |
cplex.addMaximize(obj) | Find the maximum value of obj |
2.4.3 Defining Constraints
Assume that the expression for the post-constraint is defined in cs:
function | meaning | function | meaning |
---|---|---|---|
cplex.addEq(cs,a) | cs=a | cplex.addGe(cs,a) | cs≥a |
cplex.addLe(cs,a) | cs≤a | cplex.addRange(a,cs,b) | a≤cs≤b |
After adding the constraints, we can cplex.diff(cs,cs)
clear the expression cs, and then add new expressions in cs.
2.4.4 Empty expressions
Sometimes when defining the objective function and constraints, it is necessary to define a new expression through a loop. It is troublesome to reinitialize the expression each time. At this time, the expression needs to be cleared:
cplex.diff(cs,cs)
cs = cplex.numExpr()
The first method sometimes reports a memory overflow error, so the second method is recommended.
2.5 Model solution and output
The template for model solving and output is as follows:
if (cplex.solve()) {
cplex.output().println("Solution status = " + cplex.getStatus());
cplex.output().println("Solution value = " + cplex.getObjValue());
double[] val = cplex.getValues(x);
for (int j = 0; j < val.length; j++)
System.out.println("x" + (j+1) + " = " + val[j]);
}
cplex.end();
in:
function | meaning |
---|---|
cplex.getStatus() | Get the status of the model solver |
cplex.getObjValue() | Get the value of the objective function |
cplex.getValues(x) | Get the value of the optimization variable |
cplex.end() | end model |
Model solving includes the following states:
state | meaning | state | meaning |
---|---|---|---|
Optimal | found an optimal solution | Feasible | found a working solution |
Infeasible | the model is not feasible | Error | Encountered an error |
Bounded | Model is not unbounded | Unbounded | model is unbounded |
3. Case presentation
import ilog.concert.*;
import ilog.cplex.*;
public class test {
public static void main(String[] args) {
try {
IloCplex cplex = new IloCplex(); // create a model
IloNumVar[] x = cplex.numVarArray(3, -Double.MAX_VALUE, Double.MAX_VALUE);
IloNumExpr cs1 = cplex.numExpr();
for(int i=0;i<3;i++)
{
cs1 = cplex.sum(cs1,cplex.prod(x[i], x[i]));
}
cplex.addMinimize(cs1);
cplex.addEq(cplex.sum(x[0], x[1]),1);
cplex.addEq(cplex.sum(x[0], x[2]),1);
cplex.addEq(cplex.sum(x[1], x[2]),1);
if (cplex.solve()) {
cplex.output().println("Solution status = " + cplex.getStatus());
cplex.output().println("Solution value = " + cplex.getObjValue());
double[] val = cplex.getValues(x);
for (int j = 0; j < val.length; j++)
System.out.println("x" + (j+1) + " = " + val[j]);
}
cplex.end();
} catch (IloException e) {
System.err.println("Concert exception caught: " + e);
}
}
}
The result of the operation is:
The program is relatively simple and will not be described here. You can understand it in conjunction with the content of the second part.
All in all, other people's programs, official documents and official cases are the best tutorials for learning Cplex. I hope you will explore more!