误差检查与网格调整¶
为什么需要检查配点解?¶
Pockit 使用分段插值多项式表示状态和控制。非线性规划解即使在配点处满足 方程,仍可能存在过大的插值误差或节点之间的约束违反。网格检查用于估计当前 多项式表示是否具有足够分辨率,但不能替代物理验证。
两类误差需要分别处理:
- 真实跳变应与 Radau 网格边界重合。相比在跳变两侧盲目提高多项式次数, 移动或增加边界通常更有效。
- 连续但分辨率不足的函数需要更多区间、更高的逐区间点数,或同时调整两者。
检查间断控制¶
Lobatto 插值在公共网格节点处连续,因此 Pockit 的间断处理流程只适用于
Radau 阶段。求解前,应在 Phase.set_phase_constraint() 中把相应有界
表达式标记为 bang-bang。对于没有静态参数的单阶段成功解,检查方式为:
discontinuous_ok = system.check_discontinuous(
solution,
tolerance_discontinuous=1.0e-3,
tolerance_mesh=1.0e-4,
)
检查器会在每个区间内把标记表达式缩放到 ([0,1])。若表达式在整个区间内
始终位于某一边界的 tolerance_discontinuous 范围内,则该区间通过检查;
长度小于 tolerance_mesh 的区间会被跳过。
检查失败时,先更新网格,再把插值后的结果作为下一轮初值:
from pockit.optimizer import ipopt
solution = system.refine_discontinuous(
solution,
tolerance_discontinuous=1.0e-3,
num_point_min=6,
num_point_max=12,
mesh_length_min=1.0e-3,
mesh_length_max=1.0,
)
solution, info = ipopt.solve(system, solution)
对于包含多个阶段和静态参数的系统,应依次传入各阶段结果,最后传入静态参数值; 返回列表保持相同布局:
这个简短布局示例中的名称表示多阶段求解器已经返回的结果。
奇异弧限制
该检查假设每个标记表达式都会接近上界或下界。真正的奇异控制可以严格位于
两个边界之间,因此 check_discontinuous() 和 refine_discontinuous()
不能识别、求解或验证奇异弧。详见奇异弧:识别方法与当前限制。
检查连续近似¶
对于连续区域,Pockit 采用 Patterson、Hager 与 Rao 提出的 ph 网格调整方法:
Patterson, M. A., W. W. Hager, and A. V. Rao (2015). "A mesh refinement method for optimal control." Optimal Control Applications and Methods, 36(4), 398-421.
使用明确的绝对、相对容差检查单阶段结果:
continuous_ok = system.check_continuous(
solution,
absolute_tolerance_continuous=1.0e-8,
relative_tolerance_continuous=1.0e-8,
tolerance_mesh=1.0e-4,
)
若分辨率仍然不足,则调整网格并重新求解:
solution = system.refine_continuous(
solution,
absolute_tolerance_continuous=1.0e-8,
relative_tolerance_continuous=1.0e-8,
num_point_min=6,
num_point_max=12,
mesh_length_min=1.0e-3,
mesh_length_max=1.0,
)
solution, info = ipopt.solve(system, solution)
num_point_min 和 num_point_max 限制每个区间的点数;
mesh_length_min 和 mesh_length_max 限制归一化区间长度。该方法不会
减少已有网格点数量。
同时处理两类误差¶
System.check() 和 System.refine() 将两个流程组合起来。每次调用最多
执行一种调整:尚未解析的间断具有更高优先级;否则由连续误差估计决定更新方式。
if not system.check(
solution,
absolute_tolerance_continuous=1.0e-8,
relative_tolerance_continuous=1.0e-8,
tolerance_discontinuous=1.0e-3,
):
solution = system.refine(
solution,
absolute_tolerance_continuous=1.0e-8,
relative_tolerance_continuous=1.0e-8,
tolerance_discontinuous=1.0e-3,
num_point_min=6,
num_point_max=12,
mesh_length_min=1.0e-3,
mesh_length_max=1.0,
)
solution, info = ipopt.solve(system, solution)
每一轮都应先确认求解器状态,并设置明确的最大调整次数。 超敏感问题展示了用于狭窄端点边界层的完整自适应循环。
调整后仍需验证¶
通过网格检查只说明插值误差受到控制,并不能证明全局最优性或物理可行性。应在 密集物理时间网格上重构状态、控制和路径约束,分别检查跳变左右极限,并至少比较 两套离散下的目标函数和工程诊断量。条件允许时,还应独立积分原始动力学。