2021年8月26日木曜日

組み合わせ最適化1 (ナップザック問題)

 組み合わせ最適化は、基本的に説明変数が整数値をとり最適化を行います。説明変数は0または1をとるときも多いです。典型的な例でナップザック問題をやってみます。

ナップザック問題の定式化

例題として、お菓子を値段制限があるなかで、どれだけ満足度を高められるか考えます。(Pythonで始めるプログラミング入門 コロナ社 P127 プログラム10-2 を改変)

name = ['チョコ', 'ポテトチップス', 'クッキー', 'ラムネ', 'ガム']
weight = [130, 120, 80, 30, 20] #お菓子の価格
value = [18, 15, 12, 4, 2] #お菓子の満足度
capacity = 300 #お菓子の値段合計上限

プログラムは再帰呼び出しを利用して、最大の満足度になるように計算をしています。途中、リストに入っている場合はcontinueをしているので、お菓子の重複が無いようにしています。定式化でも重複が無い式になっています。

ソースコード

ソースコードの一番下に、ソルバーを使った場合のナップザック問題を入れているので、それも実行してみると同様の答えが得られます。

今回のプログラムは少ないお菓子でしたので、総当たりで計算ができますが、商品数が増えるととても計算が終わりません。その場合は、分枝限定法やメタヒューリスティックの方法で解いていきます。

復習として、下記も参考にしてください。

線形計画法1

非線形計画法1(無制約)

非線形計画法2(制約付き)

2021/09/06 ナップサック問題をdeapを使ったものを上記のソースコードに追加。遺伝アルゴリズムのフレームワークで、形式的に利用できるが、カスタマイズをするにはそれなりに内容を理解しないと使いこなせないものです。

2021年8月25日水曜日

非線形計画法2 (制約つき)

 非線形計画法での無制約のやり方は、

https://mizunolab.sist.ac.jp/2021/08/1.html

でした。ここでは、非線形計画法の中で制約つきをscipy.optimize.minimize を使ったやり方でやっていきます。この場合、数学的な知識がそれなりに必要ですが、まずはツールとして使えるようにしていきます。制約つきの中で、(i) 線形制約、(ii)非線形制約 でツールの使い方が少し変わってきます。線形計画法と同様に制約の行列表現が重要です。また非線形制約の場合は、制約条件を関数で返しています。

ソースコード

2021年8月23日月曜日

線形計画法 : LP(scipy.optimize.linprog)を利用

 線形計画法は線形関数を最適化する方法です。LPは様々なソルバーが揃っていますが、非線形計画をやることを考えてscipy.opimize.linprogを使ってみました。scipy.optimizeで非線形計画としても解けますが、微分などwarningが出てきますので、ここではlinprogを使っていきます。

scipy.opimize.linprog の仕様 : https://docs.scipy.org/doc/scipy/reference/optimize.linprog-interior-point.html

ソースコード

ポイントとしては、線形計画問題を Ax <= b の形で行列表現をして、それをソルバーに渡してあげます。等式制約の場合も同じです。x >= 0の場合もマイナスをかけて、不等式制約に当てはまるように変形します。

一つ例題3であげたもので、変数に制約が無い場合、boundsで制約をつけないとうまく計算ができませんでした。

このようなソルバーを使ったとき大規模化が問題になるので、大規模問題では検証が必要です。

2021年8月22日日曜日

非線形計画法1 (無制約)

 非線形関数を最適化することを非線形最適化と言って、利用する場面は多いです。ここでは理論的な説明は省き、ツールを使って最適化を行う方法を紹介します。

利用するソルバー:scipy.optimize

最適化手法:Nelder-Mead Simplex algorithm

pythonコード

pythonコードを確認してもらうと、いくつか例題があります。目的関数値を返す関数を作成して、その関数を呼び出してツールの書式に従って最適化を行います。パターン化されますので理解もしやすいと思います。最適化手法は今回Nelder-Meadという基本的なものを利用しています。他の最適化手法でも試して欲しいです。

20210907 追記

ローゼンブロック関数に対して、遺伝アルゴリズム(GA)のdeapライブラリを使って実施したものを追加しました。2変数での精度は出ましたが、3変数以上は難しいです。

20210908 追記

deapのベンチマークであるackley関数を追加しました。下記は参考です。

https://deap.readthedocs.io/en/master/api/benchmarks.html#deap.benchmarks.ackley

https://qiita.com/tyoshitake/items/e76f6f8e4110731606bc