无限配送公司案例-最小费用率lingo建模,对哑变量共享绑定的简单理解

1 阅读4分钟

LINGO最小费用流建模笔记|嵌套@for+@sum、哑变量共享绑定理解记录

背景:课堂最小费用流(中转运输问题)案例,记录对两段嵌套约束的理解,重点理解LINGO集合哑变量的共享绑定规则,模型可正常求解最优解

案例描述如下图 Weixin Image_20261105190125_172_119.png

模型完整代码

model:
sets:
	node/F1 F2 DC W1 W2/:capacity;
	link(node,node)/F1,W1 F1,DC DC,W1 DC,W2 F2,W2 F2,DC/:
		maxvolume,cost,volume;
endsets

data:
	capacity = 80,70,0,60,90;
	maxvolume = 1000 50 50 50 1000 50;
	cost = 700 300 200 400 1000 500;
enddata

!工厂流出平衡约束
@for(node(i)|i#EQ#1 #OR# i#EQ#2:
	@sum(link(i,j):volume(i,j)) = capacity(i)
);
!需求点流入平衡约束
@for(node(j)|j#EQ#4 #OR# j#EQ#5:
	@sum(link(i,j):volume(i,j)) = capacity(j)
);
!DC中转节点流量守恒约束
@for(node(i)|i#EQ#3:
	@sum(link(i,j):volume(i,j)) = @sum(link(j,i):volume(j,i))
);
!链路容量上限
@for(link:volume<=maxvolume);
!目标函数:最小总运费
min=@sum(link:volume*cost);
end

节点说明:

  • F1、F2:工厂(供应点)
  • DC:中转仓(中转节点,无供给、无需求)
  • W1、W2:需求仓库

链路清单:

  1. F1,W1:上限1000,单位运费700
  2. F1,DC:上限50,单位运费300
  3. DC,W1:上限50,单位运费200
  4. DC,W2:上限50,单位运费400
  5. F2,W2:上限1000,单位运费1000
  6. F2,DC:上限50,单位运费500

一、需求点约束理解(W1、W2流入平衡)

@for(node(j)|j#EQ#4 #OR# j#EQ#5:
	@sum(link(i,j):volume(i,j)) = capacity(j)
);

运行逻辑:

  1. @for 设置过滤条件 j#EQ#4 #OR# j#EQ#5,只会迭代 node 集合索引为4、5的节点,也就是 W1、W2;

  2. LINGO嵌套结构中,外层哑变量在内部表达式共享绑定,内层link(i,j)里的j直接复用外层固定的j值;i是当前@sum内部独立的局部哑变量;

  3. 自动筛选link稀疏集合中,终点为当前j的所有边:

    • j=4(W1):匹配边 F1,W1、DC,W1
    • j=5(W2):匹配边 DC,W2、F2,W2
  4. 分别对匹配到的链路运量volume累加求和;

  5. 约束含义:W1、W2的总流入量 = 自身需求capacity,保证需求被满足。


二、中转DC节点流量守恒约束理解

@for(node(i)|i#EQ#3:
	@sum(link(i,j):volume(i,j)) = @sum(link(j,i):volume(j,i))
);

运行逻辑:

  1. @for 设置过滤条件 i#EQ#3,只迭代索引为3的节点DC,最终只会生成一条约束;
  2. 外层哑变量i固定等于3(DC),左右两个sum里面的i都复用这个固定值;
  3. 左侧 @sum(link(i,j):volume(i,j)):i固定为DC(DC作为起点),局部哑变量j遍历link里DC出发的边:DC,W1、DC,W2,求和得到DC总流出量;
  4. 右侧 @sum(link(j,i):volume(j,i)):i固定为DC(DC作为终点),局部哑变量j遍历link里流向DC的边:F1,DC、F2,DC,求和得到DC总流入量;
  5. 约束含义:中转仓DC的流入总量 = 流出总量,中转节点不积存货物,满足流量守恒。

三、补充:一组可行解参考

满足全部约束的一组可行方案(LINGO会在可行域内寻找成本最低的最优解)

链路运量链路运量
F1→W130F1→DC50
DC→W130DC→W250
F2→W240F2→DC30

校验:

  1. F1流出:30+50=80 ✔ F2流出:40+30=70 ✔
  2. W1流入:30+30=60 ✔ W2流入:40+50=90 ✔
  3. DC流入:50+30=80,DC流出:30+50=80 ✔
  4. 所有链路运量均不超过容量上限 ✔

该方案总运费:30*700 + 50*300 + 30*200 + 50*400 + 40*1000 + 30*500 = 117000


核心知识点总结

  1. LINGO中i/j这类标识是集合哑变量,不是决策变量,仅作为遍历标记,不参与求解;
  2. 嵌套结构规则:外层@for声明并固定哑变量后,内层@sum可以直接复用这个哑变量(共享绑定);如果在集合括号内重新声明同名哑变量,则会发生局部覆盖;
  3. 复合集合link只会遍历预先定义好的边,不会自动从1开始遍历;
  4. @for负责批量生成约束方程,@sum负责累加计算,二者分工不同;