资讯详情

基于模糊需求与模糊运输时间的多式联运路径优化Matlab实现

📅 2026/10/11 0:41:20 | 华诺云谱 👁 阅读
基于模糊需求与模糊运输时间的多式联运路径优化Matlab实现
做多式联运路径优化最头疼的一件事不是模型复杂而是需求量和运输时间都说不准。客户给的需求量是模糊的铁路、公路、水路在途时间也带模糊性偏偏经典路径优化模型都假设这些是定值算出来的方案看着精确落地就翻车。我最近把一个“基于模糊需求和模糊运输时间”的多式联运路径优化模型用Matlab完整实现了出来模型不算大但每一步都踩了不少坑。这篇就把完整建模思路、模糊数处理方式、求解框架和能直接跑的Matlab代码拆开讲清楚给正在做物流网络规划、供应链调度的朋友当个参考。先说清楚这套东西适合谁如果你做的是运输方案比选、多式联运路径规划、生产企业的原料或成品物流网络设计手里数据又恰恰是“大概多少”“两到三天”“大概率能装下”这种模糊表达那这个方法比硬套确定性模型靠谱得多。下面按我实际做项目时的推进顺序来讲。1. 先搞清楚这个优化问题到底在解什么1.1 多式联运路径优化在现实里长什么样多式联运不是新鲜概念。一次运输任务里货物从起点到终点往往要经过两个及以上运输方式先公路短驳到铁路货站铁路干线运输几百公里再换水运或公路完成末端配送。每一种运输方式都有对应的运输时间、运输单价、单批容量、碳排放系数并且在两种方式交接的地方必然产生中转成本和中转时间。经典优化目标很直白找到一条从起点到终点的路径以及路径上每段弧采用什么运输方式使总成本最小、总时间尽量短。约束条件则包括节点连续性货物到某个中转站必须再从该站发出、容量限制、时间窗限制、中转次数限制等。听起来不复杂但一旦把网络铺到十几个城市、每个节点有三四种可选方式组合规模立刻爆炸人工拍脑袋就完全不管用了。我这次的项目背景是一家制造企业的成品分拨网络需要从华东一个生产基地向四个区域配送中心发货候选路径上涉及公路、铁路、内河航运三种方式。问题本身不复杂难就难在企业的需求预测部门只能给出“下个月大概要发800到1000吨”这种区间描述运输部门又只能给出“铁路走这批货可能要3到5天”的时间预估。定值模型根本没法处理这种输入。1.2 需求模糊和运输时间模糊不是数学游戏是现实约束很多人看到“模糊”两个字就以为是在故意把问题搞复杂真不是。需求模糊的原因是企业订单周期短、客户预测不准销售给的是一个波动范围运输时间模糊的原因更简单高速公路堵不堵、铁路调度是否顺利、内河是否遇到水位变化这些都不是拍脑袋能精确到小时的。如果强行把这些模糊输入替换成某个确定值比如把需求取中间值900吨把时间取最可能值4天然后去求解得到的最优路径往往在真实场景下并不是最优。为什么因为决策对不确定性的敏感度不一致。需求量如果偏向区间上界原先选中的小容量公路直达方案可能装不下运输时间如果偏向区间下界原本以为会超时的水路方案反而可能满足时效。这种时候把不确定因素显式建模进优化过程比事后拍板要可靠得多。这里也解释一下为什么用模糊数而不是随机数随机规划需要知道需求量和运输时间的概率分布比如正态分布、泊松分布这需要大量历史数据。而我手里能拿到的只有业务经验判断三个值最可能值、最乐观值、最悲观值。三角模糊数正好就是为这种“经验估计型不确定”设计的不需要历史分布和实际情况贴合得最好。1.3 模糊信息进入优化模型的三种可能方式不确定性进入优化模型常见的做法有三类。第一类是情景法把不确定参数拆成高、中、低几个情景对每个情景分别求最优解最后再综合判断。好处是简单、直观缺点是情景数量少时代表性不足数量多时计算量成倍增长而且各情景结果之间怎么取舍很难说服业务方。第二类是鲁棒优化假设不确定参数落在一个集合内要求解在集合内最差情况下也可行。这类方法的优点是能保证“不管怎么波动都不出事”缺点是需要提前定不确定集且求出的方案往往偏保守成本偏高。第三类就是我这篇文章采用的模糊规划把参数表示为三角模糊数用可能度或可信性理论处理约束并把目标函数去模糊化后比较。它的好处是保留了对参数内部结构的刻画也就是不仅告诉模型一个数还告诉模型这个数“大概在哪个范围、最可能落在哪”。当业务方只愿意说“数量大概是800到1000最可能是900”时模糊规划是成本最低、解释成本也最低的建模方式。2. 把模糊信息翻译成模型能用的语言2.1 三角模糊数其实就是一个三元组加三条操作规则三角模糊数我用得最多因为它本质就是一组三元组最乐观值、最可能值、最悲观值记作a波浪号(a上标L, a上标M, a上标U)。下标L代表下界M代表最可能值U代表上界满足L到M再到U逐渐递增。比如“运输时间大概4天最坏5天半顺利的话3天”可以写成(3, 4, 5.5)。模糊数的好处在于可以把数值计算规则推广到波段上。两个三角模糊数相加结果还是三角模糊数三个分量分别相加就行。比如(3,4,5)加上(1,2,3)得到(4,6,8)。这个规则很实用一条路径上多个区段的模糊运输时间可以直接逐分量相加得到这条路径的模糊总时间。同理模糊总成本也可以由各段模糊成本相加得到只不过成本作为运输“单价×重量”的结果在计算时会涉及模糊数与实数的乘法。实数乘法同样简单每个分量乘以该实数即可。还有一个经常被忽略的操作是“比较”。模糊数比较不像普通数字那么明确不是简单看谁大谁小。因为它是三个分量两个模糊数可能一个中值大但区间宽另一个中值小但区间窄。直接比较最可能值会丢掉很多信息。我后面会细说比较方法。2.2 去模糊化方法选择期望值法比质心法更顺手去模糊化就是把三角模糊数变成一个确定数值方便放进最优解搜索的比较过程。常用的有两种一种是质心法即把三角模糊数看作一个三角形求三角形的重心横坐标得到(LMU)/3。这个方法简单但对三角分布形态有隐含假设相当于认为下界和最可能值之间的变化是线性的。另一种是期望值法。对于三角模糊数(L,M,U)期望值定义为E(a)(L2MU)/4。这个公式在我做的项目中更好用。它给最可能值M赋予更高权重符合业务上“最可能值通常最可信”的直觉。比如两个模糊时间(3,4,5)和(2,4,7)质心法都给出4但期望值法前者是(385)/44后者是(287)/44.25。体感上前者更稳定期望值法能把这种差异体现出来。在目标函数中我通常把模糊总成本的期望值作为主要目标值模糊总时间的期望值作为第二目标组合成加权目标。这种处理思路简单业务方也容易接受——你可以对对方说我们不是在比较一个模糊数而是在比较这个模糊数“平均来看”大概是多少。2.3 模糊约束不能直接比较大小要引入机会约束约束条件里如果有“装载量不超过容量”这种比较就不能直接对模糊数做大于小于判断。这时候我用到了一个基本工具可能性测度Pos(模糊数A 实数B)。含义是这个模糊数的取值不超过B的可能性有多大。计算方式很直观当模糊数的最可能值M超过B时可能性按(M-B)/(M-L)的比例衰减如果上界U都小于B那可能性就是1如果下界L都大于B可能性为0。落到代码里就是一行if-else判断。决策者给定一个置信水平alpha比如0.9那么约束就写成Pos(模糊需求量 运输工具容量) alpha。意思是我们允许有10%以内的可能超载但不允许更高。这个α是这整套模型里非常关键的一个旋钮。α越高方案越保守越倾向选容量大的运输方式和预留缓冲区α越低越激进越倾向于卡着容量上限选便宜方式。我把α作为一个可调参数暴露出来业务方就能自己观察不同风险偏好下的路径变化。3. 模型搭建目标函数、决策变量、约束条件3.1 网络定义与决策变量的选择把物流网络抽象成有向图G(N,A)。N是所有节点集合包括起点、终点和中转站A是所有有向弧集合。每条弧(i,j)上有一个可选运输方式的集合M_ij方式集合里的每个元素代表该弧可以采用的一种运输方式。决策变量有两类。第一类是路径选择变量k_ij^m0-1变量表示货物是否在弧(i,j)上采用运输方式m取1表示采用取0表示不采用。第二类是中转衔接变量y_i^(m1,m2)也是0-1变量表示货物在节点i是否从方式m1换成方式m2取1表示发生换装取0表示不换装。中转变量看起来有点抽象实际作用很大它决定要不要把一笔中转时间和一笔中转成本计算进去。这里要说一个建模上的细节弧上选择了运输方式m只代表这段路跑哪种工具并不代表在中转节点一定发生换装。换装只发生在相邻两段弧的运输方式不同的情况。比如前一段是公路后一段是铁路就必须换装如果前后都是公路就不需要。模型里用y_i要保证m1和m2不同这样才不会重复计费。3.2 目标函数把成本、时间、碳排放压成一个加权指标目标函数我采用加权和的形式。主目标是最小化期望总成本与期望总时间的加权和另外把碳排放量作为附带统计项不进入主目标但输出给决策者参考。总模糊成本由三部分组成运输模糊成本、中转模糊成本、时间罚金成本。运输模糊成本是路径上每条弧的运输单价乘以模糊需求量中转模糊成本是每发生一次换装产生的固定费用时间罚金成本是总模糊运输时间超过客户期望时间窗时产生的惩罚用超出部分乘以单位时间惩罚系数来处理。写成文本公式就是min Z w1 * E(C_total_tilde) w2 * E(T_total_tilde)其中w1和w2是权重系数由决策者根据成本和时间的相对重要性确定。E()是对三角模糊数取期望值。C_total_tilde是模糊总成本T_total_tilde是模糊总时间。如果企业特别看重时效比如生鲜或医药物流就把w2调大如果预算更紧张就把w1调大。有人可能会问为什么不直接做多目标优化求帕累托解集我的回答是这一步看项目阶段。如果只是为了快速给业务方一个可落地的方案加权法足够如果是要做完整决策支持系统可以换成NSGA-II这类多目标算法核心框架不用动。3.3 约束条件连续性、容量、时间窗、中转次数模型里我设了四组约束每一组都有它存在的意义。第一组是节点连续性约束。起点的流出总量必须等于1终点的流入总量必须等于1中间节点流入量必须等于流出量。这保证货物从起点到终点形成一条完整的、不断裂的路径。第二组是模糊容量约束。每条已选中的运输弧其计划装载量不能超过该运输方式的容量上限。表示为Pos(模糊需求量 路径上最小可用容量) α。由于需求量是模糊的我用可能性测度来保证超载风险可控。第三组是模糊时间窗约束。货物必须在客户要求的时间窗内到达而到达时间是模糊的所以也用机会约束判断Pos(到达时间 最晚允许时间) β。β是决策者给定的时效置信水平。时间窗约束在项目中非常关键有时候成本最优方案就是因为赶不上客户的收货窗口而被否掉。第四组是中转次数约束。整个行程中的换装次数不能超过K。每发生一次换装都会带来货物破损风险和时间损失业务方一般会限制在2到3次以内。约束条件里的α和β两个置信水平我建议分开设置。容量约束可以稍微松弛α取0.85到0.9时间窗约束通常要更严格β取0.9以上。不同置信水平之下算出的最优路径变化很大这本身就是可以拿给业务方讨论的敏感度素材。4. Matlab实现从模糊输入到路径输出4.1 数据准备与模糊参数生成Matlab代码的第一部分是准备网络数据。为了便于复现我把网络数据写成了结构体数组每个结构体存一条弧的信息起点、终点、可选方式、模糊运输时间、模糊运输单价、容量、碳排放系数。这样做的最大好处是后续写求解循环时非常顺手想改网络规模只要往数组里追加或删除元素即可。模糊参数我用三列矩阵表示。比如模糊运输时间的三列分别是L、M、U模糊运输单价同理。为了让模型不依赖外部数据文件我直接在代码里通过randi或其他随机函数生成测试数据。实际项目中如果你有真实数据只需要把这个生成部分替换成从Excel读取的过程即可。下面是数据准备的核心片段% 节点编号: 1起点, 2中转A, 3中转B, 4中转C, 5终点 % 每条弧: [起点, 终点, 可选方式集合(1公路 2铁路 3水运)] % 运输时间模糊参数: time(:, [L M U]) % 运输单价模糊参数: price(:, [L M U]) ArcList [1 2; 1 3; 2 3; 2 4; 3 4; 3 5; 4 5]; MethodSet {[1 2], [1 2 3], [1 2 3], [1 3], [2 3], [1 2], [1 2 3]}; N_arc size(ArcList, 1); timeL [1.2 1.0 1.8 2.0 2.5 3.0 1.5]; timeM [1.5 1.3 2.2 2.5 3.0 3.6 2.0]; timeU [2.0 1.8 3.0 3.5 4.0 4.5 2.8]; priceL [2.2 1.5 2.0 1.8 1.8 2.0 1.6]; priceM [2.8 2.0 2.5 2.3 2.2 2.6 2.2]; priceU [3.5 2.6 3.2 3.0 2.9 3.4 3.0];这里的时间单位是天价格单位是百元每吨。每条弧上的运输方式和模糊时间、模糊单价按照同样的索引顺序对应方便后续在循环里按弧取数。如果你只有确定性数据也完全可以兼容把LMU填成同一个值就行程序不用改。4.2 路径搜索与方式选择的求解框架网络规模不大我采用了两步走的求解框架第一步枚举起点到终点的所有可行路径第二步对每条路径枚举每条弧上的运输方式组合计算去模糊化后的目标值并做机会约束校验最后取最优。这里重点说一下方式组合的思路。路径一旦确定比如起点1到中转2再到中转3再到终点5那么这条路径上有三段弧每段弧可能分别有若干种运输方式。方式组合的数量等于各段可选方式数的乘积。如果路径是4段弧每段都有3种方式组合就是3的4次方等于81种枚举完全可行。如果网络扩大导致组合爆炸第二步可以改用动态规划或遗传算法但中小规模问题枚举法反而是最稳妥的不用调参也不会陷入局部最优。实际的路径枚举我用了深度优先搜索遍历所有不重复节点的路径。为了避免死循环代码里设置了一个visited数组记录当前路径上已经过哪些节点。搜索到终点后把当前路径存进RouteSet。这个方法在小规模网络上非常可靠。4.3 关键代码逐段说明下面这段代码实现了三角模糊数的期望值函数function ev fuzzy_expectation(x) % x为[L M U]三列向量返回期望值 ev (x(:,1) 2*x(:,2) x(:,3)) / 4; end这段代码实现了可能性测度函数用于模糊约束判断function pos possibility_le(x, b) % 计算 Pos(x b) 的可能性 L x(1); M x(2); U x(3); if U b pos 1; elseif L b b U if M b pos 1; else pos (M - b) / (M - L); end else pos 0; end end这里我把可能性测度的细节简化了一部分但足够用。当b落在最可能值左侧时pos直接取1因为模糊数低于b是大概率事件当b落到最可能值和上界之间时按线性衰减估算。这个逻辑和生产上“大概率能在时间内完成”的表述是一致的。主循环里我对路径集合中的每条路径进行评价。以内层方式组合枚举为例best inf; bestRoute []; bestMethod []; for r 1:size(RouteSet, 1) route RouteSet(r, :); arcs path_to_arcs(route, ArcList); n_seg length(arcs); method_combos generate_combos(arcs, MethodSet); for c 1:size(method_combos, 1) [C_tilde, T_tilde] eval_route(route, method_combos(c, :)); % 时间窗约束校验 if possibility_le(T_tilde, deadline) beta, continue; end % 容量约束校验 if possibility_le(Demand_tilde, max_cap(route, method_combos(c,:))) alpha, continue; end obj w1 * fuzzy_expectation(C_tilde) w2 * fuzzy_expectation(T_tilde); if obj best best obj; bestRoute route; bestMethod method_combos(c, :); end end endeval_route函数里做的事就是沿着路径累加模糊时间和模糊成本。模糊时间直接逐分量累加模糊成本则要把每段弧的模糊单价乘以模糊需求再累加乘法和加法都遵循三角模糊数的分量运算规则。中转成本则根据相邻两段弧的方式是否产生换装来决定是否追加。这段代码的运行速度在几十条弧的网络上非常快几秒到十几秒就能出结果。在实际项目中我把网络节点最大规模做到20个节点、3种方式枚举路径数量的上限大约在几百条量级方式组合数在几千量级Matlab仍能轻松处理。4.4 求解结果的解读方式很多人拿到代码跑出结果后只关注“哪条路径最优”但我建议把结果里的模糊成本、模糊时间、置信水平、换装次数全部打印出来整合成一张结果表再和业务方讨论。下面的代码是结果输出的核心部分fprintf(最优路径: ); fprintf(%d , bestRoute); fprintf(\n最优方式: ); fprintf(%d , bestMethod); fprintf(\n模糊总成本: [%.1f, %.1f, %.1f]\n, C_best(1), C_best(2), C_best(3)); fprintf(模糊总时间: [%.2f, %.2f, %.2f]\n, T_best(1), T_best(2), T_best(3)); fprintf(成本期望值: %.1f\n, fuzzy_expectation(C_best)); fprintf(时间期望值: %.2f\n, fuzzy_expectation(T_best));为什么输出要保留三元组而不是只给期望值因为三元组能展示波动范围。比如甲路径成本期望值比乙路径低2%但甲路径的模糊成本区间很宽最坏情况可能比乙的最坏情况高很多。如果业务方是风险规避型他们可能宁愿选乙。所以完整的模糊输出给决策者提供了确定性模型给不了的额外信息维度。5. 算例验证与实际踩坑记录5.1 小型网络算例设计与结果为了验证代码正确性我设计了一个非常小的算例4个节点起点1到终点4中间两个中转节点可选路径有3条每条弧上有公路和铁路两种方式。需求量模糊数设为(800, 900, 1000)吨置信水平α0.85β0.95时间窗deadline设为6天。运行结果如下表所示路径方式组合模糊总成本期望值模糊总时间期望值是否符合约束1-2-4公路-公路23454.2是1-2-3-4公路-铁路-公路26315.1是1-3-4铁路-公路27184.8是在这个算例里最优方案是1-2-4全程公路总成本期望值最低。但如果我们把需求量模糊数改成(900, 1100, 1300)α从0.85调高到0.95那么路径1-3-4的铁路段因为容量更大、可靠性更高反而会胜出。这里注意路径改变不是因为模型算错而是因为风险偏好变了模型主动放弃了“便宜但容量紧”的方案。这就是模糊建模比确定性建模更实用的地方。5.2 模糊参数灵敏度分析能提供额外决策价值我把需求量的模糊区间宽度从“±10%”逐步调到“±30%”观察最优路径的变化。结果发现需求量不确定性越大最优路径越倾向于采用铁路和水运组合的长距离干线方案因为这类方式单批容量大超载风险低。相反当需求量预估比较准的时候公路直达的灵活性优势就体现出来。运输时间模糊区间的灵敏度同理当运输时间不确定性增大时模型会更倾向避开中转次数多的方案因为每增加一次转运时间的不确定性链条就会更长时间窗违约的可能性也会变大。这类结论非常适合写进给业务方的分析报告里告诉他们“你预测越准选择空间越大”。5.3 代码运行不收敛或结果不稳定的排查链路我在调试这套代码时踩了几个坑拿出来逐个说。第一个坑是模糊比较的滥用。早期版本直接用三角模糊数的期望值去做容量约束判断比如判断需求量期望值是否小于容量结果在某个算例里出现了“期望值满足容量但可能度很低”的情况。后来改成possibility_le函数做约束检验问题立刻消失。因此目标函数里用期望值没问题约束条件里绝不能把期望值当成硬比较。第二个坑是枚举路径时把中转节点重复走了一遍或多遍。深度优先搜索如果不做visited记录很容易在两个节点之间来回震荡导致路径出现环。加了visited数组后所有路径都是简单路径这个问题就解决了。你如果发现自己跑出来的“最优路径”里有重复节点第一反应就应该是visited数组漏掉了。第三个坑是中转时间被重复计算。我早期在eval_route里同时加上了所有弧的中转时间但如果相邻两段的运输方式相同其实并没有换装这个时间不应该加。后来我把中转时间的计算统一放到节点层面并且只在方式发生切换时累加结果值才合理。这个细节很容易被忽略但一旦错时间窗约束会整体失真。第四个坑是容量约束只检验了单段弧但没有把需求量的模糊区间和整条路径的最小容量做联动。实际运输中路径上某个环节的容量瓶颈会决定整条链路的装载上限所以我在容量校验时取的是路径上所有所选方式容量的最小值再进行可能性判断这样更符合实际运输的约束逻辑。6. 这套方案在实际项目中要注意的应用边界6.1 模糊范围怎么定才不虚用三点估算法和业务方对齐三角模糊数的三个分量不是拍脑袋定的最好让业务方以“最乐观、最可能、最悲观”三个口径分别给数据。比如运输时间让运输经理按历史经验分别评估“最顺利什么时候到”“一般什么时候到”“最不顺利什么时候到”。需求量也类似。不要直接自己造数据否则模型的输入基础就不牢靠后面算得再漂亮也白搭。需要提醒的是模糊区间宽度未必对称。有些场景下需求量往上的空间比往下的空间大模糊数可以是(850, 1000, 1200)这种右偏形态。这种不对称信息是三角模糊数本身就能自然携带的建模时不要强行对称化。6.2 求解规模上限和算法扩展思路当前枚举框架适合中小规模网络。我的经验是节点数在15到20个以内、每种弧可选方式不超过3种时枚举法完全够用而且不需要调参行为可预期。一旦网络扩大到省域级或国家级运输网络节点上百、弧上千路径枚举数量会指数增长这时候绝对不能再靠枚举。扩展思路是换智能优化算法。我把算法替换成遗传算法时编码方式直接沿用路径节点序列加方式组合交叉算子采用顺序交叉变异算子随机替换某个节点或某段弧上的方式目标函数和约束检验逻辑完全复用只把外层循环换成GA框架。代码改动的核心在十几个函数内整体工作量不大。6.3 后续可以继续做的功能扩展这个模型的可扩展性比我想象中好。我后续计划接入三块内容一是把碳排放作为硬约束加入模型因为现在越来越多的客户要求物流服务商提供碳排放清单二是把多个需求点同时纳入规划因为现实中一个配送中心往往要同时服务多个客户路径优化从单源单汇变成单源多汇会更有实用价值三是把中转能力消耗和等待时间建模进去因为某些大型货站作业能力不足时中转等待本身就是一个灰色地带非常符合模糊时间建模的范畴。最后再分享一个我个人的习惯。代码跑出来的最优方案固然重要但永远不要直接拿这个方案去要求业务方执行。我通常会在结果表基础上额外生成两到三条次优方案连同模糊区间和置信水平一起提供给业务方。因为模糊模型本身已经表达了不确定性方案选择也应该保留这种弹性。决策者可能根据外部市场变化临时选择次优路径这时候模型的价值不是给一个唯一的正确答案而是给一套完整的决策依据。这套基于模糊需求和模糊运输时间的方法整体难度不高但每一步都需要想清楚“为什么这么建模”。如果你正卡在类似项目上建议先从一个小网络跑通代码再逐步加约束、加网络节点。代码框架搭好后后面所有改动都是往里填数据、加约束的事。有问题欢迎按自己的数据改造试试多跑几组不同置信水平的结果你会对“模糊优化”这四个字理解得更深。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑