def act(self, time, round_no, step_no): work_capacity = self.model.dt * self.model.productivity while work_capacity > 0: if self.state == "available": self.task = self.model.next_agent("task", "open") if self.task is not None: self.state = "busy" self.task.receive_instantaneous_event( Event("task_started", self.id, self.task.id)) else: # no more open tasks work_capacity = 0 if self.state == "busy": # the actual progress we make on a task depends on the remaining effort work_done = min(work_capacity, self.task.remaining_effort) work_capacity -= work_done self.task.receive_instantaneous_event( Event("task_progress", self.id, self.task.id, {"progress": work_done})) if self.task.state == "closed": self.state = "available" self.task = None
def act(self, time, round_no, step_no): if self.state == "INFECTED_LIGHT": # or self.state == "INFECTED_HARD": infected_contacts = 0 for i in range(0,self.model.contact_rate): if np.random.choice(["HEALTHY", "INFECTED"], p=[1-self.model.infectivity, self.model.infectivity]) \ == "INFECTED": infected_contacts += 1 self.infected = infected_contacts infected_light = round(0.8*infected_contacts) infected_hard = round(0.2*infected_contacts) event_factory_hard = lambda agent_id: Event("infection_hard", self.id, agent_id, data=None) event_factory_light = lambda agent_id: Event("infection_light", self.id, agent_id, data=None) self.model.random_events("person", infected_hard, event_factory_hard) self.model.random_events("person", infected_light, event_factory_light)
def act(self, time, sim_round, step): # take care of deliveries and orders self.deliver(time, sim_round, step) self.order(time, sim_round, step) # update the stocks self.incoming_orders += self.incoming_order self.outgoing_deliveries += self.outgoing_delivery self.incoming_deliveries += self.incoming_delivery self.outgoing_orders += self.outgoing_order # update the KPIs self.outstanding_orders = self.outgoing_orders - self.incoming_deliveries self.backorder = self.incoming_orders - self.outgoing_deliveries self.inventory += self.incoming_delivery - self.outgoing_delivery self.surplus = self.inventory - self.backorder self.order_balance = self.outgoing_orders - self.incoming_orders # cost kpi self.cost = self.backorder * self.model.backorder_item_cost + max( self.inventory * self.model.inventory_item_cost, self.model.minimum_inventory_cost) self.total_cost += self.cost # send the cost to the controller (in this round) self.model.next_agent("controlling", "active").receive_instantaneous_event( Event("cost", self.id, 0, {"cost": self.cost}))
def order(self, time, sim_round, step): # this is the "typical" behaviour seen by users amount = self.calculate_order(time) self.model.broadcast_event( self.supplier, lambda agent_id: Event("order", self.id, agent_id, {"order": amount})) self.outgoing_order = amount
def deliver(self, time, sim_round, step): amount = min(self.inventory + self.incoming_delivery, self.backorder + self.incoming_order) self.model.broadcast_event( self.customer, lambda agent_id: Event( "delivery", self.id, agent_id, {"delivery": amount})) self.outgoing_delivery = amount
def order(self, time, sim_round, step): amount = self.weekly_order if time > 1 else 100 self.model.next_agent(self.supplier, "active").receive_instantaneous_event( Event("order", self.id, 0, {"order": amount})) # self.model.broadcast_event(self.supplier, lambda agent_id: Event("order", self.id, agent_id, {"order": amount})) self.outgoing_order = amount
def end_round(self, time, sim_round, step): supply_chain_agents = {"brewery", "distributor", "wholesaler", "retailer"} controlling_agent = None total_reward = 0 for agent in self.agents: if agent.agent_type == "controlling": controlling_agent = agent for agent in self.agents: reward = 0 if agent.agent_type in supply_chain_agents and not self.game_over: if (agent.order_balance < 0 or agent.order_balance > 1400): self.game_over = True self.game_over_round = time + 1 # run one more round to pickup the rewards, then stop reward = -10000 elif agent.outgoing_order < agent.incoming_order: reward = -10000 else: if time == 3: if 750 >= agent.order_balance >= 600: reward += 2000 if time == 5: if 900 >= agent.order_balance >= 700: reward += 2000 if time == 10: if 1150 >= agent.order_balance >= 1000: reward += 2000 if time == 15: if 1250 >= agent.order_balance >= 1100: reward += 2000 if time == 20: if 1250 >= agent.order_balance >= 1150: reward += 2000 if time == self.stoptime - 1: # penultimate round, to ensure rewards are handled in final round if agent.total_cost < 10000: reward += 10000 if controlling_agent.supply_chain_cost < 40000: reward += 20000 total_reward += reward agent.receive_instantaneous_event(Event("reward", None, agent.id, {"reward": reward})) controlling_agent.receive_instantaneous_event(Event("supply_chain_reward", None, None, {"supply_chain_reward": total_reward}))
def act(self, time, round_no, step_no): if self.state == "HEALTHY": self.move() elif self.state == "DEAD": pass elif self. if self.state == "INFECTED_LIGHT": # or self.state == "INFECTED_HARD": infected_contacts = 0 for i in range(0, self.model.contact_rate): if np.random.choice(["HEALTHY", "INFECTED"], p=[1 - self.model.infectivity, self.model.infectivity]) \ == "INFECTED": infected_contacts += 1 self.infected = infected_contacts infected_light = round(0.8 * infected_contacts) infected_hard = round(0.2 * infected_contacts) event_factory_hard = lambda agent_id: Event("infection_hard", self.id, agent_id, data=None) event_factory_light = lambda agent_id: Event("infection_light", self.id, agent_id, data=None) self.model.random_events("person", infected_hard, event_factory_hard) self.model.random_events("person", infected_light, event_factory_light) def move(self): position_found = 0 found = False while not found: indices = [i for i in range(0, len(self.MOVING_LIST))] moving = self.MOVING_LIST[np.random.choice(indices)] position_found = (self.position[0]+moving[0], self.position[1]+moving[1]) if position_found[0] >= 0 and position_found[0]<=20 and \ position_found[1] >= 0 and position_found[1] <=20: found = True break self.position = position_found def find_neighbors(self): position = 0 neighbors_list = [] for moving_element in self.MOVING_LIST: position = (self.position[0]+moving_element[0], self.position[1]+moving_element[1]) for agent in self.model.agents: if agent == self: continue if agent.position == position: neighbors_list.append(agent.position) return neighbors_list def check_infected(self, neighbors): for agent in self.model.agents: if agent == self: continue if agent.position in neighbors: if agent.state == "INFECTED": self.state = "INFECTED" self.model.infected += 1 print("Waaah I got infected") self.infected = 1 break def infect_neighbors(self,neighbors): for agent in self.model.agents: if agent == self: continue if agent.position in neighbors: agent.state = "INFECTED"