現行計画
現行計画(総合日程表)における各ブロックのブロック搭載日、ブラスト開始日、組立開始日また外注の場合の入荷日をグラフにしたものを次に示します。
「工程’s」にはリソースの山積機能がありますので、これを利用して作業時数と場所の専有面積を山積した結果を次に示します。
時数山積み
面積山積み
実際の配員計画と定盤計画では様々なやりくり(残業・休日出勤、段積み・先行搭載など)がなされていて、実際の造船工程が回っていると言えます。
RCPSP計画
当該造船所の工程計画問題をRCPSPとして定式化した場合、大規模な組合せ最適化問題となり、ソルバーOptSeqを用いても、問題全体を一括して解くことは困難です。そのため、造船工程をブロック組立工程と艤装・待機工程に分割して、適切につなぎ合わせる工夫が必要となります。一般にブロック搭載工程は固定してよいので、下流の艤装・待機工程はプル型すなわち搭載日程に後詰めします。これに、上流の組立工程をジャストインすることになりますが、その際前詰め(方針I)するか後詰め(方針II)するかの2通りが考えられます。各ブロック組立の開始順番などは経験的に確立されているとしてよいので、総合日程表におけるブロック開始日を固定してこれに前詰めするのが方針Iです。ただ、これはジャストインの達成は難しいので、接続を行う特別の場所の確保が必要となります。これらの方針を次図に示します。
一方、組立工程を艤装・待機工程にジャストインする方針を次図に示します。
どちらともリソース(作業員と作業場所)が分離されていることが前提となりますが、実際には一部例外的な処理が必要です。
また共通した重要な課題として、日程計画・配員計画・定盤計画(場所の割付)をどう連動させるかがあります。本研究では、OptSeqのもつ小作業並列化機能を用いて作業時数と配員制約から作業期間を決めます。同時にその未知の期間に場所の割付ができるかを、OptSeqのもつ仮想アクティビティの手法を用いてチェックします。すなわち、OptSeqと用いて日程計画・配員計画・定盤計画の3つを連動させることを試みます。
●種々検討の結果、上の現行計画に対応して、方針IIに基づいて次図を得ることができました。
艤装工程計画を得るプログラムを、本資料では次のように分割して示しています。
プログラム I ************************ 艤装工程計画 ************************
・プログラム I-1 リソース(場所・メッシュ、作業員)の定義
・プログラム I-2 データセットの定義
・プログラム I-3 艤装工程計画アクティビティの定義(一部組立工程追加)
先行制約の設定
・プログラム I-4 モードの設定
艤装工程計画 資源制約(配員)
艤装工程計画 資源制約(作業場所)
・プログラム I-5 RCPSP求解
・プログラム I-6 データセットの更新
プログラム:Part I-3
#プログラムI-3.0
#=======================================================================
#識別番号
#=======================================================================
#作業項目・作業場所の識別番号 data[i][1]
#-----
#11:開始 #1:F #2:W #3:C #4:CC #5:社 #6:検 #12:正 #13:反 #14:積み #15:一体 #36:磨き #37:O/P #38:_鉄艤 #16:運
ACT_kumitate=[11,1,2,3,4,5,6,12,13,14,15,36,37,38,16]
#-----
#10:入荷 #7:社0 #8:検0 #9:W0 #16:運 #17:運0 #18:運2 #19:合体 #20:ブラスト #21:運ブ #25:運ブ2
#31:鉄艤 #32:甲配 #33:機配 #39:_甲配 #40:_機配 #34:PA #35:AT #0:搭載
ACT_gisou=[10,7,8,9,16,17,18,19,20,21,25,31,32,33,39,40,34,35,0]
#-----
#51:K1K2 #53:K3 #54:K4 #55:K5U #55:K5R #56:K6
#57:K1_1FS1 #58:K1_1S6P #59:K1_1S6S #60:K2_8S6P #61:K2_8S6S #62:K4S4 #63:県岸 #64:K1K2_K5U #65:K4_1AS1
PL_kumitate=[51,53,54,55,56,57,58,59,60,61,62,63,64,65]
#-----
#22:AB #23:BB #24:CB #70:RD #71:RD2 #72:D5_AH
#73:D7_3AS1 #74:D7_3AS12 #75:D7_1AS1P #76:D7_1AS1P2 #77:D7_1AS1S #78:D7_1AS1S2 #79:D7_1AS5
#80:D7_1AS5P2 #81:D7_1AS5S #82:D7_1AS5S2 #83:D7_2S6P #84:D7_2S6S #85:D7_AH1P #86:D7_AH1S #87:D7_AH
PL_gisou=[22,23,24,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87]
#-----
#99:その他
ACT_misc=[99]
#-----
#ブロックカテゴリの識別番号 data[i][11]
#1:S1 #2:AS #3:FS #4:S6 #5:L1 #6:D1 #7:AH
BLK_all=[1,2,3,4,5,6,7]
#-----
#外注の識別番号 data[i][12]
#1:外注 #2:内製
ORD_all=[1,0]
●プログラムI-3.1
#プログラムI-3.1a
#=======================================================================
#艤装工程計画アクティビティのidata1
#=======================================================================
w=[]
for i in data:
if (data[i][1] in ACT_gisou+PL_gisou) and (data[i][11] in BLK_all) and (data[i][12] in ORD_all):
w.append(i)
idata1=w&data.keys()
#-----
if 7 in BLK_all:
idata1=idata1-{\
'A11700','A11701','A11702','A11703','A11704','A11705','A11706',\
'A11710','A11711','A11712','A11713','A11714','A11715','A11716',\
'A11720','A11721','A11722','A11723','A11724','A11725','A11726','A11727','A11728','A11729'} #総組は場所さけ残して作業は除く
print(idata1)
#====
act1={}
for i in idata1:
j=i
while not (data[j][1] in [0]):
j=data[j][4][0]
act1[i]=usuki1.addActivity(data[i][0], duedate=data[j][3]+data[j][2], backward=True)
●プログラムI-3.1b
#=======================================================================
#艤装工程計画 先行制約
#=======================================================================
for i in idata1:
if data[i][1] in ACT_gisou:
for iw in[0,1,2,3,4]:
if data[i][4][iw] in idata1:
usuki1.addTemporal(act1[i],act1[data[i][4][iw]],tempType=CS[data[i][5][iw][0]], delay= int(data[i][5][iw][1]*2))
if data[i][1] in ["A02010","A02610","A03010","A03210","A04310","A09210",] and data[i][5][iw][0]==0: #外板
usuki1.addTemporal(act1[data[i][4][iw]],act1[i],tempType=CS[3], delay=-int(data[i][5][iw][1]*2))
#-----
for i in idata1:
if data[i][1] in PL_gisou:
for iw in [0]:
if data[i][4][iw] in idata1:
ii=data[i][4][iw]
usuki1.addTemporal(act1[i],act1[ii],tempType="CS")
usuki1.addTemporal(act1[ii],act1[i],tempType="SC")
for jj in idata1:
for iw in [0]:
if data[i][4][iw] in idata1:
if data[jj][4][iw]==i:
usuki1.addTemporal(act1[jj],act1[i],tempType="CS")
usuki1.addTemporal(act1[i],act1[jj],tempType="SC")
#-----搭載日の固定
for i in idata1:
if data[i][1] in [0,11]:
usuki1.addTemporal("source",act1[i],tempType="SS",delay= int(data[i][3]))
if data[i][1]==0:
usuki1.addTemporal(act1[i],"source",tempType="SS",delay=-int(data[i][3]))