Commit a1556795 authored by Georgios Dagkakis's avatar Georgios Dagkakis

first version of Dismantle object added to the library

parent cab0f78e
......@@ -115,11 +115,11 @@ class Assembly(Process):
def canAccept(self):
return len(self.Res.activeQ)==0
#checks if the machine can accept an entity and there is a Frame waiting for it
#checks if the Assembly can accept an entity and there is a Frame waiting for it
def canAcceptAndIsRequested(self):
return len(self.Res.activeQ)==0 and self.previousFrame[0].haveToDispose()
#checks if the machine can accept an entity and there is a Frame waiting for it
#checks if the Assembly can accept an entity and there is a Frame waiting for it
def isRequestedFromPart(self):
return len(self.Res.activeQ)==1 and self.previousPart[0].haveToDispose()
......@@ -127,7 +127,7 @@ class Assembly(Process):
def haveToDispose(self):
return len(self.Res.activeQ)>0 and self.waitToDispose
#sets the routing in and out elements for the queue
#sets the routing in and out elements for the Assembly
def defineRouting(self, pp, pf, n):
self.next=n
self.previousPart=pp
......
'''
Created on 21 May 2013
@author: George
'''
'''
Models a dicmantle object
it gathers frames that have parts loaded, unloads the parts and sends the frame to one destination and the parts to another
'''
from SimPy.Simulation import *
import xlwt
from RandomNumberGenerator import RandomNumberGenerator
import scipy.stats as stat
#the Dismantle object
class Dismantle(Process):
#initialize the object
def __init__(self, id, name, dist, time):
self.id=id
self.objName=name
self.type="Dismantle" #String that shows the type of object
self.distType=dist #the distribution that the procTime follows
self.rng=RandomNumberGenerator(self, self.distType)
self.rng.avg=time[0]
self.rng.stdev=time[1]
self.rng.min=time[2]
self.rng.max=time[3]
self.previous=[] #list with the previous objects in the flow
self.previousIds=[] #list with the ids of the previous objects in the flow
self.nextPart=[] #list with the next objects that receive parts
self.nextFrame=[] #list with the next objects that receive frames
self.nextIds=[] #list with the ids of the next objects in the flow
self.nextPartIds=[] #list with the ids of the next objects that receive parts
self.nextFrameIds=[] #list with the ids of the next objects that receive frames
#lists to hold statistics of multiple runs
self.Waiting=[]
self.Working=[]
self.Blockage=[]
def initialize(self):
Process.__init__(self)
self.waitToDispose=False #flag that shows if the object waits to dispose an entity
self.waitToDisposePart=False #flag that shows if the object waits to dispose a part
self.waitToDisposeFrame=False #flag that shows if the object waits to dispose a frame
self.Up=True #Boolean that shows if the object is in failure ("Down") or not ("up")
self.currentEntity=None
self.totalFailureTime=0 #holds the total failure time
self.timeLastFailure=0 #holds the time that the last failure of the object started
self.timeLastFailureEnded=0 #holds the time that the last failure of the object Ended
self.downTimeProcessingCurrentEntity=0 #holds the time that the object was down while processing the current entity
self.downTimeInTryingToReleaseCurrentEntity=0 #holds the time that the object was down while trying
#to release the current entity
self.downTimeInCurrentEntity=0 #holds the total time that the object was down while holding current entity
self.timeLastEntityLeft=0 #holds the last time that an entity left the object
self.processingTimeOfCurrentEntity=0 #holds the total processing time that the current entity required
self.totalBlockageTime=0 #holds the total blockage time
self.totalWaitingTime=0 #holds the total waiting time
self.totalWorkingTime=0 #holds the total working time
self.completedJobs=0 #holds the number of completed jobs
self.timeLastEntityEnded=0 #holds the last time that an entity ended processing in the object
self.timeLastEntityEntered=0 #holds the last time that an entity ended processing in the object
self.timeLastFrameWasFull=0 #holds the time that the last frame was full, ie that assembly process started
self.nameLastFrameWasFull="" #holds the name of the last frame that was full, ie that assembly process started
self.nameLastEntityEntered="" #holds the name of the last frame that entered processing in the object
self.nameLastEntityEnded="" #holds the name of the last frame that ended processing in the object
self.Res=Resource(capacity=Infinity)
self.Res.activeQ=[]
self.Res.waitQ=[]
def run(self):
while 1:
yield waituntil, self, self.canAcceptAndIsRequested #wait until the Assembly can accept a frame
#and one "frame" predecessor requests it
self.getEntity() #get the Frame with the parts
self.outputTrace(self.Res.activeQ[0].name, " got into "+ self.objName)
startWorkingTime=now()
yield hold,self,self.rng.generateNumber() #hold for the time the dismantle operation is carried
self.totalWorkingTime+=now()-startWorkingTime
self.timeLastEntityEnded=now()
startBlockageTime=now()
self.waitToDisposePart=True #Dismantle is in state to dispose a part
yield waituntil, self, self.frameIsEmpty #wait until all the parts are disposed
self.waitToDisposePart=False #Dismantle has no parts now
self.waitToDisposeFrame=True #Dismantle is in state to dispose a part
yield waituntil, self, self.isEmpty #wait until all the frame is disposed
self.completedJobs+=1 #Dismantle completed a job
self.waitToDisposeFrame=False #the Dismantle has no Frame to dispose now
self.totalBlockageTime+=now()-startBlockageTime #add the blockage time
#checks if the Dismantle can accept an entity and there is a Frame waiting for it
def canAcceptAndIsRequested(self):
return len(self.Res.activeQ)==0 and self.previous[0].haveToDispose()
#checks if the Dismantle can accept an entity
def canAccept(self):
return len(self.Res.activeQ)==0
#sets the routing in and out elements for the Dismantle
def defineRouting(self, p, np, nf):
self.previous=p
self.nextPart=np
self.nextFrame=nf
#checks if the caller waits for a part or a frame and if the Dismantle is in the state of disposing one it returnse true
def haveToDispose(self):
#identify the caller method
frame = sys._getframe(1)
arguments = frame.f_code.co_argcount
if arguments == 0:
print "Not called from a method"
return
caller_calls_self = frame.f_code.co_varnames[0]
thecaller = frame.f_locals[caller_calls_self]
#according to the caller return true or false
if thecaller in self.nextPart:
return len(self.Res.activeQ)>1 and self.waitToDisposePart
elif thecaller in self.nextFrame:
return len(self.Res.activeQ)==1 and self.waitToDisposeFrame
#checks if the frame is emptied
def frameIsEmpty(self):
return len(self.Res.activeQ)==1
#checks if Dismantle is emptied
def isEmpty(self):
return len(self.Res.activeQ)==0
#gets a frame from the predecessor that the predecessor index points to
def getEntity(self):
self.Res.activeQ.append(self.previous[0].Res.activeQ[0]) #get the frame from the predecessor
self.previous[0].removeEntity()
#append also the parts in the res so that they can be popped
for i in range(self.Res.activeQ[0].numOfParts):
#self.Res.activeQ.append(self.Res.activeQ[0].Res.activeQ[self.Res.activeQ[0].numOfParts-1-i])
self.Res.activeQ.append(self.Res.activeQ[0].Res.activeQ[i])
self.Res.activeQ[0].Res.activeQ=[]
self.Res.activeQ.append(self.Res.activeQ[0])
self.Res.activeQ.pop(0)
#removes an entity from the Dismantle
def removeEntity(self):
#to release the Frame if it is empty
if(len(self.Res.activeQ)==1):
self.outputTrace(self.Res.activeQ[0].name, " releases "+ self.objName)
self.Res.activeQ.pop(0)
self.waitToDisposeFrame=False
elif(len(self.Res.activeQ)>1):
self.outputTrace(self.Res.activeQ[0].name, " releases "+ self.objName)
self.Res.activeQ.pop(0)
if(len(self.Res.activeQ)==1):
self.waitToDisposePart=False
#outputs message to the trace.xls. Format is (Simulation Time | Entity or Frame Name | message)
def outputTrace(self, name, message):
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,1,name)
G.traceSheet.write(G.traceIndex,2,message)
G.traceIndex+=1 #increment the row
#if we reach row 65536 we need to create a new sheet (excel limitation)
if(G.traceIndex==65536):
G.traceIndex=0
G.sheetIndex+=1
G.traceSheet=G.traceFile.add_sheet('sheet '+str(G.sheetIndex), cell_overwrite_ok=True)
#actions to be taken after the simulation ends
def postProcessing(self, MaxSimtime):
'''
#if there is an entity that finished processing in Dismantle but did not get to reach
#the following Object
#till the end of simulation, we have to add this blockage to the percentage of blockage in Machine
#we should exclude the blockage time in current entity though!
if (len(self.next[0].Res.activeQ)>0) and ((self.nameLastEntityEntered == self.nameLastEntityEnded)):
self.totalBlockageTime+=now()-self.timeLastEntityEnded
'''
#if Dismantle is currently processing an entity we should count this working time
if(len(self.Res.activeQ)>0) and (not (self.nameLastEntityEnded==self.nameLastFrameWasFull)):
self.totalWorkingTime+=now()-self.timeLastEntityEnded
self.totalWaitingTime=MaxSimtime-self.totalWorkingTime-self.totalBlockageTime
self.Waiting.append(100*self.totalWaitingTime/MaxSimtime)
self.Working.append(100*self.totalWorkingTime/MaxSimtime)
self.Blockage.append(100*self.totalBlockageTime/MaxSimtime)
#outputs message to the trace.xls. Format is (Simulation Time | Entity or Frame Name | message)
def outputTrace(self, name, message):
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,1,name)
G.traceSheet.write(G.traceIndex,2,message)
G.traceIndex+=1 #increment the row
#if we reach row 65536 we need to create a new sheet (excel limitation)
if(G.traceIndex==65536):
G.traceIndex=0
G.sheetIndex+=1
G.traceSheet=G.traceFile.add_sheet('sheet '+str(G.sheetIndex), cell_overwrite_ok=True)
#outputs data to "output.xls"
def outputResultsXL(self, MaxSimtime):
from Globals import G
if(G.numberOfReplications==1): #if we had just one replication output the results to excel
G.outputSheet.write(G.outputIndex,0, "The percentage of Working of "+self.objName +" is:")
G.outputSheet.write(G.outputIndex,1,100*self.totalWorkingTime/MaxSimtime)
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "The percentage of Blockage of "+self.objName +" is:")
G.outputSheet.write(G.outputIndex,1,100*self.totalBlockageTime/MaxSimtime)
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "The percentage of Waiting of "+self.objName +" is:")
G.outputSheet.write(G.outputIndex,1,100*self.totalWaitingTime/MaxSimtime)
G.outputIndex+=1
else: #if we had multiple replications we output confidence intervals to excel
#for some outputs the results may be the same for each run (eg model is stochastic but failures fixed
#so failurePortion will be exactly the same in each run). That will give 0 variability and errors.
#so for each output value we check if there was difference in the runs' results
#if yes we output the Confidence Intervals. if not we output just the fix value
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean percentage of Working of "+self.objName +" is:")
if self.checkIfArrayHasDifValues(self.Working):
G.outputSheet.write(G.outputIndex,1,stat.bayes_mvs(self.Working, G.confidenceLevel)[0][1][0])
G.outputSheet.write(G.outputIndex,2,stat.bayes_mvs(self.Working, G.confidenceLevel)[0][0])
G.outputSheet.write(G.outputIndex,3,stat.bayes_mvs(self.Working, G.confidenceLevel)[0][1][1])
else:
G.outputSheet.write(G.outputIndex,1,self.Working[0])
G.outputSheet.write(G.outputIndex,2,self.Working[0])
G.outputSheet.write(G.outputIndex,3,self.Working[0])
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean percentage of Blockage of "+self.objName +" is:")
if self.checkIfArrayHasDifValues(self.Blockage):
G.outputSheet.write(G.outputIndex,1,stat.bayes_mvs(self.Blockage, G.confidenceLevel)[0][1][0])
G.outputSheet.write(G.outputIndex,2,stat.bayes_mvs(self.Blockage, G.confidenceLevel)[0][0])
G.outputSheet.write(G.outputIndex,3,stat.bayes_mvs(self.Blockage, G.confidenceLevel)[0][1][1])
else:
G.outputSheet.write(G.outputIndex,1,self.Blockage[0])
G.outputSheet.write(G.outputIndex,2,self.Blockage[0])
G.outputSheet.write(G.outputIndex,3,self.Blockage[0])
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean percentage of Waiting of "+self.objName +" is:")
if self.checkIfArrayHasDifValues(self.Waiting):
G.outputSheet.write(G.outputIndex,1,stat.bayes_mvs(self.Waiting, G.confidenceLevel)[0][1][0])
G.outputSheet.write(G.outputIndex,2,stat.bayes_mvs(self.Waiting, G.confidenceLevel)[0][0])
G.outputSheet.write(G.outputIndex,3,stat.bayes_mvs(self.Waiting, G.confidenceLevel)[0][1][1])
else:
G.outputSheet.write(G.outputIndex,1,self.Waiting[0])
G.outputSheet.write(G.outputIndex,2,self.Waiting[0])
G.outputSheet.write(G.outputIndex,3,self.Waiting[0])
G.outputIndex+=1
G.outputIndex+=1
#takes the array and checks if all its values are identical (returns false) or not (returns true)
#needed because if somebody runs multiple runs in deterministic case it would crash!
def checkIfArrayHasDifValues(self, array):
difValuesFlag=False
for i in range(1, len(array)):
if(array[i]!=array[1]):
difValuesFlag=True
return difValuesFlag
\ No newline at end of file
......@@ -3,7 +3,6 @@ Created on 6 Feb 2013
@author: George
'''
'''
models the exit of the model
'''
......@@ -130,10 +129,10 @@ class Exit(Process):
def outputResultsXL(self, MaxSimtime):
from Globals import G
if(G.numberOfReplications==1): #if we had just one replication output the results to excel
G.outputSheet.write(G.outputIndex,0, "The Throughput is:")
G.outputSheet.write(G.outputIndex,0, "The Throughput in " +self.objName + " is:")
G.outputSheet.write(G.outputIndex,1,self.numOfExits)
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "The average lifespan of an entity is:")
G.outputSheet.write(G.outputIndex,0, "The average lifespan of an entity that exited from "+ self.objName +" is:")
G.outputSheet.write(G.outputIndex,1,((self.totalLifespan)/self.numOfExits)/G.Base)
G.outputIndex+=1
else: #if we had multiple replications we output confidence intervals to excel
......@@ -141,7 +140,7 @@ class Exit(Process):
#so failurePortion will be exactly the same in each run). That will give 0 variability and errors.
#so for each output value we check if there was difference in the runs' results
#if yes we output the Confidence Intervals. if not we output just the fix value
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean Throughput is:")
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean Throughput in " +self.objName + " is:")
if self.checkIfArrayHasDifValues(self.Exits):
G.outputSheet.write(G.outputIndex,1,stat.bayes_mvs(self.Exits, G.confidenceLevel)[0][1][0])
G.outputSheet.write(G.outputIndex,2,stat.bayes_mvs(self.Exits, G.confidenceLevel)[0][0])
......@@ -151,7 +150,7 @@ class Exit(Process):
G.outputSheet.write(G.outputIndex,2,self.Exits[0])
G.outputSheet.write(G.outputIndex,3,self.Exits[0])
G.outputIndex+=1
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean Lifespan of an entity is:")
G.outputSheet.write(G.outputIndex,0, "CI "+str(G.confidenceLevel*100)+"% for the mean Lifespan of an entity that exited from "+ self.objName + " is:")
if self.checkIfArrayHasDifValues(self.Lifespan):
G.outputSheet.write(G.outputIndex,1,stat.bayes_mvs(self.Lifespan, G.confidenceLevel)[0][1][0])
G.outputSheet.write(G.outputIndex,2,stat.bayes_mvs(self.Lifespan, G.confidenceLevel)[0][0])
......
......@@ -38,7 +38,6 @@
"distributionType": "Fixed",
"mean": "2"
},
"entity": "Frame",
"predecessorPartList": ["S1"],
"predecessorFrameList": ["S2"],
"successorList": ["M1"]
......
......@@ -38,7 +38,6 @@
"distributionType": "Fixed",
"mean": "2"
},
"entity": "Frame",
"predecessorPartList": ["S1"],
"predecessorFrameList": ["S2"],
"successorList": ["M1"]
......
{"_class": "Dream.Simulation",
"general": {
"_class": "Dream.Configuration",
"numberOfReplications": "1",
"maxSimTime": "1440",
"trace": "Yes",
"confidenceLevel": "0.95"
},
"modelResource": [
],
"coreObject": [
{"_class": "Dream.Source",
"id": "S1",
"name": "Parts",
"interarrivalTime":
{
"distributionType": "Fixed",
"mean": "0.5"
},
"entity": "Part",
"successorList": ["Α1"]
},
{"_class": "Dream.Source",
"id": "S2",
"name": "Frames",
"interarrivalTime":
{
"distributionType": "Fixed",
"mean": "2"
},
"entity": "Frame",
"successorList": ["Α1"]
},
{"_class": "Dream.Assembly",
"id": "A1",
"name": "Assembly",
"processingTime": {
"distributionType": "Fixed",
"mean": "2"
},
"predecessorPartList": ["S1"],
"predecessorFrameList": ["S2"],
"successorList": ["M1"]
},
{"_class": "Dream.Machine",
"id": "M1",
"name": "Moulding",
"processingTime": {
"distributionType": "Fixed",
"mean": "0.25"
},
"failures":{
"failureDistribution": "Fixed",
"MTTF": "60",
"MTTR": "5",
"repairman": "None"
},
"predecessorList": ["A1"],
"successorList": ["D1"]
},
{"_class": "Dream.Dismantle",
"id": "D1",
"name": "Dismantle",
"processingTime": {
"distributionType": "Fixed",
"mean": "1"
},
"successorPartList": ["E1"],
"successorFrameList": ["E2"],
"predecessorList": ["M1"]
},
{"_class": "Dream.Exit",
"id": "E1",
"name": "Parts Stock",
"predecessorList": ["D1"]
},
{"_class": "Dream.Exit",
"id": "E2",
"name": "Frames Stock",
"predecessorList": ["D1"]
}
]
}
......@@ -18,6 +18,7 @@ from Repairman import Repairman
from Part import Part
from Frame import Frame
from Assembly import Assembly
from Dismantle import Dismantle
import xlwt
import xlrd
import time
......@@ -47,6 +48,7 @@ def createObjects():
G.QueueList=[]
G.RepairmanList=[]
G.AssemblyList=[]
G.DismantleList=[]
#loop through all the model resources
#read the data and create them
......@@ -146,6 +148,25 @@ def createObjects():
A.nextIds=successorList
G.AssemblyList.append(A)
G.ObjList.append(A)
elif objClass=='Dream.Dismantle':
id=coreObject[i].get('id', 'not found')
name=coreObject[i].get('name', 'not found')
processingTime=coreObject[i].get('processingTime', 'not found')
distributionType=processingTime.get('distributionType', 'not found')
mean=float(processingTime.get('mean', '0'))
stdev=float(processingTime.get('stdev', '0'))
min=float(processingTime.get('min', '0'))
max=float(processingTime.get('stdev', '0'))
successorPartList=coreObject[i].get('successorPartList', 'not found')
successorFrameList=coreObject[i].get('successorFrameList', 'not found')
predecessorList=coreObject[i].get('predecessorList', 'not found')
D=Dismantle(id, name, distributionType, [mean,stdev,min,max])
D.nextPartIds=successorPartList
D.nextFrameIds=successorFrameList
D.previousIds=predecessorList
G.DismantleList.append(D)
G.ObjList.append(D)
#defines the topology (predecessors and successors for all the objects)
def setTopology():
......@@ -169,6 +190,7 @@ def setTopology():
G.ObjList[i].defineRouting(next)
elif G.ObjList[i].type=="Exit":
G.ObjList[i].defineRouting(previous)
#Assembly should be changed to identify what the entity that it receives is.
#previousPart and previousFrame will become problematic
elif G.ObjList[i].type=="Assembly":
......@@ -183,6 +205,20 @@ def setTopology():
if G.ObjList[q].id==G.ObjList[i].previousFrameIds[j]:
previousFrame.append(G.ObjList[q])
G.ObjList[i].defineRouting(previousPart, previousFrame, next)
#Assembly should be changed to identify what the entity that it receives is.
#previousPart and previousFrame will become problematic
elif G.ObjList[i].type=="Dismantle":
nextPart=[]
nextFrame=[]
for j in range(len(G.ObjList[i].nextPartIds)):
for q in range(len(G.ObjList)):
if G.ObjList[q].id==G.ObjList[i].nextPartIds[j]:
nextPart.append(G.ObjList[q])
for j in range(len(G.ObjList[i].nextFrameIds)):
for q in range(len(G.ObjList)):
if G.ObjList[q].id==G.ObjList[i].nextFrameIds[j]:
nextFrame.append(G.ObjList[q])
G.ObjList[i].defineRouting(previous, nextPart, nextFrame)
else:
G.ObjList[i].defineRouting(previous, next)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment