예제 #1
0
class TestParameters(TestCase):
    def setUp(self):
        self.parametersObj = Parameters()
        self.parametersObj.WITH_SHIFTS = True
        rand = Random()
        rand.initialization()

    def tearDown(self):
        self.parametersObj = None

    def test_getTotalTime(self):
        shift_duration = [5, 9, 2, 1]
        shift_type = [
            Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA,
            Constants.DUAL
        ]
        shift_factor = 3600  # hours
        self.parametersObj.setParameters(shift_duration, shift_type,
                                         shift_factor)

        self.assertEqual(self.parametersObj.getTotalTime(Constants.ENTREGA),
                         14, "The delivery time should be 5 + 9")
        self.assertEqual(self.parametersObj.getTotalTime(Constants.RECOGIDA),
                         2, "The collection time should be 2")
        self.assertEqual(self.parametersObj.getTotalTime(Constants.DUAL), 1,
                         "The dual time should be 1")

    def test_getCurrentShift_Not_Edges(self):
        shift_duration = [5, 9, 2, 1]
        # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
        # E E E E E E E E E E E  E  E  E  R  R  D
        shift_type = [
            Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA,
            Constants.DUAL
        ]
        shift_factor = 3600  # hours
        self.parametersObj.setParameters(shift_duration, shift_type,
                                         shift_factor)

        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 2 * 3600),
            Constants.ENTREGA, "The shift should be ENTREGA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 7 * 3600),
            Constants.ENTREGA, "The shift should be ENTREGA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 15 * 3600),
            Constants.RECOGIDA, "The shift should be RECOGIDA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 17 * 3600), Constants.DUAL,
            "The shift should be DUAL")

    def test_getCurrentShift_Edges(self):
        shift_duration = [5, 9, 2, 1]
        # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
        # E E E E E E E E E E E  E  E  E  R  R  D
        shift_type = [
            Constants.ENTREGA, Constants.ENTREGA, Constants.RECOGIDA,
            Constants.DUAL
        ]
        shift_factor = 3600  # hours
        self.parametersObj.setParameters(shift_duration, shift_type,
                                         shift_factor)

        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 0 * 3600),
            Constants.ENTREGA, "The shift should be ENTREGA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 13 * 3600),
            Constants.ENTREGA, "The shift should be ENTREGA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 14 * 3600),
            Constants.RECOGIDA, "The shift should be RECOGIDA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 15 * 3600),
            Constants.RECOGIDA, "The shift should be RECOGIDA")
        self.assertEqual(
            self.parametersObj.getCurrentShift(
                Constants.SIMULATION_INITIAL_TIME + 16 * 3600), Constants.DUAL,
            "The shift should be DUAL")
예제 #2
0
class Core:
    # CLASS FUNCTIONS

    def __init__(self, parameters=None):
        if parameters is None:
            self.parameters = Parameters()
        else:
            self.parameters = parameters
        num_sources = Constants.DEFAULT_SOURCES
        num_processors = self.parameters.num_processors
        # Attributes initialization
        self.processors = []
        self.sources = []
        self.eventsList = PriorityQueue(0)  # maxsize = 0 (infinite)
        self.previousTime = Constants.SIMULATION_INITIAL_TIME
        self.currentTime = Constants.SIMULATION_INITIAL_TIME
        self.idleProcessors = 0
        self.serviceProcessors = 0
        self.entitiesSystem = 0
        self.service_per_shift = []
        self.service_per_total = []
        self.shift_durations = self.parameters.getParameters()[1]
        self.shift_next_time = self.shift_durations[0]
        self.shift_next_index = 1

        # Instance creation
        self.queue = Queue(Constants.SLOTS_BUFFER)
        self.parking = Queue(Constants.SLOTS_QUEUE)
        self.random = Random()
        for _ in range(0, num_processors):
            self.processors.append(Processor(self))
        for _ in range(0, num_sources):
            self.sources.append(Source(self))
        # Dependency injection
        for source in self.sources:
            source.addOutput(self.queue)  # source -> queue
        self.queue.addOutput(self.parking)  # queue -> parking
        self.parking.addInput(self.queue)  # parking <- queue
        for processor in self.processors:
            self.parking.addOutput(processor)  # parking -> processor
            processor.addInput(self.parking)  # processor <- parking
        self.output_file = None
        self.numberOfIdleProcessors = num_processors

    def increaseEntitiesSystem(self):
        self.entitiesSystem += 1

    def decreaseEntitiesSystem(self):
        self.entitiesSystem -= 1

    def startSimulation(self):
        """Implemented by all modules"""
        startEvent = Event(self, Constants.START_SIMULATION, self.currentTime,
                           self.currentTime)
        self.logEvent(startEvent)
        for source in self.sources:
            source.startSimulation()

    def endSimulation(self):
        """Implemented by all modules"""
        endEvent = Event(
            self,  # eventCreator
            Constants.END_SIMULATION,  # eventName
            self.currentTime,  # eventScheduled
            self.currentTime  # eventTime
        )
        self.logEvent(endEvent)
        self.updateState(endEvent)

    def executeEvent(self, currentEvent):
        """Implemented by all event creator modules"""
        if currentEvent.eventName == Constants.START_SIMULATION:
            self.startSimulation()

    def run(self):
        self.logHeaders()  # creates output file with flag w+
        with open(self.parameters.output_file + '.csv',
                  "a+") as self.output_file:
            self.startSimulation()
            while not self.eventsList.empty():
                currentEvent = self.eventsList.get()
                self.updateState(currentEvent)
                self.logEvent(currentEvent)
                currentEvent.executeEvent()
            self.endSimulation()
            self.stats()

    def addEvent(self, addedEvent):
        self.eventsList.put(addedEvent, addedEvent.eventTime)

    def getCurrentTime(self):
        return self.currentTime

    def updateState(self, event):
        self.previousTime = self.currentTime
        self.currentTime = event.eventTime
        timeStep = self.currentTime - self.previousTime
        self.numberOfIdleProcessors = 0
        for processor in self.processors:
            if processor.isIdle():
                self.idleProcessors += timeStep
                self.numberOfIdleProcessors += 1
            else:
                self.serviceProcessors += timeStep

        if self.currentTime > self.shift_next_time * 3600:
            if self.shift_next_index < len(self.shift_durations):
                self.shift_next_time += self.shift_durations[
                    self.shift_next_index]
                self.shift_next_index += 1
                if not self.service_per_shift:  # first shift - empty list; if == 0
                    self.service_per_shift.append(self.serviceProcessors)
                else:
                    self.service_per_shift.append(self.serviceProcessors -
                                                  self.service_per_total[-1])
                self.service_per_total.append(self.serviceProcessors)
        if event.eventName == Constants.END_SIMULATION and len(
                self.service_per_shift) < len(self.shift_durations):
            # print('END_SIMULATION')
            self.service_per_shift.append(self.serviceProcessors -
                                          self.service_per_total[-1])

    def getCurrentShift(self):
        return self.parameters.getCurrentShift(self.currentTime)

    def logHeaders(self):
        s = 'Current_Time,'
        s += 'Event_Name,'
        s += 'Event_Scheduled,'
        s += 'Event-Time,'
        s += 'Idle_Processors,'
        s += 'Service_Processors,'
        s += 'Number_Idle_Processors,'
        s += 'Buffer_Length,'
        s += 'Queue_Length,'
        s += 'Entities_System,'
        s += 'Shift'
        with open(self.parameters.output_file + '.csv', "w+") as output_file:
            output_file.write(s + '\n')

    def logEvent(self, currentEvent):
        s = str(self.currentTime) + ','
        s += currentEvent.eventName + ','
        s += str(currentEvent.eventScheduled) + ','
        s += str(currentEvent.eventTime) + ','
        s += str(self.idleProcessors) + ','
        s += str(self.serviceProcessors) + ','
        s += str(self.numberOfIdleProcessors) + ','
        s += str(self.queue.getQueueLength()) + ','
        s += str(self.parking.getQueueLength()) + ','
        s += str(self.entitiesSystem) + ','
        s += str(self.parameters.getCurrentShift(currentEvent.eventScheduled))
        self.output_file.write(s + '\n')

    def stats(self):
        s = 'Max_Queue_Length'
        r = str(self.parking.getMaxQueueLength())
        s += ',Processors_Capacity_Used'
        r += ',' + str(
            round(
                100 * self.serviceProcessors /
                (self.parameters.num_processors *
                 Constants.SIMULATION_DURATION), 2))  # in %
        shift_type, shift_duration = self.parameters.getParameters()
        for idx in range(len(shift_type)):
            s += ',Shift_Type'
            r += ',' + shift_type[idx]
            s += ',Shift_Duration'
            r += ',' + str(shift_duration[idx])
            s += ',Shift_Capacity_Usage'
            r += ',' + str(
                round(
                    100 * self.service_per_shift[idx] /
                    (self.parameters.num_processors *
                     self.shift_durations[idx] * 3600), 2))
        with open(self.parameters.output_file + '.stats.csv',
                  "w+") as output_file:
            output_file.write(s + '\n')
            output_file.write(r + '\n')