p2: rebuild

This commit is contained in:
2026-01-31 18:00:43 +08:00
parent fdec519764
commit e8b7db71c8
21 changed files with 4313 additions and 1586 deletions

View File

@@ -488,7 +488,7 @@ def plot_pareto_analysis(
def plot_decision_recommendation( def plot_decision_recommendation(
df: pd.DataFrame, df: pd.DataFrame,
knee_analysis: Dict, knee_analysis: Dict,
save_path: str = '/Volumes/Files/code/mm/20260130_b/decision_recommendation.png' save_path: str = '/Volumes/Files/code/mm/20260130_b/p1/decision_recommendation.png'
): ):
""" """
绘制决策建议图(更适合放在报告中) 绘制决策建议图(更适合放在报告中)
@@ -652,7 +652,7 @@ def plot_combined_range_analysis(
df: pd.DataFrame, df: pd.DataFrame,
knee_analysis: Dict, knee_analysis: Dict,
year_range: Tuple[float, float], year_range: Tuple[float, float],
save_path: str = '/Volumes/Files/code/mm/20260130_b/pareto_combined_range.png' save_path: str = '/Volumes/Files/code/mm/20260130_b/p1/pareto_combined_range.png'
): ):
""" """
绘制组合方案范围内的Pareto分析图 绘制组合方案范围内的Pareto分析图
@@ -800,7 +800,7 @@ def plot_combined_decision(
df: pd.DataFrame, df: pd.DataFrame,
knee_analysis: Dict, knee_analysis: Dict,
year_range: Tuple[float, float], year_range: Tuple[float, float],
save_path: str = '/Volumes/Files/code/mm/20260130_b/combined_decision.png' save_path: str = '/Volumes/Files/code/mm/20260130_b/p1/combined_decision.png'
): ):
""" """
绘制组合方案决策图 绘制组合方案决策图
@@ -1018,8 +1018,8 @@ if __name__ == "__main__":
plot_decision_recommendation(df_full, knee_full) plot_decision_recommendation(df_full, knee_full)
# 保存数据 # 保存数据
df_combined.to_csv('/Volumes/Files/code/mm/20260130_b/pareto_combined_range.csv', index=False) df_combined.to_csv('/Volumes/Files/code/mm/20260130_b/p1/pareto_combined_range.csv', index=False)
df_full.to_csv('/Volumes/Files/code/mm/20260130_b/pareto_front_data.csv', index=False) df_full.to_csv('/Volumes/Files/code/mm/20260130_b/p1/pareto_front_data.csv', index=False)
print("\n数据已保存至 CSV 文件") print("\n数据已保存至 CSV 文件")
print("\n" + "=" * 80) print("\n" + "=" * 80)

View File

@@ -1,382 +1,293 @@
# Task 2: 系统不确定性与鲁棒性分析 (v2) # 任务二:非完美运行条件下的蒙特卡洛模拟分析
本目录实现 **MCM 2026 Problem B** 任务二: ## Task 2: Monte Carlo Analysis Under Imperfect Operating Conditions
> **To what extent does your solution(s) change if the transportation systems are not in perfect working order (e.g., swaying of the tether, rockets fail, elevators break, etc.)?** 本目录包含针对 **MCM 2026 Problem B** 任务二的完整分析:
> "To what extent does your solution(s) change if the transportation systems are not in perfect working order (e.g, swaying of the tether, rockets fail, elevators break, etc.)."
--- ---
## 版本说明 (v2 审计后修正) ## 一、问题背景与建模思路
| 改进项 | v1 问题 | v2 修正 | ### 1.1 任务一回顾(完美条件下)
|--------|---------|---------|
| 完成时间分布 | 二分搜索中重复随机采样 | 使用期望值函数保证单调性 | | 方案 | 完成时间 | 总能耗 (PJ) | 特点 |
| 能量口径 | 只报告无条件均值 | 分条件/无条件两种口径 | |------|----------|-------------|------|
| 电梯效率 | 能量÷效率(逻辑错误) | 能量∝交付量(效率影响交付) | | 电梯 | 186.2 年 | 15,720 | 能耗最低 |
| 失败能量 | 固定 30% | 分阶段加权 44.2%(引用 FAA 数据) | | 混合-最短时间 | 100.7 年 | 31,537 | 时间最短 |
| 结论表述 | "膝点右移 40" | 决策区间 + 风险偏好表 | | 混合-膝点平衡 | 139 年 | 24,361 | 成本-时间平衡 |
### 1.2 任务二:引入故障因素
现实运输系统不可能完美运行,本任务通过**蒙特卡洛模拟**量化以下故障对方案的影响:
| 故障类型 | 物理机制 | 建模方法 |
|----------|----------|----------|
| **缆索摆动** | 释放点偏差 → 轨道修正ΔV | 正态分布 N(0, σ²),计算修正能量 |
| **火箭发射失败** | 发射失败 → 载荷损失 | 伯努利分布,失败率 2% |
| **电梯故障** | 设备停机维护 | 泊松过程 + 正态停机时间 |
| **天气取消** | 不利天气 → 发射延迟 | 伯努利分布,按发射场差异化 |
--- ---
## 一、问题分析与建模思路 ## 二、蒙特卡洛模拟模型
### 1.1 问题本质 ### 2.1 故障参数设置(基于历史数据与合理假设)
任务二要求回答的核心问题是:**在系统存在不确定性时,最优解决方案会如何变化?** ```
故障参数:
├── 火箭发射失败率: 2.0% [参考: SpaceX Falcon 9 历史失败率 ~2-3%]
├── 电梯年故障次数: 2.0 次/部/年 [假设值,进行敏感性分析]
├── 电梯平均停机时间: 14 ± 7 天 [正态分布]
├── 缆索摆动角度: σ = 0.5° [考虑潮汐力、月球引力摄动]
└── 天气取消率: 8% ~ 30% [按发射场地理位置差异化]
```
这不仅仅是计算"能耗增加多少",而是要回答 **天气取消率(分发射场)**
- 原来的最优工期(膝点)还适用吗?
- 需要预留多少时间/资源冗余?
- 哪些因素对结果影响最大?
### 1.2 不确定性来源 | 发射场 | 取消率 | 原因 |
|--------|--------|------|
| California | 8% | 气候干燥 |
| Kourou | 10% | 热带,偶有雨季 |
| Taiyuan | 10% | 内陆干燥 |
| Baikonur | 12% | 大陆性气候 |
| Texas | 12% | 风暴偶发 |
| SDSC (India) | 15% | 季风影响 |
| Virginia | 18% | 东海岸天气 |
| Mahia | 20% | 海洋性气候 |
| Florida | 25% | 雷暴频繁 |
| Alaska | 30% | 极端天气 |
| 不确定性 | 物理机制 | 影响 | ### 2.2 缆索摆动的物理建模
|---------|---------|------|
| **火箭发射失败** | 发动机故障、天气中止、轨道偏差 | 有效发射次数减少 |
| **电梯故障/维护** | 机械故障、缆绳摆动、定期维护 | 运力间歇性中断 |
| **天气/窗口约束** | 恶劣天气、发射窗口限制 | 可发射天数减少 |
| **载荷损失** | 对接失败、运输损坏 | 实际交付量减少 |
### 1.3 建模方法选择 **问题**:缆索摆动如何导致能量损失?
| 方法 | 优点 | 缺点 | 适用场景 | **第一性原理分析**
1. 摆动导致释放点**速度方向偏差** θ
2. 载荷进入非设计轨道,需要**轨道修正**
3. 轨道修正需要额外 ΔV
$$\Delta V_{correction} \approx V_{release} \cdot \sin(\theta) \approx V_{release} \cdot \theta$$
4. 额外燃料消耗(火箭方程):
$$\Delta m_{fuel} = m_{payload} \cdot \left[ \exp\left(\frac{\Delta V}{v_e}\right) - 1 \right]$$
**本模型设置**
- 摆动角度服从正态分布:$\theta \sim N(0, 0.5°)$
- 释放速度7,270 m/s100,000 km 高度)
- 每次释放独立抽取摆动角度
### 2.3 三种方案定义
| 方案 | 代号 | 策略 | 目标年限 |
|------|------|------|----------| |------|------|------|----------|
| 确定性分析 | 简单、快速 | 无法量化风险 | 初步估算 | | **成本优先** | Scenario A | 仅使用太空电梯 | 186.2 年 |
| 期望值分析 | 考虑均值影响 | 忽略分布尾部 | 快速敏感性 | | **时间优先** | Scenario B | 电梯 + 火箭全开 | 105.7 年 |
| **蒙特卡洛模拟** | 完整分布、风险量化 | 计算量大 | **本方案** | | **综合平衡** | Scenario C | 电梯优先 + 低纬火箭 | 139.0 年 |
| 逐日仿真 | 最真实 | 极慢 | 验证/附录 |
--- ---
## 二、数学原理 ## 三、蒙特卡洛模拟结果
### 2.1 二项分布模型(发射成功/失败) ### 3.1 模拟配置
火箭发射是独立的伯努利试验,成功概率为 \(p\)。在 \(n\) 次尝试中,成功次数 \(X\) 服从二项分布: - **模拟次数**1,000 次
- **时间步长**:年
- **随机种子**42可复现
$$X \sim \text{Binomial}(n, p)$$ ### 3.2 核心结果汇总
### 2.2 Beta 分布(概率参数采样) | 方案 | 目标年限 | 实际完成年限 | 延迟率 | 总能耗 (PJ) |
|------|----------|--------------|--------|-------------|
| **A: 成本优先** | 186.2 年 | **202.3 ± 0.6 年** | +8.6% | 15,738 ± 0 |
| **B: 时间优先** | 105.7 年 | **120.7 ± 0.4 年** | +14.2% | 30,217 ± 30 |
| **C: 综合平衡** | 139.0 年 | **155.3 ± 0.5 年** | +11.7% | 24,060 ± 26 |
对于 \([0,1]\) 区间的概率参数Beta 分布是自然选择: ### 3.3 故障统计详情
$$p \sim \text{Beta}(\alpha, \beta)$$ #### 方案A纯电梯
给定均值 \(\mu\) 和标准差 \(\sigma\),可反解参数。 | 指标 | 数值 |
|------|------|
| 电梯总停机时间 | 17,073 天 ≈ **46.8 年** |
| 摆动能量惩罚 | 17.9 PJ (占总能耗 0.11%) |
| 火箭失败/天气取消 | N/A |
### 2.3 完成时间分布v2 修正:单调性保证 #### 方案B时间优先混合全速
完成时间定义为**首次达到目标的时间** | 指标 | 数值 |
|------|------|
| 火箭发射失败 | **6,590 次** |
| 天气取消 | **62,761 次** |
| 电梯总停机时间 | 10,199 天 ≈ 27.9 年 |
| 摆动能量惩罚 | 10.7 PJ (占总能耗 0.04%) |
$$T^* = \inf\{T: D(T) \ge M\}$$ #### 方案C综合平衡
其中交付函数 \(D(T)\) 使用**期望值**计算: | 指标 | 数值 |
$$D(T) = E_{\text{elevator}}(T) + E[\text{rocket}(T)]$$ |------|------|
| 火箭发射失败 | **3,788 次** |
这保证了 \(D(T)\) 单调递增,避免了 v1 中二分搜索每步重新采样导致的非单调问题。 | 天气取消 | **36,078 次** |
| 电梯总停机时间 | 13,114 天 ≈ 35.9 年 |
### 2.4 失败能量分阶段建模v2 新增) | 摆动能量惩罚 | 13.8 PJ (占总能耗 0.06%) |
失败发射的能量损失取决于失败阶段(参考 FAA AST 报告):
| 失败阶段 | 能量损失比例 | 发生概率 |
|----------|-------------|---------|
| 发射前中止 | 5% | 15% |
| 一级飞行失败 | 35% | 50% |
| 上面级失败 | 70% | 30% |
| 轨道转移失败 | 100% | 5% |
| **加权平均** | **44.2%** | - |
--- ---
## 三、算法实现 ## 四、结果分析与讨论
### 3.1 核心算法:聚合 MC + 二项分布 ### 4.1 关键发现
```python #### 发现一:故障导致的时间延迟不可忽略
def monte_carlo_binomial(target_years, params, n_simulations):
# Step 1: 采样参数Beta/三角分布)
# Step 2: 计算电梯交付(能量∝交付量)
# Step 3: 成功发射次数(二项分布采样)
# Step 4: 失败能量(分阶段加权)
# Step 5: 返回条件/无条件能量分布
```
### 3.2 条件能量 vs 无条件能量v2 新增) 各方案的**完成时间均显著延迟**
- 纯电梯方案延迟 **16.1 年**+8.6%
- 时间优先方案延迟 **15.0 年**+14.2%
- 平衡方案延迟 **16.3 年**+11.7%
```python **原因分析**
# 无条件能量(包含未完成的模拟) - 电梯故障累计停机时间达 **28-47 年**(取决于运行总年限)
energy_mean = np.mean(total_energy) - 火箭发射受天气取消和失败双重影响
- 时间优先方案虽然目标年限短,但**相对延迟率最高**14.2%
# 条件能量(只算完成的模拟) #### 发现二:缆索摆动的能量惩罚可控
completed_mask = completed.astype(bool)
energy_given_completed = np.mean(total_energy[completed_mask]) 摆动能量惩罚仅占总能耗的 **0.04% - 0.11%**,原因:
``` - 0.5° 的摆动角度在工程上是可控的
- 电梯释放速度7.27 km/s相对较低
- 轨道修正效率较高
**敏感性提示**:若摆动角度增大到 5°能量惩罚将增加 ~100 倍。
#### 发现三:火箭故障是时间延迟的主要因素
对于使用火箭的方案B、C
- 天气取消是最主要的障碍(取消次数 >> 失败次数)
- 高纬度发射场Alaska 30%)贡献了大量天气取消
- 火箭失败率 2% 导致约 **6,600 次**方案B载荷损失
### 4.2 方案对比:完美 vs 非完美条件
| 指标 | 完美条件 | 非完美条件 | 变化 |
|------|----------|------------|------|
| **方案A 完成时间** | 186.2 年 | 202.3 年 | +8.6% |
| **方案B 完成时间** | 100.7 年 | 120.7 年 | +19.9% |
| **方案C 完成时间** | 139.0 年 | 155.3 年 | +11.7% |
| **方案A 能耗** | 15,720 PJ | 15,738 PJ | +0.1% |
| **方案B 能耗** | 31,537 PJ | 30,217 PJ | -4.2%* |
| **方案C 能耗** | 24,361 PJ | 24,060 PJ | -1.2%* |
*注:能耗略有下降是因为火箭失败后载荷未交付,总运输量略少。
### 4.3 敏感性分析
基于方案C的Spearman相关系数分析
| 因素 | 与完成时间的相关性 |
|------|-------------------|
| 电梯停机时间 | 强正相关 |
| 天气取消次数 | 中等正相关 |
| 火箭失败次数 | 弱正相关 |
| 缆索摆动惩罚 | 极弱相关 |
**结论****电梯可靠性**是影响项目进度的最关键因素。
--- ---
## 四、运行方式 ## 五、图表索引
| 图表文件 | 内容描述 |
|----------|----------|
| `completion_time_distribution.png` | 三方案完成时间概率分布直方图 |
| `energy_distribution.png` | 三方案能耗概率分布直方图 |
| `boxplot_comparison.png` | 完成时间与能耗箱线图对比 |
| `failure_analysis.png` | 故障统计分布(火箭失败、天气取消、电梯停机、摆动惩罚) |
| `sensitivity_tornado.png` | 敏感性分析龙卷风图 |
| `comprehensive_comparison.png` | 综合对比图散点图、CDF、统计表、延迟分布 |
### 图表预览
#### 完成时间分布
![completion_time_distribution](completion_time_distribution.png)
#### 能耗分布
![energy_distribution](energy_distribution.png)
#### 箱线图对比
![boxplot_comparison](boxplot_comparison.png)
#### 故障分析
![failure_analysis](failure_analysis.png)
#### 敏感性龙卷风图
![sensitivity_tornado](sensitivity_tornado.png)
#### 综合对比
![comprehensive_comparison](comprehensive_comparison.png)
---
## 六、结论与建议
### 6.1 核心结论
1. **故障对项目进度影响显著**:所有方案均出现 8-14% 的时间延迟
2. **电梯可靠性是关键**:电梯停机累计达 28-47 年,是最主要的延迟源
3. **缆索摆动影响可控**:在 0.5° 摆动范围内,能量惩罚 < 0.2%
4. **方案排序不变**
- 成本优先 → 纯电梯(~202 年15,738 PJ
- 时间优先 → 混合全速(~121 年30,217 PJ
- 综合平衡 → 膝点方案(~155 年24,060 PJ
### 6.2 风险缓解建议
| 风险因素 | 缓解措施 |
|----------|----------|
| 电梯故障 | 增加冗余电梯、提高可维护性设计 |
| 天气取消 | 优先使用低纬度、气候稳定的发射场 |
| 火箭失败 | 提高技术成熟度、建立快速重发机制 |
| 缆索摆动 | 主动阻尼控制、优化释放时机 |
### 6.3 模型局限性
1. **故障参数假设**:电梯故障率基于假设,缺乏实际数据
2. **故障独立性假设**:未考虑级联故障
3. **恢复时间简化**:未建模复杂的维修调度
4. **天气模型简化**:未考虑季节性变化
---
## 七、文件清单
| 文件 | 描述 |
|------|------|
| `monte_carlo_simulation.py` | 蒙特卡洛模拟核心代码 |
| `simulation_results.csv` | 原始模拟数据1000×3方案 |
| `simulation_report.txt` | 统计报告文本版 |
| `*.png` | 可视化图表6张 |
| `README.md` | 本分析报告 |
---
## 八、如何运行
```bash ```bash
cd p2 # 安装依赖
python uncertainty_analysis.py pip install numpy matplotlib pandas scipy tqdm
# 运行模拟约15分钟
cd /Volumes/Files/code/mm/20260130_b/p2
python monte_carlo_simulation.py
``` ```
--- 可在 `monte_carlo_simulation.py` 中修改:
- `n_simulations`:模拟次数(默认 1000
## 五、不确定性参数 - `FailureParameters`:故障率参数
| 参数 | 均值 | 标准差 | 分布 | 物理含义 |
|------|------|--------|------|----------|
| 火箭成功率 | 97% | 1.5% | Beta | 发射成功概率 |
| 电梯可用率 | 90% | 4% | Beta | 故障/维护导致的有效运行时间 |
| 天气因子 | 80% | 8% | Beta | 可发射天数占比 |
| 损失率 | 1% | 0.5% | 三角 | 运输过程载荷损失 |
| 电梯效率 | 95% | 2% | Beta | 缆绳摆动等效率损失 |
--- ---
## 六、程序运行输出 (v2) *报告生成时间2026-01-31*
```
================================================================================
MOON COLONY LOGISTICS - UNCERTAINTY ANALYSIS (TASK 2) v2
Revised: Binomial MC + Monotonic Time + Conditional Energy + Decision Table
================================================================================
1. UNCERTAINTY PARAMETERS (Beta/Triangular)
--------------------------------------------------
Rocket Success: 97.0% (σ=1.5%)
Elevator Avail: 90.0% (σ=4.0%)
Weather Factor: 80.0% (σ=8.0%)
Loss Rate: 1.00% (σ=0.50%)
Elevator Efficiency: 95.0% (σ=2.0%)
2. DETERMINISTIC BASELINE (139 years)
--------------------------------------------------
Total Energy: 24343 PJ
Elevator Payload: 74.6 M tons
Rocket Payload: 25.4 M tons
Launches: 202,856
3. MONTE CARLO SIMULATION (Binomial Model)
--------------------------------------------------
Simulations: 2,000
Completion Prob: 98.2%
Energy Mean (all): 28588 PJ (+17.4%)
Energy P95 (all): 30551 PJ
Energy Mean (|completed):28577 PJ (+17.4%)
Energy P95 (|completed): 30517 PJ
Avg Successful Launches: 291,675
Avg Failed Launches: 8,973
Failure Energy Ratio: 44.2% (weighted avg)
4. COMPLETION TIME DISTRIBUTION (Monotonic)
--------------------------------------------------
Mean: 124.2 years
Std: 6.6 years
P5/P50/P95: 114.5 / 123.2 / 135.9
5. DECISION GUIDANCE (ANSWER TO TASK 2)
--------------------------------------------------
Task 1 recommended knee point: 139 years
DECISION TABLE (Risk Preference → Timeline):
┌─────────────────┬──────────┬───────────┐
│ Risk Tolerance │ Timeline │ Energy P95│
├─────────────────┼──────────┼───────────┤
│ Aggressive (P≥90%) │ 133 y │ 31377 PJ│
│ Standard (P≥95%) │ 138 y │ 31002 PJ│
│ Conservative (P≥99%) │ 146 y │ 29673 PJ│
└─────────────────┴──────────┴───────────┘
Knee point in feasible region (P≥95%): 150 years
→ This is the Time-Energy tradeoff optimum within the safe zone
================================================================================
ANSWER TO 'TO WHAT EXTENT DOES YOUR SOLUTION CHANGE?'
--------------------------------------------------
1. Energy penalty: +17% (unconditional mean)
Energy penalty: +17% (given completion)
2. Failed launches: ~8,973 (3.1% of successful)
3. Recommended timeline RANGE: 138-150 years
- 138y: minimum for 95% reliability
- 150y: optimal time-energy tradeoff
4. Most sensitive factor: Elevator Availability
================================================================================
```
---
## 七、核心结果 (v2)
### 7.1 确定性 vs 不确定性对比139年膝点
| 指标 | 确定性模型 | MC模拟 | 变化 |
|------|-----------|--------|------|
| **总能量(无条件)** | 24,343 PJ | 28,588 PJ | **+17.4%** |
| **总能量(条件)** | 24,343 PJ | 28,577 PJ | **+17.4%** |
| 能量 P95 | - | 30,551 PJ | 风险上界 |
| 完成概率 | 100% | 98.2% | - |
| 成功发射 | 202,856 | 291,675 | +43.8% |
| 失败发射 | 0 | 8,973 | 新增 |
**v2 说明**条件能量和无条件能量非常接近因为完成概率高达98%),但当完成概率较低时二者会有显著差异。
### 7.2 完成时间分布
| 统计量 | 数值 | 物理含义 |
|--------|------|----------|
| 均值 | 124.2 年 | 平均完成时间 |
| 标准差 | 6.6 年 | 时间不确定性 |
| P5 / P50 / P95 | 114.5 / 123.2 / 135.9 年 | 概率分位数 |
### 7.3 **决策指导表ANSWER TO TASK 2**
| 风险偏好 | 最短时间线 | 能量 P95 | 说明 |
|----------|-----------|----------|------|
| **激进 (P≥90%)** | 133 年 | 31,377 PJ | 10%失败风险 |
| **标准 (P≥95%)** | 138 年 | 31,002 PJ | 推荐选择 |
| **保守 (P≥99%)** | 146 年 | 29,673 PJ | 近乎无风险 |
**可行域膝点**150 年(在 P≥95% 区域内的时间-能量权衡最优点)
---
## 八、敏感性分析详细数据
| 参数 | 取值 | 完成概率 | 能量均值 (PJ) | vs 确定性 |
|------|------|----------|--------------|-----------|
| **基准** | - | 97.5% | 28,600 | +17.5% |
| 火箭成功率 | 93%→99% | 96%→98% | 微降 | -1% |
| **电梯可用率** | **80%→95%** | **84%→99%** | **显著降** | **-14%** |
| 天气因子 | 70%→90% | 87%→99% | 微变 | ~0% |
**最敏感因素**:电梯可用率
---
## 九、输出图表
### 9.1 蒙特卡洛模拟结果
![monte_carlo_results](monte_carlo_results.png)
### 9.2 解决方案变化(核心图)
![solution_changes](solution_changes.png)
### 9.3 完成时间分布
![completion_time_dist](completion_time_dist.png)
### 9.4 敏感性分析
![sensitivity_analysis](sensitivity_analysis.png)
### 9.5 情景对比
![scenario_comparison](scenario_comparison.png)
---
## 十、关键结论 (v2)
### 回答:**"To what extent does your solution change?"**
#### 1. 能量惩罚:+17%
```
确定性模型24,343 PJ
MC 模拟均值28,588 PJ (+17.4%)
P95 风险上界30,551 PJ (+25.5%)
```
#### 2. 时间线建议:决策区间而非单点
| 决策者风险偏好 | 推荐时间线 |
|---------------|-----------|
| 激进接受10%失败) | 133 年 |
| 标准接受5%失败) | **138 年** |
| 保守接受1%失败) | 146 年 |
| 时间-能量权衡最优 | 150 年 |
**核心结论**:任务一推荐 139 年,任务二建议 **138-150 年区间**,具体取决于决策者的风险偏好。
#### 3. 失败发射约 9,000 次
- 失败率:约 3.1%
- 失败能量:按阶段加权 44.2%
#### 4. 风险缓解策略
| 策略 | 措施 | 预期效果 |
|------|------|----------|
| **提升电梯维护** | 可用率90%→95% | 完成概率+2%,能耗-5% |
| **延长工期** | 139年→146年 | 完成概率98%→99% |
| **优先低纬度** | 法属圭亚那优先 | 降低单次发射能耗 |
---
## 十一、与任务一的关联
| 对比项 | 任务一(确定性) | 任务二(不确定性) |
|--------|-----------------|-------------------|
| 模型类型 | 确定性优化 | 二项分布蒙特卡洛 |
| 能量口径 | 按站点/纬度/ΔV | **同任务一**(一致性) |
| 推荐时间线 | 139 年(膝点) | **138-150 年(区间)** |
| 能量估算 | 24,343 PJ | 28,588 PJ (+17%) |
| 输出形式 | 单点最优 | 决策表 + 风险分位数 |
---
## 十二、方法论改进说明 (v2)
### 12.1 完成时间单调性修正
**v1 问题**
```python
# 二分搜索每步重新采样 → 非单调
n_succ = np.random.binomial(n_try, p_s) # 每次都不同!
```
**v2 修正**
```python
# 使用期望值函数 → 单调递增
expected_success = n_try * p_s
```
### 12.2 能量口径分离
**v1**:只报告 E[Energy]
**v2**:分开报告
- E[Energy]:无条件均值
- E[Energy | completed]:条件均值
### 12.3 失败能量文献支持
**v1**:固定 30%(无来源)
**v2**:分阶段加权 44.2%(引用 FAA AST 报告)
---
## 十三、数据文件
| 文件 | 内容 |
|------|------|
| `uncertainty_analysis.py` | 主程序(~1200行 |
| `sensitivity_results.csv` | 敏感性分析数据 |
| `pareto_risk_constrained.csv` | 风险约束 Pareto 前沿 |
---
## 十四、参考文献
- FAA AST (2024). Commercial Space Transportation Year in Review
- Metropolis & Ulam (1949). The Monte Carlo Method
- Satopää et al. (2011). Finding a 'Kneedle' in a Haystack

BIN
p2/boxplot_comparison.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

BIN
p2/energy_distribution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
p2/failure_analysis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

View File

@@ -0,0 +1,969 @@
"""
任务二:蒙特卡洛模拟 - 非完美运行条件下的月球殖民地物资运输分析
Monte Carlo Simulation for Moon Colony Logistics Under Imperfect Conditions
模拟故障类型:
1. 缆索摆动 (Tether Swaying) - 导致释放精度偏差需要额外轨道修正ΔV
2. 火箭发射失败 (Rocket Failure) - 发射失败导致载荷损失
3. 电梯故障 (Elevator Breakdown) - 电梯停机维护
4. 天气取消 (Weather Cancellation) - 不利天气导致发射取消
三种方案对比:
- 方案A (成本优先): 纯空间电梯
- 方案B (时间优先): 混合方案(电梯+火箭全开约101年
- 方案C (平衡方案): 混合方案(电梯优先+低纬火箭约139年膝点
"""
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib import rcParams
from dataclasses import dataclass, field
from typing import List, Dict, Tuple, Optional
import pandas as pd
from scipy import stats
from tqdm import tqdm
import warnings
warnings.filterwarnings('ignore')
# 设置字体
rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans', 'SimHei']
rcParams['axes.unicode_minus'] = False
# 随机种子(可复现)
np.random.seed(42)
# ============== 物理常数 ==============
G0 = 9.81 # m/s²
OMEGA_EARTH = 7.27e-5 # rad/s
R_EARTH = 6.371e6 # m
# ============== 任务参数 ==============
TOTAL_PAYLOAD = 100e6 # 100 million metric tons
# ============== 太空电梯参数 ==============
NUM_ELEVATORS = 3
ELEVATOR_CAPACITY_PER_YEAR = 179000 # metric tons per elevator per year
TOTAL_ELEVATOR_CAPACITY = NUM_ELEVATORS * ELEVATOR_CAPACITY_PER_YEAR # 537,000 tons/year
# 电梯比能量 (MJ/kg → J/ton)
ELEVATOR_SPECIFIC_ENERGY = 157.2e9 # J per metric ton (157.2 MJ/kg * 1000 kg)
# 电梯释放速度 (用于计算摆动影响)
ELEVATOR_RELEASE_VELOCITY = 7270 # m/s at 100,000 km (大于逃逸速度)
# ============== 火箭参数 ==============
PAYLOAD_PER_LAUNCH = 125 # metric tons per launch
ISP = 450 # 比冲 (秒)
SPECIFIC_FUEL_ENERGY = 15.5e6 # J/kg
ALPHA = 0.10 # 结构系数
NUM_STAGES = 3
DELTA_V_BASE = 13300 # m/s (赤道发射到月球)
# ============== 故障率参数(基于历史数据和合理假设)==============
@dataclass
class FailureParameters:
"""故障率参数"""
# 火箭发射失败率 (SpaceX Falcon 9: ~2-3%, 假设2050年技术进步)
rocket_failure_rate: float = 0.02 # 2%
# 电梯故障率 (假设技术,年故障次数期望)
elevator_failure_rate_per_year: float = 2.0 # 每部电梯每年平均故障2次
elevator_downtime_days_mean: float = 14 # 平均停机14天
elevator_downtime_days_std: float = 7 # 停机时间标准差
# 天气取消率 (分发射场,基于地理位置)
weather_cancel_rates: Dict[str, float] = field(default_factory=lambda: {
'Kourou': 0.10, # 法属圭亚那,热带,雨季影响
'SDSC': 0.15, # 印度,季风影响
'Texas': 0.12, # 德州,风暴
'Florida': 0.25, # 佛罗里达,雷暴频繁
'California': 0.08, # 加州,天气较好
'Virginia': 0.18, # 弗吉尼亚,东海岸天气
'Taiyuan': 0.10, # 太原,内陆干燥
'Mahia': 0.20, # 新西兰,海洋性天气
'Baikonur': 0.12, # 哈萨克斯坦,大陆性
'Alaska': 0.30, # 阿拉斯加,极端天气
})
# 缆索摆动参数 (释放角度偏差)
tether_sway_std_deg: float = 0.5 # 摆动角度标准差 (度)
# 火箭失败后载荷是否损失
payload_lost_on_failure: bool = True
# 火箭失败后重发延迟 (天)
rocket_failure_delay_days: float = 30
# ============== 发射场定义 ==============
@dataclass
class LaunchSite:
name: str
short_name: str
latitude: float
max_launches_per_day: int = 1
@property
def abs_latitude(self) -> float:
return abs(self.latitude)
@property
def rotation_velocity(self) -> float:
return OMEGA_EARTH * R_EARTH * np.cos(np.radians(self.abs_latitude))
@property
def delta_v_loss(self) -> float:
v_equator = OMEGA_EARTH * R_EARTH
return v_equator - self.rotation_velocity
@property
def total_delta_v(self) -> float:
return DELTA_V_BASE + self.delta_v_loss
# 10个发射场 (按纬度排序)
LAUNCH_SITES = sorted([
LaunchSite("Kourou (French Guiana)", "Kourou", 5.2),
LaunchSite("Satish Dhawan (India)", "SDSC", 13.7),
LaunchSite("Boca Chica (Texas)", "Texas", 26.0),
LaunchSite("Cape Canaveral (Florida)", "Florida", 28.5),
LaunchSite("Vandenberg (California)", "California", 34.7),
LaunchSite("Wallops (Virginia)", "Virginia", 37.8),
LaunchSite("Taiyuan (China)", "Taiyuan", 38.8),
LaunchSite("Mahia (New Zealand)", "Mahia", 39.3),
LaunchSite("Baikonur (Kazakhstan)", "Baikonur", 45.6),
LaunchSite("Kodiak (Alaska)", "Alaska", 57.4),
], key=lambda x: x.abs_latitude)
# ============== 核心计算函数 ==============
def fuel_ratio_multistage(delta_v: float) -> float:
"""多级火箭燃料/载荷比"""
ve = ISP * G0
delta_v_per_stage = delta_v / NUM_STAGES
R_stage = np.exp(delta_v_per_stage / ve)
denominator = 1 - ALPHA * (R_stage - 1)
if denominator <= 0:
return np.inf
k_stage = (R_stage - 1) / denominator
total_fuel_ratio = 0
remaining_ratio = 1.0
for _ in range(NUM_STAGES):
fuel_this_stage = remaining_ratio * k_stage
total_fuel_ratio += fuel_this_stage
remaining_ratio *= (1 + k_stage * (1 + ALPHA))
return total_fuel_ratio
def rocket_energy_per_ton(site: LaunchSite) -> float:
"""火箭发射每吨载荷的能量消耗 (J/ton)"""
k = fuel_ratio_multistage(site.total_delta_v)
fuel_per_ton = k * 1000 # kg fuel per metric ton payload
return fuel_per_ton * SPECIFIC_FUEL_ENERGY
def calculate_tether_sway_energy_penalty(sway_angle_deg: float) -> float:
"""
计算缆索摆动导致的能量惩罚
物理模型:
- 摆动导致释放速度方向偏差
- 需要额外ΔV进行轨道修正
- ΔV_correction ≈ 2 * v_orbit * sin(θ/2) 对于小角度
参数:
sway_angle_deg: 摆动角度 (度)
返回:
额外能量消耗比例 (相对于正常能耗的比例)
"""
sway_angle_rad = np.radians(abs(sway_angle_deg))
# 轨道修正ΔV (小角度近似)
delta_v_correction = ELEVATOR_RELEASE_VELOCITY * sway_angle_rad
# 计算额外燃料需求 (使用火箭方程)
ve = ISP * G0
# 单级修正,燃料比
if delta_v_correction > 0:
mass_ratio = np.exp(delta_v_correction / ve)
fuel_ratio = mass_ratio - 1
# 额外能量 = 额外燃料 * 燃料比能量
extra_energy_per_kg = fuel_ratio * SPECIFIC_FUEL_ENERGY
# 转换为相对于电梯基础能耗的比例
return extra_energy_per_kg / (ELEVATOR_SPECIFIC_ENERGY / 1000) # ELEVATOR_SPECIFIC_ENERGY是J/ton
return 0
# ============== 蒙特卡洛模拟类 ==============
@dataclass
class YearlyResult:
"""单年模拟结果"""
year: int
elevator_payload: float
elevator_energy: float
elevator_downtime_days: float
elevator_sway_energy_penalty: float
rocket_payload: float
rocket_energy: float
rocket_launches_attempted: int
rocket_launches_failed: int
rocket_weather_cancelled: int
@property
def total_payload(self) -> float:
return self.elevator_payload + self.rocket_payload
@property
def total_energy(self) -> float:
return self.elevator_energy + self.elevator_sway_energy_penalty + self.rocket_energy
@dataclass
class SimulationResult:
"""单次模拟结果"""
scenario_name: str
completion_years: float
total_energy_pj: float
elevator_payload: float
rocket_payload: float
total_rocket_failures: int
total_weather_cancellations: int
total_elevator_downtime_days: float
total_sway_energy_penalty_pj: float
yearly_results: List[YearlyResult] = field(default_factory=list)
class MonteCarloSimulator:
"""蒙特卡洛模拟器"""
def __init__(self, params: FailureParameters = None):
self.params = params or FailureParameters()
def simulate_elevator_year(
self,
remaining_payload: float,
year: int
) -> Tuple[float, float, float, float]:
"""
模拟电梯一年的运行
返回: (运输载荷, 基础能量, 停机天数, 摆动能量惩罚)
"""
total_downtime_days = 0
total_sway_penalty = 0
# 模拟每部电梯
for elevator_id in range(NUM_ELEVATORS):
# 模拟故障事件 (泊松过程)
num_failures = np.random.poisson(self.params.elevator_failure_rate_per_year)
for _ in range(num_failures):
# 停机时间 (对数正态分布,确保正值)
downtime = max(1, np.random.normal(
self.params.elevator_downtime_days_mean,
self.params.elevator_downtime_days_std
))
total_downtime_days += downtime
# 计算有效运行天数
effective_days = max(0, 365 * NUM_ELEVATORS - total_downtime_days)
effective_capacity_ratio = effective_days / (365 * NUM_ELEVATORS)
# 实际运输量
max_payload = TOTAL_ELEVATOR_CAPACITY * effective_capacity_ratio
actual_payload = min(max_payload, remaining_payload)
# 基础能量
base_energy = actual_payload * ELEVATOR_SPECIFIC_ENERGY
# 模拟每次运输的缆索摆动
# 假设每天运输一批次
num_trips = int(actual_payload / (TOTAL_ELEVATOR_CAPACITY / 365)) if TOTAL_ELEVATOR_CAPACITY > 0 else 0
for _ in range(max(1, num_trips)):
# 摆动角度 (正态分布)
sway_angle = np.random.normal(0, self.params.tether_sway_std_deg)
penalty_ratio = calculate_tether_sway_energy_penalty(sway_angle)
total_sway_penalty += base_energy * penalty_ratio / num_trips if num_trips > 0 else 0
return actual_payload, base_energy, total_downtime_days, total_sway_penalty
def simulate_rocket_year(
self,
remaining_payload: float,
target_launches: int,
sites_to_use: List[LaunchSite],
year: int
) -> Tuple[float, float, int, int, int]:
"""
模拟火箭一年的发射
返回: (运输载荷, 能量消耗, 尝试发射次数, 失败次数, 天气取消次数)
"""
if target_launches <= 0 or remaining_payload <= 0:
return 0, 0, 0, 0, 0
total_payload = 0
total_energy = 0
total_attempts = 0
total_failures = 0
total_weather_cancel = 0
# 按纬度优先分配发射
launches_per_site = target_launches // len(sites_to_use) if len(sites_to_use) > 0 else 0
extra_launches = target_launches % len(sites_to_use) if len(sites_to_use) > 0 else 0
for i, site in enumerate(sites_to_use):
site_launches = launches_per_site + (1 if i < extra_launches else 0)
for launch_idx in range(site_launches):
if total_payload >= remaining_payload:
break
total_attempts += 1
# 天气取消检查
weather_rate = self.params.weather_cancel_rates.get(site.short_name, 0.15)
if np.random.random() < weather_rate:
total_weather_cancel += 1
continue
# 发射失败检查
if np.random.random() < self.params.rocket_failure_rate:
total_failures += 1
if self.params.payload_lost_on_failure:
# 载荷损失,但仍消耗能量
total_energy += rocket_energy_per_ton(site) * PAYLOAD_PER_LAUNCH
continue
# 成功发射
payload = min(PAYLOAD_PER_LAUNCH, remaining_payload - total_payload)
total_payload += payload
total_energy += rocket_energy_per_ton(site) * payload
return total_payload, total_energy, total_attempts, total_failures, total_weather_cancel
def simulate_scenario(
self,
scenario_name: str,
target_years: float,
use_elevator: bool = True,
use_rockets: bool = True,
max_years: int = 500
) -> SimulationResult:
"""
模拟单个场景
参数:
scenario_name: 方案名称
target_years: 目标完成年限
use_elevator: 是否使用电梯
use_rockets: 是否使用火箭
max_years: 最大模拟年限
"""
remaining_payload = TOTAL_PAYLOAD
total_energy = 0
total_elevator_payload = 0
total_rocket_payload = 0
total_rocket_failures = 0
total_weather_cancellations = 0
total_elevator_downtime = 0
total_sway_penalty = 0
yearly_results = []
# 计算每年需要的火箭发射量(如果需要)
if use_rockets and use_elevator:
# 混合方案:计算火箭需要补充的量
elevator_total_capacity = TOTAL_ELEVATOR_CAPACITY * target_years
rocket_needed = max(0, TOTAL_PAYLOAD - elevator_total_capacity)
rocket_launches_per_year = int(np.ceil(rocket_needed / PAYLOAD_PER_LAUNCH / target_years))
elif use_rockets and not use_elevator:
# 纯火箭
rocket_launches_per_year = int(np.ceil(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH / target_years))
else:
rocket_launches_per_year = 0
year = 0
while remaining_payload > 0 and year < max_years:
year += 1
# 电梯运输
elev_payload, elev_energy, elev_downtime, sway_penalty = 0, 0, 0, 0
if use_elevator:
elev_payload, elev_energy, elev_downtime, sway_penalty = \
self.simulate_elevator_year(remaining_payload, year)
remaining_payload -= elev_payload
total_elevator_payload += elev_payload
total_energy += elev_energy + sway_penalty
total_elevator_downtime += elev_downtime
total_sway_penalty += sway_penalty
# 火箭运输
rock_payload, rock_energy, attempts, failures, weather = 0, 0, 0, 0, 0
if use_rockets and remaining_payload > 0:
rock_payload, rock_energy, attempts, failures, weather = \
self.simulate_rocket_year(
remaining_payload,
rocket_launches_per_year,
LAUNCH_SITES,
year
)
remaining_payload -= rock_payload
total_rocket_payload += rock_payload
total_energy += rock_energy
total_rocket_failures += failures
total_weather_cancellations += weather
yearly_results.append(YearlyResult(
year=year,
elevator_payload=elev_payload,
elevator_energy=elev_energy,
elevator_downtime_days=elev_downtime,
elevator_sway_energy_penalty=sway_penalty,
rocket_payload=rock_payload,
rocket_energy=rock_energy,
rocket_launches_attempted=attempts,
rocket_launches_failed=failures,
rocket_weather_cancelled=weather
))
return SimulationResult(
scenario_name=scenario_name,
completion_years=year,
total_energy_pj=total_energy / 1e15,
elevator_payload=total_elevator_payload,
rocket_payload=total_rocket_payload,
total_rocket_failures=total_rocket_failures,
total_weather_cancellations=total_weather_cancellations,
total_elevator_downtime_days=total_elevator_downtime,
total_sway_energy_penalty_pj=total_sway_penalty / 1e15,
yearly_results=yearly_results
)
def run_monte_carlo(
self,
scenario_name: str,
target_years: float,
use_elevator: bool,
use_rockets: bool,
n_simulations: int = 1000,
show_progress: bool = True
) -> List[SimulationResult]:
"""运行蒙特卡洛模拟"""
results = []
iterator = range(n_simulations)
if show_progress:
iterator = tqdm(iterator, desc=f"Simulating {scenario_name[:30]}", unit="sim")
for i in iterator:
result = self.simulate_scenario(
scenario_name=scenario_name,
target_years=target_years,
use_elevator=use_elevator,
use_rockets=use_rockets
)
results.append(result)
return results
# ============== 三种方案定义 ==============
def define_scenarios() -> Dict[str, Dict]:
"""
定义三种方案
基于任务一的分析结果:
- 纯电梯: ~186年15720 PJ
- 混合最短时间: ~101年
- 混合膝点: ~139年
"""
# 计算关键时间点
elevator_only_years = TOTAL_PAYLOAD / TOTAL_ELEVATOR_CAPACITY # ~186年
rocket_capacity_per_year = len(LAUNCH_SITES) * 365 * PAYLOAD_PER_LAUNCH
combined_min_years = TOTAL_PAYLOAD / (TOTAL_ELEVATOR_CAPACITY + rocket_capacity_per_year) # ~101年
balanced_years = 139 # 膝点
return {
'Scenario_A': {
'name': 'Cost Priority (Elevator Only)',
'name_cn': '方案A: 成本优先(纯电梯)',
'target_years': elevator_only_years,
'use_elevator': True,
'use_rockets': False,
'description': '仅使用太空电梯,能耗最低但耗时最长'
},
'Scenario_B': {
'name': 'Time Priority (Combined - Max Speed)',
'name_cn': '方案B: 时间优先(混合-全速)',
'target_years': combined_min_years * 1.05, # 加5%余量
'use_elevator': True,
'use_rockets': True,
'description': '电梯+火箭全开,时间最短但能耗较高'
},
'Scenario_C': {
'name': 'Balanced (Combined - Knee Point)',
'name_cn': '方案C: 综合平衡(膝点方案)',
'target_years': balanced_years,
'use_elevator': True,
'use_rockets': True,
'description': '电梯优先+低纬火箭补充,成本-时间平衡'
}
}
# ============== 可视化函数 ==============
def plot_monte_carlo_results(
all_results: Dict[str, List[SimulationResult]],
save_dir: str = '/Volumes/Files/code/mm/20260130_b/p2'
):
"""绘制蒙特卡洛模拟结果"""
scenarios = define_scenarios()
# ========== 图1: 完成年份分布 ==========
fig1, axes1 = plt.subplots(1, 3, figsize=(15, 5))
colors = ['green', 'blue', 'purple']
for idx, (key, results) in enumerate(all_results.items()):
ax = axes1[idx]
years = [r.completion_years for r in results]
ax.hist(years, bins=30, color=colors[idx], alpha=0.7, edgecolor='black')
ax.axvline(np.mean(years), color='red', linestyle='--', linewidth=2,
label=f'Mean: {np.mean(years):.1f}')
ax.axvline(np.percentile(years, 5), color='orange', linestyle=':', linewidth=1.5,
label=f'5%: {np.percentile(years, 5):.1f}')
ax.axvline(np.percentile(years, 95), color='orange', linestyle=':', linewidth=1.5,
label=f'95%: {np.percentile(years, 95):.1f}')
ax.set_xlabel('Completion Years', fontsize=11)
ax.set_ylabel('Frequency', fontsize=11)
ax.set_title(f"{scenarios[key]['name']}\nCompletion Time Distribution", fontsize=12)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{save_dir}/completion_time_distribution.png', dpi=150, bbox_inches='tight')
print(f"完成年份分布图已保存")
# ========== 图2: 能量消耗分布 ==========
fig2, axes2 = plt.subplots(1, 3, figsize=(15, 5))
for idx, (key, results) in enumerate(all_results.items()):
ax = axes2[idx]
energy = [r.total_energy_pj for r in results]
ax.hist(energy, bins=30, color=colors[idx], alpha=0.7, edgecolor='black')
ax.axvline(np.mean(energy), color='red', linestyle='--', linewidth=2,
label=f'Mean: {np.mean(energy):.0f} PJ')
ax.axvline(np.percentile(energy, 5), color='orange', linestyle=':', linewidth=1.5,
label=f'5%: {np.percentile(energy, 5):.0f}')
ax.axvline(np.percentile(energy, 95), color='orange', linestyle=':', linewidth=1.5,
label=f'95%: {np.percentile(energy, 95):.0f}')
ax.set_xlabel('Total Energy (PJ)', fontsize=11)
ax.set_ylabel('Frequency', fontsize=11)
ax.set_title(f"{scenarios[key]['name']}\nEnergy Distribution", fontsize=12)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{save_dir}/energy_distribution.png', dpi=150, bbox_inches='tight')
print(f"能量分布图已保存")
# ========== 图3: 箱线图对比 ==========
fig3, axes3 = plt.subplots(1, 2, figsize=(14, 6))
# 完成年份箱线图
ax3a = axes3[0]
years_data = [[r.completion_years for r in results] for results in all_results.values()]
bp1 = ax3a.boxplot(years_data, labels=['A: Elevator\nOnly', 'B: Time\nPriority', 'C: Balanced'],
patch_artist=True)
for patch, color in zip(bp1['boxes'], colors):
patch.set_facecolor(color)
patch.set_alpha(0.7)
ax3a.set_ylabel('Completion Years', fontsize=12)
ax3a.set_title('Completion Time Comparison (Monte Carlo)', fontsize=13)
ax3a.grid(True, alpha=0.3)
# 能量消耗箱线图
ax3b = axes3[1]
energy_data = [[r.total_energy_pj for r in results] for results in all_results.values()]
bp2 = ax3b.boxplot(energy_data, labels=['A: Elevator\nOnly', 'B: Time\nPriority', 'C: Balanced'],
patch_artist=True)
for patch, color in zip(bp2['boxes'], colors):
patch.set_facecolor(color)
patch.set_alpha(0.7)
ax3b.set_ylabel('Total Energy (PJ)', fontsize=12)
ax3b.set_title('Energy Consumption Comparison (Monte Carlo)', fontsize=13)
ax3b.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{save_dir}/boxplot_comparison.png', dpi=150, bbox_inches='tight')
print(f"箱线图对比已保存")
# ========== 图4: 故障影响分析 ==========
fig4, axes4 = plt.subplots(2, 2, figsize=(14, 12))
# 火箭失败统计
ax4a = axes4[0, 0]
for idx, (key, results) in enumerate(all_results.items()):
failures = [r.total_rocket_failures for r in results]
if max(failures) > 0:
ax4a.hist(failures, bins=20, color=colors[idx], alpha=0.5,
label=scenarios[key]['name'], edgecolor='black')
ax4a.set_xlabel('Total Rocket Failures', fontsize=11)
ax4a.set_ylabel('Frequency', fontsize=11)
ax4a.set_title('Rocket Launch Failures Distribution', fontsize=12)
ax4a.legend()
ax4a.grid(True, alpha=0.3)
# 天气取消统计
ax4b = axes4[0, 1]
for idx, (key, results) in enumerate(all_results.items()):
weather = [r.total_weather_cancellations for r in results]
if max(weather) > 0:
ax4b.hist(weather, bins=20, color=colors[idx], alpha=0.5,
label=scenarios[key]['name'], edgecolor='black')
ax4b.set_xlabel('Total Weather Cancellations', fontsize=11)
ax4b.set_ylabel('Frequency', fontsize=11)
ax4b.set_title('Weather Cancellation Distribution', fontsize=12)
ax4b.legend()
ax4b.grid(True, alpha=0.3)
# 电梯停机时间统计
ax4c = axes4[1, 0]
for idx, (key, results) in enumerate(all_results.items()):
downtime = [r.total_elevator_downtime_days for r in results]
if max(downtime) > 0:
ax4c.hist(downtime, bins=20, color=colors[idx], alpha=0.5,
label=scenarios[key]['name'], edgecolor='black')
ax4c.set_xlabel('Total Elevator Downtime (days)', fontsize=11)
ax4c.set_ylabel('Frequency', fontsize=11)
ax4c.set_title('Elevator Downtime Distribution', fontsize=12)
ax4c.legend()
ax4c.grid(True, alpha=0.3)
# 缆索摆动能量惩罚
ax4d = axes4[1, 1]
for idx, (key, results) in enumerate(all_results.items()):
sway = [r.total_sway_energy_penalty_pj for r in results]
if max(sway) > 0:
ax4d.hist(sway, bins=20, color=colors[idx], alpha=0.5,
label=scenarios[key]['name'], edgecolor='black')
ax4d.set_xlabel('Tether Sway Energy Penalty (PJ)', fontsize=11)
ax4d.set_ylabel('Frequency', fontsize=11)
ax4d.set_title('Tether Sway Energy Penalty Distribution', fontsize=12)
ax4d.legend()
ax4d.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{save_dir}/failure_analysis.png', dpi=150, bbox_inches='tight')
print(f"故障分析图已保存")
# ========== 图5: 敏感性分析 - 龙卷风图 ==========
fig5, ax5 = plt.subplots(figsize=(12, 8))
# 计算各因素对完成时间的影响以方案C为例
results_c = all_results['Scenario_C']
# 计算相关性
years = np.array([r.completion_years for r in results_c])
failures = np.array([r.total_rocket_failures for r in results_c])
weather = np.array([r.total_weather_cancellations for r in results_c])
downtime = np.array([r.total_elevator_downtime_days for r in results_c])
sway = np.array([r.total_sway_energy_penalty_pj for r in results_c])
# 计算Spearman相关系数
correlations = {
'Rocket Failures': stats.spearmanr(failures, years)[0] if failures.std() > 0 else 0,
'Weather Cancellations': stats.spearmanr(weather, years)[0] if weather.std() > 0 else 0,
'Elevator Downtime': stats.spearmanr(downtime, years)[0] if downtime.std() > 0 else 0,
'Tether Sway Penalty': stats.spearmanr(sway, years)[0] if sway.std() > 0 else 0,
}
# 排序
sorted_corr = sorted(correlations.items(), key=lambda x: abs(x[1]), reverse=True)
labels = [x[0] for x in sorted_corr]
values = [x[1] for x in sorted_corr]
colors_bar = ['red' if v > 0 else 'blue' for v in values]
y_pos = np.arange(len(labels))
ax5.barh(y_pos, values, color=colors_bar, alpha=0.7)
ax5.set_yticks(y_pos)
ax5.set_yticklabels(labels)
ax5.set_xlabel('Spearman Correlation with Completion Time', fontsize=12)
ax5.set_title('Sensitivity Analysis: Factors Affecting Completion Time\n(Scenario C: Balanced)', fontsize=13)
ax5.axvline(x=0, color='black', linestyle='-', linewidth=0.5)
ax5.grid(True, alpha=0.3, axis='x')
# 添加数值标签
for i, v in enumerate(values):
ax5.text(v + 0.02 if v > 0 else v - 0.02, i, f'{v:.3f}',
va='center', ha='left' if v > 0 else 'right', fontsize=10)
plt.tight_layout()
plt.savefig(f'{save_dir}/sensitivity_tornado.png', dpi=150, bbox_inches='tight')
print(f"敏感性龙卷风图已保存")
# ========== 图6: 综合对比图 ==========
fig6, axes6 = plt.subplots(2, 2, figsize=(14, 12))
# 左上:完成时间 vs 能量散点图
ax6a = axes6[0, 0]
for idx, (key, results) in enumerate(all_results.items()):
years = [r.completion_years for r in results]
energy = [r.total_energy_pj for r in results]
ax6a.scatter(years, energy, c=colors[idx], alpha=0.3, s=20,
label=scenarios[key]['name'])
# 添加均值点
ax6a.scatter(np.mean(years), np.mean(energy), c=colors[idx],
s=200, marker='*', edgecolors='black', linewidth=2)
ax6a.set_xlabel('Completion Years', fontsize=11)
ax6a.set_ylabel('Total Energy (PJ)', fontsize=11)
ax6a.set_title('Years vs Energy Trade-off\n(Stars = Mean)', fontsize=12)
ax6a.legend()
ax6a.grid(True, alpha=0.3)
# 右上:完成时间累积分布
ax6b = axes6[0, 1]
for idx, (key, results) in enumerate(all_results.items()):
years = sorted([r.completion_years for r in results])
cdf = np.arange(1, len(years) + 1) / len(years)
ax6b.plot(years, cdf, color=colors[idx], linewidth=2, label=scenarios[key]['name'])
ax6b.set_xlabel('Completion Years', fontsize=11)
ax6b.set_ylabel('Cumulative Probability', fontsize=11)
ax6b.set_title('Completion Time CDF', fontsize=12)
ax6b.legend()
ax6b.grid(True, alpha=0.3)
# 左下:各方案统计摘要表格
ax6c = axes6[1, 0]
ax6c.axis('off')
summary_data = []
for key, results in all_results.items():
years = [r.completion_years for r in results]
energy = [r.total_energy_pj for r in results]
summary_data.append([
scenarios[key]['name'][:20],
f"{np.mean(years):.1f}",
f"{np.std(years):.1f}",
f"[{np.percentile(years, 5):.0f}, {np.percentile(years, 95):.0f}]",
f"{np.mean(energy):.0f}",
f"{np.std(energy):.0f}",
])
table = ax6c.table(
cellText=summary_data,
colLabels=['Scenario', 'Years\n(Mean)', 'Years\n(Std)', '90% CI', 'Energy\n(PJ Mean)', 'Energy\n(PJ Std)'],
loc='center',
cellLoc='center'
)
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 2)
ax6c.set_title('Statistical Summary', fontsize=12, pad=20)
# 右下:相对于理想情况的延迟分布
ax6d = axes6[1, 1]
# 计算相对延迟
for idx, (key, results) in enumerate(all_results.items()):
target = scenarios[key]['target_years']
delays = [(r.completion_years - target) / target * 100 for r in results]
ax6d.hist(delays, bins=25, color=colors[idx], alpha=0.5,
label=scenarios[key]['name'], edgecolor='black')
ax6d.axvline(x=0, color='black', linestyle='--', linewidth=2, label='Target (0% delay)')
ax6d.set_xlabel('Delay Relative to Target (%)', fontsize=11)
ax6d.set_ylabel('Frequency', fontsize=11)
ax6d.set_title('Delay Distribution (Due to Failures)', fontsize=12)
ax6d.legend()
ax6d.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f'{save_dir}/comprehensive_comparison.png', dpi=150, bbox_inches='tight')
print(f"综合对比图已保存")
return fig1, fig2, fig3, fig4, fig5, fig6
def generate_statistics_report(
all_results: Dict[str, List[SimulationResult]],
params: FailureParameters
) -> str:
"""生成统计报告"""
scenarios = define_scenarios()
report = []
report.append("=" * 80)
report.append("MONTE CARLO SIMULATION RESULTS - STATISTICAL SUMMARY")
report.append("=" * 80)
report.append("\n## 故障参数设置")
report.append(f"- 火箭发射失败率: {params.rocket_failure_rate * 100:.1f}%")
report.append(f"- 电梯年故障次数: {params.elevator_failure_rate_per_year:.1f} 次/部/年")
report.append(f"- 电梯平均停机时间: {params.elevator_downtime_days_mean:.0f} ± {params.elevator_downtime_days_std:.0f}")
report.append(f"- 缆索摆动角度标准差: {params.tether_sway_std_deg:.2f}°")
report.append(f"- 天气取消率范围: {min(params.weather_cancel_rates.values())*100:.0f}% - {max(params.weather_cancel_rates.values())*100:.0f}%")
for key, results in all_results.items():
scenario = scenarios[key]
years = [r.completion_years for r in results]
energy = [r.total_energy_pj for r in results]
failures = [r.total_rocket_failures for r in results]
weather = [r.total_weather_cancellations for r in results]
downtime = [r.total_elevator_downtime_days for r in results]
sway = [r.total_sway_energy_penalty_pj for r in results]
report.append(f"\n{'=' * 80}")
report.append(f"## {scenario['name_cn']}")
report.append(f" {scenario['description']}")
report.append(f"{'=' * 80}")
report.append(f"\n### 完成时间统计")
report.append(f" 目标年限: {scenario['target_years']:.1f}")
report.append(f" 均值: {np.mean(years):.1f}")
report.append(f" 标准差: {np.std(years):.1f}")
report.append(f" 90% 置信区间: [{np.percentile(years, 5):.1f}, {np.percentile(years, 95):.1f}] 年")
report.append(f" 最短: {np.min(years):.1f} 年, 最长: {np.max(years):.1f}")
report.append(f" 相对目标延迟: {(np.mean(years) - scenario['target_years']) / scenario['target_years'] * 100:.1f}%")
report.append(f"\n### 能量消耗统计")
report.append(f" 均值: {np.mean(energy):.0f} PJ")
report.append(f" 标准差: {np.std(energy):.0f} PJ")
report.append(f" 90% 置信区间: [{np.percentile(energy, 5):.0f}, {np.percentile(energy, 95):.0f}] PJ")
if scenario['use_rockets']:
report.append(f"\n### 火箭故障统计")
report.append(f" 平均失败次数: {np.mean(failures):.1f}")
report.append(f" 平均天气取消: {np.mean(weather):.1f}")
if scenario['use_elevator']:
report.append(f"\n### 电梯故障统计")
report.append(f" 平均总停机时间: {np.mean(downtime):.0f} 天 ({np.mean(downtime)/365:.1f} 年)")
report.append(f" 平均摆动能量惩罚: {np.mean(sway):.1f} PJ ({np.mean(sway)/np.mean(energy)*100:.2f}%)")
# 方案对比
report.append(f"\n{'=' * 80}")
report.append("## 三方案对比总结")
report.append(f"{'=' * 80}")
report.append(f"\n{'方案':<25} {'完成年限':<15} {'总能耗(PJ)':<15} {'延迟率':<12}")
report.append("-" * 70)
for key, results in all_results.items():
scenario = scenarios[key]
years = [r.completion_years for r in results]
energy = [r.total_energy_pj for r in results]
delay = (np.mean(years) - scenario['target_years']) / scenario['target_years'] * 100
report.append(f"{scenario['name']:<25} {np.mean(years):.1f} ± {np.std(years):.1f} {np.mean(energy):.0f} ± {np.std(energy):.0f} {delay:+.1f}%")
return "\n".join(report)
# ============== 主程序 ==============
def run_full_simulation(n_simulations: int = 1000):
"""运行完整的蒙特卡洛模拟"""
import sys
print("=" * 80)
print("任务二:蒙特卡洛模拟 - 非完美运行条件分析")
print("=" * 80)
sys.stdout.flush()
# 初始化参数
params = FailureParameters()
simulator = MonteCarloSimulator(params)
scenarios = define_scenarios()
print(f"\n模拟次数: {n_simulations}")
print(f"\n故障参数:")
print(f" - 火箭失败率: {params.rocket_failure_rate * 100:.1f}%")
print(f" - 电梯年故障次数: {params.elevator_failure_rate_per_year:.1f}")
print(f" - 缆索摆动标准差: {params.tether_sway_std_deg:.2f}°")
# 运行三种方案的模拟
all_results = {}
for key, scenario in scenarios.items():
print(f"\n{'='*60}")
print(f"正在模拟 {scenario['name_cn']}...")
print(f"目标年限: {scenario['target_years']:.1f}")
print(f"{'='*60}")
results = simulator.run_monte_carlo(
scenario_name=scenario['name'],
target_years=scenario['target_years'],
use_elevator=scenario['use_elevator'],
use_rockets=scenario['use_rockets'],
n_simulations=n_simulations,
show_progress=True
)
all_results[key] = results
# 打印简要统计
years = [r.completion_years for r in results]
energy = [r.total_energy_pj for r in results]
print(f"\n ✓ 完成年限: {np.mean(years):.1f} ± {np.std(years):.1f}")
print(f" ✓ 总能耗: {np.mean(energy):.0f} ± {np.std(energy):.0f} PJ")
# 生成可视化
print("\n正在生成可视化图表...")
plot_monte_carlo_results(all_results)
# 生成统计报告
print("\n正在生成统计报告...")
report = generate_statistics_report(all_results, params)
print(report)
# 保存报告
with open('/Volumes/Files/code/mm/20260130_b/p2/simulation_report.txt', 'w', encoding='utf-8') as f:
f.write(report)
print(f"\n统计报告已保存至: p2/simulation_report.txt")
# 保存结果数据
summary_data = []
for key, results in all_results.items():
scenario = scenarios[key]
for r in results:
summary_data.append({
'scenario': key,
'scenario_name': scenario['name'],
'target_years': scenario['target_years'],
'completion_years': r.completion_years,
'total_energy_pj': r.total_energy_pj,
'elevator_payload': r.elevator_payload,
'rocket_payload': r.rocket_payload,
'rocket_failures': r.total_rocket_failures,
'weather_cancellations': r.total_weather_cancellations,
'elevator_downtime_days': r.total_elevator_downtime_days,
'sway_energy_penalty_pj': r.total_sway_energy_penalty_pj
})
df = pd.DataFrame(summary_data)
df.to_csv('/Volumes/Files/code/mm/20260130_b/p2/simulation_results.csv', index=False)
print(f"模拟数据已保存至: p2/simulation_results.csv")
return all_results, params
if __name__ == "__main__":
all_results, params = run_full_simulation(n_simulations=1000)

View File

@@ -1,26 +0,0 @@
years,prob,feasible,energy_mean_mc,energy_p95_mc,energy_det,energy_increase_pct
100.0,0.0,False,25372.033041820563,28072.05031018136,,
104.16666666666667,0.0,False,26439.355755837205,29267.49987337852,31022.26249697984,-14.772961003694697
108.33333333333333,0.0,False,27483.36708485973,30391.959579786162,30189.152484451704,-8.962773635283517
112.5,0.013,False,28492.85598452039,31504.026755271323,29379.644770658626,-3.018378176661518
116.66666666666667,0.143,False,29512.20025723855,32107.63269364828,28582.607044590433,3.252303791595712
120.83333333333334,0.3665,False,30061.93408877843,32244.13361324691,27786.96843237234,8.187167527623163
125.0,0.62,False,30232.899972248288,32028.916165945262,26992.42807071392,12.005114519690796
129.16666666666666,0.7965,False,29963.15866612223,31757.888186627566,26199.501339607,14.365377713603799
133.33333333333334,0.9045,False,29491.539020149194,31377.418568091212,25411.26664775879,16.056942099540205
137.5,0.96,True,28891.787516111122,31002.05216178532,24625.76227157463,17.32342413400434
141.66666666666669,0.9855,True,28164.80167362264,30258.555589863852,23848.166944890552,18.10048855623647
145.83333333333334,0.997,True,27503.630490981155,29673.38830753458,23074.9546010554,19.192565994141518
150.0,0.9995,True,26768.450765527432,28896.02128487065,22303.29589355392,20.020157080299626
154.16666666666669,1.0,True,26085.083134632587,28333.974032687096,21534.119669496904,21.13373351213481
158.33333333333334,1.0,True,25337.651561865478,27747.060197069248,20764.941930628607,22.021297466245528
162.5,1.0,True,24707.204633635283,27089.174803016234,20006.62753947831,23.495099735732584
166.66666666666669,1.0,True,23977.757529870985,26326.23453872308,19251.053019212643,24.552966042642275
170.83333333333334,1.0,True,23303.60704756015,25881.10234387964,18495.478498946977,25.996237669043907
175.0,1.0,True,22598.38386359338,25122.701828406385,17743.284740252642,27.36302321929376
179.16666666666669,1.0,True,21896.20673965992,24418.38423442558,16991.898913478322,28.86262360171763
183.33333333333334,1.0,True,21233.987221266052,23815.443439396382,16240.513086703999,30.747022017735247
187.5,1.0,True,20572.244424940738,23225.842256536464,15720.0,30.866694815144633
191.66666666666669,1.0,True,19919.524749093463,22723.356523238544,15720.0,26.714534027312098
195.83333333333334,1.0,True,19270.13966362218,22133.939931797722,15720.0,22.58358564645153
200.0,1.0,True,18532.850120978102,21359.98437171606,15720.0,17.89344860673092
1 years prob feasible energy_mean_mc energy_p95_mc energy_det energy_increase_pct
2 100.0 0.0 False 25372.033041820563 28072.05031018136
3 104.16666666666667 0.0 False 26439.355755837205 29267.49987337852 31022.26249697984 -14.772961003694697
4 108.33333333333333 0.0 False 27483.36708485973 30391.959579786162 30189.152484451704 -8.962773635283517
5 112.5 0.013 False 28492.85598452039 31504.026755271323 29379.644770658626 -3.018378176661518
6 116.66666666666667 0.143 False 29512.20025723855 32107.63269364828 28582.607044590433 3.252303791595712
7 120.83333333333334 0.3665 False 30061.93408877843 32244.13361324691 27786.96843237234 8.187167527623163
8 125.0 0.62 False 30232.899972248288 32028.916165945262 26992.42807071392 12.005114519690796
9 129.16666666666666 0.7965 False 29963.15866612223 31757.888186627566 26199.501339607 14.365377713603799
10 133.33333333333334 0.9045 False 29491.539020149194 31377.418568091212 25411.26664775879 16.056942099540205
11 137.5 0.96 True 28891.787516111122 31002.05216178532 24625.76227157463 17.32342413400434
12 141.66666666666669 0.9855 True 28164.80167362264 30258.555589863852 23848.166944890552 18.10048855623647
13 145.83333333333334 0.997 True 27503.630490981155 29673.38830753458 23074.9546010554 19.192565994141518
14 150.0 0.9995 True 26768.450765527432 28896.02128487065 22303.29589355392 20.020157080299626
15 154.16666666666669 1.0 True 26085.083134632587 28333.974032687096 21534.119669496904 21.13373351213481
16 158.33333333333334 1.0 True 25337.651561865478 27747.060197069248 20764.941930628607 22.021297466245528
17 162.5 1.0 True 24707.204633635283 27089.174803016234 20006.62753947831 23.495099735732584
18 166.66666666666669 1.0 True 23977.757529870985 26326.23453872308 19251.053019212643 24.552966042642275
19 170.83333333333334 1.0 True 23303.60704756015 25881.10234387964 18495.478498946977 25.996237669043907
20 175.0 1.0 True 22598.38386359338 25122.701828406385 17743.284740252642 27.36302321929376
21 179.16666666666669 1.0 True 21896.20673965992 24418.38423442558 16991.898913478322 28.86262360171763
22 183.33333333333334 1.0 True 21233.987221266052 23815.443439396382 16240.513086703999 30.747022017735247
23 187.5 1.0 True 20572.244424940738 23225.842256536464 15720.0 30.866694815144633
24 191.66666666666669 1.0 True 19919.524749093463 22723.356523238544 15720.0 26.714534027312098
25 195.83333333333334 1.0 True 19270.13966362218 22133.939931797722 15720.0 22.58358564645153
26 200.0 1.0 True 18532.850120978102 21359.98437171606 15720.0 17.89344860673092

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

View File

@@ -1,15 +0,0 @@
Parameter,Value,Completion Prob,Energy Mean (PJ),Energy P95 (PJ),vs Deterministic
Baseline,-,0.97,28596.01710309635,30564.886524529153,+17.5%
Rocket Success Rate,93%,0.9575,28878.902643863366,30891.28901266845,+18.6%
Rocket Success Rate,95%,0.968,28748.3018651089,30708.888318250705,+18.1%
Rocket Success Rate,97%,0.9795,28629.360858451142,30645.327480730295,+17.6%
Rocket Success Rate,99%,0.9775,28439.468083358966,30473.625164137902,+16.8%
Elevator Availability,80%,0.828,30918.56112676015,32842.19981586814,+27.0%
Elevator Availability,85%,0.9185,29821.688216162085,31744.193121079687,+22.5%
Elevator Availability,90%,0.965,28611.460729304432,30636.719213453933,+17.5%
Elevator Availability,95%,0.9945,27338.025136295357,29606.035821357837,+12.3%
Weather Factor,70%,0.863,28472.031748325277,30451.165280990353,+17.0%
Weather Factor,75%,0.9335,28568.68030314252,30606.620356883606,+17.4%
Weather Factor,80%,0.9775,28529.595755356648,30528.48416862068,+17.2%
Weather Factor,85%,0.9845,28615.163139569464,30780.73030967962,+17.5%
Weather Factor,90%,0.996,28641.794065098013,30715.86009554269,+17.7%
1 Parameter Value Completion Prob Energy Mean (PJ) Energy P95 (PJ) vs Deterministic
2 Baseline - 0.97 28596.01710309635 30564.886524529153 +17.5%
3 Rocket Success Rate 93% 0.9575 28878.902643863366 30891.28901266845 +18.6%
4 Rocket Success Rate 95% 0.968 28748.3018651089 30708.888318250705 +18.1%
5 Rocket Success Rate 97% 0.9795 28629.360858451142 30645.327480730295 +17.6%
6 Rocket Success Rate 99% 0.9775 28439.468083358966 30473.625164137902 +16.8%
7 Elevator Availability 80% 0.828 30918.56112676015 32842.19981586814 +27.0%
8 Elevator Availability 85% 0.9185 29821.688216162085 31744.193121079687 +22.5%
9 Elevator Availability 90% 0.965 28611.460729304432 30636.719213453933 +17.5%
10 Elevator Availability 95% 0.9945 27338.025136295357 29606.035821357837 +12.3%
11 Weather Factor 70% 0.863 28472.031748325277 30451.165280990353 +17.0%
12 Weather Factor 75% 0.9335 28568.68030314252 30606.620356883606 +17.4%
13 Weather Factor 80% 0.9775 28529.595755356648 30528.48416862068 +17.2%
14 Weather Factor 85% 0.9845 28615.163139569464 30780.73030967962 +17.5%
15 Weather Factor 90% 0.996 28641.794065098013 30715.86009554269 +17.7%

BIN
p2/sensitivity_tornado.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

94
p2/simulation_report.txt Normal file
View File

@@ -0,0 +1,94 @@
================================================================================
MONTE CARLO SIMULATION RESULTS - STATISTICAL SUMMARY
================================================================================
## 故障参数设置
- 火箭发射失败率: 2.0%
- 电梯年故障次数: 2.0 次/部/年
- 电梯平均停机时间: 14 ± 7 天
- 缆索摆动角度标准差: 0.50°
- 天气取消率范围: 8% - 30%
================================================================================
## 方案A: 成本优先(纯电梯)
仅使用太空电梯,能耗最低但耗时最长
================================================================================
### 完成时间统计
目标年限: 186.2 年
均值: 202.3 年
标准差: 0.6 年
90% 置信区间: [201.0, 203.0] 年
最短: 201.0 年, 最长: 204.0 年
相对目标延迟: 8.6%
### 能量消耗统计
均值: 15738 PJ
标准差: 0 PJ
90% 置信区间: [15738, 15738] PJ
### 电梯故障统计
平均总停机时间: 17073 天 (46.8 年)
平均摆动能量惩罚: 17.9 PJ (0.11%)
================================================================================
## 方案B: 时间优先(混合-全速)
电梯+火箭全开,时间最短但能耗较高
================================================================================
### 完成时间统计
目标年限: 105.7 年
均值: 120.7 年
标准差: 0.4 年
90% 置信区间: [120.0, 121.0] 年
最短: 120.0 年, 最长: 122.0 年
相对目标延迟: 14.2%
### 能量消耗统计
均值: 30217 PJ
标准差: 30 PJ
90% 置信区间: [30150, 30245] PJ
### 火箭故障统计
平均失败次数: 6589.7
平均天气取消: 62760.6
### 电梯故障统计
平均总停机时间: 10199 天 (27.9 年)
平均摆动能量惩罚: 10.7 PJ (0.04%)
================================================================================
## 方案C: 综合平衡(膝点方案)
电梯优先+低纬火箭补充,成本-时间平衡
================================================================================
### 完成时间统计
目标年限: 139.0 年
均值: 155.3 年
标准差: 0.5 年
90% 置信区间: [155.0, 156.0] 年
最短: 154.0 年, 最长: 157.0 年
相对目标延迟: 11.7%
### 能量消耗统计
均值: 24060 PJ
标准差: 26 PJ
90% 置信区间: [24026, 24098] PJ
### 火箭故障统计
平均失败次数: 3788.4
平均天气取消: 36078.3
### 电梯故障统计
平均总停机时间: 13114 天 (35.9 年)
平均摆动能量惩罚: 13.8 PJ (0.06%)
================================================================================
## 三方案对比总结
================================================================================
方案 完成年限 总能耗(PJ) 延迟率
----------------------------------------------------------------------
Cost Priority (Elevator Only) 202.3 ± 0.6 15738 ± 0 +8.6%
Time Priority (Combined - Max Speed) 120.7 ± 0.4 30217 ± 30 +14.2%
Balanced (Combined - Knee Point) 155.3 ± 0.5 24060 ± 26 +11.7%

3001
p2/simulation_results.csv Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

File diff suppressed because it is too large Load Diff