#26 Pyomoで変数をリスト・ベクトル化してみた

マガジン『トシヤの個人研究日誌』、久々の投稿です…
インプット宣言したはずが…
先日、
しばらく『最適化手法入門』のインプットに専念することになりそうです。
とつぶやきました。
https://note.com/toshiyamiyazaki/n/n73fadcbcc4b5
が、インプットの方が遅々として進まず^^;
また、インプットしている最中に、「ここはこのライブラリを使った方がいいかも」といった、アウトプットに関するアイデアが浮かんだり、ヒントを掴んでいたりしていました。
なので、マガジンを更新していない間も、日々細々とアウトプットしていました。いや、正確に言うと、「検索しては、トライアル&エラー」ですね^^;
ただ、それらの過程を投稿する手間を惜しんでいました。
これまでの個人研究では、noteの投稿画面を開いたままにしておき、何か発見や進捗があれば、即noteに書き込んでいました。
ただ、そうやってnoteを開いた状態で個人研究を進めることをやっていませんでした。そのツケが回ってきた感じですね^^;
というわけで、前置きが長くなりましたが、前回の投稿からの進捗をここで述べていきたいと思います。
まずはPulpを試してみた
前回の投稿では、目的関数を作成していました。
https://note.com/toshiyamiyazaki/n/n425547236033
そこから、Pulpというライブラリを用いて、最適化計算を試みました。
Pulpを使おうと思ったのは、重量単価を一覧にしたPandasの表にPuLPで作成した最適化モデルの変数を使えると考えたからです。
データ分析ライブラリーのpandasは、簡単に表を扱えるという特徴があります。つまり、表形式のデータ構造を扱うのに便利ということです。 実は、pandasの表にPuLPで作成した最適化モデルの変数を使えます。つまり、pandasの表を使って最適化モデルを作れます。このとき、変数はpandasの表の列になります。
実際に、説明変数の定義はうまくいきました。
ところが、最適化計算の部分が、何度やってもうまくいきません。
おそらく、原因は、1/変数という計算を行っていることにあるのではと思っています。

各産業の廃棄物発生量Wxを計算する際に、変数Uで除算するのですが、この部分がPulpではできないようです。
このことに関しては、以下のサイトを参考にしました。
変数や定数を使った足し算や引き算が使えます。掛け算は2 * xのような定数と変数の掛け算だけ使えます。1 / xやx * xやx * yのような式は使えません。
なので、PulPを使うのは断念し、他のライブラリを検討するべく、色々検索しました。
次はCVXPYでやってみようとした
次に試したのが、CVXPYです。
こちらは、凸計画のモデリングツールで、前述の『最適化手法入門』で取り上げられています。
CVXPYでは、最適化問題をほぼ数式の通りに記述すれば、それがソルバーの入力形式に自動的に変換されて最適解が得られる
ところが、自分が調べた限りでは、先述のPulpのように、説明変数をpandasの表の列にして利用するのができないようです(もし間違いであれば、ご指摘くだされば幸いです)。
Pyomoでやってみると…
その次に検討したのが、Pyomoです。
こちらのサイトが親切丁寧に書かれていて、大変参考になりました。
まず、説明変数の定義の部分ですが、上記のサイトの別の記事を参考にさせて頂きました。
イメージとしては、先述のPulpのところで述べた変数表みたいなものを定義し、初期値を設定できればと考えました。
以下が変数表のイメージ図。

# リストで指定した内容をキーワードとして保持
model.ITEMS = list(df_price_per_ton.index)
uu = {df_price_per_ton.index[i]:df_price_per_ton.iat[i, 0] for i in range(len(df_price_per_ton.index))}
def initializeU(model, i):
'''変数の初期化'''
return uu[i]
model.u = pyo.Var(model.ITEMS, domain=pyo.NonNegativeReals, initialize=initializeU)
最適化計算については、また後日に投稿しますね。

