赞
踩
Cplex是IBM公司的一个优化问题求解器。主要用于求解线性规划,混合整数规划、二次规划等问题。
Cplex求解速度快,使用简单易上手。除了自带的语言外,cplex可以利用C++、Java、Python等语言使用。对于运筹优化方向的问题求解事半功倍。
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++的环境配置中,因为采坑不少,所以在此将过程总结出来,希望可以帮助大家减少试错时间。
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的接口相对比较简单,官方文档里给了两条路径。
但是相对来说还是比较繁琐,其实本身就是调用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 here prob.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 bounds lbs = prob.variables.get_lower_bounds() # ub1 is just the first lower bound ub1 = 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 vectors cols = 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 exc return numrows = my_prob.linear_constraints.get_num() numcols = my_prob.variables.get_num() print # solution.get_status() returns an integer code print "Solution status = " , my_prob.solution.get_status(), ":", # the following line prints the corresponding string print 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 rows c : populate by columns n : 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代码还是有些冗杂,后面其实调用的话不需要这么复杂,直接调库,建模,求解就可以啦~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。