跳到主要内容
版本:v0.7.0 beta

支持的问题形式

OPTIMake求解以下的优化问题:

min⁡v1,⋯ ,vN∑i=1Nl(vi,p)+le(vN,p)subject tofs(v1,p)=0,f(vi,vi+1,p)=0,i=1,⋯ ,N−1,fe(vN,p)=0,g(vi,p)≥0,i=1,⋯ ,N\begin{split} &\quad \quad \quad \min_{v_1,\cdots,v_N} \sum_{i=1}^{N} l(v_i, p) + l_e(v_N, p) \\ &\begin{split} \text{subject to} &\quad f_s(v_1, p) = 0,\\ &\quad f(v_{i}, v_{i+1}, p) = 0,\quad i=1,\cdots,N - 1,\\ &\quad f_e(v_N, p) = 0,\\ &\quad g(v_i, p) \geq 0,\quad i=1,\cdots,N \end{split} \end{split}

该优化问题为一个具有 NN 个stage的优化问题, 该优化问题可能为一个非线性非凸的优化问题. 其中:

  • v1,⋯ ,vN∈Rnvv_1,\cdots,v_N \in \mathbb{R}^{n_{v}} 为优化变量
  • p∈Rnpp\in \mathbb{R}^{n_{p}} 为参数
  • l:Rnv×Rnp→Rl: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R} 为stage objective
  • le:Rnv×Rnp→Rl_e: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R} 为终点处额外的objective
  • fs:Rnv×Rnp→Rnfsf_s: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R}^{n_{f_s}} 为起点等式约束
  • f:Rnv×Rnv×Rnp→Rnff: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R}^{n_{f}} 为转移等式约束
  • fe:Rnv×Rnp→Rnfef_e: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R}^{n_{f_e}} 为终点等式约束
  • g:Rnv×Rnp→Rngg: \mathbb{R}^{n_{v}} \times \mathbb{R}^{n_{p}} \rightarrow \mathbb{R}^{n_{g}} 为不等式约束

问题定义​

下面为定义问题的例子, 该例子指定了问题的名称为vehicle、最大10个stage, 并使用CasADi符号引擎:

from optimake import multi_stage_problem

prob = multi_stage_problem(name='vehicle', N=10, symbolic_engine='casadi')

其中, 函数入参的定义如下:

  • name: str 问题的名称, 该名称会用在生成代码的文件名, 函数名等

  • N: int 问题的最大stage数目, 必须大于等于1

  • symbolic_engine: str 符号建模、求导与模型函数代码生成所用的引擎, 可选值为'sympy'、'casadi', 默认值为'sympy'. Jacobian和Hessian等导数由所选引擎自动生成.

信息
  • 因为上述的优化问题为一个多stage的优化问题, 等式约束与不等式约束的表达式在所有stage上都一致, 所以不需要在每个stage上都单独定义, 只需要定义一次该表达式即可 (参数与优化变量同理)
  • N为最大stage数, OPTIMake支持动态stage数, 即在求解时可以指定有效的stage数小于N, 但不能大于N

符号引擎的选择与使用​

两种引擎都可以定义目标函数、动力学和约束, 主要区别如下:

项目SymPy ('sympy')CasADi ('casadi')
使用场景简单符号表达式,例如:车辆运动学模型复杂符号表达式,例如机器人运动学/动力学模型
表达式与求导SymPy表达式, 符号求导CasADi SX计算图, 自动微分
Matrix返回类型sympy.Matrixcasadi.SX
两个矩阵的A * B矩阵乘法逐元素乘法; 矩阵乘法使用A @ B或casadi.mtimes(A, B)

为使建模代码适用于两种引擎, 可以使用OPTIMake提供的Matrix、sin、cos等接口, 并统一使用matmul(A, B)进行矩阵乘法. 这些接口会使用创建问题时选择的引擎. 例如, 在上面的prob中继续定义:

from optimake import Matrix, sin, matmul

theta = prob.variable('theta')
A = Matrix([[1, sin(theta)], [0, 1]])
b = Matrix([theta, 1])
y = matmul(A, b)
信息
  • 对于简单的符号表达式, SymPy生成代码通常更为高效
  • 对于复杂的符号表达式, SymPy生成的时间可能很长, 甚至可能不能生成代码, 此时推荐使用CasADi
  • CasADi支持的函数,例如Pinocchio的CasADi接口,可以直接在符号表达式中使用
  • 同一模型中不混用SymPy与CasADi符号表达式

在完成问题名称和stage数的定义后, 下面说明如何定义优化问题中的参数, 优化变量及约束.