p2: rebuild
@@ -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)
|
||||||
|
|||||||
577
p2/README.md
@@ -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/s(100,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、统计表、延迟分布) |
|
||||||
|
|
||||||
|
### 图表预览
|
||||||
|
|
||||||
|
#### 完成时间分布
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 能耗分布
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 箱线图对比
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 故障分析
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 敏感性龙卷风图
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 综合对比
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、结论与建议
|
||||||
|
|
||||||
|
### 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 蒙特卡洛模拟结果
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 9.2 解决方案变化(核心图)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 9.3 完成时间分布
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 9.4 敏感性分析
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 9.5 情景对比
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 十、关键结论 (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
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 91 KiB |
BIN
p2/completion_time_distribution.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
p2/comprehensive_comparison.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 106 KiB |
BIN
p2/energy_distribution.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
p2/failure_analysis.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 268 KiB |
969
p2/monte_carlo_simulation.py
Normal 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)
|
||||||
@@ -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
|
|
||||||
|
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 302 KiB |
@@ -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%
|
|
||||||
|
BIN
p2/sensitivity_tornado.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
94
p2/simulation_report.txt
Normal 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
|
Before Width: | Height: | Size: 174 KiB |