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

Task 1: 2021年MFP访问计划——需求驱动的频次分配与日历排程

摘要

本文提出一套因果逻辑清晰、闭环可审计的2021年MFP访问频次分配与日历排程方案。核心创新点

  1. 截断回归修正识别到9个站点历史服务量 $\mu_i > 250$最高396.6),说明高需求站点的观测数据被容量截断,采用截断正态模型恢复真实需求 \tilde{\mu}_i
  2. 质量加权有效性:考虑高服务量下每户分配食物减少的质量折扣
  3. 满足率公平性:以"年度服务量/真实需求"的均等程度衡量公平,而非简单的访问次数均等

方案遵循四阶段结构:需求估计 → 频次分配 → 效果评估 → 日历排程。


整体流程图

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:#90EE90
    style SENSITIVITY fill:#90EE90
    style VISUAL fill:#90EE90

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..450} │ │  │ │✓ 站点地图(需求)  │ │         │
│  │ │  - Σk=730 ✓      │ │  │ │✓ p阈值扫描      │ │  │ │✓ k分布直方图     │ │         │
│  │ │  - k≥1 ✓         │ │  │ │✓ C̄ ∈ {200..300}│ │  │ │✓ E-F权衡曲线    │ │         │
│  │ │  - 每日2站点 ✓   │ │  │ │                  │ │  │ │✓ 日历热力图      │ │         │
│  │ └──────────────────┘ │  │ └──────────────────┘ │  │ │✓ 间隔分布箱线图  │ │         │
│  │                      │  │                      │  │ └──────────────────┘ │         │
│  │ 07_backtest.py       │  │ 结论:                │  │                      │         │
│  │ ┌──────────────────┐ │  │ E1变化 < 1.3%       │  │ 输出:                │         │
│  │ │✓ 2019数据回测    │ │  │ 模型稳健            │  │ figures/*.png        │         │
│  │ │✓ 预测vs实际对比  │ │  │                      │  │ (7张图)              │         │
│  │ │✓ 残差分析        │ │  │                      │  │                      │         │
│  │ └──────────────────┘ │  │                      │  │                      │         │
│  └──────────────────────┘  └──────────────────────┘  └──────────────────────┘         │
│                                        │                                               │
└────────────────────────────────────────┼───────────────────────────────────────────────┘
                                         │
                                         ▼
                    ┌────────────────────┴────────────────────┐
                    │                                         │
                    ▼                                         ▼
     ┌──────────────────────────┐           ┌──────────────────────────┐
     │  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 6项硬约束全部通过
历史回测 完成 07_backtest.py 模型有效性验证
敏感性分析 完成 08_sensitivity.py 参数稳健性检验
可视化 完成 09_visualize.py 7张论文图表

运行结果摘要

指标 推荐方案 均匀分配 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$。这说明:

  1. 200-250不是硬上限:高需求站点可以服务更多家庭
  2. 存在隐性容量约束卡车运力15000磅 ÷ 每户约38-75磅 ≈ 200-400户
  3. 观测被截断:当真实需求 > 容量时,只能观测到容量值
真实需求分布:          观测到的分布:
     │                      │
     │    ╱╲                │    ╱╲
     │     ╲               │     ╲▓▓▓  ← 被截断部分
     │      ╲              │      │
     │       ╲             │      │
     ├─────────────         ├───────┤
     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"

问题:什么是"周边社区需求"

两种理解

  1. 用空间核平滑估计(循环论证:用供给估计需求)
  2. 每个站点本身就服务其周边社区,\tilde{\mu}_i 就是需求代理

我们的选择:直接用修正后的 \tilde{\mu}_i 作为"周边社区需求"的代理。

为什么按比例分配?

假设目标是最大化总服务量保证公平

  • 最大化 \sum k_i \mu_i subject 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方法最大余数法的优点

  1. 保证总和\sum k_i = N 严格成立
  2. 公平性余数大的站点优先获得额外1次
  3. 可解释:政治选举中广泛使用,逻辑透明

替代方法对比

方法 优点 缺点
四舍五入 简单 总和可能不等于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变量计算复杂度过高。

贪心策略

  1. 为每个访问事件计算"理想日期"
  2. 按理想日期排序
  3. 依次分配到最近的可用槽位

为什么有效?

  • 理想日期已经考虑了均匀分布
  • 按顺序分配避免了冲突
  • 局部优化可进一步改善

5.3 排程结果

  • 365天全部满载 ✓
  • 平均间隔55.4天
  • 最大间隔179天低频站点

6. 结果验证

6.1 约束满足检验 (06_validate.py)

检验项 公式 结果
C1: 资源约束 \sum k_i = 730 通过
C2: 覆盖约束 \min k_i \geq 1 通过 (min=2)
C3: 日容量约束 每日恰好2站点 通过
C4: 无重复约束 同一天不重复访问同一站点 通过
C5: 排程一致性 排程次数 = k_i 通过
C6: 总天数 日历天数 = 365 通过

结论所有6项硬约束全部通过。

6.2 模型有效性验证 (07_backtest.py)

关键发现

指标 解读
corr(visits_2019, μ) 0.0352 2019年访问次数与需求弱相关
corr(visits_2019, μ̃) 0.0433 历史分配未充分考虑需求
CV(k/μ̃) 0.0523 k与μ̃高度成正比模型内部一致
服务量改进 +35.24% 相比2019缩放方案

结论2019年历史分配与需求几乎不相关(r=0.035)说明历史分配未按需求进行。推荐方案实现按需分配服务量提升35%。


7. 敏感性分析

7.1 参数扫描 (08_sensitivity.py)

参数 基准值 扫描范围 影响
有效容量 C 400 [350, 375, 400, 425, 450] 截断修正强度
截断阈值 p^{trunc} 0.02 [0.01, 0.02, 0.05, 0.10] 修正站点数
质量阈值 \bar{C} 250 [200, 225, 250, 275, 300] E2计算

7.2 敏感性分析结果

C (有效容量) 敏感性

C = 350:  修正9站点, E1=141,300, F1=0.3141
C = 375:  修正7站点, E1=140,476, F1=0.3115
C = 400:  修正5站点, E1=140,121, F1=0.3140  ← 基准
C = 425:  修正3站点, E1=139,692, F1=0.3146
C = 450:  修正2站点, E1=139,487, F1=0.3153

稳健性结论

  • C 变化 [350, 450] 时E1 变化范围仅 1813 (1.29%)
  • p_thresh 变化 [0.01, 0.10] 时E1 变化范围仅 80 (0.06%)
  • 模型对参数变化不敏感,结果稳健

8. 可视化

8.1 图表清单 (09_visualize.py)

图编号 图名 文件 用途
Fig.1 站点地图 fig1_site_map.png 站点分布、需求大小、访问频次
Fig.2 需求修正对比 fig2_demand_correction.png 5个修正站点μ→μ̃变化
Fig.3 频次分配分布 fig3_k_distribution.png k分布 + k与μ̃相关性
Fig.4 有效性-公平性权衡 fig4_efficiency_fairness.png 4种方案E-F对比
Fig.5 日历热力图 fig5_calendar_heatmap.png 全年排程可视化
Fig.6 访问间隔箱线图 fig6_gap_boxplot.png 间隔均匀性分析
Fig.7 敏感性分析 fig7_sensitivity.png C, p_thresh, c̄的影响

8.2 Fig.1: 站点地图

展示70个站点的地理分布点大小表示需求μ颜色表示访问频次k。

Fig.1: 站点地图

8.3 Fig.2: 需求修正对比

展示5个被截断修正的高需求站点对比修正前μ和修正后μ̃。

Fig.2: 需求修正对比

8.4 Fig.3: 频次分配分布

左图k的分布直方图右图k与μ̃的线性关系r≈1验证按比例分配

Fig.3: 频次分配分布

8.5 Fig.4: 有效性-公平性权衡

展示4种分配方案在E2-F1空间的位置揭示效率与公平的Pareto权衡。

Fig.4: 有效性-公平性权衡

8.6 Fig.5: 日历热力图

全年365天排程可视化颜色表示当日访问站点的需求总和。

Fig.5: 日历热力图

8.7 Fig.6: 访问间隔分析

左图不同频次组的间隔均值分布右图间隔CV分布衡量均匀性

Fig.6: 访问间隔分析

8.8 Fig.7: 敏感性分析

参数C、p_thresh、c̄对模型输出的影响验证模型稳健性。

Fig.7: 敏感性分析


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
├── 06_validate.xlsx
├── 07_backtest.xlsx
├── 08_sensitivity.xlsx
└── figures/                 ✅ 7张图表

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 局限性

  1. 截断修正简化使用线性近似而非完整MLE
  2. 需求外生性:未建模"访问频次→需求"的反馈效应
  3. 空间相关性:未考虑相邻站点需求相关性
  4. 季节性:未考虑冬季需求下降

11. 结论与建议

11.1 方法论贡献

  1. 截断偏误识别:发现高需求站点 \mu 被低估
  2. 质量-数量权衡:引入质量折扣因子
  3. 满足率公平:以服务充足度衡量公平

11.2 对FBST的运营建议

  1. MFP Waverly:需求异常高($k=32$),建议增派资源
  2. 数据收集:记录"被拒服务人数"以更准确估计需求
  3. 动态调整:季度末复盘,调整下季度排程

11.3 有效性-公平性权衡

推荐方案牺牲公平性换取服务量最大化。若FBST优先考虑公平

  • 可设置 k_i 上下限约束
  • 或使用混合目标函数 \max (E_2 - \lambda \cdot F_1)