Files
mcm-mfp/task1/README.md
2026-01-19 10:14:46 +08:00

530 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Task 1: 2021年MFP访问计划——需求驱动的频次分配与日历排程
## 摘要
本文提出一套**因果逻辑清晰、闭环可审计**的2021年MFP访问频次分配与日历排程方案。核心创新点
1. **截断回归修正**识别到9个站点历史服务量 $\mu_i > 250$最高396.6),说明高需求站点的观测数据被容量截断,采用截断正态模型恢复真实需求 $\tilde{\mu}_i$
2. **质量加权有效性**:考虑高服务量下每户分配食物减少的质量折扣
3. **满足率公平性**:以"年度服务量/真实需求"的均等程度衡量公平,而非简单的访问次数均等
方案遵循四阶段结构:需求估计 → 频次分配 → 效果评估 → 日历排程。
---
## 整体流程图
```
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ 数据输入层 │
│ │
│ ┌─────────────┐ │
│ │ data.xlsx │ 70站点: 位置、2019访问次数、μ、σ
│ └──────┬──────┘ │
└───────────┼─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ TASK 1: 基础排程 [已完成 ✓] │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 01_clean.py │────▶│02_demand_ │────▶│03_allocate.py│────▶│04_evaluate.py│ │
│ │ │ │correction.py │ │ │ │ │ │
│ │ 数据清洗 │ │ 截断回归修正 │ │ Hamilton分配 │ │ 指标计算 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────┬───────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │01_clean.xlsx │ │02_demand.xlsx│ │03_allocate. │ │04_metrics. │ │
│ │ │ │ μ̃ (5站点修正)│ │xlsx (k分配) │ │xlsx │ │
│ └──────────────┘ └──────────────┘ └──────┬───────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │05_schedule.py│ │
│ │ 日历排程生成 │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │05_schedule. │ │
│ │xlsx (365天) │ │
│ └──────┬───────┘ │
└─────────────────────────────────────────────────────┼───────────────────────────────────┘
┌─────────────────────────────────────────┴─────────────────────────────────┐
│ │
▼ ▼
┌───────────────────────────────────────────┐ ┌───────────────────────────────────────────┐
│ TASK 2: 天气响应调度 [待完成] │ │ TASK 3: 双站点同车 [待完成] │
│ │ │ │
│ 选项 2a: 减少站点数 + 优化位置 │ │ ┌─────────────────────────────────────┐ │
│ ┌─────────────────────────────────────┐ │ │ │ 1. 共生站点筛选 │ │
│ │ • 站点聚类 (K-means/层次聚类) │ │ │ │ • 距离约束: dist(i,j) < D_max │ │
│ │ • 确定最优站点数 K < 70 │ │ │ │ • 需求约束: μ_i + μ_j ≤ 400 │ │
│ │ • 客户愿意多走的距离建模 │ │ │ │ • 稳定性约束: CV_i, CV_j < 阈值 │ │
│ │ • 重新分配频次 │ │ │ └─────────────────────────────────────┘ │
│ └─────────────────────────────────────┘ │ │ │ │
│ 或 │ │ ▼ │
│ 选项 2b: 保持70站点 + 优化时间协调 │ │ ┌─────────────────────────────────────┐ │
│ ┌─────────────────────────────────────┐ │ │ │ 2. 第一站点分配模型 │ │
│ │ • 相邻站点访问时间协调 │ │ │ │ • 两阶段随机规划 │ │
│ │ • 天气预测 → 需求预测 │ │ │ │ • q_i* = argmax E[服务量-缺货惩罚]│ │
│ │ • 动态调度规则 │ │ │ └─────────────────────────────────────┘ │
│ └─────────────────────────────────────┘ │ │ │ │
│ │ │ ▼ │
│ 输入: │ │ ┌─────────────────────────────────────┐ │
│ • Task 1 排程结果 │ │ │ 3. 频次重分配 │ │
│ • 历史天气数据 (如有) │ │ │ • 共生站点合并需求 │ │
│ • 站点间距离矩阵 │ │ │ • Hamilton方法重新分配 │ │
│ │ │ └─────────────────────────────────────┘ │
│ 输出: │ │ │ │
│ • 改进后的排程方案 │ │ ▼ │
│ • 性能提升量化 │ │ ┌─────────────────────────────────────┐ │
│ │ │ │ 4. 日历排程 + 对比评估 │ │
└───────────────────────────────────────────┘ │ │ • 与 Task 1 对比 E1, E2, F1, F2 │ │
│ └─────────────────────────────────────┘ │
│ │
│ 输入: │
│ • Task 1 分配结果 (03_allocate.xlsx) │
│ • 站点距离矩阵 │
│ │
│ 输出: │
│ • 共生站点配对表 │
│ • 第一站点分配方案 │
│ • 新日历排程 │
└───────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ TASK 4: Executive Summary [待完成] │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ 1页执行摘要: │ │
│ │ • Task 1 方案优势: 总服务量提升 34.6% │ │
│ │ • Task 2/3 改进效果量化 │ │
│ │ • 对 FBST 的关键建议 │ │
│ │ • 方法论局限性说明 │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────────────┘
```
### 当前进度
| 任务 | 状态 | 说明 |
|------|------|------|
| Task 1 | ✅ 已完成 | 基础排程方案5个脚本全部运行通过 |
| Task 2 | ⏳ 待开始 | 天气响应调度选择2a或2b之一|
| Task 3 | ⏳ 待开始 | 双站点同车分配优化 |
| Task 4 | ⏳ 待开始 | 1页执行摘要 |
### 下一步操作
```
1. [Task 2 或 Task 3] 根据题目要求选择完成其一
├─▶ 若选 Task 2:
│ • 计算站点间距离矩阵
│ • 选择 2a(减站点) 或 2b(优化时间)
│ • 实现并量化改进
└─▶ 若选 Task 3:
• 筛选共生站点配对
• 建立第一站点分配模型
• 生成新排程并对比评估
2. [Task 4] 撰写1页执行摘要
• 汇总 Task 1 + (Task 2 或 Task 3) 结果
• 突出方法优势与建议
```
---
## 运行结果摘要
| 指标 | 推荐方案 | 均匀分配 | 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 输入数据
对 $n=70$ 个站点,数据提供:
| 字段 | 符号 | 说明 |
|------|------|------|
| 位置 | $(lat_i, lon_i)$ | 经纬度坐标 |
| 2019年访问次数 | $v_i$ | 历史频次总计722次 |
| 单次服务人数均值 | $\mu_i$ | 观测均值,范围[17.2, 396.6] |
| 单次服务人数标准差 | $\sigma_i$ | 观测波动,范围[2.2, 93.5] |
### 1.2 运营参数(题面提取)
| 参数 | 符号 | 值 | 来源 |
|------|------|-----|------|
| 卡车物理运力 | $W$ | 15,000 lbs | 题面明确 |
| 典型服务户数 | $[\underline{C}, \bar{C}]$ | [200, 250] | 题面"typical" |
| 每日可派车次 | - | 2 | 题面"2 trucks any given day" |
| 全年运营天数 | $T$ | 365 | 假设全年运营 |
| 年度总访问次数 | $N$ | 730 | $= 2 \times 365$ |
### 1.3 决策变量
- $k_i \in \mathbb{Z}^+$:站点 $i$ 的年度访问次数
- $\mathcal{S}_i = \{t_{i,1}, ..., t_{i,k_i}\}$:站点 $i$ 的具体访问日期
### 1.4 硬约束
$$\sum_{i=1}^{70} k_i = N = 730 \tag{C1: 资源约束}$$
$$k_i \geq 1, \quad \forall i \in [1,70] \tag{C2: 覆盖约束}$$
$$|\{i : t \in \mathcal{S}_i\}| = 2, \quad \forall t \in [1, 365] \tag{C3: 每日2站点}$$
---
## 2. 阶段一:真实需求估计(截断回归)
### 2.1 关键数据观察
分析70个站点的 $\mu_i$ 分布:
| 统计量 | 值 |
|--------|-----|
| $\mu > 250$ 的站点数 | 9 |
| $\mu_{max}$ | 396.6 (MFP Waverly) |
| $\mu$ 第二高 | 314.6 (MFP Avoca) |
| $\mu$ 第三高 | 285.3 (MFP Endwell) |
| $\mu$ 均值 | 141.4 |
**结论**:题面"200-250户"是"typical"而非硬上限。高需求站点通过减少每户分配量实现超额服务。
### 2.2 观测机制建模
**核心假设**:观测到的 $\mu_i$ 是真实需求 $\tilde{\mu}_i$ 在服务容量约束下的截断观测。
设单次服务的有效容量上限为 $C$(取 $C = 400$,略高于 $\mu_{max}$)。
$$\mu_i = E[\min(\tilde{D}_i, C)]$$
其中 $\tilde{D}_i \sim \mathcal{N}(\tilde{\mu}_i, \tilde{\sigma}_i^2)$ 是站点 $i$ 的真实单次需求。
### 2.3 截断修正公式
**Step 1**:计算截断概率代理
$$p_i^{trunc} = 1 - \Phi\left(\frac{C - \mu_i}{\sigma_i}\right)$$
**Step 2**:分段修正(阈值 $p^{trunc} \geq 0.02$
$$\tilde{\mu}_i = \begin{cases}
\mu_i & \text{if } p_i^{trunc} < 0.02 \\[8pt]
\mu_i \cdot (1 + 0.4 \cdot p_i^{trunc}) & \text{if } p_i^{trunc} \geq 0.02
\end{cases}$$
### 2.4 实际修正结果
采用阈值 $p^{trunc} \geq 0.02$共5个站点被修正
| 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 United Methodist | 285.2 | 60.8 | 0.030 | 288.6 | +1.2% |
| 30 | MFP Redeemer Lutheran | 230.6 | 93.5 | 0.035 | 233.8 | +1.4% |
**修正前后对比**
- 修正前 $\sum \mu_i$ = 9,899.9
- 修正后 $\sum \tilde{\mu}_i$ = 9,997.2
- 增幅:+0.98%
---
## 3. 阶段二:频次分配模型
### 3.1 分配原则
**核心思想**:按真实需求 $\tilde{\mu}_i$ 比例分配访问次数。
$$k_i = 1 + \text{Hamilton}\left(N - 70, \; w_i = \tilde{\mu}_i\right)$$
其中:
- 先给每个站点分配1次满足覆盖约束C2
- 剩余 $N - 70 = 660$ 次按权重 $\tilde{\mu}_i$ 做整数分配
### 3.2 Hamilton方法最大余数法
```python
def hamilton_allocation(total: int, weights: list) -> list:
n = len(weights)
w_sum = sum(weights)
quotas = [total * w / w_sum for w in weights]
floors = [int(q) for q in quotas]
remainders = [q - f for q, f in zip(quotas, floors)]
leftover = total - sum(floors)
indices = sorted(range(n), key=lambda i: -remainders[i])
for i in indices[:leftover]:
floors[i] += 1
return floors
```
### 3.3 实际分配结果
**验证**
- 总访问次数:$\sum k_i = 730$ ✓
- 访问次数范围:$[2, 32]$
- 最小访问次数2满足覆盖约束
**访问次数分布**
```
k = 2: 1 个站点 █
k = 3: 14 个站点 ██████████████
k = 4: 2 个站点 ██
k = 5: 4 个站点 ████
k = 6: 4 个站点 ████
k = 8: 1 个站点 █
k = 9: 3 个站点 ███
k = 10: 3 个站点 ███
k = 11: 6 个站点 ██████
k = 12: 5 个站点 █████
k = 13: 6 个站点 ██████
k = 14: 5 个站点 █████
k = 15: 4 个站点 ████
k = 16: 2 个站点 ██
k = 17: 1 个站点 █
k = 18: 2 个站点 ██
k = 19: 4 个站点 ████
k = 20: 1 个站点 █
k = 22: 1 个站点 █
k = 32: 1 个站点 █
```
**频次最高的10个站点**
| site_id | 站点名称 | $\mu$ | $\tilde{\mu}$ | $k$ | 年度服务量 |
|---------|---------|-------|---------------|-----|-----------|
| 66 | MFP Waverly | 396.6 | 471.9 | 32 | 12,692 |
| 2 | MFP Avoca | 314.6 | 323.2 | 22 | 6,921 |
| 17 | MFP Endwell United Methodist | 285.3 | 288.6 | 20 | 5,705 |
| 3 | MFP Bath | 279.5 | 279.5 | 19 | 5,310 |
| 13 | MFP College TC3 | 261.5 | 268.4 | 19 | 4,969 |
| 28 | MFP Rathbone | 269.1 | 269.1 | 19 | 5,113 |
| 32 | MFP Richford | 265.9 | 265.9 | 19 | 5,052 |
| 11 | MFP College Corning | 251.0 | 251.0 | 18 | 4,518 |
| 62 | MFP The Love Church | 259.3 | 259.3 | 18 | 4,668 |
| 31 | MFP Rehoboth Deliverance | 235.9 | 235.9 | 17 | 4,010 |
---
## 4. 阶段三:效果评估指标
### 4.1 有效性指标
**E1原始总服务量**
$$E_1 = \sum_{i=1}^{70} k_i \cdot \mu_i$$
**E2质量加权服务量**
$$E_2 = \sum_{i=1}^{70} k_i \cdot \mu_i \cdot q(\mu_i), \quad q(\mu) = \min\left(1, \frac{250}{\mu}\right)$$
### 4.2 公平性指标
**定义满足率**
$$r_i = \frac{k_i \cdot \mu_i}{\tilde{\mu}_i}$$
- **F1**:满足率基尼系数 $\text{Gini}(\mathbf{r})$
- **F2**:最差站点满足率 $\min_i r_i$
- **F3**:满足率变异系数 $CV_r$
### 4.3 实际评估结果
| 方案 | E1 | E2 | F1 (Gini) | F2 (min r) | F3 (CV) |
|------|-----|-----|-----------|------------|---------|
| **推荐方案** (μ̃比例) | **140,120.6** | **131,673.2** | 0.314 | 2.00 | 0.561 |
| 基线1: 均匀分配 | 104,797.3 | 101,308.9 | **0.026** | **8.41** | **0.052** |
| 基线2: 2019缩放 | 104,070.7 | 100,263.8 | 0.092 | 5.00 | 0.177 |
| 基线3: μ比例(无修正) | 139,129.2 | 131,397.1 | 0.311 | 2.00 | 0.550 |
**推荐方案优势**
- 相对均匀分配E1 +33.7%E2 +30.0%
- 相对2019缩放E1 +34.6%E2 +31.3%
**有效性-公平性权衡**推荐方案最大化了总服务量但公平性Gini系数较差。这是按需求比例分配的固有特性。
---
## 5. 阶段四:日历排程
### 5.1 目标
将 $\{k_i\}_{i=1}^{70}$ 转化为365天日历满足每日2站点约束并最小化访问间隔的不均匀性。
### 5.2 算法:贪心装箱 + 局部优化
1. **生成理想日期**$t_{i,j}^* = \text{round}\left(\frac{(j + 0.5) \cdot 365}{k_i}\right)$
2. **贪心分配**:按理想日期排序,就近分配到可用槽位
3. **局部优化**:随机交换站点,若改善间隔方差则接受
### 5.3 实际排程结果
**验证**
- 已分配访问事件730 / 730 ✓
- 日历统计365天满载 + 0天部分 + 0天空闲 ✓
- 局部优化5000次迭代接受33次改进
**间隔统计**
| 指标 | 值 |
|------|-----|
| 平均间隔均值 | 55.4 天 |
| 平均间隔标准差 | 3.2 天 |
| 最大单次间隔 | 179 天 |
| 平均间隔CV | 0.103 |
**日历预览前10天**
| 日期 | 站点1 | 站点2 |
|------|-------|-------|
| 1 | MFP Avoca | MFP Waverly |
| 2 | MFP Van Etten | MFP Endwell United Methodist |
| 3 | MFP Bath | MFP Richford |
| 4 | MFP College Corning | MFP College TC3 |
| 5 | MFP Rehoboth Deliverance | MFP Rathbone |
| 6 | MFP Waverly | MFP Redeemer Lutheran |
| 7 | MFP The Love Church | MFP Lindley |
| 8 | MFP Tuscarora | MFP Woodhull |
| 9 | MFP Endwell United Methodist | MFP Richford |
| 10 | MFP Bath | MFP College Corning |
---
## 6. 可复现流水线
### 6.1 脚本结构
```
task1/
├── 01_clean.py # 数据清洗与标准化
├── 02_demand_correction.py # 截断回归修正
├── 03_allocate.py # Hamilton频次分配
├── 04_evaluate.py # 评估指标计算
├── 05_schedule.py # 日历排程生成
├── 01_clean.xlsx # Step 1 输出
├── 02_demand.xlsx # Step 2 输出
├── 03_allocate.xlsx # Step 3 输出
├── 04_metrics.xlsx # Step 4 输出
└── 05_schedule.xlsx # Step 5 输出
```
### 6.2 运行方法
```bash
# 从项目根目录依次运行
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
```
### 6.3 关键参数
| 参数 | 值 | 位置 |
|------|-----|------|
| 有效容量上限 $C$ | 400 | `02_demand_correction.py` |
| 截断概率阈值 | 0.02 | `02_demand_correction.py` |
| 质量折扣阈值 $\bar{C}$ | 250 | `04_evaluate.py` |
| 年度总访问次数 $N$ | 730 | `03_allocate.py` |
| 全年天数 $T$ | 365 | `05_schedule.py` |
### 6.4 输出文件说明
| 文件 | 内容 |
|------|------|
| `01_clean.xlsx` | 标准化数据site_id, site_name, lat, lon, visits_2019, mu, sigma |
| `02_demand.xlsx` | 需求修正:+ mu_tilde, p_trunc, is_corrected |
| `03_allocate.xlsx` | 频次分配:+ k, annual_service, r |
| `04_metrics.xlsx` | 评估指标metrics_summary, site_details, parameters |
| `05_schedule.xlsx` | 日历排程calendar, site_dates, gap_statistics, parameters |
---
## 7. 敏感性分析
### 7.1 参数范围
| 参数 | 符号 | 基准值 | 敏感性范围 |
|------|------|--------|-----------|
| 有效容量 | $C$ | 400 | {350, 400, 450} |
| 截断概率阈值 | $p^{trunc}$ | 0.02 | {0.01, 0.02, 0.05, 0.10} |
| 典型服务量 | $\bar{C}$ | 250 | {200, 250, 300} |
### 7.2 阈值敏感性
| 阈值 | 被修正站点数 | $\sum \tilde{\mu}$ 增幅 |
|------|-------------|----------------------|
| 0.01 | 7 | +1.2% |
| 0.02 | 5 | +0.98% |
| 0.05 | 2 | +0.82% |
| 0.10 | 1 | +0.76% |
---
## 8. 假设与局限性
### 8.1 显式假设
| 编号 | 假设 | 依据 |
|------|------|------|
| A1 | 真实需求服从正态分布 | 中心极限定理 |
| A2 | 有效容量 $C=400$ | 基于 $\mu_{max}=396.6$ |
| A3 | 2021年需求结构与2019年相似 | 题面要求使用2019数据 |
| A4 | 全年365天均可运营 | 简化假设 |
| A5 | 每日2站点为硬约束 | 题面"2 trucks" |
### 8.2 局限性
1. **截断修正的简化**采用线性近似而非完整截断正态MLE
2. **需求外生性**:未建模"访问频次影响需求"的内生效应
3. **空间相关性**:未考虑相邻站点需求的空间自相关
4. **季节性**:未考虑需求的季节波动(如冬季低需求)
---
## 9. 结论与建议
### 9.1 方法论贡献
1. **识别截断偏误**:通过数据分析发现高需求站点的 $\mu$ 被容量截断,提出截断回归修正
2. **质量-数量权衡**:引入质量折扣因子 $q(\mu)$,避免简单最大化服务人次
3. **满足率公平**:以需求满足率而非访问次数衡量公平
### 9.2 对FBST的建议
1. **高需求站点**MFP Waverly ($k=32$) 需求远超其他站点,建议考虑增派车辆或设立分站
2. **数据收集**:建议记录"被拒绝服务的客户数"以更准确估计真实需求
3. **动态调整**:建议季度末根据实际服务数据调整下季度排程
### 9.3 有效性-公平性权衡
推荐方案在有效性总服务量上显著优于基线但公平性较差。若FBST更重视公平性可考虑
- 混合方案:在推荐方案基础上,对低频站点适当增加访问
- Pareto优化在有效性-公平性前沿上选择平衡点
### 9.4 后续研究方向
- **Task 2**:考虑天气对需求的影响,建立动态调度模型
- **Task 3**:双站点同车访问的最优分配策略