编译速度过慢

set_* 函数运行时间很长,则遇到了编译速度过慢的问题(是的,确实很慢)。这是因为 set_* 会调用 Numba 编译所需函数,以加速后续问题的求解。Pockit 已经尽可能地优化了整个过程,但对于复杂的问题,编译时间仍然会很长(可能需要几分钟)。

若编译时间过长,可以尝试以下方法:

检查问题设定

  • 不要设置 simplify=Trueparallel=True,因为这会使编译时间更长。(默认值为 False,因此若未手动设置,则可忽略此项。)
  • 输入的表达式应尽量适宜整个编译过程。例如 \(x^2\) 应输入为 x * xx ** 2,而不是 pow(x, 2.0),从而使得符号微分过程能更好地处理这一表达式。

优化求解过程

为了避免重复编译,pockit 中 set_* 函数被设计为解耦的。即设定新的动力学方程、约束方程、目标函数、边界条件、离散化参数等时,不需要重新编译其它函数。例如,若需要对相同系统、不同边界条件进行求解,则更改边界条件时只需要调用 set_boundary_condition 函数,而不需要重新调用 set_dynamics 函数,从而避免重复编译。

注意:若在 System.set_phase 之后又调用了 Phase 的 set_* 函数,则在完成后需要调用一次 System.update 函数,以更新问题信息。(System.update 函数不需要编译任何函数,速度很快。)

缓存编译结果

对于反复研究同一问题的用户,可以将编译结果缓存到本地,以避免重复编译。这样可以显著减少编译时间。方法为

  1. 创建一个缓存文件夹,用于存放编译结果。
  2. set_* 函数中设置 cache 参数为缓存目录的路径。以 set_dynamics 为例:
    P.set_dynamics(..., cache='./path/to/cache')
    支持的函数有 Phase.set_dynamicsPhase.set_integralPhase.set_phase_constraintPhase.set_boundary_conditionSystem.set_objectiveSystem.set_system_constraint

这样,编译结果会被保存到缓存文件夹中,下次运行时会直接加载编译结果。

使用预先手动编译的函数

若以上方法仍无法满足需求,可以完全放弃 Pockit 的符号微分、编译功能,而直接使用预先编译的函数。参见略过符号微分