クソコード製造機

数理最適化とかPythonとか

Gurobi Python APIにおけるmodel.update()について

Gurobi Python APIのコードを見ていると、次のようなコードをよく見かける。

import gurobipy as gp

model = gp.Model()

# model.addVarで変数を作る処理を書く

model.update()

# model.addConstrで制約を書く

model.optimize()

このコード自体は問題なく動くが、model.update()を考えたい。実はこのコードはmodel.update()がなくても動作する。(最新バージョンの場合)

# 動く
import gurobipy as gp

model = gp.Model()

# model.addVarで変数を作る処理を書く

# model.addConstrで制約を書く

model.optimize()

つまり、なんらかの事情があって古いバージョン(v.6以前かな?)を使ったり、互換性を保ちたい場合を除いて、model.update()を呼び出すのは不要である。

そのうえ、不必要にmodel.update()を呼び出すことはパフォーマンス低下にも繋がってしまうため、避けるべきである。(遅延評価の良さを生かしきれない。)


それでも、限定的ではあるが、model.update()を呼びだす局面がある。例えば次のような状況である。

モデルのデバッグをするとき

制約のデバッグなどをするときに、作った変数などをprintしても役に立つ情報が得られない場合が多い。例えば次の状況である。

x = model.addVar(vtype="I", name="x")
y = model.addVar(vtype="I", name="y")
z = x + 2 * y
print(z)  # zの中身を確認したい。

遅延評価のため、この出力結果は<gurobi.LinExpr: <gurobi.Var *Awaiting Model Update*> + 2.0 <gurobi.Var *Awaiting Model Update*>>のようになってしまうが、print文の前にmodel.update()を呼びだしておくことで、<gurobi.LinExpr: x + 2.0 y>のような出力が得られるため、デバッグがしやすくなる。

変数のアトリビュートにアクセスしたいとき

これも用途はデバッグと近いが、変数のアトリビュートにアクセスするためには、model.update()を呼び出しておく必要がある。これはログ出力などをしたい場合にも注意が必要な点である。

x = model.addVar(vtype="I", name="x", ub=30)
model.update()  # 無いと以下がエラーになる。
print(x.vtype)
print(x.varname)
print(x.ub)