【エンジニア向け】文系出身エンジニアが数理最適化の本を読んでみた2-Gurobi編

前回の続きで、数理最適化とGurobiの使い方の記事を書いていきます。

前回の記事はこちらをご覧ください。

【エンジニア向け】文系出身エンジニアが数理最適化の本を読んでみた1-基礎編

また、今回の記事では以下の本を参考にしています、興味のある方は買ってみてください。

あたらしい数理最適化 Python言語とGurobiで解く [ 久保幹雄 ]

価格:3,520円
(2021/9/22 00:06時点)
感想(0件)

前回は、以下の数式について確認し、線形問題の内容を取り上げました。

そしてこの線形問題をプログラミングするのは、かなり難しいことも説明しました。

しかし、「Gurobi」を利用することで簡単に問題を解くことが可能になります。

まずは「Gurobi」をpythonで利用できるようにするためにモジュールをインポートします。

from gurobipy import *

アスタリスク「*」は全てを意味するため、上記の記載で「Gurobi」に関する機能を全て呼び出し可能になりました。

ちなみに、必要最低限の機能しか使わない場合であれば、アスタリスクではなく個別にモジュール名を指定することも可能です。

次に、Modelクラスを呼び出します。「Gurobi」を使って複雑な計算をする時は、このModelクラスを使うことで様々な計算を「Gurobi」内でしてくれるようになります。(非常に便利!)

model = Model("lo1")

「lo1」は、モデルの名前になりますが、自由な名前づけが可能です。ここでは「lo1」と命名しています。

次に数式で使われる変数(x1, x2, x3)を、python × Gurobiで定義しています。

x1を定義する場合、以下のように書くことができます。

x1 = model.addVar(vType="C", name="x1")

最初に作成した「model」変数に「addVar」メソッドを使うことで変数を追加することができました。

1つ目の引数は変数の「型」となります。

線形問題に関して非負の実数を取ることのできるものは、「実数変数(real variable)」、もしくは「連続変数(continuous variable)」のどちらかでしたね。

vType=”C”は、continuous variableの略となります。

2つ目の低数は変数の「名前」です

今回は、x1という変数だったので、x1を引数に追加しています。

また、1つの引数「vType」は、デフォルトでC(continuous variable)が設定されるため、以下のように記載することができます。

x2 = model.addVar(name="x2")

他にも、変数に引数に以下のような値も設定可能です。

1b: 下限値

ub: 上限値

今回の数式では、x3が30以下 = 上限30となるため

変数を定義する時に、以下の様に定義することで同じことが実現できます。

x3 = model.addVar(ub="30" name="x3")

変数を定義し終わったら、必ずmodelをupdateする必要があります。

model.update()

これは怠惰な更新と呼ばれていて、面倒ではありますが手動で更新する必要があります。

モデルの変数が変更されるたびにGurobiの内部データの構造が変わると時間を要するため、このような仕組みを採用しているようです。

次に、制約をGurobiに追加する方法についてみていきましょう。

制約関数は、Gurobiで、「addConstr」メソッドを使うことで実現できます。

model.addConstr(2*x1 + x2 + x3 <= 60)

同様に2つ目の制約も追加していきましょう。

model.addConstr(x1 + 2*x2 + x3 <= 60)

これで全ての制約をGurobiに追加することができました。

最後に目的関数をGurobiに追加します。

目的関数は、以下のように「setObjective」メソッドを使うことで実現可能です。

model.setObjective(15*x1 + 18*x2 + 30*x3, GRB.MAXIMIZE)

2つ目の引数は、目的関数の方向を決めます。

GRB.MAXIMIZE: 最大化を指定

GRB.MINIMIZE: 最小化を指定

全ての関数が設定できたら最適化を行います。

最適化は、「optimize」メソッドで求めることができます。

model.optimize()

これで数式の答えを算出することができました。非常に簡単で驚きですね。

なお、「optimize」メソッドを実行すると内部で自動で「update」メソッドを呼び出してから最適解を算出する仕様になっているため、わざわざ直前に「update」メソッドを記載する必要はありません。

結果を出力する場合は、以下のように記載します。

print "Opt, Value=",model.ObjVal

これで最適解が出力されます。

また、各変数の値は「getVars」で確認可能です。

for v in model.getVars():
  print v.VarName, v.X

以下のように出力されれば成功です。

Opt, Value= 1230.0

x1 10.0

x2 10.0

x3 30.0

どうでしょう、数理最適化面白いと思いましたか?もう少し詳しい内容は是非本を買って勉強してみてください。

あたらしい数理最適化 Python言語とGurobiで解く [ 久保幹雄 ]

価格:3,520円
(2021/9/22 00:06時点)
感想(0件)

この記事が皆さんのお役に立てれば嬉しいです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です