Exemplo n.º 1
0
    def _evaluate_cancellation_callback(self, event: Event):
        """Callback detailing how the dispatcher evaluates canceling an order"""

        self._evaluate_cancellation_event()

        event.succeed()
        event.callbacks = []
Exemplo n.º 2
0
    def _master_process(self, env):
        min_scheduling_interval = self.min_scheduling_interval
        scheduling_time = self.scheduling_time
        timeout = self.env.timeout

        # We are here intentionally separate registering workers
        # and task submit, as it is usually separated in real-word
        # reactors.

        self.new_workers += self.workers
        schedule = self.send_update()
        assert not schedule

        self.new_tasks += list(self.task_graph.tasks.values())
        self.new_objects += list(self.task_graph.objects.values())

        schedule = self.send_update()
        if scheduling_time:
            yield timeout(scheduling_time)
        if schedule:
            self.apply_schedule(schedule)

        while self.unprocessed_tasks > 0:
            self.wakeup_event = Event(env)
            if min_scheduling_interval:
                yield self.wakeup_event & timeout(min_scheduling_interval)
            else:
                yield self.wakeup_event

            schedule = self.send_update()
            if scheduling_time:
                yield timeout(scheduling_time)
            if schedule:
                self.apply_schedule(schedule)
Exemplo n.º 3
0
    def handle(self, from_agent: AgentId, event: WorldEvent) -> Event:
        """
        Main method which governs how events cause each other in the
        environment. Not to be overridden in children: `handleAction` and
        `handleWorldEvent` should be overridden instead.
        """
        if isinstance(event, MasterEvent):
            from_agent = event.agent
            event = event.inner

        if isinstance(event, Message):
            return self.handleMessage(from_agent, event)

        elif isinstance(event, Action):
            return self.handleAction(from_agent, event)

        elif isinstance(event, DelayedEvent):
            proc = self.env.process(self._delayedHandleGen(from_agent, event))
            self.delayed_evs[from_agent][event.id] = proc
            return Event(self.env).succeed()

        elif isinstance(event, DelayInterrupt):
            try:
                self.delayed_evs[from_agent][event.delay_id].interrupt()
            except (KeyError, RuntimeError):
                pass
            return Event(self.env).succeed()

        elif from_agent[0] == 'world':
            return handleWorldEvent(event)

        else:
            raise Exception('Non-world event: ' + str(event))
Exemplo n.º 4
0
    def init(self, env, workers):
        super().init(env, workers)
        self.downloads = {}
        self.recompute_event = Event(env)
        self.flows = np.zeros((len(workers), len(workers)))

        self.recompute_flows = False
        self.flow_cache = LruCache(self.CACHE_SIZE)

        def network_process():
            while True:
                if self.recompute_flows:
                    self.recompute_flows = False
                    self._recompute_flows()
                    logger.info("Flows reconfigured:\n%s", self.flows)

                timeout = self._update_speeds()
                logger.info("Earliest download finished in: %s", timeout)
                if timeout is not None:
                    start_time = self.env.now
                    r = yield self.recompute_event | self.env.timeout(timeout)
                    self._update_sizes(self.env.now - start_time)
                    if self.recompute_event in r:
                        self.recompute_event = Event(env)
                else:
                    logger.info("No active downloads")
                    yield self.recompute_event
                    self.recompute_event = Event(env)

        env.process(network_process())
Exemplo n.º 5
0
    def shift_controller(self):
        # Reference to SimPy environment
        env = self.procflow_sim.simpy_env
        while True:
            # Wait for shift on time
            yield env.timeout(self.shift_on_time)

            # End the shift (interrupt the process)
            self.logger.info(
                "{}\t\t\t{}\t\t(ShiftController)\t\t\t{}\t\t(Process):\t\t\t"
                "Shift end triggered".format(self.env.now, '<no name>',
                                             self.name))
            self.shift_end_event.succeed(value={'event': "Shift end"})
            self.shift_end_event = Event(env)

            # Wait for shift off time
            yield env.timeout(self.shift_off_time)

            # Start the shift (interrupt the process)
            self.logger.info(
                "{}\t\t\t{}\t\t(ShiftController)\t\t\t{}\t\t(Process):\t\t\t"
                "Shift start triggered".format(self.env.now, '<no name>',
                                               self.name))
            self.shift_start_event.succeed(value={'event': "Shift start"})
            self.shift_start_event = Event(env)
Exemplo n.º 6
0
    def on_activate(self):
        # otp_attributes = {'maxWalkDistance': self.env.config.get('drt.default_max_walk'),
        #                   'numItineraries': 1}
        if self._activity_time_screwed():
            yield Event(self.env).succeed()
            self.env.process(self.unactivatable())
            return

        self.person.update_otp_params()
        try:
            direct_trip = self.person.serviceProvider.standalone_osrm_request(
                self.person)
            timeout = self.person.get_planning_time(direct_trip)
            self.person.set_direct_trip(direct_trip)
            # transit_trip = self.person.serviceProvider.standalone_otp_request(self.person, OtpMode.TRANSIT,
            #                                                                   otp_attributes)
            # timeout = self.person.get_planning_time(transit_trip[0])

            if timeout > 0:
                self.person.update_travel_log(TravellerEventType.ACT_STARTED,
                                              self.person.curr_activity)
            yield self.person.env.timeout(timeout)
            self.env.process(self.plan())
        except (OTPNoPath, OTPTrivialPath) as e:
            log.warning('{}: {}\n{}'.format(self.env.now, e.msg, e.context))
            log.warning(
                '{}: Person {} will be excluded from the simulation'.format(
                    self.env.now, self.person))
            yield Event(self.env).succeed()
            self.env.process(self.unactivatable())
Exemplo n.º 7
0
    def _buffer_order_callback(self, event: Event):
        """Callback detailing how the dispatcher buffers an order once it's placed"""

        self._buffer_order_event()
        self._schedule_evaluate_cancellation_event()

        event.succeed()
        event.callbacks = []
Exemplo n.º 8
0
    def _master_process(self, env):
        self.schedule(self.task_graph.source_nodes(), [])

        while self.unprocessed_tasks > 0:
            self.wakeup_event = Event(env)
            yield self.wakeup_event
            self.schedule(self.new_ready, self.new_finished)
            self.new_finished = []
            self.new_ready = []
Exemplo n.º 9
0
def process(kwargs: SystemArgs):
    world = kwargs['WORLD']
    env = kwargs['ENV']
    kitchen_layout = world.component_for_entity(1, KitchenLayout)
    for _ in range(kitchen_layout.personnel):
        env.process(cook(kwargs))
    yield Event(env)
Exemplo n.º 10
0
 def _download(self, output, priority):
     logger.info("Worker %s: scheduled downloading %s, priority=%s", self,
                 output, priority)
     assert output not in self.data
     download = Download(Event(self.env), output, priority)
     self.scheduled_downloads[output] = download
     return download
Exemplo n.º 11
0
    def on_plan(self):
        yield Event(self.env).succeed()
        while self.env.peek() == self.env.now:
            # TODO: this makes sure that a request-replan sequence for a person is not broken
            # if it is, we must save multiple requests and have some policy to merge them
            yield self.person.env.timeout(0.000001)
        self.person.update_travel_log(TravellerEventType.ACT_FINISHED,
                                      self.person.curr_activity)

        if self.person.planned_trip is None:
            try:
                self.person.update_travel_log(
                    TravellerEventType.TRIP_REQUEST_SUBMITTED,
                    self.person.curr_activity)

                alternatives = self.person.serviceProvider.request(self.person)

                self.person.alternatives = alternatives
                self.person.update_travel_log(
                    TravellerEventType.TRIP_ALTERNATIVES_RECEIVED,
                    self.person.curr_activity)
                self.env.process(self.choose())
            except (OTPTrivialPath, OTPUnreachable) as e:
                log.warning('{}'.format(e.msg))
                log.warning('{}: Excluding person from simulation. {}'.format(
                    self.env.now, self.person))
                self.env.process(self.unplannable())
Exemplo n.º 12
0
    def step(self, action: object) -> Tuple[object, float, bool, dict]:
        """ takes action and executes simulation until next action is needed """

        # 1. preparation
        self.reward_holder.reset_step_reward()

        # provide action via event
        self.action_holder.provided_action.succeed(action)
        self.action_holder.action_needed = Event(self.model.env)

        # 2. run model
        self.model.env.run(until=self.action_holder.action_needed)
        self.finished_gym_steps_in_current_episode += 1

        # 3. collect information to return to agent
        done = self.check_if_model_is_done()

        # enable time-dependent rewards
        time_needed_for_step = self.model.env.now - self.time_of_last_step
        reward = self.get_reward(time_needed_for_step, done)
        self.time_of_last_step = self.model.env.now

        observation = self._get_observation()
        info = self.get_info()

        if done:
            self.finished_episodes += 1
        self.finished_gym_steps_overall += 1

        return (observation, reward, done, info)
Exemplo n.º 13
0
    def on_choose(self):
        """Chooses one of the alternatives according to config.person.mode_choice
        """
        yield Event(self.env).succeed()
        chosen_trip = self.person.mode_choice.choose(self.person.alternatives)
        if chosen_trip is None:
            log.warning(
                '{}: Trip could not be selected for Person {}.'
                'It is possibly because there is no PT and person has no driving license.\n'
                'Person will be excluded from simulation.'.format(
                    self.env.now, self.person.id))
            log.debug('{}\n{}'.format(self.person, self.person.alternatives))
            self.env.process(self.unchoosable())
        else:
            log.info('{}: Person {} have chosen trip {}'.format(
                self.env.now, self.person.id, chosen_trip))
            self.person.planned_trip = chosen_trip.deepcopy()
            self.person.init_actual_trip()
            self.person.serviceProvider.start_trip(self.person)
            self.person.update_travel_log(TravellerEventType.TRIP_CHOSEN,
                                          chosen_trip.deepcopy())

            # TODO: after choosing, a traveler should wait for beginning of a trip
            # But that would break the current routing as start tim may be updated by other requests
            self.env.process(self.execute_trip())
Exemplo n.º 14
0
 def on_unreactivatable(self):
     yield Event(self.env).succeed()
     log.warning(
         '{}: {} going from {} to {} cannot reach the destination. Ignoring the person.'
         .format(self.env.now, self.person, self.person.curr_activity.coord,
                 self.person.next_activity.coord))
     self.person.serviceProvider.log_unactivatable(self.person)
     self.person.update_travel_log(TravellerEventType.NO_RUTE)
Exemplo n.º 15
0
 def on_unchoosable(self):
     yield Event(self.env).succeed()
     log.warning(
         '{}: {} going from {} to {} received none alternatives. Ignoring the person.'
         .format(self.env.now, self.person, self.person.curr_activity.coord,
                 self.person.next_activity.coord))
     self.person.serviceProvider.log_unchoosable(self.person)
     self.person.update_travel_log(TravellerEventType.NO_RUTE)
Exemplo n.º 16
0
    def handleAction(self, from_agent: AgentId, action: Action) -> Event:
        if isinstance(action, PkgRouteAction):
            to_agent = action.to
            if not self.conn_graph.has_edge(from_agent, to_agent):
                raise Exception("Trying to route to a non-neighbor")

            self.env.process(self._edgeTransfer(from_agent, to_agent, action.pkg))
            return Event(self.env).succeed()

        elif isinstance(action, PkgReceiveAction):
            logger.debug(f"Package #{action.pkg.id} received at node {from_agent[1]} at time {self.env.now}")

            self.data_series.logEvent(self.env.now, self.env.now - action.pkg.start_time)
            return Event(self.env).succeed()

        else:
            return super().handleAction(from_agent, action)
Exemplo n.º 17
0
    def _schedule_log_off_event(self):
        """Method that allows the courier to schedule the log off time"""

        log_off_event = Event(env=self.env)
        log_off_event.callbacks.append(self._log_off_callback)
        log_off_delay = time_diff(self.off_time, self.on_time)
        self.env.schedule(event=log_off_event,
                          priority=NORMAL,
                          delay=log_off_delay)
Exemplo n.º 18
0
    def _schedule_buffer_order_event(self, order: Order):
        """Method that allows the dispatcher to schedule the order buffering event"""

        buffering_event = Event(env=self.env)
        buffering_event.callbacks.append(self._buffer_order_callback)
        self.env.schedule(event=buffering_event,
                          priority=NORMAL,
                          delay=time_diff(order.preparation_time,
                                          order.placement_time))
Exemplo n.º 19
0
    def _schedule_evaluate_cancellation_event(self):
        """Method that allows the dispatcher to schedule the cancellation evaluation event"""

        evaluate_cancellation_event = Event(env=self.env)
        evaluate_cancellation_event.callbacks.append(
            self._evaluate_cancellation_callback)
        self.env.schedule(event=evaluate_cancellation_event,
                          priority=NORMAL,
                          delay=settings.DISPATCHER_WAIT_TO_CANCEL)
Exemplo n.º 20
0
    def run(self, env, simulator, netmodel):
        self.env = env
        self.simulator = simulator
        self.netmodel = netmodel
        self.ready_store = Store(env)
        self.download_wakeup = Event(self.simulator.env)

        self.free_cpus = self.cpus
        env.process(self._download_process())

        prepared_assignments = []
        events = [self.ready_store.get()]

        while True:
            finished = yield env.any_of(events)
            for event in finished.keys():
                if event == events[0]:
                    events[0] = self.ready_store.get()
                    assignment = event.value
                    if assignment.cancelled:
                        continue
                    prepared_assignments.append(assignment)
                    prepared_assignments.sort(key=lambda a: a.priority,
                                              reverse=True)
                    continue

                assignment = event.value
                task = assignment.task
                self.free_cpus += task.cpus
                assert not assignment.cancelled
                del self.assignments[assignment.task]
                events.remove(event)
                del self.running_tasks[task]
                simulator.add_trace_event(
                    TaskEndTraceEvent(self.env.now, self, task))
                for output in task.outputs:
                    self._add_data(output)
                simulator.on_task_finished(self, task)

            block = float("-inf")
            for assignment in prepared_assignments[:]:
                if assignment.priority < block:
                    continue
                task = assignment.task
                if task.cpus <= self.free_cpus:
                    prepared_assignments.remove(assignment)
                    if assignment.cancelled:
                        continue
                    self.free_cpus -= task.cpus
                    self.running_tasks[task] = RunningTask(task, self.env.now)
                    simulator.add_trace_event(
                        TaskStartTraceEvent(self.env.now, self, task))
                    events.append(env.timeout(task.duration, assignment))
                    self.simulator.on_task_start(self, assignment.task)
                else:
                    block = max(block, assignment.block)
Exemplo n.º 21
0
        def network_process():
            while True:
                if self.recompute_flows:
                    self.recompute_flows = False
                    self._recompute_flows()
                    logger.info("Flows reconfigured:\n%s", self.flows)

                timeout = self._update_speeds()
                logger.info("Earliest download finished in: %s", timeout)
                if timeout is not None:
                    start_time = self.env.now
                    r = yield self.recompute_event | self.env.timeout(timeout)
                    self._update_sizes(self.env.now - start_time)
                    if self.recompute_event in r:
                        self.recompute_event = Event(env)
                else:
                    logger.info("No active downloads")
                    yield self.recompute_event
                    self.recompute_event = Event(env)
Exemplo n.º 22
0
    def _download_process(self):
        events = [self.download_wakeup]
        env = self.env
        runtime_state = self.simulator.runtime_state

        while True:
            finished = yield env.any_of(events)
            for event in finished.keys():
                if event == events[0]:
                    self.download_wakeup = Event(self.simulator.env)
                    events[0] = self.download_wakeup
                    downloads = None
                    continue
                events.remove(event)
                download = event.value
                assert download.output not in self.data
                self.data.add(download.output)
                self.running_downloads.remove(download)
                del self.scheduled_downloads[download.output]
                download.event.succeed(download)
                self.simulator.add_trace_event(
                    FetchEndTraceEvent(self.env.now, self, download.source,
                                       download.output))

            if len(self.running_downloads) < self.max_downloads:
                # We need to sort any time, as it priority may changed in background

                if downloads is None:
                    downloads = list(
                        o for o in self.scheduled_downloads.values()
                        if o not in self.running_downloads)
                    downloads.sort(key=lambda d: d.priority, reverse=True)

                for d in downloads[:]:
                    count = 0
                    worker = runtime_state.output_info(d.output).placing[0]
                    for rd in self.running_downloads:
                        if worker == rd.source:
                            count += 1
                    if count >= self.max_downloads_per_worker:
                        continue
                    downloads.remove(d)
                    d.start_time = self.env.now
                    d.source = worker
                    self.running_downloads.append(d)
                    event = self.netmodel.download(worker, self, d.output.size,
                                                   d)
                    events.append(event)
                    self.simulator.add_trace_event(
                        FetchStartTraceEvent(self.env.now, self, worker,
                                             d.output))
                    if len(self.running_downloads) >= self.max_downloads:
                        break
Exemplo n.º 23
0
    def reset(self) -> object:
        """ resets env and simulation model and return initial observation """
        self.before_reset()

        self._initialize_model()

        # run until the first action is needed
        self.action_holder.action_needed = Event(self.model.env)
        self.model.env.run(until=self.action_holder.action_needed)

        initial_observation = self._get_observation()
        return initial_observation
Exemplo n.º 24
0
 def handleMessage(self, from_agent: AgentId, msg: Message) -> Event:
     """
     Method which handles how messages should be dealt with. Is not meant to be
     overridden.
     """
     if isinstance(msg, WireOutMsg):
         # Out message is considered to be handled as soon as its
         # handling by the recipient is scheduled. We do not
         # wait for other agent to handle them.
         self.env.process(self._handleOutMsgGen(from_agent, msg))
         return Event(self.env).succeed()
     else:
         raise UnsupportedMessageType(msg)
Exemplo n.º 25
0
    def __init__(self, unsched_id, proc, params):
        self.name = params['name']
        self.id = unsched_id
        self.duration_mean = params['duration_mean']
        self.duration_stddev = params['duration_stddev']
        self.mtbf = params['mtbf']

        # References to simulation and events
        self.process = proc
        self.logger = proc.procflow_sim.logger
        self.procflow_sim = proc.procflow_sim

        self.shift_start_event = proc.shift_start_event
        self.env = proc.procflow_sim.simpy_env

        # Remaining scheduled maintenance duration
        # (in case the scheduled maintenance activity gets preempted by end of the shift)
        self.remaining_duration = self.sample_duration()
        self.remaining_interarrival_time = self.sample_frequency()

        # The maintenance event to yield on
        self.maintenance_event = Event(self.env)
        self.maintenance_complete_event = Event(self.env)
Exemplo n.º 26
0
    def _master_process(self, env):
        timeout = self.env.timeout
        min_scheduling_interval = self.min_scheduling_interval
        scheduling_time = self.scheduling_time

        schedule = self.schedule(self.task_graph.source_tasks(), [])
        if scheduling_time:
            yield timeout(scheduling_time)
        if schedule:
            self.apply_schedule(schedule)

        while self.unprocessed_tasks > 0:
            self.wakeup_event = Event(env)
            if min_scheduling_interval:
                yield self.wakeup_event & timeout(min_scheduling_interval)
            else:
                yield self.wakeup_event
            schedule = self.schedule(self.new_ready, self.new_finished)
            self.new_finished = []
            self.new_ready = []
            if scheduling_time:
                yield timeout(scheduling_time)
            if schedule:
                self.apply_schedule(schedule)
Exemplo n.º 27
0
    def _checkInterrupt(self, callback):
        if self.conveyors_move_proc is None:
            callback()
        else:
            try:
                self.conveyors_move_proc.interrupt()
                self.conveyors_move_proc = None
            except RuntimeError as err:
                self.log('UNEXPECTED INTERRUPT FAIL {}'.format(err), True)

            for model in self.conveyor_models.values():
                model.pause()

            callback()
            self._updateAll()

        return Event(self.env).succeed()
Exemplo n.º 28
0
 def download(self, source, target, size, value=None):
     assert source != target
     event = Event(self.env)
     rd = RunningDownload(size, event, value)
     logger.info("New download %s; %s-%s size=%s", rd, source, target, size)
     key = (source, target)
     lst = self.downloads.get(key)
     if lst is None:
         lst = []
         self.downloads[key] = lst
     if not lst:
         logger.info("Link %s-%s opened, need recompute flows", source,
                     target)
         self.recompute_flows = True
     lst.append(rd)
     if not self.recompute_event.triggered:
         self.recompute_event.succeed()
     return event
Exemplo n.º 29
0
    def handleAction(self, from_agent: AgentId, action: Action) -> Event:
        if isinstance(action, BagReceiveAction):
            assert agent_type(
                from_agent) == 'sink', "Only sink can receive bags!"
            bag = action.bag

            self.log(f"bag #{bag.id} received at sink {from_agent[1]}")

            if from_agent != bag.dst:
                raise Exception(
                    f'Bag #{action.bag.id} came to {from_agent}, but its destination was {bag.dst}'
                )

            assert bag.id in self.current_bags, "why leave twice??"
            self.current_bags.pop(action.bag.id)

            # fix to make reinforce work
            from ..agents.routers.reinforce import PackageHistory
            PackageHistory.finishHistory(bag)

            self.data_series.logEvent('time', self.env.now,
                                      self.env.now - action.bag.start_time)
            return Event(self.env).succeed()

        elif isinstance(action, DiverterKickAction):
            assert agent_type(
                from_agent) == 'diverter', "Only diverter can do kick actions!"
            self.log(f'diverter {agent_idx(from_agent)} kicks')

            return self._checkInterrupt(lambda: self._diverterKick(from_agent))

        elif isinstance(action, ConveyorSpeedChangeAction):
            assert agent_type(
                from_agent) == 'conveyor', "Only conveyor can change speed!"
            self.log(
                f'change conv {agent_idx(from_agent)} speed to {action.new_speed}'
            )

            return self._checkInterrupt(lambda: self._changeConvSpeed(
                agent_idx(from_agent), action.new_speed))

        else:
            return super().handleAction(from_agent, action)
Exemplo n.º 30
0
    def _move(self):
        try:
            events = all_next_events(self.conveyor_models)
            self.log('MOVING: {}'.format(events))

            if len(events) > 0:
                conv_idx, (bag, node, delay) = events[0]
                assert delay > 0, "next event delay is 0!"
                self.log('NEXT EVENT: conv {} - ({}, {}, {})'.format(
                    conv_idx, bag, node, delay))
                yield self.env.timeout(delay)
            else:
                # hang forever (until interrupt)
                yield Event(self.env)

            for model in self.conveyor_models.values():
                model.pause()

            self._updateAll()
        except Interrupt:
            pass