案例 061 什么时候去换电最划算
案例 061 什么时候去换电最划算
摘要:换电不是"没电了才去",而是"什么时候去最不亏"。早换,正跑着的派单被打断;晚换,可能半路推车。本文把一日的 10 趟配送写成能量递推的混合整数规划:\(r_{k}\) 决定在第 \(k\) 趟之后是否换电,\(e_{k}\) 是趟末电量,0.62% 每 km 的衰减把里程与电量缝在一起,机会约束把"半路没电"的风险写进安全线。用 Gurobi 求出的最优时点是岗顶柜(第 7 趟),只换 1 次,净收益 279.8 元,推车概率 0.0%。两种凭直觉的策略都吃亏:按 30% 阈值换要 253.0 元且推车概率 28.1%,送完即换要 257.7 元、晚点 27 分钟。最优时点不在电量最低处,而在单量最低谷处。
关键词:换电时点;能量递推;机会约束;混合整数规划;电动自行车配送
1 问题提出
1.1 问题是什么
小哥这一天跑 10 趟、48 单、148.2 km。电池满电出门,每公里掉 0.62 个百分点,低于 15% 就得推车。表 1 是整天的时间表:里程从 12.4 km 到 18.2 km,收入从 23.6 元到 35.4 元,换电柜只在第 4、7、9 趟经过,柜前排队分别 9、2、12 分钟。
表 1 十趟的里程、单量、单量密度与换电柜位置
| 趟次 | 出发 | 单量 | 里程 /km | 收入 /元 | 单量密度 /(单每分) | 换电柜 | 柜前排队 /min | 无换电趟末电量 /% |
|---|---|---|---|---|---|---|---|---|
| 1 | 10:20 | 4 | 12.6 | 23.6 | 0.11 | — | — | 92.2 |
| 2 | 11:05 | 5 | 15.4 | 29.5 | 0.17 | — | — | 82.6 |
| 3 | 11:45 | 5 | 15.4 | 29.5 | 0.20 | — | — | 73.1 |
| 4 | 12:25 | 6 | 18.2 | 35.4 | 0.25 | 体育西柜 | 9 | 61.8 |
| 5 | 13:10 | 4 | 12.6 | 23.6 | 0.13 | — | — | 54.0 |
| 6 | 13:50 | 5 | 15.4 | 29.5 | 0.15 | — | — | 44.4 |
| 7 | 14:35 | 4 | 12.4 | 23.6 | 0.10 | 岗顶柜 | 2 | 36.8 |
| 8 | 15:15 | 4 | 12.6 | 23.6 | 0.11 | — | — | 28.9 |
| 9 | 16:00 | 6 | 18.2 | 35.4 | 0.22 | 客村柜 | 12 | 17.7 |
| 10 | 16:45 | 5 | 15.4 | 29.5 | 0.18 | — | — | 8.1 |
把表 1 的里程一路减下来,一天要走掉 91.9% 的电——超过 85% 的可用额度,所以不换电一定推车:第 9 趟结束只剩 17.7%,第 10 趟跑完是 8.1%。可换电又不是免费的:绕行 1.2 km、停车换电 3 分钟、柜前还要排队,这段时间本来能接单。于是问题变成一句话:把这一次换电插在十趟里的哪一趟之后,既不打断赚钱的时段,又不把自己逼到 15% 的红线上。
1.2 为什么要优化
第一,换电的代价随时段变化,而电量风险只跟位置有关。第 4 趟是午高峰,单量密度 0.25 单每分、柜前排队 9 分钟,换一次电要停 12 分钟,按表 1 的收入折算等于丢掉 9.2 元;第 7 趟是下午茶低谷,密度只有 0.10 单每分、不排队,同样的动作只丢 3.2 元。同一个动作,换个时点,代价差 2.8 倍。
第二,"电量够不够"是随机的,不能按平均值算。单趟里程有 16% 的波动,10 趟累积下来标准差接近 4.7 个百分点。按平均值刚好卡在 15% 上的计划,真实推车概率远不止一半——这就是阈值策略翻车的地方。
第三,三件事必须放在同一把尺子上量。换电次数、平均余量、推车与超时风险,单看任何一个都会得出错的结论:余量最高的方案(77.3%)恰恰是最贵的,因为余量是花钱买来的。
1.3 Gurobi 如何求解
模型是 10 个 0-1 换电变量、10 个连续电量状态、10 个接单比例,共 30 个决策量、41 条约束的 MILP。电量用"上限递推 + 满电封顶"表达(式 2),风险用机会约束写成线性的安全线(式 3),换电对派单的打断用一条线性不等式接到接单比例上(式 5)。求解在根节点即证最优;随机风险 \(\hat{P}\) 不进入 MIP,而在解出方案后用 6000 次蒙特卡洛回算(式 6),避免把非线性概率硬塞进模型。全枚举(7 种至多两次换电的组合)与 MIP 解完全重合,用作交叉校验。
2 数学模型
2.1 符号说明
\(k=1,\dots,n\) 为当日趟次(\(n=10\));\(d_{k}\) 为单趟里程(km);\(n_{k}\) 为单量;\(w_{k}\) 为单趟收入(元);\(\rho_{k}\) 为单量密度(单每分);\(g_{k}\) 为是否有换电柜;\(q_{k}\) 为柜前排队(min);\(r_{k}\) 为"第 \(k\) 趟后换电"的 0-1 变量;\(e_{k}\) 为趟末电量(%);\(x_{k}\) 为接单比例;\(\lambda_{k}\) 为换电打断系数;\(z_{\alpha}\) 为正态分位数。
2.2 目标函数
三项各有角色:\(\sum w_{k}x_{k}\) 是当天能挣到的钱,\(0.2\sum r_{k}\) 是换电本身的服务费(微乎其微),\(50\hat{P}\) 是把推车风险按每次 50 元的代价折进来。注意 \(x_{k}\) 不是"接不接这趟",而是"这趟能接几成"——换电占掉的时间,直接折算成这一趟丢掉的单量比例,这才是"打断派单"的准确写法。
2.3 约束条件
电量递推。这里用"上限"而不是"等式"是关键:\(r_{k}=1\) 时右边多出 100,若写成等式,电量会算成 100 以上甚至 180%;加上 \(e_{k}\le 100\) 封顶后,模型自动把"换电后满电"这件事表达对了——因为 \(e_{k}\) 只在下界里出现,模型会把它顶到允许的最大值,而那个最大值恰好就是真实电量。
机会约束。\(\sigma_{k}\) 是"从出门到第 \(k\) 趟结束"累计里程的标准差(按 16% 的相对波动、各趟独立),乘 0.62 换成电量百分点。\(z=1.645\) 对应 95% 的把握。这条式子把"平均值刚好够"变成"九成半的把握够",代价是要么早换、要么多换——这正是模型与拍脑袋的分界线。
换电点与次数。只能在第 4、7、9 趟换(\(g_{k}=1\)),一天最多两次。上限 2 次不是随便定的:可用电量 85% 除以单趟最大耗电 11.3%,两次足够覆盖整天;设成 1 次会让晚高峰那一段被卡死。
打断损失。在第 \(k\) 趟后换电,占用 \(3+q_{k}\) 分钟,这段时间原本的接单密度是 \(\rho_{k+1}\),于是下一趟的接单比例上限被压到 \(1-\lambda_{k}\)。\(\lambda\) 随时段变化(本案 0.39、0.14、0.54),这就是"什么时候换最划算"的定量答案:找 \(\lambda\) 最小的那一趟。
净收益口径。\(\hat{P}\) 由 6000 次模拟的推车频率估计,用于方案比较与正文报数。
2.4 规模与性质
10 个 0-1、20 个连续变量、41 条约束,规模小到可以全枚举校验。但它不是普通的集合覆盖:状态 \(e_{k}\) 把十趟串成一条链,任何一次换电都会改写后面所有趟的可行域,这就是"状态-决策"结构的麻烦之处——也正是它能给出"该在第几趟换"这种答案的原因。全枚举的 7 种组合中,只有 5 种同时满足硬下限与机会约束,其余因第 10 趟跌破 15% 被判不可行。
3 Gurobi 求解实现
3.1 建模要点
r = m.addVars(N, vtype=GRB.BINARY) # 在第 k 趟之后换电
e = m.addVars(N, lb=0.0, ub=100.0) # 趟末电量(上限 100 = 满电封顶)
x = m.addVars(N, lb=0.0, ub=1.0) # 本趟接单比例
for k in range(N):
pe = 100.0 if k == 0 else e[k-1]
m.addConstr(e[k] <= pe - 0.62*DD[k]*x[k] + 100.0*r[k]) # 上限递推
m.addConstr(e[k] >= 15.0 + BETA[k]) # 机会约束安全线
m.addConstr(r[k] <= G[k]) # 只能在有柜处换
m.addConstr(x[k] <= 1.0 - LAM[k-1]*r[k-1] if k else 1.0) # 换电打断下一趟
m.addConstr(gp.quicksum(r) <= 2)
m.setObjective(gp.quicksum(W[k]*x[k] - 0.2*r[k] for k in range(N)), GRB.MAXIMIZE)
两个实现细节。第一,电量递推要写成"\(\le\) + 封顶",不能写成等式:等式在换电时会把上一趟的余量重复计算,\(e\) 冲到 150 以上,随后所有"电量够不够"的判断全部失真;改成上限后,模型为满足下界会自动把 \(e\) 顶到 \(\min(100,\ e_{k-1}-0.62d_{k}x_{k}+100r_{k})\),与物理过程逐点相等。第二,风险不进目标函数,进约束:\(50\hat{P}\) 是非线性的,直接写进去要么线性化失真,要么大 M 爆炸;写成式 (3) 的安全线后,模型只需要保证"每一个时点都有 95% 的把握不推车",风险定价留给事后核账。
3.2 求解结果
表 2 三种择时策略的当日结果对照
| 策略 | 换电时点 | 次数 | 净收益 /元 | 较最优差 /元 | 推车概率 /% | 超时概率 /% | 平均余量 /% | 最低余量 /% |
|---|---|---|---|---|---|---|---|---|
| 阈值 30% 就换 | 第 9 趟 | 1 | 253.0 | +26.8 | 28.1 | 37.0 | 58.2 | 17.7 |
| 送完即换(65%) | 第 4 趟、第 9 趟 | 2 | 257.7 | +22.1 | 0.0 | 59.5 | 77.3 | 55.7 |
| 模型择时 | 第 7 趟 | 1 | 279.8 | 0 | 0.0 | 20.9 | 69.0 | 36.8 |
三行读完:阈值 30% 的策略在第 9 趟才换,净收益 253.0 元,推车概率 28.1%;见柜就换的保守派换两次,净 257.7 元,却把最后一趟拖晚 27 分钟;模型选在第 7 趟换,净 279.8 元,推车概率 0.0%、超时概率 20.9%。模型的解比阈值策略多赚 26.8 元,比保守派多赚 22.1 元,而且两个风险指标都不是最差的。
4 结果分析

图 1 三种择时策略下的趟末电量曲线,虚线为 15% 安全下限
4.1 电量曲线长什么样 图 1 三条曲线的锯齿就是换电动作:竖线处电量跳回 100%,之后按 0.62% 每 km 匀速下滑。阈值策略(红)一路滑到 17.7% 才在第 9 趟换,曲线在最右端才反弹,等于把整天的风险都压在了下午 4 点;模型择时(蓝)在第 7 趟就换,反弹点刚好落在下午茶的低谷;保守派(绿)换两次,曲线始终高高在上。 三条线的形状说明一件事:换电时点不是"某一点",而是"某一段"——它决定了后面所有趟的起跑电量。

图 2 十趟的里程—收入分布,气泡面积为单量,红色为经过换电柜的趟
4.2 数据全景:赚钱的趟和能换电的趟不重合 图 2 里横轴是里程、纵轴是收入,两者高度同向(多跑一单多挣 5.90 元)。三个红点(第 4、7、9 趟)分别落在右上、中下、右下:第 4 趟收入 35.4 元最肥但柜前排队 9 分钟,第 7 趟收入 23.6 元最瘦且不排队,第 9 趟里程最长、排队最久(12 分钟)。 这就是"换电时点"的结构性矛盾:最需要换电的时候(电量最低),往往也是最不该换的时候(正在高峰)。

图 3 三种策略的净收益与推车概率对照
4.3 三策略对比:钱差得不多,风险差得多 图 3 柱子是净收益,折线是推车概率。三种策略的钱依次是 253.0、257.7、279.8 元,最贵与最便宜只差 26.8 元;推车概率却是 28.1%、0.0%、0.0%。钱的口径看不出问题,风险的口径一眼就看出来了:阈值策略的 28.1% 意味着一周里有一天半要推车,而它省下的不过是 26.8 元。 反过来,保守派的推车概率是 0,却因为多换一次、多排两次队,白扔掉 22.1 元。

图 4 三策略的累计净收益阶梯
4.4 钱是一趟一趟挣回来的 图 4 把当天的收入按趟摊平累加,末点扣掉风险折价。三条线在前 6 趟几乎重合——因为换电还没发生;分岔出现在第 7 趟之后:模型择时的线最陡,因为它在低谷换电、几乎没丢单;阈值策略在第 9 趟之后少挣 16.1 元(换电排队丢单),末点再扣 14.1 元风险折价;保守派在第 4 趟就先丢 9.4 元。 换句话说,全天的差距不是慢慢拉开的,是在换电那一刻一次性决定的。

图 5 换电触发阈值对净收益与换电次数的影响
4.5 阈值这个旋钮到底该拧到几 图 5 横轴是阈值 \(\theta\),左轴净收益、右轴换电次数。阈值从 20% 抬到 65%,净收益先在 253.0 元附近趴着,到 40% 达到最高 279.8 元,再往上就被"多换一次"拖下去。 阶梯很清楚:阈值不超过 30% 时策略一直拖到第 9 趟,抬到 40% 就提前到第 7 趟,再抬到 65% 变成两次。模型的最优解正好落在 40% 这一档,说明"30% 才换"这个经验值偏保守了整整 10 个百分点——经验的错,不在保守,而在把一个跟时段无关的数字当成了安全线。

图 6 阈值与订单流强度的二维扫描,星号为本案参数
4.6 阈值 × 订单流强度 图 6 是五档阈值乘四档订单流强度的填色图。最浅的格子(最优)在阈值 40%、强度 1.8 倍处,值 422 元;最深的在阈值 20%、强度 0.6 倍处,只有 186 元,整张图的落差 235.9 元。 沿强度方向看:单量越密,整块颜色越浅(钱多了),而同一行内从左到右的落差也跟着变大——单量密的时候,换电那几分钟丢的单更多,"随便什么时候换"的代价被放大。 沿阈值方向看:每个强度下都有一个浅色的竖带,说明"该把阈值抬到 40% 上下"这条结论对订单流强度不敏感,是可以拿去做规则的。

图 7 订单流强度对最优净收益与最优换电时点的影响
4.7 第三维:单量越密,选错时点越贵 图 7 扫订单流强度从 0.6 到 1.6 倍。净收益从 208.9 涨到 386.1 元(单多了钱自然多);右轴的阶梯是"把时点从第 7 趟挪到第 9 趟"要少赚多少——从 23.3 元涨到 31.9 元,翻了 1.4 倍。 而六个强度下最优时点一步没动,始终是第 7 趟:订单流整体变密时,高峰与低谷的"相对贵贱"没变,第 7 趟仍是全天的价格洼地;变的是选错的代价,越密越输不起。

图 8 净收益—推车概率的非支配前沿,灰区为不可接受风险区
4.8 前沿与不可行区 图 8 横轴净收益、纵轴推车概率。本案只有第 4、7、9 趟能换,至多两次共 7 种组合(深蓝,其中 5 种可行),浅灰小点是"假如十趟都能换"的 56 种组合,用来对照柜子密度的影响。左上角的叉是不换电:一分不花,却有 92.4% 的概率推车。灰区是风险超过 5% 的不可接受带,浅灰点里掉进去的那些,全是"撑到很晚才换"的方案——钱省在了刀刃上,人也进了灰区。 非支配前沿(红虚线)沿着灰区边缘从左下爬到右上:把风险从 28.1% 压到 0,最便宜的办法就是 26.8 元的代价;而要在不推车的前提下再多挣一点,前沿已经贴顶。 三个标记里阈值策略落在灰区边线上,保守派在右下(安全但贵),模型择时(星)贴着前沿右上角——这就是"最划算"三个字的几何含义。

图 9 两种策略日末剩余电量的模拟分布与累计概率
4.9 余量的分布,而不是余量的均值 图 9 是 6000 次模拟的日末电量分布。阈值策略(红)的分布左端被 15% 的红线切掉一大块:28.1% 的模拟次数直接推车;模型择时(蓝)的日末电量整条在 60.1% 以上,全程最低点的 5% 分位也有 30.3%。 两条累计概率曲线在 15% 处的高度差,就是两种策略的风险差。这张图解释了一件事:平均余量 58.2% 对 69.0% 看着只差 10.7 个点,但分布的形状完全不同——一个是"均值还行、尾巴要命",一个是"整条都安全"。

图 10 三策略的电量分段消耗结构
4.10 电是怎么一段一段用掉的 图 10 把每两次换电之间的耗电拆成一段一段堆起来,虚线是 85% 的可用额度。阈值策略只有两段:第一段一口气吃掉 82.3%,几乎顶到虚线才停;模型择时切成 63.2% 与 28.6% 两段,两段都留了余量;保守派切三段,累计 91.9%,反而没跑满。 堆叠图最有说服力的一句是:阈值策略并不"省电",它只是把电一次性赌在了最后;模型择时也不是"多用电",而是把同一份电切成两段安全的花法。
5 结论
- 答案是第 7 趟换一次。 净收益 279.8 元,推车概率 0.0%,超时概率 20.9%,平均余量 69.0%。这个时点既不是电量最低的第 9 趟,也不是最宽裕的第 4 趟,而是单量密度最低、柜前不排队的第 7 趟。
- 按 30% 阈值换电要付 26.8 元的学费。 它一路撑到第 9 趟(电量 17.7%)才换,推车概率 28.1%、超时 37.0%,是三种策略里唯一落进不可接受区的。"低于 30% 就换"这条经验,在换电柜稀疏的片区等于"低于 30% 时已经没有柜了"。
- 见柜就换同样不划算,多花 22.1 元。 保守派换两次、排两次队,把最后一趟拖晚 27 分钟,超时概率 59.5%。它换来的平均余量 77.3% 并没有变成收入——余量本身不值钱,余量买到的"不出事"才值钱,而 0.0% 的风险用一次换电就够了。
- 阈值该拧到 40% 上下,而不是 30%。 图 5 显示净收益在阈值 40% 处最高(279.8 元),且这条结论在订单流强度 0.6 到 1.8 倍的范围内都成立。经验值可以保留,但要按片区柜距重新标定——柜越稀,阈值越高。
- 换电时点的本质是"用几分钟的确定损失,换几十个百分点的尾部风险"。 第 4 趟换丢 9.2 元,第 7 趟换只丢 3.2 元,第 9 趟换要冒 28.1% 的推车概率。把这三笔账摊开,答案是唯一的;把这三笔账混在一起,答案就变成了"看感觉"。
参考文献
[1] Gurobi Optimization LLC. Gurobi Optimizer Reference Manual[Z]. 2024.
[2] Kellerer H, Pferschy U, Pisinger D. Knapsack Problems[M]. Berlin: Springer, 2004.
[3] Martello S, Toth P. Knapsack Problems: Algorithms and Computer Implementations[M]. Chichester: John Wiley & Sons, 1990.
[4] 司守奎, 孙玺菁. 数学建模算法与应用[M]. 3 版. 北京: 国防工业出版社, 2021.
复现方式:python -u batch_061.py;数据与结果见同目录 data_061.csv / results_061.json,图见 figs/

浙公网安备 33010602011771号