求解プログラム

OptSeq

#rcpsp51a.py
from optseq import *
import math
prob=Model()
CS=["CS","CC","SS","SC"]
#=======================================================================
#リソースの定義(場所) 
#=======================================================================
#場所の名前と矩形サイズ [name,L=L2-L1+1,B=B2-B1+1]
R={
 1:["P01", 58, 13],\
 2:["P02", 58, 13],\
 3:["P03", 42, 16],\
 5:["P05", 52, 12],\
 6:["P06", 52, 13],\
}
#-----各場所の長さ方向線分[L1,L2]・幅方向線分[B1,B2]
P01=[ 1,0, R[1][1],0, R[1][2]]
P02=[ 2,0, R[2][1],0, R[2][2]]
P03=[ 3,0, R[3][1],0, R[3][2]]
P05=[ 5,0, R[5][1],0, R[5][2]]
P06=[ 6,0, R[6][1],0, R[6][2]]
#-----メッシュの使用可否
resPL={}
S={}
for id in R:
  resPL[id]=0
  S[id]=0
 #if not id in [2,3,4,5,6,11,13,14,15,16,17,18,19,20]:
 #if not id in [2,3,4,5,6,7,13]:      
  if not id in [2,3,5,6]:       
    for i in range(0,R[id][1]):
      for j in range(0,R[id][2]):        
        resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1}) 
        S[id]+=1
  if id==2:
    for i in range(0,R[id][1]):
      for j in range(0,R[id][2]):  
        if i in  range(0,15) and j in range(0,13):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):0})
        else:     
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
          S[id]+=1
  if id==3:
    for i in range(0,R[id][1]):
      for j in range(0,R[id][2]):  
        if i in  range(0,28) and j in range(0,2):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):0})
        elif i in  range(0,4) and j in range(2,15):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
        elif i in  range(0,46) and j in range(15,16):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
        else:     
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
          S[id]+=1
  if id==5:
    for i in range(0,R[id][1]):
      for j in range(0,R[id][2]):  
        if i in  range(0,13) and j in range(0,12):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):0})
        else:     
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
          S[id]+=1
  if id==6:
    for i in range(0,R[id][1]):
      for j in range(0,R[id][2]):  
        if i in  range(0,3) and j in range(0,13):
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):0})
        else:     
          resPL[id,i,j] =prob.addResource(R[id][0]+"[{0:02d}_{1:02d}]".format(i,j), capacity={(0,"inf"):1})
          S[id]+=1            
#=======================================================================
#データセット 
#=======================================================================
data_P12={
#id:["activity",[1:定盤],2:期間,3:開始,[4:L,4:B]],
1:["S01_B041S_FWFW",[P01,P02],11,45,[14,13]],
2:["S01_B041P_FWFW",[P01,P02],10,47,[11,12]],
3:["S01_B051S_FWFW",[P01,P02],11,48,[14,13]],
4:["S01_B051P_FWFW",[P01,P02],10,50,[11,13]],
5:["S01_B061S_FWFW",[P01,P02],11,51,[14,13]],
6:["S01_B061P_FWFW",[P01,P02],10,53,[11,13]],
7:["S01_B071S_FWFW",[P01,P02],11,56,[11,13]],
8:["S01_B071P_FWFW",[P01,P02],10,58,[10,11]],
9:["S01_B091S_FWFW",[P01,P02],11,59,[14,13]],
10:["S01_B091P_FWFW",[P01,P02],10,61,[11,13]],
11:["S01_B101S_FWFW",[P01,P02],11,62,[14,12]],
12:["S01_B101P_FWFW",[P01,P02],10,65,[14,9]],
13:["S01_B123C_FWFW",[[1,42,57,0,12]],13,58,[15,12]],
14:["S01_B184C_FW",[P01,P02],8,73,[17,9]],
15:["S01_B184H_FW",[P01,P02],6,68,[11,12]],
16:["S01_B392P_FWFW",[[1,46,58,0,13]],10,71,[12,13]],
17:["S01_B392S_FWFW",[[1,34,46,0,13]],10,73,[12,13]],
18:["S01_B432S_FWFW",[[2,45,55,0,13]],10,75,[10,13]],
19:["S01_B432P_FWFW",[[2,33,43,0,13]],10,77,[10,13]],
20:["S01_B444S_FW",[P01,P02],9,88,[10,12]],
21:["S01_B462P_FCW",[P01,P02],10,79,[9,13]],
22:["S01_B462S_FCW",[P01,P02],10,81,[9,13]],
23:["S01_B472P_FWFW",[P01,P02],10,82,[14,13]],
24:["S01_B472S_FWFW",[P01,P02],10,84,[14,13]],
25:["S01_B502P_FWFW",[P01,P02],9,85,[14,13]],
26:["S01_B502S_FWFW",[P01,P02],9,88,[14,13]],
27:["S01_B534S_FW",[P01,P02],8,92,[12,13]],
28:["S01_B544P_FW",[P01,P02],8,95,[12,13]],
29:["S01_B563H_FW",[P01,P02],3,75,[8,9]],
}
data_P03={
#id:["activity",[1:定盤],2:期間,3:開始,[4:L,4:B]],
30:["S01_B114C_FWFW",[P03],14,60,[12,13]],
31:["S01_B114H_FW",[P03],5,57,[14,6]],
32:["S01_B223D_FW",[P03],9,65,[9,13]],
33:["S01_B223C_FW",[P03],9,65,[14,9]],
34:["S01_B223C_W",[P03],3,75,[14,9]],
35:["S01_B384C_FWFW",[P03],16,75,[17,10]],
36:["S01_B563C_FW",[P03],6,77,[7,10]],
37:["S01_B573C_F",[P03],3,92,[15,11]],
38:["S01_B573C_FW",[P03],8,96,[15,11]],
}
data_P05={
#id:["activity",[1:定盤],2:期間,3:開始,[4:L,4:B]],
39:["S01_B153H_FW",[P05],5,60,[10,12]],
40:["S01_B223H_FW",[P05],4,62,[11,12]],
41:["S01_B293D_FW",[P05],8,68,[15,10]],
42:["S01_B293C_FW",[P05],6,70,[7,8]],
43:["S01_B293C_W",[P05],2,77,[7,8]],
44:["S01_B422P_FFW",[P05],9,75,[5,12]],
45:["S01_B422S_FFW",[P05],9,77,[5,12]],
46:["S01_B454P_FW",[P05],9,90,[10,12]],
47:["S01_B594C_FW",[P05],9,98,[21,7]],
48:["S01_B594H_FW",[P05],4,95,[8,8]],
49:["S01_B707D_FW",[P05],9,86,[24,12]],
}
data_P06={
#id:["activity",[1:定盤],2:期間,3:開始,[4:L,4:B]],
50:["S01_B165C_FWF",[P06],7,64,[13,12]],
51:["S01_B175C_FWF",[P06],7,66,[13,11]],
52:["S01_B195C_FWF",[P06],7,68,[13,13]],
53:["S01_B235C_FWF",[P06],7,71,[13,13]],
54:["S01_B245C_FWF",[P06],7,73,[13,13]],
55:["S01_B265C_FWF",[P06],7,75,[13,12]],
56:["S01_B275C_FWF",[P06],7,78,[13,11]],
57:["S01_B345C_FWF",[P06],7,80,[13,9]],
58:["S01_B375C_FWF",[P06],7,82,[14,12]],
59:["S01_B496P_FW",[P06],5,90,[20,11]],
60:["S01_B496S_FW",[P06],5,92,[20,11]],
61:["S01_B586P_FW",[P06],5,96,[20,12]],
62:["S01_B586S_FW",[P06],5,98,[20,12]],
63:["S01_B626P_FW",[P06],5,102,[20,12]],
64:["S01_B626S_FW",[P06],5,104,[20,12]],
65:["S01_B636P_FW",[P06],5,108,[20,12]],
66:["S01_B636S_FW",[P06],5,110,[20,12]],
67:["S01_B646P_FW",[P06],5,113,[20,12]],
68:["S01_B646S_FW",[P06],5,115,[20,12]],
}

data={}
data.update(data_P12)
data.update(data_P03) 
data.update(data_P05) 
data.update(data_P06)
OptSeq

idata=data_P12.keys()
# idata=data_P03.keys()
# idata=data_P05.keys()
# idata=data_P06.keys() 
OptSeq

#=======================================================================
#作業の定義
#=======================================================================
act={}
for i in idata:    
    act[i]=prob.addActivity(data[i][0])
#=======================================================================
#先行制約
#=======================================================================
#-----日程固定
for i in idata:  
    prob.addTemporal("source",act[i],tempType="SS",delay= data[i][3])   
    prob.addTemporal(act[i],"source",tempType="SS",delay=-data[i][3])    
# sys.exit()   
#=======================================================================
#資源制約(作業場所)      
#=======================================================================
mode={} 
for i in idata:  
    for no in range(len(data[i][1])):      
        no1=data[i][1][no][0];
        L=R[no1][1]; B=R[no1][2];
        L1=data[i][1][no][1]; L2=data[i][1][no][2];     
        B1=data[i][1][no][3]; B2=data[i][1][no][4];   
        l=math.floor(data[i][4][0]); b=math.floor(data[i][4][1]);           
        skipL=1; skipB=1;        
        for j in range(L1,L2-l+1,skipL): 
            for k in range(B1,B2-b+1,skipB):
                mode[i,no1,j,k]=Mode(\
         "mode[{0:02d}]_[{1:03d}][{2:03d}_{3:03d}][{4:03d}_{5:03d}]"\
                .format(i,no1,j,k,l,b),duration=data[i][2])
                for s in range(0,l):
                    for t in range(0,b):
                        mode[i,no1,j,k].addResource(resPL[no1,j+s,k+t],1)            
                act[i].addModes(mode[i,no1,j,k])
#=====モード制約
con={}
for i in idata:
    if i in [33,37,42]: 
        no1=data[i][1][no][0];
        L=R[no1][1]; B=R[no1][2];
        L1=data[i][1][no][1]; L2=data[i][1][no][2];     
        B1=data[i][1][no][3]; B2=data[i][1][no][4];   
        l=math.floor(data[i][4][0]); b=math.floor(data[i][4][1]);           
        skipL=1; skipB=1;       
        for j in range(L1,L2-l+1,skipL): 
            for k in range(B1,B2-b+1,skipB):   
                con[i,no1,j,k]=prob.addResource("constraint["+str(i)+"]_\
                    [{0:03d}][{1:03d}_{2:03d}][{3:03d}_{4:03d}]"\
                    .format(no1,j,k,l,b),rhs=0,direction="=")
                con[i,no1,j,k].addTerms(1,act[i],mode[i,no1,j,k])
                con[i,no1,j,k].addTerms(-1,act[i+1],mode[i+1,no1,j,k])  
#=======================================================================
#組立工程計画 問題の規模
#=======================================================================
A=[]
for a in prob.act: A.append(a.name) 
#print("アクティビティ:",A)  
N=len(prob.act)
print("アクティビティ総数(含待機数):",N)  
M=[]
for a in prob.act: M.append(len(a.modes)) 
#print("モード数:",M)  
print("平均モード数:",round(sum(M)/N))
P=math.ceil(math.log10(round(sum(M)/N)**N))
print("問題の規模: 10**",P)                        
#=======================================================================
#組立工程計画 問題求解
#=======================================================================
# prob.Params.Makespan=True
# prob.Params.Initial=False
prob.Params.TimeLimit=30
# prob.Params.Neighborhood=20
# prob.Params.RandomSeed=1
# prob.Params.OutputFlag=False
prob.optimize()
filename="rcpsp51.csv"
prob.writeExcel(filename) 
#=======================================================================
sys.exit()    
#eof
OptSeq

#rcpsp51b.py
# idata=data_P12.keys()
idata=data_P03.keys()
# idata=data_P05.keys()
# idata=data_P06.keys() 
OptSeq

#rcpsp51c.py
# idata=data_P12.keys()
# idata=data_P03.keys()
idata=data_P05.keys()
# idata=data_P06.keys() 
OptSeq

#rcpsp51d.py
# idata=data_P12.keys()
# idata=data_P03.keys()
# idata=data_P05.keys()
idata=data_P06.keys() 
OptSeq

#rcpsp51.py
idata_P12=data_P12.keys()
idata_P03=data_P03.keys()
idata_P05=data_P05.keys()
idata_P06=data_P06.keys() 
idata=idata_P12|idata_P03|idata_P05|idata_P06

準備

作業場所

P01:58Lx13B Q01:40Lx18B R01:4Lx14B
P02:58Lx13B Q02:50Lx18B R02:11Lx14B
P03:42Lx16B Q03:70Lx22B R03:4Lx14B
P04:26Lx43B Q04:40Lx14B R04:51Lx13B
P05:52Lx12B Q05:35Lx17B R05:26Lx18B
P06:52Lx13B Q06:40Lx15B R06:5Lx10B
P07:61Lx29B Q07:30Lx12B R07:6Lx29B
Q08:32Lx12B
B01:16Lx19B Q09:35Lx15B DOC:136Lx24B
B02:16Lx19B Q10:30Lx12B
B03:16Lx19B Q11:30Lx12B

ブロックリスト

B014C*:4Lx8B B184H : 11Lx12B B384C : 17Lx10B B552P*: 14Lx13B
B021S*:14Lx13B B195C : 13Lx13B B392P : 12Lx14B B552S*: 14Lx13B
B021P*:11Lx13B B208P : 7Lx13B B392S : 12Lx14B B563C : 7Lx10B
B031S*:14Lx13B B208S : 7Lx13B B408P : 7Lx13B B563H : 8Lx9B
B031P*:11Lx13B B218P : 7Lx13B B408S : 7Lx13B B573C : 15Lx11B
B041S :14Lx13B B218S : 7Lx13B B414P*: 12Lx12B B573H : 10Lx10B
B041P :11Lx12B B223C : 11Lx12B B414S*: 12Lx12B B586P : 20Lx12B
B051S :14Lx13B B223H : 11Lx12B B422P : 5Lx13B B586S : 20Lx12B
B051P :11Lx13B B223D : 9Lx13B B422S : 5Lx13B B594C : 21Lx7B
B061S :14Lx13B B235C : 13Lx13B B432S : 10Lx13B B594H : 19Lx4B
B061P :11Lx13B B245C : 13Lx13B B432P : 10Lx13B B602P*: 14Lx13B
B071S :13Lx11B B258P : 7Lx13B B444S : 10Lx12B B602S*: 14Lx13B
B071P :10Lx11B B258S : 7Lx13B B444H : 5Lx11B B613C*: 21Lx13B
B084P*:8Lx11B B265C : 13Lx11B B454P : 10Lx12B B626P : 20Lx12B
B084S*:8Lx8B B275C : 13Lx11B B454H : 5Lx11B B626S : 20Lx12B
B084C :19Lx9B B288P : 7Lx13B B462P : 13Lx9B B636P : 20Lx12B
B091S :14Lx13B B288S : 7Lx13B B462S : 13Lx9B B636S : 20Lx12B
B091P :11Lx13B B293C : 8Lx7B B472P : 14Lx13B B646P : 20Lx12B
B101S :14Lx12B B293D : 15Lx10B B472S : 14Lx13B B646S : 20Lx12B
B101P :14Lx9B B308P : 7Lx13B B484C*: 21Lx10B B657C*: 6Lx6B
B114C :13Lx13B B308S : 7Lx13B B496P : 20Lx11B B667C*: 6Lx10B
B114H :29Lx3B B318P : 7Lx13B B496S : 20Lx11B B677P*: 18Lx12B
B123C :15Lx12B B318S : 7Lx13B B502P : 14Lx13B B677S*: 18Lx12B
B134P*:12Lx11B B324P : 11Lx12B B502S : 14Lx13B B687C*: 3Lx7B
B134S*:11Lx12B B324S : 11Lx12B B514P*: 12Lx13B B697C*: 16Lx9B
B143C*:14Lx8B B333C*: 17Lx10B B514S*: 12Lx13B B707C*: 24Lx12B
B153C :7Lx10B B345C : 13Lx9B B522P*: 14Lx13B B707D : 24Lx14B
B153H :10Lx12B B358P : 7Lx13B B522S*: 14Lx13B B707E*: 15Lx9B
B153D :8Lx10B B358S : 7Lx13B B534S : 12Lx13B B717P*: 3Lx6B
B165C :13Lx12B B364P*: 10Lx11B B534H : 4Lx13B B717S*: 5Lx7B
B175C :13Lx11B B364S*: 10Lx11B B544P : 12Lx13B B727P*: 3Lx7B
B184C :17Lx9B B375C : 14Lx12B B544H : 4Lx13B B727S*: 3Lx7B

補遺4

VB

Sub Waritsuke()
  Worksheets("waritsuke").Activate
  ActiveSheet.DrawingObjects.Delete
  Dim Sheet1 As Variant
  Sheet1 = "rcpsp42"
  Dim time1 As Integer, time2 As Integer, sp As Integer
  time1 = 2: time2 = 10: sp = 7:
  Dim act As Variant, mode As Variant, ID As Integer, no As Integer
  Dim joban As Integer, sx As Integer, sy As Integer, tx As Integer
  Dim ty As Integer, start As Integer, completion As Integer
  Dim S As Range, Q As Shape
  For i = 2 To 14
    act = Worksheets(Sheet1).Cells(i, 1) 'MsgBox (act)
    act = Mid(act, 8, 3)
    mode = Worksheets(Sheet1).Cells(i, 2)
    ID = Len(mode)
    If ID = 21 Then
      sx = Val(Mid(mode, 9, 2))
      sy = Val(Mid(mode, 12, 2))
      tx = Val(Mid(mode, 16, 2))
      ty = Val(Mid(mode, 19, 2))
      start = Worksheets(Sheet1).Cells(i, 3) + 1
      completion = Worksheets(Sheet1).Cells(i, 5)
      For j = start - time1 To completion - time1
        Set S = Range(Cells(3 + sp * j + sx, 4 + 1 + sy), _
        Cells(2 + sp * j + sx + tx, 3 + 1 + sy + ty))
        Set Q = ActiveSheet.Shapes.AddShape(1, S.Left, S.Top, _
        S.Width, S.Height)
        Q.Select
        ic = i Mod 6
        Selection.Font.ColorIndex = 1
        If ic = 0 Then
          Q.Fill.ForeColor.RGB = RGB(255, 0, 0)  '赤
        ElseIf ic = 1 Then
          Q.Fill.ForeColor.RGB = RGB(0, 255, 0)  '緑
        ElseIf ic = 2 Then
          Q.Fill.ForeColor.RGB = RGB(0, 0, 255)  '青
          Selection.Font.ColorIndex = 2
        ElseIf ic = 3 Then
          Q.Fill.ForeColor.RGB = RGB(255, 255, 0) '黄
        ElseIf ic = 4 Then
          Q.Fill.ForeColor.RGB = RGB(0, 255, 255) 'シアン
        ElseIf ic = 5 Then
          Q.Fill.ForeColor.RGB = RGB(255, 0, 255) 'マジェンダ
        End If
        Selection.Text = act
        Selection.Font.Size = 7
      Next j
    End If
  Next i
End Sub

逐次計画の基礎

rcpsp43.py

OptSeq

#rcpsp43.py
from optseq import *
import math
#====データセット
#Key:["",期間,[後続]、員数,開始,完了],\
data={
"A01":["A01_3人",3,["A04","A06"],3,0,0],
"A02":["A02_1人",4,["A05","A07"],1,0,0],
"A03":["A03_1人",6,["A08","0"],1,0,0],
"A04":["A04_4人",4,["A05","A07"],4,0,0],
"A05":["A05_4人",5,["A08","0"],4,0,0],
"A06":["A06_4人",5,["A09","0"],4,0,0],
"A07":["A07_5人",4,["A10","0"],5,0,0],
"A08":["A08_2人",2,["A10","0"],2,0,0],
"A09":["A09_5人",2,["A10","0"],5,0,0],
"A10":["A10_3人",4,["0","0"],3,0,0],\
}
#====アクティビティ
prob=Model()
act={}
for i in data:
    act[i]=prob.addActivity(data[i][0])
#====先行制約
for i in data:
    for j in data[i][2]:
        if j!="0": prob.addTemporal(act[i],act[j])  
#====資源制約  
res=prob.addResource("Resource",capacity={(0,"inf"):10}) 
mode={}  
for i in data:
    mode[i]=Mode("M["+i+"][{0:02d}]".format(data[i][3]),
                                    duration=data[i][1])
    mode[i].addResource(res,requirement=data[i][3])
    act[i].addModes(mode[i])
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp43a.txt")
prob.writeExcel("rcpsp43a.csv")  
#=======================================================================
print("") 
for a in prob.act:
  mode_nam=a.selected.name
  i=a.name[0:3]
  data[i][4]=a.start
  data[i][5]=a.completion  
#-----
w1=[]; w2=[]; w3=[]; w4=[]; w5=[];
d1=5; d2=20; 
for i in data:
  start=data[i][4]
  stop=data[i][5]
  if stop < d1: w1.append(i)                  # 完了
  if start+1 <= d1 and d1 <= stop: w2.append(i) #仕掛
  if d1 < start+1  and stop < d2:  w3.append(i) #自由
  if start+1 <= d2 and d2 < stop: w4.append(i) #次のリスケにおける仕掛
  if d2 < start+1: w5.append(i)               #未着手
idata2a=w2;   #仕掛かり中のアクティビティ
idata2b=w3;   #仕掛かっていないアクティビティ 
idata2=w2+w3; #リスケすべきアクティビティ日
#====アクティビティ
prob2=Model()
act2={}
for i in idata2b:
    act2[i]=prob2.addActivity(data[i][0])
#====先行制約
for i in idata2b:
    for j in data[i][2]:
        if j!="0": prob2.addTemporal(act2[i],act2[j])
#----リスケ日以降
    prob2.addTemporal("source",act[i],tempType="SS",delay=d1)      
#====資源制約  
w={(0,3):5,(3,4):0,(4,6):1,(6,7):2,(7,8):6,(8,30):10} #Case1
w={(0,3):5,(3,4):0,(4,6):1,(6,7):2,(7,8):6,(8,30):8}  #Case2
res2=prob2.addResource("Resource2",capacity=w) 
mode2={}  
for i in idata2b:
    mode2[i]=Mode("M["+i+"][{0:02d}]".format(data[i][3]),
                                    duration=data[i][1])
    mode2[i].addResource(res2,requirement=data[i][3])
    act2[i].addModes(mode2[i])
#====求解
prob2.Params.Makespan=True
prob2.Params.TimeLimit=1
prob2.Params.OutputFlag=True
prob2.optimize()
prob2.write("rcpsp43b.txt")
prob2.writeExcel("rcpsp43b.csv")  
#=======================================================================
#eof

同時計画の基礎

rcpsp42.py

OptSeq

#rcpsp42.py
from optseq import *
import math
#====データセット
#i:[期間,納期,[l,b]]
data={
#key:["名前",ID,[後続],[B,L],時数]
"A11":["A11_BLK1_開始" ,1, ["A12"],[1,2],0],
"A12":["A12_BLK1_作業1",11,["A13"],[1,2],10],
"A13":["A13_BLK1_作業2",12,["A31"],[1,2],20],
"A21":["A21_BLK2_開始" ,1, ["A22"],[2,1],0],
"A22":["A22_BLK2_作業1",11,["A23"],[2,1],20],
"A23":["A23_BLK2_作業2",12,["A31"],[2,1],30],
"A31":["A31_BLK3_合体" ,2, ["A32","A33"],[2,2],0],
"A32":["A32_BLK3_作業3",13,["A41"],[2,2],5],
"A33":["A33_BLK3_作業4",14,["A41"],[2,2],5],
"A41":["A41_BLK3_納品" ,0, ["0"  ],[2,2],0],
}    
#=====アクティビティ
prob=Model()
act={}
for i in data:
   #act[i]=prob.addActivity(data[i][0])
    act[i]=prob.addActivity(name=data[i][0],duedate=10,backward=True)    
#====先行制約
for i in data:
    for j in data[i][2]:
        if j!="0": prob.addTemporal(act[i],act[j])      
#----納期日の固定
for i in data:
    if data[i][2][0]=="0":
        prob.addTemporal("source",act[i],tempType="CC",delay= 10)   
        prob.addTemporal(act[i],"source",tempType="CC",delay=-10)      
#====資源制約         
res1=prob.addResource("worker",capacity={(0,"inf"):5}) 
mode={}  
for i in data:
    if data[i][1] in [11,12,13,14]:
        period=math.ceil(data[i][4]/8) #1人で何日かかるか
        mode[i]=Mode("M["+i+"]_[{0:02d}]".format(period),duration=period)
        mode[i].addResource(res1,requirement=1)
        mode[i].addParallel(start=1,finish=period,maxparallel=2)
        act[i].addModes(mode[i])
    else:
        mode[i]=Mode("M["+i+"]",duration=1)
        act[i].addModes(mode[i])   
#----場所取り
res={}
for i in range(0,4):
    for j in range(0,4):  
        if i==1 and j==2 :
            res[i,j]=prob.addResource(\
                "place[{0:02d}_{1:02d}]".format(i,j),\
                capacity={(0,"inf"):0})            
        else:     
            res[i,j]=prob.addResource(\
                "place[{0:02d}_{1:02d}]".format(i,j),\
                capacity={(0,"inf"):1})   
#----
d_act={}
d_mode={}
ww={'A11':'A13', 'A21':'A23', 'A31':'A33'}    
L=5; B=5; L1=0; L2=4; B1=0; B2=4; skipL=1; skipB=1; 
for i in data:  
    if data[i][1] in [1,2]:
        d_act[i]=prob.addActivity("場所_for_"+i)  
        l=data[i][3][0]; b=data[i][3][1];    
        for j in range(L1,L2-l+1,skipL): 
            for k in range(B1,B2-b+1,skipB):
                d_mode[i,j,k]=Mode(\
                    "M["+i+"]_[{0:02d}_{1:02d}][{2:02d}_{3:02d}]"\
                    .format(j,k,l,b))
                d_mode[i,j,k].addBreak(0,'inf')
                for s in range(0,l):
                    for t in range(0,b):
                        d_mode[i,j,k].addResource(res[j+s,k+t],1,"break")
                d_act[i].addModes(d_mode[i,j,k])
        prob.addTemporal(act[i],d_act[i],tempType="SS")
        prob.addTemporal(d_act[i],act[i],tempType="SS")
        ii=ww[i]              
        prob.addTemporal(d_act[i],act[ii],tempType="CC")
        prob.addTemporal(act[ii],d_act[i],tempType="CC")  
#====問題の規模:      
A=[]
for a in prob.act: A.append(a.name) 
print("アクティビティ:",A)  
N=len(prob.act)
print("アクティビティ総数(含待機数):",N)  
M=[]
for a in prob.act: M.append(len(a.modes)) 
print("モード数:",M)  
print("平均モード数:",round(sum(M)/N))
P=math.ceil(math.log10(round(sum(M)/N)**N))
print("問題の規模: 10**",P)       
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp42.txt")
prob.writeExcel("rcpsp42.csv")
sys.exit()   

定盤計画の基礎

rcpsp41.py

OptSeq

#rcpsp41.py
from optseq import *
import math
#====データセット
#i:[名前,期間,[l,b]]
data={
1:["BLK1",1,[2,2]],
2:["BLK2",1,[1,2]],
3:["BLK3",1,[2,1]]
}    
#=====アクティビティ
prob=Model()
act={}
for i in data.keys():
    act[i]=prob.addActivity(data[i][0])
#====資源制約  
res={}
for i in range(0,4):
    for j in range(0,4):  
        if i==1 and j==2 :
            res[i,j]=prob.addResource(\
                "place[{0:02d}_{1:02d}]".format(i,j),\
                capacity={(0,"inf"):0})            
        else:     
            res[i,j]=prob.addResource(\
                "place[{0:02d}_{1:02d}]".format(i,j),\
                capacity={(0,"inf"):1})  
#-----
mode={}  
L=5; B=5; L1=0; L2=4; B1=0; B2=4;
for i in data:
    l=data[i][2][0]; b=data[i][2][1];
    for j in range(L1,L2-l+1):
        for k in range(B1,B2-b+1):         
             mode[i,j,k]=Mode(\
                 "mode[{0:02d}]_[{1:02d}_{2:02d}][{3:02d}_{4:02d}]"\
                 .format(i,j,k,l,b),duration=data[i][1])
             for s in range(0,l):
                 for t in range(0,b):
                     mode[i,j,k].addResource(res[j+s,k+t],1)         
             act[i].addModes(mode[i,j,k])    
#====問題の規模:      
A=[]
for a in prob.act: A.append(a.name) 
print("アクティビティ:",A)  
N=len(prob.act)
print("アクティビティ総数(含待機数):",N)  
M=[]
for a in prob.act: M.append(len(a.modes)) 
print("モード数:",M)  
print("平均モード数:",round(sum(M)/N))
P=math.ceil(math.log10(round(sum(M)/N)**N))
print("問題の規模: 10**",P)       
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp41.txt")
prob.writeExcel("rcpsp41.csv")

仮想アクティビティ

rcpsp34.py

OptSeq

#rcpsp34.py
from optseq import *
#====データセット 
#i:[名前,期間,後続,資源]
data={
 1:["A01",5,[2],1],
 2:["A02",1,[0],0]
}
date10=10 #納期日
#====アクティビティ
prob=Model()
act={}
for i in data:
    act[i]=prob.addActivity(name=data[i][0])    
#====先行制約
for i in data.keys():
    for j in data[i][2]:
        if j>0: 
            prob.addTemporal(act[i],act[j],tempType="CS",delay=0)            
            prob.addTemporal(act[j],act[i],tempType="SC",delay=0) #重要             
#----A02固定
i==2
prob.addTemporal("source",act[i],tempType="CC",delay= date10)   
prob.addTemporal(act[i],"source",tempType="CC",delay=-date10)  
#====資源制約  
res=prob.addResource("place",capacity={(0,"inf"):1}) 
mode={}  
for i in data:
    mode[i]=Mode("M{0:02d}".format(i),duration=data[i][1])
    mode[i].addResource(res,requirement=data[i][3])
    if i==1:
        mode[i].addBreak(0,'inf')           #Case1
       #mode[i].addBreak(0,'inf',maxtime=2) #Case2
       #mode[i].addBreak(0,0)               #Case3
        mode[i].addResource(res,1,'break')  
    act[i].addModes(mode[i])
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp34.txt")
prob.writeExcel("rcpsp34.csv")

rcpsp35.py

OptSeq

#rcpsp35.py
from optseq import *
import math
#====データセット 
#i:[名前、後続、時数]
data={
 1:["搬入", [2],1],
 2:["作業1",[3],10],
 3:["作業2",[4],20],
 4:["搬出", [0],1],
}
#====アクティビティ
prob=Model()
act={}
for i in data:
    act[i]=prob.addActivity(name=data[i][0])
#====先行制約
for i in data:
    for j in data[i][1]:
        if j>0: prob.addTemporal(act[i],act[j])  
#----搬入日・搬出日の固定
prob.addTemporal("source",act[1],tempType="CC",delay= 1)   
prob.addTemporal(act[1],"source",tempType="CC",delay=-1)   
# prob.addTemporal("source",act[4],tempType="CC",delay= 10)   
# prob.addTemporal(act[4],"source",tempType="CC",delay=-10)      
#====資源制約  
res=prob.addResource("worker",capacity={(0,"inf"):5}) 
mode={}  
for i in data:
  if i in [2,3]:
    period=math.ceil(data[i][2]/8) #1人で何日かかるか
    mode[i]=Mode("M{0:02d}_{1:02d}".format(i,period),duration=period)
    mode[i].addResource(res,requirement=1)
    mode[i].addParallel(start=1,finish=period,maxparallel=2)
    act[i].addModes(mode[i])
  else:
    mode[i]=Mode("M{0:02d}".format(i),duration=1)
    act[i].addModes(mode[i])
#----場所取り
d_act={}
d_act=prob.addActivity("場所取り")
place=prob.addResource("place",capacity={(0,"inf"):1}) 
d_mode={}      
d_mode=Mode("M01_")
d_mode.addBreak(0,'inf')
d_mode.addResource(place,1,"break")
d_act.addModes(d_mode)                    
prob.addTemporal(act[1],d_act,tempType="CS")
prob.addTemporal(d_act,act[1],tempType="SC") 
prob.addTemporal(d_act,act[4],tempType="CS")
prob.addTemporal(act[4],d_act,tempType="SC") 
#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.optimize()
prob.write("rcpsp35.txt")
prob.writeExcel("rcpsp35.csv")

小作業の並列化

rcpsp33.py

OptSeq

#rcpsp33.py 
 :
#====資源制約  
res=prob.addResource("Resource",capacity={(0,"inf"):10}) 
mode={}  
for i in data:
    period=data[i][1]*data[i][3] #1人で何日かかるか
    mode[i]=Mode("M{0:02d}_{1:02d}".format(i,period),duration=period)
    mode[i].addResource(res,requirement=1)
    mode[i].addParallel(start=1,finish=period,maxparallel=10)
    act[i].addModes(mode[i])  

RCPSP求解プログラムの枠組み

rcpsp30.py

OptSeq

#rcpsp30.py
from optseq import *
data=["A01",5,10] #[名前,期間,納期]
prob=Model()
act=prob.addActivity(name=data[0])
#act=prob.addActivity(name=data[0],duedate=data[2]-1,backward=True)
mode=Mode("Mode",duration=data[1])
act.addModes(mode)
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp30.txt")

rcpsp31.py

OptSeq

#rcpsp31.py
from optseq import *
#====データセット 
#i:[名前,期間,後続,資源]
data={
 1:["A01",5,[2],1],
 2:["A02",1,[0],0]
}
date10=10 #納期日
OptSeq

#====アクティビティ
prob=Model()
act={}
for i in data:
   #act[i]=prob.addActivity(name=data[i][0])   
    act[i]=prob.addActivity(name=data[i][0],duedate=date10,backward=True)  
OptSeq

#====先行制約
for i in data:
    for j in data[i][2]:
        if j>0: prob.addTemporal(act[i],act[j]) 
#----A02固定
i==2
prob.addTemporal("source",act[i],tempType="CC",delay= date10)   
prob.addTemporal(act[i],"source",tempType="CC",delay=-date10)     
OptSeq

#====資源制約  
res=prob.addResource("worker",capacity={(0,"inf"):1}) 
mode={}  
for i in data:
    mode[i]=Mode("M{0:02d}".format(i),duration=data[i][1])
    mode[i].addResource(res,requirement=data[i][3])
    act[i].addModes(mode[i])   
OptSeq

#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp31.txt") 

rcpsp32.py

OptSeq

#rcpsp32.py
from optseq import *
#====データセット
#i:[名前,期間,後続,資源]
data={
 1:["A01",3,[4,6],3],
 2:["A02",4,[5,7],1],
 3:["A03",6,[8]  ,1],
 4:["A04",4,[5,7],4],
 5:["A05",5,[8]  ,4],
 6:["A06",5,[9]  ,4],
 7:["A07",4,[10] ,5],
 8:["A08",2,[10] ,2],
 9:["A09",2,[10] ,5],
10:["A10",5,[0]  ,3],
}
OptSeq

#====アクティビティ
prob=Model()
act={}
for i in data:
    act[i]=prob.addActivity(data[i][0])
OptSeq

#====先行制約
for i in data:
    for j in data[i][2]:
        if j>0: prob.addTemporal(act[i],act[j])  
OptSeq

#====資源制約  
res=prob.addResource("Resource",capacity={(0,"inf"):10}) 
mode={}  
for i in data:
    mode[i]=Mode("M{0:02d}_{1:02d}".format(i,data[i][3]),
                                    duration=data[i][1])
    mode[i].addResource(res,requirement=data[i][3])
    act[i].addModes(mode[i])
OptSeq

#====求解
prob.Params.Makespan=True
prob.Params.TimeLimit=1
prob.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp32.txt")
prob.writeExcel("rcpsp32.csv")