你有没有遇到过这样的场景?公司有几个工厂生产产品,要运到不同的仓库,每个工厂的产能有限,每个仓库的需求也固定,怎么安排运输路线才能让总运费最低?这就是经典的运输问题啦!作为一个经常和数据打交道的人,我之前一直用Excel的规划求解来做,但数据量大的时候就很慢,而且容易出错。后来发现Matlab解决这个问题简直是神器!今天就来分享一下用Matlab解决运输问题的完整流程,从模型建立到代码实现,保证你一看就懂!
运输问题是线性规划的一个经典分支,核心目标就是在满足供需约束的前提下,找到总运输成本最低的方案。举个简单的例子:
假设我们有3个工厂(F1、F2、F3),产能分别是100吨、200吨、150吨;4个仓库(W1、W2、W3、W4),需求分别是120吨、130吨、100吨、100吨。从每个工厂到仓库的单位运费已知(比如F1到W1是5元/吨,F1到W2是6元/吨)。我们的任务就是确定每个工厂运多少货物到每个仓库,让总运费最少,同时不超过工厂产能、满足仓库需求。
要想用Matlab解决问题,得先把问题转化为数学语言。我们设:
- (x_{ij}):从工厂i运到仓库j的货物量(i=1,2,3;j=1,2,3,4)
- (c_{ij}):工厂i到仓库j的单位运费
- (s_i):工厂i的产能
- (d_j):仓库j的需求
目标函数(总运费最小):
[ \min Z = \sum_{i=1}^3 \sum_{j=1}^4 c_{ij} x_{ij} ]
约束条件:
1. 每个工厂运出总量 ≤ 产能(平衡问题中可改为等于,因为不运完会浪费成本):
[ \sum_{j=1}^4 x_{ij} = s_i \quad (i=1,2,3) ]
2. 每个仓库收到总量 = 需求:
[ \sum_{i=1}^3 x_{ij} = d_j \quad (j=1,2,3,4) ]
3. 运输量非负:
[ x_{ij} ≥ 0 \quad (\forall i,j) ]
Matlab的linprog函数专门用来解线性规划问题,所以我们要把运输问题转化为linprog能处理的标准形式:
[ \min f^T x \quad \text{s.t.} \quad A_{eq}x = b_{eq}, \quad lb ≤ x ≤ ub ]
这里的关键是把二维的(x_{ij})转化为一维向量,然后构建对应的目标函数系数、约束矩阵等。下面分步骤讲解:
首先,我们把问题中的已知数据输入Matlab:matlab
n_plant = 3; % 工厂数量
n_warehouse = 4; % 仓库数量
s = [100; 200; 150]; % 工厂产能(列向量)
d = [120;130;100;100];% 仓库需求(列向量)
% 成本矩阵:行=工厂,列=仓库
c = [5,6,7,8;
4,5,6,7;
3,4,5,6];
linprog的目标函数是一维向量(f^T x),所以我们要把成本矩阵(c)按行展开成一维向量:matlab
f = c(:); % 把矩阵转成列向量(顺序:x11→x12→x13→x14→x21→...→x34)
约束矩阵(A_{eq})的行数 = 工厂数 + 仓库数(3+4=7),列数 = 工厂数×仓库数(3×4=12)。
- 前3行:工厂产能约束(每行对应一个工厂,该工厂的所有运输量系数为1)
- 后4行:仓库需求约束(每行对应一个仓库,该仓库的所有运输量系数为1)
代码实现:
```matlab
Aeq = zeros(n_plant + n_warehouse, n_plant*n_warehouse);
% 工厂约束:每行对应一个工厂 for i = 1:n_plant start_idx = (i-1)n_warehouse + 1; end_idx = in_warehouse; Aeq(i, start_idx:end_idx) = 1; end
% 仓库约束:每行对应一个仓库 for j = 1:n_warehouse col_idx = j:n_warehouse:(n_plant*n_warehouse); Aeq(n_plant + j, col_idx) = 1; end
% beq:产能+需求(列向量) beq = [s; d]; ```
运输量不能为负,所以下界lb全为0:matlab
lb = zeros(n_plant*n_warehouse, 1);
设置算法(比如内点法),然后调用linprog:matlab
% 设置优化选项(用内点法,适合大规模问题)
options = optimoptions('linprog', 'Algorithm', 'interior-point');
% 求解:A和b为空(无不等式约束),ub为空(默认无穷大)
[x, fval] = linprog(f, [], [], Aeq, beq, lb, [], options);
把一维的x向量转成工厂×仓库的矩阵,方便查看:
```matlab
% 注意reshape顺序:先转成仓库×工厂,再转置为工厂×仓库
x_matrix = reshape(x, n_warehouse, n_plant)';
% 输出结果 disp('运输量矩阵(行:工厂,列:仓库):'); disp(x_matrix); disp(['总运费:', num2str(fval), '元']); ```
运行上面的代码,你会得到类似这样的输出:运输量矩阵(行:工厂,列:仓库):
100 0 0 0
20 130 50 0
0 0 50 100
总运费:2380元
分析:
- F1把所有100吨运到W1(成本最低)
- F2运20吨到W1、130吨到W2、50吨到W3(满足W2和W3需求)
- F3运50吨到W3、100吨到W4(满足W4需求)
- 总运费2380元,完全符合约束条件!
我第一次写这段代码时,reshape那里忘记转置,结果矩阵变成了仓库×工厂,看了半天都没明白数据不对!后来才发现这个小坑,大家一定要注意哦!
现实中很多运输问题是供需不平衡的(比如产能总和≠需求总和),这时候怎么办?
比如产能总和450,需求总和420,差30吨。这时候可以加一个虚拟仓库,需求30吨,单位运费0(因为不用真的运输)。修改参数:matlab
n_warehouse = 5; % 加虚拟仓库
d = [120;130;100;70;30]; % 需求加30
c = [5,6,7,8,0; 4,5,6,7,0;3,4,5,6,0]; % 成本矩阵加一列0
比如需求总和480,产能总和450,差30吨。加一个虚拟工厂,产能30吨,单位运费0:matlab
n_plant =4; % 加虚拟工厂
s = [100;200;150;30]; % 产能加30
c = [5,6,7,8;4,5,6,7;3,4,5,6;0,0,0,0]; % 成本矩阵加一行0
这样就能把不平衡问题转化为平衡问题,继续用上面的代码解决!
interior-point算法更快;小数据用simplex算法(如果Matlab版本支持)。 用Matlab解决运输问题真的很高效,尤其是处理大规模数据时,比Excel规划求解快N倍!关键是掌握模型转化和约束矩阵构建这两个核心步骤。只要你跟着这篇文章的案例走,从简单平衡问题到复杂不平衡问题,都能轻松搞定!
希望这篇文章能帮到正在学习的你,下次遇到运输问题就不用愁啦!如果你有其他问题,欢迎在评论区交流哦(虽然我看不到,但你可以自己思考哈哈)!
最后,记得多动手实践,代码写多了自然就熟练啦!