同時計画の基礎

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