CPLEX 求解过程详解,注释

本代码块是经过注释的,要查看更加精简的,请查看另一篇文章

/* --------------------------------------------------------------------------
 * File: mipex1.c
 * Version 12.4
 * --------------------------------------------------------------------------
 * Licensed Materials - Property of IBM
 * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55
 * Copyright IBM Corporation 1997, 2011. All Rights Reserved.
 *
 * 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);




/* The problem we are optimizing will have 3 rows, 4 columns
   and 9 nonzeros.  */


#define NUMROWS   3
#define NUMCOLS    4
#define NUMNZ      9




int
main (void)
{
/* 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];




   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status;
   int           i, j;
   int           cur_numrows, cur_numcols;


   /* Initialize the CPLEX environment */


   env = CPXopenCPLEX (&status);//打开一个工作环境


   /* Turn on output to the screen */


   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;
   }




TERMINATE:


   /* Free up the problem as allocated by CPXcreateprob, if necessary */


   if ( lp != NULL ) {
      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 */




/* This function fills in the data structures for the mixed integer program:


      Maximize
       obj: x1 + 2 x2 + 3 x3 + x4
      Subject To
       c1: - x1 + x2 + x3 + 10x4  <= 20
       c2: x1 - 3 x2 + x3         <= 30
       c3:       x2       - 3.5x4  = 0
      Bounds
       0 <= x1 <= 40
       2 <= x4 <= 3
      Integers
        x4
      End
 */




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;




TERMINATE:


   if ( status ) {
      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 */






/* This simple routine frees up the pointer *ptr, and sets *ptr to NULL */


static void
free_and_null (char **ptr)
{
   if ( *ptr != NULL ) {
      free (*ptr);
      *ptr = NULL;
   }
} /* END free_and_null */


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要在Pyomo中使用CPLEX求解,你需要先安装CPLEX软件,并配置Pyomo以使用CPLEX求解。下面是安装CPLEX求解的一般步骤: 1. 下载CPLEX软件:访问IBM的官方网站,下载适用于你的操作系统的CPLEX软件。请确保下载与你的操作系统和Python版本兼容的版本。 2. 安装CPLEX软件:按照官方文档提供的说明,运行安装程序,并按照向导中的步骤完成安装过程。确保选择适用于Python的安装选项。 3. 配置环境变量:在安装完成后,你需要将CPLEX的安装路径添加到系统的环境变量中。具体步骤取决于你使用的操作系统。在Windows上,你可以在“控制面板”中找到“系统”>“高级系统设置”>“环境变量”来进行配置。 4. 安装CPLEX Python API:CPLEX提供了Python API,允许Pyomo与CPLEX求解进行交互。你可以使用pip命令来安装CPLEX Python API。在终端或命令提示符中运行以下命令: ``` pip install cplex ``` 这将安装CPLEX Python API,并使其可用于Pyomo。 5. 配置Pyomo以使用CPLEX求解:在Pyomo代码中,你需要指定使用CPLEX求解。在创建Pyomo求解对象时,可以指定使用CPLEX求解。例如: ```python from pyomo.environ import * model = ConcreteModel() # 定义模型和变量 # 创建求解对象并指定CPLEX求解 solver = SolverFactory('cplex') # 求解模型 solver.solve(model) ``` 请注意,如果你在安装CPLEX软件时选择了默认安装路径,Pyomo通常能够自动找到CPLEX求解。 安装和配置CPLEX求解可能会因操作系统和软件版本而有所不同。建议参考IBM的官方文档和支持资源,以获得关于安装和配置CPLEX求解的详细说明。 希望这个回答对你有帮助!如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值