代码
所有实验代码可在 Google Colab 免费 GPU / CPU 上运行。STL 仿真不依赖 GPU,本地 CPU 即可完成。
Notebook 列表
| Notebook | 说明 | 预计运行时间 |
|---|---|---|
paper03_stl_sim | STL-101/102 主仿真(4 场景 + 噪声扫描) | ~20 min(CPU) |
paper03_ortho_ablation | 五步消融消融实验 | ~10 min |
paper03_route_eval | 16 条测试查询路由准确率评估 | ~15 min |
STL-101 仿真核心代码
力矩轨迹仿真
import numpy as np
import matplotlib.pyplot as plt
def simulate_torque(scenario, t_act=25, T=60, sigma=0.5, seed=42):
"""
仿真螺栓拧紧/松开力矩轨迹。
场景定义:
S1: 正确执行 R09(拧紧,目标力矩 50 N·m)
S2: 错误执行 R07(拧松,力矩为负方向)
S3: 错误执行 R09 超力矩(> 60 N·m)
S4: 位置偏移(角位移越界)
"""
rng = np.random.default_rng(seed)
t = np.linspace(0, T, T * 10) # 10 Hz 采样
tau = np.zeros_like(t)
if scenario == 'S1': # 正常拧紧
mask = t >= t_act
tau[mask] = 50.0 + rng.normal(0, sigma, mask.sum())
elif scenario == 'S2': # 拧松(力矩反向)
mask = t >= t_act
tau[mask] = -20.0 + rng.normal(0, sigma, mask.sum())
elif scenario == 'S3': # 超力矩
mask = t >= t_act
tau[mask] = 75.0 + rng.normal(0, sigma, mask.sum())
return t, tau
def stl_101_robustness(tau, t, t_act, window=(40, 60)):
"""
计算 STL-101 鲁棒度 ρ(φ_101)。
ρ = min_{t ∈ [t_act, T]} min(τ(t) - 40, 60 - τ(t))
ρ < 0 → FAILSAFE 触发
"""
mask = t >= t_act
tau_window = tau[mask]
rho = np.min(np.minimum(tau_window - window[0], window[1] - tau_window))
return rho
# 运行四场景评估
results = {}
for scenario in ['S1', 'S2', 'S3']:
t, tau = simulate_torque(scenario, sigma=0.5)
rho = stl_101_robustness(tau, t, t_act=25)
failsafe = rho < 0
results[scenario] = {'rho': rho, 'failsafe': failsafe}
print(f"{scenario}: ρ = {rho:.2f} N·m, FAILSAFE = {failsafe}")
# 输出:
# S1: ρ = 4.44 N·m, FAILSAFE = False ← 正常执行
# S2: ρ = -40.24 N·m, FAILSAFE = True ← 立即拦截
# S3: ρ = -19.68 N·m, FAILSAFE = True ← 立即拦截
噪声鲁棒性扫描(Exp-A)
def noise_sweep_experiment(sigmas, n_trials=20, scenarios=('S1', 'S2', 'S3')):
"""
Exp-A:噪声扫描实验(5×20 = 100 次仿真)。
返回每个噪声级别的 FPR (S1) 和拦截率 (S2/S3)。
"""
records = []
for sigma in sigmas:
fpr_s1 = 0
intercept_s2 = 0
intercept_s3 = 0
for seed in range(n_trials):
for sc in scenarios:
t, tau = simulate_torque(sc, sigma=sigma, seed=seed)
rho = stl_101_robustness(tau, t, t_act=25)
triggered = rho < 0
if sc == 'S1' and triggered:
fpr_s1 += 1 # 误触发
elif sc == 'S2' and triggered:
intercept_s2 += 1
elif sc == 'S3' and triggered:
intercept_s3 += 1
records.append({
'sigma': sigma,
'FPR': fpr_s1 / n_trials,
'Intercept_S2': intercept_s2 / n_trials,
'Intercept_S3': intercept_s3 / n_trials,
})
return records
sigmas = [0.25, 0.5, 1.0, 2.0, 4.0]
results = noise_sweep_experiment(sigmas, n_trials=20)
# FPR=0% for σ ≤ 2.0 N·m (4× specification noise)
跨域正交化消融代码
from FlagEmbedding import FlagModel
import numpy as np
model = FlagModel("BAAI/bge-large-zh-v1.5", use_fp16=True)
# V_damp 五步消融词汇定义
v_damp_versions = {
'step1': {
'R07': "拧松螺栓固定夹具",
'R09': "拧紧螺栓固定夹具",
},
'step2': {
'R07': "逆时针拧松螺栓固定夹具",
'R09': "顺时针拧紧螺栓固定夹具",
},
'step3': {
'R07': "逆时针拧松螺栓固定夹具(低力矩区间)",
'R09': "顺时针拧紧螺栓固定夹具至规定力矩 [40-60 N·m]",
},
'step4': {
'R07': "逆时针拧松螺栓固定夹具(低力矩区间,松脱状态 disengage)",
'R09': "顺时针拧紧螺栓固定夹具至规定力矩 [40-60 N·m](紧固状态 secure)",
},
'step5_v2': {
'R07': "[P2-Remove] 逆时针拧松螺栓固定夹具(拆除阶段,低力矩区间)",
'R09': "[P3-Install] 顺时针拧紧螺栓固定夹具(安装阶段,规定力矩 [40-60 N·m])",
},
}
def cosine_distance(a, b):
return 1 - np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
for step, vocab in v_damp_versions.items():
embs = model.encode([vocab['R07'], vocab['R09']])
d = cosine_distance(embs[0], embs[1])
print(f"{step}: d(R07, R09) = {d:.4f}")
# step1: d(R07, R09) = 0.1225
# step2: d(R07, R09) = 0.1520 (+0.0295)
# step3: d(R07, R09) = 0.1734 (+0.0214)
# step4: d(R07, R09) = 0.1987 (+0.0253)
# step5_v2: d(R07, R09) = 0.1889 (全局 d_min 最优)
环境配置
# 主要依赖(STL 仿真无需 GPU)
pip install numpy scipy matplotlib
pip install FlagEmbedding==1.2.11
# 可选(推理延迟测试)
pip install transformers accelerate bitsandbytes