はじめに #
最適化ライブラリCasADiには、行列を扱える3つのクラス (SX, MX, DM) があります。これらのクラスの違いをまとめました。
この記事では、CasADiのPythonインターフェイスを使用しています。PythonとCasADiのバージョンは以下の通りです。
- Python 3.9.7
- CasADi 3.5.5
各クラスの基礎 #
CasADiの公式リファレンスでは、SX, MX, DMクラスの説明は以下となっています。
- SX: 単項演算や二項演算で表現されるシンボルを要素に持つ行列 (scalar expression)
- MX: SXに似ているが、行列をシンボルで表現する (matrix expression)
- DM: 非ゼロ要素を数値として持ち、シンボルによる表現は持たない行列
シンボルとは、数学の記号(xやyなど)のような概念です。DMクラスはシンボルを定義できないので、NumPyのarray
クラスに似ています。
各クラスのオブジェクトを定義する例を以下に示します。
import casadi as ca
s0 = ca.SX.sym("a",2,3) # シンボルaとして定義
s1 = ca.SX(2,3)
s2 = ca.SX([[1,2],[3,4]])
m0 = ca.MX.sym("c",2,3) # シンボルcとして定義
m1 = ca.MX(2,3)
# m2 = ca.MX([[1,2],[3,4]]) # NG
# d0 = ca.DM("b",2,3) # NG
d1 = ca.DM(2,3)
d2 = ca.DM([[1,2],[3,4]])
ca.SX(2,3)
などは2x3サイズの行列を表します。また、ca.SX([[1,2],[3,4]])
などは具体的な数値を持つ行列の定義を表します。
NG例の通り、シンボルを持つDMオブジェクトd0
と、数値を持つMXオブジェクトm2
は作成できません。
また、SXとMXのシンボルの違いを以下に示します。SXオブジェクトでは、a_0
, a_1
などのように各要素がシンボルを持ちます。一方、MXオブジェクトでは行列がc
というシンボルを持ちます。
>>> s0
SX(
[[a_0, a_2, a_4],
[a_1, a_3, a_5]])
>>> m0
MX(c)
異なるクラス同士の演算 #
異なるクラス同士の演算を解説します。SXオブジェクトとMXオブジェクトを組み合わせた計算は出来ませんが、以下の組み合わせは計算可能です。
- SXとDM→SXオブジェクトになる
- MXとDM→MXオブジェクトになる
例を以下に示します。
>>> # s0 + m0 # NG
>>> s0 + d1 # SX
SX(
[[a_0, a_2, a_4],
[a_1, a_3, a_5]])
>>> m1 + d1 # MX
MX(zeros(2x3,0nz))
当然、同じ種類のオブジェクト同士は計算可能です。
CasADi固有のクラス #
CasADiに実装されている固有のクラスと、SX, MX, DMクラスとの関係を見ていきます。
Lookup table #
CasADiには、テーブルを補間するinterpolant
クラスが実装されています。interpolant
オブジェクトの引数にはスカラー、MX, DMクラスを取ることができますが、SXクラスは不可です。
>>> xgrid = [1,2,3]
>>> val = [1,4,9]
>>> lut = ca.interpolant('LUT','linear',[xgrid],val)
>>> lut(1.5) # DM
DM(2.5)
>>> # lut(s0) # NG
>>> lut(m0)
MX(((((((zeros(2x3)[0] = LUT(c[0]){0})[1] = LUT(c[1]){0})[2] = LUT(c[2]){0})[3] = LUT(c[3]){0})[4] = LUT(c[4]){0})[5] = LUT(c[5]){0}))
>>> lut(d1)
DM(
[[-2, -2, -2],
[-2, -2, -2]])
引数をスカラーにした場合、戻り値はDMクラスとなります。
Opti stack #
CasADiには、数理最適化計算を実行するためのOpti stackというフレームワークが実装されています。Opti
オブジェクトのvariable()
メソッドで変数を定義します。この変数はMX
オブジェクトとなります。
>>> opti = ca.Opti()
>>> x = opti.variable() # MX
MX(opti0_x_1)
MXオブジェクトとSXオブジェクトは合わせて計算することができないため、Opti stackを使用する場合、変数やパラメータはMXやDMクラスで宣言すると良いでしょう。
参考 #
CasADiの公式リファレンス