同時計画の基礎

rcpsp42.py


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033

#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)  

034
035
003
036
037
038
039
040
041
042
043
044
045
    
#====資源制約         
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])   

014
015
016
017
018
019


020
021


022
023
024
025
026
027
028
029
030
031
032
033


034
035
036
037
038
039
040
041
042
043
  
#----場所取り
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")

044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
062

#====問題の規模:      
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()   

【rcpsp42.csv】