Task 1: 2021年MFP访问计划——需求驱动的频次分配与日历排程
摘要
本文提出一套因果逻辑清晰、闭环可审计的2021年MFP访问频次分配与日历排程方案。核心创新点:
- 截断回归修正:识别到9个站点历史服务量 $\mu_i > 250$(最高396.6),说明高需求站点的观测数据被容量截断,采用截断正态模型恢复真实需求
\tilde{\mu}_i - 质量加权有效性:考虑高服务量下每户分配食物减少的质量折扣
- 满足率公平性:以"年度服务量/真实需求"的均等程度衡量公平,而非简单的访问次数均等
方案遵循四阶段结构:需求估计 → 频次分配 → 效果评估 → 日历排程。
整体流程图
Mermaid版本(GitHub可渲染)
flowchart TB
subgraph INPUT["数据输入"]
A[data.xlsx<br/>70站点数据]
end
subgraph TASK1["TASK 1: 基础排程"]
direction TB
subgraph CORE["核心流程 ✅ 已完成"]
B1[01_clean.py<br/>数据清洗]
B2[02_demand_correction.py<br/>截断回归修正]
B3[03_allocate.py<br/>Hamilton分配]
B4[04_evaluate.py<br/>指标计算]
B5[05_schedule.py<br/>日历排程]
B1 --> B2 --> B3 --> B4
B3 --> B5
end
subgraph VALIDATE["结果验证 ⏳ 待完成"]
V1[06_validate.py<br/>约束检验]
V2[07_backtest.py<br/>历史回测]
end
subgraph SENSITIVITY["敏感性分析 ⏳ 待完成"]
S1[08_sensitivity.py<br/>参数扫描]
end
subgraph VISUAL["可视化 ⏳ 待完成"]
P1[09_visualize.py<br/>图表生成]
end
CORE --> VALIDATE
CORE --> SENSITIVITY
VALIDATE --> VISUAL
SENSITIVITY --> VISUAL
end
subgraph TASK2["TASK 2: 天气响应 ⏳"]
C1[2a或2b方案]
end
subgraph TASK3["TASK 3: 双站点同车 ⏳"]
D1[共生站点优化]
end
subgraph TASK4["TASK 4: Executive Summary ⏳"]
E1[1页执行摘要]
end
A --> B1
VISUAL --> TASK2
VISUAL --> TASK3
TASK2 --> TASK4
TASK3 --> TASK4
style CORE fill:#90EE90
style VALIDATE fill:#FFE4B5
style SENSITIVITY fill:#FFE4B5
style VISUAL fill:#FFE4B5
ASCII版本(详细)
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ TASK 1 完整流程 │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ 核心流程 [已完成 ✓] │ │
│ │ │ │
│ │ data.xlsx ──▶ 01_clean ──▶ 02_demand ──▶ 03_allocate ──▶ 04_evaluate │ │
│ │ correction │ │ │
│ │ ▼ │ │
│ │ 05_schedule │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ │ │ │
│ ┌─────────────┴────────────┬───────────┴───────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ 结果验证 [待完成 ⏳] │ │ 敏感性分析 [待完成 ⏳] │ │ 可视化 [待完成 ⏳] │ │
│ │ │ │ │ │ │ │
│ │ 06_validate.py │ │ 08_sensitivity.py │ │ 09_visualize.py │ │
│ │ ┌──────────────────┐ │ │ ┌──────────────────┐ │ │ ┌──────────────────┐ │ │
│ │ │• 约束满足检验 │ │ │ │• C ∈ {350,400,450}│ │ │ │• 站点地图(需求) │ │ │
│ │ │ - Σk=730? │ │ │ │• p阈值扫描 │ │ │ │• k分布直方图 │ │ │
│ │ │ - k≥1? │ │ │ │• C̄ ∈ {200,250,300}│ │ │ │• E-F权衡曲线 │ │ │
│ │ │ - 每日2站点? │ │ │ │ │ │ │ │• 日历热力图 │ │ │
│ │ └──────────────────┘ │ │ └──────────────────┘ │ │ │• 间隔分布箱线图 │ │ │
│ │ │ │ │ │ └──────────────────┘ │ │
│ │ 07_backtest.py │ │ 输出: │ │ │ │
│ │ ┌──────────────────┐ │ │ • 参数-指标表 │ │ 输出: │ │
│ │ │• 2019数据回测 │ │ │ • Pareto前沿图 │ │ • figures/*.png │ │
│ │ │• 预测vs实际对比 │ │ │ │ │ • 论文插图 │ │
│ │ │• 残差分析 │ │ │ │ │ │ │
│ │ └──────────────────┘ │ │ │ │ │ │
│ └──────────────────────┘ └──────────────────────┘ └──────────────────────┘ │
│ │ │
└────────────────────────────────────────┼───────────────────────────────────────────────┘
│
▼
┌────────────────────┴────────────────────┐
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ TASK 2: 天气响应 [待完成] │ │ TASK 3: 双站点 [待完成] │
└──────────────────────────┘ └──────────────────────────┘
│ │
└────────────────┬────────────────────────┘
▼
┌──────────────────────────┐
│ TASK 4: 执行摘要 [待完成] │
└──────────────────────────┘
当前进度与待完成事项
| 模块 | 状态 | 脚本 | 说明 |
|---|---|---|---|
| 数据清洗 | ✅ 完成 | 01_clean.py |
字段标准化 |
| 需求修正 | ✅ 完成 | 02_demand_correction.py |
截断回归 |
| 频次分配 | ✅ 完成 | 03_allocate.py |
Hamilton方法 |
| 指标计算 | ✅ 完成 | 04_evaluate.py |
E1,E2,F1,F2 |
| 日历排程 | ✅ 完成 | 05_schedule.py |
贪心+局部优化 |
| 约束验证 | ⏳ 待完成 | 06_validate.py |
硬约束检验 |
| 历史回测 | ⏳ 待完成 | 07_backtest.py |
模型有效性 |
| 敏感性分析 | ⏳ 待完成 | 08_sensitivity.py |
参数稳健性 |
| 可视化 | ⏳ 待完成 | 09_visualize.py |
论文图表 |
运行结果摘要
| 指标 | 推荐方案 | 均匀分配 | 2019缩放 | 变化 |
|---|---|---|---|---|
| E1 (总服务量) | 140,121 | 104,797 | 104,071 | +34.6% |
| E2 (质量加权) | 131,673 | 101,309 | 100,264 | +31.3% |
| F1 (Gini系数) | 0.314 | 0.026 | 0.092 | 公平性降低 |
| F2 (最低满足率) | 2.0 | 8.4 | 5.0 | - |
核心发现:按需求比例分配可提升34.6%的总服务量,但存在有效性-公平性权衡。
1. 问题形式化
1.1 输入数据
| 字段 | 符号 | 说明 |
|---|---|---|
| 位置 | (lat_i, lon_i) |
经纬度坐标 |
| 2019年访问次数 | v_i |
历史频次,总计722次 |
| 单次服务人数均值 | \mu_i |
观测均值,范围[17.2, 396.6] |
| 单次服务人数标准差 | \sigma_i |
观测波动,范围[2.2, 93.5] |
1.2 运营参数
| 参数 | 值 | 来源 |
|---|---|---|
| 卡车物理运力 | 15,000 lbs | 题面明确 |
| 典型服务户数 | [200, 250] | 题面"typical" |
| 每日可派车次 | 2 | 题面 |
年度总访问次数 N |
730 | 365 \times 2 |
1.3 硬约束
\sum_{i=1}^{70} k_i = 730 \tag{C1: 资源约束}
k_i \geq 1 \tag{C2: 覆盖约束}
|\text{sites on day } t| = 2 \tag{C3: 每日容量}
2. 阶段一:真实需求估计(截断回归)
2.1 问题本质:为什么需要修正?
底层逻辑:
题面说"typical visit serves 200-250 families",但数据中 $\mu_{max} = 396.6$。这说明:
- 200-250不是硬上限:高需求站点可以服务更多家庭
- 存在隐性容量约束:卡车运力15000磅 ÷ 每户约38-75磅 ≈ 200-400户
- 观测被截断:当真实需求 > 容量时,只能观测到容量值
真实需求分布: 观测到的分布:
│ │
│ ╱╲ │ ╱╲
│ ╱ ╲ │ ╱ ╲▓▓▓ ← 被截断部分
│ ╱ ╲ │ ╱ │
│ ╱ ╲ │ ╱ │
├───────────── ├───────┤
0 μ̃ C 0 μ C
因此:直接用 \mu_i 会系统性低估高需求站点的真实需求。
2.2 截断概率的推导
假设:真实需求 \tilde{D}_i \sim \mathcal{N}(\tilde{\mu}_i, \sigma_i^2)
推导:截断概率 = 真实需求超过容量C的概率
p_i^{trunc} = P(\tilde{D}_i > C) = P\left(Z > \frac{C - \tilde{\mu}_i}{\sigma_i}\right) = 1 - \Phi\left(\frac{C - \tilde{\mu}_i}{\sigma_i}\right)
近似:由于我们不知道 $\tilde{\mu}_i$,用观测值 \mu_i 近似:
p_i^{trunc} \approx 1 - \Phi\left(\frac{C - \mu_i}{\sigma_i}\right)
物理意义:p_i^{trunc} 越大,说明该站点越可能被截断,需要更大的修正。
2.3 修正公式的推导
截断正态的条件期望(Mills ratio):
对于 $X \sim \mathcal{N}(\mu, \sigma^2)$,有:
E[X | X > c] = \mu + \sigma \cdot \frac{\phi\left(\frac{c-\mu}{\sigma}\right)}{1 - \Phi\left(\frac{c-\mu}{\sigma}\right)}
简化近似:
当截断概率 p^{trunc} 较小时,修正量近似与 p^{trunc} 线性相关:
\tilde{\mu}_i \approx \mu_i \cdot (1 + \alpha \cdot p_i^{trunc})
取 $\alpha = 0.4$(经验系数,可通过敏感性分析调整)。
分段处理的原因:
- 当 $p^{trunc} < 0.02$:截断概率很低,修正量可忽略
- 当 $p^{trunc} \geq 0.02$:存在显著截断,需要修正
2.4 实际修正结果
| site_id | 站点名称 | \mu |
\sigma |
p^{trunc} |
\tilde{\mu} |
修正幅度 |
|---|---|---|---|---|---|---|
| 66 | MFP Waverly | 396.6 | 51.9 | 0.474 | 471.9 | +19.0% |
| 2 | MFP Avoca | 314.6 | 57.3 | 0.068 | 323.2 | +2.7% |
| 13 | MFP College TC3 | 261.5 | 92.0 | 0.066 | 268.4 | +2.6% |
| 17 | MFP Endwell | 285.2 | 60.8 | 0.030 | 288.6 | +1.2% |
| 30 | MFP Redeemer | 230.6 | 93.5 | 0.035 | 233.8 | +1.4% |
3. 阶段二:频次分配模型
3.1 分配原则的底层逻辑
题面要求:"frequency informed by total demand in surrounding communities"
问题:什么是"周边社区需求"?
两种理解:
- ❌ 用空间核平滑估计(循环论证:用供给估计需求)
- ✅ 每个站点本身就服务其周边社区,
\tilde{\mu}_i就是需求代理
我们的选择:直接用修正后的 \tilde{\mu}_i 作为"周边社区需求"的代理。
为什么按比例分配?
假设目标是最大化总服务量且保证公平:
- 最大化
\sum k_i \mu_isubject to\sum k_i = N - 拉格朗日条件:
\frac{\partial}{\partial k_i}(k_i \mu_i - \lambda k_i) = \mu_i - \lambda = 0
这说明最优解是 $k_i \propto \mu_i$(或 $\tilde{\mu}_i$)。
3.2 为什么用Hamilton方法?
问题:按比例分配得到的是实数,需要转换为整数。
Hamilton方法(最大余数法)的优点:
- 保证总和:
\sum k_i = N严格成立 - 公平性:余数大的站点优先获得额外1次
- 可解释:政治选举中广泛使用,逻辑透明
替代方法对比:
| 方法 | 优点 | 缺点 |
|---|---|---|
| 四舍五入 | 简单 | 总和可能不等于N |
| 向下取整+贪心 | 简单 | 可能不公平 |
| Hamilton | 公平、总和准确 | 稍复杂 |
| 整数规划 | 可加约束 | 过于复杂 |
3.3 分配结果验证
- 总访问次数:
\sum k_i = 730✓ - 访问次数范围:
[2, 32] - 覆盖约束:
\min k_i = 2 \geq 1✓
4. 阶段三:效果评估指标
4.1 有效性指标的设计逻辑
E1:原始总服务量
E_1 = \sum_{i=1}^{70} k_i \cdot \mu_i
问题:E1假设服务量与访问次数线性增长,但忽略了质量下降。
E2:质量加权服务量
底层逻辑:当 \mu_i > 250 时,每户获得的食物量下降。
\text{每户食物量} = \frac{15000 \text{ lbs}}{\mu_i}
当 \mu_i = 250 时,每户60磅(典型值)。
当 \mu_i = 400 时,每户37.5磅(低于典型)。
质量折扣因子:
q(\mu) = \min\left(1, \frac{250}{\mu}\right) = \begin{cases} 1 & \mu \leq 250 \\ \frac{250}{\mu} & \mu > 250 \end{cases}
物理意义:q(\mu) 表示"相对于典型服务质量的比例"。
4.2 公平性指标的设计逻辑
为什么不用"访问次数相等"衡量公平?
题面说"are some served much better than others"——关键词是served,不是visited。
需求100的站点访问10次 vs 需求200的站点访问10次 → 后者服务不足。
满足率的定义:
r_i = \frac{\text{年度服务量}}{\text{年度需求}} = \frac{k_i \cdot \mu_i}{\tilde{\mu}_i}
为什么用Gini系数?
- Gini系数是衡量分布不均等的标准指标
- 取值[0,1],0表示完全均等,1表示完全不均等
- 易于解释:收入分配、资源分配广泛使用
4.3 评估结果
| 方案 | E1 | E2 | F1 (Gini) | F2 (min r) |
|---|---|---|---|---|
| 推荐方案 | 140,121 | 131,673 | 0.314 | 2.00 |
| 均匀分配 | 104,797 | 101,309 | 0.026 | 8.41 |
| 2019缩放 | 104,071 | 100,264 | 0.092 | 5.00 |
有效性-公平性权衡:
F1 (Gini, 越小越公平)
▲
0.4 │ ● 推荐方案 (E1=140k)
│
0.3 │
│
0.2 │
│
0.1 │ ● 2019缩放 (E1=104k)
│
0.0 │● 均匀分配 (E1=105k)
└────────────────────────────▶ E1 (总服务量)
100k 120k 140k
5. 阶段四:日历排程
5.1 排程目标的底层逻辑
为什么要均匀分布访问日期?
题面说"schedule published months in advance to help clients plan"。
如果某站点访问间隔不均匀(如:1月5次,2月0次),客户难以规划。
理想间隔:
\Delta_i^* = \frac{365}{k_i}
例如:k_i = 12 次/年 → 理想间隔 ≈ 30天/次
5.2 贪心算法的设计逻辑
为什么不用整数规划?
730个访问事件 × 365天 = 26万个0-1变量,计算复杂度过高。
贪心策略:
- 为每个访问事件计算"理想日期"
- 按理想日期排序
- 依次分配到最近的可用槽位
为什么有效?
- 理想日期已经考虑了均匀分布
- 按顺序分配避免了冲突
- 局部优化可进一步改善
5.3 排程结果
- 365天全部满载 ✓
- 平均间隔:55.4天
- 最大间隔:179天(低频站点)
6. 待完成:结果验证
6.1 约束满足检验 (06_validate.py)
| 检验项 | 公式 | 预期结果 |
|---|---|---|
| 资源约束 | \sum k_i = 730 |
通过 |
| 覆盖约束 | \min k_i \geq 1 |
通过 |
| 日容量约束 | 每日恰好2站点 | 通过 |
| 无重复约束 | 同一天不重复访问同一站点 | 通过 |
6.2 模型有效性验证 (07_backtest.py)
方法:留一交叉验证(Leave-One-Out)
- 用2019年的69个站点数据训练模型
- 预测第70个站点的
\tilde{\mu}和k - 与实际值对比
- 重复70次,计算平均误差
评估指标:
- MAPE(平均绝对百分比误差)
- $R^2$(决定系数)
7. 待完成:敏感性分析
7.1 参数扫描 (08_sensitivity.py)
| 参数 | 基准值 | 扫描范围 | 影响 |
|---|---|---|---|
有效容量 C |
400 | [350, 450] | 截断修正强度 |
截断阈值 p^{trunc} |
0.02 | [0.01, 0.10] | 修正站点数 |
质量阈值 \bar{C} |
250 | [200, 300] | E2计算 |
7.2 敏感性报告格式
C = 350: 修正7站点, E1=141,234, F1=0.318
C = 400: 修正5站点, E1=140,121, F1=0.314 ← 基准
C = 450: 修正3站点, E1=139,456, F1=0.310
8. 待完成:可视化
8.1 图表清单 (09_visualize.py)
| 图编号 | 图名 | 类型 | 用途 |
|---|---|---|---|
| Fig.1 | 站点地图 | 散点图+地图底图 | 展示站点分布和需求 |
| Fig.2 | 需求修正对比 | 柱状图 | 展示修正前后μ变化 |
| Fig.3 | 频次分配分布 | 直方图 | 展示k的分布 |
| Fig.4 | 有效性-公平性权衡 | 散点图 | Pareto前沿 |
| Fig.5 | 日历热力图 | 热力图 | 全年排程概览 |
| Fig.6 | 访问间隔箱线图 | 箱线图 | 间隔分布 |
| Fig.7 | 敏感性分析 | 折线图 | 参数影响 |
8.2 图表示例说明
Fig.1 站点地图:
- X轴:经度
- Y轴:纬度
- 点大小:$\mu_i$(需求)
- 点颜色:$k_i$(访问频次)
Fig.4 有效性-公平性权衡:
- X轴:E2(质量加权服务量)
- Y轴:F1(Gini系数,越小越公平)
- 多个方案的散点
- Pareto前沿曲线
Fig.5 日历热力图:
- X轴:月份(1-12)
- Y轴:日期(1-31)
- 颜色:该日访问的站点需求总和
9. 可复现流水线
9.1 完整脚本结构
task1/
├── 01_clean.py ✅ 数据清洗
├── 02_demand_correction.py ✅ 截断修正
├── 03_allocate.py ✅ 频次分配
├── 04_evaluate.py ✅ 指标计算
├── 05_schedule.py ✅ 日历排程
├── 06_validate.py ⏳ 约束验证
├── 07_backtest.py ⏳ 历史回测
├── 08_sensitivity.py ⏳ 敏感性分析
├── 09_visualize.py ⏳ 可视化
├── 01_clean.xlsx
├── 02_demand.xlsx
├── 03_allocate.xlsx
├── 04_metrics.xlsx
├── 05_schedule.xlsx
└── figures/ ⏳ 图表输出目录
9.2 运行命令
# 核心流程(已完成)
python task1/01_clean.py
python task1/02_demand_correction.py
python task1/03_allocate.py
python task1/04_evaluate.py
python task1/05_schedule.py
# 验证与分析(待完成)
python task1/06_validate.py
python task1/07_backtest.py
python task1/08_sensitivity.py
python task1/09_visualize.py
10. 假设与局限性
10.1 显式假设
| 编号 | 假设 | 依据 | 影响 |
|---|---|---|---|
| A1 | 真实需求服从正态分布 | 中心极限定理 | 截断修正公式 |
| A2 | 有效容量 C=400 |
\mu_{max}=396.6 |
修正强度 |
| A3 | 2021年需求≈2019年 | 题面要求 | 整体方案有效性 |
| A4 | 全年365天运营 | 简化假设 | 总访问次数 |
| A5 | 每日2站点硬约束 | 题面 | 排程可行性 |
10.2 局限性
- 截断修正简化:使用线性近似而非完整MLE
- 需求外生性:未建模"访问频次→需求"的反馈效应
- 空间相关性:未考虑相邻站点需求相关性
- 季节性:未考虑冬季需求下降
11. 结论与建议
11.1 方法论贡献
- 截断偏误识别:发现高需求站点
\mu被低估 - 质量-数量权衡:引入质量折扣因子
- 满足率公平:以服务充足度衡量公平
11.2 对FBST的运营建议
- MFP Waverly:需求异常高($k=32$),建议增派资源
- 数据收集:记录"被拒服务人数"以更准确估计需求
- 动态调整:季度末复盘,调整下季度排程
11.3 有效性-公平性权衡
推荐方案牺牲公平性换取服务量最大化。若FBST优先考虑公平:
- 可设置
k_i上下限约束 - 或使用混合目标函数
\max (E_2 - \lambda \cdot F_1)