2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解

2020年全国大学生数学建模竞赛B题 穿越沙漠
2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解_第1张图片
2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解_第2张图片
题目是讲玩家在不同地图下穿越沙漠,所获得的资金数要最多(大概是这个意思)。然后通过文章的描述又总结了N个约束条件。整体的思路就是对资金最大化作为目标函数在给定约束,利用具体(已知)条件,进行单目标优化。
总的分三小问:
第一问:玩家在已知每天天气条件下,对地图1和2进行路径规划。
第二问:玩家在未知每天天气条件下,对地图3和4进行路径规划。
第三问:多个玩家游戏,讨论已知天气条件(地图5)和未知天气条件(地图6)的合理决策。
每个地图在Result.xls附录中给出了具体的信息,其中包括:

地图拓扑结构,初始购买金额限值,负重限制,日期限值,不同天气对当日物资消耗的影响。
玩家总的思路就是从起点去往终点,在路途中确定当天合适的决策(移动/停留),物资不能消耗殆尽(不能饿死也不能渴死)。如果选择在矿山停留可以选择挖矿,经过村落可以通过资金进行补给,最后到达终点时使剩余资金最大化。
确定好思路后,就可以开始建模了。
主要考虑四大部分:
已知条件、决策变量、约束条件、目标函数
1.已知条件:
前两问给出了已知的天气情况,这里用 w i w_i wi表示第 i i i天的天气:
w i = { 1 2 3 晴朗 高温 沙暴 w_i=\left\{ \begin{array}{c} 1\\ 2\\ 3\\ \end{array} \right. \begin{array}{c} \text{晴朗}\\ \text{高温}\\ \text{沙暴}\\ \end{array} wi=123晴朗高温沙暴
2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解_第3张图片
根据题目给出的已知信息,可以知道对应基础水和食物的消耗量分别为:
p i = { 5 8 10 w i = 1 w i = 2 w i = 3    q i = { 7 6 10 w i = 1 w i = 2 w i = 3 p_i=\left\{ \begin{array}{c} 5\\ 8\\ 10\\ \end{array} \right. \begin{array}{c} w_i=1\\ w_i=2\\ w_i=3\\ \end{array}\,\, q_i=\left\{ \begin{array}{c} 7\\ 6\\ 10\\ \end{array} \right. \begin{array}{c} w_i=1\\ w_i=2\\ w_i=3\\ \end{array} pi=5810wi=1wi=2wi=3qi=7610wi=1wi=2wi=3
2.决策变量:
初始食物和水的购买量:X,Y均为正整数
村落食物和水的补给量:CX,CY均为正整数
当日行动决策变量均为0-1变量:
x j k i = { 1  第 i 天从地方 j 走向地方 k 0  其他       z 1 i = { 1  停留 0  行走       z 2 i = { 1  挖矿 0  不挖矿       z 3 i = { 1  购买物资 0  不购买物资 x_{jk}^{i}=\left\{ \begin{array}{c} 1 \text{ 第}i\text{天从地方}j\text{走向地方}k\\ 0 \text{ 其他}\\ \end{array} \right. \\ \,\, \\ \,\,z1_i=\left\{ \begin{array}{c} 1 \text{ 停留}\\ 0 \text{ 行走}\\ \end{array} \right. \,\, \\ \,\, \\ z2_i=\left\{ \begin{array}{c} 1 \text{ 挖矿}\\ 0 \text{ 不挖矿}\\ \end{array} \right. \,\, \\ \,\, \\ z3_i=\left\{ \begin{array}{c} 1 \text{ 购买物资}\\ 0 \text{ 不购买物资}\\ \end{array} \right. xjki={1 i天从地方j走向地方k0 其他z1i={1 停留0 行走z2i={1 挖矿0 不挖矿z3i={1 购买物资0 不购买物资
3.约束条件
物资(水和食物)的重量限制和初始资金限制:
{ w e i g h t = 3 X + 2 Y ⩽ 1200 c o s t = 5 X + 10 Y ⩽ 10000 \left\{ \begin{array}{c} weight=3X+2Y\leqslant 1200\\ cost=5X+10Y\leqslant 10000\\ \end{array} \right. {weight=3X+2Y1200cost=5X+10Y10000
对于移动我们只能在相邻的区域之间进行移动,因此我们需要通过matlab对图区域之间的接壤情况列出距离矩阵 d i j d_{ij} dij
d i j = { 1 0 区域 i 与区域 j 接壤 不接壤 d_{ij}=\begin{cases} 1\\ 0\\ \end{cases}\begin{array}{c} \text{区域}i\text{与区域}j\text{接壤}\\ \text{不接壤}\\ \end{array} dij={10区域i与区域j接壤不接壤
列出距离矩阵后,对决策变量进行限制,使玩家只能在相邻区域之间进行移动:
x j k i ⩽ d j k {x_{jk}^{i}}\leqslant d_{jk} xjkidjk
每天的决策只能有一个,要么在某地停留要么移动,因此有约束条件:
∑ j = 1 N ∑ k = 1 N x j k i = 1 \sum_{j=1}^N{\sum_{k=1}^N{x_{jk}^{i}}}=1 j=1Nk=1Nxjki=1
首先第1天要从起点1开始出发去往某地k,于是便有:
∑ k = 1 N x 1 k 1 = 1 \sum_{k=1}^N{x_{1k}^{1}}=1 k=1Nx1k1=1
其次我们需要保证路径是连续的,因此当天的出发地要是前一天的目的地:
∑ j = 1 N x j k i    = ∑ j = 1 N x k j i + 1 \sum_{j=1}^N{x_{jk}^{i}}\,\,=\sum_{j=1}^N{x_{kj}^{i+1}} j=1Nxjki=j=1Nxkji+1
最后需要某一天抵达终点,因此需要保证:
∑ i = 1 n ∑ k = 1 N − 1 x k N i = 1 \sum_{i=1}^{n}{\sum_{\begin{array}{c} k=1 \end{array}}^{N-1}{x_{kN}^{i}}}=1 i=1nk=1N1xkNi=1
到达终点停止,若到达终点,未满30天,后面的天数则视为在终点处停留,不消耗物资,资金数也不发生变化:
∑ j = 1 N x j    27 i − x 2727 i + 1 = 0 \sum_{j=1}^N{x_{j\,\,27}^{i}-x_{27 27}^{i+1}}=0 j=1Nxj27ix2727i+1=0
如果第 i i i天想在某地 j j j停留则可以表示为: x j j i = 1 x_{jj}^{i}=1 xjji=1,那么表示停留/行走的0-1变量 z 1 i z1_i z1i就需要满足表达式:
z 1 i = ∑ j = 1 N x j j i z1_i=\sum_{j=1}^N{x_{jj}^{i}} z1i=j=1Nxjji
题目给定的额外条件有:
沙暴天气一定得停留:
w i − ∑ j = 1 n x j j i ⩽ 2 w_i-\sum_{j=1}^n{x_{jj}^{i}}\leqslant 2 wij=1nxjji2
停留矿山可以挖矿,设矿山为 m m m则有:
z 2 i ⩽ x m m i z2_i\leqslant x_{mm}^{i} z2ixmmi
途径村落可以购买物资,设村庄为 t t t则有:
z 3 i ⩽ ∑ j = 1 N x t j i + x j t i z3_i\leqslant \sum_{j=1}^N{x_{tj}^{i}+x_{jt}^{i}} z3ij=1Nxtji+xjti
决策所产生的资金变化:
a.挖矿收益:
r i = { 0 1000 z 2 i = 1 z 2 i = 0 r_i=\left\{ \begin{array}{c} 0\\ 1000\\ \end{array} \right. \begin{array}{c} z2_i=1\\ z2_i=0\\ \end{array} ri={01000z2i=1z2i=0
b.物资购买为初始地的两倍价格。
最后得出的每天资金减少量为: c l o s s i = 10 c X i + 20 c Y i − r i closs_i=10cX_i+20cY_i-r_i clossi=10cXi+20cYiri
剩余资金: r e w a r d i = 10000 − c o s t − ∑ q = 1 i − 1 c l o s s q reward_i=10000-cost-\sum_{q=1}^{i-1}{closs_q} rewardi=10000costq=1i1clossq
决策后所剩余的水和食物必须充足,满足生存条件,同时资金限制和重量限制也需要满足:
10000 − c o s t − ∑ q = 1 i − 1 c l o s s q ⩾ c l o s s i 1200 − w e i g h t − ∑ q = 1 i − 1 w l o s s q ⩾ w l o s s i \\ 10000-cost-\sum_{q=1}^{i-1}{closs_q}\geqslant closs_i \\ 1200-weight-\sum_{q=1}^{i-1}{wloss_q}\geqslant wloss_i 10000costq=1i1clossqclossi1200weightq=1i1wlossqwlossi
每天水和食物的消耗量计算公式:
y X i = { p i b i 0       未抵达终点 抵达终点    y Y i = { q i b i 0    未抵达终点 抵达终点 yX_i=\left\{ \begin{array}{c} p_ib_i\\ 0\\ \end{array} \right. \,\,\begin{array}{c} \,\,\text{未抵达终点}\\ \text{抵达终点}\\ \end{array}\,\,yY_i=\left\{ \begin{array}{c} q_ib_i\\ 0\\ \end{array} \right. \begin{array}{c} \,\,\text{未抵达终点}\\ \text{抵达终点}\\ \end{array} yXi={pibi0未抵达终点抵达终点yYi={qibi0未抵达终点抵达终点
其中倍数 b i b_i bi的计算公式为:
b i = { 1 2 3 停留 移动 挖矿 b_i=\left\{ \begin{array}{c} 1\\ 2\\ 3\\ \end{array} \right. \begin{array}{c} \text{停留}\\ \text{移动}\\ \text{挖矿}\\ \end{array} bi=123停留移动挖矿
4.目标函数:
剩余物资半价回收处理:
max ⁡ f = r e w a r d 30 + 5 f o o d 30 + 2.5 w a t e r 30 \max f=reward_{30}+5food_{30}+2.5water_{30} maxf=reward30+5food30+2.5water30
LINGO编程求解:

model:
sets:
a1/1..27/;
a2(a1,a1):d;
!d是由题目给出的拓扑图所获得的相邻矩阵关系,d(j,k)=1表示区域j和k相邻,否则不相邻;
a3/1..30/:cX,cY,yY,yX,w,z1,z2,z3,b,r,aX,aY,kk,wuzi,shui;
!cX cY是村庄购买食物和水的量,yX,yY是食物和水对应天气所需要的消耗量,w代表天气 1 2 3分别为晴朗、高温和沙暴;
!z1,z2,z3代表移动、挖矿、购买的决策变量,b是z1、z2、z3决策所造成的倍数:移动是2 停留是1 挖矿是3,r是挖矿收益,若挖矿则收益为1000,aX、aY每天食物和水的消耗量;
!kk代表剩余资金,wuzi为剩余食物,shui剩余水;
a4(a3,a1,a1):x;!x(i,j,k)=1表示第i天从j点去往k点;
a5(a3,a1);
endsets

x1>0;
y1>0;
@gin(x1);
@gin(y1);
!起始点购买水和物资的数量大于0且为整数;

@for(a3(i):@bin(z1(i)));
@for(a3(i):@bin(z2(i)));
@for(a3(i):@bin(z3(i)));
!行动决策变量为0-1变量,z1=1表示停留 0作移动,z2=1表示挖矿 0则不挖矿,z3=1表示途径村落购买物资,0则不买物资;
@for(a3(i):@gin(cX(i)));
@for(a3(i):@gin(cY(i)));
@for(a3(i):cX(i)>=0);
@for(a3(i):cY(i)>=0);
!购买食物和水的数量必须大于0且为整数;
!各变量约束;

weight=3*x1+2*y1;
cost=5*x1+10*y1;
cost<=10000;
weight<=1200;
!初始约束,重量和资金约束;

@for(a4(i,j,k):x(i,j,k)<=d(j,k));
!只走接壤 只有d(j,k)=1时候,x(i,j,k)才可以为1,因此x严格小于等于d;
@for(a4(i,j,k):@bin(x(i,j,k)));
!整数规划;
@for(a3(i):@sum(a2(j,k):x(i,j,k))=1);
!每天一决策 对j k求和 对于所有的i x(i,j,k)仅有一个为1;
@sum(a1(k):x(1,1,k))=1;
!起点出发 第一天从1处去往k点,若k=1则为停留;
@sum(a5(i,j)|j#ne#27:x(i,j,27))=1;
!有一天走去终点,必然从不等于27的区域去往27 27是第一问题目的终点;
@for(a3(i)|i#ne#30:x(i+1,27,27)=@sum(a1(j):x(i,j,27)));
!到达终点停止,若到达终点,未满30,后面的天数则视为在27处停留,不消耗物资,资金数也不发生变化;
@for(a5(i,j)|i#ne#30:@sum(a1(k):x(i+1,j,k))=@sum(a1(k):x(i,k,j)));
!当天出发=前一天目的地,保持移动路径连续;
@for(a3(i):z1(i)=@sum(a1(j):x(i,j,j)));
!是否停留;
@for(a3(i):w(i)-@sum(a1(j):x(i,j,j))<=2);
!沙暴必须停留 w=3 @sum(a1(j):x(i,j,j))必须为1进行停留 w=1或者2时候@sum(a1(j):x(i,j,j))可以为0或者1;
@for(a3(i):cX(i)<=1000*z3(i));
!购买食物条件,只有z3=1时可以购买物资,姑且设1000为数量上限;
@for(a3(i):cY(i)<=1000*z3(i));
!购买水条件,同样只有z3=1时可以购买物资,姑且设1000为数量上限;
@for(a3(i):r(i)=1000*z2(i));
!挖矿条件 z2=1,才会有收益;
@for(a3(i):10*cX(i)+20*cY(i)<=10000-cost-@sum(a3(j)|j#lt#i:10*cX(j)+20*cY(j)-r(j)));
!资金限制,(第i天购买水和食物的资金)必须小于(总资金-初始购买所花资金-前面所有天历史花费的资金+历史挖矿所得资金);
@for(a3(i):3*cX(i)+2*cY(i)<=1200-weight-@sum(a3(j)|j#lt#i:3*cX(j)+2*cY(j)-3*yX(j)-2*yY(j)));
!重量限制,(第i天购买水和食物的重量)必须小于(总重量-初始购买的水和食物的重量-前面所有天消耗的水和食物的重量+前面所有天历史购买的水和食物的重量);
@for(a3(i):yX(i)=aX(i)*b(i));
@for(a3(i):yY(i)=aY(i)*b(i));
!消耗量函数 总消耗量=单位消耗量决策倍数;
@for(a3(i):b(i)=2+2*z2(i)-z1(i)-x(i,27,27));
!消耗量关于天气 决策的函数关系 b表示倍数 挖矿3倍 移动2倍 停留1倍 如果抵达终点在终点停留为0;
@for(a3(i):z2(i)<=x(i,12,12));
@for(a3(i):z3(i)<=@sum(a1(j):x(i,j,15)+x(i,15,j)));
!挖矿 购买 决策约束条件 挖矿必须在矿山12处作停留 购买物资必须途径村庄15;
max=kk(30)+2.5*shui(30)+5*wuzi(30);
!目标函数;
@for(a3(i):kk(i)=10000-cost-@sum(a3(j)|j#lt#i:10*cX(j)+20*cY(j)-r(j))+r(i));
!剩余总资金;
@for(a3(i):shui(i)=x1-@sum(a3(j)|j#lt#i:yX(j)-cX(j))-yX(i));
@for(a3(i):wuzi(i)=y1-@sum(a3(j)|j#lt#i:yY(j)-cY(j))-yY(i));
!剩余水和食物必须大于0;
@for(a3(i):wuzi(i)>=0);
@for(a3(i):shui(i)>=0);
@for(a3(i):aX(i)=@if(w(i)#eq#1,5,@if(w(i)#eq#2,8,10)));
@for(a3(i):aY(i)=@if(w(i)#eq#1,7,@if(w(i)#eq#2,6,10)));
data:
w=2 2 1 3 1 2 3 1 2 2 3 2 1 2 2 2 3 3 2 2 1 1 2 1 3 2 1 1 2 2;
@text('data.txt')=@write('最大资金数为',kk(30)+2.5*shui(30)+5*wuzi(30),'元 行走路径为:',@newline(1));
@text('data.txt')=@writefor(a4(i,j,k)|x(i,j,k)#eq#1 #and# x(i,27,27)#eq#0:'第',i,'天','从',j,'点去往',k,'点,','消耗水',yX(i),'个,食物',yY(i),'个,剩余水',shui(i),'个,食物有',wuzi(i),'个;',@newline(1));
@text('data.txt')=@writefor(a3(i)|@sum(a1(j):x(i,j,27))#eq#1 #and# x(i,27,27)#eq# 0:'在第',i,'天抵达终点。',@newline(1));
@text('data.txt')=@writefor(a3(i)|z2(i)#eq#1:'在第',i,'天选择挖矿',@newline(1));
@text('data.txt')=@writefor(a3(i)|z3(i)#eq#1:'在第',i,'天从村落里购买了',cX,'个食物和',cY,'个水',@newline(1));
d=
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1
0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1;
enddata
end

LINGO求解结果:
第一问通过LINGO@text{}输出结果如下:
最大资金数为10470元 行走路径为:
第1天从1点去往25点,消耗水16个,食物12个,剩余水162个,食物有321个;第2天从25点去往24点,消耗水16个,食物12个,剩余水146个,食物有309个;第3天从24点去往23点,消耗水10个,食物14个,剩余水136个,食物有295个;第4天从23点去往23点,消耗水10个,食物10个,剩余水126个,食物有285个;第5天从23点去往22点,消耗水10个,食物14个,剩余水116个,食物有271个;第6天从22点去往9点,消耗水16个,食物12个,剩余水100个,食物有259个;第7天从9点去往9点,消耗水10个,食物10个,剩余水90个,食物有249个;第8天从9点去往15点,消耗水10个,食物14个,剩余水80个,食物有235个;第9天从15点去往14点,消耗水16个,食物12个,剩余水64个,食物有223个;第10天从14点去往12点,消耗水16个,食物12个,剩余水211个,食物有211个;第11天从12点去往12点,消耗水10个,食物10个,剩余水201个,食物有201个;第12天从12点去往12点,消耗水24个,食物18个,剩余水177个,食物有183个;第13天从12点去往12点,消耗水15个,食物21个,剩余水162个,食物有162个;第14天从12点去往12点,消耗水24个,食物18个,剩余水138个,食物有144个;第15天从12点去往12点,消耗水24个,食物18个,剩余水114个,食物有126个;第16天从12点去往12点,消耗水24个,食物18个,剩余水90个,食物有108个;第17天从12点去往12点,消耗水30个,食物30个,剩余水60个,食物有78个;第18天从12点去往12点,消耗水10个,食物10个,剩余水50个,食物有68个;第19天从12点去往12点,消耗水24个,食物18个,剩余水26个,食物有50个;第20天从12点去往13点,消耗水16个,食物12个,剩余水10个,食物有38个;第21天从13点去往15点,消耗水10个,食物14个,剩余水0个,食物有24个;第22天从15点去往9点,消耗水10个,食物14个,剩余水0个,食物有26个;第23天从9点去往21点,消耗水16个,食物12个,剩余水10个,食物有14个;第24天从21点去往27点,消耗水10个,食物14个,剩余水0个,食物有0个;在第24天抵达终点。
在第12天选择挖矿,在第13天选择挖矿,在第14天选择挖矿,在第15天选择挖矿,在第16天选择挖矿,在第17天选择挖矿,在第19天选择挖矿
在第9天从村落里购买了163个食物和0个水
在第21天从村落里购买了10个食物和16个水
在第22天从村落里购买了26个食物和0个水

2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解_第4张图片2020年全国大学生数学建模竞赛B题穿越沙漠问题——建立整数线性规划模型(ILP)——通过LINGO求解_第5张图片
建立的模型均是ILP,求解速度都很快。
第二问代码见:https://download.csdn.net/download/Xialiuto/79002543

你可能感兴趣的:(LINGO,数学建模,美国大学生数学建模竞赛,线性规划)