スケジューリングモデルとは

82
ススススススススススススススス OptSeq II Python ススススススススス ススススOptSeq II ススススススススススススス スススススススススス http://www. logopt .com/OptSeq/OptSeq. htm

Upload: kessie-shaffer

Post on 03-Jan-2016

14 views

Category:

Documents


0 download

DESCRIPTION

スケジューリング最適化システム OptSeq II Python モジュールの使い方 補助資料: OptSeq II によるスケジューリング入門 トライアルバージョン http://www.logopt.com/OptSeq/OptSeq.htm. スケジューリングモデルとは. 作業( activity ;活動) :遂行すべき仕事のこと.別名,オペレーション( operation ),ジョブ,仕事 (job) ,タスク (task) .作業時間や納期の情報が付加される. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: スケジューリングモデルとは

スケジューリング最適化システムOptSeq II

Python モジュールの使い方

補助資料: OptSeq II によるスケジューリング入門 トライアルバージョン

http://www.logopt.com/OptSeq/OptSeq.htm

Page 2: スケジューリングモデルとは

スケジューリングモデルとは

• 作業( activity ;活動):遂行すべき仕事のこと.別名,オペレーション( operation ),ジョブ,仕事(job) ,タスク (task) .作業時間や納期の情報が付加される.

• 先行(時間)制約( precedence (time) constraint ):ある作業(ジョブ,活動)がある作業(ジョブ,活動)の前に処理されなければならないことを表す制約.

• 資源( resource ):作業を行うときに必要とされるもので,その量に限りがあるもの.機械 (machine )はジョブによって占有される資源.その他,人員,材料,お金なども全部資源.

Page 3: スケジューリングモデルとは

optseq2.py モジュールとは

• スケジューリングソルバー OptSeq を,超高級言語 Python から直接呼び出して,求解するためのモジュール

• すべて Python で書かれたクラスで構成

• ソースコード(すべて Python で記述)も公開されているので,ユーザが書き換え可能

Page 4: スケジューリングモデルとは

Python モジュールのクラス

• 作業クラス ー  Activity

• モードクラス ー  Mode

• 資源クラス ー  Resource

• 先行制約クラス ー  Temporal

• モデルクラス ー  Model

• パラメータクラス ー  Parameters

Page 5: スケジューリングモデルとは

作業クラス ー  Activity

• activity の引数と引数のデフォルト値activity(name=‘’, dudate=‘inf’, weight=1)– name : 作業の名前,文字列で入力– dudate : 作業の納期,非負の整数または‘ inf’ で入力– weight : 作業が納期遅れした時のペナルティ, positive 整

• activity の addModes メソッドactivity.addModes(modes) – modes  : モードクラスで作成– 作業にモード(一つまたは複数のモード)を追加する時に使

用– 例:  activity.addModes(mode1,mode2)

作業の定義を行う

Page 6: スケジューリングモデルとは

モードクラス ー Mode (1)

• mode の引数と引数のデフォルト値mode(name=‘ ’, duration=0) – name  : モードの名前,文字列で入力– duration  : このモードを選択した場合の作業時間

• mode のメソッド (次のページで詳しく)– addBreak(start=0, finish=0, maxtime=‘inf’)

休憩に関する情報をモードに追加 –   addParallel(start=1, finish=1, maxparallel=‘inf’)

並列処理に関する情報をモードに追加 –   addResource(resource, requirement={}, rtype=None)

資源に関する情報をモードに追加

モードの定義を行う

Page 7: スケジューリングモデルとは

モードクラス ー Mode (2)

• addBreak メソッドaddBreak(start=0, finish=0, maxtime=‘inf’)– start , finish  : 休憩開始時間,休憩終了時間– maxtime  : 最大休憩可能時間

• addParallel メソッドaddParallel(start=1, finish=1, maxparallel=‘inf’)– start , finish  : 並列開始小作業番号,並列終了小作業

番号– maxparallel  : 最大並列数

モードメソッド(1)

Page 8: スケジューリングモデルとは

モード名 .addBreak(0,3,1)

モード名 .addBreak( 中断開始時刻 , 中断終了時刻 , 最大中断時間 )

作業の途中中断•  Python インターフェイスによる記述

作業 A が, 0 から 3 の区間でそれぞれ最大 1 中断可能:

開始から 2 時刻で中断した例

Page 9: スケジューリングモデルとは

モード名 .addParallel(1,1,3)

モード名 .addParallel( 開始小作業番号 , 終了小作業番号 , 最大並列数 )

作業の並列処理

小作業 1, 小作業 1

作業1(作業時間は3秒)を最大3単位並列可能:

•  Python インターフェイスによる記述

作業1

Page 10: スケジューリングモデルとは

並列処理の結果

•  1 番目の小作業を 3 単位並列可能:

2 3

1

Page 11: スケジューリングモデルとは

モードクラス ー Mode (3)

• addResource メソッドaddResource(resource, requirement={}, rtype=None)– resource  : 資源オブジェクト– requirement  : 資源必要量

資源を必要とする開始時刻と終了時刻を辞書で表す.必要量を正数値として入力すると,開始 0 ,終了 “ inf” になる.

例:  mode.addResource(worker,{(0,10):1}) 時刻 0 から時刻 10 まで worker という資源を1単位必要

– rtype  : リソースのタイプ ----- break と max がある例:  mode.addResource(machine,{(0,"inf"):1},"break") break は休憩中も資源を1単位使用例:  mode.addResource(machine,{(0,"inf"):1},"max") max は並列処理を行う時も資源は1単位使用

モードメソッド(2)

Page 12: スケジューリングモデルとは

資源クラス ー Resource (1)

• resource の引数と引数のデフォルト値resource (name=' ', capacity= {} , rhs=0, direction='<=') – name : 資源の名前,文字列で入力– capacity : 再生可能資源の最大容量 ; 区間と容量の辞書で入力

       正数値を入力すると,開始時刻 0 ,終了時刻 “ inf” に変換 

– rhs : 再生不能資源の制約– direction : 再生不能資源制約の向き "<=" or ">="

• resource のメソッド (次のページで詳しく)– addCapacity(start=0, finish=0, amount=1)

資源に容量を追加– addTerms(coeffs=[], vars=[], values=[])

再生不能資源に関する制約の左辺追加– printConstraint( )

再生不能資源に関する制約を展開 – setRhs(rhs=0)– 再生不能資源に関する制約の右辺追加

資源の定義を行う

Page 13: スケジューリングモデルとは

資源メソッド

資源クラス ー Resource (2)

resource のメソッド– addCapacity(start=0, finish=0, amount=1)

start, finish  : 資源使用開始と終了時刻amount  : 資源の使用量例:  manpower.addCapacity(0,5,2) 時刻 0 から時刻 5 の間に資源 (manpower) を 2 単位使

用– addTerms(coeffs=[], vars=[], values=[])

coeffs    : 追加する項; リストで入力可vars  : 作業オブジェクト; リストで入力可values  : モードオブジェクト; リストで入力可例:  budget.addTerms(1,act,express)   act と言う作業が express と言うモードで行う時

再生不能資源を 1 単位追加

Page 14: スケジューリングモデルとは

時間制約クラス ー  Temporal

• Temporal の引数と引数のデフォルト値Temporal(pred, succ, tempType, delay) – pred  : 先行作業のオブジェクト– succ  : 後続作業のオブジェクト– tempType  : 時間制約のタイプ; 規定値 = "CS"

• "CS"=Completion-Start, "SS"=Start-Start, "SC"= Start-Completion, "CC"=Completion-Completion

• 先行作業の終了 ( 開始 ) 時刻 +delay <= 後続作業の開始 ( 終了 ) 時刻

– delay  : 先行作業と後続作業の時間ずれ; 負の数も可

時間制約の定義を行う

Page 15: スケジューリングモデルとは

時間制約

A B

Temporal ( 先行作業 , 後続作業 , “ 制約タイプ” , 時間ずれ )

時間制約オブジェクトの生成法

先行作業 後続作業

Temporal(pred=A, succ=B, tempType=“CS”, delay=0)

作業 A の完了後に作業 B の開始

Completion Start

Page 16: スケジューリングモデルとは

制約タイプ( type )

A B type SS

Start Start

A B type SC

Start Completion

A B type CC

Completion Completion

Page 17: スケジューリングモデルとは

時間ずれ( delay )

A B

Completion Start

delay 10

10 作業 B の開始可能時間帯

A B

Completion Start

delay -10

10作業 B の開始可能時間帯

Page 18: スケジューリングモデルとは

時間制約の応用 1 (同時開始)

A と B の同時開始

A の開始 +0 ≦ B の開始

B の開始 +0 ≦ A の開始A の開始 = Bの開始

モデル名 .addTemporal(A,B,"SS",0)モデル名 .addTemporal(B,A,"SS",0)

モデル名 .addTemporal( 先行作業 , 後続作業 ,“ 制約タイプ” , 時間ずれ )

•  Python インターフェイスによる記述

Page 19: スケジューリングモデルとは

時間制約の応用 2 (開始時間固定)

A の開始を 50 に固定

ダミーの始点( source )の開始 +50 ≦ A の開始

A の開始 =50

A の開始 -50 ≦ ダミーの始点( source )の開始

source の開始時刻は 0

モデル名 .addTemporal(source,A,"SS",50)モデル名 .addTemporal(A, source,"SS",-50)

Page 20: スケジューリングモデルとは

時間制約の応用 3(最大・最小段取り時間)

A の完了後最小10 分最大 30 分でB を開始

A の終了 +10 ≦ B の開始

B の開始は A の終了 +[10,30]

B の開始 -30 ≦A の終了 B の開始≦ A の終了 +30

モデル名 .addTemporal(A,B,"CS",10)モデル名 .addTemporal(B,A,"SC",-30)

Page 21: スケジューリングモデルとは

モデルクラス ー  Model

• モデルクラスのメソッド  – addActivity(name=‘’, duedate=‘inf’, weight=1)

モデルに作業を追加  (括弧内の引数説明は activity クラス参照)

– addResource(name=‘’, capacity={}, rhs=0, direction=‘<=’)モデルに資源を追加  (括弧内の引数説明は resource クラス参照)

– addTemporal(pred, succ, tempType=‘CS’, delay=0)モデルに先行制約を追加 (括弧内の引数説明は temporal クラス参照)

– optimize()モデルの最適化を行う

– write(filename=‘optseq.txt’)テキスト形式のガントチャートを書く

モデルを作成

Page 22: スケジューリングモデルとは

パラメータクラス ー Parameters

• TimeLimit :求解する時の制限時間;単位は秒;既定値 =600 秒  

• OutputFlag :モデルを出力する場合 True ,出力しない場合 False  ; 既定値 =False

• Makespan :最大完了時刻最小化の時は True ,それ以外の時は False  ; 既定値 =False  

• RandomSeed – random seed を設定;整数;既定値 =1

よく使うパラメータ

Page 23: スケジューリングモデルとは

• PERT: Program Evaluation and Review Technique,第二次世界大戦のポラリス潜水艦の建造で利用.( ORの古典)

航空機を早く離陸させよう!

22 分25 分

13 分 15 分 27 分

作業 1

作業 2

作業 3 作業 4

作業 5

ダミー作業

先行制約

作業1:乗客降ろし(13分)作業2:荷物降ろし(25分)作業3:機内清掃(15分)作業4:乗客搭乗(27分)作業5:荷物積み込み(22分)

完了時刻最小化

点が作業(活動)のグラフ -> 点上活動図式

Page 24: スケジューリングモデルとは

航空機を早く離陸させよう!

作業1:乗客降ろし(13分)作業2:荷物降ろし(25分)作業3:機内清掃(15分)作業4:乗客搭乗(27分)作業5:荷物積み込み(22分)

完了時刻最小化

22 分25 分

13 分 15 分 27 分

作業 1

作業 2

作業 3 作業 4

作業 5

ダミー作業

ダミー作業

先行制約開始時刻

終了時刻

Page 25: スケジューリングモデルとは

Python インターフェイスによる記述(1)

• OptSeqⅡのモジュールを読み込む

• モデルオブジェクト m1 を作成 

• 作業時間を作業をキー,作業時間を値とする辞書 duration に保管

from optseq2 import *      

m1=Model()                  

duration ={1:13, 2:25, 3:15, 4:27, 5:22 }    

    キー   値

Page 26: スケジューリングモデルとは

Python インターフェイスによる記述(2)

• 作業を保管するための空の辞書 act を作成

• モードを保管するための空の辞書 mode を作成 

act={}

mode={}

Page 27: スケジューリングモデルとは

Python インターフェイスによる記述(3)

• モデルオブジェクト m1 の addActivity(“ 作業名” ) メソッドを用いてモデルに作業を追加

• モードクラス Mode(“ モード名” , 作業時間 ) を用いてモードに必要な作業時間を入力

• addModes メソッドを用いて作業にモードを追加for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

act[i].addModes(mode[i])

Page 28: スケジューリングモデルとは

Python インターフェイスによる記述(4)

• モデルに addTemporal ( 先行作業 , 後続作業 ) メソッドを用いて時間制約を追加

m1.addTemporal(act[1],act[3])

m1.addTemporal(act[2],act[4])

m1.addTemporal(act[2],act[5])

m1.addTemporal(act[3],act[4])

Page 29: スケジューリングモデルとは

Python インターフェイスによる記述(5)

• m1.optimize() を入力して求解

m1.Params.TimeLimit=1         求解時の制限時間

m1.Params.OutputFlag=True    モデルを出力する場合 True    

m1.Params.Makespan=True     最大完了時刻最小化の時はTrue

m1.optimize()

Page 30: スケジューリングモデルとは

Python インターフェイスによる記述(6)

•  Python コードまとめ

from optseq2 import *

m1=Model()

duration ={1:13, 2:25, 3:15, 4:27, 5:22 }

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

act[i].addModes(mode[i])

m1.addTemporal(act[1],act[3])

m1.addTemporal(act[2],act[4])

m1.addTemporal(act[2],act[5])

m1.addTemporal(act[3],act[4])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Page 31: スケジューリングモデルとは

Python インターフェイスによる記述(7)

• 実行結果(一部)source ---: 0 0                          ダミーの始点の開始時刻が0

sink ---: 55 55                  ダミーの終点の開始時刻が55(完了時刻)

activity[1] ---: 0 0--13 13             作業1は0に開始されて13に終了

activity[2] ---: 0 0--25 25        作業2は0に開始されて25に終了

activity[3] ---: 13 13--28 28          作業3は13に開始されて28に終了

activity[4] ---: 28 28--55 55        作業4は28に開始されて55に終了

activity[5] ---: 25 25--47 47          作業5は25に開始されて47に終了

objective value = 55                     目的関数

cpu time = 0.00/1.00(s)                 計算時間

iteration = 1/15962 反復回数

Page 32: スケジューリングモデルとは

航空機を早く離陸させよう!最適解

13分

1作 業15分

3作 業27分

4作 業

25分

2作 業22分

5作 業

時 間0 55

Page 33: スケジューリングモデルとは

航空機を早く離陸させよう!

作業1:乗客降ろし(13分)作業2:荷物降ろし(25分)作業3:機内清掃(15分)作業4:乗客搭乗(27分)作業5:荷物積み込み(22分)

完了時刻最小化

22 分25 分

13 分 15 分 27 分

作業 1

作業 2

作業 3 作業 4

作業 5

ダミー作業

ダミー作業

先行制約開始時刻

終了時刻

作業員1人

Page 34: スケジューリングモデルとは

Python インターフェイスによる記述(1)•資源(この例題の場合は作業員)制約の記述:

モデル名 .addResource ( “資源名” , {( 時刻 1, 時刻 2):供給量 } )

•モードに資源使用量追加:

モード名 .addResource ( 資源 ,{( 資源使用可能区間 ): 使用量 } )

r e s=m1. addResource ( "worker " , {(0 , " i n f " ) : 1} )

for i in duration: 

    act[i]=m1.addActivity("Act[%s]"%i)

    mode[i]=Mode("Mode[%s]"%i,duration[i])

    mode[i].addResource(res,{(0,"inf"):1})

    act[i].addModes(mode[i])

Page 35: スケジューリングモデルとは

Python インターフェイスによる記述(2)

•  Python コードまとめfrom optseq2 import *

m1=Model()

duration ={1:13, 2:25, 3:15, 4:27, 5:22 }

res=m1.addResource("worker",capacity={(0,"inf"):1})

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

m1.addTemporal(act[1],act[3])

m1.addTemporal(act[2],act[4])

m1.addTemporal(act[2],act[5])

m1.addTemporal(act[3],act[4])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Page 36: スケジューリングモデルとは

Python インターフェイスによる記述(3)

source ---: 0 0sink ---: 102 102activity[1] ---: 47 47--60 60activity[2] ---: 0 0--25 25activity[3] ---: 60 60--75 75activity[4] ---: 75 75--102 102activity[5] ---: 25 25--47 47

objective value = 102cpu time = 0.00/3.00(s)iteration = 0/64983

• 実行結果(一部)

Page 37: スケジューリングモデルとは

並列ショップスケジューリングピットイン時間を短縮せよ!

gas

4

4

4

4

2

3

2

2

2

11作業1

作業2

作業3

作業4

作業5

作業6

作業7

作業8

作業9

作業10

3人のピットクルー(資源制約)

資源(機械)制約があると難しい!

Page 38: スケジューリングモデルとは

Python インターフェイスによる記述(1)3人の作業員記述:資源制約モデル名 .addResource ( " 資源名

",( 時刻 1, 時刻 2):供給量 ) の供給量を 3 に設定

from optseq2 import *m1=Model()                duration ={1:3, 2:2, 3:2, 4:2, 5:4, 6:4, 7:4, 8:4, 9:11, 10:2 }res=m1.addResource("worker",capacity={(0,"inf"):3})act={}mode={}        for i in duration:     act[i]=m1.addActivity("Act[%s]"%i)    mode[i]=Mode("Mode[%s]"%i,duration[i])    mode[i].addResource(res,{(0,"inf"):1})    act[i].addModes(mode[i])

Page 39: スケジューリングモデルとは

Python インターフェイスによる記述(2)

時間制約

求解実行

m1.addTemporal(act[1],act[9])for i in range(5,9):    m1.addTemporal(act[4],act[i])    m1.addTemporal(act[i],act[10])

m1.Params.TimeLimit=1m1.Params.OutputFlag=Truem1.Params.Makespan=Truem1.optimize()

Page 40: スケジューリングモデルとは

Python インターフェイスによる記述(3)•  Python コードまとめ

from optseq2 import *

m1=Model()

duration ={1:3, 2:2, 3:2, 4:2, 5:4, 6:4, 7:4, 8:4, 9:11, 10:2 }

res=m1.addResource("worker",capacity={(0,"inf"):3})

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

m1.addTemporal(act[1],act[9])

for i in range(5,9):

m1.addTemporal(act[4],act[i])

m1.addTemporal(act[i],act[10])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Page 41: スケジューリングモデルとは

source ---: 0 0sink ---: 14 14prepare ---: 0 0--3 3water ---: 0 0--2 2front ---: 0 0--2 2jackup ---: 2 2--4 4tire1 ---: 8 8--12 12tire2 ---: 4 4--8 8tire3 ---: 8 8--12 12tire4 ---: 4 4--8 8oil ---: 3 3--14 14jackdown ---: 12 12--14 14

objective value = 14cpu time = 0.00/3.00(s)iteration = 0/37644

Python インターフェイスによる記述(4)

• 実行結果(一部)

Page 42: スケジューリングモデルとは

並列ショップスケジューリング- 複数モード -

3人のピットクルー(資源制約)

資源(機械)制約があると難しい!

gas

WATER

4

4

4

4

2

3

2

2

2

11

作業1

作業2

作業3

作業4

作業5

作業6

作業7

作業8

作業9

作業10

1人   3秒2人   2秒3人   1秒

Page 43: スケジューリングモデルとは

並列ショップスケジューリング 2  - モードの概念と使用法 -

コンビニモード:作業時間 20 分,お金資源 120 円,人資源 1 人

自販機モード:作業時間 5 分,お金資源 120 円,人資源 1 人

スーパーモード:作業時間 40 分,お金資源 100 円,人資源 1 人,車資源 1 台

モード:作業を行うための処理方法

例: 作業 「ジュースを買う」

Page 44: スケジューリングモデルとは

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

if i==1:

mode[1,1]=Mode("Mode[1_1]",3)

mode[1,1].addResource(res,{(0,"inf"):1})

mode[1,2]=Mode("Mode[1_2]",2)

mode[1,2].addResource(res,{(0,"inf"):2})

mode[1,3]=Mode("Mode[1_3]",1)

mode[1,3].addResource(res,{(0,"inf"):3})

act[i].addModes(mode[1,1],mode[1,2],mode[1,3])

else:

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

作業1のモード1

作業1のモード1に資源を追加

作業1にモード1,モード2,モード3

を追加

• 多モードの記述

Python インターフェイスによる記述(1)

Page 45: スケジューリングモデルとは

Python インターフェイスによる記述(2)

•  Python コードまとめ(1)

from optseq2 import *

m1=Model()

duration ={1:3, 2:2, 3:2, 4:2, 5:4, 6:4, 7:4, 8:4, 9:11, 10:2 }

res=m1.addResource("worker",capacity={(0,"inf"):3})

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

if i==1:

mode[1,1]=Mode("Mode[1_1]",3)

mode[1,1].addResource(res,{(0,"inf"):1})

mode[1,2]=Mode("Mode[1_2]",2)

mode[1,2].addResource(res,{(0,"inf"):2})

mode[1,3]=Mode("Mode[1_3]",1)

mode[1,3].addResource(res,{(0,"inf"):3})

       act[i].addModes(mode[1,1],mode[1,2],mode[1,3])

else:

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

Page 46: スケジューリングモデルとは

m1.addTemporal(act[1],act[9])

for i in range(5,9):

m1.addTemporal(act[4],act[i])

m1.addTemporal(act[i],act[10])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Python インターフェイスによる記述(3)

•  Python コードまとめ(2)

Page 47: スケジューリングモデルとは

Python インターフェイスによる記述(4)

計算結果とガントチャート

objective value = 13

cpu time = 0.00/1.00(s)

iteration = 7/7343

source --- 0 0

sink --- 13 13

Act[1] Mode[1_3] 0 1

Act[2] --- 1 3

Act[3] --- 11 13

Act[4] --- 1 3

Act[5] --- 7 11

Act[6] --- 3 7

Act[7] --- 7 11

Act[8] --- 3 7

Act[9] --- 1 12

Act[10] --- 11 13

planning horizon= 13

Page 48: スケジューリングモデルとは

資源制約付きスケジュールングお家を早く造ろう!

土台

1階

内装

屋根

完成!

時間(日)

資源量(人)

30

2人

1人の作業員休暇

作業時間=2日1日目1人,2日目2人の資源が必要!

Page 49: スケジューリングモデルとは

最適解

時 間 ( 日 )

資 源 量 ( 人 )

資源制約付きスケジューリングは一般的なモデル(ジョブショップ,並列ショップスケジューリングを特殊形として含む.)

Page 50: スケジューリングモデルとは

Python インターフェイスによる記述(1)

• 資源の必要量入力m1=Model()

duration ={1:1,2:3,3:2,4:2}

req={}

req[1]={(0,1):2 }

req[2]={(0,1):2 ,(1,3):1}

req[3]={(0,2):1 }

req[4]={(0,1):1,(1,2):2 }

res=m1.addResource("worker")

res.addCapacity(0,2,2)

res.addCapacity(2,3,1)

res.addCapacity(3,"inf",2)

{(0,1):2 }

{( 開始時刻,終了時刻 ): 資源必要量 }

土台造り  ( req[1] )は1日目に資源(人)が2単位必要

(0,2,2)    

(開始時刻,終了時刻,資源容量) 最初の2日間は資源(人)が

2単位使用可能

• 資源の容量制約入力

Page 51: スケジューリングモデルとは

Python インターフェイスによる記述(2)•  Python コードまとめ

from optseq2 import *

m1=Model()

duration ={1:1,2:3,3:2,4:2}

req={}

req[1]={(0,1):2 }

req[2]={(0,1):2 ,(1,3):1}

req[3]={(0,2):1 }

req[4]={(0,1):1,(1,2):2 }

res=m1.addResource("worker")

res.addCapacity(0,2,2)

res.addCapacity(2,3,1)

res.addCapacity(3,"inf",2)

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,req[i])

act[i].addModes(mode[i])

m1.addTemporal(act[1],act[2])

m1.addTemporal(act[1],act[3])

m1.addTemporal(act[2],act[4])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Page 52: スケジューリングモデルとは

Python インターフェイスによる記述(3)

objective value = 6cpu time = 0.00/1.00(s)iteration = 1/6936

source --- 0 0sink --- 6 6Act[1] --- 0 1Act[2] --- 1 4Act[3] --- 3 5Act[4] --- 4 6planning horizon= 6

• 実行結果(一部)

Page 53: スケジューリングモデルとは

1機械スケジュールング納期遅れを最小にしよう!

• 完了時刻最小化(メイクスパン)以外の目的関数の例– 納期遅れ最小化– 納期ずれ最小化– 納期遅れした作業(ジョブ)数最小化– 納期遅れの最大値の最小化– 上の指標の重み付きの尺度最小化 ....会社名 A社 B社 C社 D社

作業時間 1日 2日 3日 4日

納期 5日後 9日後 6日後 4日後

Page 54: スケジューリングモデルとは

Python インターフェイスによる記述(1)

 納期を辞書に保管 due={1:5,2:9,3:6,4:4}

.......

for i in req: act[i]=m1.addActivity("Act[%s]"%i,duedate=due[i])

mode[i]=Mode("Mode[%s]"%i,req[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

• 納期に関する入力

 納期を作業に追加

Page 55: スケジューリングモデルとは

Python インターフェイスによる記述(2)

•  Python コードまとめ

from optseq2 import *

m1=Model()

due={1:5,2:9,3:6,4:4}

req={1:1, 2:2, 3:3, 4:4 }

res=m1.addResource("writer")

res.addCapacity(0,"inf",1)

act={}

mode={}

for i in req: act[i]=m1.addActivity("Act[%s]"%i,duedate=due[i])

mode[i]=Mode("Mode[%s]"%i,req[i])

mode[i].addResource(res,{(0,"inf"):1})

act[i].addModes(mode[i])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=False

m1.optimize()

Page 56: スケジューリングモデルとは

--- best solution ---source,---, 0 0sink,---, 10 10Act[1],---, 4 4--5 5Act[2],---, 8 8--10 10Act[3],---, 5 5--8 8Act[4],---, 0 0--4 4

--- tardy activity ---Act[2]: 1Act[3]: 2

時 間 ( 日 )

010

1(A作 業 社 ) 2 B作 業 ( 社 ) 3 C作 業 ( 社 ) 4 D作 業 ( 社 )

A社 納 期C社 納 期D社 納 期 B社 納 期

納 期 遅 れ 納 期 遅 れ

会社名 A社 B社 C社 D社

作業時間

1日 2日 3日 4日

納期 5日後 9日後 6日後 4日後

Python インターフェイスによる記述(3)

• 実行結果(一部)

Page 57: スケジューリングモデルとは

航空機をもっと早く離陸させよう !

作業 1 :乗客降ろし 13 分. 10 分に短縮可能で, 1 万円必要.作業 2 :荷物降ろし 25 分. 20 分に短縮可能で, 1万円必要.作業 3 :機内清掃 15 分. 10 分に短縮可能で, 1万円必要.作業 4 :新しい乗客の搭乗 27 分. 25 分に短縮可能で, 1万円必要.作業 5 : 新しい荷物積み込み 22 分. 20 分に短縮可能で, 1万円必要.

クリティカルパス法 ( critical path method ,略して CPM )

作業時間を費用をかけることによって短縮できる

再生不能資源(使用可能なお金) 4 万万円以下

Page 58: スケジューリングモデルとは

再生可能資源と再生不能資源

• 再生可能資源作業完了後に再び使用可能になる資源機械や作業員など

• 再生不能資源一度使うとなくなってしまう資源(計画期間内での合計に制約を設ける)お金や原材料など

クリティカルパス法の予算を再生不能資源として扱う!

Page 59: スケジューリングモデルとは

Python インターフェイスによる記述(1)

通常時の作業時間

再生不能資源使用時の作業時間

m1=Model()

durationA = {1:13, 2:25, 3:15, 4:27, 5:22 }

durationB = {1:10, 2:20, 3:10, 4:25, 5:20 }

act={}

mode={}

res=m1.addResource("money",rhs=4,direction="<=")

• 再生不能資源に関する入力(1)

 再生不能資源使用可能量制約

Page 60: スケジューリングモデルとは

Python インターフェイスによる記述(2)

•  Python コードまとめm1.addTemporal(act[1],act[3])

m1.addTemporal(act[2],act[4])

m1.addTemporal(act[2],act[5])

m1.addTemporal(act[3],act[4])

print m1

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

from optseq2 import *

m1=Model()

durationA = {1:13, 2:25, 3:15, 4:27, 5:22 }

durationB = {1:10, 2:20, 3:10, 4:25, 5:20 }

act={}

mode={}

res=m1.addResource("money",rhs=4,direction="<=")

for i in durationA:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i,1]=Mode("Mode[%s][1]"%i,durationA[i])

mode[i,2]=Mode("Mode[%s][2]"%i,durationB[i])

act[i].addModes(mode[i,1],mode[i,2])

res.addTerms(1,act[i],mode[i,2])

Page 61: スケジューリングモデルとは

結果

10分

1作業

13分

1作業

10分

3作業

10分

3作業

25分

4作業

27分

4作業

20分

2作業

25分

2作業

22分

5作業

22分

5作業

時間

時間

45

13分

1作業15分

3作業27分

4作業

25分

2作業22分

5作業

時間0 55

52

4万円

1万円

0万円

Page 62: スケジューリングモデルとは

並列ショップスケジューリング

3人のピットクルー(資源制約)

資源(機械)制約があると難しい!

gas

WATER

4

4

4

4

2

3

2

2

2

11

作業1

作業2

作業3

作業4

作業5

作業6

作業7

作業8

作業9

作業10

1人   3秒2人   2秒3人   1秒

複数モード 複数資源による作業の並列処理

Page 63: スケジューリングモデルとは

Python インターフェイスによる記述(1)

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

if i==1:

mode[i].addParallel(1,1,3)

act[i].addModes(mode[i])

• 並列処理入力

1 番目の小作業を 3 単位並列可能

Page 64: スケジューリングモデルとは

Python インターフェイスによる記述(2)•  Python コードまとめ

m1.addTemporal(act[1],act[9])

for i in range(5,9):

m1.addTemporal(act[4],act[i])

m1.addTemporal(act[i],act[10])

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

from optseq2 import *

m1=Model()

duration ={1:3, 2:2, 3:2, 4:2, 5:4, 6:4, 7:4, 8:4, 9:11, 10:2 }

res=m1.addResource("worker")

res.addCapacity(0,"inf",3)

act={}

mode={}

for i in duration:

act[i]=m1.addActivity("Act[%s]"%i)

mode[i]=Mode("Mode[%s]"%i,duration[i])

mode[i].addResource(res,{(0,"inf"):1})

if i==1:

mode[i].addParallel(1,1,3)

act[i].addModes(mode[i])

Page 65: スケジューリングモデルとは

ジョブショップスケジューリンングジョブ(作業)ごとに機械(工程)順が異なっても良い!

5

1 0

1 3

4

11

9

1 2

7

3

6

機械 作業機械3

機械1

機械2

機械1

機械1

機械1

機械2

機械2

機械2

機械3

機械3

機械3

作業 1

作業 2

作業 3

作業 4

小作業 1 小作業 2 小作業 3

Page 66: スケジューリングモデルとは

ジョブショップスケジューリンング

• 各作業は,最初の2日間は作業員の作業が必要• 各作業は小作業 1,2,3 の順に処理される• 各作業は1日目の作業後休むことが可能• 作業員は平日(週5日間)のみ作業可能• 作業員は1日最大2人作業可能• 機械1の最初の2日間分の作業は並列処理可能• 機械2は express モードで処理可能;処理時間は4日

間に短縮可能• express モードは最大1回しか使用できない• 機械1での作業2は,作業1が完了した直後に行う

(他の作業が間に入らない)

Page 67: スケジューリングモデルとは

manpower=m1.addResource("manpower")

for t in range(9):

manpower.addCapacity(t*7,t*7+5,2)     #  作業員は平日のみ作業可能;平日の作業可能な作業員上限2人

machine={}

for j in range(1,4):

  machine[j]=m1.addResource("machine[%s]"%j,capacity={(0,"inf"):1})     # 3種類の機械;各機械は1つの作業しか処理できない

Python インターフェイスによる記述(1)

• 作業員に関する制約

• 機械に関する制約

Page 68: スケジューリングモデルとは

JobInfo={ (1,1):(1,7), (1,2):(2,10), (1,3):(3,4),

(2,1):(3,9), (2,2):(1,5), (2,3):(2,11),

(3,1):(1,3), (3,2):(3,9), (3,3):(2,12),

(4,1):(2,6), (4,2):(3,13), (4,3):(1,9) }

Python インターフェイスによる記述(2)

(1,1): (1,7) は作業1の子作業1の機械1での作業時間が7日であること

• 作業と機械

1047

作業1小作業1 小作業2 小作業3

Page 69: スケジューリングモデルとは

budget=m1.addResource(“budget_constraint”,rhs=1)     #   express モードが1回しか使え

ないことを資源( budget )の使用可能量 (rhs) =1 で表現

express=Mode("Express",duration=4)   #     express の作業時間は4日

express.addResource(machine[2],{(0,"inf"):1},"max")   #     express は機械2を1単位使用

express.addResource(manpower,{(0,2):1})     #  最初の2期の間は作業員が1人必要

express.addBreak(1,1)         #  各作業は1日目作業後休憩可能

Python インターフェイスによる記述(3)

• 機械2は express モードで処理可能

express.addResource(machine[2],{(0,"inf"):1},"max")資源タイプ“ max” :並列作業時も機械は1単位しか使用しない

資源タイプ

Page 70: スケジューリングモデルとは

for (i,j) in JobInfo:

act[i,j]=m1.addActivity(“Act[%s][%s]”%(i,j))                  #   (作業名)

mode[i,j]=Mode(“Mode[%s][%s]”%(i,j),duration=JobInfo[i,j][1])#モード名 , 作業時間追加    mode[i,j].addResource(machine[JobInfo[i,j][0]],{(0,“inf”):1},“max”)

    mode[i,j].addResource(manpowe):1}) # 最初の2期の間は作業員が1人必要

mode[i,j].addBreak(1,1) #  各作業は1日目作業後休憩可能

if JobInfo[i,j][0]==1:

mode[i,j].addParallel(1,1,2) # 機械1での各小作業は並列処理可能

if JobInfo[i,j][0]==2:

act[i,j].addModes(mode[i,j],express)           # 機械2に express モードを追加

budget.addTerms(1,act[i,j],express)         # express モードは最大1回しか使用できない

else:

act[i,j].addModes(mode[i,j])

Python インターフェイスによる記述(4)

• 作業にモード追加

Page 71: スケジューリングモデルとは

Python インターフェイスによる記述(5)

for i in range(1,5):

for j in range(1,3):

m1.addTemporal(act[i,j],act[i,j+1])    

• 各作業は子作業 1,2,3 の作業順で処理される

5

1 0

1 3

4

11

9

1 2

7

3

6

作業1

小作業1 小作業2 小作業3

小作業1 小作業2 小作業3

小作業1 小作業2 小作業3

小作業1 小作業2 小作業3

作業2

作業3

作業4

Page 72: スケジューリングモデルとは

Python インターフェイスによる記述(6)

d_act=m1.addActivity(“dummy_activity”)   #  ダミーの作業を追加

d_mode=Mode(“dummy_mode”)           #  ダミーのモードを追加

d_mode.addBreak(0,0)           #  作業開始時刻から無限に休憩可能

d_mode.addResource(machine[1],{(0,0):1},“break”)   #  休憩中にも資源を使用

d_act.addModes(d_mode)                     #  作業にモードを追加

機械1での作業2は,作業1が完了した直後に行う(他の作業が間に入らない)

1. ダミーの作業を生成

資源使用量

作業時間 0 のダミーの作業

作業開始時刻から無限に休憩可能

休憩中にも資源を使用

Page 73: スケジューリングモデルとは

Python インターフェイスによる記述(6)

m1.addTemporal(act[1,1],d_act,tempType=“CS”)   #(1)

m1.addTemporal(d_act,act[1,1],tempType="SC") #(2)

m1.addTemporal(d_act,act[2,2],tempType="CS") #(3)

m1.addTemporal(act[2,2],d_act,tempType="SC") #(4)

2.  時間制約追加

ダミー作業は休憩中にも資源を使用act[1,1]       act[2,2]

(1)  作業 1 の小作業 1(act[1,1]) が終了しないとダミー作業 (d_act) が開始できない

(2) ダミー作業 (d_act) が開始しないと作業 1 の小作業 1 (act[1,1]) が終了できない

(3) , (4) も (1) , (2) と同様

ダミー作業

資源使用量

結論: 作業 1 の小作業 1 はダミー作業の直後に開始

     ダミー作業は作業 1 の小作業 1 の直後に開始

Page 74: スケジューリングモデルとは

Python インターフェイスによる記述(7)

•  Python コードまとめ(1)from optseq2 import *

m1=Model()

machine={}

for j in range(1,4):

    machine[j]=m1.addResource("machine[%s]"%j,capacity={(0,"inf"):1})

manpower=m1.addResource("manpower")

for t in range(9):

manpower.addCapacity(t*7,t*7+5,2)

budget=m1.addResource("budget_constraint",rhs=1)

JobInfo={ (1,1):(1,7), (1,2):(2,10), (1,3):(3,4),

(2,1):(3,9), (2,2):(1,5), (2,3):(2,11),

(3,1):(1,3), (3,2):(3,9), (3,3):(2,12),

(4,1):(2,6), (4,2):(3,13), (4,3):(1,9) }

act={}

Page 75: スケジューリングモデルとは

Python インターフェイスによる記述(8)

•  Python コードまとめ(2)

express=Mode("Express",duration=4)

express.addResource(machine[2],{(0,"inf"):1},"max")

express.addResource(manpower,{(0,2):1})

express.addBreak(1,1)

mode={}

for (i,j) in JobInfo:

act[i,j]=m1.addActivity("Act[%s][%s]"%(i,j))

mode[i,j]=Mode("Mode[%s][%s]"%(i,j),

                  duration=JobInfo[i,j][1])

mode[i,j].addResource (

                machine[JobInfo[i,j][0]],{(0,"inf"):1},"max")

mode[i,j].addResource(manpower,{(0,2):1})

mode[i,j].addBreak(1,1)

if JobInfo[i,j][0]==1:

mode[i,j].addParallel(1,1,2)

if JobInfo[i,j][0]==2:

act[i,j].addModes(mode[i,j],express)

budget.addTerms(1,act[i,j],express)

else:

act[i,j].addModes(mode[i,j])

Page 76: スケジューリングモデルとは

Python インターフェイスによる記述(9)

•  Python コードまとめ(3)for i in range(1,5):

for j in range(1,3):

m1.addTemporal(act[i,j],act[i,j+1])

d_act=m1.addActivity("dummy_activity")

d_mode=Mode("dummy_mode")

d_mode.addBreak(0,0)

d_mode.addResource(machine[1],{(0,0):1},"break")

d_act.addModes(d_mode)

m1.addTemporal(act[1,1],d_act,tempType="CS")

m1.addTemporal(d_act,act[1,1],tempType="SC")

m1.addTemporal(d_act,act[2,2],tempType="CS")

m1.addTemporal(act[2,2],d_act,tempType="SC")

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()

Page 77: スケジューリングモデルとは

時刻によって変化可能

• 段取り替えを表現

• 特定の時刻になると仕事を開始する– 例:毎週月曜日にしか開始できない仕事を表現

状態1

A1 A2 B1

段取り替え 段取り替え生産ライン

1 時間 5 時間

日1 8 15 22

Page 78: スケジューリングモデルとは

• モデルに状態メソッドを追加– 引数は状態の名称を表す文字列,返値は状態オブジェ

クト– addState(name= ' ' )

• モードに状態メソッドを追加– モード実行時における状態の値と状態の実行直後(実

行開始が時刻 t のときには,時刻 t+1 )の状態の値を定義する

– addState(state, fromValue=0, toValue=0)• state :モードに付随する状態オブジェクト,省略不可• fromValue :モード実行時における状態の値,省略可,規定値

は 0

• toValue :状態の実行直後の値,省略可,規定値は 0

状態2

autoselect

状態オブジェクトに addValue (初期状態)

Page 79: スケジューリングモデルとは

状態(例題)

A タイプ

A タイプ

B タイプ

段取り替え 段取り替え機械

1 時間 5 時間

処理時間3 時間

処理時間3 時間

目的: 最大完了時刻最小化

機械( 1台)

A1 A2 B1A3 B2 B3作業( 6 つ)

A タイプ B タイプ

Page 80: スケジューリングモデルとは

Python インターフェイスによる記述(1)

from optseq2 import *

m1=Model()

duration={(1,1):3,(1,2):3,(1,3):3,(2,1):3,(2,2):3,(2,3):3}     # 作業時間

setup={(1,1):1,(1,2):5,(2,1):5,(2,2):1}     # 段取り時間

act={}                                                # 作業

act_setup={}                                          # 段取り作業

mode={}                                              # 作業モード

mode_setup={}                                      # 段取りモード

rs=m1.addResource(“machine”,1)         # 機械資源

s1=m1.addState(“Setup_State”) # モデルに状態を追加

s1.addValue(time=0,value=1)              # 時刻 0 の状態は 1 (状態 1 は作業 A の状態)

Page 81: スケジューリングモデルとは

Python インターフェイスによる記述(2)for (i,j) in setup:

mode_setup[i,j]=Mode(" Mode_setup " +str(i)+str(j),setup[i,j])       # 段取りモード作成

mode_setup[i,j].addState(s1,i,j)     # 段取りモードに状態を追加(状態 2 は作業 Bの状態)

mode_setup[i,j].addResource(rs,{(0, " inf "):1})   # 段取りのとき機械資源1を使用

for (i,j) in duration:

act_setup[i,j]=m1.addActivity("Setup" +str(i)+str(j),autoselect=True)     # 段取り作業作成

act_setup[i,j].addModes(mode_setup[1,i],mode_setup[2,i])     # 段取り作業にモード追加

act[i,j]=m1.addActivity(" Act " +str(i)+str(j))     # 作業作成

mode[i,j]=Mode(" Mode "+str(i)+str(j),duration[i,j])     # 作業にモード追加

mode[i,j].addResource(rs,{(0,"inf"):1})        # 作業にードに資源追加

mode[i,j].addBreak(0,0)         # 作業は中断可能

mode[i,j].addResource(rs,{(0,"inf"):1},"break")       # 作業の中断中も資源使用

act[i,j].addModes(mode[i,j])           # 作業にモード追加

Page 82: スケジューリングモデルとは

Python インターフェイスによる記述(3)

for (i,j) in duration:                                     # 先行制約追加

m1.addTemporal(act_setup[i,j],act[i,j],"CS")

m1.addTemporal(act[i,j],act_setup[i,j],"SC")

m1.Params.TimeLimit=1

m1.Params.OutputFlag=True

m1.Params.Makespan=True

m1.optimize()