设定问题
简介
在对问题建立多段最优控制模型后,只需要将表达式输入 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.s
和 Phase.s
属性访问,二者结果相同。状态和控制变量的 Sympy 符号列表可以通过 Phase.x
和 Phase.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