Python を用いた Gurobi 入門

46
Python をををを Gurobi をを をを をを

description

Python を用いた Gurobi 入門. 久保 幹雄. Why Python?. モジュールを読み込めば何でもできる! 最適化もできる! import gurobipy (MIP) import SCOP (CP) グラフも描ける! import networkX import matplotlib 空を飛ぶことも!? import antigravity ?. http://www.logopt.com/ mikiokubo/ に 20 分の入門ビデオ. http://xkcd.com/353 /. Python 1 ページ解説. 複合型 - PowerPoint PPT Presentation

Transcript of Python を用いた Gurobi 入門

Page 1: Python を用いた Gurobi 入門

Python を用いた Gurobi 入門

久保 幹雄

Page 2: Python を用いた Gurobi 入門

Why Python?• モジュールを読み込めば

何でもできる!• 最適化もできる!

import gurobipy (MIP)import SCOP (CP)

• グラフも描ける!import networkXimport matplotlib

• 空を飛ぶことも!?import antigravity ?

http://xkcd.com/353/

http://www.logopt.com/mikiokubo/ に 20 分の入門ビデオ

Page 3: Python を用いた Gurobi 入門

Python 1 ページ解説複合型

– リスト:任意の要素から成る順序型A=[] これだけで,スタック,キュー,連結リスト,ソート

A.append(5), a=A.pop(), A.remove(“6”), A.sort()

– 辞書: キーと 値の組から構成されるマップ型D= { }Hash 関数と同じ.何でも辞書で高速に保管できる! D[(1,2)] =6, D[“Hello”]=“ こんにちは”

反復 for i in [1,2,5,6]: for key in D: print i*2 print key,D[key]

=> 2,4,10,12 => キーと値を出力

Page 4: Python を用いた Gurobi 入門

k-median 問題• min-sum 型の施設配置問題• 顧客数 n=200 ,施設数 k=20

(顧客上から選択)• Euclid 距離, x,y 座標は一様ランダム

n=200, k=5 の例

Page 6: Python を用いた Gurobi 入門

Python での実装( 1 )from gurobipy import * #gurobipy モジュールの読み込み

# k-median ソルバーの関数

def solve(n,k,cost):

model=Model(“median”) # モデルオブジェクトの生成

y={} # 変数を表す辞書の準備

x={}

キー“Hanako”,

(1,2)写像

値“127cm”

変数オブジェクト

Page 8: Python を用いた Gurobi 入門

Python での実装(3) for i in range(n):

L=LinExpr() # 線形表現オブジェクト L を空で作成

for j in range(n):

L.addTerms(1,x[i,j]) # 線形表現オブジェクトに項を追加

    model.addConstr(lhs=L,sense= " = ",                    rhs=1,name="Demand"+str(i))

線形表現( Linear Express ) クラス LinExpr

Page 9: Python を用いた Gurobi 入門

Python での実装(4) 中略

model.optimize() # 最適化実行

print “Opt.value=”,model.ObjVal # 目的関数値

edge=[] # 選ばれた枝 (i,j) のリスト

for (i,j) in x: # 変数 x の辞書を反復

if x[i,j].X==1: #x[i,j] の解が 1 なら

edge.append((i,j)) # リスト edge に (i,j) を追加

return edge

Page 10: Python を用いた Gurobi 入門

Python での実装(5) import networkx as NX #networkX モジュールの読み込み

import matplotlib.pyplot as P # 描画の準備

P.ion()

G = NX.Graph() # グラフオブジェクト G の生成

G.add_nodes_from(range(n)) # 点の追加

for (i,j) in edge: # グラフに枝を追加

G.add_edge(i,j)

NX.draw(G) # 描画

Page 11: Python を用いた Gurobi 入門

Optimize a model with 401 Rows, 40200 Columns and 80400 NonZeros

中略

Explored 1445 nodes (63581 simplex iterations) in 67.08 seconds

Thread count was 2 (of 2 available processors)

Optimal solution found (tolerance 1.00e-04)

Best objective 1.0180195861e+01, best bound 1.0179189780e+01, gap 0.0099%

Opt.value= 10.1801958607

弱い定式化での結果n=200,k=20

Page 12: Python を用いた Gurobi 入門

上界と下界の変化

0

2

4

6

8

10

12

14

16

18

0 10 20 30 40 50 60 70

CPU

Obj. F

unc.

Value

Page 13: Python を用いた Gurobi 入門

Optimize a model with 40401 Rows, 40200 Columns and 160400 NonZeros

中略

Explored 0 nodes (1697 simplex iterations) in 3.33 seconds( 分枝しないで終了!)

Thread count was 2 (of 2 available processors)

Optimal solution found (tolerance 1.00e-04)

Best objective 1.0180195861e+01, best bound 1.0180195861e+01, gap 0.0%

Opt.value= 10.1801958607

強い定式化での結果

Page 14: Python を用いた Gurobi 入門

知見

• Big M を用いない強い定式化が望ましい.• この程度の式なら,必要な式のみを切

除平面として追加するような小細工は必要なし.

(ただし,式の数が増え退化するので,大規模なLPを高速に解けるソルバーが前提)

Page 15: Python を用いた Gurobi 入門

巡回セールスマン問題(TSP)

• すべての点をちょうど1回通る最短巡回路

• 切除平面法で 85,900 点の実際問題(対称TSP)の最適解

Page 16: Python を用いた Gurobi 入門

Miller-Tucker-Zemlin の定式化

Page 17: Python を用いた Gurobi 入門

上界と下界の変化(80点, Euclid TSP )

0

5

10

15

20

25

30

35

40

45

0 50 100 150 200 250 300 350 400

CPU

Obj. F

unc.

Value

強化した式でないと...1日まわして

Out of Memory!

Page 18: Python を用いた Gurobi 入門

結果Optimize a model with 6480 Rows, 6400 Columns and 37762 NonZeros

中略

Cutting planes:

Gomory: 62

Implied bound: 470

MIR: 299

Zero half: 34

Explored 125799 nodes (2799697 simplex iterations) in 359.01 seconds

Optimal solution found (tolerance 1.00e-04)

Best objective 7.4532855108e+00, best bound 7.4525704995e+00, gap 0.0096%

Opt.value= 7.45328551084

Page 19: Python を用いた Gurobi 入門

知見

• 式を持ち上げ操作などで強化すると,高速化され,大きな問題例が解けるようになる.

 (そのためには多面体論の知識が多少必要なので,専門家に相談する)

Page 20: Python を用いた Gurobi 入門

多品目ロットサイズ決定問題

• 段取り費用と在庫費用のトレードオフを最適化する多期間生産計画

• 多品目で共通の資源を使う容量制約付き問題は, MIP ソルバーには難問(と言われてきた)

• T=30 期, P=24 品目: Trigeiro, Thomas, McClain ( 1989年)の最大のベンチマーク

Page 21: Python を用いた Gurobi 入門

期 t

需要量 (t)

生産量 (t)

在庫量 (t-1)

在庫量( t-1)+ 生産量 (t)= 需要量 (t)+ 在庫量( t)

在庫量 (t)

ロットサイズ決定問題標準定式化のフローモデル

生産量 (t)≦大きな数 “ Large M” × 段取りの有無 (t)

弱い定式化の原因

0-1 変数

Page 22: Python を用いた Gurobi 入門

期 s

期 t

需要量 (t)

s 期に生産して t 期まで在庫される量 = 需要量 (t)

ロットサイズ決定問題施設配置定式化のフローモデル

ts

s 期に生産して t 期まで在庫される量

s 期に生産して t 期まで在庫される量 ≦需要量 (t)× 段取りの有無 (t)

Page 23: Python を用いた Gurobi 入門

弱い定式化

標準定式化 施設配置定式化)( 2nO

強い定式化= 線形計画緩和が整数多面体と一致

変数の数

定式化のサイズと強さの比較

制約の数)( 2nO

)(nO変数の数制約の数

)(nO

(S,l)不等式切除平面

追加した制約の数)2( nO

n: 期数強い定式化

Page 24: Python を用いた Gurobi 入門

上界と下界の変化(標準定式化)

112000

114000

116000

118000

120000

122000

124000

126000

128000

130000

132000

0 200 400 600 800 1000 1200 1400 1600 1800 2000

CPU

Obj. F

unc.

Value

1800秒で最適解;これ以上大きな問題例は無理!

Page 25: Python を用いた Gurobi 入門

上界と下界の変化(施設配置定式化)

40秒で最適解; T=100 でも大丈夫!

113600

113650

113700

113750

113800

113850

113900

113950

114000

114050

0 5 10 15 20 25 30 35 40 45

CPU

Obj. F

unc.

Val.

Page 26: Python を用いた Gurobi 入門

知見

• 従来では難問と言われてきたロットサイズ決定問題でもある程度までは大丈夫

• 緩和固定法( Federgruen, Meissner,Tzur “Progressive Interval Heuristics for Multi-Item

Capacitated Lot-Sizing Problems” 2007 )という MIPベースのメタ解法を作ってみたが,同時間通常の探索を行う「打ち切り分枝限定法」の方が良い!

Page 27: Python を用いた Gurobi 入門

k-center 問題

• min-max 型の施設配置問題• 100 顧客, 10 施設(顧客上から選択)• Euclid 距離, x,y 座標は一様ランダム

Page 29: Python を用いた Gurobi 入門

上界と下界の変化

0

0.2

0.4

0.6

0.8

1

1.2

0 50 100 150 200 250 300 350 400

CPU Time

Obj. F

un. V

alue

Page 30: Python を用いた Gurobi 入門

知見• Min-max 型の目的関数は MIP ソルバーでは解

きにくい(双対ギャップが大きい;上界も下界も悪いので,途中で止めても悪い解!).

• 例: Job shop スケジューリングの最大完了時刻(メイクスパン)最小化

• 制約計画としてモデル化して,上限を制約として扱うとうまくいく場合もある.

Page 31: Python を用いた Gurobi 入門

グラフ彩色問題

• 解の対称性• 点数 n=40 ,彩色数上限 Kmax=10• ランダムグラフ G(n,p=0.5)• 彩色数 8 が最適値

Page 32: Python を用いた Gurobi 入門

定式化

弱い定式化

Page 33: Python を用いた Gurobi 入門

上界と下界の変化(原定式化)

点数 n=40 ,彩色数上限 Kmax=10

0

2

4

6

8

10

12

0 200 400 600 800 1000 1200 1400

CPU Time

Obj. F

unc.

Value

Optimize a model with 3820 Rows, 410 Columns and 11740 NonZeros

Explored 17149 nodes (3425130 simplex iterations) in 1321.63 seconds

Page 34: Python を用いた Gurobi 入門

定式化の改良

対称性の除去(番号の小さい方の色を優先して使う!)

特殊順序集合( SOS: Special Ordered Set ) Type 1 (いずれか1つの変数が正になることの宣言)の追加

model.addSOS(1, 変数リスト )

Page 35: Python を用いた Gurobi 入門

上界と下界の変化(対称性除去)

0

2

4

6

8

10

12

0 50 100 150 200 250 300 350 400 450

CPU

Obj. F

unc.

Value

Optimize a model with 3829 Rows, 410 Columns and 11758 NonZeros

Explored 4399 nodes (1013290 simplex iterations) in 384.53 seconds

MIPFocus=2 (最適性保証優先) で 67秒, MIPFocus=3 (下界優先) で 70秒

Page 36: Python を用いた Gurobi 入門

上界と下界の変化( +SOS )

Optimize a model with 3829 Rows, 410 Columns and 11758 NonZerosExplored 109 nodes (58792 simplex iterations) in 22.02 seconds

MIPFocus=2 (最適性保証優先) で 65秒, MIPFocus=3 (下界優先) で 126秒

0

2

4

6

8

10

12

0 5 10 15 20 25

CPU

Obj. F

unc.

Val.

Page 37: Python を用いた Gurobi 入門

知見

• 解の対称性のある問題は,下界の改善がしにくいので,分枝限定法では解きにくい(モダンなソルバーは群論などを用いた工夫を入れてはいるが,あまり機能しない問題もある)

• 対称性を除く工夫を入れると多少は改善• SOS ( Special Ordered Set )制約の宣言は損

はない(ただし,探索手法の変更との相性は悪い.)

Page 38: Python を用いた Gurobi 入門

Gurobi クラス

• モデルクラス Model モデルオブジェクト =Model(“ モデル名”)

• 変数クラス Var変数オブジェクト = モデルオブジェクト .addVar()

• 制約クラス Constr制約オブジェクト = モデルオブジェクト .addConstr()

• 線形制約クラス LinExpr線形制約オブジェクト =LinExpr()

• 他にも,特殊順序集合クラス SOS,定数クラス GRB,コールバッククラス Callbacks,エラークラス GurobiError,列クラス Column がある.

Page 39: Python を用いた Gurobi 入門

変数追加メソッド addVar の引数

• lb ( 下限 ) :規定値 =0• ub ( 上限 ) :規定値 =GRB.INFINITY (無限大)• obj ( 目的関数の係数 ) :=0• vtype ( 変数の種類 ): GRB.CONTINUOUS (連続変

数; “ C” でも可) , GRB.BINARY ( 2 値変数;“ B” ) , GRB.INTEGER (整数変数;“ I” ) , GRB.SEMICONT ( 0 もしくはある範囲内の連続変数;“ S” でも可) , GRB.SEMIINT ( 0 もしくはある範囲内の整数変数;“N” でも可)

• name (名前 ): =“”• column (列 ): = なし( None 型)

Page 40: Python を用いた Gurobi 入門

制約追加メソッド addConstr の引数

• l hs (左辺):線形制約オブジェクトか定数

• sense (制約の向き): GRB.LESS_EQUAL(≦;“ <” でも可) , GRB.EQUAL (=; “ =”でも可) , GRB.GREATER_EQUAL (≧;“ >” でも可)

• rhs (右辺):線形制約オブジェクトか定数• name (名前)

Page 41: Python を用いた Gurobi 入門

モデルのその他の主要メソッド

• optimize(コールバック関数):最適化実行• update :モデルの変更を Gurobi に知らせる• getVars :変数オブジェクトを入れたリストを得る• relax :緩和問題を生成• computeIIS :既約不整合部分系(実行不能になっ

ている原因の制約と変数; Irreducible Inconsistent Subsystem : IIS )を計算

• addSOS ( 1 or 2, 変数リスト,重み( option )):特殊順序集合( Special Ordered Set : SOS )を追加

Page 42: Python を用いた Gurobi 入門

パラメータの設定

書式: setParam(“パラメータ名” , 値) model.Params.パラメータ名 = 値例:混合整数計画( MIP )の相対誤差

(終了条件);規定値は 10-4

setParam(“MIPGap”,0.0) model.Params.MIPGap=0.0

Page 43: Python を用いた Gurobi 入門

よく使うパラメータ

• TimeLimit :計算時間上限(秒)• MIPGap :相対誤差上限(規定値は 10-4 )• MIPFocus : MIP探索戦略( 0= バランス ,1=暫

定解改良 ,2= 最適性の保証 ,3=限界値改良)• SolutionNumber :探索中に発見された解の番号• LPMethod :線形計画の解法( 0=主単体, 1=双対単体, 2=内点)

• OutputFlag :出力制御( 0=Off , 1=On )

Page 44: Python を用いた Gurobi 入門

属性( attributes )

書式: オブジェクト .setAttr(“属性名” , 値) オブジェクト .属性名 = 値例:変数 var の目的関数を 100 に変更 var.setAttr(“Obj”,100) var.Obj=100

Page 45: Python を用いた Gurobi 入門

よく使う属性( 1 )• モデル

– ObjVal :最適目的関数値(最適化後のみ)– ModelSense :目的関数の方向( 1= 最小化, 2= 最

大化)– Runtime :計算時間(最後の求解時の)– Status :モデルの状態(1から 1 3まで; 2=OPTI

MAL, 3=INFEASIBLE, 4=UNBOUNDED, 9=TIME_LIMIT, 11=INTERRUPTED, 13=SUBOPTIMAL)

– SolCount :探索で見つかった解の数

Page 46: Python を用いた Gurobi 入門

よく使う属性(2)• 変数

– LB , UB :下限,上限– Obj :目的関数の係数– Vtype :変数の種類(“ C”= 連続,“ B”=2 値,“ I”=整数,“ S”=半連続,“ N”=半整数

– VarName :変数名– X :解の値– Xn :パラメータ SolutionNumber で指定された番号の解の値– RC :被約費用

• 制約– Sense :制約の向き(“ <” ,“ >” ,“ =” )– RHS :右辺定数– ConstrName :制約名– Pi :双対変数(連続最適化のみ)– Slack :余裕変数の値