Cplex安装与环境配置步骤(C++与Python)

2023-09-23 35 0

一、Cplex简介

Cplex是IBM公司的一个优化问题求解器。主要用于求解线性规划,混合整数规划、二次规划等问题。
Cplex求解速度快,使用简单易上手。除了自带的语言外,cplex可以利用C++、Java、Python等语言使用。对于运筹优化方向的问题求解事半功倍。

二、Cplex下载与安装

Cplex可以从官方网站利用电子邮件注册下载,网址如下:
https://www.ibm.com/analytics/cplex-optimizer
社区版的可以随便下载,但是变量个数有限制。
安装完成后可以查看版本,这个是社区版。在这里插入图片描述

三、设置环境变量

1.IBM cplex的官方文档《Getting Started with CPLEX》
网址如下 https://www.ibm.com/support/knowledgecenter/SSSA5P_12.7.1/ilog.odms.studio.help/pdf/gscplex.pdf
初次使用 Cplex 的基础文档,里面包含了如何安装使用Cplex及在不同语言环境下的配置方法。
2.设置环境变量在这里插入图片描述
通过对官方文档的查看,在windows中需要配置环境变量。打开控制面板,win10中可以在设置中搜索打开。总体步骤如下:
控制面板—系统—高级—环境变量—系统变量中查看Path—添加图上路径

在这里插入图片描述
笔者的Cplex装在D盘中,所以路径示例如上。

四、配置VS C++ 2019调用 CPLEX 接口

笔者将大部分时间都耗费在了对VS C++的环境配置中,因为采坑不少,所以在此将过程总结出来,希望可以帮助大家减少试错时间。
1.将调试环境修改为 Release x64
将VS调试环境修改为release, x64. 如图所示。(代码是官方示例,附在文末)

在这里插入图片描述
笔者之前没有注意修改调试环境,次次出错。VS调试环境默认是Debug模式。Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。x86平台编译出来的可执行文件都是32位的。x64对应的则是64位的。Cplex是64位的,所以VS中的环境配置也必须是64位

2.将解决方案属性也修改为 Release x64
在解决方案管理器中右键点击测试文件Cplex的属性,配置为release ,x64。
在这里插入图片描述
3.添加include的路径
在c++中调用cplex,需要让vs知道include的各种路径。
具体的办法是:
属性页面——附加包含目录——编辑——点击带星号的文件夹——增加路径
具体的路径需要根据自己电脑上的cplex安装位置匹配。其实就是两个文件夹路径:
cplex\concert\include
cplex\include
在这里插入图片描述
4.链接库
这一步的目的是让 C++ 的 Linker(链接器) 知道cplex以及 Concert 的库在哪里,以便调用。如下图所示:
在这里插入图片描述
5.添加附加依赖项
在这里插入图片描述
将具体的lib链接进去。
D:\Cplex\concert\lib\x64_windows_msvc14\stat_mda\concert.lib
D:\Cplex\cplex\lib\x64_windows_msvc14\stat_mda\cplex12100.lib
D:\Cplex\cplex\lib\x64_windows_msvc14\stat_mda\ilocplex.lib
具体的路径要根据自己文件所在的位置!!!不要直接copy,不然连接器还是找不到

6.添加预处理器指令
在这里插入图片描述
注意不要敲错,添加之后应用。

7.注意调整代码生成的运行库为 多线程DLL(/MD)
一般是默认的,但是笔者踩坑时就是有过因为代码生成的运行库没有调整,因此也列出来以便查阅。
在这里插入图片描述
以上七步结束后,就可以在vs c++ 2019中调用cplex啦~

可以用官方提供的测试代码试试:

#include <ilcplex/ilocplex.h>
ILOSTLBEGIN
int
main(int argc, char** argv)
{IloEnv env;try {IloModel model(env);IloNumVarArray vars(env);vars.add(IloNumVar(env, 0.0, 40.0));vars.add(IloNumVar(env));vars.add(IloNumVar(env));model.add(IloMaximize(env, vars[0] + 2 * vars[1] + 3 * vars[2]));model.add(-vars[0] + vars[1] + vars[2] <= 20);model.add(vars[0] - 3 * vars[1] + vars[2] <= 30);IloCplex cplex(model);if (!cplex.solve()) {env.error() << "Failed to optimize LP." << endl;throw(-1);}IloNumArray vals(env);env.out() << "Solution status = " << cplex.getStatus() << endl;env.out() << "Solution value = " << cplex.getObjValue() << endl;cplex.getValues(vals, vars);env.out() << "Values = " << vals << endl;}catch (IloException& e) {cerr << "Concert exception caught: " << e << endl;}catch (...) {cerr << "Unknown exception caught" << endl;}env.end();return 0;
}

来源:https://www.ibm.com/support/knowledgecenter/SSSA5P_12.7.1/ilog.odms.studio.help/pdf/gscplex.pdf
第12页

五、在python中调用Cplex

在python中调用Cplex的接口相对比较简单,官方文档里给了两条路径。
在这里插入图片描述
但是相对来说还是比较繁琐,其实本身就是调用cplex的库嘛,直接用pip安装第三方库 cplex就可以了。如果用anaconda的话可以直接在anaconda prompt中安装
在这里插入图片描述
But,笔者在多次安装后都提示失败,没有找到相应的版本,无奈准备用官方的方法时,发现cplex文件夹里只支持python3.6 和3.7 的版本。
在这里插入图片描述
而笔者现在用的python和anaconda的python版本都是3.8,所以屡次报错。当然也不需要重新安装了,回滚到python3.7版本就好啦~

以anaconda 为例,利用python -V命令查看目前python版本:
在这里插入图片描述
笔者这里已经回滚到3.7了,如果是3.8及以上,可以利用

conda install python=3.7

**将anaconda的python版本回滚到3.7。**然后就可以利用pip命令在anaconda中安装cplex库啦~注意新版的anaconda里面是搜不到cplex库的,因为目前cplex 12.10.0.0最高只能支持到python3.7。所以相对而言这是一个比较简便的方法。
在这里插入图片描述
安装完cplex包之后环境就配置好啦~可以利用官方提供的代码示例试试!


```python
execfile("cplexpypath.py")
import cplex
from cplex.exceptions import CplexError
import sys# data common to all populateby functions
my_obj = [1.0, 2.0, 3.0]
my_ub = [40.0, cplex.infinity, cplex.infinity]
my_colnames = ["x1", "x2", "x3"]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "LL"def populatebyrow(prob):prob.objective.set_sense(prob.objective.sense.maximize)# since lower bounds are all 0.0 (the default), lb is omitted hereprob.variables.add(obj = my_obj, ub = my_ub, names = my_colnames)# can query variables like the following bounds and names:# lbs is a list of all the lower boundslbs = prob.variables.get_lower_bounds()# ub1 is just the first lower boundub1 = prob.variables.get_upper_bounds(0)# names is ["x1", "x3"]names = prob.variables.get_names([0, 2])rows = [[[0,"x2","x3"],[-1.0, 1.0,1.0]],[["x1",1,2],[ 1.0,-3.0,1.0]]]prob.linear_constraints.add(lin_expr = rows, senses = my_sense,rhs = my_rhs, names = my_rownames)# because there are two arguments, they are taken to specify a range# thus, cols is the entire constraint matrix as a list of column vectorscols = prob.variables.get_cols("x1", "x3")def populatebycolumn(prob):prob.objective.set_sense(prob.objective.sense.maximize)prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)c = [[[0,1],[-1.0, 1.0]],[["c1",1],[ 1.0,-3.0]],[[0,"c2"],[ 1.0, 1.0]]]prob.variables.add(obj = my_obj, ub = my_ub, names = my_colnames,columns = c)
def populatebynonzero(prob):prob.objective.set_sense(prob.objective.sense.maximize)prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)prob.variables.add(obj = my_obj, ub = my_ub, names = my_colnames)rows = [0,0,0,1,1,1]cols = [0,1,2,0,1,2]vals = [-1.0,1.0,1.0,1.0,-3.0,1.0]prob.linear_constraints.set_coefficients(zip(rows, cols, vals))# can also change one coefficient at a time# prob.linear_constraints.set_coefficients(1,1,-3.0)# or pass in a list of triples# prob.linear_constraints.set_coefficients([(0,1,1.0), (1,1,-3.0)])
def lpex1(pop_method):try:my_prob = cplex.Cplex()if pop_method == "r":handle = populatebyrow(my_prob)if pop_method == "c":handle = populatebycolumn(my_prob)if pop_method == "n":handle = populatebynonzero(my_prob)my_prob.solve()except CplexError, exc:print excreturnnumrows = my_prob.linear_constraints.get_num()numcols = my_prob.variables.get_num()print# solution.get_status() returns an integer codeprint "Solution status = " , my_prob.solution.get_status(), ":",# the following line prints the corresponding stringprint my_prob.solution.status[my_prob.solution.get_status()]print "Solution value = ", my_prob.solution.get_objective_value()slack = my_prob.solution.get_linear_slacks()pi = my_prob.solution.get_dual_values()x = my_prob.solution.get_values()dj = my_prob.solution.get_reduced_costs()for i in range(numrows):print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])for j in range(numcols):print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])my_prob.write("lpex1.lp")if __name__ == "__main__":if len(sys.argv) != 2 or sys.argv[1] not in ["-r", "-c", "-n"]:print "Usage: lpex1.py -X"print " where X is one of the following options:"print " r generate problem by row"print " c generate problem by column"print " n generate problem by nonzero"print " Exiting..."sys.exit(-1)lpex1(sys.argv[1][1])
else:prompt = """Enter the letter indicating how the problem data should be populated:r : populate by rowsc : populate by columnsn : populate by nonzeros\n ? > """r = ’r’c = ’c’n = ’n’lpex1(input(prompt))

来源:https://www.ibm.com/support/knowledgecenter/SSSA5P_12.7.1/ilog.odms.studio.help/pdf/gscplex.pdf
第16页

当然这段python代码还是有些冗杂,后面其实调用的话不需要这么复杂,直接调库,建模,求解就可以啦~

最后感谢各位大佬的经验贴指导!

代码编程
赞赏

相关文章

数商云食品行业解决方案:新技术加持食品行业,为企业快速发展提供有力支撑
星期零斩获2021新消费领域“投资界50强企业”和“中国食品工业创新品牌”奖项
2022-2028年中国食品产业园区行业市场运行格局及发展策略分析报告
工业互联网业务知识
劲牌公司荣获2020年度“中国食品工业协会科学技术奖”特等奖
面试3_:不修改数组找出重复的数字