Files
mcm-mfp/README.md
2026-01-18 14:26:44 +08:00

85 lines
4.6 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.
# 20260116 美赛模拟食物分发MFP
本仓库包含对 2019 年 MFP 站点数据的频次分配(任务一)与全年排班优化(任务二)脚本。
核心数据文件:`prob/MFP Regular Sites 2019.xlsx`
## Task 1: 频次分配Visit Frequency Allocation
目标:在总车次约束下,为每个站点分配年度访问次数 `f_i`,并评估有效性/公平性含最低10%平均、基尼系数等)。
- 运行:`python3 kmin_effectiveness.py`
- 输出(写入 `data/`
- `data/kmin_effectiveness.png`k_min 与指标曲线图
- `data/kmin_effectiveness_data.csv`:每个 `k_min` 的汇总指标 + 各站点 `visits_01..visits_N`
- `data/kmin_effectiveness_sites.csv``visits_XX` 与站点名称/顺序映射
说明:`kmin_effectiveness.py` 当前使用 Monte Carlo引入 `StDev(Demand per Visit)`)对有效性做多次模拟平均。
![kmin effectiveness](data/kmin_effectiveness.png)
## Scheduling (Step 2)
Optimize a 365-day schedule with at most 2 visits per day and minimum gap constraints:
- `python3 scheduling_optimization.py --days 365 --daily-capacity 2 --gap-min 14`
- Outputs are written to `data/` (e.g., `data/schedule_optimized_kmin6.8_gap14.csv`), using `data/kmin_effectiveness_data.csv` as the frequency source.
### Visualization (Plan A)
- `python3 visualize_schedule.py`
- Outputs: `data/schedule_barcode_*.png` and `data/schedule_gap_deviation_*.png`
- Site label rule: remove first 4 chars, then take 12 chars.
![schedule barcode](data/schedule_barcode_kmin6.8_gap14.png)
![schedule gap deviation](data/schedule_gap_deviation_kmin6.8_gap14.png)
## Task 3: 双站点同车方案Two-stop trips
目标:允许同一辆车在一次出车中访问两个站点,需要在**站点配对、访问日期**以及**第一站分配量**上共同决策,并评估有效性/公平性。
### 算法框架(基于 Task 1/2 输出)
1. **需求与频次基线**
使用 `kmin_effectiveness.py` 得到各站点年度访问频次 `f_i` 与需求分布(均值、标准差)。
记单车载量 `C=15000lb`(或折算为服务人数上限 `C_OPT`),每次出车总量不超过 `C`
2. **候选配对生成**
基于地理距离/车程/同县等规则,生成可在同日完成的站点对 `(i, j)`;仅保留“距离阈值内 + 预期需求量不极端失衡”的组合。
可直接使用数据中的经纬度(若有)或县域分组构造“近邻候选集”。
3. **第一站分配量优化(核心不确定性)**
假设 `D_i ~ Normal(mu_i, sigma_i)``D_j ~ Normal(mu_j, sigma_j)`,选择第一站上限 `q_i`
- 实际服务:`S_i = min(D_i, q_i)`
- 剩余载量:`R = C - S_i`
- 第二站服务:`S_j = min(D_j, R)`
用一维搜索/网格或解析近似,选择 `q_i*` 最大化期望目标:
```
maximize E[S_i + S_j]
- alpha * E[unmet_i + unmet_j]
- beta * E[waste_i + waste_j]
- gamma * |E[S_i / D_i] - E[S_j / D_j]|
```
期望可用 Monte Carlo与 `kmin_effectiveness.py` 一致)或截断正态闭式近似;得到每个候选对的 `(q_i*, score)`。
4. **排程与配对选择CP-SAT / MIP**
在 Task 2 的日程框架上,将“单站访问”与“可配对双站访问”视作不同任务,决策变量:
- 是否在某天为一辆车选择 `(i, j)`
- 其他站点仍按单站访问
约束:每站点访问次数 = `f_i`;每日出车数 ≤ 2每辆车最多一条路线。
目标:最大化总期望有效性得分,并在目标函数中加入公平性惩罚(如 Gini 或最低 10% 均值惩罚)。
5. **有效性 & 公平性评估**
复用 Task 1 指标:
- 有效性:总体服务率、总未满足需求、总浪费
- 公平性:基尼系数、最低 10% 站点平均服务比例、最小服务比例
对双站路线进行 Monte Carlo 汇总,给出与单站方案的对比提升/退化幅度。
### 直观规则(工程可用的简化版)
- **配对规则**:优先将“高需求站点 + 低需求站点”或“需求相近且近邻”的站点配对,降低极端不公平。
- **第一站分配**`q_i` 取 `D_i` 的 60%~80% 分位数作为保守上限,剩余量留给第二站;必要时按历史波动调整分位数。
- **动态修正**:若某站点连续出现“后站不足”,在后续排程中降低其作为第一站的概率或提高 `q_i` 分位数阈值。
该方案与当前脚本兼容:`kmin_effectiveness.py` 提供需求统计与 Monte Carlo 框架;`scheduling_optimization.py` 的 CP-SAT 可扩展为“单站/双站二选一”的排程模型。