update readme
@@ -59,7 +59,7 @@ def truncation_correction(mu: float, sigma: float, C: float = 350) -> tuple:
|
|||||||
# E[D | D > C] = μ + σ * φ(z) / (1 - Φ(z))
|
# E[D | D > C] = μ + σ * φ(z) / (1 - Φ(z))
|
||||||
# 修正后: μ̃ ≈ μ * (1 + α * p_trunc)
|
# 修正后: μ̃ ≈ μ * (1 + α * p_trunc)
|
||||||
# 这里使用简化的线性修正
|
# 这里使用简化的线性修正
|
||||||
correction_factor = 1 + 0.4 * p_trunc
|
correction_factor = 1 + 0.1 * p_trunc
|
||||||
mu_tilde = mu * correction_factor
|
mu_tilde = mu * correction_factor
|
||||||
return mu_tilde, p_trunc, True
|
return mu_tilde, p_trunc, True
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ def fig1_site_map():
|
|||||||
|
|
||||||
# ... (图例和标签代码保持不变) ...
|
# ... (图例和标签代码保持不变) ...
|
||||||
|
|
||||||
ax.set_title('Fig.1: Site Map (Demand μ & Visit Frequency k)', fontsize=14, fontweight='bold')
|
# ax.set_title('Fig.1: Site Map (Demand μ & Visit Frequency k)', fontsize=14, fontweight='bold')
|
||||||
ax.set_xlabel('Longitude', fontsize=12)
|
ax.set_xlabel('Longitude', fontsize=12)
|
||||||
ax.set_ylabel('Latitude', fontsize=12)
|
ax.set_ylabel('Latitude', fontsize=12)
|
||||||
style_axes(ax)
|
style_axes(ax)
|
||||||
@@ -213,7 +213,7 @@ def fig2_demand_correction():
|
|||||||
|
|
||||||
ax.set_xlabel('Site', fontsize=12)
|
ax.set_xlabel('Site', fontsize=12)
|
||||||
ax.set_ylabel('Demand per Visit', fontsize=12)
|
ax.set_ylabel('Demand per Visit', fontsize=12)
|
||||||
ax.set_title('Fig.2: Truncation Correction for High-Demand Sites', fontsize=14, fontweight='bold')
|
# ax.set_title('Fig.2: Truncation Correction for High-Demand Sites', fontsize=14, fontweight='bold')
|
||||||
ax.set_xticks(x)
|
ax.set_xticks(x)
|
||||||
ax.set_xticklabels([name[:20] for name in corrected['site_name']], rotation=30, ha='right', fontsize=9)
|
ax.set_xticklabels([name[:20] for name in corrected['site_name']], rotation=30, ha='right', fontsize=9)
|
||||||
ax.legend(fontsize=10)
|
ax.legend(fontsize=10)
|
||||||
@@ -267,7 +267,7 @@ def fig3_k_distribution():
|
|||||||
ax2.legend(fontsize=10)
|
ax2.legend(fontsize=10)
|
||||||
style_axes(ax2)
|
style_axes(ax2)
|
||||||
|
|
||||||
plt.suptitle('Fig.3: Visit Frequency Allocation Analysis', fontsize=14, fontweight='bold', y=1.02)
|
# plt.suptitle('Fig.3: Visit Frequency Allocation Analysis', fontsize=14, fontweight='bold', y=1.02)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig(FIGURES_PATH / 'fig3_k_distribution.png', dpi=150, bbox_inches='tight')
|
plt.savefig(FIGURES_PATH / 'fig3_k_distribution.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
@@ -361,7 +361,7 @@ def fig4_efficiency_fairness():
|
|||||||
|
|
||||||
ax.set_xlabel('E2 (Quality-Weighted Service Volume)', fontsize=12)
|
ax.set_xlabel('E2 (Quality-Weighted Service Volume)', fontsize=12)
|
||||||
ax.set_ylabel('F1 (Gini Coefficient, lower = fairer)', fontsize=12)
|
ax.set_ylabel('F1 (Gini Coefficient, lower = fairer)', fontsize=12)
|
||||||
ax.set_title('Fig.4: Efficiency-Fairness Tradeoff Analysis', fontsize=14, fontweight='bold')
|
# ax.set_title('Fig.4: Efficiency-Fairness Tradeoff Analysis', fontsize=14, fontweight='bold')
|
||||||
ax.legend(
|
ax.legend(
|
||||||
handles=legend_handles,
|
handles=legend_handles,
|
||||||
loc="upper left",
|
loc="upper left",
|
||||||
@@ -432,7 +432,7 @@ def fig5_calendar_heatmap():
|
|||||||
|
|
||||||
ax.set_xlabel('Day of Month', fontsize=12)
|
ax.set_xlabel('Day of Month', fontsize=12)
|
||||||
ax.set_ylabel('Month', fontsize=12)
|
ax.set_ylabel('Month', fontsize=12)
|
||||||
ax.set_title('Fig.5: Annual Schedule Calendar Heatmap (Daily Demand)', fontsize=14, fontweight='bold')
|
# ax.set_title('Fig.5: Annual Schedule Calendar Heatmap (Daily Demand)', fontsize=14, fontweight='bold')
|
||||||
ax.grid(False)
|
ax.grid(False)
|
||||||
|
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
@@ -488,7 +488,7 @@ def fig6_gap_boxplot():
|
|||||||
ax2.legend(fontsize=10)
|
ax2.legend(fontsize=10)
|
||||||
style_axes(ax2)
|
style_axes(ax2)
|
||||||
|
|
||||||
plt.suptitle('Fig.6: Visit Interval Analysis', fontsize=14, fontweight='bold', y=1.02)
|
# plt.suptitle('Fig.6: Visit Interval Analysis', fontsize=14, fontweight='bold', y=1.02)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig(FIGURES_PATH / 'fig6_gap_boxplot.png', dpi=150, bbox_inches='tight')
|
plt.savefig(FIGURES_PATH / 'fig6_gap_boxplot.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
@@ -548,7 +548,7 @@ def fig7_sensitivity():
|
|||||||
ax4.legend(fontsize=9)
|
ax4.legend(fontsize=9)
|
||||||
style_axes(ax4)
|
style_axes(ax4)
|
||||||
|
|
||||||
plt.suptitle('Fig.7: Sensitivity Analysis of Model Parameters', fontsize=14, fontweight='bold', y=1.02)
|
# plt.suptitle('Fig.7: Sensitivity Analysis of Model Parameters', fontsize=14, fontweight='bold', y=1.02)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig(FIGURES_PATH / 'fig7_sensitivity.png', dpi=150, bbox_inches='tight')
|
plt.savefig(FIGURES_PATH / 'fig7_sensitivity.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
|
|||||||
@@ -674,32 +674,41 @@ python task1/09_visualize.py
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. 论文展示数据表 (Task 1 Results)
|
## 12. 论文展示数据表与深度解析 (Task 1 Results & Analysis)
|
||||||
|
|
||||||
为了在论文中展示模型 1 的核心成果,以下整理了关键的评估数据表。
|
### 表 1: 不同分配方案的性能对比 (效能与公平性的权衡)
|
||||||
|
|
||||||
### 表 1: 不同分配方案的性能对比 (有效性与公平性)
|
|
||||||
| 分配方案 | 总服务量 (E1) | 质量加权服务量 (E2) | 满足率 Gini 系数 (F1) ↓ | 最低满足率 (F2) ↑ |
|
| 分配方案 | 总服务量 (E1) | 质量加权服务量 (E2) | 满足率 Gini 系数 (F1) ↓ | 最低满足率 (F2) ↑ |
|
||||||
| :--- | :---: | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: | :---: |
|
||||||
| **推荐方案 (μ̃ Proportional)** | **140,121** | **131,673** | 0.314 | 2.00 |
|
| **推荐方案 (μ̃ Proportional)** | **139,469** | **131,462** | 0.314 | 2.00 |
|
||||||
| 基线 1: 均匀分配 (Uniform) | 104,797 | 101,309 | **0.026** | **8.41** |
|
| 基线 1: 均匀分配 (Uniform) | 104,797 | 101,309 | **0.024** | **9.25** |
|
||||||
| 基线 2: 2019 历史缩放 (Scaled) | 104,071 | 100,264 | 0.092 | 5.00 |
|
| 基线 2: 2019 历史缩放 (Scaled) | 104,071 | 100,264 | 0.091 | 5.00 |
|
||||||
| 基线 3: 原始需求比例 (Raw μ) | 139,487 | 131,462 | 0.315 | 2.00 |
|
| 基线 3: 原始需求比例 (Raw μ) | 139,129 | 131,397 | 0.313 | 2.00 |
|
||||||
|
|
||||||
### 表 2: 关键高需求站点的截断回归修正结果
|
**深度解析**:
|
||||||
|
* **效能跃升**:推荐方案通过将资源集中于高需求站点,使总服务量 (E1) 相比 2019 年历史方案(缩放后)提升了 **34.0%**。在考虑服务质量折扣后 (E2),依然保持了 **31.1%** 的显著增幅。
|
||||||
|
* **公平性权衡**:均匀分配方案虽具有极低的 Gini 系数(0.024),但由于忽视了人口分布差异,导致大量高需求社区处于严重的“服务赤字”状态。推荐方案选择在维持最低服务门槛($k \ge 2$)的前提下最大化总量,其 F1 指标反映了资源与需求精准匹配后的正态分布特征。
|
||||||
|
|
||||||
|
### 表 2: 关键高需求站点的截断回归修正 (Truncation Correction)
|
||||||
| 站点名称 (Site Name) | 观测均值 (μ) | 截断概率 ($P_{trunc}$) | 修正后需求 ($\tilde{\mu}$) | 修正幅度 |
|
| 站点名称 (Site Name) | 观测均值 (μ) | 截断概率 ($P_{trunc}$) | 修正后需求 ($\tilde{\mu}$) | 修正幅度 |
|
||||||
| :--- | :---: | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: | :---: |
|
||||||
| MFP Waverly | 396.6 | 47.4% | 471.9 | +19.0% |
|
| MFP Waverly | 396.6 | 81.57% | 429.0 | +8.2% |
|
||||||
| MFP Avoca | 314.6 | 6.8% | 323.2 | +2.7% |
|
| MFP Avoca | 314.6 | 26.84% | 323.0 | +2.7% |
|
||||||
| MFP College TC3 | 261.5 | 6.6% | 268.4 | +2.6% |
|
| MFP Endwell United Methodist | 285.3 | 14.34% | 289.3 | +1.4% |
|
||||||
| MFP Endwell | 285.2 | 3.0% | 288.6 | +1.2% |
|
| MFP College TC3 -College | 261.5 | 16.80% | 265.9 | +1.7% |
|
||||||
| MFP Redeemer | 230.6 | 3.5% | 233.8 | +1.4% |
|
| MFP Redeemer Lutheran Church | 230.6 | 10.07% | 232.9 | +1.0% |
|
||||||
|
|
||||||
### 表 3: 方案排程约束验证与稳健性
|
**深度解析 (对应 Fig.2)**:
|
||||||
| 评估维度 | 指标名称 | 计算结果 / 状态 | 预期目标 |
|
* **识别隐性需求**:Fig.2 揭示了观测数据中的“幸存者偏差”。以 **MFP Waverly** 为例,其截断概率高达 **81.57%**,意味着该站点在历史运营中几乎处于永久性满载状态,观测均值 396.6 仅是运力上限的体现而非真实需求上限。
|
||||||
| :--- | :--- | :--- | :--- |
|
* **修正意义**:通过截断正态模型,我们将该站点的潜在需求上调至 429.0。这一修正确保了资源分配不仅是基于“历史给了多少”,而是基于“社区实际缺多少”,有效弥补了高需求区域因历史供给不足而被低估的问题。
|
||||||
| **资源约束** | 年度总访问次数 ($\sum k_i$) | 730 | 730 |
|
|
||||||
| **覆盖约束** | 最小访问频次 ($\min k_i$) | 2 | $\ge 1$ |
|
### 表 3: 方案稳健性与模型拟合统计
|
||||||
| **排程约束** | 每日派车车次 | 2 | 2 |
|
| 评估维度 | 指标名称 | 计算结果 | 业务含义 |
|
||||||
| **一致性** | 频次与需求相关性 ($r_{k, \tilde{\mu}}$) | **0.9996** | $\to 1.0$ |
|
| :--- | :--- | :---: | :--- |
|
||||||
| **稳健性** | 参数 $C$ 波动对 E1 的影响 | < 1.3% | 保持稳定 |
|
| **分配逻辑** | 历史相关性 $r(v_{2019}, \mu)$ | 0.035 | 证实 2019 年分配与需求几乎无关 (随机分配) |
|
||||||
|
| **改进潜力** | 相比历史方案提升幅度 | **+34.61%** | 实现按需分配后的效率净增益 |
|
||||||
|
| **约束满足** | 每日派车容量合格率 | 100% | 确保 365 天排程无资源冲突 |
|
||||||
|
| **均匀度** | 访问间隔 CV 均值 | 0.197 | 保证了客户对访问日期的可预测性 |
|
||||||
|
|
||||||
|
**深度解析**:
|
||||||
|
* **模型稳健性**:敏感性分析显示,即使当运力估计 $C$ 在 [350, 450] 范围内波动时,总服务量 E1 的变化率不足 1.3%,证明了分配逻辑对参数设定具有极强的鲁棒性。
|
||||||
|
* **排程科学性 (对应 Fig.5 & Fig.6)**:通过日历热力图可以观察到需求负荷在年度周期内的均匀分布,避免了车辆调度的高峰冲突;箱线图验证了各站点的访问间隔高度集中在理想值附近。
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 185 KiB |