Skip to content

Introduction

To introduce a new station in the simulation environment, a new class should be created that extends the Station class. The new station must define its own behavior by providing implementations of the run() and init_state() method. For instance, suppose we want to implement a simple Inspection Station that evaluates carriers and flags defective ones. This can be achieved by defining a class that inherits from Station:

class Inspection(Station):
    def __init__(self, name, buffer_in=None, buffer_out=None, position=None, defect_probability=0.1):
        super().__init__(
            name=name,
            position=position,
        )
        self.defect_probability = defect_probability

        if buffer_in is not None:
            self._connect_to_input(buffer_in)
        if buffer_out is not None:
            self._connect_to_output(buffer_out)

    def init_state(self):
        self.state = ObjectStates(
            DiscreteState('on', categories=[True, False], is_actionable=False, is_observable=False),
            DiscreteState('mode', categories=['working', 'waiting', 'failing']),
            TokenState(name='carrier', is_observable=False),
            CountState('defective_parts', is_actionable=False, is_observable=True, vmin=0),
        )
        self.state['on'].update(True)
        self.state['mode'].update("waiting")
        self.state['carrier'].update(None)
        self.state['defective_parts'].update(0)

    def run(self):
        while True:
            if self.is_on():
                # wait for carrier
                yield self.env.process(self.set_to_waiting())
                carrier = yield self.env.process(self.buffer_in())
                self.state['carrier'].update(carrier.name)

                # process part
                yield self.env.process(self.set_to_work())
                self.state['mode'].update('working')
                yield self.env.timeout(self.processing_time)

                if self.random.uniform(0, 1) < self.defect_probability:
                    # handle defective part
                    self.state['defective_parts'].increment()
                    yield self.env.timeout(2)
                    self.state['mode'].update('waiting')

                # push carrier on buffer out
                yield self.env.process(self.buffer_out(carrier))
                self.state['carrier'].update(None)
            else:
                yield self.turn_off()