※記事内に商品プロモーションを含むことがあります。
はじめに
最適化フレームワークCasADiのOptiスタックで、多変数の最適化を簡潔に記述するため、変数と制約をベクトル化する方法をまとめました。言語はPythonです。
検証環境は以下の通りです。
ソフトウェア | バージョン |
---|---|
Python | 3.9.7 |
CasADi | 3.6.3 |
対象とする最適化問題
以下の2変数最適化問題を考えます。
$$ \begin{array}{ll} \text{maximize} \ & x_1 + 2x_2 \\ \text{subject to} \ & 3x_1 + x_2 \le 9 \\ & x_1 + 3x_2 \le 6 \\ & x_1 \ge 0, \ x_2 \ge 0 \end{array}$$
ここで、
$$A=\left[ \begin{array}{cc} 3 & 1 \\ 1 & 3 \end{array} \right], \ b=\left[ \begin{array}{c} 9 \\ 6 \end{array} \right], \ c=\left[ \begin{array}{c} 1 \\ 2 \end{array} \right]$$
とおいて、最適化問題を次式の一般的な線形計画問題の形式とします。
$$ \begin{array}{ll} \text{maximize} \ & c^{\top}x \\ \text{subject to} \ & Ax \le b \\ & x \ge 0 \end{array} $$
この形式に従ってコーディングします。
CasADiのソースコード
上記の最適化問題をPython+CasADiで記述します。最適化ソルバはIPOPTとしました。
|
|
実行すると、(IPOPTのログの後に)最適化結果が以下の通り表示されます。
評価関数: 4.875000043735819
x: [2.62500002 1.12500001]
ソースコードの解説
以下、ソースコードを簡単に解説します。
変数・パラメータの定義
|
|
最適化の変数はopti.variable()
, 固定値となるパラメータはopti.parameter()
でそれぞれ定義します。(2)
は2次元のベクトル、(2, 2)
は2×2行列となります。
また、パラメータにはopti.set_value()
で値を設定します。ベクトルの場合はリストで設定できますが、行列の場合はDM
クラスで設定します。
制約式の定義
|
|
制約式はopti.subject_to()
で定義します。
行列とベクトルの積、または行列同士の積は@
記号で定義します。*
記号を使った場合、要素同士の積になります。
また、opti.subject_to()
内の式がベクトルになる場合、各要素に対して制約式が定義されます。
評価関数の定義
|
|
最小化する評価関数をopti.minimize()
で定義します。最大化 (maximize()
) は実装されていないため、評価関数に-
を掛けて最小化します。
なお、c.T@x
では内積を計算しています。この式はca.sum1(c*x)
(要素同士の積をとり、和を取る)と等価です。
参考
CasADiの公式リファレンス
CasADi - Docs