Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
dream
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
dream
Commits
a6618f51
Commit
a6618f51
authored
May 27, 2014
by
Ioannis Papagiannopoulos
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first changes, topology09 running
parent
f9392dab
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
231 additions
and
179 deletions
+231
-179
dream/simulation/CoreObject.py
dream/simulation/CoreObject.py
+55
-42
dream/simulation/Exit.py
dream/simulation/Exit.py
+9
-7
dream/simulation/LineGenerationJSON.py
dream/simulation/LineGenerationJSON.py
+18
-11
dream/simulation/Machine.py
dream/simulation/Machine.py
+109
-88
dream/simulation/Source.py
dream/simulation/Source.py
+40
-31
No files found.
dream/simulation/CoreObject.py
View file @
a6618f51
...
...
@@ -25,15 +25,18 @@ Created on 12 Jul 2012
Class that acts as an abstract. It should have no instances. All the core-objects should inherit from it
'''
from
SimPy.Simulation
import
Process
,
Resource
,
now
,
SimEvent
,
waitevent
# from SimPy.Simulation import Process, Resource, now, SimEvent, waitevent
import
simpy
# ===========================================================================
# the core object
# ===========================================================================
class
CoreObject
(
Process
):
class
CoreObject
(
object
):
def
__init__
(
self
,
id
,
name
,
**
kw
):
Process
.
__init__
(
self
)
from
Globals
import
G
self
.
env
=
G
.
env
# Process.__init__(self)
self
.
id
=
id
self
.
objName
=
name
# lists that hold the previous and next objects in the flow
...
...
@@ -54,14 +57,18 @@ class CoreObject(Process):
self
.
interruptCause
=
None
self
.
gatherWipStat
=
False
# signalizing an event that activates the generator
self
.
isRequested
=
SimEvent
(
'isRequested'
)
self
.
canDispose
=
SimEvent
(
'canDispose'
)
self
.
interruptionEnd
=
SimEvent
(
'interruptionEnd'
)
self
.
interruptionStart
=
SimEvent
(
'interruptionStart'
)
# self.isRequested=SimEvent('isRequested')
self
.
isRequested
=
self
.
env
.
event
()
# self.canDispose=SimEvent('canDispose')
self
.
canDispose
=
self
.
env
.
event
()
# self.interruptionEnd=SimEvent('interruptionEnd')
self
.
interruptionEnd
=
self
.
env
.
event
()
# self.interruptionStart=SimEvent('interruptionStart')
self
.
interruptionStart
=
self
.
env
.
event
()
def
initialize
(
self
):
# XXX why call super.__init__ outside of __init__ ?
Process
.
__init__
(
self
)
#
Process.__init__(self)
self
.
Up
=
True
#Boolean that shows if the machine is in failure ("Down") or not ("up")
self
.
onShift
=
True
self
.
currentEntity
=
None
...
...
@@ -133,10 +140,14 @@ class CoreObject(Process):
# TODO, this should be also updated in Globals.setWIP (in case we have initial wip)
self
.
wipStatList
=
[[
0
,
0
]]
# signalizing an event that activates the generator
self
.
isRequested
=
SimEvent
(
'isRequested'
)
self
.
canDispose
=
SimEvent
(
'canDispose'
)
self
.
interruptionEnd
=
SimEvent
(
'interruptionEnd'
)
self
.
interruptionStart
=
SimEvent
(
'interruptionStart'
)
# self.isRequested=SimEvent('isRequested')
self
.
isRequested
=
self
.
env
.
event
()
# self.canDispose=SimEvent('canDispose')
self
.
canDispose
=
self
.
env
.
event
()
# self.interruptionEnd=SimEvent('interruptionEnd')
self
.
interruptionEnd
=
self
.
env
.
event
()
# self.interruptionStart=SimEvent('interruptionStart')
self
.
interruptionStart
=
self
.
env
.
event
()
# =======================================================================
# the main process of the core object
...
...
@@ -167,7 +178,7 @@ class CoreObject(Process):
def
removeEntity
(
self
,
entity
=
None
):
self
.
addBlockage
()
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
activeObjectQueue
.
remove
(
entity
)
#remove the Entity from the queue
if
self
.
receiver
:
self
.
receiver
.
appendEntity
(
entity
)
...
...
@@ -176,11 +187,11 @@ class CoreObject(Process):
self
.
downTimeInTryingToReleaseCurrentEntity
=
0
self
.
offShiftTimeTryingToReleaseCurrentEntity
=
0
self
.
timeLastEntityLeft
=
now
()
self
.
timeLastEntityLeft
=
self
.
env
.
now
self
.
outputTrace
(
entity
.
name
,
"released "
+
self
.
objName
)
# update wipStatList
if
self
.
gatherWipStat
:
self
.
wipStatList
.
append
([
now
()
,
len
(
activeObjectQueue
)])
self
.
wipStatList
.
append
([
self
.
env
.
now
,
len
(
activeObjectQueue
)])
return
entity
#===========================================================================
...
...
@@ -188,7 +199,7 @@ class CoreObject(Process):
# this method is created to be overridden by the Assembly class in its getEntity where Frames are loaded
#===========================================================================
def
appendEntity
(
self
,
entity
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
activeObjectQueue
.
append
(
entity
)
# =======================================================================
...
...
@@ -205,11 +216,11 @@ class CoreObject(Process):
# each time an Entity is removed
# =======================================================================
def
addBlockage
(
self
):
self
.
totalTimeInCurrentEntity
=
now
()
-
self
.
timeLastEntityEntered
self
.
totalTimeInCurrentEntity
=
self
.
env
.
now
-
self
.
timeLastEntityEntered
self
.
totalTimeWaitingForOperator
+=
self
.
operatorWaitTimeCurrentEntity
if
self
.
timeLastEntityEnded
<
self
.
timeLastShiftStarted
:
self
.
offShiftTimeTryingToReleaseCurrentEntity
=
self
.
timeLastShiftStarted
-
self
.
timeLastShiftEnded
blockage
=
now
()
-
(
self
.
timeLastEntityEnded
+
self
.
downTimeInTryingToReleaseCurrentEntity
+
self
.
offShiftTimeTryingToReleaseCurrentEntity
)
blockage
=
self
.
env
.
now
-
(
self
.
timeLastEntityEnded
+
self
.
downTimeInTryingToReleaseCurrentEntity
+
self
.
offShiftTimeTryingToReleaseCurrentEntity
)
self
.
totalBlockageTime
+=
blockage
# =======================================================================
...
...
@@ -219,12 +230,12 @@ class CoreObject(Process):
# get active object and its queue, as well as the active (to be) entity
#(after the sorting of the entities in the queue of the giver object)
# activeObject=self.getActiveObject()
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
# get giver object, its queue, and sort the entities according to this object priorities
giverObject
=
self
.
giver
giverObject
.
sortEntities
()
#sort the Entities of the giver
#according to the scheduling rule if applied
giverObjectQueue
=
giverObject
.
Res
.
activeQ
giverObjectQueue
=
giverObject
.
Res
.
users
# if the giverObject is blocked then unBlock it
if
giverObject
.
exitIsAssignedTo
():
giverObject
.
unAssignExit
()
...
...
@@ -242,10 +253,10 @@ class CoreObject(Process):
#append the time to schedule so that it can be read in the result
#remember that every entity has it's schedule which is supposed to be updated every time
# he entity enters a new object
activeEntity
.
schedule
.
append
([
self
,
now
()
])
activeEntity
.
schedule
.
append
([
self
,
self
.
env
.
now
])
#update variables
activeEntity
.
currentStation
=
self
self
.
timeLastEntityEntered
=
now
()
self
.
timeLastEntityEntered
=
self
.
env
.
now
self
.
nameLastEntityEntered
=
activeEntity
.
name
# this holds the name of the last entity that got into Machine
self
.
downTimeProcessingCurrentEntity
=
0
# update the next list of the object
...
...
@@ -265,7 +276,7 @@ class CoreObject(Process):
# and if preemption is required
#===========================================================================
def
preemptReceiver
(
self
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
# find a critical order if any
critical
=
False
...
...
@@ -296,13 +307,13 @@ class CoreObject(Process):
# if the obtained Entity is critical and the receiver is preemptive and not operated
# in the case that the receiver is operated the preemption is performed by the operators
# if the receiver is not Up then no preemption will be performed
if
not
receiverOperated
and
len
(
receiver
.
Res
.
activeQ
)
>
0
:
if
not
receiverOperated
and
len
(
receiver
.
Res
.
users
)
>
0
:
#if the receiver does not hold an Entity that is also critical
if
not
receiver
.
Res
.
activeQ
[
0
].
isCritical
:
if
not
receiver
.
Res
.
users
[
0
].
isCritical
:
receiver
.
shouldPreempt
=
True
# self.printTrace(self.id, preempt=receiver.id)
receiver
.
preempt
()
receiver
.
timeLastEntityEnded
=
now
()
#required to count blockage correctly in the preemptied station
receiver
.
timeLastEntityEnded
=
self
.
env
.
now
#required to count blockage correctly in the preemptied station
# sort so that the critical entity is placed in front
activeObjectQueue
.
sort
(
key
=
lambda
x
:
x
==
activeEntity
,
reverse
=
True
)
# if there is a critical entity and the possible receivers are operated then signal the Router
...
...
@@ -311,7 +322,7 @@ class CoreObject(Process):
activeObjectQueue
.
sort
(
key
=
lambda
x
:
x
==
activeEntity
,
reverse
=
True
)
# update wipStatList
if
self
.
gatherWipStat
:
self
.
wipStatList
.
append
([
now
()
,
len
(
activeObjectQueue
)])
self
.
wipStatList
.
append
([
self
.
env
.
now
,
len
(
activeObjectQueue
)])
#===========================================================================
...
...
@@ -364,7 +375,7 @@ class CoreObject(Process):
# self.printTrace(self.id, signalReceiver=self.receiver.id)
# assign the entry of the receiver
self
.
receiver
.
assignEntryTo
()
self
.
receiver
.
isRequested
.
s
ignal
(
self
)
self
.
receiver
.
isRequested
.
s
ucceed
(
self
)
return
True
# if no receiver can accept then try to preempt a receive if the stations holds a critical order
self
.
preemptReceiver
()
...
...
@@ -379,8 +390,9 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting
=
0
# dummy variable counting the time a successor is waiting
receiver
=
None
from
Globals
import
G
for
object
in
candidates
:
timeWaiting
=
now
()
-
object
.
timeLastEntityLeft
# the time it has been waiting is updated and stored in dummy variable timeWaiting
timeWaiting
=
G
.
env
.
now
-
object
.
timeLastEntityLeft
# the time it has been waiting is updated and stored in dummy variable timeWaiting
if
(
timeWaiting
>
maxTimeWaiting
or
maxTimeWaiting
==
0
):
# if the timeWaiting is the maximum among the ones of the successors
maxTimeWaiting
=
timeWaiting
receiver
=
object
# set the receiver as the longest waiting possible receiver
...
...
@@ -394,13 +406,13 @@ class CoreObject(Process):
# if an operator is not assigned to the receiver then do not signal the receiver but the Router
try
:
if
not
receiver
.
assignedOperator
or
\
(
receiver
.
isPreemptive
and
len
(
receiver
.
Res
.
activeQ
)
>
0
):
(
receiver
.
isPreemptive
and
len
(
receiver
.
Res
.
users
)
>
0
):
if
receiver
.
isLoadRequested
():
from
Globals
import
G
if
not
G
.
Router
.
invoked
:
# self.printTrace(self.id, signal='router')
G
.
Router
.
invoked
=
True
G
.
Router
.
isCalled
.
s
ignal
(
now
()
)
G
.
Router
.
isCalled
.
s
ucceed
(
self
.
env
.
now
)
return
True
else
:
return
False
...
...
@@ -454,7 +466,7 @@ class CoreObject(Process):
self
.
giver
=
giver
self
.
giver
.
receiver
=
self
# self.printTrace(self.id, signalGiver=self.giver.id)
self
.
giver
.
canDispose
.
s
ignal
(
self
)
self
.
giver
.
canDispose
.
s
ucceed
(
self
)
return
True
return
False
...
...
@@ -467,12 +479,13 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting
=
0
# dummy variable counting the time a predecessor is blocked
giver
=
None
from
Globals
import
G
# loop through the possible givers to see which have to dispose and which is the one blocked for longer
for
object
in
candidates
:
if
(
object
.
downTimeInTryingToReleaseCurrentEntity
>
0
):
# and the predecessor has been down while trying to give away the Entity
timeWaiting
=
now
()
-
object
.
timeLastFailureEnded
# the timeWaiting dummy variable counts the time end of the last failure of the giver object
timeWaiting
=
self
.
env
.
now
-
object
.
timeLastFailureEnded
# the timeWaiting dummy variable counts the time end of the last failure of the giver object
else
:
timeWaiting
=
now
()
-
object
.
timeLastEntityEnded
# in any other case, it holds the time since the end of the Entity processing
timeWaiting
=
G
.
env
.
now
-
object
.
timeLastEntityEnded
# in any other case, it holds the time since the end of the Entity processing
#if more than one predecessor have to dispose take the part from the one that is blocked longer
if
(
timeWaiting
>=
maxTimeWaiting
):
giver
=
object
# the object to deliver the Entity to the activeObject is set to the ith member of the previous list
...
...
@@ -493,7 +506,7 @@ class CoreObject(Process):
from
Globals
import
G
if
(
G
.
trace
==
"Yes"
):
#output only if the user has selected to
#handle the 3 columns
G
.
traceSheet
.
write
(
G
.
traceIndex
,
0
,
str
(
now
()
))
G
.
traceSheet
.
write
(
G
.
traceIndex
,
0
,
str
(
self
.
env
.
now
))
G
.
traceSheet
.
write
(
G
.
traceIndex
,
1
,
entityName
)
G
.
traceSheet
.
write
(
G
.
traceIndex
,
2
,
message
)
G
.
traceIndex
+=
1
#increment the row
...
...
@@ -509,7 +522,7 @@ class CoreObject(Process):
assert
len
(
kw
)
==
1
,
'only one phrase per printTrace supported for the moment'
from
Globals
import
G
import
Globals
time
=
now
()
time
=
self
.
env
.
now
charLimit
=
60
remainingChar
=
charLimit
-
len
(
entity
)
-
len
(
str
(
time
))
if
(
G
.
console
==
'Yes'
):
...
...
@@ -549,7 +562,7 @@ class CoreObject(Process):
# checks if the Object can dispose an entity to the following object
# =======================================================================
def
haveToDispose
(
self
,
callerObject
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
return
len
(
activeObjectQueue
)
>
0
# =======================================================================
...
...
@@ -581,7 +594,7 @@ class CoreObject(Process):
# get the activeQ of the active object.
# =======================================================================
def
getActiveObjectQueue
(
self
):
return
self
.
Res
.
activeQ
return
self
.
Res
.
users
# =======================================================================
# get the giver object in a getEntity transaction.
...
...
@@ -593,7 +606,7 @@ class CoreObject(Process):
# get the giver object queue in a getEntity transaction.
# =======================================================================
def
getGiverObjectQueue
(
self
):
return
self
.
giver
.
Res
.
activeQ
return
self
.
giver
.
Res
.
users
# =======================================================================
# get the receiver object in a removeEntity transaction.
...
...
@@ -605,7 +618,7 @@ class CoreObject(Process):
# get the receiver object queue in a removeEntity transaction.
# =======================================================================
def
getReceiverObjectQueue
(
self
):
return
self
.
receiver
.
Res
.
activeQ
return
self
.
receiver
.
Res
.
users
# =======================================================================
# calculates the processing time
...
...
@@ -674,7 +687,7 @@ class CoreObject(Process):
# false if object holds entities in its queue
#===========================================================================
def
activeQueueIsEmpty
(
self
):
return
len
(
self
.
Res
.
activeQ
)
==
0
return
len
(
self
.
Res
.
users
)
==
0
# =======================================================================
# actions to be carried out when the processing of an Entity ends
...
...
@@ -686,5 +699,5 @@ class CoreObject(Process):
# check if an entity is in the internal Queue of the object
#===========================================================================
def
isInActiveQueue
(
self
,
entity
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
return
any
(
x
==
entity
for
x
in
activeObjectQueue
)
dream/simulation/Exit.py
View file @
a6618f51
...
...
@@ -25,7 +25,8 @@ Created on 6 Feb 2013
models the exit of the model
'''
from
SimPy.Simulation
import
now
,
Process
,
Resource
,
infinity
,
waituntil
,
waitevent
# from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent
import
simpy
import
xlwt
from
CoreObject
import
CoreObject
...
...
@@ -54,7 +55,7 @@ class Exit(CoreObject):
CoreObject
.
initialize
(
self
)
# initialize the internal Queue (type Resource) of the Exit
self
.
Res
=
Resource
(
capacity
=
infinity
)
self
.
Res
=
simpy
.
Resource
(
self
.
env
,
capacity
=
10000
)
# The number of resource that exited through this exit.
# XXX bug: cannot output as json when nothing has exited.
self
.
numOfExits
=
0
...
...
@@ -68,7 +69,8 @@ class Exit(CoreObject):
def
run
(
self
):
while
1
:
# wait until the Queue can accept an entity and one predecessor requests it
yield
waitevent
,
self
,
self
.
isRequested
yield
self
.
isRequested
self
.
isRequested
=
self
.
env
.
event
()
# TODO: insert extra controls to check whether the self.giver attribute is correctly updated
self
.
getEntity
()
...
...
@@ -109,13 +111,13 @@ class Exit(CoreObject):
# if activeEntity in G.EntityList:
# G.EntityList.remove(activeEntity)
# self.clear(activeEntity)
self
.
totalLifespan
+=
now
()
-
activeEntity
.
startTime
#Add the entity's lifespan to the total one.
self
.
totalLifespan
+=
self
.
env
.
now
-
activeEntity
.
startTime
#Add the entity's lifespan to the total one.
self
.
numOfExits
+=
1
# increase the exits by one
self
.
totalNumberOfUnitsExited
+=
activeEntity
.
numberOfUnits
# add the number of units that xited
self
.
totalTaktTime
+=
now
()
-
self
.
timeLastEntityLeft
# add the takt time
self
.
timeLastEntityLeft
=
now
()
# update the time that the last entity left from the Exit
self
.
totalTaktTime
+=
self
.
env
.
now
-
self
.
timeLastEntityLeft
# add the takt time
self
.
timeLastEntityLeft
=
self
.
env
.
now
# update the time that the last entity left from the Exit
activeObjectQueue
=
self
.
getActiveObjectQueue
()
del
self
.
Res
.
activeQ
[:]
del
self
.
Res
.
users
[:]
return
activeEntity
@
staticmethod
...
...
dream/simulation/LineGenerationJSON.py
View file @
a6618f51
...
...
@@ -40,7 +40,8 @@ import numpy
numpy
.
seterr
(
all
=
'raise'
)
from
SimPy.Simulation
import
activate
,
initialize
,
simulate
,
now
,
infinity
# from SimPy.Simulation import activate, initialize, simulate, now, infinity
import
simpy
from
Globals
import
G
from
Source
import
Source
from
Machine
import
Machine
...
...
@@ -885,11 +886,14 @@ def initializeObjects():
# ===========================================================================
def
activateObjects
():
for
element
in
G
.
ObjList
:
activate
(
element
,
element
.
run
())
# activate(element, element.run())
G
.
env
.
process
(
element
.
run
())
for
ev
in
G
.
EventGeneratorList
:
activate
(
ev
,
ev
.
run
())
# activate(ev, ev.run())
G
.
env
.
process
(
ev
.
run
())
for
oi
in
G
.
ObjectInterruptionList
:
activate
(
oi
,
oi
.
run
())
# activate(oi, oi.run())
G
.
env
.
process
(
oi
.
run
())
# ===========================================================================
# reads the WIP of the stations
...
...
@@ -1261,6 +1265,7 @@ def main(argv=[], input_data=None):
#read the input from the JSON file and create the line
G
.
JSONData
=
json
.
loads
(
G
.
InputData
)
# create the dictionary JSONData
readGeneralInput
()
G
.
env
=
simpy
.
Environment
()
# initialize the environment
createObjects
()
createObjectInterruptions
()
setTopology
()
...
...
@@ -1272,7 +1277,7 @@ def main(argv=[], input_data=None):
G
.
Rnd
=
Random
(
'%s%s'
%
(
G
.
seed
,
i
))
else
:
G
.
Rnd
=
Random
()
initialize
()
#initialize the simulation
# initialize() #initialize the simulation
createWIP
()
initializeObjects
()
Globals
.
setWIP
(
G
.
EntityList
)
...
...
@@ -1281,22 +1286,24 @@ def main(argv=[], input_data=None):
# if the simulation is ran until no more events are scheduled,
# then we have to find the end time as the time the last entity ended.
if
G
.
maxSimTime
==-
1
:
simulate
(
until
=
infinity
)
# simulate until there are no more events.
# If someone does it for a model that has always events, then it will run forever!
G
.
env
.
run
(
until
=
infinity
)
# simulate(until=infinity) # simulate until there are no more events.
# # If someone does it for a model that has always events, then it will run forever!
# # identify from the exits what is the time that the last entity has ended.
# endList=[]
# for exit in G.ExitList:
# endList.append(exit.timeLastEntityLeft)
# G.maxSimTime=float(max(endList))
# identify the time of the last event
if
now
()
!=
0
:
#do not let G.maxSimTime=0 so that there will be no crash
G
.
maxSimTime
=
now
()
if
G
.
env
.
now
!=
0
:
#do not let G.maxSimTime=0 so that there will be no crash
G
.
maxSimTime
=
env
.
now
else
:
print
"simulation ran for 0 time, something may have gone wrong"
logger
.
info
(
"simulation ran for 0 time, something may have gone wrong"
)
#else we simulate until the given maxSimTime
else
:
simulate
(
until
=
G
.
maxSimTime
)
#simulate until the given maxSimTime
else
:
G
.
env
.
run
(
until
=
G
.
maxSimTime
)
# simulate(until=G.maxSimTime) #simulate until the given maxSimTime
#carry on the post processing operations for every object in the topology
for
element
in
G
.
ObjList
:
...
...
dream/simulation/Machine.py
View file @
a6618f51
...
...
@@ -25,8 +25,9 @@ Created on 8 Nov 2012
Models a machine that can also have failures
'''
from
SimPy.Simulation
import
Process
,
Resource
,
SimEvent
from
SimPy.Simulation
import
activate
,
passivate
,
waituntil
,
now
,
hold
,
request
,
release
,
waitevent
# from SimPy.Simulation import Process, Resource, SimEvent
# from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, release, waitevent
import
simpy
from
Failure
import
Failure
from
CoreObject
import
CoreObject
...
...
@@ -150,12 +151,14 @@ class Machine(CoreObject):
self
.
isPreemptive
=
isPreemptive
self
.
resetOnPreemption
=
resetOnPreemption
# events used by the broker
self
.
brokerIsSet
=
SimEvent
(
'brokerIsSet'
)
# self.brokerIsSet=SimEvent('brokerIsSet')
self
.
brokerIsSet
=
self
.
env
.
event
()
# this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity,
# then it must be signalled that the operator is now available
self
.
loadOperatorAvailable
=
SimEvent
(
'loadOperatorAvailable'
)
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
# flag notifying that there is operator assigned to the actievObject
self
.
assignedOperator
=
True
...
...
@@ -166,7 +169,8 @@ class Machine(CoreObject):
# using the Process __init__ and not the CoreObject __init__
CoreObject
.
initialize
(
self
)
# initialize the internal Queue (type Resource) of the Machine
self
.
Res
=
Resource
(
self
.
capacity
)
#self.Res=Resource(self.capacity)
self
.
Res
=
simpy
.
Resource
(
self
.
env
,
capacity
=
1
)
# initiate the Broker responsible to control the request/release
# initialize the operator pool if any
if
(
self
.
operatorPool
!=
"None"
):
...
...
@@ -211,12 +215,14 @@ class Machine(CoreObject):
# flag notifying that there is operator assigned to the actievObject
self
.
assignedOperator
=
True
self
.
brokerIsSet
=
SimEvent
(
'brokerIsSet'
)
# self.brokerIsSet=SimEvent('brokerIsSet')
self
.
brokerIsSet
=
self
.
env
.
event
()
# this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity,
# then it must be signalled that the operator is now available
self
.
loadOperatorAvailable
=
SimEvent
(
'loadOperatorAvailable'
)
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
# =======================================================================
# the main process of the machine
...
...
@@ -229,23 +235,29 @@ class Machine(CoreObject):
# waitEvent isRequested /interruptionEnd/loadOperatorAvailable
while
1
:
# self.printTrace(self.id, waitEvent='')
yield
waitevent
,
self
,
[
self
.
isRequested
,
self
.
interruptionEnd
,
self
.
loadOperatorAvailable
]
# yield waitevent, self, [self.isRequested, self.interruptionEnd, self.loadOperatorAvailable]
receivedEvent
=
yield
self
.
isRequested
|
self
.
interruptionEnd
|
self
.
loadOperatorAvailable
# self.printTrace(self.id, received='')
# if the machine can accept an entity and one predecessor requests it continue with receiving the entity
if
self
.
isRequested
.
signalparam
:
# self.printTrace(self.id, isRequested=self.isRequested.
signalparam
.id)
assert
self
.
isRequested
.
signalparam
==
self
.
giver
,
'the giver is not the requestingObject'
if
self
.
isRequested
in
receivedEvent
:
# self.printTrace(self.id, isRequested=self.isRequested.
value
.id)
assert
self
.
isRequested
.
value
==
self
.
giver
,
'the giver is not the requestingObject'
assert
self
.
giver
.
receiver
==
self
,
'the receiver of the signalling object in not the station'
# reset the signalparam of the isRequested event
self
.
isRequested
.
signalparam
=
None
# self.isRequested.value=None
self
.
isRequested
=
self
.
env
.
event
()
break
# if an interruption caused the control to be taken by the machine or
# if an operator was rendered available while it was needed by the machine to proceed with getEntity
if
self
.
interruptionEnd
.
signalparam
==
now
()
or
self
.
loadOperatorAvailable
.
signalparam
==
now
():
# if self.interruptionEnd.signalparam==now():
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.signalparam))
# elif self.loadOperatorAvailable.signalparam==now():
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.signalparam))
if
self
.
interruptionEnd
.
value
==
self
.
env
.
now
or
self
.
loadOperatorAvailable
.
value
==
self
.
env
.
now
:
if
self
.
interruptionEnd
in
receivedEvent
:
self
.
interruptionEnd
=
self
.
env
.
event
()
if
self
.
loadOperatorAvailable
in
receivedEvent
:
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
# if self.interruptionEnd.value==self.env.now:
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.value))
# elif self.loadOperatorAvailable.value==self.env.now:
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.value))
# try to signal the Giver, otherwise wait until it is requested
if
self
.
signalGiver
():
break
...
...
@@ -264,19 +276,20 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator)
self
.
requestOperator
()
self
.
timeWaitForLoadOperatorStarted
=
now
()
self
.
timeWaitForLoadOperatorStarted
=
self
.
env
.
now
# wait until the Broker has waited times equal to loadTime (if any)
yield
waitevent
,
self
,
self
.
brokerIsSet
self
.
timeWaitForLoadOperatorEnded
=
now
()
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
self
.
timeWaitForLoadOperatorEnded
=
self
.
env
.
now
self
.
loadOperatorWaitTimeCurrentEntity
+=
self
.
timeWaitForLoadOperatorEnded
-
self
.
timeWaitForLoadOperatorStarted
self
.
totalTimeWaitingForLoadOperator
+=
self
.
loadOperatorWaitTimeCurrentEntity
# ======= Load the machine if the Load is defined as one of the Operators' operation types
if
any
(
type
==
"Load"
for
type
in
self
.
multOperationTypeList
)
and
self
.
isOperated
():
self
.
timeLoadStarted
=
now
()
yield
hold
,
self
,
self
.
calculateLoadTime
(
)
self
.
timeLoadStarted
=
self
.
env
.
now
yield
self
.
env
.
timeout
(
self
.
calculateLoadTime
()
)
# TODO: if self.interrupted(): There is the issue of failure during the Loading
self
.
timeLoadEnded
=
now
()
self
.
timeLoadEnded
=
self
.
env
.
now
self
.
loadTimeCurrentEntity
=
self
.
timeLoadEnded
-
self
.
timeLoadStarted
self
.
totalLoadTime
+=
self
.
loadTimeCurrentEntity
...
...
@@ -290,7 +303,8 @@ class Machine(CoreObject):
# machine has to release the operator
self
.
releaseOperator
()
# wait until the Broker has finished processing
yield
waitevent
,
self
,
self
.
brokerIsSet
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
# TODO: reset the requestinEntity before receiving the currentEntity
self
.
requestingEntity
=
None
...
...
@@ -310,10 +324,11 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator)
self
.
requestOperator
()
self
.
timeWaitForOperatorStarted
=
now
()
self
.
timeWaitForOperatorStarted
=
self
.
env
.
now
# wait until the Broker has waited times equal to loadTime (if any)
yield
waitevent
,
self
,
self
.
brokerIsSet
self
.
timeWaitForOperatorEnded
=
now
()
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
self
.
timeWaitForOperatorEnded
=
self
.
env
.
now
self
.
operatorWaitTimeCurrentEntity
+=
self
.
timeWaitForOperatorEnded
-
self
.
timeWaitForOperatorStarted
# variables dedicated to hold the processing times, the time when the Entity entered,
...
...
@@ -324,10 +339,10 @@ class Machine(CoreObject):
# ======= setup the machine if the Setup is defined as one of the Operators' operation types
# in plantSim the setup is performed when the machine has to process a new type of Entity and only once
if
any
(
type
==
"Setup"
for
type
in
self
.
multOperationTypeList
)
and
self
.
isOperated
():
self
.
timeSetupStarted
=
now
()
yield
hold
,
self
,
self
.
calculateSetupTime
(
)
self
.
timeSetupStarted
=
self
.
env
.
now
yield
self
.
env
.
timeout
(
self
.
calculateSetupTime
()
)
# TODO: if self.interrupted(): There is the issue of failure during the setup
self
.
timeSetupEnded
=
now
()
self
.
timeSetupEnded
=
self
.
env
.
now
self
.
setupTimeCurrentEntity
=
self
.
timeSetupEnded
-
self
.
timeSetupStarted
self
.
totalSetupTime
+=
self
.
setupTimeCurrentEntity
...
...
@@ -336,10 +351,10 @@ class Machine(CoreObject):
# but setupTime is given for the entity to be processed
# try:
# if self.setupTime and not any(type=="Setup" for type in self.multOperationTypeList):
# self.timeSetupStarted =
now()
# self.timeSetupStarted =
self.env.now
# yield hold,self,self.calculateSetupTime()
# # TODO: if self.interrupted(): There is the issue of failure during the setup
# self.timeSetupEnded =
now()
# self.timeSetupEnded =
self.env.now
# self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted
# self.totalSetupTime += self.setupTimeCurrentEntity
# except:
...
...
@@ -355,7 +370,8 @@ class Machine(CoreObject):
# machine has to release the operator
self
.
releaseOperator
()
# wait until the Broker has finished processing
yield
waitevent
,
self
,
self
.
brokerIsSet
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
# variables used to flag any interruptions and the end of the processing
self
.
interruption
=
False
...
...
@@ -368,13 +384,15 @@ class Machine(CoreObject):
while
processingNotFinished
:
# timeRestartingProcessing : dummy variable to keep track of the time that the processing starts after
# every interruption
self
.
timeRestartingProcessing
=
now
()
self
.
timeRestartingProcessing
=
self
.
env
.
now
# wait for the processing time left tinM, if no interruption occurs then change the processingEndedFlag and exit loop,
# else (if interrupted()) set interruption flag to true (only if tinM==0),
# and recalculate the processing time left tinM, passivate while waiting for repair.
# if a preemption has occurred then react accordingly (proceed with getting the critical entity)
yield
hold
,
self
,
self
.
tinM
# getting processed for remaining processing time tinM
if
self
.
interrupted
():
# if a failure occurs while processing the machine is interrupted.
receivedEvent
=
yield
self
.
env
.
timeout
(
self
.
tinM
)
|
self
.
interruptionStart
# getting processed for remaining processing time tinM
if
self
.
interruptionStart
in
receivedEvent
:
# if a failure occurs while processing the machine is interrupted.
assert
self
.
interruptionStart
.
value
==
self
.
env
.
now
,
'the interruption has not been processed on the time of activation'
self
.
interruptionStart
=
self
.
env
.
event
()
self
.
interruptionActions
()
# execute interruption actions
# =============== release the operator if there is interruption
...
...
@@ -382,12 +400,14 @@ class Machine(CoreObject):
and
self
.
isOperated
()
\
and
any
(
type
==
"Processing"
for
type
in
self
.
multOperationTypeList
):
self
.
releaseOperator
()
yield
waitevent
,
self
,
self
.
brokerIsSet
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
# if there is a failure in the machine or interruption due to preemption, it is passivated
# passivate the Machine for as long as there is no repair
yield
waitevent
,
self
,
self
.
interruptionEnd
assert
now
()
==
self
.
interruptionEnd
.
signalparam
,
'the victim of the failure is not the object that received it'
yield
self
.
interruptionEnd
assert
self
.
env
.
now
==
self
.
interruptionEnd
.
value
,
'the victim of the failure is not the object that received it'
self
.
interruptionEnd
=
self
.
env
.
event
()
self
.
postInterruptionActions
()
...
...
@@ -395,10 +415,11 @@ class Machine(CoreObject):
if
(
self
.
operatorPool
!=
"None"
)
\
and
any
(
type
==
"Processing"
for
type
in
self
.
multOperationTypeList
)
\
and
not
self
.
interruption
:
self
.
timeWaitForOperatorStarted
=
now
()
self
.
timeWaitForOperatorStarted
=
self
.
env
.
now
self
.
requestOperator
()
yield
waitevent
,
self
,
self
.
brokerIsSet
self
.
timeWaitForOperatorEnded
=
now
()
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
self
.
timeWaitForOperatorEnded
=
self
.
env
.
now
self
.
operatorWaitTimeCurrentEntity
+=
self
.
timeWaitForOperatorEnded
-
self
.
timeWaitForOperatorStarted
# if the station is reactivated by the preempt method
elif
(
self
.
shouldPreempt
):
...
...
@@ -409,7 +430,8 @@ class Machine(CoreObject):
and
self
.
isOperated
()
\
and
any
(
type
==
"Processing"
for
type
in
self
.
multOperationTypeList
):
self
.
releaseOperator
()
yield
waitevent
,
self
,
self
.
brokerIsSet
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
self
.
postInterruptionActions
()
break
...
...
@@ -426,30 +448,29 @@ class Machine(CoreObject):
and
any
(
type
==
"Processing"
for
type
in
self
.
multOperationTypeList
)
\
and
not
self
.
interruption
:
self
.
releaseOperator
()
yield
waitevent
,
self
,
self
.
brokerIsSet
yield
self
.
brokerIsSet
self
.
brokerIsSet
=
self
.
env
.
event
()
# signal the receiver that the activeObject has something to dispose of
if
not
self
.
signalReceiver
():
# if there was no available receiver, get into blocking control
while
1
:
# wait the event canDispose, this means that the station can deliver the item to successor
event
=
yield
waitevent
,
self
,
[
self
.
canDispose
,
self
.
interruptionStart
]
receivedEvent
=
yield
self
.
canDispose
|
self
.
interruptionStart
# if there was interruption
#if self.interrupted():
# TODO not good implementation
if
self
.
interruptionStart
.
signalparam
==
now
():
if
self
.
interruptionStart
in
receivedEvent
:
assert
self
.
interruptionStart
.
value
==
self
.
env
.
now
,
'the interruption has not been processed on the time of activation'
self
.
interruptionStart
=
self
.
env
.
event
()
# wait for the end of the interruption
self
.
interruptionActions
()
# execute interruption actions
yield
waitevent
,
self
,
self
.
interruptionEnd
# interruptionEnd to be triggered by ObjectInterruption
assert
now
()
==
self
.
interruptionEnd
.
signalparam
,
'the victim of the failure is not the object that received it'
yield
self
.
interruptionEnd
# interruptionEnd to be triggered by ObjectInterruption
assert
self
.
env
.
now
==
self
.
interruptionEnd
.
value
,
'the victim of the failure is not the object that received it'
self
.
interruptionEnd
=
self
.
env
.
event
()
self
.
postInterruptionActions
()
#=======================================================
# TODO: not sure if this is required now
# #if during the interruption the object became empty break
# if (len(self.getActiveObjectQueue())==0 and self.shouldPreempt):
# self.shouldPreempt==False
# break
#=======================================================
if
self
.
canDispose
in
receivedEvent
:
self
.
canDispose
=
self
.
env
.
event
()
# try to signal a receiver, if successful then proceed to get an other entity
if
self
.
signalReceiver
():
break
...
...
@@ -458,7 +479,7 @@ class Machine(CoreObject):
# signals the preceding station (e.g. self.machine) and immediately after that gets the entity.
# the preceding machine gets the canDispose signal which is actually useless, is emptied by the following station
# and then cannot exit an infinite loop.
yield
hold
,
self
,
0
yield
self
.
env
.
timeout
(
0
)
# if while waiting (for a canDispose event) became free as the machines that follows emptied it, then proceed
if
not
self
.
haveToDispose
():
break
...
...
@@ -467,7 +488,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def
endProcessingActions
(
self
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
activeEntity
=
activeObjectQueue
[
0
]
# self.printTrace(activeObject.getActiveObjectQueue()[0].name, processEnd=activeObject.objName)
# reset the variables used to handle the interruptions timing
...
...
@@ -498,16 +519,16 @@ class Machine(CoreObject):
self
.
waitToDispose
=
True
#do this so that if it is overtime working it is not counted as off-shift time
if
not
self
.
onShift
:
self
.
timeLastShiftEnded
=
now
()
self
.
timeLastShiftEnded
=
self
.
env
.
now
# update the total working time
# the total processing time for this entity is what the distribution initially gave
if
not
self
.
shouldPreempt
:
self
.
totalWorkingTime
+=
self
.
totalProcessingTimeInCurrentEntity
# if the station was preemptied for a critical order then calculate the total working time accorindingly
else
:
self
.
totalWorkingTime
+=
now
()
-
(
self
.
timeLastEntityEntered
)
self
.
totalWorkingTime
+=
self
.
env
.
now
-
(
self
.
timeLastEntityEntered
)
# update the variables keeping track of Entity related attributes of the machine
self
.
timeLastEntityEnded
=
now
()
# this holds the time that the last entity ended processing in Machine
self
.
timeLastEntityEnded
=
self
.
env
.
now
# this holds the time that the last entity ended processing in Machine
self
.
nameLastEntityEnded
=
self
.
currentEntity
.
name
# this holds the name of the last entity that ended processing in Machine
self
.
completedJobs
+=
1
# Machine completed one more Job
# reseting the shouldPreempt flag
...
...
@@ -517,7 +538,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def
interruptionActions
(
self
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
activeEntity
=
activeObjectQueue
[
0
]
# self.printTrace(activeEntity.name, interrupted=self.objName)
# if the interrupt occured while processing an entity
...
...
@@ -528,40 +549,40 @@ class Machine(CoreObject):
except
IndexError
:
pass
# recalculate the processing time left tinM
self
.
tinM
=
self
.
tinM
-
(
now
()
-
self
.
timeRestartingProcessing
)
self
.
tinM
=
self
.
tinM
-
(
self
.
env
.
now
-
self
.
timeRestartingProcessing
)
if
(
self
.
tinM
==
0
):
# sometimes the failure may happen exactly at the time that the processing would finish
# this may produce disagreement with the simul8 because in both SimPy and Simul8
# it seems to be random which happens 1st
# this should not appear often to stochastic models though where times are random
self
.
interruption
=
True
# start counting the down time at breatTime dummy variable
self
.
breakTime
=
now
()
# dummy variable that the interruption happened
self
.
breakTime
=
self
.
env
.
now
# dummy variable that the interruption happened
# =======================================================================
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def
postInterruptionActions
(
self
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
activeEntity
=
activeObjectQueue
[
0
]
# if the machine returns from an failure while processing an entity
if
not
self
.
waitToDispose
:
# use the timers to count the time that Machine is down and related
self
.
downTimeProcessingCurrentEntity
+=
now
()
-
self
.
breakTime
# count the time that Machine is down while processing this Entity
self
.
downTimeInCurrentEntity
+=
now
()
-
self
.
breakTime
# count the time that Machine is down while on currentEntity
self
.
timeLastFailureEnded
=
now
()
# set the timeLastFailureEnded
self
.
failureTimeInCurrentEntity
+=
now
()
-
self
.
breakTime
# dummy variable keeping track of the failure time
self
.
downTimeProcessingCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
# count the time that Machine is down while processing this Entity
self
.
downTimeInCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
# count the time that Machine is down while on currentEntity
self
.
timeLastFailureEnded
=
self
.
env
.
now
# set the timeLastFailureEnded
self
.
failureTimeInCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
# dummy variable keeping track of the failure time
# output to trace that the Machine self.objName was passivated for the current failure time
self
.
outputTrace
(
activeObjectQueue
[
0
].
name
,
"passivated in "
+
self
.
objName
+
" for "
+
str
(
now
()
-
self
.
breakTime
))
self
.
outputTrace
(
activeObjectQueue
[
0
].
name
,
"passivated in "
+
self
.
objName
+
" for "
+
str
(
self
.
env
.
now
-
self
.
breakTime
))
# when a machine returns from failure while trying to deliver an entity
else
:
# count the failure while on current entity time with failureTime variable
self
.
failureTimeInCurrentEntity
+=
now
()
-
self
.
breakTime
self
.
failureTimeInCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
# calculate the time the Machine was down while trying to dispose the current Entity,
# and the total down time while on current Entity
self
.
downTimeInTryingToReleaseCurrentEntity
+=
now
()
-
self
.
breakTime
self
.
downTimeInCurrentEntity
+=
now
()
-
self
.
breakTime
# already updated from failures during processing
self
.
downTimeInTryingToReleaseCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
self
.
downTimeInCurrentEntity
+=
self
.
env
.
now
-
self
.
breakTime
# already updated from failures during processing
# update the timeLastFailureEnded
self
.
timeLastFailureEnded
=
now
()
self
.
timeLastFailureEnded
=
self
.
env
.
now
# reset the variable holding the time the failure happened
self
.
breakTime
=
0
...
...
@@ -577,7 +598,7 @@ class Machine(CoreObject):
# that will give the entity.
# =======================================================================
def
canAccept
(
self
,
callerObject
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
# if we have only one predecessor just check if there is a place and the machine is up
# this is done to achieve better (cpu) processing time
# then we can also use it as a filter for a yield method
...
...
@@ -615,7 +636,7 @@ class Machine(CoreObject):
# also updates the giver to the one that is to be taken
# =======================================================================
def
canAcceptAndIsRequested
(
self
,
callerObject
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
giverObject
=
callerObject
assert
giverObject
,
'there must be a caller for canAcceptAndIsRequested'
# check if there is a place, the machine is up and the predecessor has an entity to dispose. if the machine has to compete
...
...
@@ -701,7 +722,7 @@ class Machine(CoreObject):
# checks if the Machine can dispose an entity to the following object
# =======================================================================
def
haveToDispose
(
self
,
callerObject
=
None
):
activeObjectQueue
=
self
.
Res
.
activeQ
activeObjectQueue
=
self
.
Res
.
users
#if we have only one successor just check if machine waits to dispose and also is up
# this is done to achieve better (cpu) processing time
if
(
len
(
self
.
next
)
==
1
or
callerObject
==
None
):
...
...
@@ -796,7 +817,7 @@ class Machine(CoreObject):
offShiftTimeInCurrentEntity
=
0
if
self
.
interruptCause
:
if
self
.
onShift
==
False
and
self
.
interruptCause
.
type
==
'ShiftScheduler'
:
offShiftTimeInCurrentEntity
=
now
()
-
activeObject
.
timeLastShiftEnded
offShiftTimeInCurrentEntity
=
self
.
env
.
now
-
activeObject
.
timeLastShiftEnded
# if there is an entity that finished processing in a Machine but did not get to reach
# the following Object till the end of simulation,
...
...
@@ -805,9 +826,9 @@ class Machine(CoreObject):
if
(
len
(
activeObjectQueue
)
>
0
)
and
(
mightBeBlocked
)
\
and
((
activeObject
.
nameLastEntityEntered
==
activeObject
.
nameLastEntityEnded
))
and
self
.
onShift
:
# be careful here, might have to reconsider
activeObject
.
totalBlockageTime
+=
now
()
-
(
activeObject
.
timeLastEntityEnded
+
activeObject
.
downTimeInTryingToReleaseCurrentEntity
)
activeObject
.
totalBlockageTime
+=
self
.
env
.
now
-
(
activeObject
.
timeLastEntityEnded
+
activeObject
.
downTimeInTryingToReleaseCurrentEntity
)
if
activeObject
.
Up
==
False
:
activeObject
.
totalBlockageTime
-=
now
()
-
activeObject
.
timeLastFailure
activeObject
.
totalBlockageTime
-=
self
.
env
.
now
-
activeObject
.
timeLastFailure
alreadyAdded
=
True
#if Machine is currently processing an entity we should count this working time
...
...
@@ -817,8 +838,8 @@ class Machine(CoreObject):
#if Machine is down we should add this last failure time to the time that it has been down in current entity
if
self
.
Up
==
False
:
# if(len(activeObjectQueue)>0) and (self.Up==False):
activeObject
.
downTimeProcessingCurrentEntity
+=
now
()
-
activeObject
.
timeLastFailure
activeObject
.
totalWorkingTime
+=
now
()
-
activeObject
.
timeLastEntityEntered
\
activeObject
.
downTimeProcessingCurrentEntity
+=
self
.
env
.
now
-
activeObject
.
timeLastFailure
activeObject
.
totalWorkingTime
+=
self
.
env
.
now
-
activeObject
.
timeLastEntityEntered
\
-
activeObject
.
downTimeProcessingCurrentEntity
\
-
activeObject
.
operatorWaitTimeCurrentEntity
\
-
activeObject
.
setupTimeCurrentEntity
\
...
...
@@ -830,17 +851,17 @@ class Machine(CoreObject):
and
(
activeObject
.
currentOperator
==
None
):
# TODO: needs further research as the time of failure while waiting for operator is not counted yet
if
self
.
Up
==
False
:
activeObject
.
downTimeProcessingCurrentEntity
+=
now
()
-
activeObject
.
timeLastFailure
activeObject
.
totalTimeWaitingForOperator
+=
now
()
-
activeObject
.
timeWaitForOperatorStarted
\
activeObject
.
downTimeProcessingCurrentEntity
+=
self
.
env
.
now
-
activeObject
.
timeLastFailure
activeObject
.
totalTimeWaitingForOperator
+=
self
.
env
.
now
-
activeObject
.
timeWaitForOperatorStarted
\
-
activeObject
.
downTimeProcessingCurrentEntity
\
-
offShiftTimeInCurrentEntity
# if Machine is down we have to add this failure time to its total failure time
# we also need to add the last blocking time to total blockage time
if
(
activeObject
.
Up
==
False
):
activeObject
.
totalFailureTime
+=
now
()
-
activeObject
.
timeLastFailure
activeObject
.
totalFailureTime
+=
self
.
env
.
now
-
activeObject
.
timeLastFailure
# we add the value only if it hasn't already been added
if
((
mightBeBlocked
)
and
(
activeObject
.
nameLastEntityEnded
==
activeObject
.
nameLastEntityEntered
)
and
(
not
alreadyAdded
)):
activeObject
.
totalBlockageTime
+=
(
now
()
-
activeObject
.
timeLastEntityEnded
)
-
(
now
()
-
activeObject
.
timeLastFailure
)
-
activeObject
.
downTimeInTryingToReleaseCurrentEntity
activeObject
.
totalBlockageTime
+=
(
self
.
env
.
now
-
activeObject
.
timeLastEntityEnded
)
-
(
self
.
env
.
now
-
activeObject
.
timeLastFailure
)
-
activeObject
.
downTimeInTryingToReleaseCurrentEntity
alreadyAdded
=
True
#if the machine is off shift,add this to the off-shift time
...
...
@@ -849,12 +870,12 @@ class Machine(CoreObject):
#add the time only if the object is interrupted because of off-shift
if
self
.
interruptCause
:
if
self
.
interruptCause
.
type
==
'ShiftScheduler'
:
self
.
totalOffShiftTime
+=
now
()
-
self
.
timeLastShiftEnded
self
.
totalOffShiftTime
+=
self
.
env
.
now
-
self
.
timeLastShiftEnded
elif
len
(
self
.
getActiveObjectQueue
())
==
0
or
self
.
waitToDispose
:
self
.
totalOffShiftTime
+=
now
()
-
self
.
timeLastShiftEnded
self
.
totalOffShiftTime
+=
self
.
env
.
now
-
self
.
timeLastShiftEnded
# we add the value only if it hasn't already been added
if
((
mightBeBlocked
)
and
(
activeObject
.
nameLastEntityEnded
==
activeObject
.
nameLastEntityEntered
)
and
(
not
alreadyAdded
)):
activeObject
.
totalBlockageTime
+=
(
now
()
-
activeObject
.
timeLastEntityEnded
)
-
(
now
()
-
activeObject
.
timeLastShiftEnded
)
-
offShiftTimeInCurrentEntity
activeObject
.
totalBlockageTime
+=
(
self
.
env
.
now
-
activeObject
.
timeLastEntityEnded
)
-
(
self
.
env
.
now
-
activeObject
.
timeLastShiftEnded
)
-
offShiftTimeInCurrentEntity
#Machine was idle when it was not in any other state
activeObject
.
totalWaitingTime
=
MaxSimtime
-
activeObject
.
totalWorkingTime
-
activeObject
.
totalBlockageTime
-
activeObject
.
totalFailureTime
-
activeObject
.
totalLoadTime
-
activeObject
.
totalSetupTime
-
self
.
totalOffShiftTime
...
...
dream/simulation/Source.py
View file @
a6618f51
...
...
@@ -26,7 +26,8 @@ Created on 8 Nov 2012
models the source object that generates the entities
'''
from
SimPy.Simulation
import
now
,
Process
,
Resource
,
infinity
,
hold
,
SimEvent
,
activate
,
waitevent
# from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent
import
simpy
from
RandomNumberGenerator
import
RandomNumberGenerator
from
CoreObject
import
CoreObject
from
Globals
import
G
...
...
@@ -36,20 +37,20 @@ import Globals
#============================================================================
# the EntityGenerator object
#============================================================================
class
EntityGenerator
(
Process
):
class
EntityGenerator
(
object
):
#===========================================================================
# the __init__ method of the EntityGenerator
#===========================================================================
def
__init__
(
self
,
victim
=
None
):
Process
.
__init__
(
self
)
self
.
env
=
G
.
env
self
.
type
=
"EntityGenerator"
#String that shows the type of object
self
.
victim
=
victim
#===========================================================================
# initialize method of the EntityGenerator
#===========================================================================
def
initialize
(
self
):
Process
.
__init__
(
self
)
#
#===========================================================================
#
# initialize method of the EntityGenerator
#
#===========================================================================
#
def initialize(self):
# Process.__init__(self)
#===========================================================================
# the generator of the EntitiesGenerator
...
...
@@ -59,8 +60,8 @@ class EntityGenerator(Process):
# if the Source is empty create the Entity
if
len
(
self
.
victim
.
getActiveObjectQueue
())
==
0
:
entity
=
self
.
victim
.
createEntity
()
# create the Entity object and assign its name
entity
.
creationTime
=
now
()
# assign the current simulation time as the Entity's creation time
entity
.
startTime
=
now
()
# assign the current simulation time as the Entity's start time
entity
.
creationTime
=
self
.
env
.
now
# assign the current simulation time as the Entity's creation time
entity
.
startTime
=
self
.
env
.
now
# assign the current simulation time as the Entity's start time
entity
.
currentStation
=
self
.
victim
# update the current station of the Entity
G
.
EntityList
.
append
(
entity
)
self
.
victim
.
outputTrace
(
entity
.
name
,
"generated"
)
# output the trace
...
...
@@ -68,13 +69,13 @@ class EntityGenerator(Process):
self
.
victim
.
numberOfArrivals
+=
1
# we have one new arrival
G
.
numberOfEntities
+=
1
self
.
victim
.
appendEntity
(
entity
)
self
.
victim
.
entityCreated
.
s
ignal
(
entity
)
self
.
victim
.
entityCreated
.
s
ucceed
(
entity
)
# else put it on the time list for scheduled Entities
else
:
#print
now()
, 'appending to the list'
self
.
victim
.
scheduledEntities
.
append
(
now
()
)
#print
self.env.now
, 'appending to the list'
self
.
victim
.
scheduledEntities
.
append
(
self
.
env
.
now
)
self
.
victim
.
outputTrace
(
entity
.
name
,
"generated"
)
# output the trace
yield
hold
,
self
,
self
.
victim
.
calculateInterarrivalTime
(
)
# wait until the next arrival
yield
self
.
env
.
timeout
(
self
.
victim
.
calculateInterarrivalTime
()
)
# wait until the next arrival
#============================================================================
# The Source object is a Process
...
...
@@ -104,9 +105,11 @@ class Source(CoreObject):
self
.
entityGenerator
=
EntityGenerator
(
victim
=
self
)
# the EntityGenerator of the Source
self
.
entityCreated
=
SimEvent
(
'an entity is created'
)
# self.entityCreated=SimEvent('an entity is created')
self
.
entityCreated
=
self
.
env
.
event
()
# event used by router
self
.
loadOperatorAvailable
=
SimEvent
(
'loadOperatorAvailable'
)
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
self
.
scheduledEntities
=
[]
# list of creations that are scheduled
...
...
@@ -118,15 +121,19 @@ class Source(CoreObject):
CoreObject
.
initialize
(
self
)
# initialize the internal Queue (type Resource) of the Source
self
.
Res
=
Resource
(
capacity
=
infinity
)
self
.
Res
.
activeQ
=
[]
self
.
Res
.
waitQ
=
[]
# self.Res=Resource(capacity=infinity)
self
.
Res
=
simpy
.
Resource
(
self
.
env
,
capacity
=
10000
)
self
.
Res
.
users
=
[]
# self.Res.waitQ=[]
self
.
numberOfArrivals
=
0
self
.
entityGenerator
.
initialize
()
activate
(
self
.
entityGenerator
,
self
.
entityGenerator
.
run
())
self
.
entityCreated
=
SimEvent
(
'an entity is created'
)
# self.entityGenerator.initialize()
# activate(self.entityGenerator,self.entityGenerator.run())
self
.
env
.
process
(
self
.
entityGenerator
.
run
())
# self.entityCreated=SimEvent('an entity is created')
self
.
entityCreated
=
self
.
env
.
event
()
# event used by router
self
.
loadOperatorAvailable
=
SimEvent
(
'loadOperatorAvailable'
)
# self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
self
.
scheduledEntities
=
[]
# list of creations that are scheduled
#===========================================================================
...
...
@@ -138,16 +145,18 @@ class Source(CoreObject):
activeObjectQueue
=
self
.
getActiveObjectQueue
()
while
1
:
# wait for any event (entity creation or request for disposal of entity)
yield
waitevent
,
self
,
[
self
.
entityCreated
,
self
.
canDispose
,
self
.
loadOperatorAvailable
]
receivedEvent
=
yield
self
.
entityCreated
|
self
.
canDispose
|
self
.
loadOperatorAvailable
# if an entity is created try to signal the receiver and continue
if
self
.
entityCreated
.
signalparam
:
self
.
entityCreated
.
signalparam
=
None
if
self
.
entityCreated
in
receivedEvent
:
self
.
entityCreated
=
self
.
env
.
event
()
if
self
.
signalReceiver
():
continue
# otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of
if
self
.
canDispose
.
signalparam
or
self
.
loadOperatorAvailable
.
signalparam
:
self
.
canDispose
.
signalparam
=
None
self
.
loadOperatorAvailable
.
signalparam
=
None
if
self
.
canDispose
in
receivedEvent
or
self
.
loadOperatorAvailable
in
receivedEvent
:
# self.canDispose.signalparam=None
self
.
canDispose
=
self
.
env
.
event
()
# self.loadOperatorAvailable.signalparam=None
self
.
loadOperatorAvailable
=
self
.
env
.
event
()
if
self
.
haveToDispose
():
if
self
.
signalReceiver
():
continue
...
...
@@ -188,7 +197,7 @@ class Source(CoreObject):
newEntity
=
self
.
createEntity
()
# create the Entity object and assign its name
newEntity
.
creationTime
=
self
.
scheduledEntities
.
pop
(
0
)
# assign the current simulation time as the Entity's creation time
newEntity
.
startTime
=
newEntity
.
creationTime
# assign the current simulation time as the Entity's start time
#print
now()
, 'getting from the list. StartTime=',newEntity.startTime
#print
self.env.now
, 'getting from the list. StartTime=',newEntity.startTime
newEntity
.
currentStation
=
self
# update the current station of the Entity
G
.
EntityList
.
append
(
newEntity
)
self
.
getActiveObjectQueue
().
append
(
newEntity
)
# append the entity to the resource
...
...
@@ -197,5 +206,5 @@ class Source(CoreObject):
self
.
appendEntity
(
newEntity
)
activeEntity
=
CoreObject
.
removeEntity
(
self
,
entity
)
# run the default method
if
len
(
self
.
getActiveObjectQueue
())
==
1
:
self
.
entityCreated
.
s
ignal
(
newEntity
)
self
.
entityCreated
.
s
ucceed
(
newEntity
)
return
activeEntity
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment