用Yalmip玩转0-1变量:从物流选址到逻辑约束的5个经典案例

用Yalmip玩转0-1变量:从物流选址到逻辑约束的5个经典案例

如果你曾经被那些“要么选,要么不选”的决策问题困扰过——比如到底在哪个城市建仓库最划算,或者如何安排生产线才能让机器开关最省电——那么你其实已经摸到了离散优化的大门。这类问题里,决策变量往往不是连续变化的数字,而是非此即彼的二元选择。在MATLAB的Yalmip建模工具箱里,binvar就是专门用来定义这种0-1变量的利器。但很多工程师的认知可能就停留在“哦,binvar就是定义0-1变量”,然后照着模板写几行代码。这就像只学会了螺丝刀的握法,却从没想过它能拧出多么精密的机械结构。

实际上,binvar的潜力远不止于简单的“是/否”标记。它更像是一把逻辑建模的瑞士军刀,能够将现实世界中复杂的“如果...那么...”、“至少满足一个”、“不能同时发生”等业务规则,转化为优化求解器(如Gurobi、CPLEX)能够理解的线性或二次约束。掌握它,意味着你能将许多看似棘手的运营难题,转化为可计算、可优化的数学模型。本文将从五个源自工业实践的经典案例出发,不仅展示binvar的基础用法,更深入剖析如何用“大M法”等技巧处理复杂的逻辑关系与分段函数,并分享在Gurobi求解器下提升求解效率的参数调优心得。我们的目标是,让你手里的binvar从一把简单的起子,变成一套能解决复杂工程问题的组合工具。

1. 案例一:多仓库选址与容量分配——构建成本最优的物流网络

想象一下,你是一家电商公司的物流规划师。公司业务扩张,需要在华北地区的五个候选城市(北京、天津、石家庄、太原、济南)中,选择至多三个城市建立区域性配送中心。每个城市建仓有固定的建设成本(如土地、基建),并且每个仓库有最大处理容量限制。你的任务是在满足所有城市客户需求的前提下,最小化总成本(建设成本+运输成本)。

这是一个典型的设施选址问题(Facility Location Problem)binvar在这里的核心作用是决定在哪个城市建仓(建或不建)。我们首先定义决策变量:

% 假设有5个候选地点,20个需求点
num_sites = 5;
num_customers = 20;

% 决策变量
% y_i = 1 表示在第i个候选地点建仓,否则为0
y = binvar(num_sites, 1, 'full');
% x_ij 表示从仓库i运往客户j的货物量(连续变量)
x = sdpvar(num_sites, num_customers, 'full');

接下来是目标函数和约束。目标是最小化总成本,包括固定建设成本和可变运输成本:

% 参数:固定建设成本f_i, 单位运输成本c_ij, 仓库容量cap_i, 客户需求d_j
f = [500; 400; 300; 350; 450]; % 万元
c = rand(num_sites, num_customers) * 10; % 随机生成运输成本
cap = [800; 600; 500; 550; 700]; % 千件
d = randi([20, 100], 1, num_customers); % 随机生成客户需求

% 目标函数:总成本 = 固定成本 + 运输成本
objective = f' * y + sum(sum(c .* x));

% 约束条件
constraints = [];

% 1. 每个客户的需求必须被满足
for j = 1:num_customers
    constraints = [constraints, sum(x(:, j)) == d(j)];
end

% 2. 从仓库i发出的货物总量不能超过其容量,且只有建仓了才能发货
for i = 1:num_sites
    constraints = [constraints, sum(x(i, :)) <= cap(i) * y(i)];
end

% 3. 至多建3个仓库
constraints = [constraints, sum(y) <= 3];

% 4. 非负约束
constraints = [constraints, x >= 0];

注意:约束 sum(x(i, :)) <= cap(i) * y(i) 是建模的精髓。当 y(i)=0(不建仓)时,不等式右边为0,强制 x(i, :)=0,即该仓库不能发货。当 y(i)=1时,约束变为正常的容量限制。这种用0-1变量激活或禁用一组连续变量约束的技巧,是离散优化中的基础且重要的模式。

最后,调用求解器求解。这里我们以Gurobi为例:

% 设置求解器为Gurobi
ops = sdpsettings('solver', 'gurobi', 'verbose', 1);
% 求解最小化问题
diagnostics = optimize(constraints, objective, ops);

if diagnostics.problem == 0
    disp('求解成功!');
    optimal_y = value(y);
    optimal_x = value(x);
    optimal_cost = value(objective);
    fprintf('最优建仓方案(1为建,0为不建): %s\n', mat2str(optimal_y'));
    fprintf('最小总成本: %.2f 万元\n', optimal_cost);
else
    disp('求解失败,请检查模型或参数。');
end

这个案例清晰地展示了binvar如何将“建或不建”的离散决策嵌入到线性规划框架中。通过y变量,我们优雅地控制了与之关联的连续决策x的有效性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值