/* --------------------------------------------------------------------------
* File: mipex1.c
* Version 12.4
* --------------------------------------------------------------------------
* Licensed Materials - Property of IBM
* 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with
* IBM Corp.
* --------------------------------------------------------------------------
/* mipex1.c - Entering and optimizing a MIP problem */
/* Bring in the CPLEX function declarations and the C library
header file stdio.h with the include of cplex.h. */
#include <ilcplex/cplex.h>
/* Bring in the declarations for the string functions */
#include <string.h>
#include <stdlib.h>
/* Include declaration for function at end of program */
static int
setproblemdata (char **probname_p, int *numcols_p, int *numrows_p,
int *objsen_p, double **obj_p, double **rhs_p,
char **sense_p, int **matbeg_p, int **matcnt_p,
int **matind_p, double **matval_p,
double **lb_p, double **ub_p, char **ctype_p);
static void
free_and_null (char **ptr);
/* Declare pointers for the variables and arrays that will contain
the data which define the LP problem. The setproblemdata() routine
allocates space for the problem data. */
char *probname = NULL;
int numcols;
int numrows;
int objsen;
double *obj = NULL;
double *rhs = NULL;
char *sense = NULL;
int *matbeg = NULL;
int *matcnt = NULL;
int *matind = NULL;
double *matval = NULL;
double *lb = NULL;
double *ub = NULL;
char *ctype = NULL;
/* Declare and allocate space for the variables and arrays where we will
store the optimization results including the status, objective value,
variable values, and row slacks. */
int solstat;
double objval;
double x[NUMCOLS];
double slack[NUMROWS];
status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
//This routine sets the value of a CPLEX parameter of type int.(设置整数变量的参数)
//CPX_PARAM_SCRIND if On --Display messages on screen...(设置是否显示在屏幕上面)
/* Fill in the data for the problem. */
status = setproblemdata (&probname, &numcols, &numrows, &objsen, &obj,
&rhs, &sense, &matbeg, &matcnt, &matind, &matval,
&lb, &ub, &ctype);
//(对数据设置具体的数值)
/* Create the problem. */
lp = CPXcreateprob (env, &status, probname);
/*(创建一个对象)
The routine CPXcreateprob() creates a CPLEX problem object in the CPLEX environment. The arguments to CPXcreateprob() define an LP problem name.
The problem that is created is an LP minimization problem with zero constraints, zero variables, and an empty constraint matrix.
The CPLEX problem object exists until the routine CPXfreeprob() is called.
(用于创建一个问题对象,但是目前是空的,零约束,零变量,空约束矩阵)
To define the constraints, variables, and nonzero entries of the constraint matrix, any of the CPLEX LP problem modification routines may be used.
In addition, any of the routines beginning with the prefix CPXcopy may be used to copy data into the CPLEX problem object.
New constraints or new variables can be created with the routines CPXnewrows() or CPXnewcols(), respectively.
(要定义约束或者矩阵,需要用到CPXnewrows()等函数)
/* Now copy the problem data into the lp */
status = CPXcopylp (env, lp, numcols, numrows, objsen, obj, rhs,
sense, matbeg, matcnt, matind, matval,
lb, ub, NULL);
Description
(复制与约束,目标函数相关的内容)
The routine CPXcopylp() copies data that defines an LP problem to a CPLEX LP problem object.
The arguments to CPXcopylp() define an objective function, the constraint matrix, the right-hand side, and the bounds on the variables.
The CPXcopylp() routine does not copy names. Calling CPXcopylp() destroys any existing data associated with the LP problem object.
The more comprehensive routine CPXcopylpwnames() can be used in place of CPXcopylp() to copy linear programs with associated names.
The arguments passed to CPXcopylp() define a linear program. Note that these arguments are copied into local arrays maintained by CPLEX.
Hence, the LP problem data passed via CPXcopylp() may be modified or freed after the call to CPXcopylp() without affecting the state of the LP problem object.
Synopsis
int CPXcopylp (CPXENVptr env,(cplex 环境)
CPXLPptr lp,(line problem 对象)
int numcols,(column 数目)
int numrows,(rows 数目)
int objsen,(目标最大最小化 1 最小,-1 最大)
double *obj,(目标函数的系数)
double *rhs,(约束条件右边项)
char *sense,(表示不等式的大于 小于 等于 等标识)
int *matbeg,(一下4个参数用于表示约束矩阵)
int *matcnt,
int *matind,
double *matval,
double *lb,(上下限)
double *ub,
double *rngval
Example
status = CPXcopylp (env, lp, numcols, numrows, objsen, obj, rhs,
sense, matbeg, matcnt, matind, matval, lb,
ub, rngval);
/* Now copy the ctype array */
status = CPXcopyctype (env, lp, ctype);
//(复制变量类型)
/* Optimize the problem and obtain solution. */
status = CPXmipopt (env, lp);
(求解问题)
At any time after a mixed integer program has been created via a call to CPXcreateprob(), the routine CPXmipopt() may be used to find a solution to that problem.
solstat = CPXgetstat (env, lp);
(用于求解结果值)
The routine CPXgetstat() is used to access the solution status of the problem after an LP, QP, or mixed integer optimization.
/* Write the output to the screen. */
printf ("\nSolution status = %d\n", solstat);
status = CPXgetobjval (env, lp, &objval);
(用于返回目标函数值)
The routine CPXgetobjval() is used to return the LP or QP solution objective value.
if ( status ) {
fprintf (stderr,"No MIP objective value available. Exiting...\n");
goto TERMINATE;
printf ("Solution value = %f\n\n", objval);
/* The size of the problem should be obtained by asking CPLEX what
the actual size is, rather than using what was passed to CPXcopylp.
cur_numrows and cur_numcols store the current number of rows and
columns, respectively. */
cur_numrows = CPXgetnumrows (env, lp);
cur_numcols = CPXgetnumcols (env, lp);
status = CPXgetx (env, lp, x, 0, cur_numcols-1);
/*(获取结果值)
The routine CPXgetx() is used to access the solution values for a range of problem variables of a linear
or quadratic program. The beginning and end of the range must be specified.
if ( status ) {
fprintf (stderr, "Failed to get optimal integer x.\n");
goto TERMINATE;
status = CPXgetslack (env, lp, slack, 0, cur_numrows-1);
if ( status ) {
fprintf (stderr, "Failed to get optimal slack values.\n");
goto TERMINATE;
for (i = 0; i < cur_numrows; i++) {
printf ("Row %d: Slack = %10f\n", i, slack[i]);
for (j = 0; j < cur_numcols; j++) {
printf ("Column %d: Value = %10f\n", j, x[j]);
/* Finally, write a copy of the problem to a file. */
status = CPXwriteprob (env, lp, "mipex1.lp", NULL);
if ( status ) {
fprintf (stderr, "Failed to write LP to disk.\n");
goto TERMINATE;
status = CPXfreeprob (env, &lp);
if ( status ) {
fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
/* Free up the CPLEX environment, if necessary */
if ( env != NULL ) {
status = CPXcloseCPLEX (&env);
/* Note that CPXcloseCPLEX produces no output,
so the only way to see the cause of the error is to use
CPXgeterrorstring. For other CPLEX routines, the errors will
be seen if the CPX_PARAM_SCRIND indicator is set to CPX_ON. */
if ( status ) {
char errmsg[CPXMESSAGEBUFSIZE];
fprintf (stderr, "Could not close CPLEX environment.\n");
CPXgeterrorstring (env, status, errmsg);
fprintf (stderr, "%s", errmsg);
/* Free up the problem data arrays, if necessary. */
free_and_null ((char **) &probname);
free_and_null ((char **) &obj);
free_and_null ((char **) &rhs);
free_and_null ((char **) &sense);
free_and_null ((char **) &matbeg);
free_and_null ((char **) &matcnt);
free_and_null ((char **) &matind);
free_and_null ((char **) &matval);
free_and_null ((char **) &lb);
free_and_null ((char **) &ub);
free_and_null ((char **) &ctype);
return (status);
} /* END main */
static int
setproblemdata (char **probname_p, int *numcols_p, int *numrows_p,
int *objsen_p, double **obj_p, double **rhs_p,
char **sense_p, int **matbeg_p, int **matcnt_p,
int **matind_p, double **matval_p,
double **lb_p, double **ub_p, char **ctype_p)
char *zprobname = NULL; /* Problem name <= 16 characters */
double *zobj = NULL;
double *zrhs = NULL;
char *zsense = NULL;
int *zmatbeg = NULL;
int *zmatcnt = NULL;
int *zmatind = NULL;
double *zmatval = NULL;
double *zlb = NULL;
double *zub = NULL;
char *zctype = NULL;
int status = 0;
//Malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
zprobname = (char *) malloc (16 * sizeof(char));
zobj = (double *) malloc (NUMCOLS * sizeof(double));
zrhs = (double *) malloc (NUMROWS * sizeof(double));
zsense = (char *) malloc (NUMROWS * sizeof(char));
zmatbeg = (int *) malloc (NUMCOLS * sizeof(int));
zmatcnt = (int *) malloc (NUMCOLS * sizeof(int));
zmatind = (int *) malloc (NUMNZ * sizeof(int));
zmatval = (double *) malloc (NUMNZ * sizeof(double));
zlb = (double *) malloc (NUMCOLS * sizeof(double));//变量的上下限,多少个变量n 就N*sizeof()
zub = (double *) malloc (NUMCOLS * sizeof(double));
zctype = (char *) malloc (NUMCOLS * sizeof(char));//类型
if ( zprobname == NULL || zobj == NULL ||
zrhs == NULL || zsense == NULL ||
zmatbeg == NULL || zmatcnt == NULL ||
zmatind == NULL || zmatval == NULL ||
zlb == NULL || zub == NULL ||
zctype == NULL ) {
status = 1;
goto TERMINATE;
strcpy (zprobname, "example");
/* The code is formatted to make a visual correspondence
between the mathematical linear program and the specific data
items. */
//目标函数系数
zobj[0] = 1.0; zobj[1] = 2.0; zobj[2] = 3.0; zobj[3] = 1.0;
/*这儿4个数组,只需要存储不为零的个数
zmatbeg[]表示每列数据开始在zmatval中的位置
zmatcnt[]统计每列的个数
zmatind[]数组行位置
zmatval[]数据
zmatbeg[0] = 0; zmatbeg[1] = 2; zmatbeg[2] = 5; zmatbeg[3] = 7;
zmatcnt[0] = 2; zmatcnt[1] = 3; zmatcnt[2] = 2; zmatcnt[3] = 2;
zmatind[0] = 0; zmatind[2] = 0; zmatind[5] = 0; zmatind[7] = 0;
zmatval[0] = -1.0; zmatval[2] = 1.0; zmatval[5] = 1.0; zmatval[7] = 10.0;
zmatind[1] = 1; zmatind[3] = 1; zmatind[6] = 1;
zmatval[1] = 1.0; zmatval[3] = -3.0; zmatval[6] = 1.0;
zmatind[4] = 2; zmatind[8] = 2;
zmatval[4] = 1.0; zmatval[8] = -3.5;
//问题的上下限值
zlb[0] = 0.0; zlb[1] = 0.0; zlb[2] = 0.0; zlb[3] = 2.0;
zub[0] = 40.0; zub[1] = CPX_INFBOUND; zub[2] = CPX_INFBOUND; zub[3] = 3.0;
//问题的变量类型,'C'表示连续变量;'I' 表示整数变量
zctype[0] = 'C'; zctype[1] = 'C'; zctype[2] = 'C'; zctype[3] = 'I';
/* The right-hand-side values don't fit nicely on a line above. So put
them here. */
//右边项的表示
zsense[0] = 'L';
zrhs[0] = 20.0;
zsense[1] = 'L';
zrhs[1] = 30.0;
zsense[2] = 'E';
zrhs[2] = 0.0;
free_and_null ((char **) &zprobname);
free_and_null ((char **) &zobj);
free_and_null ((char **) &zrhs);
free_and_null ((char **) &zsense);
free_and_null ((char **) &zmatbeg);
free_and_null ((char **) &zmatcnt);
free_and_null ((char **) &zmatind);
free_and_null ((char **) &zmatval);
free_and_null ((char **) &zlb);
free_and_null ((char **) &zub);
free_and_null ((char **) &zctype);
else {
*numcols_p = NUMCOLS;
*numrows_p = NUMROWS;
*objsen_p = CPX_MAX; /* The problem is maximization */
*probname_p = zprobname;
*obj_p = zobj;
*rhs_p = zrhs;
*sense_p = zsense;
*matbeg_p = zmatbeg;
*matcnt_p = zmatcnt;
*matind_p = zmatind;
*matval_p = zmatval;
*lb_p = zlb;
*ub_p = zub;
*ctype_p = zctype;
return (status);
} /* END setproblemdata */
用OPL语言在CPLEX Studio IDE上解一些较为复杂的线性规划问题时,有时会用到条件约束,在其他语言体系下用 if 可以很简便地表达出来,但在CPLEX Studio IDE里,if 的判断条件不能包括决策变量,带来了很多麻烦,这里提供一种解决方法:
比如当 q[t-1]<=u[t] 时, u1[t] == q[t-1]
我们可以直接表达为:
(q[t-1]<=u[t]) => u1[t] == q[t-1];
\qquad首先指出,在CPLEX的OPL语言中,不支持range定义的范围的取并集运算,但是想要获得不连续的range 范围应该怎样做呢?
2、解决方法
\qquad使用not in将连续范围进行打断,迂回实现取并集的操作。下面通过一段例子来具体结束。
range T1 = 1..4;
range T2 = 7..9;
range T3 = 5..6;
range T4 = 1..9;
dvar int x[T4][T4];
subject to
forall(j in T1)sum
官方中文JAVA手册:https://www.ibm.com/docs/zh/icos/12.9.0?topic=application-structure
cplex是IBM开发的一款线性规划问题的求解器。
一、适用范围
cplex适用于求解的问题类型:
CPLEX的适用范围:
1.适用于一般的线性规划(LP)问题.
2.CPLEX 还可对 LP 的多个扩展求解:
2.1.网络流问题,是 LP 的一种特殊情况,CPLEX 可以通过利用问题结构以快得多的速度对其求解。
文章目录1. 什么是分段线性函数2. Ilog CPLEX 表示 Piecewise Function 分段线性函数3. java Cplex 表示分段线性函数4. matlab/gurobi 中的分段线性函数
1. 什么是分段线性函数
Piecewise func...
00 前言前面我们已经搭建好cplex的java环境了,相信大家已经跃跃欲试,想动手写几个模型了。今天就来拿一个TSP的问题模型来给大家演示一下吧~CPLEX系列教程可以关注我们的公众号哦!获取更多精彩消息!01 TSP建模关于TSP建模,就不多解释了。以及什么是TSP问题,也不要问我了。直接贴一个现成的模型出来吧。02 程序框架整个程序框架如图,app下是调用cplex的主要package。其中...
从两天前开始接触CPLEX的OPL语言,各种错误不断,但网上参考资料又很少。本博文基于自己的摸索,汇总部分基础语法,以备不时之需。以TSP为例。
关键词 range 表示一个范围,使用范例:range city=0..CityNum-1; 表示定义了一个city的变量,取值是0到CityNum-1,其中CityNum是我在此之前定义的int型变量,表示城市数量。
关键词 dvar 表示变量。其...
我正在构建一个CPLEX模型(类似VRP) . 在模型约束之一中,我迫使从仓库到我拥有的每组不同客户的初始流程,至少足以应对集合客户的需求 .因此,假设我有 n 不同的 I[i] 集, i = 1..n . 然后,对于每个 I[i] ,如果电弧经过,那么离开仓库到 I[i] 中每个元素的弧的总和将被计为卡车的容量,例如 Q . 因此,上述总和应大于或等于需求的总和,例如 I[i] 为每个客户 ...
CPLEX是一种数学优化技术。主要用于提高效率、快速实现策略并提高收益率。使用 WebSphere ILOG CPLEX 的数学优化技术可以就资源的高效利用做出更佳决策。使用 CPLEX,可以将复杂的业务问题表现为数学规划 (Mathematic Programming) 模型。高级优化算法使您能够快速找到这些模型的解决方案。提示:以下是本篇文章正文内容。
这个错误呢查了ibm knowledge center显示如下:
里面讲了一堆想必大家也懒得去看了,我来讲讲这类问题的解决方案吧~出现这个错误的原因不是编程上的问题,而是建模方式上的问题。简单来说就是目标函数或者约束上出现了非线性的数学表达式。
那么什么是线性和非线性呢?我这里引一下百度知道上一个非常通俗易懂的解释:
两个变量之间的关系是一次函数关系的——图象是