メインコンテンツへスキップ

CasADiのOptiスタックでcallback関数を使って解の推移を取得する

·773 文字·2 分
目次

はじめに
#

最適化フレームワークCasADiのOptiスタックでcallback関数を使って、最適化ソルバの各反復における解の推移を取得する方法をまとめました。言語はPythonです。

検証環境は以下の通りです。

ソフトウェア バージョン
Python 3.9.7
CasADi 3.6.3

callback関数の基本的な使い方
#

2変数の凸連続最適化問題を例に、Optiスタックでcallback関数を使用する例を以下に示します。最適化ソルバには、凸連続最適化問題に適したIPOPTを使用しています。

import casadi as ca

opti = ca.Opti()

# 変数を定義
x1 = opti.variable()
x2 = opti.variable()

# 初期値を指定
opti.set_initial(x1, 100)
opti.set_initial(x2, 10)

# 目的関数を定義
obj = x1**2 + x2**2
opti.minimize(obj)

# 制約条件を定義
opti.subject_to( x1*x2 >= 1 )

# 最適化ソルバを設定
p_opts = {}
s_opts = {'print_level': 4}
opti.solver('ipopt', p_opts, s_opts)

# callback関数を定義
opti.callback(lambda i: print(i, opti.debug.value(x1)))

# 最適化計算を実行
sol = opti.solve()

上記のコードを実行すると、変数x1, x2の内、x1の推移が以下のようにコンソールに出力されます。左側の数字は最適化ソルバの反復回数、右側の数字はx1です。x1が初期値の100から、最適解の1に近づいていることが分かります。

0 100.0
1 4.689542724520109
2 1.0795374935431634
3 0.5517089519112491
4 0.8179977199977577
5 1.0262185402295063
6 1.0018147643511712
7 1.0000773780870829
8 1.00000092044001
9 0.999999996253379
opti.callback(lambda i: print(i, opti.debug.value(x1)))

上記の例では、ラムダ式(無名関数)を使い、最適化ソルバの反復ごとに呼び出すcallback関数を定義しています。このラムダ式の引数iには、反復回数が与えられます。また、変数にはopti.debug.value()メソッドを使ってアクセスします。

全変数の推移を取得
#

全ての変数の推移を取得する方法は色々ありますが、1例を以下に示します。logというリストに各反復のopti.debugを追加していきます。最適化計算の終了後、各変数を取り出します。

log = []

# callback関数を定義
opti.callback(lambda i: log.append(opti.debug))

# 最適化計算を実行
sol = opti.solve()

for deb in log:
    print(deb.value(x1), deb.value(x2))

実行結果

100.0 10.0
4.689542724520109 16.043123296985808
1.0795374935431634 1.9311817025775309
0.5517089519112491 0.6966250709025741
0.8179977199977577 0.8500586577938801
1.0262185402295063 1.0243870906377914
1.0018147643511712 1.0017967248568909
1.0000773780870829 1.000077373885306
1.00000092044001 1.0000009204400082
0.999999996253379 0.999999996253379

参考
#

CasADiの公式リファレンス CasADi - Docs

Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

CasADiで最適化の変数と制約をベクトル化する
·1082 文字·3 分
最適化フレームワークCasADiのOptiスタックで、多変数の最適化を簡潔に記述するため、変数と制約をベクトル化する方法をまとめました。
PythonとCasADiを使ったDirect Multiple Shooting法による最適制御
·2473 文字·5 分
Pythonと最適化ライブラリCasADiを使って、Direct Multiple Shooting法と呼ばれる手法によって最適制御問題を解きました。
最適制御向け最適化ライブラリOpEnのRust build of TCP interface failedエラーについて
·1185 文字·3 分
OpEnで発生するRust build of TCP interface failedエラーの解消方法を示します。
PythonとCasADiを使ったDirect Single Shooting法による最適制御
·2545 文字·6 分
Pythonと最適化ライブラリCasADiを使って、Direct Single Shooting法と呼ばれる手法によって最適制御問題を解きました。対象とした例題は斜方投射(物体を斜め方向に上げる)で、指定の時刻・距離に物体を到達させる最小の初速度を求めます。
最適制御向け最適化ライブラリOpEnに入門する
··1759 文字·4 分
Rust製の最適制御向け最適化ライブラリOpEnに入門するためチュートリアルの非線形計画問題を解いたので、備忘録を兼ねてまとめた。
CasADiとBONMINで混合整数非線形計画問題を解く
·913 文字·2 分
Pythonで自動微分・非線形最適化ライブラリCasADiと最適化ソルバBONMINを使って、混合整数非線形計画問題を解く方法をまとめた。