Python を用いた お気楽最適化とその実践

74
Python をををを ををををををををををを をを をを

description

Python を用いた お気楽最適化とその実践. 久保 幹雄. Why Python?. モジュールを読み込めば何でもできる! 最適化もできる! import gurobipy (MIP) import scop2 (CP) import optseq2 (Scheduling) 空を飛ぶことも!? import antigravity ?. http://www.logopt.com/ mikiokubo/ に 20 分の入門ビデオ. http://xkcd.com/353 /. Python をお薦めする訳. キーワード(覚えるべき予約後)が 30 程度と少ない. - PowerPoint PPT Presentation

Transcript of Python を用いた お気楽最適化とその実践

Page 1: Python を用いた お気楽最適化とその実践

Python を用いたお気楽最適化とその実践

久保 幹雄

Page 2: Python を用いた お気楽最適化とその実践

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

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

import gurobipy (MIP)import scop2 (CP)

• import optseq2 (Scheduling)

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

http://xkcd.com/353/

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

Page 3: Python を用いた お気楽最適化とその実践

Python をお薦めする訳

• キーワード(覚えるべき予約後)が 30 程度と少ない.

• 字下げの強要で,誰でも読みやすいプログラム• 短時間で開発可能(行数が短く,モジュール豊富)• 変数の宣言必要なし• インタープリタ(コンパイルする必要なし;並列

用コンパイラもついている)• メモリ管理も必要なし• 多くのプラットフォームで動作( Windows, Mac, Li

nux)• オブジェクト指向(すべてがオブジェクト)• しかもフリーソフト

Page 4: Python を用いた お気楽最適化とその実践

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 5: Python を用いた お気楽最適化とその実践

How to solve hard optimization problems quickly by Python

MetaheuristicsMetaheuristics Python Source Codes Developed by: Me & J. Pedro Pedroso  

MIP solver GurobiMIP solver Gurobi Developed by: Zonghao Gu, Edward Rothberg ,Robert Bixby

VS. ? +

Free academic license + Python Interface

Page 6: Python を用いた お気楽最適化とその実践

MIP, CP, Scheduling Solvers

• 混合整数計画 (MIP) ソルバー : Gurobi• 制約計画 (CP) ソルバー : SCOP (Solver for COnstrai

nt Programming)• スケジューリング問題に特化したソルバー : OptS

eq II

モデリング ( 定式化)のコツ使い分けのコツ

「新時代の最適化 -Python 言語を用いた最適化入門 - 」近代科学社(執筆中)参照

Page 7: Python を用いた お気楽最適化とその実践

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

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

Page 9: Python を用いた お気楽最適化とその実践

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

# k-median ソルバーの関数

def solve(n,k,cost):

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

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

x={}

キー“Hanako”,

(1,2)

写像値

“127cm”変数オブジェクト

Page 11: Python を用いた お気楽最適化とその実践

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 12: Python を用いた お気楽最適化とその実践

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 13: Python を用いた お気楽最適化とその実践

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 14: Python を用いた お気楽最適化とその実践

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 15: Python を用いた お気楽最適化とその実践

上界と下界の変化

0

2

4

6

8

10

12

14

16

18

0 10 20 30 40 50 60 70

CPU

Obj

. Fun

c. V

alue

Page 16: Python を用いた お気楽最適化とその実践

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 17: Python を用いた お気楽最適化とその実践

知見

• Big M を用いない強い定式化が望ましい.• この程度の式なら,必要な式のみを切除平面として追加するような小細工は必要なし.

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

Page 18: Python を用いた お気楽最適化とその実践

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

Which is the solution of the k-center problem?

Page 20: Python を用いた お気楽最適化とその実践

上界と下界の変化

0

0.2

0.4

0.6

0.8

1

1.2

0 50 100 150 200 250 300 350 400

CPU Time

Obj

. Fun

. Val

ue

100 顧客, 10 施設 ( k-median は 200 施設, 20 顧客で 3秒)

Page 22: Python を用いた お気楽最適化とその実践

k-被覆問題 +Binary Search

顧客・施設間の距離の上限 UB ,下限 LB

while UB – LB >ε: θ= (UB+LB)/2 if K-被覆問題の最適値が 0 then

UB = θ else LB = θ

Page 23: Python を用いた お気楽最適化とその実践

実験結果

Page 24: Python を用いた お気楽最適化とその実践

知見• Min-max 型の目的関数は MIP ソルバーでは解きにくい(双対ギャップが大きい;上界も下界も悪いので,途中で止めても悪い解!).

• 例: Job shop スケジューリングの最大完了時刻(メイクスパン)最小化 => スケジューリング問題に特化したソルバーの方が良い!

• k-被覆問題を用いた二分探索だとある程度 min-max 型の目的関数を回避できる.

• min-max 型の問題は,制約計画としてモデル化して,上限を制約として扱うと良い.

Page 25: Python を用いた お気楽最適化とその実践

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

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

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

Page 26: Python を用いた お気楽最適化とその実践

Miller-Tucker-Zemlin の定式化

Page 27: Python を用いた お気楽最適化とその実践

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

0

5

10

15

20

25

30

35

40

45

0 50 100 150 200 250 300 350 400

CPU

Obj

. Fun

c. V

alue

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

Out of Memory!

Page 28: Python を用いた お気楽最適化とその実践

結果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 29: Python を用いた お気楽最適化とその実践

単一フロー定式化

多少強化

Page 30: Python を用いた お気楽最適化とその実践

対称な問題( DFJ 定式化)

Page 31: Python を用いた お気楽最適化とその実践

部分巡回路除去制約を追加線形緩和問題

Page 32: Python を用いた お気楽最適化とその実践

部分巡回路除去制約を追加整数解

連結成分を求めて切除平面を追加

Page 33: Python を用いた お気楽最適化とその実践

部分巡回路除去制約を追加最適解

Page 34: Python を用いた お気楽最適化とその実践

知見

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

 (そのためには多面体論の知識が多少必要なので,専門家に相談.ちょっと式をいじるだけで劇的に改善する場合もある!)

• 他にも単品種フロー,多品種フロー定式化などがある.(下界が強い方が良いとは限らない! LP のサイズと解きやすさ(退化の具合)を考慮して定式化を選択!)

• 対称な問題なら分枝カット法が良い.

Page 35: Python を用いた お気楽最適化とその実践

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

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

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

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

Page 36: Python を用いた お気楽最適化とその実践

期 t

需要量 (t)

生産量 (t)

在庫量 (t-1)

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

在庫量 (t)

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

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

弱い定式化の原因

0-1 変数

Page 37: Python を用いた お気楽最適化とその実践

期 s

期 t

需要量 (t)

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

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

ts

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

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

Page 38: Python を用いた お気楽最適化とその実践

弱い定式化弱い定式化

標準定式化 施設配置定式化

)( 2nO

強い定式化

= 線形計画緩和が整数多面体と一致

変数の数

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

制約の数

)( 2nO

)(nO変数の数

制約の数)(nO

(S,l)不等式

切除平面

(S,l)不等式

切除平面

追加した制約の数

)2( nO

n: 期数強い定式化

Page 39: Python を用いた お気楽最適化とその実践

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

112000

114000

116000

118000

120000

122000

124000

126000

128000

130000

132000

0 200 400 600 800 1000 1200 1400 1600 1800 2000

CPU

Obj

. Func. Val

ue

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

Page 40: Python を用いた お気楽最適化とその実践

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

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.

Func. Val.

Page 41: Python を用いた お気楽最適化とその実践

知見

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

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

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

Page 42: Python を用いた お気楽最適化とその実践

ビンパッキング問題

5 55 55 56 6

44 44 4422 22

3 3

7 78 8

}9アイテム j=1,…,n のサイズsj

サイズ B のビン

Page 43: Python を用いた お気楽最適化とその実践

切断問題

データが離散値をとるビンパッキング問題と同じ

Page 45: Python を用いた お気楽最適化とその実践

切断問題の定式化初期パターンの線形緩和問題

初期切断パターン(どのアイテムを何回切断するか)

切断パターンを使用する回数

[4, 0, 0, 0, 0, 0, 0]

[0, 3, 0, 0, 0, 0, 0]

[0, 0, 2, 0, 0, 0, 0]

[0, 0, 0, 1, 0, 0, 0]

[0, 0, 0, 0, 1, 0, 0]

[0, 0, 0, 0, 0, 1, 0]

[0, 0, 0, 0, 0, 0, 1] 最適双対変数 (1/4,1/3,1/2,1,1,1,1)

Page 47: Python を用いた お気楽最適化とその実践

Python による記述(主問題) K = len(t)

master = Model("MP")

x = {}

for k in range(K):

x[k] = master.addVar(obj=1, vtype="I", name="x[%d]"%k)

master.update()

orders={}

for i in range(m):

coef = [t[k][i] for k in range(K) if t[k][i] > 0]

var = [x[k] for k in range(K) if t[k][i] > 0]

orders[i] = master.addConstr(LinExpr(coef,var), ">", q[i], name="Order[%d]"%i)

master.update()

t: 初期パターンのリスト

Page 48: Python を用いた お気楽最適化とその実践

Python による記述(列生成) while 1:

iter += 1

relax = master.relax()

relax.optimize()

pi = [c.Pi for c in relax.getConstrs()]

knapsack = Model("KP")

knapsack.ModelSense=-1

y = {}

for i in range(m):

y[i] = knapsack.addVar(obj=pi[i], ub=q[i], vtype="I", name="y[%d]"%i)

knapsack.update()

L = LinExpr(w, [y[i] for i in range(m)])

knapsack.addConstr(L, "<", B, name="width")

knapsack.update()

knapsack.optimize()

if knapsack.ObjVal < 1+EPS:

break

col = Column()

for i in range(m):

if t[K][i] > 0:

col.addTerms(t[K][i], orders[i])

x[K] = master.addVar(obj=1, vtype="I",

name="x[%d]"%K, column=col)

master.update()

K += 1

master.optimize()

Page 49: Python を用いた お気楽最適化とその実践

列生成法の応用事例(タンカースケジューリング

問題)• タンカーのパーティションを考慮した

複雑な実際問題• 海技研からの委託• 可能なパターンの列挙,集合被覆問題

による選択を 2回反復した解法• 従来法( CP ): 9 時間かけて実行不能• 開発法: 10 分程度で求解

Page 50: Python を用いた お気楽最適化とその実践

グラフ彩色問題

• 解の対称性• 点数 n=40 ,彩色数上限 Kmax=10

• ランダムグラフ G(n,p=0.5)

• 彩色数 8 が最適値

Page 51: Python を用いた お気楽最適化とその実践

定式化

弱い定式化

Page 52: Python を用いた お気楽最適化とその実践

Python での実装(1)

from gurobipy import *

model=Model("gcp")

x={}

y={}

for i in range(n):

for k in range(K):

x[i,k]=model.addVar(obj=0, vtype="B",name="x"+str(i)+str(k))

for k in range(K):

y[k]=model.addVar(obj=1,vtype=“B”,name="y"+str(k))

model.update()

Page 53: Python を用いた お気楽最適化とその実践

Python での実装(2)

for i in range(n):

L=LinExpr()

for k in range(K):

L.addTerms(1,x[i,k])

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

中略

model.optimize()

print "Opt.value=",model.ObjVal

for v in model.getVars():

if v.X>0.001:

print v.VarName,v.X

Page 54: Python を用いた お気楽最適化とその実践

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

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

0

2

4

6

8

10

12

0 200 400 600 800 1000 1200 1400

CPU Time

Obj

. Fun

c. V

alue

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

Explored 17149 nodes (3425130 simplex iterations) in 1321.63 seconds

Page 55: Python を用いた お気楽最適化とその実践

定式化の改良

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

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

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

Page 56: Python を用いた お気楽最適化とその実践

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

0

2

4

6

8

10

12

0 50 100 150 200 250 300 350 400 450

CPU

Obj

. Fun

c. V

alue

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 57: Python を用いた お気楽最適化とその実践

上界と下界の変化( +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

. Fun

c. V

al.

Page 59: Python を用いた お気楽最適化とその実践

Fixed-K Approach +Binary Search

彩色数 K の上界 UB ,下界 LB

while UB – LB >1: K= [ (UB+LB)/2 ] [ ] : Gauss の記号 if Fixd-K 定式化の最適値が 0 then

UB = K else LB = K

Page 60: Python を用いた お気楽最適化とその実践

Fixed-K Approach +Binary Search

Improved Formulation

Page 61: Python を用いた お気楽最適化とその実践

知見

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

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

い(ただし,探索手法の変更との相性は悪い.)• K を固定すると解きやすくなり,二分探索は有効

Page 62: Python を用いた お気楽最適化とその実践

多目的最適化

• 非劣解の集合をどのように生成するか? ( Gurobi は分枝限定法で見つかった複数の解を出力)

• 線形和によるスカラー化

• 制約に変換してスライドさせる方法

• 理想点からの距離を最小化する方法

Page 63: Python を用いた お気楽最適化とその実践

この領域の解はA に優越される

非劣解 とスカラー化法

第一目的関数

第二目的関数

Aスカラー化の目的関数の方向

スカラー化が見逃す非劣解

Page 64: Python を用いた お気楽最適化とその実践

二目的巡回セールスマン問題に対する制約スライド法の結果

Page 65: Python を用いた お気楽最適化とその実践

制約スライド法と理想点法の比較

Page 66: Python を用いた お気楽最適化とその実践

Gurobi Objects

Model

Variable

Constraint

LinExpr QuadExpr

Column

Callbacks

GRBError

addVar

addConstr

SOS

addSOS

Page 67: Python を用いた お気楽最適化とその実践

Model Object= Model(“name of model” )

Methods Attributes• AddVar• AddConstr• optimize• update• getVars• relax ...

• Params• ObjVal• ModelSense• Runtime• Status• SolCount ...

Page 68: Python を用いた お気楽最適化とその実践

Prams (Parameters to control the optimizer)

• TimeLimit : limit of the computational time• MIPGap : upper bound of the relative error • MIPFocus : MIP search strategy• SolutionNumber : number of solution • LPMethod : solution method of linear optimization• OutputFlag : 0=Off , 1=On

...

E.g., : ModelObject.Params.TimeLimit=10

Page 69: Python を用いた お気楽最適化とその実践

SCOP Objects

Model

Variable

Linear

addVariable(s)

Quadratic

Alldiff

addConstraint

詳細については http://www.logopt.com/scop/

Page 70: Python を用いた お気楽最適化とその実践

Model Object= Model(“name of model” )

Methods Attributes• AddVariable(s)• AddConstraint• optimize

• Params• variables• constraints

Page 71: Python を用いた お気楽最適化とその実践

Prams (Parameters to control the optimizer)

• TimeLimit : limit of the computational time• Target : target penalty value• RandomSeed: random seed number• OutputFlag : 0=Off , 1=On

Page 72: Python を用いた お気楽最適化とその実践

OptSeq Objects

Model

Attribute

Mode

addActivity

Resource

Temporal

addResource

addTemporal

addMode

詳細については http://www.logopt.com/OptSeq/

Page 73: Python を用いた お気楽最適化とその実践

Model Object= Model(“name of model” )

Methods Attributes• AddActivity• AddResource• AddTemporal• optimize• write

• Params• activities• modes• resources• temporals

Page 74: Python を用いた お気楽最適化とその実践

Prams (Parameters to control the optimizer)

• TimeLimit : limit of the computational time• Makespan: True= makespan minimization,

False=weighted tardiness minimization • RandomSeed: random seed number• OutputFlag : 0=Off , 1=On