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
9fc33f6a
Commit
9fc33f6a
authored
Nov 04, 2014
by
Georgios Dagkakis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
applications folder intoduced and CapacityObjects added there
parent
8a9dd26a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
952 additions
and
0 deletions
+952
-0
dream/simulation/applications/CapacityStations/CapacityEntity.py
...imulation/applications/CapacityStations/CapacityEntity.py
+56
-0
dream/simulation/applications/CapacityStations/CapacityProject.py
...mulation/applications/CapacityStations/CapacityProject.py
+67
-0
dream/simulation/applications/CapacityStations/CapacityStation.py
...mulation/applications/CapacityStations/CapacityStation.py
+96
-0
dream/simulation/applications/CapacityStations/CapacityStationBuffer.py
...on/applications/CapacityStations/CapacityStationBuffer.py
+65
-0
dream/simulation/applications/CapacityStations/CapacityStationController.py
...pplications/CapacityStations/CapacityStationController.py
+535
-0
dream/simulation/applications/CapacityStations/CapacityStationExit.py
...tion/applications/CapacityStations/CapacityStationExit.py
+85
-0
dream/simulation/applications/CapacityStations/__init__.py
dream/simulation/applications/CapacityStations/__init__.py
+24
-0
dream/simulation/applications/__init__.py
dream/simulation/applications/__init__.py
+24
-0
No files found.
dream/simulation/applications/CapacityStations/CapacityEntity.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 5 June 2013
@author: George
'''
'''
entity that requires specific capacity from a station
'''
from
dream.simulation.Entity
import
Entity
# ===========================================================================
# The CapacityEntity object
# ===========================================================================
class
CapacityEntity
(
Entity
):
type
=
"CapacityEntity"
def
__init__
(
self
,
id
=
None
,
name
=
None
,
capacityProjectId
=
None
,
requiredCapacity
=
10
,
priority
=
0
,
dueDate
=
0
,
orderDate
=
0
,
currentStation
=
None
,
isCritical
=
False
,
**
kw
):
Entity
.
__init__
(
self
,
id
,
name
,
priority
,
dueDate
,
orderDate
,
isCritical
,
currentStation
=
currentStation
)
self
.
capacityProjectId
=
capacityProjectId
# the project id hat the capacity Entity is part of
self
.
capacityProject
=
None
# the project that the capacity Entity is part of. It is defined in initialize
self
.
requiredCapacity
=
requiredCapacity
# the capacity that the capacity entity requires from the following station
self
.
shouldMove
=
False
from
dream.simulation.Globals
import
G
G
.
CapacityEntityList
.
append
(
self
)
def
initialize
(
self
):
Entity
.
initialize
(
self
)
self
.
shouldMove
=
False
from
dream.simulation.Globals
import
G
# find the project that the capacity entity is part of
for
project
in
G
.
CapacityProjectList
:
if
project
.
id
==
self
.
capacityProjectId
:
self
.
capacityProject
=
project
break
\ No newline at end of file
dream/simulation/applications/CapacityStations/CapacityProject.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 5 June 2013
@author: George
'''
'''
a project that requires specific capacity from each station
'''
from
dream.simulation.Entity
import
Entity
# ===========================================================================
# The CapacityEntityProject object
# ===========================================================================
class
CapacityProject
(
Entity
):
type
=
"CapacityProject"
def
__init__
(
self
,
id
=
None
,
name
=
None
,
capacityRequirementDict
=
{},
earliestStartDict
=
{},
dueDate
=
0
,
assemblySpaceRequirement
=
0
,
**
kw
):
Entity
.
__init__
(
self
,
id
,
name
,
dueDate
=
dueDate
)
# a dict that shows the required capacity from every station
self
.
capacityRequirementDict
=
capacityRequirementDict
# a dict that shows the earliest start in every station
self
.
earliestStartDict
=
earliestStartDict
# the assembly space the project requires
self
.
assemblySpaceRequirement
=
assemblySpaceRequirement
from
dream.simulation.Globals
import
G
G
.
CapacityProjectList
.
append
(
self
)
def
initialize
(
self
):
self
.
projectSchedule
=
[]
# a list of dicts to keep the schedule
self
.
alreadyWorkedDict
=
{}
# a dict that hold what has been processed at every station
for
stationId
in
self
.
capacityRequirementDict
:
self
.
alreadyWorkedDict
[
stationId
]
=
0
# =======================================================================
# outputs results to JSON File
# =======================================================================
def
outputResultsJSON
(
self
):
from
dream.simulation.Globals
import
G
json
=
{
'_class'
:
'Dream.%s'
%
(
self
.
__class__
.
__name__
),
'id'
:
self
.
id
,
'family'
:
'Job'
,
'results'
:
{}}
if
(
G
.
numberOfReplications
==
1
):
# if we had just one replication output the results as numbers
json
[
'results'
][
'schedule'
]
=
self
.
projectSchedule
G
.
outputJSON
[
'elementList'
].
append
(
json
)
dream/simulation/applications/CapacityStations/CapacityStation.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 5 June 2013
@author: George
'''
'''
a station that can process a specified capacity in every time period
'''
from
dream.simulation.Queue
import
Queue
import
simpy
# ===========================================================================
# the CapacityStation object
# ===========================================================================
class
CapacityStation
(
Queue
):
family
=
'CapacityStation'
#===========================================================================
# the __init__ method of the CapacityStation
#===========================================================================
def
__init__
(
self
,
id
,
name
,
capacity
=
float
(
"inf"
),
intervalCapacity
=
[],
schedulingRule
=
"FIFO"
,
gatherWipStat
=
False
,
sharedResources
=
{},
**
kw
):
Queue
.
__init__
(
self
,
id
,
name
,
capacity
=
capacity
)
# a list that holds the capacity (manhours) that is available in each interval
self
.
intervalCapacity
=
intervalCapacity
# a list that holds the capacity (manhours) that is available in each interval for the remaining time
self
.
remainingIntervalCapacity
=
list
(
self
.
intervalCapacity
)
# blocks the entry of the capacity station, so that it can be manipulated to accept only in certain moments of simulation time
self
.
isLocked
=
True
# dict that holds information if station shares workpower with some other station
self
.
sharedResources
=
sharedResources
def
initialize
(
self
):
Queue
.
initialize
(
self
)
# if the station shares resources and the capacity is not defined in this
# then read it from some other of the sharing stations
if
not
self
.
intervalCapacity
and
self
.
sharedResources
:
for
stationId
in
self
.
sharedResources
.
get
(
'stationIds'
,[]):
import
dream.simulation.Globals
station
=
Globals
.
findObjectById
(
stationId
)
if
station
.
intervalCapacity
:
self
.
intervalCapacity
=
station
.
intervalCapacity
break
# initialize variables
self
.
remainingIntervalCapacity
=
list
(
self
.
intervalCapacity
)
self
.
isLocked
=
True
self
.
utilisationDict
=
[]
# a list of dicts for the utilization results
self
.
detailedWorkPlan
=
[]
# a list of dicts to keep detailed data
from
dream.simulation.Globals
import
G
G
.
CapacityStationList
.
append
(
self
)
def
canAccept
(
self
,
callerObject
=
None
):
if
self
.
isLocked
:
return
False
return
Queue
.
canAccept
(
self
)
# =======================================================================
# outputs results to JSON File
# =======================================================================
def
outputResultsJSON
(
self
):
from
dream.simulation.Globals
import
G
json
=
{
'_class'
:
'Dream.%s'
%
self
.
__class__
.
__name__
,
'id'
:
self
.
id
,
'family'
:
self
.
family
,
'results'
:
{}}
if
(
G
.
numberOfReplications
==
1
):
# if we had just one replication output the results as numbers
json
[
'results'
][
'capacityUsed'
]
=
self
.
utilisationDict
meanUtilization
=
0
for
entry
in
self
.
utilisationDict
:
meanUtilization
+=
entry
[
'utilization'
]
/
float
(
len
(
self
.
utilisationDict
))
json
[
'results'
][
'meanUtilization'
]
=
meanUtilization
json
[
'results'
][
'detailedWorkPlan'
]
=
self
.
detailedWorkPlan
G
.
outputJSON
[
'elementList'
].
append
(
json
)
\ No newline at end of file
dream/simulation/applications/CapacityStations/CapacityStationBuffer.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 6 June 2013
@author: George
'''
'''
the buffer of the capacity station. Only change from queue that it can be blocked.
'''
import
simpy
from
dream.simulation.Queue
import
Queue
# ===========================================================================
# the Queue object
# ===========================================================================
class
CapacityStationBuffer
(
Queue
):
#===========================================================================
# the __init__ method of the CapacityStationBuffer
#===========================================================================
def
__init__
(
self
,
id
,
name
,
requireFullProject
=
False
,
capacity
=
float
(
"inf"
),
isDummy
=
False
,
schedulingRule
=
"FIFO"
,
gatherWipStat
=
False
,
**
kw
):
Queue
.
__init__
(
self
,
id
,
name
,
capacity
=
capacity
)
self
.
isLocked
=
True
self
.
requireFullProject
=
requireFullProject
# flag that shows if here the whole project is assembled
from
dream.simulation.Globals
import
G
G
.
CapacityStationBufferList
.
append
(
self
)
def
initialize
(
self
):
Queue
.
initialize
(
self
)
self
.
isLocked
=
True
def
canAccept
(
self
,
callerObject
=
None
):
if
self
.
isLocked
:
return
False
return
Queue
.
canAccept
(
self
)
def
haveToDispose
(
self
,
callerObject
=
None
):
activeObjectQ
=
self
.
getActiveObjectQueue
()
if
len
(
activeObjectQ
)
==
0
:
return
False
if
not
activeObjectQ
[
0
].
shouldMove
:
return
False
# put the entities that should move in front
def
sortEntities
(
self
):
activeObjectQ
=
self
.
getActiveObjectQueue
()
activeObjectQ
.
sort
(
key
=
lambda
x
:
x
.
shouldMove
,
reverse
=
True
)
dream/simulation/applications/CapacityStations/CapacityStationController.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 6 June 2013
@author: George
'''
'''
event generator that controls the capacity station objects
'''
import
simpy
from
dream.simulation.EventGenerator
import
EventGenerator
from
dream.simulation.applications.CapacityStations.CapacityEntity
import
CapacityEntity
from
dream.simulation.Globals
import
G
class
CapacityStationController
(
EventGenerator
):
def
__init__
(
self
,
id
=
id
,
name
=
None
,
start
=
0
,
stop
=
float
(
'inf'
),
interval
=
1
,
duration
=
0
,
method
=
None
,
argumentDict
=
{},
dueDateThreshold
=
float
(
'inf'
),
prioritizeIfCanFinish
=
False
,
**
kw
):
EventGenerator
.
__init__
(
self
,
id
,
name
,
start
,
stop
,
interval
,
duration
,
method
,
argumentDict
)
# attribute used by optimization in calculateWhatIsToBeProcessed
# only the projects that are within this threshold from the one with EDD in the same bufffer
# will be considered to move at first
self
.
dueDateThreshold
=
float
(
dueDateThreshold
)
# attribute that shows if we prioritize entities that can finish work in this station in the next interval
self
.
prioritizeIfCanFinish
=
bool
(
int
(
prioritizeIfCanFinish
))
# the total assemblySpace in the system
self
.
assemblySpace
=
float
(
G
.
extraPropertyDict
.
get
(
'assemblySpace'
,
float
(
'inf'
)))
self
.
method
=
self
.
steps
def
initialize
(
self
):
EventGenerator
.
initialize
(
self
)
# sort the buffers so if they have shared resources the ones with highest priority will go in front
self
.
sortBuffers
()
# the main loop that is carried in every interval
def
steps
(
self
):
# loop through the stations
for
station
in
G
.
CapacityStationList
:
exit
=
station
.
next
[
0
]
# take the exit
exit
.
isLocked
=
False
# unlock the exit
# loop though the entities
entitiesToCheck
=
list
(
station
.
getActiveObjectQueue
())
for
entity
in
entitiesToCheck
:
if
not
exit
.
isRequested
.
triggered
:
# this is needed because the signal can be triggered also by the buffer
if
exit
.
expectedSignals
[
'isRequested'
]:
self
.
sendSignal
(
receiver
=
exit
,
signal
=
exit
.
isRequested
)
# wait until the entity is removed
station
.
waitEntityRemoval
=
True
station
.
expectedSignals
[
'entityRemoved'
]
=
1
yield
station
.
entityRemoved
transmitter
,
eventTime
=
station
.
entityRemoved
.
value
station
.
waitEntityRemoval
=
False
exit
.
currentlyObtainedEntities
.
append
(
entity
)
station
.
entityRemoved
=
self
.
env
.
event
()
project
=
entity
.
capacityProject
# output the finish time of the project. This will updated every time, so in the end it should be correct
for
entry
in
project
.
projectSchedule
:
if
entry
[
'stationId'
]
==
station
.
id
:
entry
[
'exitTime'
]
=
self
.
env
.
now
# lock the exit again
exit
.
isLocked
=
True
# create the entities in the following stations
self
.
createInCapacityStationBuffers
()
# if the last exits led to an empty system then the simulation must be stopped
# step returns and the generator never yields the stepsAreComplete signal
if
self
.
checkIfSystemEmpty
():
# if the system is empty set stop to now so that the generator stops and return
self
.
stop
=
self
.
env
.
now
return
# if there is need to merge entities in a buffer
self
.
mergeEntities
()
# Calculate from the last moves in Station->StationExits
# what should be created in StationBuffers and create it
self
.
createInCapacityStationBuffers
()
# Calculate what should be given in every Station
# and set the flags to the entities of StationBuffers
self
.
calculateWhatIsToBeProcessed
()
# move the entities into the stations
# loop through the stations
for
station
in
G
.
CapacityStationList
:
station
.
isLocked
=
False
# unlock the station
buffer
=
station
.
previous
[
0
]
# take the buffer
buffer
.
sortEntities
()
# sort the entities of the buffer so the ones to move go in front
periodDict
=
{}
periodDict
[
'period'
]
=
self
.
env
.
now
# loop though the entities
entitiesToCheck
=
list
(
buffer
.
getActiveObjectQueue
())
capacityAvailable
=
station
.
intervalCapacity
[
int
(
self
.
env
.
now
)]
capacityAllocated
=
0
for
entity
in
entitiesToCheck
:
if
not
entity
.
shouldMove
:
# when the first entity that should not move is reached break
break
# ToDo, here we do not check if station.expectedSignals['isRequested']==1
# consistency problem?
self
.
sendSignal
(
receiver
=
station
,
signal
=
station
.
isRequested
)
buffer
.
waitEntityRemoval
=
True
buffer
.
expectedSignals
[
'entityRemoved'
]
=
1
yield
buffer
.
entityRemoved
transmitter
,
eventTime
=
buffer
.
entityRemoved
.
value
buffer
.
waitEntityRemoval
=
False
buffer
.
entityRemoved
=
self
.
env
.
event
()
project
=
entity
.
capacityProject
periodDict
[
project
.
id
]
=
entity
.
requiredCapacity
# dict to be appended in the utilization list
# append the move in the detailedWorkPlan of the station
station
.
detailedWorkPlan
.
append
({
'time'
:
self
.
env
.
now
,
'operation'
:
station
.
id
,
'project'
:
project
.
id
,
'allocation'
:
entity
.
requiredCapacity
})
capacityAllocated
+=
entity
.
requiredCapacity
if
self
.
checkIfProjectJustStartsInStation
(
project
,
station
):
project
.
projectSchedule
.
append
({
"stationId"
:
station
.
id
,
"entranceTime"
:
self
.
env
.
now
})
# lock the station
station
.
isLocked
=
True
# calculate the utilization
if
capacityAvailable
:
periodDict
[
'utilization'
]
=
capacityAllocated
/
float
(
capacityAvailable
)
else
:
# TODO check how the utilization and mean utilization should be calculated if it is 0
periodDict
[
'utilization'
]
=
0
# update the utilisationDict of the station
station
.
utilisationDict
.
append
(
periodDict
)
# for every station update the remaining interval capacity so that it is ready for next loop
for
station
in
G
.
CapacityStationList
:
station
.
remainingIntervalCapacity
.
pop
(
0
)
# invoked after entities have exited one station to create
# the corresponding entities to the following buffer
def
createInCapacityStationBuffers
(
self
):
# loop through the exits
for
exit
in
G
.
CapacityStationExitList
:
# if the exit received nothing currently there is nothing to do
if
exit
.
currentlyObtainedEntities
==
[]:
continue
buffer
=
exit
.
nextCapacityStationBuffer
# the next buffer
# if it is the end of the system there is nothing to do
if
not
buffer
:
exit
.
currentlyObtainedEntities
=
[]
continue
previousStation
=
exit
.
previous
[
0
]
# the station the the entity just finished from
previousBuffer
=
previousStation
.
previous
[
0
]
# the buffer of the station
nextStation
=
buffer
.
next
[
0
]
# the next processing station
# for every entity calculate the new entity to be created in the next station and create it
for
entity
in
exit
.
currentlyObtainedEntities
:
project
=
entity
.
capacityProject
# if the entity exits from an assembly station
# and not all project is finished there, then do not create anything in the next
if
previousBuffer
.
requireFullProject
:
projectFinishedFromLast
=
True
for
e
in
previousBuffer
.
getActiveObjectQueue
():
if
e
.
capacityProject
==
project
:
projectFinishedFromLast
=
False
break
if
not
projectFinishedFromLast
:
continue
entityCapacity
=
entity
.
requiredCapacity
previousRequirement
=
float
(
project
.
capacityRequirementDict
[
previousStation
.
id
])
nextRequirement
=
float
(
project
.
capacityRequirementDict
[
nextStation
.
id
])
# if the previous station was assembly then in the next the full project arrives
# so requires whatever the project requires
if
previousBuffer
.
requireFullProject
:
nextStationCapacityRequirement
=
nextRequirement
# else calculate proportionally
else
:
proportion
=
nextRequirement
/
previousRequirement
nextStationCapacityRequirement
=
proportion
*
entityCapacity
entityToCreateName
=
entity
.
capacityProjectId
+
'_'
+
nextStation
.
objName
+
'_'
+
str
(
nextStationCapacityRequirement
)
entityToCreate
=
CapacityEntity
(
name
=
entityToCreateName
,
capacityProjectId
=
entity
.
capacityProjectId
,
requiredCapacity
=
nextStationCapacityRequirement
)
entityToCreate
.
currentStation
=
buffer
entityToCreate
.
initialize
()
import
dream.simulation.Globals
as
Globals
Globals
.
setWIP
([
entityToCreate
])
#set the new components as wip
# reset the currently obtained entities list to empty
exit
.
currentlyObtainedEntities
=
[]
def
calculateWhatIsToBeProcessed
(
self
):
import
dream.simulation.Globals
as
Globals
# calculate what space is available
availableSpace
=
self
.
assemblySpace
-
self
.
calculateConsumedSpace
()
assert
availableSpace
>=
0
,
'negative available space'
# list to hold the buffers that are already considered (due to shared resources)
alreadyConsideredBuffers
=
[]
# loop through the capacity station buffers
for
buffer
in
G
.
CapacityStationBufferList
:
# if the buffer was considered before (due to shared resources) continue
if
buffer
in
alreadyConsideredBuffers
:
continue
alreadyConsideredBuffers
.
append
(
buffer
)
sharedBuffers
=
[]
station
=
buffer
.
next
[
0
]
# get the station
# find the stations that share resources with the one considered now
if
station
.
sharedResources
:
sharedStations
=
station
.
sharedResources
.
get
(
'stationIds'
,[])
for
element
in
sharedStations
:
s
=
Globals
.
findObjectById
(
element
)
b
=
s
.
previous
[
0
]
sharedBuffers
.
append
(
b
)
activeObjectQueue
=
buffer
.
getActiveObjectQueue
()
# the entities considered should be the entities in the current buffer plus the ones in buffers
# of stations that share resources with the current one
entitiesConsidered
=
list
(
activeObjectQueue
)
for
b
in
sharedBuffers
:
entitiesConsidered
+=
b
.
getActiveObjectQueue
()
alreadyConsideredBuffers
.
append
(
b
)
# sort entities according to due date of the project that each belongs to
entitiesConsidered
.
sort
(
key
=
lambda
x
:
x
.
capacityProject
.
dueDate
)
totalAvailableCapacity
=
station
.
remainingIntervalCapacity
[
0
]
# get the available capacity of the station
# for this interval
# list to keep entities that have not been already allocated
entitiesNotAllocated
=
list
(
entitiesConsidered
)
allCapacityConsumed
=
False
# if there is no available capacity no need to do anything
if
totalAvailableCapacity
==
0
:
continue
while
not
allCapacityConsumed
:
# list to keep entities that are within a threshold from the EDD
entitiesWithinThreshold
=
[]
# list to keep entities that are outside a threshold from the EDD
entitiesOutsideThreshold
=
[]
# get the EDD
EDD
=
float
(
'inf'
)
for
entity
in
entitiesNotAllocated
:
if
EDD
>
entity
.
capacityProject
.
dueDate
:
EDD
=
entity
.
capacityProject
.
dueDate
# put the entities in the corresponding list according to their due date
for
entity
in
entitiesNotAllocated
:
if
entity
.
capacityProject
.
dueDate
-
EDD
<=
self
.
dueDateThreshold
:
entitiesWithinThreshold
.
append
(
entity
)
else
:
entitiesOutsideThreshold
.
append
(
entity
)
# calculate the total capacity that is requested
totalRequestedCapacity
=
0
for
entity
in
entitiesWithinThreshold
:
# get buffer where the entity is and the station it requests to get in
entityBuffer
=
entity
.
currentStation
entityStation
=
entity
.
currentStation
.
next
[
0
]
# entities that cannot start (due to space, need for assembly or earliest start)
# do not request for capacity
if
self
.
checkIfProjectCanStartInStation
(
entity
.
capacityProject
,
entityStation
)
and
\
(
not
self
.
checkIfProjectNeedsToBeAssembled
(
entity
.
capacityProject
,
entityBuffer
))
\
and
self
.
checkIfThereIsEnoughSpace
(
entity
,
entityBuffer
,
availableSpace
):
totalRequestedCapacity
+=
entity
.
requiredCapacity
# if there is enough capacity for all the entities set them that they all should move
if
totalRequestedCapacity
<=
totalAvailableCapacity
:
for
entity
in
entitiesWithinThreshold
:
# get buffer where the entity is and the station it requests to get in
entityBuffer
=
entity
.
currentStation
entityStation
=
entity
.
currentStation
.
next
[
0
]
if
self
.
checkIfProjectCanStartInStation
(
entity
.
capacityProject
,
entityStation
)
and
\
(
not
self
.
checkIfProjectNeedsToBeAssembled
(
entity
.
capacityProject
,
entityBuffer
))
\
and
self
.
checkIfThereIsEnoughSpace
(
entity
,
entityBuffer
,
availableSpace
):
entity
.
shouldMove
=
True
# reduce the available space if there is need to
if
entityBuffer
.
requireFullProject
and
\
(
not
self
.
checkIfProjectConsumesAssemblySpace
(
entity
,
entityBuffer
)):
availableSpace
-=
entity
.
capacityProject
.
assemblySpaceRequirement
assert
availableSpace
>=
0
,
'negative available space'
# remove the entity from the none allocated ones
entitiesNotAllocated
.
remove
(
entity
)
# check if all the capacity is consumed to update the flag and break the loop
if
totalRequestedCapacity
==
totalAvailableCapacity
:
# the capacity will be 0 since we consumed it all
totalAvailableCapacity
=
0
allCapacityConsumed
=
True
# if we still have available capacity
else
:
# check in the entities outside the threshold if there is one or more that can be moved
haveMoreEntitiesToAllocate
=
False
for
entity
in
entitiesOutsideThreshold
:
# get buffer where the entity is and the station it requests to get in
entityBuffer
=
entity
.
currentStation
entityStation
=
entity
.
currentStation
.
next
[
0
]
if
self
.
checkIfProjectCanStartInStation
(
entity
.
capacityProject
,
entityStation
)
and
\
(
not
self
.
checkIfProjectNeedsToBeAssembled
(
entity
.
capacityProject
,
entityBuffer
))
\
and
self
.
checkIfThereIsEnoughSpace
(
entity
,
entityBuffer
,
availableSpace
):
haveMoreEntitiesToAllocate
=
True
break
# otherwise we have to calculate the capacity for next loop
# the remaining capacity will be decreased by the one that was originally requested
totalAvailableCapacity
-=
totalRequestedCapacity
# if we have more entities break
if
not
haveMoreEntitiesToAllocate
:
break
# else calculate the capacity for every entity and create the entities
else
:
allCapacityConsumed
=
True
entitiesToBeBroken
=
list
(
entitiesWithinThreshold
)
# we sort the entities so the ones that can finish in current period (if any) go in front
entitiesToBeBroken
.
sort
(
key
=
lambda
\
x
:
self
.
checkIfAProjectCanBeFinishedInStation
(
x
,
x
.
currentStation
.
next
[
0
],
totalAvailableCapacity
)
\
and
self
.
prioritizeIfCanFinish
,
reverse
=
True
)
# loop through the entities
for
entity
in
entitiesToBeBroken
:
# get buffer where the entity is and the station it requests to get in
entityBuffer
=
entity
.
currentStation
entityStation
=
entity
.
currentStation
.
next
[
0
]
# consider only entities that can move - not those waiting for assembly or earliest start
if
self
.
checkIfProjectCanStartInStation
(
entity
.
capacityProject
,
entityStation
)
and
\
(
not
self
.
checkIfProjectNeedsToBeAssembled
(
entity
.
capacityProject
,
entityBuffer
))
and
\
self
.
checkIfThereIsEnoughSpace
(
entity
,
entityBuffer
,
availableSpace
):
# if we prioritize an entity that can completely finish then check for this
if
self
.
checkIfAProjectCanBeFinishedInStation
(
entity
,
entityStation
,
totalAvailableCapacity
)
\
and
self
.
prioritizeIfCanFinish
:
# set that the entity can move
entity
.
shouldMove
=
True
# reduce the available space if there is need to
if
entityBuffer
.
requireFullProject
and
\
(
not
self
.
checkIfProjectConsumesAssemblySpace
(
entity
,
entityBuffer
)):
availableSpace
-=
entity
.
capacityProject
.
assemblySpaceRequirement
assert
availableSpace
>=
0
,
'negative available space'
# update the values
totalAvailableCapacity
-=
entity
.
requiredCapacity
totalRequestedCapacity
-=
entity
.
requiredCapacity
# else break the entity according to rule
else
:
self
.
breakEntity
(
entity
,
entityBuffer
,
entityStation
,
totalAvailableCapacity
,
totalRequestedCapacity
)
# reduce the available space if there is need to
if
entityBuffer
.
requireFullProject
and
\
(
not
self
.
checkIfProjectConsumesAssemblySpace
(
entity
,
entityBuffer
)):
availableSpace
-=
entity
.
capacityProject
.
assemblySpaceRequirement
assert
availableSpace
>=
0
,
'negative available space'
# breaks an entity in the part that should move and the one that should stay
def
breakEntity
(
self
,
entity
,
buffer
,
station
,
totalAvailableCapacity
,
totalRequestedCapacity
):
# calculate what is the capacity that should proceed and what that should remain
capacityToMove
=
totalAvailableCapacity
*
(
entity
.
requiredCapacity
)
/
float
(
totalRequestedCapacity
)
capacityToStay
=
entity
.
requiredCapacity
-
capacityToMove
# remove the capacity entity by the buffer so that the broken ones are created
buffer
.
getActiveObjectQueue
().
remove
(
entity
)
entityToMoveName
=
entity
.
capacityProjectId
+
'_'
+
station
.
objName
+
'_'
+
str
(
capacityToMove
)
entityToMove
=
CapacityEntity
(
name
=
entityToMoveName
,
capacityProjectId
=
entity
.
capacityProjectId
,
requiredCapacity
=
capacityToMove
)
entityToMove
.
initialize
()
entityToMove
.
currentStation
=
buffer
entityToMove
.
shouldMove
=
True
entityToStayName
=
entity
.
capacityProjectId
+
'_'
+
station
.
objName
+
'_'
+
str
(
capacityToStay
)
entityToStay
=
CapacityEntity
(
name
=
entityToStayName
,
capacityProjectId
=
entity
.
capacityProjectId
,
requiredCapacity
=
capacityToStay
)
entityToStay
.
initialize
()
entityToStay
.
currentStation
=
buffer
import
dream.simulation.Globals
as
Globals
Globals
.
setWIP
([
entityToMove
,
entityToStay
])
#set the new components as wip
# merges the capacity entities if they belong to the same project
def
mergeEntities
(
self
):
# loop through the capacity station buffers
for
buffer
in
G
.
CapacityStationBufferList
:
nextStation
=
buffer
.
next
[
0
]
projectList
=
[]
# loop through the entities to see what projects lie in the buffer
for
entity
in
buffer
.
getActiveObjectQueue
():
if
entity
.
capacityProject
not
in
projectList
:
projectList
.
append
(
entity
.
capacityProject
)
for
project
in
projectList
:
entitiesToBeMerged
=
[]
for
entity
in
buffer
.
getActiveObjectQueue
():
if
entity
.
capacityProject
==
project
:
entitiesToBeMerged
.
append
(
entity
)
totalCapacityRequirement
=
0
# if the buffer acts as assembly there is no need to calculate the total capacity requirement,
# it will be the one that the project has as a total for this station
if
buffer
.
requireFullProject
:
# find what has been already processed
alreadyProcessed
=
0
for
record
in
nextStation
.
detailedWorkPlan
:
if
record
[
'project'
]
==
project
.
id
:
alreadyProcessed
+=
float
(
record
[
'allocation'
])
totalCapacityRequirement
=
project
.
capacityRequirementDict
[
nextStation
.
id
]
-
alreadyProcessed
# else calculate the total capacity requirement by adding the one each entity requires
else
:
for
entity
in
entitiesToBeMerged
:
totalCapacityRequirement
+=
entity
.
requiredCapacity
# erase the Entities to create the merged one
for
entity
in
entitiesToBeMerged
:
buffer
.
getActiveObjectQueue
().
remove
(
entity
)
# create the merged entity
entityToCreateName
=
entity
.
capacityProjectId
+
'_'
+
nextStation
.
objName
+
'_'
+
str
(
totalCapacityRequirement
)
entityToCreate
=
CapacityEntity
(
name
=
entityToCreateName
,
capacityProjectId
=
project
.
id
,
requiredCapacity
=
totalCapacityRequirement
)
entityToCreate
.
currentStation
=
buffer
entityToCreate
.
initialize
()
import
dream.simulation.Globals
as
Globals
Globals
.
setWIP
([
entityToCreate
])
#set the new components as wip
# checks if the system is empty so that the simulation can be stopped
def
checkIfSystemEmpty
(
self
):
for
object
in
G
.
CapacityStationList
+
G
.
CapacityStationBufferList
+
G
.
CapacityStationExitList
:
if
len
(
object
.
getActiveObjectQueue
()):
return
False
return
True
# checks if a project is just starting in station
def
checkIfProjectJustStartsInStation
(
self
,
project
,
station
):
for
entry
in
project
.
projectSchedule
:
if
entry
[
'stationId'
]
==
station
.
id
:
return
False
return
True
# checks if a project cannot move because it needs to be assembled first
def
checkIfProjectNeedsToBeAssembled
(
self
,
project
,
buffer
):
# if we are not in assembly return false
if
not
buffer
.
requireFullProject
:
return
False
# if project is already assembled return false
if
self
.
checkIfProjectAssembledInBuffer
(
project
,
buffer
):
return
False
# at any other case return true
return
True
# checks if the given project is all in the buffer
def
checkIfProjectAssembledInBuffer
(
self
,
project
,
buffer
):
# loop through all the stations of the system
for
object
in
G
.
CapacityStationList
+
G
.
CapacityStationBufferList
+
G
.
CapacityStationExitList
:
# skip the given buffer
if
object
is
buffer
:
continue
# if there is one entity from the same project which we check somewhere else return false
for
entity
in
object
.
getActiveObjectQueue
():
if
entity
.
capacityProject
==
project
:
return
False
# if nothing was found return true
return
True
# checks if the given project can start in the station or not because there is an earliest start defined
def
checkIfProjectCanStartInStation
(
self
,
project
,
station
):
earliestStartInStation
=
project
.
earliestStartDict
.
get
(
station
.
id
,
0
)
if
self
.
env
.
now
<
earliestStartInStation
:
return
False
return
True
# checks if the whole project can be finished in one station in the next time period
def
checkIfAProjectCanBeFinishedInStation
(
self
,
entity
,
station
,
availableCapacity
):
required
=
entity
.
requiredCapacity
alreadyWorked
=
entity
.
capacityProject
.
alreadyWorkedDict
[
station
.
id
]
total
=
entity
.
capacityProject
.
capacityRequirementDict
[
station
.
id
]
# return true if all the work can be finished and if there is available capacity
if
total
-
(
alreadyWorked
+
required
)
<
0.001
and
availableCapacity
>=
required
:
# a small value to avoid mistakes due to rounding
return
True
return
False
# returns true if there is enough space for the entity to move
def
checkIfThereIsEnoughSpace
(
self
,
entity
,
buffer
,
availableSpace
):
if
buffer
.
requireFullProject
:
# if the project already consumes assembly space then there is enough space for it
if
self
.
checkIfProjectConsumesAssemblySpace
(
entity
,
buffer
):
return
True
# else check if there is enough space
return
entity
.
capacityProject
.
assemblySpaceRequirement
<=
availableSpace
# if the station is not assembly then return true
return
True
# sorts the buffers so if they have shared resources the ones with highest priority will go in front
def
sortBuffers
(
self
):
for
buffer
in
G
.
CapacityStationBufferList
:
station
=
buffer
.
next
[
0
]
buffer
.
sharedPriority
=
station
.
sharedResources
.
get
(
'priority'
,
-
float
(
'inf'
))
G
.
CapacityStationBufferList
.
sort
(
key
=
lambda
x
:
x
.
sharedPriority
,
reverse
=
True
)
# calculates the space that is already consumed before the allocation for current period
def
calculateConsumedSpace
(
self
):
consumedSpace
=
0
# loop in the buffers and find projects that have started assembly without having been finished
# add what they consume
for
buffer
in
G
.
CapacityStationBufferList
:
station
=
buffer
.
next
[
0
]
for
entity
in
buffer
.
getActiveObjectQueue
():
if
self
.
checkIfProjectConsumesAssemblySpace
(
entity
,
buffer
):
consumedSpace
+=
entity
.
capacityProject
.
assemblySpaceRequirement
return
consumedSpace
# checks if a project already consumes assembly space because assembly work started in a previous period
# and was not completed
def
checkIfProjectConsumesAssemblySpace
(
self
,
entity
,
buffer
):
if
buffer
.
requireFullProject
:
station
=
buffer
.
next
[
0
]
project
=
entity
.
capacityProject
projectRequirement
=
project
.
capacityRequirementDict
[
station
.
id
]
if
projectRequirement
>
entity
.
requiredCapacity
:
return
True
return
False
\ No newline at end of file
dream/simulation/applications/CapacityStations/CapacityStationExit.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
'''
Created on 6 June 2013
@author: George
'''
'''
the exit of the capacity station. Only change from buffer that it can be blocked.
'''
from
dream.simulation.Exit
import
Exit
import
simpy
# ===========================================================================
# the CapacityStationExit object
# ===========================================================================
class
CapacityStationExit
(
Exit
):
#===========================================================================
# the __init__ method of the CapacityStationExit
#===========================================================================
def
__init__
(
self
,
id
,
name
=
None
,
nextCapacityStationBufferId
=
None
,
**
kw
):
Exit
.
__init__
(
self
,
id
,
name
)
self
.
isLocked
=
True
self
.
nextCapacityStationBufferId
=
nextCapacityStationBufferId
# the id of the next station. If it is None it
# means it is the end of the system.
self
.
nextCapacityStationBuffer
=
None
# the next buffer. If it is None it
from
dream.simulation.Globals
import
G
G
.
CapacityStationExitList
.
append
(
self
)
# means it is the end of the system.
def
initialize
(
self
):
Exit
.
initialize
(
self
)
self
.
isLocked
=
True
# list that contains the entities that are just obtained so that they can be
# moved to the next buffer
self
.
currentlyObtainedEntities
=
[]
# find the next buffer
if
self
.
nextCapacityStationBufferId
:
from
dream.simulation.Globals
import
G
# find the project that the capacity entity is part of
for
capacityStationBuffer
in
G
.
CapacityStationBufferList
:
if
capacityStationBuffer
.
id
==
self
.
nextCapacityStationBufferId
:
self
.
nextCapacityStationBuffer
=
capacityStationBuffer
break
def
canAccept
(
self
,
callerObject
=
None
):
if
self
.
isLocked
:
return
False
return
Exit
.
canAccept
(
self
)
# =======================================================================
# outputs results to JSON File
# =======================================================================
def
outputResultsJSON
(
self
):
# output results only for the last exit
if
not
self
.
nextCapacityStationBuffer
:
Exit
.
outputResultsJSON
(
self
)
# extend so that it updates alreadyWorkedDict of the project
def
getEntity
(
self
):
activeEntity
=
Exit
.
getEntity
(
self
)
alreadyWorkedDict
=
activeEntity
.
capacityProject
.
alreadyWorkedDict
stationId
=
self
.
giver
.
id
alreadyWorkedDict
[
stationId
]
+=
activeEntity
.
requiredCapacity
\ No newline at end of file
dream/simulation/applications/CapacityStations/__init__.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try
:
__import__
(
'pkg_resources'
).
declare_namespace
(
__name__
)
except
ImportError
:
from
pkgutil
import
extend_path
__path__
=
extend_path
(
__path__
,
__name__
)
\ No newline at end of file
dream/simulation/applications/__init__.py
0 → 100644
View file @
9fc33f6a
# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM. If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
try
:
__import__
(
'pkg_resources'
).
declare_namespace
(
__name__
)
except
ImportError
:
from
pkgutil
import
extend_path
__path__
=
extend_path
(
__path__
,
__name__
)
\ No newline at end of file
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