仮想アクティビティ

rcpsp34.py
cace 1


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
034
035
036
037
038
039
040
041
042
043

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

これを実行すると次を得ます。
【rcpsp34.txt】


001
002
003
004
005
006
007
008
009
010

  activity    mode   duration  1 2 3 4 5 6 7 8 910
------------------------------------------------------------
   A01       M01        5     ==========........  
   A02       M02        1                       ==
------------------------------------------------------------
   resource usage/capacity     
------------------------------------------------------------
            place              1 1 1 1 1 1 1 1 1 0
                               1 1 1 1 1 1 1 1 1 1
------------------------------------------------------------

cace 2


032
033
034
035

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

これを実行すると次を得ます。
【rcpsp34.txt】


001
002
003
004
005
006
007
008
009
010

  activity    mode   duration  1 2 3 4 5 6 7 8 910
------------------------------------------------------------
   A01       M01        5     ========....==....  
   A02       M02        1                       ==
------------------------------------------------------------
   resource usage/capacity     
------------------------------------------------------------
            place              1 1 1 1 1 1 1 1 1 0
                               1 1 1 1 1 1 1 1 1 1
------------------------------------------------------------

cace 3


032
033
034
035

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

これを実行すると次を得ます。
【rcpsp34.txt】


001
002
003
004
005
006
007
008
009
010

  activity    mode   duration  1 2 3 4 5 6 7 8 910
------------------------------------------------------------
   A01       M01        5             ==========  
   A02       M02        1                       ==
------------------------------------------------------------
   resource usage/capacity     
------------------------------------------------------------
            place              0 0 0 0 1 1 1 1 1 0
                               1 1 1 1 1 1 1 1 1 1
------------------------------------------------------------

rcpsp35.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
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058

#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.Params.OutputFlag=True
prob.optimize()
prob.write("rcpsp35.txt")
prob.writeExcel("rcpsp35.csv")

場所取りを行う仮想アクティビティdactは、前後の搬入作業act[1]、搬出作業act[4]と「隙間なく」連結されています。これは不等式

C(act[1])+0\le S(dact)\ \Leftrightarrow\ C(act[1])\le S(dact)
S(dact)-0\le C(act[1])\ \Leftrightarrow\ S(dact)\le C(act[1])

C(dact)+0\le S(act[4])\ \Leftrightarrow\ C(dact)\le S(act[4])
S(act[4])-0\le C(dact)\ \Leftrightarrow\ S(act[4])\le C(dact)

が成り立つ、すなわち

C(act[1])=S(dact)
C(dact)=S(act[4])

を要求しているからです。

これを実行すると次を得ます。
【rcpsp35.txt】


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016

  activity    mode   duration 12345
------------------------------------
   作業1     M02_02     2     *2   
   作業2     M03_03     3     *2= 
   場所取り   M01_       0      ... 
   搬入       M01        1     =    
   搬出       M04        1         =
------------------------------------
   resource usage/capacity     
------------------------------------
            place             01110
                              11111
------------------------------------
            worker            02210
                              55555
------------------------------------

いま、次のように24行と25行のコメントを外し、搬出作業日を固定します。


021
022
023
024
025

#----搬入日・搬出日の固定
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)    

これを実行すると次を得ます。
【rcpsp35.txt】


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016

  activity    mode   duration  1 2 3 4 5 6 7 8 910
------------------------------------------------------------
   作業1      M02_02     2      *2                
   作業2      M03_03     3        *2==            
   場所取り    M01_       0     ................  
   搬入        M01        1   ==                  
   搬出        M04        1                     ==
------------------------------------------------------------
   resource usage/capacity     
------------------------------------------------------------
            place              0 1 1 1 1 1 1 1 1 0
                               1 1 1 1 1 1 1 1 1 1
------------------------------------------------------------
            worker             0 2 2 1 0 0 0 0 0 0
                               5 5 5 5 5 5 5 5 5 5
------------------------------------------------------------