--- ASMR++ 奖励计算完整分析 默认配置使用 reward_type: spatial_max + error_metric: maximum。整个奖励信号链分以下步骤: Step 1: 误差估计 — 精细网格参考解 参考网格 (初始网格细化6次) ↓ FEM求解 参考解 u_ref (视为"真值") ↓ 粗网格解 u_coarse 在每个积分点(参考网格元素中点)与 u_ref 比较 ↓ 绝对误差 |u_ref - u_coarse| per 积分点 ↓ scatter_max per 粗元素 error_per_element: 每个粗网格元素内的最大误差 (num_elements, solution_dim) 用精细网格做数值积分 (error_integrator.py:86-169),支持三种积分方式:mean(积分平均值)、squared(积分平方误差)、maximum(元素内最大误差)。默认Poisson 是标量 PDE,solution_dim=1。 Step 2: spatial_max 奖励计算 核心代码在 mesh_refinement.py:657-714,以下是逐步推导: 奖励基准 (reward_per_agent_and_dim) = previous_error_per_element ← 细分前该元素的误差 ┌─────┬─────┐ │ │ │ ├─────┼─────┤ │ │ │ └─────┴─────┘ 父元素 i (error=0.8) 子元素: j1(0.3), j2(0.5), j3(0.6), j4(0.1) ↓ scatter_max per agent_mapping max_mapped_error[i] = max(0.3, 0.5, 0.6, 0.1) = 0.6 ↓ reward_raw[i] = 0.8 - 0.6 = +0.2 ✅ 误差最大的子元素也比父元素好 关键:spatial_max 只奖励"所有子元素误差都下降"的情况。如果有任一子元素误差仍等于原父元素误差,reward=0。 父元素 j (error=0.5) 子元素: k1(0.5), k2(0.1), k3(0.2), k4(0.05) ↓ max_mapped_error[j] = max(0.5, 0.1, 0.2, 0.05) = 0.5 ↓ reward_raw[j] = 0.5 - 0.5 = 0 ❌ 有一个子元素仍未改善 对比 spatial (非 max) 模式: reward_raw[i] = previous_error[i] - Σ_j φ_ij * error[j] = 标量加法 (np.add.at) 把所有子元素误差从父元素误差中减去 这种模式下即使部分子元素没有改善,整体仍有正奖励。 Step 3: 归一化 + 降维到标量 # 除以初始网格的误差 → 把误差改善量归一化到 [0, ~1] 区间 reward_per_agent_and_dim = reward_per_agent_and_dim / initial_approximation_error # 多维 PDE 降维: dot product with solution_dimension_weights # Poisson 是标量PDE, weights=[1.0], 即恒等变换 reward_per_agent = project_to_scalar(reward_per_agent_and_dim) # = np.dot(reward_per_agent_and_dim, [1.0]) = reward_per_agent_and_dim Step 4: 元素惩罚 (Element Penalty) # 统计每个父元素产生了多少子元素 element_counts = unique(agent_mapping, return_counts=True)[1] # 每个父元素→子元素的数量 element_counts = element_counts - 1 # 减1因为是"新增的"子元素数 # 默认 λ ~ 0.01 (loguniform 采样于 [1e-3, 1e-1]) element_penalty = λ * element_counts ┌──────────────────────────┬────────────────┬──────────────────┐ │ 场景 │ element_counts │ penalty (λ=0.01) │ ├──────────────────────────┼────────────────┼──────────────────┤ │ 未细分元素 │ 0 │ 0 │ ├──────────────────────────┼────────────────┼──────────────────┤ │ 分裂为 4 个子三角 │ 3 │ 0.03 │ ├──────────────────────────┼────────────────┼──────────────────┤ │ 被波及细分 (Rivara 平滑) │ 1-3 │ 0.01-0.03 │ └──────────────────────────┴────────────────┴──────────────────┘ 作用: 惩罚是正则化项,防止策略无节制细分所有元素。只在"误差改善 > 细分代价"时细分才有利。 Step 5: 元素上限惩罚 (Element Limit Penalty) if num_elements > maximum_elements (20000): element_limit_penalty = 1000 / previous_num_elements # ≈ 0.05~0.5 per agent else: element_limit_penalty = 0 Step 6: 最终每 Agent 奖励 r_i = error_improvement_i / initial_error - λ * new_elements_created_by_i - limit_penalty 形状为 (num_agents_t,) — 每个 agent(父元素)一个标量奖励。 Step 7: 奖励到 TD 误差 — 与论文公式 (3) 的对应 Buffer 存储: r_i(s_t, a_t) ← 父元素 i 的奖励 (num_agents_t,) V_i(s_t) ← 父元素 i 的价值 (num_agents_t,) φ_ij = agent_mapping ← 子元素j → 父元素i 的映射 V_j(s_{t+1}) ← 子元素的价值 (num_agents_{t+1},) GAE Delta 计算: projected_V = scatter_sum(V_j(s_{t+1}), index=φ_ij) ← Σ_j φ_ij·V_j(s_{t+1}) δ_i = r_i + γ * projected_V_i - V_i(s_t) 对应论文 (3): δ_i^t = r(s^t, a^t)_i + γ·Σ_j φ_ij^t·V_j(s^{t+1}) - V_i(s^t) Step 8: 混合奖励 (Mixed Return, global_weight=0.5) 在 MixedOnPolicyBuffer 中额外计算: # 全局奖励 (均值) r_global = mean(r_i) # 所有agent的平均奖励 # 全局价值 (均值) V_global = mean(V_i) # 所有agent的平均价值 # 全局 GAE δ_global = r_global + γ·V_global' - V_global # 局部 GAE δ_local_i = 上述 per-agent GAE # 混合 Advantage A_i = (1 - 0.5) * A_local_i + 0.5 * A_global 完整奖励流总结 FEM求解 → 逐元素误差估计 (±积分 vs 参考网格) ↓ spatial_max: error_before - max_error_of_children ↓ 归一化 (/ initial_error) ↓ - λ * new_elements + limit_penalty ↓ r_i (per agent) ────────────→ 局部 GAE → A_local_i │ ↓ └→ r_global = mean(r_i) → 全局 GAE → A_global ↓ A_i = 0.5·A_local_i + 0.5·A_global ↓ 送入 PPO policy_loss 设计精巧之处: 1. 空间奖励 + agent_mapping:每个元素独立计算误差改善,通过 agent_mapping φ_ij 追踪父→子关系 2. spatial_max 语义:reward 表示"最差子元素的误差下降量"——驱动策略优先细分误差最大的区域 3. 元素惩罚:防止盲目细分,精确到每个 agent 独立计算代价 4. 混合奖励:局部信号指导细粒度决策 + 全局信号稳定整体训练