设定问题

简介

在对问题建立多段最优控制模型后,只需要将表达式输入 pockit 即可自动生成离散优化问题。 有关多段最优控制问题定义,请参见多段最优控制问题

Pockit 问题输入完全基于 Sympy 构造表达式。在对象被创建时相应 Sympy 符号自动被创建,利用符号构造所需的表达式并输入 pockit。 从而可以利用 Sympy 库的函数便捷操作表达式,并且其在 jupyter notebook 等环境中可以以公式形式显示。

创建对象

Pockit 有 Radau 和 Lobatto 两种插值节点,其拥有完全一样的编程接口。引入方法分别为

from pockit.radau import System, Phase
from pockit.labotto import System, Phase
# 二选一

关于 Radau 节点和 Labotto 节点选择,参见离散与插值

  • 创建系统对象的方法为 System 类构造函数
    S = System(n_s)
    # n_s 为系统变量数量,或
    S = System(['s_0', 's_1', ..., 's_{n_s - 1}'])
    # 列表为系统变量名称
    
  • 使用 System.new_phase 方法创建阶段对象
    P = S.new_phase(n_x, n_u)
    # n_x, n_u 为状态、控制变量数量,或
    P = S.new_phase(['name_x_0', ..., 'name_x_{n_x - 1}'],
                    ['name_u_0', ..., 'name_u_{n_u - 1}'])
    # 列表为状态、控制变量名称
    

设置函数关系

在创建完对象后,相应的 Sympy 符号会自动生成。我们可以通过这些符号构造问题的函数关系,并将表达式输入以构建问题。注:set_* 方法可能会较慢,因为其需要计算符号微分并编译为 Numba 函数。最好将其置于独立的 Jupyter Notebook 单元格中执行。修改其中的任何一项(例如为同一系统更换边界条件)无需重复执行其它单元格,仅需在最后执行 System.update() 更新系统对象数据(见下文)。这样可以大幅提高计算效率。

访问变量

系统变量可通过System.sPhase.s 属性访问,二者结果相同。状态和控制变量的 Sympy 符号列表可以通过 Phase.xPhase.u 属性访问。 此外,每个 Phase 自动生成一个额外的 Sympy 符号 P.t 表示时间变量。

设置阶段(Phase)

我们需要首先配置所有阶段的各项函数关系和离散方法,然后在系统层级集成。 所有输入的数学函数应由相应属性中符号组成 Sympy 表达式构建。

  • 设置动力学微分方程:Phase.set_dynamics
  • P.set_dynamics([expr_0, ..., expr_{n_x - 1}])
    # expr_* 为 P.x, P.u, P.s 和 P.t 中符号构成的表达式
    
  • 设置积分:Phase.set_integral
  • P.set_integral([expr_0, ..., expr_{n_i - 1}])
    # expr_* 为 P.x, P.u, P.s 和 P.t 中符号构成的表达式
    
  • 设置阶段(路径)约束:Phase.set_phase_constraint
  • P.set_phase_constraint(
        [expr_0, ..., expr_{n_c - 1}],
        [lb_0, ..., lb_{n_c - 1}],
        [ub_0, ..., ub_{n_c - 1}],
        [b_0, ..., b_{n_c - 1}],
    )
    # expr_* 为 P.x, P.u, P.s 和 P.t 中符号构成的表达式
    # lb_*, ub_* 为浮点数(可为 +/- inf), lb_i <= ub_i
    # b_* 为 True/False,表示该阶段约束是否为 bang-bang 控制
    
  • 设置边界条件:Phase.set_boundary_condition
  • P.set_boundary_condition(
        [x_0_0, ..., x_0_{n_x - 1}],
        [x_f_0, ..., x_f_{n_x - 1}],
        t_0,
        t_f,
    )
    # x_0_*, x_f_*, t_0, t_f 为 None 或浮点数或 S.s 中符号构成的表达式
    # 分别表示自由、固定为常数和固定为函数
    
  • 设置离散参数:Phase.set_discretization
  • P.set_discretization(
      [mesh_0, ..., mesh_{n_i}],
      [num_points_0, ..., num_points_{n_i - 1}],
    )
    # mesh_* 为网格点位置,为单调递增的浮点数
    #(也可简化为一个整数 n_i,表示 n_i 个均匀子区间)
    # num_points_* 为每个子区间的插值点个数
    #(也可简化为一个整数 n_p,表示每个子区间都用 n_p 个插值点)
    

设置系统函数

在阶段关系都设置完后,在系统层面进行组合,以构建最终的优化问题。

  • 设置阶段:System.set_phase
    S.set_phase(P_0, ..., P_{n_p - 1})
    
    若在设置阶段后又改变了阶段的函数或离散方法(通过 set_* 方法),则需要在系统层面调用 System.update() 更新系统对象数据。
  • 设置目标函数:System.set_objective
    S.set_objective(expr)
    # expr 为 P_0.I, ..., P_{n_p - 1}.I 和 S.s 中符号构成的表达式
    
  • 设置系统(代数)约束:System.set_system_constraint
    S.set_system_constraint(
      [expr_0, ..., expr_{n_l - 1}],
      [lb_0, ..., lb_{n_l - 1}],
      [ub_0, ..., ub_{n_l - 1}])
    )
    # expr_* 为 P_1.I, ..., P_{n_p - 1}.I 和 S.s 中符号构成的表达式
    # lb_*, ub_* 为浮点数(可为 +/- inf), lb_i <= ub_i