数学建模神器——Cplex求解器入门
之前我在CSDN写过一篇采用Matlab调用Cplex文章,有7000多的阅读量,超过10个以上的人私聊我,询问问题,索要代码(都是无偿的)。于是我觉得这可能是很多工科研究生或者想要参加数学建模的人需要学习的,而且关键的是网上很难找到Cplex的完整运行的代码,我也是根据实验室祖传代码学习。因此想把他分享给各位,会附上代码和具体的例子供各位学习,不懂的话可以找我讨论,不过本人不搞组合优化很久(已经还给老师了),可能知识不足,请多多见谅。
既然是求解器,那么肯定有问题了,我们举一个经典的组合优化问题为例,介绍该求解器的使用方法。本文种的例子是RCPSP(资源受限的项目调度)问题,这是一个超级经典的项目调度问题,经典程度堪比旅行商问题,同时也是一个NP问题。
首先,我们来介绍下这个问题:
上面的就是RCPSP的完整介绍和数据建模方法,接下来就是怎么使用Cplex求解,采用Matlab调用Cplex网上还是有不少的介绍,本文主要介绍的是Cplex在matlab种的语法。话不多说,直接上代码(代码是换了一种建模方式写的,主要是决策变量换了,逻辑不变,如果转化不过来的同学可以看我的博客,上面有与下面求解代码对应的建模方式)。
1% CPLEX matlab上实现
2% a cplex code of RCPSP on matlab
3function solution=cplex_function()
4% 定义的全部变量,储存项目信息
5global Case
6% 假设的时间最大值
7H=sum(Case.dur);
8% 定义变量 bin是0 1 值 full代表是满的矩阵,非稀疏矩阵
9x=binvar(Case.job_count,H,'full');
10% 资源上限,是常数
11r=Case.Con_R;
12% 定义中间变量 int 是整数值,可以是任意整数
13C=intvar(1);
14% 目标函数
15Objective=min(C);
16
17 % 约束
18Constraints=[];
19% 作业时间约束
20% dur 代表作业持续时间
21x2=sum(x,2);
22for i=1:Case.job_count
23 Constraints=[Constraints,x2(i)==Case.dur(i)];
24end
25for j=1:Case.job_count
26 for i=1:H
27 Constraints=[Constraints,x(j,i)*i<=C];
28 end
29end
30
31% prec代表作业间约束
32% 紧前紧后约束
33for j=2:Case.job_count
34 Pjj=[];
35 for jj=1:j
36 if(jj~=j && Case.prec(jj,j)==1)
37 Pjj=[Pjj jj];
38 end
39 end
40 for index=1:length(Pjj) %对于任意一个j的紧前任务
41 for d=1:H
42 last=0;
43 for dd=1:d-1
44 last=last+x(Pjj(index),dd);
45 end
46 Constraints=[Constraints,Case.dur(Pjj(index))*x(j,d)<=last];
47 end
48 end
49end
50% 作业工期约束
51% for j=1:Case.job_count
52% for d=1:Cases.Times
53% Constraints=[Constraints,d*x(j,d)<=Paras.T];
54% end
55% end
56% 作业不可中断
57for j=1:Case.job_count
58 for d=1:H-1
59 dur_instant=0;
60 for q=d+2:H
61 dur_instant=dur_instant+x(j,q);
62 end
63 Constraints=[Constraints,Case.dur(j)*x(j,d)-Case.dur(j)*x(j,d+1)+ dur_instant<=Case.dur(j)];
64 end
65end
66% 资源约束
67% r代表给定资源数
68for k=1:4
69 for d=1:H
70 total_alloc=0;
71 for j=1:Case.job_count
72 total_alloc=total_alloc+x(j,d)*Case.res(j,k);
73 end
74 Constraints=[Constraints,total_alloc<=r(k)];
75 end
76end
77Constraints=[Constraints,0<C<H]; %目标函数C的约束
78% 约束构建好了接下来是求解过程,所有的都一样
79options = sdpsettings('solver','cplex','showprogress',1,'verbose',2);
80% 这是最大求解时间
81options.cplex.MaxTime=36000;
82options.cplex.NodeDisplayInterval=1;
83sol=optimize(Constraints,Objective,options);
84if strcmp(sol.info,'Successfully solved (CPLEX-IBM)')==true
85 solution.Objective=value(Objective);
86 display(solution.Objective);
87 solution.feasibility='feasible'
88 solution.info=sol.info;
89 solution.x=value(C);
90 for j=1:Case.job_count
91 for t=1:H
92 if(double(x(j,t))==1)
93 solution.st(j)=t;
94 break;
95 end
96 end
97 end
98
99elseif strcmp(sol.info,'Maximum iterations or time limit exceeded (CPLEX-IBM)')==true
100 solution.Objective=value(Objective);
101 display(solution.Objective);
102 solution.feasibility='unknown';
103 solution.info=sol.info;
104else
105 solution.feasibility='infeasible';
106 solution.solvertime=sol.solvertime;
107 solution.x=value(C);
108end
从上面代码可看到,从第7行到15行,主要定义的是变量和目标函数,从第17行到第76行就是搭积木的方式把数学公式转化为代码的形式,只要建模没有问题,那么一定可以求解的。79到82行就是进行求解,最后面的就是按照想要的形式输出变量和求解结果。
关于matlab调用Cplex求解RCPSP问题的讲解就饿到此结束了,如果想学习的朋友可以关注公众号私聊我,免费赠与可运行的完整代码。另外科普一下,如果有些朋友喜欢用python,又要用求解器,那么推荐使用Gurobi,学生可以免费申请使用,并且有学习文档,语法与Cplex语法极为相似。
欢迎加入ChallengeHub学习交流群:
同时也可以加我微信号进入我们的微信交流群,群内定期更新各种春招,内推消息。