1. 需求的出现
- 由于我要做的是混合整数规划问题(MIP),考虑到有现成的求解工具,于是决定使用Cplex来进行计算。
2. 尝试的第一种解决方法——Cplex+yalmip+Matlab
- 首先下载Cplex,现在最新的已经出到了12.9,当然其实版本问题自己看吧。
下载的话可以去官网下载,如果是学生或者教师是有教育版的可供免费下载的,需要注册一下即可。
(https://www.ibm.com/cn-zh/products/ilog-cplex-optimization-studio?mhq=Cplex%20product&mhsrc=ibmsearch_p
这个链接里有学生、教师版。) - yalmip 是一个可以把不同优化器用yalmip自己的语言来进行调用的一个“通用接口器”般的存在,在其官网上有详细的安装介绍,在此不多赘述。官方链接附上:
https://yalmip.github.io/tutorial/installation/
里面有详细的安装方法和例子可供参考,而且据我的同学说有什么问题给作者留言他会耐心解答。 - 在如下链接中也有一些使用上的介绍,不过其实官网上的肯定是最直接的,如果能够看懂的话建议还是去看官网上的tutorial:
http://ravenxrz.ink/2019/05/03/yalmip-usage-learning.html - Matlab不用多说了。
3. Cplex Python API
- 首先附上cplex的使用说明,里面有关于接口的详细描述,包括C++, java等等,当然也有python的。https://www.ibm.com/support/knowledgecenter/SSSA5P_12.8.0/ilog.odms.studio.help/pdf/gscplex.pdf
按照这里面的安装好python下的cplex module以后,就可以参考一下里面几个示例lpex.py。其中lpex1.py是关于人工输入模型的方法的描述,lpex2.py是关于调用.lp文件的描述。
4. 使用文件导入模型并求解
- Cplex Python API +.lp文件导入模型:模型变量过多、约束过多-->手动输入不可能时,可以通过编写模型的文件并使用python程序来调用Cplex、导入模型并求解来实现问题的解决。
- Cplex支持三种文件输入来导入模型,包括LP、MPS和SAV。具体的文件编写规则自己查找,这里附上一个写的很好的LP文件的编写规则的链接:
http://lpsolve.sourceforge.net/5.5/CPLEX-format.htm - 在写好.lp文件以后,可以按前面说的使用lpex2.py来从Terminal里面使用命令行实现问题的求解。
5. 总结
- 之所以后面使用了python Cplex API其实是因Matlab+yalmip+Cplex的组合虽然简单易行,上手特别快,而且在matlab里面使用矩阵真的特别方便,但是有些想象不到的问题会出现。
- 比如我的问题分为大中小三个时,以不同的求解顺序来使用Matlab+yalmip+Cplex求解时,大、中、小三个的求解时间有比较大的区别,也就是说,求解的时间或者说是效率和求解顺序有关(这个就很神了,内心有点不安)。
- 后来在求解一个更大的问题时使用Matlab+yalmip+Cplex又出现的问题——“跑->跑->matlab自动退出,跑->跑->matlab自动退出,...,跑->跑->matlab自动退出”的情况。
- 后面使用python调用API接口,感觉效率比Matlab+yalmip+Cplex更高。
使用中碰到的问题:
- 问题1:Dual infeasible due to empty column 'x4161'.
网上找的解答:Like I said above, this problem occurs if presolve reduces the model to a model with an empty column. You can disable presolve (set CPX_PARAM_PREIND=0) but that will not fix the issue that your model is infeasible. You can use the conflict refiner to analyze the infeasibility of your model. You will have to check with yalmip support to figure out how to do any of this. 即应该是有全零行出现。 - 问题2:Infeasibility row 'c27283': 0 = 1.
解决:出现0等于1的情况了,说明有0等于1这样的约束出现,不可能有可行解。可能是约束哪里写错了。我最后就是找了一下约束中的问题并进行了解决。 - 问题3:raise CplexSolverError(error_string, env, status)
cplex.exceptions.errors.CplexSolverError: CPLEX Error 1464: Line 27618: Identifier/name too long to process.
解决:
This error is due to the fact that an LP file has a maximum length of any line (560)
说明一行的字太长了,在需要的时候在lp文件里面使用'\n'进行分行即可,反正lp文件是可以分行的。
对应问题的一个链接:https://www.ibm.com/developerworks/community/forums/html/threadTopic?id=77777777-0000-0000-0000-000014393504
注:
本文只是个人使用中的一些小小的总结,如果有读者和其他人有更好的方法和更多的经验,欢迎批评指正和分享经验。