class WalkerWorld(Model): ''' Random walker world. ''' height = 10 width = 10 def __init__(self, height, width, agent_count): ''' Create a new WalkerWorld. Args: height, width: World size. agent_count: How many agents to create. ''' self.height = height self.width = width self.grid = MultiGrid(self.height, self.width, torus=True) self.agent_count = agent_count self.schedule = RandomActivation(self) # Create agents for i in range(self.agent_count): x = random.randrange(self.width) y = random.randrange(self.height) a = WalkerAgent((x, y), self, True) self.schedule.add(a) self.grid.place_agent(a, (x, y)) def step(self): self.schedule.step()
class MoneyModel(Model): """A model with some number of agents.""" def __init__(self, N, width, height): self.num_agents = N self.running = True self.grid = MultiGrid(height, width, True) self.schedule = RandomActivation(self) self.datacollector = DataCollector(model_reporters={"Gini": compute_gini}, agent_reporters={"Wealth": lambda a: a.wealth}) # Create agents for i in range(self.num_agents): a = MoneyAgent(i) self.schedule.add(a) # Add the agent to a random grid cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def step(self): self.datacollector.collect(self) self.schedule.step() def run_model(self, n): for i in range(n): self.step()
class Money_Model(Model): def __init__(self, N, width=50, height=50, torus=True): self.num_agents = N self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus) self.create_agents() self.dc = DataCollector({"Gini": lambda m: m.compute_gini()}, {"Wealth": lambda a: a.wealth}) self.running = True def create_agents(self): for i in range(self.num_agents): a = Money_Agent(i) self.schedule.add(a) x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def step(self): self.dc.collect(self) self.schedule.step() def run_model(self, steps): for i in range(steps): self.step() def compute_gini(self): agent_wealths = [agent.wealth for agent in self.schedule.agents] x = sorted(agent_wealths) N = self.num_agents B = sum( xi * (N-i) for i,xi in enumerate(x) ) / (N*sum(x)) return (1 + (1/N) - 2*B)
class MoneyModel(Model): """A simple model of an economy where agents exchange currency at random. All the agents begin with one unit of currency, and each time step can give a unit of currency to another agent. Note how, over time, this produces a highly skewed distribution of wealth. """ def __init__(self, N, width, height): self.num_agents = N self.running = True self.grid = MultiGrid(height, width, True) self.schedule = RandomActivation(self) self.datacollector = DataCollector( model_reporters={"Gini": compute_gini}, agent_reporters={"Wealth": lambda a: a.wealth} ) # Create agents for i in range(self.num_agents): a = MoneyAgent(i, self) self.schedule.add(a) # Add the agent to a random grid cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y)) def step(self): self.datacollector.collect(self) self.schedule.step() def run_model(self, n): for i in range(n): self.step()
class Charts(Model): # grid height grid_h = 20 # grid width grid_w = 20 """init parameters "init_people", "rich_threshold", and "reserve_percent" are all UserSettableParameters""" def __init__(self, height=grid_h, width=grid_w, init_people=2, rich_threshold=10, reserve_percent=50,): self.height = height self.width = width self.init_people = init_people self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus=True) # rich_threshold is the amount of savings a person needs to be considered "rich" self.rich_threshold = rich_threshold self.reserve_percent = reserve_percent # see datacollector functions above self.datacollector = DataCollector(model_reporters={ "Rich": get_num_rich_agents, "Poor": get_num_poor_agents, "Middle Class": get_num_mid_agents, "Savings": get_total_savings, "Wallets": get_total_wallets, "Money": get_total_money, "Loans": get_total_loans}, agent_reporters={ "Wealth": lambda x: x.wealth}) # create a single bank for the model self.bank = Bank(1, self, self.reserve_percent) # create people for the model according to number of people set by user for i in range(self.init_people): # set x, y coords randomly within the grid x = self.random.randrange(self.width) y = self.random.randrange(self.height) p = Person(i, (x, y), self, True, self.bank, self.rich_threshold) # place the Person object on the grid at coordinates (x, y) self.grid.place_agent(p, (x, y)) # add the Person object to the model schedule self.schedule.add(p) self.running = True self.datacollector.collect(self) def step(self): # tell all the agents in the model to run their step function self.schedule.step() # collect data self.datacollector.collect(self) def run_model(self): for i in range(self.run_time): self.step()
class TestMultiGrid(unittest.TestCase): ''' Testing a toroidal MultiGrid ''' torus = True def setUp(self): ''' Create a test non-toroidal grid and populate it with Mock Agents ''' width = 3 height = 5 self.grid = MultiGrid(width, height, self.torus) self.agents = [] counter = 0 for x in range(width): for y in range(height): for i in range(TEST_MULTIGRID[x][y]): counter += 1 # Create and place the mock agent a = MockAgent(counter, None) self.agents.append(a) self.grid.place_agent(a, (x, y)) def test_agent_positions(self): ''' Ensure that the agents are all placed properly on the MultiGrid. ''' for agent in self.agents: x, y = agent.pos assert agent in self.grid[x][y] def test_neighbors(self): ''' Test the toroidal MultiGrid neighborhood methods. ''' neighborhood = self.grid.get_neighborhood((1, 1), moore=True) assert len(neighborhood) == 8 neighborhood = self.grid.get_neighborhood((1, 4), moore=True) assert len(neighborhood) == 8 neighborhood = self.grid.get_neighborhood((0, 0), moore=False) assert len(neighborhood) == 4 neighbors = self.grid.get_neighbors((1, 4), moore=False) assert len(neighbors) == 0 neighbors = self.grid.get_neighbors((1, 4), moore=True) assert len(neighbors) == 5 neighbors = self.grid.get_neighbors((1, 1), moore=False, include_center=True) assert len(neighbors) == 7 neighbors = self.grid.get_neighbors((1, 3), moore=False, radius=2) assert len(neighbors) == 11
def __init__(self, N, width=50, height=50, torus=True): self.num_agents = N self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus) self.create_agents() self.dc = DataCollector({"Gini": lambda m: m.compute_gini()}, {"Wealth": lambda a: a.wealth}) self.running = True
def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, sheep_gain_from_food=4): ''' Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy sheep_gain_from_food: Energy sheep gain from grass, if enabled. ''' # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.sheep_gain_from_food = sheep_gain_from_food self.schedule = RandomActivation(self) self.grid = MultiGrid(self.height, self.width, torus=True) # Create sheep: for i in range(self.initial_sheep): x = random.randrange(self.width) y = random.randrange(self.height) sheep = Sheep(self.grid, x, y, True) self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.wolf_gain_from_food) wolf = Wolf(self.grid, x, y, True, energy) self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) self.running = True
def setUp(self): ''' Create a test non-toroidal grid and populate it with Mock Agents ''' self.grid = MultiGrid(3, 5, self.torus) self.agents = [] counter = 0 for y in range(3): for x in range(5): for i in range(TEST_MULTIGRID[y][x]): counter += 1 # Create and place the mock agent a = MockAgent(counter, None) self.agents.append(a) self.grid.place_agent(a, (x, y))
def setUp(self): ''' Create a test non-toroidal grid and populate it with Mock Agents ''' width = 3 height = 5 self.grid = MultiGrid(width, height, self.torus) self.agents = [] counter = 0 for x in range(width): for y in range(height): for i in range(TEST_MULTIGRID[x][y]): counter += 1 # Create and place the mock agent a = MockAgent(counter, None) self.agents.append(a) self.grid.place_agent(a, (x, y))
def __init__(self, N, width, height): self.num_agents = N self.running = True self.grid = MultiGrid(height, width, True) self.schedule = RandomActivation(self) self.datacollector = DataCollector( model_reporters={"Gini": compute_gini}, agent_reporters={"Wealth": lambda a: a.wealth} ) # Create agents for i in range(self.num_agents): a = MoneyAgent(i, self) self.schedule.add(a) # Add the agent to a random grid cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) self.grid.place_agent(a, (x, y))
def __init__(self, height=grid_h, width=grid_w, init_people=2, rich_threshold=10, reserve_percent=50,): self.uid = next(self.id_gen) self.height = height self.width = width self.init_people = init_people self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus=True) # rich_threshold is the amount of savings a person needs to be considered "rich" self.rich_threshold = rich_threshold self.reserve_percent = reserve_percent # see datacollector functions above self.datacollector = DataCollector(model_reporters={ "Rich": get_num_rich_agents, "Poor": get_num_poor_agents, "Middle Class": get_num_mid_agents, "Savings": get_total_savings, "Wallets": get_total_wallets, "Money": get_total_money, "Loans": get_total_loans, "Model Params": track_params, "Run": track_run}, agent_reporters={ "Wealth": lambda x: x.wealth}) # create a single bank for the model self.bank = Bank(1, self, self.reserve_percent) # create people for the model according to number of people set by user for i in range(self.init_people): # set x coordinate as a random number within the width of the grid x = self.random.randrange(self.width) # set y coordinate as a random number within the height of the grid y = self.random.randrange(self.height) p = Person(i, (x, y), self, True, self.bank, self.rich_threshold) # place the Person object on the grid at coordinates (x, y) self.grid.place_agent(p, (x, y)) # add the Person object to the model schedule self.schedule.add(p) self.running = True
def __init__(self, height=50, width=50, initial_population=100): ''' Create a new Constant Growback model with the given parameters. Args: initial_population: Number of population to start with ''' # Set parameters self.height = height self.width = width self.initial_population = initial_population self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=False) self.datacollector = DataCollector({"SsAgent": lambda m: m.schedule.get_breed_count(SsAgent), }) # Create sugar import numpy as np sugar_distribution = np.genfromtxt("sugarscape_cg/sugar-map.txt") for _, x, y in self.grid.coord_iter(): max_sugar = sugar_distribution[x, y] sugar = Sugar((x, y), self, max_sugar) self.grid.place_agent(sugar, (x, y)) self.schedule.add(sugar) # Create agent: for i in range(self.initial_population): x = self.random.randrange(self.width) y = self.random.randrange(self.height) sugar = self.random.randrange(6, 25) metabolism = self.random.randrange(2, 4) vision = self.random.randrange(1, 6) ssa = SsAgent((x, y), self, False, sugar, metabolism, vision) self.grid.place_agent(ssa, (x, y)) self.schedule.add(ssa) self.running = True self.datacollector.collect(self)
def __init__(self, height=50, width=50, init_agents=500, max_metabolism=3, max_vision=10, max_init_sugar=5, min_age=30, max_age=60, init_poll=3, ex_ratio=2, ex_mod=1, poll_growth_rule=True, inheritance_rule=True): self.height = height self.width = width self.init_agents = init_agents self.init_poll = init_poll self.max_metabolism = max_metabolism self.max_vision = max_vision self.max_init_sugar = max_init_sugar self.min_age = min_age self.max_age = max_age self.ex_ratio = ex_ratio self.ex_mod = ex_mod self.replacement_rule = True self.pollution_rule = False self.diffusion_rule = False self.push_rule = False self.poll_growth_rule = poll_growth_rule self.expend_rule = True self.inheritance_rule = inheritance_rule self.map = self.import_map() self.grid = MultiGrid(height, width, torus=True) self.schedule = RandomActivationByType(self) self.datacollector = DataCollector({'Pollution': (lambda m: m.total_pollution), 'Wealth': (lambda m: m.total_wealth/m.init_agents), 'Agents': (lambda m: len(m.schedule.agents_by_type[ScapeAgent]))}, {'Wealth': self.collect_wealth, 'Metabolism': self.collect_metabolism, 'Vision': self.collect_vision}) self.total_wealth = 0 self.total_pollution = 0 self.populate_sugar() self.populate_agents()
class Epidemic(Model): height = 30 width = 30 initial_susceptible = 100 initial_infected = 50 initial_recovered = 0 hospital = 1 mortalityRate = 0.1 social_isolation = False verbose = False description = 'A model for simulating spread of Corona Virus using SIR modelling.' def __init__(self, height=30, width=30, initial_susceptible=100, initial_infected=50, hospital=1, social_isolation=False, mortalityRate=0.1): super().__init__() # Set parameters self.height = height self.width = width self.initial_susceptible = initial_susceptible self.initial_infected = initial_infected self.hospital = hospital self.social_isolation = social_isolation self.mortalityRate = mortalityRate self.schedule = RandomActivationByType(self) self.grid = MultiGrid(self.height, self.width, torus=True) #Collecting the data for Agents self.datacollector = DataCollector({ "Infected": lambda m: m.schedule.get_type_count(Infected), "Susceptible": lambda m: m.schedule.get_type_count(Susceptible), "Recovered": lambda m: m.schedule.get_type_count(Recovered) }) #Creating Susceptibles for i in range(self.initial_susceptible): x = self.random.randrange(self.width) y = self.random.randrange(self.height) newSusceptible = Susceptible(self.next_id(), (x, y), self, social_isolation) self.grid.place_agent(newSusceptible, (x, y)) self.schedule.add(newSusceptible) #Creating Infected for i in range(self.initial_infected): x = self.random.randrange(self.width) y = self.random.randrange(self.height) newInfected = Infected(self.next_id(), (x, y), self, social_isolation, mortalityRate) self.grid.place_agent(newInfected, (x, y)) self.schedule.add(newInfected) #Creating Hospitals for i in range(self.hospital): x = self.random.randrange(self.width) y = self.random.randrange(self.height) newHospital = Hospital(self.next_id(), (x, y), self, social_isolation) self.grid.place_agent(newHospital, (x, y)) self.schedule.add(newHospital) self.running = True self.datacollector.collect(self) def step(self): self.schedule.step() self.datacollector.collect(self) if self.verbose: print([ self.schedule.time, self.schedule.get_type_count(Infected), self.schedule.get_type_count(Susceptible), self.schedule.get_type_count(Recovered) ]) def run_model(self, step_count=200): if self.verbose: print('Initial number infected: ', self.schedule.get_type_count(Infected)) print('Initial number susceptible: ', self.schedule.get_type_count(Susceptible)) print('Initial number recovered: ', self.schedule.get_type_count(Recovered)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number infected: ', self.schedule.get_type_count(Infected)) print('Final number susceptible: ', self.schedule.get_type_count(Susceptible)) print('Final number recovered: ', self.schedule.get_type_count(Recovered))
def __init__(self, N, iterations, bleedout_rate=np.random.normal(0.5, scale=0.1), mp=False): """ Create a new instance of the DDA model. Parameters: N - the number of agents iterations - the number of iterations to run the model for blr - the bleedout rate (the probability that agents leave at the midpoint) (default normal distribution with mean=0.5 and sd=0.1) mp - whether to use multiprocess (agents call step() method at same time) (doesn't work!) (default False) """ self.num_agents = N self._bleedout_rate = bleedout_rate self.iterations = iterations self.mp = mp # Locations of important parts of the environment. These shouldn't be changed self.graveyard = (0, 0) # x,y locations of the graveyard self.loc_a = (1, 0) # Location a (on left side of street) self.loc_b = (23, 0) # Location b (on the right side) self.loc_mid = (12, 0) # The midpoint # 'Cameras' that store the number of agents who pass them over the course of an hour. The historical counts # are saved by mesa using the DataCollector self._camera_a = 0 # Camera A self._camera_b = 0 # Camera B self._camera_m = 0 # The midpoint # Set up the scheduler. Note that this isn't actually used (see below re. agent's stepping) self.schedule = RandomActivation(self) # Random order for calling agent's step methods # For multiprocess step method self.pool = Pool() # Create the environment self.grid = MultiGrid(DDAModel._width, DDAModel._height, False) # Define a variable that can be used to indicate whether the model has finished self.running = True # Create a distribution that tells us the number of agents to be added to the world at each self._agent_dist = DDAModel._make_agent_distribution(N) # Create all the agents for i in range(self.num_agents): a = DDAAgent(i, self) self.schedule.add(a) # Add the agents to the schedule # All agents start as 'retired' in the graveyard a.state = AgentStates.RETIRED self.grid.place_agent(a, self.graveyard) # All agents start in the graveyard print("Created {} agents".format(len(self.schedule.agents))) # Define a collector for model data self.datacollector = DataCollector( model_reporters={"Bleedout rate": lambda m: m.bleedout_rate, "Number of active agents": lambda m: len(m.active_agents()), "Camera A counts": lambda m: m.camera_a, "Camera B counts": lambda m: m.camera_b, "Camera M counts": lambda m: m.camera_m }, agent_reporters={"Location (x)": lambda agent: agent.pos[0], "State": lambda agent: agent.state } )
def __init__(self, height=height, width=width, ini_buyers=ini_buyers, ini_sellers=ini_sellers): '''Parameters''' reader = csv.reader(open(self.fpath, 'r')) d = dict() for key, value in reader: d[key] = float(value) self.height = int(d['height']) self.width = int(d['width']) self.ini_buyers = int(d['ini_buyers']) self.ini_sellers = int(d['ini_sellers']) self.ini_cash = d['ini_cash'] self.num_w = int(d['num_w']) self.trust_w = d['trust_w'] self.costs = d['costs'] * ini_buyers self.mktresearch = d['mktresearch'] self.priceRange = d['priceRange'] self.csa = d['csa'] self.csa_length = int(d['csa_length']) self.network = d['network'] self.lb = d['lb'] # Lower bound self.ub = d['ub'] # Upper bound (in effect, unbounded) self.up = d['up'] # Up rate self.down = d['down'] # Down rate ''' Entry mode 0: No entry 1: Full market research 2: Whenever Avg cash balance > entryThreshhold with a random position 3: Whenever Max cash balance > entryThreshhold enter nearby that position ''' self.entry = int(d['entry']) self.entryFrequency = int(d['entryFrequency']) self.entryThreshhold = d['entryThreshhold'] * self.ini_cash self.entryRadius = int(d['entryRadius']) # Area within high earner that a new seller will plop down '''Debugging''' self.sellerDebug = d['sellerDebug'] self.buyerDebug = d['buyerDebug'] self.networkDebug = d['networkDebug'] self.utilweightDebug = d['utilweightDebug'] self.entryDebug = d['entryDebug'] self.schedule = RandomActivationByType(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector( {"Sellers": lambda m: m.schedule.get_type_count(Seller), "Buyers": lambda m: m.schedule.get_type_count(Buyer)}) '''Initialization''' self.cnt = 0 # Period counter self.buyers = {} # Dictionary of buyer instances self.sellers = {} # Dictionary of seller instances self.sid_alive = [] self.pi = [0] * (height * width) # Profitability prices = {} for i in range(ini_sellers): prices[i] = self.priceRange * np.random.rand() + 1 min_price = min(prices.values()) for i in range(self.num_w): prices[i] = min_price * 0.9 self.prices = prices e = {} # Embeddedness for i in range(ini_sellers): e[i] = 0.8*np.random.rand() + 0.2 # 0.2 - 1.0 for i in range(self.num_w): e[i] = 0 self.e = e '''Create buyers''' for i in range(self.ini_buyers): # It seems coincidence in the same cell is allowed x = np.random.randint(self.width) y = np.random.randint(self.height) α = d['alpha'] trust = {} β = d['beta']*np.random.rand() for j in range(ini_sellers): trust[j] = np.random.rand() for j in range(self.num_w): trust[j] = self.trust_w γ = d['gamma'] ''' Network ties ties[j]=0 means 'no connection with bid=j buyer' ties[own bid] = 0 or 1 means nothing. ''' ties = dict(zip(range(ini_buyers),[0]*ini_buyers)) buyer = Buyer(i, self.grid, (x, y), True, α, trust, β, γ, ties) self.buyers[i] = buyer # Dictionary key is an integer self.grid.place_agent(buyer, (x, y)) self.schedule.add(buyer) '''Create sellers''' for i in range(self.ini_sellers): x = np.random.randint(self.width) y = np.random.randint(self.height) cash = self.ini_cash costs = self.costs price = self.prices[i] w = False if i < self.num_w: w = True e = self.e[i] seller = Seller(i, self.grid, (x, y), True, cash, costs, price, w, e) self.sellers[i] = seller self.grid.place_agent(seller, (x, y)) self.schedule.add(seller) self.running = True
class SleepAnimals_sinDataColl(Model): ''' Analysis of the evolution of sleep in animals ''' # Default values width = 40 height = 40 number_food_patch = 40 number_sleep_patch = 40 interdistance_factor = 0.7 intradistance_factor = 0.2 fp_depletion_tick = 60 def __init__(self, model_id , genome,width = 40, height = 40, number_food_patch = 40, number_sleep_patch = 40, interdistance_factor = 0.7, intradistance_factor = 0.2, fp_depletion = 60, sleep_and_food_gainfactor = 1): super().__init__() # Setting Parameters self.model_id = model_id self.width = width self.height = height self.number_food_patch = number_food_patch self.number_sleep_patch = number_sleep_patch self.interdistance_factor = interdistance_factor self.intradistance_factor = intradistance_factor self.sue_factor = sleep_and_food_gainfactor self.genome = genome self.fp_center_x = 0 self.fp_center_y = 0 self.sp_center_x = 0 self.sp_center_y = 0 self.current_id_food_patch = 0 self.current_id_sleep_patch = 0 self.fp_tick_to_depletion = fp_depletion self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus = False) #self.datacollector = DataCollector( # agent_reporters={"Food_fitness" : lambda a: a.fitness_food, # "Sleep_fitness" : lambda a: a.fitness_sleep, # "Fitness" : lambda a: a.fitness, # "Mode" : lambda a: a.mode, # "Direction" : lambda a: a.lookingto}) # Picking Centers for Food and Sleep Patches self.interdistance = 0 self.intradistance = 0 self.findingcenters() # Populating Food Patches self.available_food_patches = self.grid.get_neighborhood( (self.fp_center_x, self.fp_center_y), False, True, self.intradistance ) i = 0 while i < self.number_food_patch: self.new_foodpatch() i += 1 # Populating Sleep Patches self.available_sleep_patches = self.grid.get_neighborhood( (self.sp_center_x, self.sp_center_y), False, True, self.intradistance ) i = 0 while i < self.number_sleep_patch: current_spot = random.choice(self.available_sleep_patches) if not self.grid.is_cell_empty(current_spot): continue sleep_patch = SleepPatch( self.next_id_sleeppatch(), self, current_spot ) self.grid.place_agent( sleep_patch, current_spot ) i += 1 # Adding Animal to the world current_spot = random.choice( self.grid.empties ) animal = Animal( self.next_id(), self, current_spot, self.genome, self.sue_factor, self.sue_factor ) self.grid.place_agent( animal, current_spot ) self.schedule.add( animal ) def step(self): '''Advance the model by one step.''' # self.datacollector.collect(self) self.schedule.step() def findingcenters(self): max_manhattan_length = self.height + self.width self.interdistance = int(max_manhattan_length * self.interdistance_factor) self.intradistance = int(max_manhattan_length * self.intradistance_factor) fp_center_x = 0 fp_center_y = 0 sp_center_x = 0 sp_center_y = 0 centers_selected = False while not centers_selected: fp_center_x = random.randrange(self.width) fp_center_y = random.randrange(self.height) fp_center = (fp_center_x, fp_center_y) available_spots_food = self.grid.get_neighborhood(fp_center, False, False, self.intradistance) if len(available_spots_food) < 80: continue if self.interdistance > 0: list_centers_sp = list( set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance + 1) ) - set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance - 1) ) ) if len(list_centers_sp) < 5: continue else: list_centers_sp = [(fp_center_x,fp_center_y)] sp_center = random.choice(list_centers_sp) (sp_center_x, sp_center_y) = sp_center available_spots_sleep = self.grid.get_neighborhood(sp_center, False, False, self.intradistance) if len(available_spots_sleep) < 80: continue centers_selected = True self.fp_center_x = fp_center_x self.fp_center_y = fp_center_y self.sp_center_x = sp_center_x self.sp_center_y = sp_center_y def next_id_foodpatch(self): """ Return the next unique ID for food patches, increment current_id""" self.current_id_food_patch += 1 a = 'M' + str(self.model_id) + 'F' + str(self.current_id_food_patch) return a def next_id_sleeppatch(self): """ Return the next unique ID for sleep patches, increment current_id""" self.current_id_sleep_patch += 1 a = 'M' + str(self.model_id) + 'S' + str(self.current_id_sleep_patch) return a def new_foodpatch(self): spot_found = False while not spot_found : current_spot = random.choice(self.available_food_patches) if not self.grid.is_cell_empty(current_spot): continue food_patch = FoodPatch(self.next_id_foodpatch(), self, current_spot, self.fp_tick_to_depletion) self.grid.place_agent(food_patch, current_spot) spot_found = True def arrayRGB_clusters(self): available_spots = np.full( (self.grid.width , self.grid.height , 3) , 255) for coordinates in self.available_sleep_patches: (x, y) = coordinates available_spots[x][y]= [100, 0, 150] for coordinates in self.available_food_patches: (x, y) = coordinates available_spots[x][y]= [10, 150, 0] return available_spots def arrayRGB_display(self): RGBdisplay = np.full((self.grid.width, self.grid.height,3), 255) for cell in self.grid.coord_iter(): cell_content, x, y = cell a = list(cell_content) if len(a) == 0: RGBdisplay[x][y] = [255,255,255] elif len(a) == 1: if isinstance(a[0], SleepPatch): RGBdisplay[x][y] = [100,0,150] elif isinstance(a[0], FoodPatch): RGBdisplay[x][y] = [10,150,0] elif isinstance(a[0], Animal): RGBdisplay[x][y] = [0,0,0] else: pass elif len(a) == 2: RGBdisplay[x][y] = [0,0,0] else: pass return RGBdisplay def array2D_display(self): display2D = np.zeros((self.grid.width, self.grid.height)) for cell in self.grid.coord_iter(): cell_content, x, y = cell a = list(cell_content) if len(a) == 0: display2D[x][y] = 0 elif len(a) == 1: if isinstance(a[0], SleepPatch): display2D[x][y] = 10 elif isinstance(a[0], FoodPatch): display2D[x][y] = 20 elif isinstance(a[0], Animal): display2D[x][y] = 30 else: pass else: pass return display2D
def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4, compGregSheep=1, compGregWolf=0): ''' Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. ''' super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.compGregSheep = compGregSheep self.compGregWolf = compGregWolf self.energy_totale = 0 self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep) }) # Create sheep: for i in range(self.initial_sheep): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.sheep_gain_from_food) self.energy_totale += energy sheep = Sheep(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.wolf_gain_from_food) self.energy_totale += energy wolf = Wolf(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = random.randrange(self.grass_regrowth_time) patch = GrassPatch(self.next_id(), (x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self)
def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4): ''' Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. ''' super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector( {"Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep)}) # Create sheep: for i in range(self.initial_sheep): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.sheep_gain_from_food) sheep = Sheep(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.wolf_gain_from_food) wolf = Wolf(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = self.random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = self.random.randrange(self.grass_regrowth_time) patch = GrassPatch(self.next_id(), (x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self)
class RoadNetworkModel(Model): description = ( "A model for simulating Road Network Model" ) def __init__(self, number_of_cars, width, height, is_odd_even_policy_enabled, is_odd_date, policy_range_time): # Tick increment self.tick = 0 # Mean Travel Time self.mean_travel_time = 0.0 # Odd-Even Policy Enabled self.is_odd_even_policy_enabled = is_odd_even_policy_enabled # Set the day of the week self.is_odd_date = is_odd_date # Set up Spatial dimension self.grid = MultiGrid(width, height, True) # Set up Temporal dimension self.schedule = SimultaneousActivation(self) self.running = True self.policy_range_time = policy_range_time # Set up peak hours self.start_peak_hour_1 = PEAK_HOURS["START_PEAK_HOUR_1"] #7 self.end_peak_hour_1 = PEAK_HOURS["END_PEAK_HOUR_1"] #10 self.start_peak_hour_2 = PEAK_HOURS["START_PEAK_HOUR_2"] #4 self.end_peak_hour_2 = PEAK_HOURS["END_PEAK_HOUR_2"] #7 # Car distribution num_highly_active_cars = math.ceil(ACTIVITY_PROPORTION["HIGHLY_ACTIVE"] * number_of_cars) num_business_hours_cars = math.ceil(ACTIVITY_PROPORTION["BUSINESS_HOURS"] * number_of_cars) num_peak_hours_cars = number_of_cars - (num_highly_active_cars + num_business_hours_cars) # generate road self.map = MapGenerator() roadPosition = self.map.get_road_position() for i in range(len(roadPosition)): road = Road(i, roadPosition[i], self) self.grid.place_agent(road, roadPosition[i]) ## generate office officePosition = self.map.get_office_position() for i in range(len(officePosition)): office = Office(i, officePosition[i], self) self.grid.place_agent(office, officePosition[i]) # generate residence residencePosition = self.map.get_residence_position() for i in range(len(residencePosition)): residence = Residence(i, residencePosition[i], self) self.grid.place_agent(residence, residencePosition[i]) # generate entertainment entertainmentPosition = self.map.get_entertainment_position() for i in range(len(entertainmentPosition)): entertainment = Entertainment(i, entertainmentPosition[i], self) self.grid.place_agent(entertainment, entertainmentPosition[i]) # generate traffic light trafficLightPosition = self.map.get_traffic_light_position() for i in range(len(trafficLightPosition)): trafficLight = TrafficLight(i, trafficLightPosition[i], self, COLOR["dark_grey"]) self.grid.place_agent(trafficLight, trafficLightPosition[i]) # Get source and destination lists residence_list = self.map.get_residence_position() office = self.map.get_office_position() entertainment = self.map.get_entertainment_position() # Create destination list based on weekday/weekend proportion proportion_of_office_workers = 0.65 number_of_office_workers = math.ceil(proportion_of_office_workers * number_of_cars) number_of_shopper = number_of_cars - number_of_office_workers office_list = [] while len(office_list) <= number_of_office_workers: office_list.append(office[self.random.randint(0, len(office) -1)]) entertainment_list = [] while len(entertainment_list) <= number_of_shopper: entertainment_list.append(entertainment[self.random.randint(0, len(entertainment) - 1)]) office_entertainment_list = office_list + entertainment_list random.shuffle(residence_list) layout = self.map.get_layout() for i in range(number_of_cars): # determine departure and return time based on activity level if i <= num_highly_active_cars: activity_level = "HIGHLY_ACTIVE" departure_time = 0 return_time = float("inf") elif i <= num_business_hours_cars: activity_level = "BUSINESS_HOURS" departure_time = self.start_peak_hour_1 return_time = float("inf") else: activity_level = "PEAK_HOURS" departure_time = self.random.randint(self.start_peak_hour_1,self.end_peak_hour_1) return_time = self.random.randint(self.start_peak_hour_2,self.end_peak_hour_2) plate_number_oddity = self.random.randint(0, 1) source_x = residence_list[i][0] source_y = residence_list[i][1] destination_x = office_entertainment_list[i][0] destination_y = office_entertainment_list[i][1] state_fringes = self.map.get_fringes(source_x, source_y) shortest_distance = float("inf") car_direction = state_fringes[0][1] for state_fringe in state_fringes: current_direction = state_fringe[1] # "^" "v" ">" "<" if current_direction in DIRECTION: temp_x = state_fringe[0][0] + DIRECTION[current_direction][0] temp_y = state_fringe[0][1] + DIRECTION[current_direction][1] newDist = get_euclidean_distance((temp_x, temp_y), (destination_x, destination_y)) if newDist < shortest_distance: shortest_distance = newDist car_direction = current_direction # all cars are initialised as IDLE car_state = "IDLE" car = Car(i, plate_number_oddity, (source_x,source_y), (destination_x,destination_y), car_direction, car_state, departure_time, return_time, activity_level, self) self.grid.place_agent(car, (source_x,source_y)) self.schedule.add(car) # Data Collection self.datacollector = DataCollector({ "Idle": number_idle_cars, "Move": number_move_cars, "Finished": number_finished_cars, "SimulationMinutes": simulation_minutes, "ToOffice": number_office, "ToResidence": number_residence, "MeanTravelTime": mean_travel_time, "StdTravelTime": std_travel_time }) self.datacollector.collect(self) def step(self): self.schedule.step() self.tick += 1 self.mean_travel_time = np.mean([cell.travel_time for j in range(100) for i in range(100) for cell in self.grid.iter_cell_list_contents((i,j)) if type(cell) is Car]) self.datacollector.collect(self) # After a day (1440 minutes), stop the simulation if self.tick >= 1440: self.running = False def is_plate_number_oddity_allowed(self, plate_number_oddity=0, xy=(0, 0)): x, y = xy # implement odd even policy for avenue only. if(self.map.is_avenue(x, y)): if(self.is_odd_date == True): # date is odd if(plate_number_oddity % 2 == 1): # plate is odd return True else: return False else: # date is even if(plate_number_oddity % 2 == 0): # plate is even return True else: return False else: return True def is_odd_even_policy_time(self): #1 day == 1440 minutes day_tick = self.tick % 1440 if self.policy_range_time == '7_10_and_16_19': if day_tick >= (7 * 60) and day_tick <= (10 * 60): return True elif day_tick >= (16 * 60) and day_tick <= (19 * 60): return True else: return False elif self.policy_range_time == '8_11_and_17_20': if day_tick >= (8 * 60) and day_tick <= (11 * 60): return True elif day_tick >= (17 * 60) and day_tick <= (20 * 60): return True else: return False elif self.policy_range_time == '6_9_and_15_18': if day_tick >= (6 * 60) and day_tick <= (9 * 60): return True elif day_tick >= (15 * 60) and day_tick <= (18 * 60): return True else: return False elif self.policy_range_time == '8_9_and_17_18': if day_tick >= (8 * 60) and day_tick <= (9 * 60): return True elif day_tick >= 17 * 60 and day_tick <= 18 * 60: return True else: return False elif self.policy_range_time == '6_11_and_15_20': if day_tick >= (6 * 60) and day_tick <= (11 * 60): return True elif day_tick >= (15 * 60) and day_tick <= (20 * 60): return True else: return False else: return False
def __init__(self, elevators=4, floors=16, a=0, passager_flow='up', controller='baseline', alpha=1, beta=1, theta=1, output_file=False): super().__init__() #self.running = True self.num_elevators = int(elevators) self.num_floors = int(floors) self.grid = MultiGrid(int(elevators) + 1, (int(floors)), False) self.schedule = BaseScheduler(self) self.a = a self.between_floors = 3 self.verbose = False # Print-monitoring self.floors = [] self.elevators = [] self.attended = [] self.passager_flow = passager_flow self.simulation = self.get_simulation(passager_flow) self.alpha = alpha self.beta = beta self.theta = theta self.controller = controller self.gerado_saida = not output_file # Create elevators for i in range(self.num_elevators): # Add the agent to a random grid cell a = ElevatorAgent("e_" + str(i), (i + 1, 0), self, self.alpha, self.beta, self.theta) #seta todos UP # #estado de todos é 5 (0 =fora d servico, 1 = parado com viagem para baixo, 2 = parado com viagem para cima, 3 = sem missao, 4 = descendo, 5 = subindo) self.schedule.add(a) self.elevators.append(a) self.grid.place_agent(a, (i + 1, 0)) # Create floors for i in range(self.num_floors): a = FloorAgent("f_" + str(i), i, (0, i), self) self.schedule.add(a) self.grid.place_agent(a, (0, i)) self.floors.append(a) #tempo medio de espera #tempo medio de atendimento #tempo medio global #numero de passageiros em cada andar #numero de passageiros em cada carro self.datacollector = DataCollector( model_reporters={ "Attended": get_attended, "Floors": get_floors, "Cars": get_cars, "JourneyTime": get_journey_time, "WaitingTime": get_waiting_time, "TotalTime": get_total_time, "WaitingFloor": get_waiting_floor })
class Modelo(Model): """ A model with some number of agents. """ atendidos = 0 num_elevators = 1 num_floors = 15 a = 1 floors = [] elevators = [] attended = [] gerado_saida = False def __init__(self, elevators=4, floors=16, a=0, passager_flow='up', controller='baseline', alpha=1, beta=1, theta=1, output_file=False): super().__init__() #self.running = True self.num_elevators = int(elevators) self.num_floors = int(floors) self.grid = MultiGrid(int(elevators) + 1, (int(floors)), False) self.schedule = BaseScheduler(self) self.a = a self.between_floors = 3 self.verbose = False # Print-monitoring self.floors = [] self.elevators = [] self.attended = [] self.passager_flow = passager_flow self.simulation = self.get_simulation(passager_flow) self.alpha = alpha self.beta = beta self.theta = theta self.controller = controller self.gerado_saida = not output_file # Create elevators for i in range(self.num_elevators): # Add the agent to a random grid cell a = ElevatorAgent("e_" + str(i), (i + 1, 0), self, self.alpha, self.beta, self.theta) #seta todos UP # #estado de todos é 5 (0 =fora d servico, 1 = parado com viagem para baixo, 2 = parado com viagem para cima, 3 = sem missao, 4 = descendo, 5 = subindo) self.schedule.add(a) self.elevators.append(a) self.grid.place_agent(a, (i + 1, 0)) # Create floors for i in range(self.num_floors): a = FloorAgent("f_" + str(i), i, (0, i), self) self.schedule.add(a) self.grid.place_agent(a, (0, i)) self.floors.append(a) #tempo medio de espera #tempo medio de atendimento #tempo medio global #numero de passageiros em cada andar #numero de passageiros em cada carro self.datacollector = DataCollector( model_reporters={ "Attended": get_attended, "Floors": get_floors, "Cars": get_cars, "JourneyTime": get_journey_time, "WaitingTime": get_waiting_time, "TotalTime": get_total_time, "WaitingFloor": get_waiting_floor }) def step(self): #aqui vai a logica do fluxo de passageiros #chegada de passageiros #lista de botoes self.schedule.step() print(self.schedule.get_agent_count) self.datacollector.collect(self) #se nao tem mais passageiros pra chegar nem pra ser atendido #cria um csv com os dados #so uma vez if not self.gerado_saida and self.schedule.time > 1198: self.gerado_saida = True save_file_results(self) def run_model(self, step_count=1200): for i in range(step_count): self.step() print("step: ", i) def get_simulation(self, fluxo): #le o arquivo de fluxos # simulação: if fluxo == 'up': with open('resources/traff_up.txt', 'r') as f: traff_up = json.loads(f.read()) return traff_up elif fluxo == 'dp': with open('resources/traff_dp.txt', 'r') as f: traff_dp = json.loads(f.read()) return traff_dp elif fluxo == 'du': with open('resources/traff_du.txt', 'r') as f: traff_du = json.loads(f.read()) return traff_du else: with open('resources/traff_poisson.txt', 'r') as f: traff_poisson = json.loads(f.read()) return traff_poisson
class board(Model): def __init__(self,num_wolverines,num_spartans,num_buckeyes, height = 40, width = 40): '''Initializes the board and randomly puts spartans and wolverines in the board. This uses a multigrid and rolling boundary conditions''' self.num_wolverines = num_wolverines self.num_spartans = num_spartans self.num_buckeyes = num_buckeyes self.height = height self.width = width self.grid = MultiGrid(self.height, self.width,torus = True) self.schedule = RandomActivation(self) #Creates Wolverines for i in range(self.num_wolverines): x = random.randrange(self.width) y = random.randrange(self.height) wolverine = Wolverine((x, y), self) self.grid.place_agent(wolverine, (x, y)) self.schedule.add(wolverine) # Create Spartans for i in range(self.num_spartans): x = random.randrange(self.width) y = random.randrange(self.height) spartan = Spartan((x, y), self) self.grid.place_agent(spartan, (x, y)) self.schedule.add(spartan) # Create Buckeyes for i in range(self.num_spartans): x = random.randrange(self.width) y = random.randrange(self.height) buckeye = Buckeye((x, y), self) self.grid.place_agent(buckeye, (x, y)) self.schedule.add(buckeye) self.running = True def step(self): '''Goes through the step functions found in the agents''' self.schedule.step() def run_model(self,num_iterations): '''Just iterates over the step for a given number of times and shows the colormap, this is mostly just for testing and the final result should include animation''' for i in range(num_iterations): self.step() self.print_model() def print_model(self): '''This function prints and does some operations in the function, specifically it goes through each square and if a wolverine and spartan are in the same square, it initiates combat along with putting the concentration of entities on a colormap, which is from my jupyter notebook''' agent_counts = np.zeros((self.grid.width, self.grid.height)) self.total_count = 0 for cell in self.grid.coord_iter(): cell_content, x, y = cell self.total_count+=len(cell_content) cell_cont = list(cell_content) #This is statement goes through each cell and sees if there is a #spartan and wolverine in the same square, then initiates combat if cell_cont!=[]: #Have the class objects return their name and if it meets the #criteria, moves to combat if any(x.name() == "Spartan" for x in cell_cont) and \ any(x.name() == "Wolverine" for x in cell_cont): killed = False for j in cell_content: if j.name()=="Spartan": killed = j.kill_wolverine() break if killed: for i in cell_content: if i.name() == "Wolverine": j.add_food_from_kill(i.food_contents()) i.wolverine_killed() print('A wolverine has just been killed') break if any(x.name() == "Buckeye" for x in cell_cont) and \ any(x.name() == "Wolverine" for x in cell_cont): killed = False for j in cell_content: if j.name()=="Buckeye": killed = j.kill_wolverine() break if killed: for i in cell_content: if i.name() == "Wolverine": j.add_food_from_kill(i.food_contents()) i.wolverine_killed() print('A wolverine has just been killed') break if any(x.name() == "Spartan" for x in cell_cont) and \ any(x.name() == "Buckeye" for x in cell_cont): killed = False for j in cell_content: if j.name()=="Spartan": killed = j.kill_wolverine() break if killed: for i in cell_content: if i.name() == "Buckeye": j.add_food_from_kill(i.food_contents()) i.buckeye_killed() print('A buckeye has just been killed') break agent_count = len(cell_content) agent_counts[x][y] = agent_count print(self.total_count) plt.imshow(agent_counts, interpolation='nearest') plt.colorbar() plt.show()
def __init__(self, shock_period, shock_duration, shock_rate, N_cities, N_a, nc_rate, width, height): #canvas info self.width = width self.height = height #sim boilerplate self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.running = True self.num_nc = 0 #counts number of applicants self.num_azc = N_a #number of AZC in sim self.nc_rate = nc_rate #rate of inflow of newcomers self.num_cities = N_cities #number of cities in sim self.num_buildings = 3 self.num_activity_centers = 2 self.num_activities_per_center = 2 self.num_per_step = 10 self.num_activity_centers = 2 self.num_activities_per_center = 2 #initialize shock values self.shock_period = shock_period #how often does shock occur self.shock_duration = shock_duration #how long does shock last self._shock_duration = shock_duration #current position in shock self.shock_rate = shock_rate #amt of increase during shock self.shock = False #shock flag self.number_added = 1 #base rate of influx self.number_shocks = 4 self.shock_growth = 2 #dict of probabilities of first/second decision success rates by country self.specs = {} # list of multinomial probabilities for countries self.country_multinomial = [] # list of shock distributions for countries related to adding newcomers self.country_shock_dist = [] # list of countries self.country_list = [] with open("country-input.csv") as csvfile: reader = csv.DictReader(csvfile) for row in reader: decisionList = [] decisionList.append(float(row['DecisionA'])) decisionList.append(float(row['DecisionB'])) self.specs[row['Country']] = decisionList self.country_shock_dist.append(row['ShockDist']) self.country_list.append(row['Country']) self.country_multinomial.append(row['Multinomial']) self.country_count = np.zeros( len(self.country_list )) #keeps track of how many applicants from each country self.country_success = np.zeros(len(self.country_list)) self.current_country_index = -1 #records capacitiy of each AZC type self.datacollector = DataCollector(model_reporters={ 'Cap - Extended-AS': calc_extended_as, 'Cap - AS': calc_as }) #records success rates of each country of origin using current_country_index #which is manipulated in sr_country sr_functions = {} for i in range(0, len(self.country_list)): self.current_country_index = i sr_functions[self.country_list[ self.current_country_index]] = sr_country self.sr = DataCollector(model_reporters=sr_functions) self.capacity_dc = DataCollector(model_reporters={ 'Current Capacity': coa_occ, 'Projected Capacity': coa_proj }) #Ter apel ta_pos = (int(self.width / 2), int(self.height / 6 * 5)) ta_id = self.num_cities + 1 ter_apel = City(self.num_cities + 1, self, ta_pos) ta_coa = COA(ta_id, self, ter_apel) ta_coa.ta = True self.schedule.add(ta_coa) ta_ind = IND(ta_id, self, ter_apel) self.schedule.add(ta_ind) ta_azc = AZC(ta_id, self, 'edp', ta_pos, ta_coa) ta_azc.ta = True ta_coa.azcs.add(ta_azc) ta_coa.capacities[ta_azc] = ta_azc.occupancy self.schedule.add(ta_azc) self.grid.place_agent(ta_azc, ta_pos) self.ter_apel = ta_azc #add activities self.test_activity = Football(0, self, 5) self.schedule.add(self.test_activity) #generate cities for city in range(self.num_cities): space_per_city = int(self.width / self.num_cities) orientation_x = int( space_per_city / 2 + city * space_per_city + int(space_per_city / self.num_azc / 2)) #center point for city pos = (orientation_x, int(self.height / 2)) #placeholder position city_size = np.random.uniform(low=0, high=1) city_is_big = False if city_size > 0.70: city_is_big = True current_city = City(city, self, pos, city_is_big) #instantiates city #add COA current_coa = COA(city, self, current_city) current_city.coa = current_coa self.schedule.add(current_coa) self.grid.place_agent(current_coa, (pos[0], int(self.height / 3 * 2))) current_ind = IND(city, self, current_city) self.schedule.add(current_ind) current_coa.IND = current_ind current_ind.coa = current_coa #adds city to schedule n grid self.schedule.add(current_city) self.grid.place_agent(current_city, (current_city.pos)) #azc location essentials space_per_azc = int(space_per_city / self.num_azc) azc_starting_point = orientation_x - (.5 * space_per_city) num_activity_centers_added = 0 # Create AZCs for i in range(self.num_azc): ''' if i == 0: occupant_type = 'edp' # ter apel ''' if i < self.num_azc - 2: occupant_type = 'as' # standard AZC elif i == self.num_azc - 2: occupant_type = 'as_ext' # extended procedure AZC else: occupant_type = 'tr' # 'Housing' for those with #place evenly x = int(azc_starting_point + i * space_per_azc) y = int(self.height * .5) a = AZC(i, self, occupant_type, (x, y), current_coa) #instantiate self.schedule.add(a) #add in time self.grid.place_agent(a, (x, y)) #add in spaace current_city.buildings.add(a) if a.occupant_type != 'tr': current_coa.azcs.add(a) current_coa.capacities[a] = a.occupancy if a.occupant_type == 'tr': current_city.social_housing = a #add viz v = AZC_Viz(self, a) self.schedule.add(v) self.grid.place_agent(v, v.pos) #create civilian buildings y = int(self.height / 5) space_per_building = space_per_city / self.num_buildings row_size = 15 if city == 0: x = int(azc_starting_point + .5 * space_per_building) current = Hotel(self.num_buildings + 1, self, (x, y), 1000) current_city.buildings.add(current) current.city = current_city self.grid.place_agent(current, (x, y)) self.schedule.add(current) empty = Empty(self.num_buildings + 1, self, (int(x + space_per_building), y), 100) current_city.buildings.add(empty) empty.city = current_city self.grid.place_agent(empty, (int(x + space_per_building), y)) self.schedule.add(empty) for bdg in range(city * self.num_buildings): x = int(azc_starting_point + (bdg % 3) * space_per_building) if bdg == 0: current = Hotel(bdg, self, (x, y), 1000) current_city.buildings.add(current) current.city = current_city self.grid.place_agent(current, (x, y)) self.schedule.add(current) else: empty = Empty(bdg, self, (x, y - row_size * int(bdg / 3)), 100 * bdg) current_city.buildings.add(empty) empty.city = current_city self.grid.place_agent(empty, (x, y - row_size * int(bdg / 3))) self.schedule.add(empty)
class HumanitarianLogistics(Model): """A model with: number of azc rate of newcomer arrival dimensions width and height""" def __init__(self, shock_period, shock_duration, shock_rate, N_cities, N_a, nc_rate, width, height): #canvas info self.width = width self.height = height #sim boilerplate self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.running = True self.num_nc = 0 #counts number of applicants self.num_azc = N_a #number of AZC in sim self.nc_rate = nc_rate #rate of inflow of newcomers self.num_cities = N_cities #number of cities in sim self.num_buildings = 3 self.num_activity_centers = 2 self.num_activities_per_center = 2 self.num_per_step = 10 self.num_activity_centers = 2 self.num_activities_per_center = 2 #initialize shock values self.shock_period = shock_period #how often does shock occur self.shock_duration = shock_duration #how long does shock last self._shock_duration = shock_duration #current position in shock self.shock_rate = shock_rate #amt of increase during shock self.shock = False #shock flag self.number_added = 1 #base rate of influx self.number_shocks = 4 self.shock_growth = 2 #dict of probabilities of first/second decision success rates by country self.specs = {} # list of multinomial probabilities for countries self.country_multinomial = [] # list of shock distributions for countries related to adding newcomers self.country_shock_dist = [] # list of countries self.country_list = [] with open("country-input.csv") as csvfile: reader = csv.DictReader(csvfile) for row in reader: decisionList = [] decisionList.append(float(row['DecisionA'])) decisionList.append(float(row['DecisionB'])) self.specs[row['Country']] = decisionList self.country_shock_dist.append(row['ShockDist']) self.country_list.append(row['Country']) self.country_multinomial.append(row['Multinomial']) self.country_count = np.zeros( len(self.country_list )) #keeps track of how many applicants from each country self.country_success = np.zeros(len(self.country_list)) self.current_country_index = -1 #records capacitiy of each AZC type self.datacollector = DataCollector(model_reporters={ 'Cap - Extended-AS': calc_extended_as, 'Cap - AS': calc_as }) #records success rates of each country of origin using current_country_index #which is manipulated in sr_country sr_functions = {} for i in range(0, len(self.country_list)): self.current_country_index = i sr_functions[self.country_list[ self.current_country_index]] = sr_country self.sr = DataCollector(model_reporters=sr_functions) self.capacity_dc = DataCollector(model_reporters={ 'Current Capacity': coa_occ, 'Projected Capacity': coa_proj }) #Ter apel ta_pos = (int(self.width / 2), int(self.height / 6 * 5)) ta_id = self.num_cities + 1 ter_apel = City(self.num_cities + 1, self, ta_pos) ta_coa = COA(ta_id, self, ter_apel) ta_coa.ta = True self.schedule.add(ta_coa) ta_ind = IND(ta_id, self, ter_apel) self.schedule.add(ta_ind) ta_azc = AZC(ta_id, self, 'edp', ta_pos, ta_coa) ta_azc.ta = True ta_coa.azcs.add(ta_azc) ta_coa.capacities[ta_azc] = ta_azc.occupancy self.schedule.add(ta_azc) self.grid.place_agent(ta_azc, ta_pos) self.ter_apel = ta_azc #add activities self.test_activity = Football(0, self, 5) self.schedule.add(self.test_activity) #generate cities for city in range(self.num_cities): space_per_city = int(self.width / self.num_cities) orientation_x = int( space_per_city / 2 + city * space_per_city + int(space_per_city / self.num_azc / 2)) #center point for city pos = (orientation_x, int(self.height / 2)) #placeholder position city_size = np.random.uniform(low=0, high=1) city_is_big = False if city_size > 0.70: city_is_big = True current_city = City(city, self, pos, city_is_big) #instantiates city #add COA current_coa = COA(city, self, current_city) current_city.coa = current_coa self.schedule.add(current_coa) self.grid.place_agent(current_coa, (pos[0], int(self.height / 3 * 2))) current_ind = IND(city, self, current_city) self.schedule.add(current_ind) current_coa.IND = current_ind current_ind.coa = current_coa #adds city to schedule n grid self.schedule.add(current_city) self.grid.place_agent(current_city, (current_city.pos)) #azc location essentials space_per_azc = int(space_per_city / self.num_azc) azc_starting_point = orientation_x - (.5 * space_per_city) num_activity_centers_added = 0 # Create AZCs for i in range(self.num_azc): ''' if i == 0: occupant_type = 'edp' # ter apel ''' if i < self.num_azc - 2: occupant_type = 'as' # standard AZC elif i == self.num_azc - 2: occupant_type = 'as_ext' # extended procedure AZC else: occupant_type = 'tr' # 'Housing' for those with #place evenly x = int(azc_starting_point + i * space_per_azc) y = int(self.height * .5) a = AZC(i, self, occupant_type, (x, y), current_coa) #instantiate self.schedule.add(a) #add in time self.grid.place_agent(a, (x, y)) #add in spaace current_city.buildings.add(a) if a.occupant_type != 'tr': current_coa.azcs.add(a) current_coa.capacities[a] = a.occupancy if a.occupant_type == 'tr': current_city.social_housing = a #add viz v = AZC_Viz(self, a) self.schedule.add(v) self.grid.place_agent(v, v.pos) #create civilian buildings y = int(self.height / 5) space_per_building = space_per_city / self.num_buildings row_size = 15 if city == 0: x = int(azc_starting_point + .5 * space_per_building) current = Hotel(self.num_buildings + 1, self, (x, y), 1000) current_city.buildings.add(current) current.city = current_city self.grid.place_agent(current, (x, y)) self.schedule.add(current) empty = Empty(self.num_buildings + 1, self, (int(x + space_per_building), y), 100) current_city.buildings.add(empty) empty.city = current_city self.grid.place_agent(empty, (int(x + space_per_building), y)) self.schedule.add(empty) for bdg in range(city * self.num_buildings): x = int(azc_starting_point + (bdg % 3) * space_per_building) if bdg == 0: current = Hotel(bdg, self, (x, y), 1000) current_city.buildings.add(current) current.city = current_city self.grid.place_agent(current, (x, y)) self.schedule.add(current) else: empty = Empty(bdg, self, (x, y - row_size * int(bdg / 3)), 100 * bdg) current_city.buildings.add(empty) empty.city = current_city self.grid.place_agent(empty, (x, y - row_size * int(bdg / 3))) self.schedule.add(empty) def house(self, newcomer): #find building for newcomers legal status eligible_buildings = [ x for x in self.schedule.agents if type(x) is AZC and x.occupant_type == newcomer.ls ] #take first one, in future, evaluate buildings on some criteria destination = eligible_buildings[0] house_loc = destination.pos #where is it if newcomer.ls is not 'edp': newcomer.loc.occupancy -= 1 #reduce occupance of prev building #add noise so agents don't overlap x = house_loc[0] + np.random.randint(-20, 20) y = house_loc[1] + np.random.randint(-20, 20) self.grid.move_agent(newcomer, (x, y)) #place destination.occupants.add(newcomer) #add agent to building roster newcomer.loc = destination #update agent location destination.occupancy += 1 #update occupancy def Remove(self, agent): agent.loc.occupancy -= 1 #reduce occupancy of building agent.loc.occupants.remove(agent) #remove from time n space self.schedule.remove(agent) self.grid.remove_agent(agent) def shock_distribution(self): #draws a random discrete number from multinomial distribution country = np.random.multinomial(1, self.country_shock_dist, size=1) # turns that distribution into a number country = np.where(country == 1)[1][0] # assigns that number to a country country_of_origin = self.country_list[country] return country_of_origin def country_distribution(self): #draws a random discrete number from multinomial distribution country = np.random.multinomial(1, self.country_multinomial, size=1) # turns that distribution into a number country = np.where(country == 1)[1][0] # updates country count self.country_count[country] += 1 # assigns that number to a country country_of_origin = self.country_list[country] return country_of_origin def addNewcomer(self, shock, country_of_origin): #increase count self.num_nc += 1 if not shock: country_of_origin = self.country_distribution() else: self.country_count[self.country_list.index(country_of_origin)] += 1 x = np.random.randint(0, 10, dtype='int') y = np.random.randint(0, 10, dtype='int') #define newcomer r = Newcomer(self.num_nc, self, country_of_origin, (x, y)) self.schedule.add(r) self.grid.place_agent(r, r.pos) #find coa coa = [x for x in self.schedule.agents if type(x) is COA][0] coa.intake(r) #place n ter apel coa.newcomers.add(r) #adds NC to coa's list of residents r.coa = coa #likewise for the newcomer def step(self): self.schedule.step() self.datacollector.collect(self) #collects occupancy data self.sr.collect(self) #collects success rate data self.capacity_dc.collect(self) if self.schedule.steps % self.shock_period == 0: self.shock = True self.shock_counter = 0 if self.shock: #if self._shock_duration > (self._shock_duration / 2): # self.number_added += self.shock_rate #else: # self.number_added -= self.shock_rate self.number_added += self.shock_rate for i in range(int(self.number_added)): shock_country = self.shock_distribution() self.addNewcomer( True, shock_country ) # currently in data file all shocks come from Syria self.shock_counter += 1 self._shock_duration -= 1 if self._shock_duration == 0: self.shock = False self._shock_duration = self.shock_duration self.number_added = 1 self.shock_counter = 0 self.shock_rate = self.shock_rate * self.shock_growth else: #adds newcomers to simuluation at a given rate if uniform(0, 1) < self.nc_rate: for i in range(self.num_per_step): self.addNewcomer(False, None)
def __init__(self, num_agents, width, height, kmob, repscaling, rate_inbound, age_mortality, sex_mortality, age_distribution, sex_distribution, prop_initial_infected, proportion_asymptomatic, proportion_severe, avg_incubation_time, avg_recovery_time, prob_contagion, proportion_isolated, day_start_isolation, days_isolation_lasts, after_isolation, prob_isolation_effective, social_distance, day_distancing_start, days_distancing_lasts, proportion_detected, day_testing_start, days_testing_lasts, new_agent_proportion, new_agent_start, new_agent_lasts, new_agent_age_mean, new_agent_prop_infected, day_tracing_start, days_tracing_lasts, stage_value_matrix, test_cost, alpha_private, alpha_public, proportion_beds_pop, dummy=0): self.running = True self.num_agents = num_agents self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.age_mortality = age_mortality self.sex_mortality = sex_mortality self.age_distribution = age_distribution self.sex_distribution = sex_distribution self.stage_value_dist = stage_value_matrix self.test_cost = test_cost self.stepno = 0 self.alpha_private = alpha_private self.alpha_public = alpha_public # Number of 15 minute dwelling times per day self.dwell_15_day = 96 # Average dwelling units self.avg_dwell = 4 # The average incubation period is 5 days, which can be changed self.avg_incubation = int(round(avg_incubation_time * self.dwell_15_day)) # Probability of contagion after exposure in the same cell # Presupposes a person centered on a 1.8 meter radius square. # We use a proxy value to account for social distancing. # Representativeness modifies the probability of contagion by the scaling factor if repscaling < 2: self.repscaling = 1 else: self.repscaling = (np.log(repscaling)/np.log(1.96587)) self.prob_contagion_base = prob_contagion / self.repscaling # Mobility constant for geographic rescaling self.kmob = kmob # Proportion of daily incoming infected people from other places self.rate_inbound = rate_inbound/self.dwell_15_day # Probability of contagion due to residual droplets: TODO self.prob_contagion_places = 0.001 # Probability of being asymptomatic, contagious # and only detectable by testing self.prob_asymptomatic = proportion_asymptomatic # Average recovery time self.avg_recovery = avg_recovery_time * self.dwell_15_day # Proportion of detection. We use the rate as reference and # activate testing at the rate and specified dates self.testing_rate = proportion_detected/(days_testing_lasts * self.dwell_15_day) self.testing_start = day_testing_start* self.dwell_15_day self.testing_end = self.testing_start + days_testing_lasts*self.dwell_15_day # We need an additional variable to activate and inactivate automatic contact tracing self.tracing_start = day_tracing_start* self.dwell_15_day self.tracing_end = self.tracing_start + days_tracing_lasts*self.dwell_15_day self.tracing_now = False # Same for isolation rate self.isolation_rate = proportion_isolated self.isolation_start = day_start_isolation*self.dwell_15_day self.isolation_end = self.isolation_start + days_isolation_lasts*self.dwell_15_day self.after_isolation = after_isolation self.prob_isolation_effective = prob_isolation_effective # Same for social distancing self.distancing = social_distance self.distancing_start = day_distancing_start*self.dwell_15_day self.distancing_end = self.distancing_start + days_distancing_lasts*self.dwell_15_day # Introduction of new agents after a specific time self.new_agent_num = int(new_agent_proportion * self.num_agents) self.new_agent_start = new_agent_start*self.dwell_15_day self.new_agent_end = self.new_agent_start + new_agent_lasts*self.dwell_15_day self.new_agent_age_mean = new_agent_age_mean self.new_agent_prop_infected = new_agent_prop_infected # Closing of various businesses # TODO: at the moment, we assume that closing businesses decreases the dwell time. # A more proper implementation would a) use a power law distribution for dwell times # and b) assign a background of dwell times first, modifying them upwards later # for all cells. # Alternatively, shutting restaurants corresponds to 15% of interactions in an active day, and bars to a 7% # of those interactions # Now, a neat python trick: generate the spacing of entries and then build a map times_list = list(np.linspace(self.new_agent_start, self.new_agent_end, self.new_agent_num, dtype=int)) self.new_agent_time_map = {x:times_list.count(x) for x in times_list} # Probability of severity self.prob_severe = proportion_severe # Number of beds where saturation limit occurs self.max_beds_available = self.num_agents * proportion_beds_pop # Create agents self.i = 0 for ag in self.age_distribution: for sg in self.sex_distribution: r = self.age_distribution[ag]*self.sex_distribution[sg] num_agents = int(round(self.num_agents*r)) mort = self.age_mortality[ag]*self.sex_mortality[sg] for k in range(num_agents): a = CovidAgent(self.i, ag, sg, mort, self) self.schedule.add(a) x = self.random.randrange(self.grid.width) y = self.random.randrange(self.grid.height) self.grid.place_agent(a, (x,y)) self.i = self.i + 1 self.datacollector = DataCollector( model_reporters = { "Step": compute_stepno, "N": compute_num_agents, "Susceptible": compute_susceptible, "Exposed": compute_incubating, "Asymptomatic": compute_asymptomatic, "SymptQuarantined": compute_symptdetected, "AsymptQuarantined": compute_asymptdetected, "Severe": compute_severe, "Recovered": compute_recovered, "Deceased": compute_deceased, "Isolated": compute_isolated, "CumulPrivValue": compute_cumul_private_value, "CumulPublValue": compute_cumul_public_value, "CumulTestCost": compute_cumul_testing_cost, "Rt": compute_eff_reprod_number, "Employed": compute_employed, "Unemployed": compute_unemployed, "Tested": compute_tested, "Traced": compute_traced } ) # Final step: infect an initial proportion of random agents num_init = int(self.num_agents * prop_initial_infected) for a in self.schedule.agents: if num_init < 0: break else: a.stage = Stage.EXPOSED num_init = num_init - 1
def __init__(self, floor_plan_file, human_count, collaboration_percentage, fire_probability, visualise_vision, random_spawn, save_plots): # Load floorplan # floorplan = np.genfromtxt(path.join("fire_evacuation/floorplans/", floor_plan_file)) with open(os.path.join("fire_evacuation/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix([line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.width = width self.height = height self.human_count = human_count self.collaboration_percentage = collaboration_percentage self.visualise_vision = visualise_vision self.fire_probability = fire_probability self.fire_started = False # Turns to true when a fire has started self.save_plots = save_plots # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to start a fire at a random furniture location self.furniture_list = [] # Used to easily see if a location is a FireExit or Door, since this needs to be done a lot self.fire_exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value is "W": floor_object = Wall((x, y), self) elif value is "E": floor_object = FireExit((x, y), self) self.fire_exit_list.append((x, y)) self.door_list.append((x, y)) # Add fire exits to doors as well, since, well, they are elif value is "F": floor_object = Furniture((x, y), self) self.furniture_list.append((x, y)) elif value is "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value is "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or FireExits, skip them if not self.grid.is_cell_empty(neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector( { "Alive": lambda m: self.count_human_status(m, Human.Status.ALIVE), "Dead": lambda m: self.count_human_status(m, Human.Status.DEAD), "Escaped": lambda m: self.count_human_status(m, Human.Status.ESCAPED), "Incapacitated": lambda m: self.count_human_mobility(m, Human.Mobility.INCAPACITATED), "Normal": lambda m: self.count_human_mobility(m, Human.Mobility.NORMAL), "Panic": lambda m: self.count_human_mobility(m, Human.Mobility.PANIC), "Verbal Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.VERBAL_SUPPORT), "Physical Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.PHYSICAL_SUPPORT), "Morale Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.MORALE_SUPPORT) } ) # Calculate how many agents will be collaborators number_collaborators = int(round(self.human_count * (self.collaboration_percentage / 100))) # Start placing human agents for i in range(0, self.human_count): if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) if pos: # Create a random human health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) if number_collaborators > 0: collaborates = True number_collaborators -= 1 else: collaborates = False # Vision statistics obtained from http://www.who.int/blindness/GLOBALDATAFINALforweb.pdf vision_distribution = [0.0058, 0.0365, 0.0424, 0.9153] vision = int(np.random.choice(np.arange(self.MIN_VISION, self.width + 1, (self.width / len(vision_distribution))), p=vision_distribution)) nervousness_distribution = [0.025, 0.025, 0.1, 0.1, 0.1, 0.3, 0.2, 0.1, 0.025, 0.025] # Distribution with slight higher weighting for above median nerovusness nervousness = int(np.random.choice(range(self.MIN_NERVOUSNESS, self.MAX_NERVOUSNESS + 1), p=nervousness_distribution)) # Random choice starting at 1 and up to and including 10 experience = random.randint(self.MIN_EXPERIENCE, self.MAX_EXPERIENCE) belief_distribution = [0.9, 0.1] # [Believes, Doesn't Believe] believes_alarm = np.random.choice([True, False], p=belief_distribution) human = Human(pos, health=health, speed=speed, vision=vision, collaborates=collaborates, nervousness=nervousness, experience=experience, believes_alarm=believes_alarm, model=self) self.grid.place_agent(human, pos) self.schedule.add(human) else: print("No tile empty for human placement!") self.running = True
def __init__(self, width, height, torus): MultiGrid.__init__(self, width, height, torus)
def __init__(self, number_of_cars, width, height, is_odd_even_policy_enabled, is_odd_date, policy_range_time): # Tick increment self.tick = 0 # Mean Travel Time self.mean_travel_time = 0.0 # Odd-Even Policy Enabled self.is_odd_even_policy_enabled = is_odd_even_policy_enabled # Set the day of the week self.is_odd_date = is_odd_date # Set up Spatial dimension self.grid = MultiGrid(width, height, True) # Set up Temporal dimension self.schedule = SimultaneousActivation(self) self.running = True self.policy_range_time = policy_range_time # Set up peak hours self.start_peak_hour_1 = PEAK_HOURS["START_PEAK_HOUR_1"] #7 self.end_peak_hour_1 = PEAK_HOURS["END_PEAK_HOUR_1"] #10 self.start_peak_hour_2 = PEAK_HOURS["START_PEAK_HOUR_2"] #4 self.end_peak_hour_2 = PEAK_HOURS["END_PEAK_HOUR_2"] #7 # Car distribution num_highly_active_cars = math.ceil(ACTIVITY_PROPORTION["HIGHLY_ACTIVE"] * number_of_cars) num_business_hours_cars = math.ceil(ACTIVITY_PROPORTION["BUSINESS_HOURS"] * number_of_cars) num_peak_hours_cars = number_of_cars - (num_highly_active_cars + num_business_hours_cars) # generate road self.map = MapGenerator() roadPosition = self.map.get_road_position() for i in range(len(roadPosition)): road = Road(i, roadPosition[i], self) self.grid.place_agent(road, roadPosition[i]) ## generate office officePosition = self.map.get_office_position() for i in range(len(officePosition)): office = Office(i, officePosition[i], self) self.grid.place_agent(office, officePosition[i]) # generate residence residencePosition = self.map.get_residence_position() for i in range(len(residencePosition)): residence = Residence(i, residencePosition[i], self) self.grid.place_agent(residence, residencePosition[i]) # generate entertainment entertainmentPosition = self.map.get_entertainment_position() for i in range(len(entertainmentPosition)): entertainment = Entertainment(i, entertainmentPosition[i], self) self.grid.place_agent(entertainment, entertainmentPosition[i]) # generate traffic light trafficLightPosition = self.map.get_traffic_light_position() for i in range(len(trafficLightPosition)): trafficLight = TrafficLight(i, trafficLightPosition[i], self, COLOR["dark_grey"]) self.grid.place_agent(trafficLight, trafficLightPosition[i]) # Get source and destination lists residence_list = self.map.get_residence_position() office = self.map.get_office_position() entertainment = self.map.get_entertainment_position() # Create destination list based on weekday/weekend proportion proportion_of_office_workers = 0.65 number_of_office_workers = math.ceil(proportion_of_office_workers * number_of_cars) number_of_shopper = number_of_cars - number_of_office_workers office_list = [] while len(office_list) <= number_of_office_workers: office_list.append(office[self.random.randint(0, len(office) -1)]) entertainment_list = [] while len(entertainment_list) <= number_of_shopper: entertainment_list.append(entertainment[self.random.randint(0, len(entertainment) - 1)]) office_entertainment_list = office_list + entertainment_list random.shuffle(residence_list) layout = self.map.get_layout() for i in range(number_of_cars): # determine departure and return time based on activity level if i <= num_highly_active_cars: activity_level = "HIGHLY_ACTIVE" departure_time = 0 return_time = float("inf") elif i <= num_business_hours_cars: activity_level = "BUSINESS_HOURS" departure_time = self.start_peak_hour_1 return_time = float("inf") else: activity_level = "PEAK_HOURS" departure_time = self.random.randint(self.start_peak_hour_1,self.end_peak_hour_1) return_time = self.random.randint(self.start_peak_hour_2,self.end_peak_hour_2) plate_number_oddity = self.random.randint(0, 1) source_x = residence_list[i][0] source_y = residence_list[i][1] destination_x = office_entertainment_list[i][0] destination_y = office_entertainment_list[i][1] state_fringes = self.map.get_fringes(source_x, source_y) shortest_distance = float("inf") car_direction = state_fringes[0][1] for state_fringe in state_fringes: current_direction = state_fringe[1] # "^" "v" ">" "<" if current_direction in DIRECTION: temp_x = state_fringe[0][0] + DIRECTION[current_direction][0] temp_y = state_fringe[0][1] + DIRECTION[current_direction][1] newDist = get_euclidean_distance((temp_x, temp_y), (destination_x, destination_y)) if newDist < shortest_distance: shortest_distance = newDist car_direction = current_direction # all cars are initialised as IDLE car_state = "IDLE" car = Car(i, plate_number_oddity, (source_x,source_y), (destination_x,destination_y), car_direction, car_state, departure_time, return_time, activity_level, self) self.grid.place_agent(car, (source_x,source_y)) self.schedule.add(car) # Data Collection self.datacollector = DataCollector({ "Idle": number_idle_cars, "Move": number_move_cars, "Finished": number_finished_cars, "SimulationMinutes": simulation_minutes, "ToOffice": number_office, "ToResidence": number_residence, "MeanTravelTime": mean_travel_time, "StdTravelTime": std_travel_time }) self.datacollector.collect(self)
class MarketModel(Model): def __init__(self, buff, plot_buff, max_agents_number, market, checkout_slider, width=50, height=50, steps=3000): self.steps = steps self.plot_buff = plot_buff self.running = True self.market = market self.checkout_slider = checkout_slider self.num_agents = max_agents_number self.schedule = RandomActivation(self) self.grid = MultiGrid(width, height, True) self.grid_mutex = Lock() self.agents_number = 1 self.regal_agents = [] self.checkout_agents = [] self.opened_checkouts = [] self.closed_checkouts = [] self.space_graph = np.zeros((width, height)) self.place_checkouts() self.place_regals() self.thread_pool = ThreadPool(20) self.customer_list = buff self.total_income = 0.0 self.agent_counts = [[0 for x in range(self.grid.width)] for y in range(self.grid.height)] self.plot_buff.append(self.agent_counts) self.plot_buff.append(self.grid.width) self.plot_buff.append(self.grid.height) self.income_data_collector = DataCollector( model_reporters={"total_income": get_income}) self.queue_length_data_collector = DataCollector( model_reporters={ "average_queue_length": compute_average_queue_size }) self.open_checkouts() def add_agent(self): i = random.randint(0, 1) if i == 0: a = CommonCustomer(self.agents_number, self, self.market.articles) else: a = LazyCustomer(self.agents_number, self, self.market.articles) # a = CommonCustomer(self.agents_number, self, self.market.articles) self.agents_number += 1 self.schedule.add(a) self.grid.place_agent(a, (a.x, a.y)) self.customer_list.append(a) def place_checkouts(self): for checkout_location in self.market.cashRegisters: checkout_agent = Checkout(self.agents_number, self, checkout_location) self.agents_number += 1 self.grid.place_agent(checkout_agent, checkout_location) self.checkout_agents.append(checkout_agent) self.space_graph[checkout_location[0], checkout_location[1]] = 1 self.closed_checkouts = self.checkout_agents def place_regals(self): for regal in self.market.regals: self.place_regal(regal) def place_regal(self, regal): for shelf in regal.shelf_list: self.place_shelf(shelf) def place_shelf(self, shelf): shelf_agent = ShelfAgent(self.agents_number, self, shelf) pos = shelf_agent.get_location() self.agents_number += 1 self.grid.place_agent(shelf_agent, pos) self.regal_agents.append(shelf_agent) self.space_graph[pos[0], pos[1]] = 1 def open_checkouts(self): for i in range(0, len(self.checkout_agents), len(self.checkout_agents) // self.checkout_slider): checkout = self.closed_checkouts.pop( random.randint(0, len(self.closed_checkouts) - 1)) checkout.open() self.opened_checkouts.append(checkout) self.schedule.add(checkout) def open_random_checkout(self): if len(self.closed_checkouts) != 0: checkout = self.closed_checkouts.pop( random.randint(0, len(self.closed_checkouts) - 1)) checkout.open() self.opened_checkouts.append(checkout) self.schedule.add(checkout) def close_random_checkout(self): if len(self.opened_checkouts) > 1: checkout = self.opened_checkouts.pop( random.randint(0, len(self.opened_checkouts) - 1)) checkout.close() self.closed_checkouts.append(checkout) # self.schedule.add(checkout) def find_nearest_checkouts(self, location, n): new_list = self.opened_checkouts.copy() ordered_list = sorted(new_list, key=(lambda x: ((x.location[0] - location[0])**2) + ( (x.location[1] - location[1])**2))) return ordered_list[0:] def generate_random_starting_pos(self): pos_list = [(self.grid.width // 2 + 1, 0), (self.grid.width - 1, 1), (self.grid.width - 1, self.grid.height - 2)] i = random.randint(0, len(pos_list) - 1) pos = pos_list[i] if i == 0: pos = (pos_list[0][0] + random.randint(-2, 2), pos_list[0][1]) return pos def step(self): print(self.checkout_slider) self.income_data_collector.collect(self) self.queue_length_data_collector.collect(self) if compute_average_queue_size(self) > 3: self.open_random_checkout() if compute_average_queue_size(self) < 3: self.close_random_checkout() sigma = 1 cycle_steps = 1500 n = self.schedule.steps // cycle_steps + 1 gauss = gaussian( self.schedule.steps * (6 * sigma / cycle_steps) - 3 * n * sigma, 0, sigma) * self.num_agents print(gauss) while len(self.schedule.agents) - len( self.checkout_agents) < np.ceil(gauss): self.add_agent() self.schedule.step() def move_agent(self, agent, new_pos): # self.grid_mutex.acquire() self.agent_counts[new_pos[0]][new_pos[1]] += 1 self.plot_buff[0] = self.agent_counts self.grid.move_agent(agent, new_pos) # self.grid_mutex.release() def remove_agent(self, agent): # self.grid_mutex.acquire() self.grid.remove_agent(agent) self.schedule.remove(agent) if type(agent) is CommonCustomer: self.customer_list.remove(agent) # self.grid_mutex.release() def get_customers(self): return self.customer_list
class trafficSimulation(Model): def __init__(self, spawn_speed): self.spawn_speed = spawn_speed self.counter = 0 self.traffic_lights_schedule = TrafficScheduler(self) self.cars_schedule = SimultaneousActivation(self) self.grid = MultiGrid(10, 10, False) self.id = 0 self.spawnpoints = [(9, 5), (0, 4), (6, 0), (5, 9)] self.kill_agents = [] self.datacollector = DataCollector(model_reporters={"Grid": get_grid}) traffic_light_coords = [(7, 5), (4, 4), (6, 3), (5, 6)] for coord in traffic_light_coords: light = trafficLight(self.id, coord, self) self.id = self.id + 1 self.grid.place_agent(light, coord) self.traffic_lights_schedule.add(light) self.datacollector.collect(self) def get_data(self): traffic_lights = [{ "coords": { "x": agent.coords[0], "y": agent.coords[1] }, "state": stateToString(agent.state) } for agent in get_other_lights(-1, self)] cars = [{ "direction": { "x": agent.direction[0], "y": agent.direction[1] }, "coords": { "x": agent.coords[0], "y": agent.coords[1] } } for agent in self.cars_schedule.agents] return traffic_lights, cars def step(self): self.traffic_lights_schedule.step() self.cars_schedule.step() if self.counter == self.spawn_speed - 1 and random.random() > 0.5: orientation, coords = random.choice( [x for x in zip(direction.lst, self.spawnpoints)]) anyCar = any([ isinstance(agent, carAgent) for agent in self.grid.iter_neighbors(coords, False, True, 0) ]) if not anyCar: car = carAgent(self.id, coords, orientation, self) self.grid.place_agent(car, coords) self.cars_schedule.add(car) self.id = self.id + 1 self.counter = (self.counter + 1) % self.spawn_speed for x in self.kill_agents: self.grid.remove_agent(x) self.cars_schedule.remove(x) self.kill_agents.remove(x)
def __init__(self, N_attr, N_cust, width, height, strategy, theme, max_time, weight, adaptive): self.theme = theme self.max_time = max_time self.N_attr = N_attr self.penalty_per = PENALTY_PERCENTAGE self.weight = weight self.adaptive = adaptive self.strategies = STRATEGIES self.x_list, self.y_list, self.positions = xlist, ylist, positions self.x_list, self.y_list, self.positions = get_attraction_coordinates(WIDTH, HEIGHT, self.N_attr, theme) self.happinesses = [] self.starting_positions = [[int((WIDTH/2)-1), 0], [int(WIDTH/2), 0], [int((WIDTH/2)+1), 0]] self.path_coordinates = get_coordinates(WIDTH, HEIGHT, NUM_OBSTACLES, self.N_attr, theme) self.N_attr = N_attr # num of attraction agents self.N_cust = N_cust # num of customer agents self.width = width self.height = height self.total_steps = 0 self.cust_ids = N_cust self.strategy = strategy self.grid = MultiGrid(width, height, torus=False) self.schedule = BaseScheduler(self) self.schedule_Attraction = BaseScheduler(self) self.schedule_Customer = BaseScheduler(self) self.totalTOTAL = 0 self.attractions = self.make_attractions() self.attraction_history = self.make_attr_hist() self.running = True self.data = [] self.data_customers = [] self.park_score = [] self.data_dict = {} self.hist_random_strat = [] self.hist_close_strat = [] self.all_rides_list = [] self.strategy_composition = self.make_strategy_composition() self.memory = 5 self.customer_score = [] self.customers = self.add_customers(self.N_cust) self.only_random = False for attraction in self.get_attractions(): self.data_dict[attraction.unique_id] = ({ "id": attraction.unique_id, "length": attraction.attraction_duration, "waiting_list": []}) if len(self.strategies) == 6: self.datacollector = DataCollector( {"Random": lambda m: self.strategy_counter(self.strategies[0]), "0.00": lambda m: self.strategy_counter(self.strategies[1]), "0.25": lambda m: self.strategy_counter(self.strategies[2]), "0.50": lambda m: self.strategy_counter(self.strategies[3]), "0.75": lambda m: self.strategy_counter(self.strategies[4]), "1.00": lambda m: self.strategy_counter(self.strategies[5]), }) else: self.datacollector = DataCollector( {"0.00": lambda m: self.strategy_counter(self.strategies[0]), "0.25": lambda m: self.strategy_counter(self.strategies[1]), "0.50": lambda m: self.strategy_counter(self.strategies[2]), "0.75": lambda m: self.strategy_counter(self.strategies[3]), "1.00": lambda m: self.strategy_counter(self.strategies[4]), }) self.datacollector2 = DataCollector( {"score": lambda m: self.make_score()}) self.total_waited_time = 0 self.monitor = Monitor(self.max_time, self.N_attr, self.positions)
class AntModel(Model): def __init__(self, num_ln, num_fj, num_mk_col, num_ft_col, width, height): """ :param num_ln: Number of L. Niger agents :param num_fj: Number of F. Japonica agents :param num_mk_col: Number of M. Kuricola colonies :param num_ft_col: Number of F. Tropicalis colonies :param width: Width of the model grid :param height: Height of the model grid """ super().__init__() self.num_ln = num_ln self.num_fj = num_fj self.num_mk_col = num_mk_col self.num_ft_col = num_ft_col self.grid = MultiGrid(width, height, True) self.schedule = RandomActivation(self) self.running = True for h in range(self.num_fj): ant = FJaponica(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) for j in range(self.num_mk_col): colony = MKuricolaColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for k in range(self.num_ft_col): colony = FTropicalisColony(uuid4(), self) self.schedule.add(colony) self.grid.place_agent(colony, self.grid.find_empty()) for i in range(self.num_ln): ant = LNiger(uuid4(), self) self.schedule.add(ant) self.grid.place_agent(ant, self.grid.find_empty()) ant._init_post_place() self.data_collector = DataCollector( model_reporters={}, agent_reporters={"states": ant_state_collector}) self.weights_dict = json.load(open("newout.json", "r")) def drop_pheromone(self, location): """ Drops a LNPheromone object at the given location if one does not already exist. If one does already exist, 1 is added to the existing object's 'tracks' field. :param location: An (x, y) tuple detailing the location to drop the pheromone. :return: None """ if not self.is_pheromone_in_cell(location): self.grid.place_agent(LNPheromone(uuid4(), self), location) else: self.get_pheromone_in_cell(location).tracks += 1 def is_pheromone_in_cell(self, location): """ Determines if a pheromone already exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == LNPheromone for x in self.grid.get_cell_list_contents(location) ] def is_ant_in_cell(self, location): """ Determines whether an ant exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ isinstance(x, Ant) for x in self.grid.get_cell_list_contents(location) ] def is_colony_in_cell(self, location): """ Determines whether an aphid colony exists in a given cell. :param location: The location to check. :return: boolean """ return True in [ type(x) == MKuricolaColony or type(x) == FTropicalisColony for x in self.grid.get_cell_list_contents(location) ] def get_pheromone_in_cell(self, location): """ Returns a LNPheromone object from a cell. ASsumes the cell has already been proven to have a pheromone object in it. :param location: The cell location to check. :return: The LNPheromone object within the cell. """ in_cell_pheromone = None for i in self.grid.get_cell_list_contents(location): if type(i) == LNPheromone: in_cell_pheromone = i return in_cell_pheromone def get_closest_agent_of_type(self, agent, agent_type): """ Gets the closest agent (besides self) of type agent_type. Returns -1 if it cannot find one. :param agent: The agent to find the closest agent_type to. :param agent_type: The type of the agent we are looking for. :return: """ for radius in range(1, self.grid.width): for neighbor in self.grid.get_neighbors(pos=agent.pos, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): return neighbor return -1 def get_closest_colony(self, agent): """ Gets the closest colony to an agent. If an agent is of type colony, it returns itself. :param agent: The agent to find the closest colony to. :return: The closest colony or -1 if not found. """ return self.get_closest_agent_of_type(agent, Colony) @staticmethod def distance_between_cells(location_a, location_b): """ Calculates the distance between two cells on the grid. :param location_a: First cell location. :param location_b: Second cell location. :return: """ return np.sqrt((location_a[0] - location_b[0])**2 + (location_a[1] - location_a[1])**2) def get_nearest_cell_to_goal(self, goal_cell, possible_cells): """ Returns the cell from a list of possible cells which is closest to the end location. :param goal_cell: The goal cell of the agent :param possible_cells: Candidate cells. :return: The location of the closest cell to the goal cell. """ closest_neighbor_index = -1 closest_neighbor_distance = np.inf for i in range(0, len(possible_cells)): dist = self.distance_between_cells(possible_cells[i], goal_cell) if dist < closest_neighbor_distance: closest_neighbor_index = i closest_neighbor_distance = dist return possible_cells[closest_neighbor_index] def get_number_of_agents_in_radius(self, location, radius, agent_type): """ Returns the number of agents of type agent_type within a radius (not including center) of location. :param location: Location to search around. :param radius: Radius to search. :param agent_type: Type of agent to search for. :return: int """ total_agents = 0 for neighbor in self.grid.get_neighbors(pos=location, moore=True, include_center=False, radius=radius): if isinstance(neighbor, agent_type): total_agents += 1 return total_agents def get_all_of_agent_type(self, agent_type): """ Returns all instances of agents of type agent_type in the Grid. :param agent_type: The type of agent to find. :return: A list of agent objects. """ return [ x for x in self.grid.get_neighbors(pos=(0, 0), moore=True, include_center=True, radius=self.grid.width) if isinstance(x, agent_type) ] def step(self): """ A method called every step that occurs :return: None """ self.data_collector.collect(self) self.schedule.step()
def __init__(self, height = 50, width = 50, initial_population =200, \ Moore = False, torus = True, regrow = 1, seed = None): ''' Args: height - y axis of grid_size width - x axis of grid size initial_population - number of agents starting moore - type of neighborhood torus - whether or no world wraps regrow - amout each resource grows bas each step process - Number of additonal proces by agents 0 = Movement/Survive; 1 = +trade, 2 = + Initial Parameters: Multigrid ActivationbyBreed (see schedule) Num_Agents counter to account for each agent number timekeeper - dictionary to keep track of time for each section start_time - create initial time datacollector to collect agent data of model ''' self.step_num = 0 self.height = height self.width = width self.initial_population = initial_population self.num_agents = 0 #Mesa Agent Scheduler #self.schedule = schedule.RandomActivationByBreed(self) self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.regrow = regrow self.running = True self.price_record = defaultdict(list) ''' Recorders Start datacollector Start time recorder ''' self.start_time = time.time() self.datacollector = DataCollector(\ model_reporters = {"MetaAgent": recorder.survivors}, \ tables ={"Health":["Agent", "Step", "Sugar_Level", \ "Spice_Level"], \ "Time":["Time Per Step"]}) ''' Creates the landscape: Fours mounds 2 sugar, 2 spice located- 1 in each quadrant imports landscape module to account for various landscape sizes ''' self.resource_dict = {} landscape = Landscape.create_landscape(height, width) #places resources from landscape on grid for k,v in landscape.items(): resource = R.resource(k, self, v, self.regrow) self.grid.place_agent(resource, (resource.pos[0], resource.pos[1])) #POINT self.schedule.add(resource) #fills in empty grids with null value resource agent #Deviation from GrAS -- in empty cells has random resource from 0 to 4 for a,x,y in self.grid.coord_iter(): if a == set(): resource = R.resource((x,y), self, \ (self.random.randrange(0,2), \ self.random.randrange(0,2)),self.regrow) self.grid.place_agent(resource, (resource.pos[0], resource.pos[1])) #POINT self.schedule.add(resource) ''' Creates the agents: ''' pos_array = list(self.schedule.agents_by_breed[R.resource].keys()) self.random.shuffle(pos_array) vision_array = np.random.randint(1,6,self.initial_population) spice_array = np.random.randint(1,6,self.initial_population) sugar_array = np.random.randint(1,6,self.initial_population) for n in range(self.initial_population): #x = 0 #y = 0 #print ("position: ", (n, x,y)) #GrAS p. 108 sugar = self.random.randrange(25,50) spice = self.random.randrange(25,50) #GrAS p.108 sug_bolism = sugar_array[n] spice_bolism = spice_array[n] #GrAS p. 108 vision = vision_array[n] neighbors = Moore a = N.NetAgent(n, pos_array[n], self, \ {"sug_bolism": sug_bolism, \ "spice_bolism": spice_bolism}, \ {1 : sugar, 2: spice}, {"vision": vision}, \ neighbors) #POINT self.schedule.add(a) self.grid.place_agent(a,pos_array[n])
class FactoryModel(Model): """A model with some number of agents.""" def __init__(self, N, num_task, num_empty, num_full): global task_over task_over = False # 1 means walls self.fmap = [[0,0,0,1,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,1,0,0,0]] self.height = self.width = len(self.fmap) self.grid = MultiGrid(self.width, self.height, False) self.running = True self.schedule = RandomActivation(self) self.ttl = 1 empty = [] full = [] # Create boxes while (len(empty)+len(full)) != (num_empty+num_full): x = random.randrange(self.width) y = random.randrange(self.height) if self.fmap[x][y] == 0: if len(empty)<num_empty and ((x,y) not in empty): empty.append((x,y)) elif (x,y) not in full and ((x,y) not in empty): full.append((x,y)) # [[empty boxes], [full boxes]] self.boxes = [empty,full] # Create tasks tasks = [] while len(tasks) < N*num_task: for i in range(num_task): pos = random.choice(full) if pos not in tasks: tasks.append(pos) print("tasks are ",tasks) # Create Wall agents self.createWall() # Create box agents self.createBox() # Create Robot agents self.createRobot(N, num_task, tasks) def createWall(self): type = 1 for i in range(self.height): for j in range(self.width): if (self.fmap[i][j] == 1): a = WallAgent(self.ttl, self, type) self.grid.place_agent(a,(i,j)) self.schedule.add(a) self.ttl += 1 def createBox(self): type = 2 # empty box for pos in self.boxes[0]: a = BoxAgent(self.ttl, self, type) self.grid.place_agent(a,pos) self.schedule.add(a) self.ttl += 1 type = 3 # full box for pos in self.boxes[1]: a = BoxAgent(self.ttl, self, type) self.grid.place_agent(a,pos) self.schedule.add(a) self.ttl += 1 def createRobot(self, num_agents, num_task, tasks): type = 0 agents = [] while len(agents) < num_agents: # add an agent into a random cell x = random.randrange(self.grid.width) y = random.randrange(self.grid.height) if (self.fmap[x][y] == 0 and (x,y) not in self.boxes[1] and (x,y) not in self.boxes[0] and (x,y) not in agents): a = RobotAgent(self.ttl, self, type, tasks[:num_task], self.fmap, self.boxes) self.schedule.add(a) self.ttl += 1 tasks = tasks[num_task:] self.grid.place_agent(a,(x,y)) agents.append((x,y)) print("start from ", agents) # self.grid.place_agent(a,(9,0)) def step(self): '''Advance the model by one step.''' global task_over if not task_over: self.schedule.step() else: print("task over") self.running = False
class Trade(Model): verbose = False # Print-monitoring os.chdir(os.path.dirname(__file__)) fpath = os.getcwd() + '/parameters.csv' reader = csv.reader(open(fpath, 'r')) d = dict() for key, value in reader: d[key] = float(value) height = int(d['height']) width = int(d['width']) ini_buyers = int(d['ini_buyers']) ini_sellers = int(d['ini_sellers']) def __init__(self, height=height, width=width, ini_buyers=ini_buyers, ini_sellers=ini_sellers): '''Parameters''' reader = csv.reader(open(self.fpath, 'r')) d = dict() for key, value in reader: d[key] = float(value) self.height = int(d['height']) self.width = int(d['width']) self.ini_buyers = int(d['ini_buyers']) self.ini_sellers = int(d['ini_sellers']) self.ini_cash = d['ini_cash'] self.num_w = int(d['num_w']) self.trust_w = d['trust_w'] self.costs = d['costs'] * ini_buyers self.mktresearch = d['mktresearch'] self.priceRange = d['priceRange'] self.csa = d['csa'] self.csa_length = int(d['csa_length']) self.network = d['network'] self.lb = d['lb'] # Lower bound self.ub = d['ub'] # Upper bound (in effect, unbounded) self.up = d['up'] # Up rate self.down = d['down'] # Down rate ''' Entry mode 0: No entry 1: Full market research 2: Whenever Avg cash balance > entryThreshhold with a random position 3: Whenever Max cash balance > entryThreshhold enter nearby that position ''' self.entry = int(d['entry']) self.entryFrequency = int(d['entryFrequency']) self.entryThreshhold = d['entryThreshhold'] * self.ini_cash self.entryRadius = int(d['entryRadius']) # Area within high earner that a new seller will plop down '''Debugging''' self.sellerDebug = d['sellerDebug'] self.buyerDebug = d['buyerDebug'] self.networkDebug = d['networkDebug'] self.utilweightDebug = d['utilweightDebug'] self.entryDebug = d['entryDebug'] self.schedule = RandomActivationByType(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector( {"Sellers": lambda m: m.schedule.get_type_count(Seller), "Buyers": lambda m: m.schedule.get_type_count(Buyer)}) '''Initialization''' self.cnt = 0 # Period counter self.buyers = {} # Dictionary of buyer instances self.sellers = {} # Dictionary of seller instances self.sid_alive = [] self.pi = [0] * (height * width) # Profitability prices = {} for i in range(ini_sellers): prices[i] = self.priceRange * np.random.rand() + 1 min_price = min(prices.values()) for i in range(self.num_w): prices[i] = min_price * 0.9 self.prices = prices e = {} # Embeddedness for i in range(ini_sellers): e[i] = 0.8*np.random.rand() + 0.2 # 0.2 - 1.0 for i in range(self.num_w): e[i] = 0 self.e = e '''Create buyers''' for i in range(self.ini_buyers): # It seems coincidence in the same cell is allowed x = np.random.randint(self.width) y = np.random.randint(self.height) α = d['alpha'] trust = {} β = d['beta']*np.random.rand() for j in range(ini_sellers): trust[j] = np.random.rand() for j in range(self.num_w): trust[j] = self.trust_w γ = d['gamma'] ''' Network ties ties[j]=0 means 'no connection with bid=j buyer' ties[own bid] = 0 or 1 means nothing. ''' ties = dict(zip(range(ini_buyers),[0]*ini_buyers)) buyer = Buyer(i, self.grid, (x, y), True, α, trust, β, γ, ties) self.buyers[i] = buyer # Dictionary key is an integer self.grid.place_agent(buyer, (x, y)) self.schedule.add(buyer) '''Create sellers''' for i in range(self.ini_sellers): x = np.random.randint(self.width) y = np.random.randint(self.height) cash = self.ini_cash costs = self.costs price = self.prices[i] w = False if i < self.num_w: w = True e = self.e[i] seller = Seller(i, self.grid, (x, y), True, cash, costs, price, w, e) self.sellers[i] = seller self.grid.place_agent(seller, (x, y)) self.schedule.add(seller) self.running = True def step(self): '''Initialization''' self.cnt += 1 self.sid_alive = [] # Excluding Wal-Mart for sid, seller in self.sellers.items(): if seller.csa == False: '''Adjacent sales''' seller.sales = 0 '''Customer list''' seller.customers[self.cnt] = [] else: seller.customers[self.cnt] = seller.customers[self.cnt - 1] '''A list of living sellers (excluding Wal-Mart)''' if (seller.alive and seller.w == False): self.sid_alive.append(sid) # For entry if self.entry == 1: # Initialize the profitability vector self.pi = [0] * (self.height * self.width) elif self.entry == 2: # Calculate the average cash balance (scalar) total_cash = 0 cnt_seller = 0 total_cash = sum([self.sellers[sid].cash for sid in self.sid_alive]) self.avg_cash = total_cash / len(self.sid_alive) elif self.entry == 3: # Calculate the max cash balance (scalar) temp_sids = self.sid_alive cash_bals = [self.sellers[sid].cash for sid in temp_sids] new_sellers = True # Loops over maximal sellers until it finds one with no new firms nearby while(new_sellers): max_cash = max(cash_bals) if(max_cash < self.entryThreshhold): break max_cash_ind = cash_bals.index(max_cash) max_sid = temp_sids[max_cash_ind] max_x = self.sellers[max_sid].pos[0] max_y = self.sellers[max_sid].pos[1] if(self.entryDebug): print("Max Cash, sid:", max_sid, ", Cell:(" + str(max_x) + ", " + str(max_y) + ")") print("-Neighbor Ages:", end=" ") new_sellers = False # Check the age of all firms nearby the max cash balance firm # (wants to avoid new firms) for neighbor in self.grid.get_neighbors((max_x, max_y),True,True,self.entryRadius): if(isinstance(neighbor, Seller) and self.entryDebug): print(str(neighbor.age), end=" ") if(isinstance(neighbor, Seller) and neighbor.age < 52): new_sellers = True if(new_sellers): if(self.entryDebug): print("\n-New Firm Exists Near sid: ", max_sid, ", Cell:(" + str(max_x) + ", " + str(max_y) + ")") del temp_sids[max_cash_ind] del cash_bals[max_cash_ind] ''' Entry Entry=1 Determine the most profitable position and whether to enter Threshold: the fixed costs Entry=2 Enter whenever Avg cash balance > entryThreshhold Entry=3 Checks that no new firms are near the max balance seller Enters within entryRadius units of the seller with max cash balance ''' entry_on = False if (self.entry == 1 and self.mktresearch): opt = max(self.pi) opt_pos = self.pi.index(opt) if opt >= self.costs: x = opt_pos // self.width y = opt_pos % self.width entry_on = True elif (self.entry == 2 and self.avg_cash > self.entryThreshhold): x = np.random.randint(self.width) y = np.random.randint(self.height) entry_on = True elif (self.entry == 3 and max_cash > self.entryThreshhold and not new_sellers): x = max_x + np.random.randint(-self.entryRadius,self.entryRadius) y = max_y + np.random.randint(-self.entryRadius,self.entryRadius) x = x % self.width y = y % self.height entry_on = True if entry_on: cash = self.ini_cash costs = self.costs w = False price = np.mean([self.sellers[sid].price for sid in self.sid_alive]) # e = np.random.choice([self.sellers[sid].e for sid in self.sid_alive]) e = np.random.rand() sid = max([seller.sid for seller in self.sellers.values()]) + 1 self.sid_alive.append(sid) seller = Seller(sid, self.grid, (x, y), True, cash, costs, price, w, e) self.sellers[sid] = seller self.sellers[sid].customers[self.cnt] = [] for buyer in self.buyers.values(): buyer.trust[sid] = self.lb self.grid.place_agent(seller, (x, y)) self.schedule.add(seller) self.prices[sid] = price if (self.entry >= 1 and self.entryDebug): entry_NewFirm(sid, x, y) self.mktresearch = False '''Move''' self.schedule.step() self.datacollector.collect(self) if self.verbose: print([self.schedule.time, self.schedule.get_type_count(Seller), self.schedule.get_type_count(Buyer)]) '''Network''' if self.network: network.formation(self.cnt, self.buyers, self.sellers) def run_model(self, step_count): for _ in range(step_count): self.step() ''' Debugging ''' '''Display trust levels''' if self.buyerDebug: debug.buyers(self.buyers) '''Network''' if self.networkDebug: debug.network(self.buyers) '''Display seller information''' if self.sellerDebug: debug.sellers(self.cnt, self.num_w, self.sellers, self.buyers) '''End of the run''' print("\n************\nPut a summary here.\n************")
class Intersection(Model): """ Here the model is initialized. The Generatedmap.txt is read in order to locate traffic lights and car spawns. Cars and traffic lights are spawned here. """ def __init__(self, spawnrate, tactic, offset, cycletime): # Variable parameters self.tactic = tactic # [ Offset, Proportional, Lookahead, GreenWave] self.spawnrate = spawnrate self.offset = offset self.slowmotionrate = 0.2 self.cycletime = cycletime # Value initializations self.emission = [0, 0, 0] # emission per step self.traveltime = [] self.averagetraveltime = 0 self.carID = 0 self.averageemission = [] # Reading roadmap and emission values self.emissionvalues = reademissionvalues() [ self.roadmap, self.spawns, self.lights, self.height, self.cellsperlane, self.intersections, self.streetlength, self.gridsize, ] = readroadmap() # Model and visualization parameters self.schedule = RandomActivation(self) self.width = self.height self.grid = MultiGrid(self.width, self.height, True) self.running = True # Initializing matrix which shows what cars in front of traffic lights go to what over traffic lights. self.tlightmatrix = np.empty((len(self.lights), len(self.lights))) self.tlightmatrix[:] = np.nan self.trafficlightlist = [] self.lightcombinations = [ ["SR", "SD", "SL", "WR"], ["ER", "ED", "EL", "SR"], ["NR", "ND", "NL", "ER"], ["WR", "WD", "WL", "NR"], ] # Data collection self.datacollector = DataCollector( model_reporters={ "tactic": "tactic", "Spawnrate": "spawnrate", "Offset": "offset", "Cycletime": "cycletime", "AverageTraveltime": "averagetraveltime", "Totalcars": lambda m: self.numberofcars(), "CO2": lambda m: self.getco2(), "NOx": lambda m: self.getnox(), "PM10": lambda m: self.getpm(), "AverageCO2": lambda m: self.getaverageco2(), "AverageNOx": lambda m: self.getaveragenox(), "AveragePM": lambda m: self.getaveragepm(), }, ) # Needed for green wave tactic self.mostcars = [] self.goesto = [] self.firstgreenintersection = -1 self.secondgreenintersection = -1 self.firstcombination = None self.secondcombination = None self.firstcycledone = 0 # Needed for lookahead tactic self.mostexpectedcars = [0, 0, 0] # cars,intersection,combination # results in list of lists with intersectionnumbers in the right place, e.g.: [[0, 1],[2,3]] # Needed for the offset tactic to know which lights to offset self.intersectionmatrix = [] lastnumber = 0 for i in range(int(math.sqrt(self.intersections))): tempmaptrix = [] for j in range(int(math.sqrt(self.intersections))): tempmaptrix.append(j + lastnumber) lastnumber = tempmaptrix[-1] + 1 self.intersectionmatrix.append(tempmaptrix) self.intersectionmatrix = np.array(self.intersectionmatrix) # Initialize information dictionary (which lights are suppesed to be green and how long they have been green for self.trafficlightinfo = {} for i in range(self.intersections): self.trafficlightinfo.update( {f"intersection{i}": {"Trafficlightinfo": {}, "Timeinfo": {}}} ) # Initializes traffic lights for i, light in enumerate(self.lights): self.trafficlightinfo[f"intersection{light[1][3]}"]["Trafficlightinfo"][ f"{light[1][1:3]}" ] = i self.trafficlightinfo[f"intersection{light[1][3]}"]["Timeinfo"].update( { "Currentgreen": -1, "Currenttimegreen": 0, "Maxtimegreen": 0, "Allred": 1, } ) intersectionnumber = int(light[1][3]) intersectiony = np.where(self.intersectionmatrix == intersectionnumber)[0] intersectionx = np.where(self.intersectionmatrix == intersectionnumber)[1] direction = light[1][1] lane = light[1][2] location = light[0] xlocation = int(location[0]) ylocation = self.height - 1 - int(location[1]) trafficlight = TrafficLightAgent( f"{xlocation},{ylocation},{light[1][1:3]}", self, "red", direction, lane, i, intersectionnumber, self.tactic, self.offset, [intersectionx, intersectiony], self.cycletime, ) self.trafficlightlist.append([light[1], i]) self.schedule.add(trafficlight) self.grid.place_agent(trafficlight, (xlocation, ylocation)) self.tlightmatrix = lightconnection( self.tlightmatrix, self.trafficlightlist, self.intersections ) # Place legend self.grid.place_agent(LegendCarIcon("Caricon", self), (65, 68)) self.grid.place_agent(LegendGreenTlightIcon("GreenTlighticon", self), (65, 69)) self.grid.place_agent(LegendRedTlightIcon("RedTlighticon", self), (65, 70)) # Get emission values def getco2(self): return self.emission[0] def getnox(self): return self.emission[1] def getpm(self): return self.emission[2] def getaveragetraveltime(self): return self.averagetraveltime def getaverageco2(self): totalco2 = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalco2 += emissions[0] return totalco2 / len(self.averageemission) else: return 0 def getaveragenox(self): totalnox = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalnox += emissions[1] return totalnox / len(self.averageemission) else: return 0 def getaveragepm(self): totalpm = 0 if len(self.averageemission) > 0: for i, emissions in enumerate(self.averageemission): totalpm += emissions[2] return totalpm / len(self.averageemission) else: return 0 def numberofcars(self): return len(self.schedule.agents) - 12 * self.intersections def step(self): """ Step function that will randomly place cars based on the spawn chance and will visit all the agents to perform their step function. """ # Spawn cars for spawn in self.spawns: location = spawn[0] cell_contents = self.grid.get_cell_list_contents([location]) if ( not cell_contents and random.randint(0, int(100 / self.slowmotionrate)) < self.spawnrate ): location = spawn[0] xlocation = int(location[0]) ylocation = self.height - 1 - int(location[1]) direction = spawn[1][1] lane = spawn[1][2] car = CarAgent( f"car{self.carID}", self, direction, lane, [xlocation, ylocation] ) self.carID += 1 self.schedule.add(car) self.grid.place_agent(car, (xlocation, ylocation)) # Clear all previous step's emission and travel time if len(self.traveltime) > 0: self.averagetraveltime = sum(self.traveltime) / len(self.traveltime) # For the greenwave tactic if ( self.tactic == "GreenWave" and len(self.schedule.agents) > 12 * self.intersections and ((self.schedule.steps % (self.cycletime * 2)) == 0) ): self.firstcycledone = 0 self.mostcars = np.argmax(np.nansum(self.tlightmatrix, axis=1)) if self.mostcars: self.goesto = np.where(~np.isnan(self.tlightmatrix[self.mostcars])) self.firstgreenintersection = self.lights[self.mostcars][1][3] self.secondgreenintersection = self.lights[self.goesto[0][0]][1][3] # Determines the direction of traffic lights firstdirection = self.schedule.agents[int(self.mostcars)].direction seconddirection = self.schedule.agents[self.goesto[0][0]].direction # Determines combinations of traffic lights that can stay green for i, combination in enumerate(self.lightcombinations): if firstdirection + "D" in combination: self.firstcombination = self.lightcombinations[i] if seconddirection + "D" in combination: self.secondcombination = self.lightcombinations[i] # If 1st part of green wave is over (so 1 cycle has been done) if not ((self.schedule.steps % (self.cycletime * 2)) == 0): self.firstcycledone = 1 # For the proportional tactic if ( self.tactic == "Proportional" and len(self.schedule.agents) > 12 * self.intersections ): for i in range(self.intersections): currenttimegreen = self.trafficlightinfo[f"intersection{i}"][ "Timeinfo" ]["Currenttimegreen"] maxgreentime = self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = (currenttimegreen + 1) if currenttimegreen > maxgreentime + 6: carsinfront = np.nansum(self.tlightmatrix, axis=1) totalcars = [0, 0, 0, 0] for key in self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ].keys(): trafficlight = int( self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ][key] ) cars = carsinfront[trafficlight] for j, combi in enumerate(self.lightcombinations): if key in combi: totalcars[j] = totalcars[j] + cars # No cars? pick regular timeschedule if sum(totalcars) == 0: totalcars = [1, 1, 1, 1] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = totalcars.index(max(totalcars)) self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] = (max(totalcars) / (sum(totalcars) / 4) * self.cycletime) self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = 0 if currenttimegreen == maxgreentime: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = -1 # For the lookahead tactic if ( self.tactic == "Lookahead" and len(self.schedule.agents) > 12 * self.intersections ): self.mostexpectedcars = [0, 0, 0] for i in range(self.intersections): currenttimegreen = self.trafficlightinfo[f"intersection{i}"][ "Timeinfo" ]["Currenttimegreen"] maxgreentime = self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = (currenttimegreen + 1) if currenttimegreen > maxgreentime + 6: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"]["Allred"] = 0 carsexpected = np.nansum(self.tlightmatrix, axis=0) carsinfront = np.nansum(self.tlightmatrix, axis=1) totalcars = [0, 0, 0, 0] # For every direction + lane in intersection for key in self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ].keys(): trafficlight = int( self.trafficlightinfo[f"intersection{i}"][ "Trafficlightinfo" ][key] ) cars = carsinfront[trafficlight] # For every lightcombination for j, combi in enumerate(self.lightcombinations): if key in combi: totalcars[j] = ( totalcars[j] + cars + carsexpected[trafficlight] ) if totalcars[j] > self.mostexpectedcars[0]: self.mostexpectedcars[0] = totalcars[j] self.mostexpectedcars[1] = i self.mostexpectedcars[2] = j # Reset timers self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] = ( self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currentgreen" ] + 1 ) % 4 self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Maxtimegreen" ] = self.cycletime self.trafficlightinfo[f"intersection{i}"]["Timeinfo"][ "Currenttimegreen" ] = 0 if currenttimegreen == maxgreentime: self.trafficlightinfo[f"intersection{i}"]["Timeinfo"]["Allred"] = 1 if self.mostexpectedcars[0] != 0: # Change green light information of intersection with most expected cars self.trafficlightinfo[f"intersection{self.mostexpectedcars[1]}"][ "Timeinfo" ]["Currentgreen"] = self.mostexpectedcars[2] # Get trafficlightnumbers of ligths where most cars are expected mostcars = 0 mostcarslight = None comingfrom = np.nansum(self.tlightmatrix, axis=1) for direction in self.lightcombinations[self.mostexpectedcars[2]]: greenlight = int( self.trafficlightinfo[ f"intersection{self.mostexpectedcars[1]}" ]["Trafficlightinfo"][direction] ) # Where the cars to those lights come from. lightscomingfrom = np.argwhere( ~np.isnan(self.tlightmatrix[:, greenlight]) ) for light in lightscomingfrom: if light: light = light[0] carsinfront = np.sum(comingfrom[light]) if carsinfront > mostcars: mostcars = int(carsinfront) mostcarslight = light # Find intersection + directon of this light and change this intersection's green light information if mostcars != 0: intersection = int(self.lights[mostcarslight][1][3]) direction = self.lights[mostcarslight][1][1:3] for k, directs in enumerate(self.lightcombinations): if direction in directs[0:3]: self.trafficlightinfo[f"intersection{intersection}"][ "Timeinfo" ]["Currentgreen"] = k pass self.datacollector.collect(self) self.emission = [0, 0, 0] self.schedule.step()
class DDAModel(Model): """A simple DDA model""" _width = _WIDTH # width and height of the world. These shouldn't be changed _height = _HEIGHT def __init__(self, N, iterations, bleedout_rate=np.random.normal(0.5, scale=0.1), mp=False): """ Create a new instance of the DDA model. Parameters: N - the number of agents iterations - the number of iterations to run the model for blr - the bleedout rate (the probability that agents leave at the midpoint) (default normal distribution with mean=0.5 and sd=0.1) mp - whether to use multiprocess (agents call step() method at same time) (doesn't work!) (default False) """ self.num_agents = N self._bleedout_rate = bleedout_rate self.iterations = iterations self.mp = mp # Locations of important parts of the environment. These shouldn't be changed self.graveyard = (0, 0) # x,y locations of the graveyard self.loc_a = (1, 0) # Location a (on left side of street) self.loc_b = (23, 0) # Location b (on the right side) self.loc_mid = (12, 0) # The midpoint # 'Cameras' that store the number of agents who pass them over the course of an hour. The historical counts # are saved by mesa using the DataCollector self._camera_a = 0 # Camera A self._camera_b = 0 # Camera B self._camera_m = 0 # The midpoint # Set up the scheduler. Note that this isn't actually used (see below re. agent's stepping) self.schedule = RandomActivation(self) # Random order for calling agent's step methods # For multiprocess step method self.pool = Pool() # Create the environment self.grid = MultiGrid(DDAModel._width, DDAModel._height, False) # Define a variable that can be used to indicate whether the model has finished self.running = True # Create a distribution that tells us the number of agents to be added to the world at each self._agent_dist = DDAModel._make_agent_distribution(N) # Create all the agents for i in range(self.num_agents): a = DDAAgent(i, self) self.schedule.add(a) # Add the agents to the schedule # All agents start as 'retired' in the graveyard a.state = AgentStates.RETIRED self.grid.place_agent(a, self.graveyard) # All agents start in the graveyard print("Created {} agents".format(len(self.schedule.agents))) # Define a collector for model data self.datacollector = DataCollector( model_reporters={"Bleedout rate": lambda m: m.bleedout_rate, "Number of active agents": lambda m: len(m.active_agents()), "Camera A counts": lambda m: m.camera_a, "Camera B counts": lambda m: m.camera_b, "Camera M counts": lambda m: m.camera_m }, agent_reporters={"Location (x)": lambda agent: agent.pos[0], "State": lambda agent: agent.state } ) def step(self): """Advance the model by one step.""" print("Iteration {}".format(self.schedule.steps)) self.datacollector.collect(self) # Collect data about the model # See if the model has finished running. if self.schedule.steps >= self.iterations: self.running = False return # Things to do every hour. # - 1 - reset the camera counters # - 2 - activate some agents num_to_activate = -1 s = self.schedule.steps # Number of steps (for convenience) if s % 60 == 0: # On the hour # Reset the cameras self._reset_cameras() # Calculate the number of agents to activate num_to_activate = int(self._agent_dist[int((s / 60) % 24)]) print("\tActivating {} agents on hour {}".format(num_to_activate, s % 60)) else: num_to_activate = 0 assert num_to_activate >= 0, \ "The number of agents to activate should be greater or equal to 0, not {}".format(num_to_activate) if num_to_activate > 0: # Choose some agents that are currently retired to activate. retired_agents = [a for a in self.schedule.agents if a.state == AgentStates.RETIRED] assert len(retired_agents) >= num_to_activate, \ "Too few agents to activate (have {}, need {})".format(len(retired_agents), num_to_activate) to_activate = np.random.choice(retired_agents, size=num_to_activate, replace=False) print("\t\tActivating agents: {}".format(to_activate)) for a in to_activate: a.activate() # XXXX HERE - see line 477 om wprlomgca,eras/py # Call all agents' 'step' method. if not self.mp: # Not using multiprocess. Do it the mesa way: self.schedule.step() else: # Better to do it a different way to take advantage of multicore processors and to ignore agents who are not # active (no need for them to step at all) # NOTE: Doesn't work! The problem is that the DDAAgent needs the DDAModel class, which means # that this class needs to be pickled and copied to the child processes. The first problem (which can be # fixed by creating functions rather than using lambda, although this is messy) is that DDAModel uses # lambda functions, that can't be pickled. Second and more difficult problem is that the Pool object itself # cannot be shared. Possible solution here: # https://stackoverflow.com/questions/25382455/python-notimplementederror-pool-objects-cannot-be-passed-between-processes # but for the meantime I'm not going to try to fix this. active_agents = self.active_agents() # Get all of the active agents random.shuffle(active_agents) if active_agents is None: print("\tNo agents are active") # Nothing to do else: p = Pool() p.map(DDAAgent._step_agent, active_agents) # Calls step() for all agents # As not using the proper schedule method, need to update time manually. self.schedule.steps += 1 self.schedule.time += 1 def increment_camera_a(self): """Used by agents to tell the model that they have just passed the camera at location A. It would be neater to have the cameras detect the agents, but I think that this would be quite expensive.""" self._camera_a += 1 # Increment the count of the current hour (most recent) def increment_camera_b(self): """Used by agents to tell the model that they have just passed the camera at location B. It would be neater to have the cameras detect the agents, but I think that this would be quite expensive.""" self._camera_b += 1 # Increment the count of the current hour (most recent) def increment_camera_m(self): """Used by agents to tell the model that they have just passed the camera at the midpoint. This is only for information really, in this scenario there is no camera at the midpoint""" self._camera_m += 1 # Increment the count of the current hour (most recent) @property def camera_a(self) -> int: """Getter for the count of the camera at location A""" return self._camera_a @property def camera_b(self) -> int: """Getter for the count of the camera at location B""" return self._camera_b @property def camera_m(self) -> int: """Getter for the count of the camera at the midpoint""" return self._camera_m def _reset_cameras(self): """Reset the cameras to zero. Done on the hour""" self._camera_a = 0 self._camera_b = 0 self._camera_m = 0 @staticmethod def _step_agent(a): """Call the given agent's step method. Only required because Pool.map doesn't take lambda functions.""" a.step() # bleedout rate is defined as a property: http://www.python-course.eu/python3_properties.php @property def bleedout_rate(self): """Get the current bleedout rate""" return self._bleedout_rate @bleedout_rate.setter def bleedout_rate(self, blr: float) -> None: """Set the bleedout rate. It must be between 0 and 1 (inclusive). Failure to do that raises a ValueError.""" if blr < 0 or blr > 1: raise ValueError("The bleedout rate must be between 0 and 1, not '{}'".format(blr)) self._bleedout_rate = blr def active_agents(self) -> List[DDAAgent]: """Return a list of the active agents (i.e. those who are not retired)""" return [a for a in self.schedule.agents if a.state != AgentStates.RETIRED] @classmethod def _make_agent_distribution(cls, N): """Create a distribution that tells us the number of agents to be created at each hour""" a = np.arange(0, 24, 1) # Create an array with one item for each hour rv1 = norm(loc=12., scale=6.0) # A continuous, normal random variable with a peak at 12 dist = rv1.pdf(a) # Draw from the random variable pdf, taking values from a return [round(item * N, ndigits=0) for item in dist] # Return a rounded list (the number of agents at each hour)
class SugarscapeModel(Model): def __init__(self, height=50, width=50, init_agents=500, max_metabolism=3, max_vision=10, max_init_sugar=5, min_age=30, max_age=60, init_poll=3, ex_ratio=2, ex_mod=1, poll_growth_rule=True, inheritance_rule=True): self.height = height self.width = width self.init_agents = init_agents self.init_poll = init_poll self.max_metabolism = max_metabolism self.max_vision = max_vision self.max_init_sugar = max_init_sugar self.min_age = min_age self.max_age = max_age self.ex_ratio = ex_ratio self.ex_mod = ex_mod self.replacement_rule = True self.pollution_rule = False self.diffusion_rule = False self.push_rule = False self.poll_growth_rule = poll_growth_rule self.expend_rule = True self.inheritance_rule = inheritance_rule self.map = self.import_map() self.grid = MultiGrid(height, width, torus=True) self.schedule = RandomActivationByType(self) self.datacollector = DataCollector({'Pollution': (lambda m: m.total_pollution), 'Wealth': (lambda m: m.total_wealth/m.init_agents), 'Agents': (lambda m: len(m.schedule.agents_by_type[ScapeAgent]))}, {'Wealth': self.collect_wealth, 'Metabolism': self.collect_metabolism, 'Vision': self.collect_vision}) self.total_wealth = 0 self.total_pollution = 0 self.populate_sugar() self.populate_agents() def step(self): ''' Step method run by the visualization module''' self.schedule.step([ScapeAgent, SugarPatch]) self.datacollector.collect(self) # if self.schedule.time == 20: # self.pollution_rule = True if self.schedule.time == 30: self.push_rule = True self.total_wealth = 0 self.total_pollution = 0 for agent in self.schedule.agents_by_type[ScapeAgent]: self.total_wealth += agent.wealth for patch in self.schedule.agents_by_type[SugarPatch]: self.total_pollution += patch.pollution def import_map(self): ''' Imports a text file into an array to be used when generating and placing the sugar Agents into the grid ''' f = open('Maps/sugar_map.txt', 'r') map_list = [] for line in f: num_list = line.split(' ') for num in num_list: map_list.append(int(num[0])) return map_list def new_agent(self, uid, inheritance): ''' Place a new agent on the sugarscape in order to replace a death''' free = False while not free: location = random.choice([cell for cell in self.grid.coord_iter()]) if len(location[0]) == 1: free = True pos = (location[1], location[2]) patch = self.grid.get_cell_list_contents([pos])[0] if self.inheritance_rule: if inheritance == 'rand': wealth = random.randint(1, self.max_init_sugar) else: wealth = inheritance else: wealth = random.randint(1, self.max_init_sugar) agent = ScapeAgent(uid, pos, wealth, random.randint(1,self.max_metabolism), random.randint(1,self.max_vision), random.randint(self.min_age, self.max_age), patch, self.ex_ratio, self.ex_mod) self.grid.place_agent(agent, agent.pos) self.schedule.add(agent) def populate_agents(self): ''' Place ScapeAgent's in random unoccupied locations on the grid with randomomized sets of parameters ''' cells = [(cell[1], cell[2]) for cell in self.grid.coord_iter()] for i in range(self.init_agents): uid = 'a' + str(i) location = random.choice(cells) cells.remove(location) patch = self.grid.get_cell_list_contents([location])[0] agent = ScapeAgent(uid, location, random.randint(1,self.max_init_sugar), random.randint(1,self.max_metabolism), random.randint(1,self.max_vision), random.randint(self.min_age, self.max_age), patch, self.ex_ratio, self.ex_mod) self.grid.place_agent(agent, location) self.schedule.add(agent) def populate_sugar(self): ''' Place SugarPatch's on every cell with maximum sugar content according to the imported 'sugar_map.txt' file ''' map_i = 0 for cell in self.grid.coord_iter(): x = cell[1] y = cell[2] uid = 's'+str(y)+str(x) # patch = SugarPatch(uid, (x,y), 3) patch = SugarPatch(uid, (x,y), self.map[map_i], self.init_poll) self.grid.place_agent(patch, (x,y)) self.schedule.add(patch) map_i += 1 def collect_wealth(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.wealth def collect_metabolism(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.metabolism def collect_vision(self, agent): '''Method for datacollector''' if isinstance(agent, ScapeAgent): return agent.vision def calc_gini(self, wealths): '''Returns gini coefficient''' sort_wealths = sorted(wealths) num_agents = len(sort_wealths) gini,count = 0,0 for wealth in sort_wealths: gini += wealth * (num_agents - count) count += 1 gini /= (num_agents*sum(sort_wealths)) return num_agents**(-1) - 2*gini + 1
class BankReserves(Model): """ This model is a Mesa implementation of the Bank Reserves model from NetLogo. It is a highly abstracted, simplified model of an economy, with only one type of agent and a single bank representing all banks in an economy. People (represented by circles) move randomly within the grid. If two or more people are on the same grid location, there is a 50% chance that they will trade with each other. If they trade, there is an equal chance of giving the other agent $5 or $2. A positive trade balance will be deposited in the bank as savings. If trading results in a negative balance, the agent will try to withdraw from its savings to cover the balance. If it does not have enough savings to cover the negative balance, it will take out a loan from the bank to cover the difference. The bank is required to keep a certain percentage of deposits as reserves and the bank's ability to loan at any given time is a function of the amount of deposits, its reserves, and its current total outstanding loan amount. """ # grid height grid_h = 20 # grid width grid_w = 20 """init parameters "init_people", "rich_threshold", and "reserve_percent" are all UserSettableParameters""" def __init__(self, height=grid_h, width=grid_w, init_people=2, rich_threshold=10, reserve_percent=50,): self.height = height self.width = width self.init_people = init_people self.schedule = RandomActivation(self) self.grid = MultiGrid(self.width, self.height, torus=True) # rich_threshold is the amount of savings a person needs to be considered "rich" self.rich_threshold = rich_threshold self.reserve_percent = reserve_percent # see datacollector functions above self.datacollector = DataCollector(model_reporters={ "Rich": get_num_rich_agents, "Poor": get_num_poor_agents, "Middle Class": get_num_mid_agents, "Savings": get_total_savings, "Wallets": get_total_wallets, "Money": get_total_money, "Loans": get_total_loans}, agent_reporters={ "Wealth": lambda x: x.wealth}) # create a single bank for the model self.bank = Bank(1, self, self.reserve_percent) # create people for the model according to number of people set by user for i in range(self.init_people): # set x, y coords randomly within the grid x = self.random.randrange(self.width) y = self.random.randrange(self.height) p = Person(i, (x, y), self, True, self.bank, self.rich_threshold) # place the Person object on the grid at coordinates (x, y) self.grid.place_agent(p, (x, y)) # add the Person object to the model schedule self.schedule.add(p) self.running = True self.datacollector.collect(self) def step(self): # tell all the agents in the model to run their step function self.schedule.step() # collect data self.datacollector.collect(self) def run_model(self): for i in range(self.run_time): self.step()
def __init__(self, height=60, width=60, no_of_species=4, no_of_seeds=2, no_of_agents=20): ''' Create a new MesaTraitsModel. Args: ''' super().__init__() # Set parameters self.height = height self.width = width self.no_of_agents = no_of_agents self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.no_of_species = no_of_species self.no_of_seeds = no_of_seeds self.patch_manager = PatchManager() self.datacollector = DataCollector( {"Organisms": lambda m: m.schedule.get_breed_count(Organism)}) # Create patches for agent, x, y in self.grid.coord_iter(): #print("new patch added") grown = False patch = Patch(self.next_id(), (x, y), self, 0.04, None, grown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.patch_manager.add_patch(patch) list_of_cells = [] #select some random patches (without substitution) total_seeds = no_of_species * no_of_seeds for i in range(self.width): for j in range(self.height): list_of_cells.append((i, j)) cords = random.sample(list_of_cells, total_seeds) #choose agents at those patches to be assigned the species _ = 0 for i in range(no_of_species): for j in range(no_of_seeds): patch = self.grid.get_cell_list_contents(cords[_]) patch[0].grown = True patch[0].species = i self.patch_manager.remove_patch(patch[0]) _ += 1 #make the patch grow self.patch_manager.grow_patches() # make moving agents for i in range(20): #20 agents x = random.choice(range(self.width)) y = random.choice(range(self.height)) agent = Organism(self.next_id(), (x, y), self, energy_tank=100, current_energy=50, metabolic_cost=1, energy_gain_per_patch=5, age=5, sexual=False, maturity_age=20, max_longevity=1000, patch_affinity=[1, 1, 0, 0], climatic_affinity=0.6, climatic_affinity_sd=0.05, line_of_sight=1, dispersal_speed=2, reproductive_delay=0, offspring_number=1, moore=True) self.grid.place_agent(agent, (x, y)) self.schedule.add(agent) self.running = True self.datacollector.collect(self)
class Sugarscape2ConstantGrowback(Model): ''' Sugarscape 2 Constant Growback ''' verbose = True # Print-monitoring def __init__(self, height=50, width=50, initial_population=100): ''' Create a new Constant Growback model with the given parameters. Args: initial_population: Number of population to start with ''' # Set parameters self.height = height self.width = width self.initial_population = initial_population self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=False) self.datacollector = DataCollector({"SsAgent": lambda m: m.schedule.get_breed_count(SsAgent), }) # Create sugar import numpy as np sugar_distribution = np.genfromtxt("sugarscape/sugar-map.txt") for _, x, y in self.grid.coord_iter(): max_sugar = sugar_distribution[x, y] sugar = Sugar((x, y), self, max_sugar) self.grid.place_agent(sugar, (x, y)) self.schedule.add(sugar) # Create agent: for i in range(self.initial_population): x = random.randrange(self.width) y = random.randrange(self.height) sugar = random.randrange(6, 25) metabolism = random.randrange(2, 4) vision = random.randrange(1, 6) ssa = SsAgent((x, y), self, False, sugar, metabolism, vision) self.grid.place_agent(ssa, (x, y)) self.schedule.add(ssa) self.running = True def step(self): self.schedule.step() self.datacollector.collect(self) if self.verbose: print([self.schedule.time, self.schedule.get_breed_count(SsAgent)]) def run_model(self, step_count=200): if self.verbose: print('Initial number Sugarscape Agent: ', self.schedule.get_breed_count(SsAgent)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number Sugarscape Agent: ', self.schedule.get_breed_count(SsAgent))
def __init__(self, num_demolition, num_construction, recycling_tendency_percentage, num_hubs=1, event_rate_construction=5., event_rate_demolition=3., width=20, height=20): super().__init__() self.width = width self.height = height ## TODO calculate duration #self.duration = calculate_lifespan(event_rate) self.duration = 37 self.tick_counter = 0 self.num_demolition = num_demolition self.num_construction = num_construction self.recycling_tendency = recycling_tendency_percentage / 100 self.num_hubs = num_hubs self.grid = MultiGrid(self.width, self.height, True) self.schedule = RandomActivation(self) self.datacollector = DataCollector(model_reporters={ "Amount direct recycled": calculate_recycled, "Amount recycled via hub": calculate_recycled_hub, "Amount not recycled": calculate_not_recycled, "Amount raw material consumed": calculate_raw_material_consumed, "Stock level materials in hubs": get_stock_level_hubs, "Supply demolition materials": get_demolition_current_amount, "Demand construction materials": get_construction_current_amount }, agent_reporters={ "Amount": lambda agent: agent.unique_id }) # create construction hubs if num_hubs > 0: hubs = [] for i in range(self.num_hubs): a = RecyclingHub(self.next_id(), self) x = self.random.randrange(self.width) y = self.random.randrange(self.height) self.grid.place_agent(a, (x, y)) hubs.append(a) self.schedule.add(a) # Create agents for i in range(self.num_demolition): hub = None if num_hubs > 0: hub = random.choice(hubs) a = DemolitionProjectAgent( self.next_id(), self, recycling_tendency=self.recycling_tendency, hub=hub, event_rate=event_rate_demolition, status=Status.passive, total_amount=100.) x = self.random.randrange(self.width) y = self.random.randrange(self.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) for i in range(self.num_construction): hub = None if num_hubs > 0: hub = random.choice(hubs) a = ConstructionProjectAgent(self.next_id(), self, hub=hub, event_rate=event_rate_construction, status=Status.active, total_amount=100.) x = self.random.randrange(self.width) y = self.random.randrange(self.height) self.grid.place_agent(a, (x, y)) self.schedule.add(a) self.running = True self.datacollector.collect(self)
class FireEvacuation(Model): MIN_HEALTH = 0.75 MAX_HEALTH = 1 MIN_SPEED = 1 MAX_SPEED = 2 MIN_NERVOUSNESS = 1 MAX_NERVOUSNESS = 10 MIN_EXPERIENCE = 1 MAX_EXPERIENCE = 10 MIN_VISION = 1 # MAX_VISION is simply the size of the grid def __init__(self, floor_plan_file, human_count, collaboration_percentage, fire_probability, visualise_vision, random_spawn, save_plots): # Load floorplan # floorplan = np.genfromtxt(path.join("fire_evacuation/floorplans/", floor_plan_file)) with open(os.path.join("fire_evacuation/floorplans/", floor_plan_file), "rt") as f: floorplan = np.matrix([line.strip().split() for line in f.readlines()]) # Rotate the floorplan so it's interpreted as seen in the text file floorplan = np.rot90(floorplan, 3) # Check what dimension our floorplan is width, height = np.shape(floorplan) # Init params self.width = width self.height = height self.human_count = human_count self.collaboration_percentage = collaboration_percentage self.visualise_vision = visualise_vision self.fire_probability = fire_probability self.fire_started = False # Turns to true when a fire has started self.save_plots = save_plots # Set up model objects self.schedule = RandomActivation(self) self.grid = MultiGrid(height, width, torus=False) # Used to start a fire at a random furniture location self.furniture_list = [] # Used to easily see if a location is a FireExit or Door, since this needs to be done a lot self.fire_exit_list = [] self.door_list = [] # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan self.random_spawn = random_spawn self.spawn_list = [] # Load floorplan objects for (x, y), value in np.ndenumerate(floorplan): value = str(value) floor_object = None if value is "W": floor_object = Wall((x, y), self) elif value is "E": floor_object = FireExit((x, y), self) self.fire_exit_list.append((x, y)) self.door_list.append((x, y)) # Add fire exits to doors as well, since, well, they are elif value is "F": floor_object = Furniture((x, y), self) self.furniture_list.append((x, y)) elif value is "D": floor_object = Door((x, y), self) self.door_list.append((x, y)) elif value is "S": self.spawn_list.append((x, y)) if floor_object: self.grid.place_agent(floor_object, (x, y)) self.schedule.add(floor_object) # Create a graph of traversable routes, used by agents for pathing self.graph = nx.Graph() for agents, x, y in self.grid.coord_iter(): pos = (x, y) # If the location is empty, or a door if not agents or any(isinstance(agent, Door) for agent in agents): neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1) for neighbor in neighbors: # If there is contents at this location and they are not Doors or FireExits, skip them if not self.grid.is_cell_empty(neighbor) and neighbor not in self.door_list: continue self.graph.add_edge(pos, neighbor) # Collects statistics from our model run self.datacollector = DataCollector( { "Alive": lambda m: self.count_human_status(m, Human.Status.ALIVE), "Dead": lambda m: self.count_human_status(m, Human.Status.DEAD), "Escaped": lambda m: self.count_human_status(m, Human.Status.ESCAPED), "Incapacitated": lambda m: self.count_human_mobility(m, Human.Mobility.INCAPACITATED), "Normal": lambda m: self.count_human_mobility(m, Human.Mobility.NORMAL), "Panic": lambda m: self.count_human_mobility(m, Human.Mobility.PANIC), "Verbal Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.VERBAL_SUPPORT), "Physical Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.PHYSICAL_SUPPORT), "Morale Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.MORALE_SUPPORT) } ) # Calculate how many agents will be collaborators number_collaborators = int(round(self.human_count * (self.collaboration_percentage / 100))) # Start placing human agents for i in range(0, self.human_count): if self.random_spawn: # Place human agents randomly pos = self.grid.find_empty() else: # Place human agents at specified spawn locations pos = random.choice(self.spawn_list) if pos: # Create a random human health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100 speed = random.randint(self.MIN_SPEED, self.MAX_SPEED) if number_collaborators > 0: collaborates = True number_collaborators -= 1 else: collaborates = False # Vision statistics obtained from http://www.who.int/blindness/GLOBALDATAFINALforweb.pdf vision_distribution = [0.0058, 0.0365, 0.0424, 0.9153] vision = int(np.random.choice(np.arange(self.MIN_VISION, self.width + 1, (self.width / len(vision_distribution))), p=vision_distribution)) nervousness_distribution = [0.025, 0.025, 0.1, 0.1, 0.1, 0.3, 0.2, 0.1, 0.025, 0.025] # Distribution with slight higher weighting for above median nerovusness nervousness = int(np.random.choice(range(self.MIN_NERVOUSNESS, self.MAX_NERVOUSNESS + 1), p=nervousness_distribution)) # Random choice starting at 1 and up to and including 10 experience = random.randint(self.MIN_EXPERIENCE, self.MAX_EXPERIENCE) belief_distribution = [0.9, 0.1] # [Believes, Doesn't Believe] believes_alarm = np.random.choice([True, False], p=belief_distribution) human = Human(pos, health=health, speed=speed, vision=vision, collaborates=collaborates, nervousness=nervousness, experience=experience, believes_alarm=believes_alarm, model=self) self.grid.place_agent(human, pos) self.schedule.add(human) else: print("No tile empty for human placement!") self.running = True # Plots line charts of various statistics from a run def save_figures(self): DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) OUTPUT_DIR = DIR + "/output" results = self.datacollector.get_model_vars_dataframe() dpi = 100 fig, axes = plt.subplots(figsize=(1920 / dpi, 1080 / dpi), dpi=dpi, nrows=1, ncols=3) status_results = results.loc[:, ['Alive', 'Dead', 'Escaped']] status_plot = status_results.plot(ax=axes[0]) status_plot.set_title("Human Status") status_plot.set_xlabel("Simulation Step") status_plot.set_ylabel("Count") mobility_results = results.loc[:, ['Incapacitated', 'Normal', 'Panic']] mobility_plot = mobility_results.plot(ax=axes[1]) mobility_plot.set_title("Human Mobility") mobility_plot.set_xlabel("Simulation Step") mobility_plot.set_ylabel("Count") collaboration_results = results.loc[:, ['Verbal Collaboration', 'Physical Collaboration', 'Morale Collaboration']] collaboration_plot = collaboration_results.plot(ax=axes[2]) collaboration_plot.set_title("Human Collaboration") collaboration_plot.set_xlabel("Simulation Step") collaboration_plot.set_ylabel("Successful Attempts") collaboration_plot.set_ylim(ymin=0) timestr = time.strftime("%Y%m%d-%H%M%S") plt.suptitle("Percentage Collaborating: " + str(self.collaboration_percentage) + "%, Number of Human Agents: " + str(self.human_count), fontsize=16) plt.savefig(OUTPUT_DIR + "/model_graphs/" + timestr + ".png") plt.close(fig) # Starts a fire at a random piece of furniture with file_probability chance def start_fire(self): rand = random.random() if rand < self.fire_probability: fire_furniture = random.choice(self.furniture_list) fire = Fire(fire_furniture, self) self.grid.place_agent(fire, fire_furniture) self.schedule.add(fire) self.fire_started = True print("Fire started at:", fire_furniture) def step(self): """ Advance the model by one step. """ self.schedule.step() # If there's no fire yet, attempt to start one if not self.fire_started: self.start_fire() self.datacollector.collect(self) # If no more agents are alive, stop the model and collect the results if self.count_human_status(self, Human.Status.ALIVE) == 0: self.running = False if self.save_plots: self.save_figures() @staticmethod def count_human_collaboration(model, collaboration_type): """ Helper method to count the number of collaborations performed by Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if collaboration_type == Human.Action.VERBAL_SUPPORT: count += agent.get_verbal_collaboration_count() elif collaboration_type == Human.Action.MORALE_SUPPORT: count += agent.get_morale_collaboration_count() elif collaboration_type == Human.Action.PHYSICAL_SUPPORT: count += agent.get_physical_collaboration_count() return count @staticmethod def count_human_status(model, status): """ Helper method to count the status of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_status() == status: count += 1 return count @staticmethod def count_human_mobility(model, mobility): """ Helper method to count the mobility of Human agents in the model """ count = 0 for agent in model.schedule.agents: if isinstance(agent, Human): if agent.get_mobility() == mobility: count += 1 return count
def __init__(self, no_people, total_area, no_agents, Nc_N, n, all_x, all_y, centers, infection_rate, city_label, no_steps): self.num_agents = no_agents grid_size = round(math.sqrt((self.num_agents / no_people) * total_area) * 100) self.grid = MultiGrid(grid_size, grid_size, False) self.schedule = RandomActivation(self) self.running = True flux_store = np.zeros((1, 3)) home_store1 = np.zeros((self.num_agents, 2)) for i in range(round(len(centers) / 2)): print(i, datetime.datetime.now() - begin_time) n_cities = random.sample(range(1, round(len(centers) / 2)), n) for j in range(len(n_cities)): mi = np.count_nonzero(city_label == i+1) nj = np.count_nonzero(city_label == n_cities[j]) radius = math.sqrt((centers[i, 0] - centers[n_cities[j], 0]) ** 2 + (centers[i, 1] - centers[n_cities[j], 1]) ** 2) sij = 0 for k in range(len(all_x)): if (all_x[k] - centers[i, 0]) ** 2 + (all_y[k] - centers[i, 1]) ** 2 < radius ** 2: sij += 1 sij = sij - mi - nj if sij < 0: sij = 0 try: Tij = (mi * Nc_N * mi * nj) / ((mi + sij) * (mi + nj + sij))*10 except ZeroDivisionError: Tij = 0 if Tij > 75: Tij = 75 if Tij > 1 and (i != n_cities[j]): flux_store = np.vstack((flux_store, (Tij, i+1, n_cities[j]))) work_place = np.zeros(self.num_agents) work_store1 = np.zeros((num, 2)) flux_store = np.delete(flux_store, 0, 0) for i in np.unique(flux_store[:, 1]): place = np.where(flux_store[:, 1] == i)[0] place1 = np.where(city_label == i)[0] for j in place1: for k in place: if random.uniform(0, 100) < flux_store[k, 0]: work_place[j] = flux_store[k, 2] for i in range(len(work_store1)): if work_place[i] != 0: n = int(work_place[i]) work_store1[i, :] = centers[n, 0], centers[n, 1] for i in range(self.num_agents): home_store1[i, :] = int(all_x[i]), int(all_y[i]) work_store = np.int64(work_store1) home_store = np.int64(home_store1) for i in range(self.num_agents): a = Agent(i, self, infection_rate, work_store, home_store, no_steps) self.schedule.add(a) self.grid.place_agent(a, (int(all_x[i]), int(all_y[i]))) if i == 1: a.infected = 1 self.datacollector = DataCollector( model_reporters={"Tot informed": compute_informed}, agent_reporters={"Infected": "infected"})
class WolfSheep(Model): ''' Wolf-Sheep Predation Model ''' height = 20 width = 20 initial_sheep = 100 initial_wolves = 50 sheep_reproduce = 0.04 wolf_reproduce = 0.05 wolf_gain_from_food = 20 grass = False grass_regrowth_time = 30 sheep_gain_from_food = 4 verbose = False # Print-monitoring description = 'A model for simulating wolf and sheep (predator-prey) ecosystem modelling.' def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4): ''' Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. ''' super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector( {"Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep)}) # Create sheep: for i in range(self.initial_sheep): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.sheep_gain_from_food) sheep = Sheep(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = self.random.randrange(self.width) y = self.random.randrange(self.height) energy = self.random.randrange(2 * self.wolf_gain_from_food) wolf = Wolf(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = self.random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = self.random.randrange(self.grass_regrowth_time) patch = GrassPatch(self.next_id(), (x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self) def step(self): self.schedule.step() # collect data self.datacollector.collect(self) if self.verbose: print([self.schedule.time, self.schedule.get_breed_count(Wolf), self.schedule.get_breed_count(Sheep)]) def run_model(self, step_count=200): if self.verbose: print('Initial number wolves: ', self.schedule.get_breed_count(Wolf)) print('Initial number sheep: ', self.schedule.get_breed_count(Sheep)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number wolves: ', self.schedule.get_breed_count(Wolf)) print('Final number sheep: ', self.schedule.get_breed_count(Sheep))
class MSUvUoMPredation(Model): ''' MSUvUoM Predation Model ''' height = 20 width = 20 initial_UoM = 100 initial_MSU = 50 UoM_reproduce = 0.04 MSU_reproduce = 0.05 MSU_gain_from_food = 20 grass = False grass_regrowth_time = 30 UoM_gain_from_food = 4 verbose = True # Print-monitoring description = 'A model for simulating MSU and UoM (predator-prey) ecosystem modelling.' def __init__(self, height=20, width=20, initial_UoM=100, initial_MSU=50, UoM_reproduce=0.04, MSU_reproduce=0.05, MSU_gain_from_food=20, grass=False, grass_regrowth_time=30, UoM_gain_from_food=4): ''' Create a new MSU vs UoM model with the given parameters. Args: initial_UoM: Number of UoM to start with initial_MSU: Number of MSU to start with UoM_reproduce: Probability of each UoM reproducing each step MSU_reproduce: Probability of each MSU reproducing each step MSU_gain_from_food: Energy a MSU gains from eating a UoM grass: Whether to have the UoM eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten UoM_gain_from_food: Energy UoM gain from grass, if enabled. ''' # Set parameters self.height = height self.width = width self.initial_UoM = initial_UoM self.initial_MSU = initial_MSU self.UoM_reproduce = UoM_reproduce self.MSU_reproduce = MSU_reproduce self.MSU_gain_from_food = MSU_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.UoM_gain_from_food = UoM_gain_from_food self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "MSU": lambda m: m.schedule.get_breed_count(MSU), "UoM": lambda m: m.schedule.get_breed_count(UoM) }) # Create UoM: for i in range(self.initial_UoM): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.UoM_gain_from_food) student = UoM((x, y), self, True, energy) self.grid.place_agent(student, (x, y)) self.schedule.add(student) # Create MSU for i in range(self.initial_MSU): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.MSU_gain_from_food) student = MSU((x, y), self, True, energy) self.grid.place_agent(student, (x, y)) self.schedule.add(student) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = random.randrange(self.grass_regrowth_time) patch = GrassPatch((x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self) def step(self): self.schedule.step() # collect data self.datacollector.collect(self) if self.verbose: print([ self.schedule.time, self.schedule.get_breed_count(MSU), self.schedule.get_breed_count(UoM) ]) def run_model(self, step_count=200): if self.verbose: print('Initial number MSU: ', self.schedule.get_breed_count(MSU)) print('Initial number UoM: ', self.schedule.get_breed_count(UoM)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number MSU: ', self.schedule.get_breed_count(MSU)) print('Final number UoM: ', self.schedule.get_breed_count(UoM))
def __init__(self, height, width, color, numAgents, gDense, kRate, dcDiffu, dhRes, dtRes, secRate): # number of agents per tile self.n = numAgents # grid density self.gD = gDense # rate of cAMP decay self.k = 0.1 # diffusion constant of cAMP self.Dc = dcDiffu # spatial resolution for cAMP simulation self.Dh = dhRes # time resolution for cAMP simulation self.Dt = dtRes # rate of cAMP secretion by an agent self.f = secRate # number of rows/columns in spatial array self.w = masterHeight # agent color self.color = color # height of grid self.height = masterHeight # width of grid self.width = masterWidth # Counter for generating sequential unique id's self.j = 0 # Counter for DataVis agents' unique id's self.dv = 0 # Counter for NumDataVis agents' unique id's self.ndv = 0 # Blacklist for agents in clustering self.blacklist = list() # List for current cluser agents self.cluster_agents = list() # List for cluster neighbors self.cluster_neighbors = list() # List to check how many cells have been examined during cluster detection self.cells = 0 # Create randomly ordered scheduler self.schedule = SimultaneousActivation(self) # Create grid (of type MultiGrid to support multiple agents per cell self.grid = MultiGrid(self.width, self.height, torus=False) # Initialize list of cAMP molecules self.cAMPs = list() # Initialize dict for datacollector with total datacollector dc = {"Total Amount of cAMP": self.getAmts} # Initialize for iterating through columns (x) and rows (y) self.x = 0 self.y = 0 # Loop to fill datacollector dictionary with dict entries for each column and row for x in range(masterWidth): dc.update({("x: " + str(x)): self.getColAmts}) dc.update({("y: " + str(x)): self.getRowAmts}) # Create datacollector to retrieve total amounts of cAMP from dc dict created above self.datacollector = DataCollector(dc) # Variable for storing random numbers r = 0 # Initial loop to create agents and fill agents list with them for (contents, x, y) in self.grid.coord_iter(): # Create object of type cAMP cell = cAMP([x, y], self, self.j, 0, self.k) # Add random amoutn of cAMP to cell (<1) cell.add(random.random()) # Place cAMP onto grid at coordinates x, y self.grid._place_agent((x, y), cell) # Add cAMP molecule to list self.cAMPs.append(cell) # print("x:", x, " y:", y) if x == 50: # Create DataVis agent ag = DataVis([x, y], self, self.dv) # Place DataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.dv += 1 elif x > 50: # Create NumDataVis agent with appropriate slice num ag = NumDataVis([x, y], self, self.ndv) # Place NumDataVis agent self.grid.place_agent(ag, tuple([x, y])) # Increment unique id counter self.ndv += 1 else: # Loop to create SlimeAgents if self.gD % 1 != 0: r = random.random() if r <= self.gD: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, 10, self.color) ag.setSecRate(5) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 else: for i in range(self.n): # Create object of type SlimeAgent ag = SlimeAgent([x, y], self, self.j, 10, self.color) ag.setSecRate(5) # Place agent onto grid at coordinates x, y self.grid.place_agent(ag, tuple([x, y])) # Add agent to schedule self.schedule.add(ag) # Increment j (unique_id variable) self.j += 1 # Print out number of agents print("# of agents:", self.j) self.running = True
def __init__(self, height=20, width=20, initial_UoM=100, initial_MSU=50, UoM_reproduce=0.04, MSU_reproduce=0.05, MSU_gain_from_food=20, grass=False, grass_regrowth_time=30, UoM_gain_from_food=4): ''' Create a new MSU vs UoM model with the given parameters. Args: initial_UoM: Number of UoM to start with initial_MSU: Number of MSU to start with UoM_reproduce: Probability of each UoM reproducing each step MSU_reproduce: Probability of each MSU reproducing each step MSU_gain_from_food: Energy a MSU gains from eating a UoM grass: Whether to have the UoM eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten UoM_gain_from_food: Energy UoM gain from grass, if enabled. ''' # Set parameters self.height = height self.width = width self.initial_UoM = initial_UoM self.initial_MSU = initial_MSU self.UoM_reproduce = UoM_reproduce self.MSU_reproduce = MSU_reproduce self.MSU_gain_from_food = MSU_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.UoM_gain_from_food = UoM_gain_from_food self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "MSU": lambda m: m.schedule.get_breed_count(MSU), "UoM": lambda m: m.schedule.get_breed_count(UoM) }) # Create UoM: for i in range(self.initial_UoM): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.UoM_gain_from_food) student = UoM((x, y), self, True, energy) self.grid.place_agent(student, (x, y)) self.schedule.add(student) # Create MSU for i in range(self.initial_MSU): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.MSU_gain_from_food) student = MSU((x, y), self, True, energy) self.grid.place_agent(student, (x, y)) self.schedule.add(student) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = random.randrange(self.grass_regrowth_time) patch = GrassPatch((x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self)
def __init__(self, width = 0, height = 0, torus = False, time = 0, step_in_year = 0, number_of_families = family_setting, number_of_monkeys = 0, monkey_birth_count = 0, monkey_death_count = 0, monkey_id_count = 0, number_of_humans = 0, grid_type = human_setting, run_type = run_setting, human_id_count = 0): # change the # of families here for graph.py, but use server.py to change # of families in the movement model # torus = False means monkey movement can't 'wrap around' edges super().__init__() self.width = width self.height = height self.time = time # time increases by 1/73 (decimal) each step self.step_in_year = step_in_year # 1-73; each step is 5 days, and 5 * 73 = 365 days in a year self.number_of_families = number_of_families self.number_of_monkeys = number_of_monkeys # total, not in each family self.monkey_birth_count = monkey_birth_count self.monkey_death_count = monkey_death_count self.monkey_id_count = monkey_id_count self.number_of_humans = number_of_humans self.grid_type = grid_type # string 'with_humans' or 'without_humans' self.run_type = run_type # string with 'normal_run' or 'first_run' self.human_id_count = human_id_count # width = self._readASCII(vegetation_file)[1] # width as listed at the beginning of the ASCII file # height = self._readASCII(vegetation_file)[2] # height as listed at the beginning of the ASCII file width = 85 height = 100 self.grid = MultiGrid(width, height, torus) # creates environmental grid, sets schedule # MultiGrid is a Mesa function that sets up the grid; options are between SingleGrid and MultiGrid # MultiGrid allows you to put multiple layers on the grid self.schedule = RandomActivation(self) # Mesa: Random vs. Staged Activation # similar to NetLogo's Ask Agents - determines order (or lack of) in which each agents act empty_masterdict = {'Outside_FNNR': [], 'Elevation_Out_of_Bound': [], 'Household': [], 'PES': [], 'Farm': [], 'Forest': [], 'Bamboo': [], 'Coniferous': [], 'Broadleaf': [], 'Mixed': [], 'Lichen': [], 'Deciduous': [], 'Shrublands': [], 'Clouds': [], 'Farmland': []} # generate land if self.run_type == 'first_run': gridlist = self._readASCII(vegetation_file)[0] # list of all coordinate values; see readASCII function gridlist2 = self._readASCII(elevation_file)[0] # list of all elevation values gridlist3 = self._readASCII(household_file)[0] # list of all household coordinate values gridlist4 = self._readASCII(pes_file)[0] # list of all PES coordinate values gridlist5 = self._readASCII(farm_file)[0] # list of all farm coordinate values gridlist6 = self._readASCII(forest_file)[0] # list of all managed forest coordinate values # The '_populate' function below builds the environmental grid. for x in [Elevation_Out_of_Bound]: self._populate(empty_masterdict, gridlist2, x, width, height) for x in [Household]: self._populate(empty_masterdict, gridlist3, x, width, height) for x in [PES]: self._populate(empty_masterdict, gridlist4, x, width, height) for x in [Farm]: self._populate(empty_masterdict, gridlist5, x, width, height) for x in [Forest]: self._populate(empty_masterdict, gridlist6, x, width, height) for x in [Bamboo, Coniferous, Broadleaf, Mixed, Lichen, Deciduous, Shrublands, Clouds, Farmland, Outside_FNNR]: self._populate(empty_masterdict, gridlist, x, width, height) self.saveLoad(empty_masterdict, 'masterdict_veg', 'save') self.saveLoad(self.grid, 'grid_veg', 'save') self.saveLoad(self.schedule, 'schedule_veg', 'save') # Pickling below load_dict = {} # placeholder for model parameters, leave this here even though it does nothing if self.grid_type == 'with_humans': empty_masterdict = self.saveLoad(load_dict, 'masterdict_veg', 'load') self.grid = self.saveLoad(self.grid, 'grid_veg', 'load') if self.grid_type == 'without_humans': empty_masterdict = self.saveLoad(load_dict, 'masterdict_without_humans', 'load') self.grid = self.saveLoad(load_dict, 'grid_without_humans', 'load') masterdict = empty_masterdict startinglist = masterdict['Broadleaf'] + masterdict['Mixed'] + masterdict['Deciduous'] # Agents will start out in high-probability areas. for coordinate in masterdict['Elevation_Out_of_Bound'] + masterdict['Household'] + masterdict['PES'] \ + masterdict['Farm'] + masterdict['Forest']: if coordinate in startinglist: startinglist.remove(coordinate) # Creation of resources (yellow dots in simulation) # These include Fuelwood, Herbs, Bamboo, etc., but right now resource type and frequency are not used if self.grid_type == 'with_humans': for line in _readCSV('hh_survey.csv')[1:]: # see 'hh_survey.csv' hh_id_match = int(line[0]) resource_name = line[1] # frequency is monthly; currently not-used frequency = float(line[2]) / 6 # divided by 6 for 5-day frequency, as opposed to 30-day (1 month) y = int(line[5]) x = int(line[6]) resource = Resource(_readCSV('hh_survey.csv')[1:].index(line), self, (x, y), hh_id_match, resource_name, frequency) self.grid.place_agent(resource, (int(x), int(y))) resource_dict.setdefault(hh_id_match, []).append(resource) if self.run_type == 'first_run': self.saveLoad(resource_dict, 'resource_dict', 'save') # Creation of land parcels land_parcel_count = 0 # individual land parcels in each household (non-gtgp and gtgp) for line in _readCSV('hh_land.csv')[2:]: # exclude headers; for each household: age_1 = float(line[45]) gender_1 = float(line[46]) education_1 = float(line[47]) hh_id = int(line[0]) hh_size = 0 # calculate later total_rice = float(line[41]) if total_rice in [-2, -3, -4]: total_rice = 0 gtgp_rice = float(line[42]) if gtgp_rice in [-2, -3, -4]: gtgp_rice = 0 total_dry = float(line[43]) if total_dry in [-2, -3, -4]: total_dry = 0 gtgp_dry = float(line[44]) if gtgp_dry in [-2, -3, -4]: gtgp_dry = 0 # non_gtgp_area = float(total_rice) + float(total_dry) - float(gtgp_dry) - float(gtgp_rice) # gtgp_area = float(gtgp_dry) + float(gtgp_rice) for i in range(1, 6): # for each household, which has up to 5 each of possible non-GTGP and GTGP parcels: # non_gtgp_area = float(line[i + 47].replace("\"","")) # gtgp_area = float(line[i + 52].replace("\"","")) non_gtgp_area = float(total_rice) + float(total_dry) - float(gtgp_dry) - float(gtgp_rice) gtgp_area = float(gtgp_dry) + float(gtgp_rice) if gtgp_area in [-2, -3, -4]: gtgp_area = 0 if non_gtgp_area in [-2, -3, -4]: non_gtgp_area = 0 if non_gtgp_area > 0: gtgp_enrolled = 0 non_gtgp_output = float(line[i].replace("\"","")) pre_gtgp_output = 0 land_time = float(line[i + 25].replace("\"","")) # non-gtgp travel time plant_type = float(line[i + 10].replace("\"","")) # non-gtgp plant type land_type = float(line[i + 30].replace("\"","")) # non-gtgp land type if land_type not in [-2, -3, -4]: land_parcel_count += 1 if non_gtgp_output in [-3, '-3', -4, '-4']: non_gtgp_output = 0 if pre_gtgp_output in [-3, '-3', -4, '-4']: pre_gtgp_output = 0 lp = Land(land_parcel_count, self, hh_id, gtgp_enrolled, age_1, gender_1, education_1, gtgp_dry, gtgp_rice, total_dry, total_rice, land_type, land_time, plant_type, non_gtgp_output, pre_gtgp_output, hh_size, non_gtgp_area, gtgp_area) self.schedule.add(lp) if gtgp_area > 0: gtgp_enrolled = 1 pre_gtgp_output = 0 non_gtgp_output = float(line[i].replace("\"","")) land_time = float(line[i + 20].replace("\"","")) # gtgp travel time plant_type = float(line[i + 15].replace("\"","")) # gtgp plant type land_type = float(line[i + 35].replace("\"","")) # gtgp land type if land_type not in [-3, '-3', -4, '-4']: land_parcel_count += 1 if non_gtgp_output in [-3, '-3', -4, '-4']: non_gtgp_output = 0 if pre_gtgp_output in [-3, '-3', -4, '-4']: pre_gtgp_output = 0 lp = Land(land_parcel_count, self, hh_id, gtgp_enrolled, age_1, gender_1, education_1, gtgp_dry, gtgp_rice, total_dry, total_rice, land_type, land_time, plant_type, non_gtgp_output, pre_gtgp_output, hh_size, non_gtgp_area, gtgp_area) self.schedule.add(lp) # Creation of humans (brown dots in simulation) self.number_of_humans = 0 self.human_id_count = 0 line_counter = 0 for line in _readCSV('hh_citizens.csv')[1:]: # exclude headers; for each household: hh_id = int(line[0]) line_counter += 1 starting_position = (int(_readCSV('household.csv')[line_counter][4]), int(_readCSV('household.csv')[line_counter][3])) try: resource = random.choice(resource_dict[str(hh_id)]) # random resource point for human resource_position = resource.position resource_frequency = resource.frequency # to travel to, among the list of resource points reported by that household; may change later # to another randomly-picked resource except KeyError: resource_position = starting_position # some households don't collect resources resource_frequency = 0 hh_gender_list = line[1:10] hh_age_list = line[10:19] hh_education_list = line[19:28] hh_marriage_list = line[28:37] # creation of non-migrants for list_item in hh_age_list: if str(list_item) == '-3' or str(list_item) == '': hh_age_list.remove(list_item) for x in range(len(hh_age_list) - 1): person = [] for item in [hh_age_list, hh_gender_list, hh_education_list, hh_marriage_list]: person.append(item[x]) age = float(person[0]) gender = int(person[1]) education = int(person[2]) marriage = int(person[3]) if marriage != 1: marriage = 6 if 15 < age < 59: work_status = 1 elif 7 < age < 15: work_status = 5 else: work_status = 6 mig_years = 0 migration_network = int(line[37]) income_local_off_farm = int(line[57]) resource_check = 0 mig_remittances = int(line[48]) past_hh_id = hh_id migration_status = 0 death_rate = 0 gtgp_part = 0 non_gtgp_area = 0 if str(gender) == '1': if 0 < age <= 10: age_category = 0 elif 10 < age <= 20: age_category = 1 elif 20 < age <= 30: age_category = 2 elif 30 < age <= 40: age_category = 3 elif 40 < age <= 50: age_category = 4 elif 50 < age <= 60: age_category = 5 elif 60 < age <= 70: age_category = 6 elif 70 < age <= 80: age_category = 7 elif 80 < age <= 90: age_category = 8 elif 90 < age: age_category = 9 elif str(gender) != "1": if 0 < age <= 10: age_category = 10 elif 10 < age <= 20: age_category = 11 elif 20 < age <= 30: age_category = 12 elif 30 < age <= 40: age_category = 13 elif 40 < age <= 50: age_category = 14 elif 50 < age <= 60: age_category = 15 elif 60 < age <= 70: age_category = 16 elif 70 < age <= 80: age_category = 17 elif 80 < age <= 90: age_category = 18 elif 90 < age: age_category = 19 children = 0 if gender == 2: if marriage == 1 and age < 45: children = random.randint(0, 4) # might already have kids birth_plan_chance = random.random() if birth_plan_chance < 0.03125: birth_plan = 0 elif 0.03125 <= birth_plan_chance < 0.1875: birth_plan = 1 elif 0.1875 <= birth_plan_chance < 0.5: birth_plan = 2 elif 0.5 <= birth_plan_chance < 0.8125: birth_plan = 3 elif 0.8125 <= birth_plan_chance < 0.96875: birth_plan = 4 else: birth_plan = 5 elif gender != 2: birth_plan = 0 last_birth_time = random.uniform(0, 1) human_demographic_structure_list[age_category] += 1 if str(person[0]) != '' and str(person[0]) != '-3' and str(person[1]) != '-3': # sorts out all blanks self.number_of_humans += 1 self.human_id_count += 1 human = Human(self.human_id_count, self, starting_position, hh_id, age, # creates human resource_check, starting_position, resource_position, resource_frequency, gender, education, work_status, marriage, past_hh_id, mig_years, migration_status, gtgp_part, non_gtgp_area, migration_network, mig_remittances, income_local_off_farm, last_birth_time, death_rate, age_category, children, birth_plan) if self.grid_type == 'with_humans': self.grid.place_agent(human, starting_position) self.schedule.add(human) # creation of migrant hh_migrants = line[38:43] # age, gender, marriage, education of migrants if str(hh_migrants[0]) != '' and str(hh_migrants[0]) != '-3'\ and str(hh_migrants[1]) != '' and str(hh_migrants[1]) != '-3': # if that household has any migrants, create migrant person self.number_of_humans += 1 self.human_id_count += 1 age = float(hh_migrants[0]) gender = float(hh_migrants[1]) education = int(hh_migrants[2]) marriage = int(hh_migrants[3]) mig_years = int(hh_migrants[4]) if 15 < age < 59: work_status = 1 elif 7 < age < 15: work_status = 5 else: work_status = 6 past_hh_id = hh_id hh_id = 'Migrated' migration_status = 1 migration_network = int(line[37]) last_birth_time = random.uniform(0, 1) total_rice = float(line[43]) gtgp_rice = float(line[44]) total_dry = float(line[45]) gtgp_dry = float(line[46]) income_local_off_farm = float(line[57]) if total_rice in ['-3', '-4', -3, None]: total_rice = 0 if total_dry in ['-3', '-4', -3, None]: total_dry = 0 if gtgp_dry in ['-3', '-4', -3, None]: gtgp_dry = 0 if gtgp_rice in ['-3', '-4', -3, None]: gtgp_rice = 0 if (gtgp_dry + gtgp_rice) != 0: gtgp_part = 1 else: gtgp_part = 0 non_gtgp_area = ((total_rice) + (total_dry)) \ - ((gtgp_dry) + (gtgp_rice)) resource_check = 0 mig_remittances = int(line[48]) death_rate = 0 if gender == 1: # human male (monkeys are 0 and 1, humans are 1 and 2) if 0 < age <= 10: age_category = 0 elif 10 < age <= 20: age_category = 1 elif 20 < age <= 30: age_category = 2 elif 30 < age <= 40: age_category = 3 elif 40 < age <= 50: age_category = 4 elif 50 < age <= 60: age_category = 5 elif 60 < age <= 70: age_category = 6 elif 70 < age <= 80: age_category = 7 elif 80 < age <= 90: age_category = 8 elif 90 < age: age_category = 9 elif gender != 1: if 0 < age <= 10: age_category = 10 elif 10 < age <= 20: age_category = 11 elif 20 < age <= 30: age_category = 12 elif 30 < age <= 40: age_category = 13 elif 40 < age <= 50: age_category = 14 elif 50 < age <= 60: age_category = 15 elif 60 < age <= 70: age_category = 16 elif 70 < age <= 80: age_category = 17 elif 80 < age <= 90: age_category = 18 elif 90 < age: age_category = 19 children = 0 if gender == 2: if marriage == 1 and age < 45: children = random.randint(0, 4) # might already have kids birth_plan_chance = random.random() if birth_plan_chance < 0.03125: birth_plan = 0 elif 0.03125 <= birth_plan_chance < 0.1875: birth_plan = 1 elif 0.1875 <= birth_plan_chance < 0.5: birth_plan = 2 elif 0.5 <= birth_plan_chance < 0.8125: birth_plan = 3 elif 0.8125 <= birth_plan_chance < 0.96875: birth_plan = 4 else: birth_plan = 5 elif gender != 2: birth_plan = 0 human_demographic_structure_list[age_category] += 1 human = Human(self.human_id_count, self, starting_position, hh_id, age, # creates human resource_check, starting_position, resource_position, resource_frequency, gender, education, work_status, marriage, past_hh_id, mig_years, migration_status, gtgp_part, non_gtgp_area, migration_network, mig_remittances, income_local_off_farm, last_birth_time, death_rate, age_category, children, birth_plan) if self.grid_type == 'with_humans': self.grid.place_agent(human, starting_position) self.schedule.add(human) # Creation of monkey families (moving agents in the visualization) for i in range(self.number_of_families): # the following code block creates families starting_position = random.choice(startinglist) saved_position = starting_position from families import Family family_size = random.randint(25, 45) # sets family size for each group--random integer family_id = i list_of_family_members = [] family_type = 'traditional' # as opposed to an all-male subgroup split_flag = 0 # binary: 1 means its members start migrating out to a new family family = Family(family_id, self, starting_position, family_size, list_of_family_members, family_type, saved_position, split_flag) self.grid.place_agent(family, starting_position) self.schedule.add(family) global_family_id_list.append(family_id) # Creation of individual monkeys (not in the visualization submodel, but for the demographic submodel) for monkey_family_member in range(family_size): # creates the amount of monkeys indicated earlier id = self.monkey_id_count gender = random.randint(0, 1) if gender == 1: # gender = 1 is female, gender = 0 is male. this is different than with humans (1 or 2) female_list.append(id) last_birth_interval = random.uniform(0, 2) else: male_maingroup_list.append(id) # as opposed to the all-male subgroup last_birth_interval = -9999 # males will never give birth mother = 0 # no parent check for first generation choice = random.random() # 0 - 1 float - age is determined randomly based on weights if choice <= 0.11: # 11% of starting monkey population age = random.uniform(0, 1) # are randomly aged befween age_category = 0 # ages 0-1 demographic_structure_list[0] += 1 elif 0.11 < choice <= 0.27: # 16% of starting monkey population age = random.uniform(1, 3) # are randomly aged befween age_category = 1 # ages 1-3 demographic_structure_list[1] += 1 elif 0.27 < choice <= 0.42: # 15% of starting monkey population age = random.uniform(3, 7) # are randomly aged between age_category = 2 # ages 3-7 demographic_structure_list[2] += 1 elif 0.42 < choice <= 0.62: # 11% of starting monkey population age = random.uniform(7, 10) # are randomly aged befween age_category = 3 # ages 7-10 demographic_structure_list[3] += 1 elif 0.62 < choice <= 0.96: # 34% of starting monkey population age = random.uniform(10, 25) # are randomly aged befween age_category = 4 # ages 10-25 demographic_structure_list[4] += 1 if gender == 1: if id not in reproductive_female_list: reproductive_female_list.append(id) # starting representation of male defection/gender ratio structure_convert = random.random() if gender == 0: if structure_convert < 0.6: gender = 1 last_birth_interval = random.uniform(0, 3) if id not in reproductive_female_list: reproductive_female_list.append(id) elif 0.96 < choice: # 4% of starting monkey population age = random.uniform(25, 30) # are randomly aged between age_category = 5 # ages 25-30 demographic_structure_list[5] += 1 gender = 1 monkey = Monkey(id, self, gender, age, age_category, family, last_birth_interval, mother ) self.number_of_monkeys += 1 self.monkey_id_count += 1 list_of_family_members.append(monkey.unique_id) self.schedule.add(monkey)
class WolfSheepPredation(Model): ''' Wolf-Sheep Predation Model ''' height = 20 width = 20 initial_sheep = 100 initial_wolves = 50 sheep_reproduce = 0.04 wolf_reproduce = 0.05 wolf_gain_from_food = 20 grass = False grass_regrowth_time = 30 sheep_gain_from_food = 4 compGregSheep = 1 compGregWolf = 1 verbose = True # Print-monitoring description = 'A model for simulating wolf and sheep (predator-prey) ecosystem modelling.' def __init__(self, height=20, width=20, initial_sheep=100, initial_wolves=50, sheep_reproduce=0.04, wolf_reproduce=0.05, wolf_gain_from_food=20, grass=False, grass_regrowth_time=30, sheep_gain_from_food=4, compGregSheep=1, compGregWolf=0): ''' Create a new Wolf-Sheep model with the given parameters. Args: initial_sheep: Number of sheep to start with initial_wolves: Number of wolves to start with sheep_reproduce: Probability of each sheep reproducing each step wolf_reproduce: Probability of each wolf reproducing each step wolf_gain_from_food: Energy a wolf gains from eating a sheep grass: Whether to have the sheep eat grass for energy grass_regrowth_time: How long it takes for a grass patch to regrow once it is eaten sheep_gain_from_food: Energy sheep gain from grass, if enabled. ''' super().__init__() # Set parameters self.height = height self.width = width self.initial_sheep = initial_sheep self.initial_wolves = initial_wolves self.sheep_reproduce = sheep_reproduce self.wolf_reproduce = wolf_reproduce self.wolf_gain_from_food = wolf_gain_from_food self.grass = grass self.grass_regrowth_time = grass_regrowth_time self.sheep_gain_from_food = sheep_gain_from_food self.compGregSheep = compGregSheep self.compGregWolf = compGregWolf self.energy_totale = 0 self.schedule = RandomActivationByBreed(self) self.grid = MultiGrid(self.height, self.width, torus=True) self.datacollector = DataCollector({ "Wolves": lambda m: m.schedule.get_breed_count(Wolf), "Sheep": lambda m: m.schedule.get_breed_count(Sheep) }) # Create sheep: for i in range(self.initial_sheep): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.sheep_gain_from_food) self.energy_totale += energy sheep = Sheep(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(sheep, (x, y)) self.schedule.add(sheep) # Create wolves for i in range(self.initial_wolves): x = random.randrange(self.width) y = random.randrange(self.height) energy = random.randrange(2 * self.wolf_gain_from_food) self.energy_totale += energy wolf = Wolf(self.next_id(), (x, y), self, True, energy) self.grid.place_agent(wolf, (x, y)) self.schedule.add(wolf) # Create grass patches if self.grass: for agent, x, y in self.grid.coord_iter(): fully_grown = random.choice([True, False]) if fully_grown: countdown = self.grass_regrowth_time else: countdown = random.randrange(self.grass_regrowth_time) patch = GrassPatch(self.next_id(), (x, y), self, fully_grown, countdown) self.grid.place_agent(patch, (x, y)) self.schedule.add(patch) self.running = True self.datacollector.collect(self) def step(self): self.energy_totale = 0 self.schedule.step() # collect data if self.verbose: result = [ self.schedule.time, self.schedule.get_breed_count(Wolf), self.schedule.get_breed_count(Sheep), self.energy_totale ] fitness = result[3] / (result[1] + result[2]) print('fitness:', fitness) return (fitness) def run_model(self, step_count=200): if self.verbose: print('Initial number wolves: ', self.schedule.get_breed_count(Wolf)) print('Initial number sheep: ', self.schedule.get_breed_count(Sheep)) for i in range(step_count): self.step() if self.verbose: print('') print('Final number wolves: ', self.schedule.get_breed_count(Wolf)) print('Final number sheep: ', self.schedule.get_breed_count(Sheep)) print('energie totale:', self.energy_totale)
def __init__(self, spawnrate, tactic, offset, cycletime): # Variable parameters self.tactic = tactic # [ Offset, Proportional, Lookahead, GreenWave] self.spawnrate = spawnrate self.offset = offset self.slowmotionrate = 0.2 self.cycletime = cycletime # Value initializations self.emission = [0, 0, 0] # emission per step self.traveltime = [] self.averagetraveltime = 0 self.carID = 0 self.averageemission = [] # Reading roadmap and emission values self.emissionvalues = reademissionvalues() [ self.roadmap, self.spawns, self.lights, self.height, self.cellsperlane, self.intersections, self.streetlength, self.gridsize, ] = readroadmap() # Model and visualization parameters self.schedule = RandomActivation(self) self.width = self.height self.grid = MultiGrid(self.width, self.height, True) self.running = True # Initializing matrix which shows what cars in front of traffic lights go to what over traffic lights. self.tlightmatrix = np.empty((len(self.lights), len(self.lights))) self.tlightmatrix[:] = np.nan self.trafficlightlist = [] self.lightcombinations = [ ["SR", "SD", "SL", "WR"], ["ER", "ED", "EL", "SR"], ["NR", "ND", "NL", "ER"], ["WR", "WD", "WL", "NR"], ] # Data collection self.datacollector = DataCollector( model_reporters={ "tactic": "tactic", "Spawnrate": "spawnrate", "Offset": "offset", "Cycletime": "cycletime", "AverageTraveltime": "averagetraveltime", "Totalcars": lambda m: self.numberofcars(), "CO2": lambda m: self.getco2(), "NOx": lambda m: self.getnox(), "PM10": lambda m: self.getpm(), "AverageCO2": lambda m: self.getaverageco2(), "AverageNOx": lambda m: self.getaveragenox(), "AveragePM": lambda m: self.getaveragepm(), }, ) # Needed for green wave tactic self.mostcars = [] self.goesto = [] self.firstgreenintersection = -1 self.secondgreenintersection = -1 self.firstcombination = None self.secondcombination = None self.firstcycledone = 0 # Needed for lookahead tactic self.mostexpectedcars = [0, 0, 0] # cars,intersection,combination # results in list of lists with intersectionnumbers in the right place, e.g.: [[0, 1],[2,3]] # Needed for the offset tactic to know which lights to offset self.intersectionmatrix = [] lastnumber = 0 for i in range(int(math.sqrt(self.intersections))): tempmaptrix = [] for j in range(int(math.sqrt(self.intersections))): tempmaptrix.append(j + lastnumber) lastnumber = tempmaptrix[-1] + 1 self.intersectionmatrix.append(tempmaptrix) self.intersectionmatrix = np.array(self.intersectionmatrix) # Initialize information dictionary (which lights are suppesed to be green and how long they have been green for self.trafficlightinfo = {} for i in range(self.intersections): self.trafficlightinfo.update( {f"intersection{i}": {"Trafficlightinfo": {}, "Timeinfo": {}}} ) # Initializes traffic lights for i, light in enumerate(self.lights): self.trafficlightinfo[f"intersection{light[1][3]}"]["Trafficlightinfo"][ f"{light[1][1:3]}" ] = i self.trafficlightinfo[f"intersection{light[1][3]}"]["Timeinfo"].update( { "Currentgreen": -1, "Currenttimegreen": 0, "Maxtimegreen": 0, "Allred": 1, } ) intersectionnumber = int(light[1][3]) intersectiony = np.where(self.intersectionmatrix == intersectionnumber)[0] intersectionx = np.where(self.intersectionmatrix == intersectionnumber)[1] direction = light[1][1] lane = light[1][2] location = light[0] xlocation = int(location[0]) ylocation = self.height - 1 - int(location[1]) trafficlight = TrafficLightAgent( f"{xlocation},{ylocation},{light[1][1:3]}", self, "red", direction, lane, i, intersectionnumber, self.tactic, self.offset, [intersectionx, intersectiony], self.cycletime, ) self.trafficlightlist.append([light[1], i]) self.schedule.add(trafficlight) self.grid.place_agent(trafficlight, (xlocation, ylocation)) self.tlightmatrix = lightconnection( self.tlightmatrix, self.trafficlightlist, self.intersections ) # Place legend self.grid.place_agent(LegendCarIcon("Caricon", self), (65, 68)) self.grid.place_agent(LegendGreenTlightIcon("GreenTlighticon", self), (65, 69)) self.grid.place_agent(LegendRedTlightIcon("RedTlighticon", self), (65, 70))
class Themepark(Model): def __init__(self, N_attr, N_cust, width, height, strategy, theme, max_time, weight, adaptive): self.theme = theme self.max_time = max_time self.N_attr = N_attr self.penalty_per = PENALTY_PERCENTAGE self.weight = weight self.adaptive = adaptive self.strategies = STRATEGIES self.x_list, self.y_list, self.positions = xlist, ylist, positions self.x_list, self.y_list, self.positions = get_attraction_coordinates(WIDTH, HEIGHT, self.N_attr, theme) self.happinesses = [] self.starting_positions = [[int((WIDTH/2)-1), 0], [int(WIDTH/2), 0], [int((WIDTH/2)+1), 0]] self.path_coordinates = get_coordinates(WIDTH, HEIGHT, NUM_OBSTACLES, self.N_attr, theme) self.N_attr = N_attr # num of attraction agents self.N_cust = N_cust # num of customer agents self.width = width self.height = height self.total_steps = 0 self.cust_ids = N_cust self.strategy = strategy self.grid = MultiGrid(width, height, torus=False) self.schedule = BaseScheduler(self) self.schedule_Attraction = BaseScheduler(self) self.schedule_Customer = BaseScheduler(self) self.totalTOTAL = 0 self.attractions = self.make_attractions() self.attraction_history = self.make_attr_hist() self.running = True self.data = [] self.data_customers = [] self.park_score = [] self.data_dict = {} self.hist_random_strat = [] self.hist_close_strat = [] self.all_rides_list = [] self.strategy_composition = self.make_strategy_composition() self.memory = 5 self.customer_score = [] self.customers = self.add_customers(self.N_cust) self.only_random = False for attraction in self.get_attractions(): self.data_dict[attraction.unique_id] = ({ "id": attraction.unique_id, "length": attraction.attraction_duration, "waiting_list": []}) if len(self.strategies) == 6: self.datacollector = DataCollector( {"Random": lambda m: self.strategy_counter(self.strategies[0]), "0.00": lambda m: self.strategy_counter(self.strategies[1]), "0.25": lambda m: self.strategy_counter(self.strategies[2]), "0.50": lambda m: self.strategy_counter(self.strategies[3]), "0.75": lambda m: self.strategy_counter(self.strategies[4]), "1.00": lambda m: self.strategy_counter(self.strategies[5]), }) else: self.datacollector = DataCollector( {"0.00": lambda m: self.strategy_counter(self.strategies[0]), "0.25": lambda m: self.strategy_counter(self.strategies[1]), "0.50": lambda m: self.strategy_counter(self.strategies[2]), "0.75": lambda m: self.strategy_counter(self.strategies[3]), "1.00": lambda m: self.strategy_counter(self.strategies[4]), }) self.datacollector2 = DataCollector( {"score": lambda m: self.make_score()}) self.total_waited_time = 0 self.monitor = Monitor(self.max_time, self.N_attr, self.positions) def make_score(self): ideal = {} cust_in_row = 0 for i in range(len(self.get_attractions())): ideal[i] = self.N_cust/self.N_attr cust_in_row += self.get_attractions()[i].N_current_cust tot_difference = 0 for i in range(len(self.get_attractions())): difference = abs(cust_in_row/self.N_attr - self.get_attractions()[i].N_current_cust) tot_difference += difference fraction_not_right = (tot_difference/self.N_cust) return abs(1-(fraction_not_right)) * cust_in_row/self.N_cust def make_attr_hist(self): attraction_history = {} for attraction in self.get_attractions(): attraction_history[attraction] = [0] * (self.max_time + 1) return attraction_history def strategy_counter(self, strategy): counter_total = {} for attraction_pos in self.positions: agents = self.grid.get_neighbors( attraction_pos, moore=True, radius=0, include_center=True ) counter = 0 for agent in self.customers: if agent.weight == strategy: counter += 1 return counter def make_strategy_composition(self): if self.strategy == "Random_test_4": self.strategies = ["Random_test_4", 0.0, 0.25, 0.50, 0.75, 1.0] dict = {self.strategies[0]: 1/6, self.strategies[1]:0.20, self.strategies[2]:0.20, self.strategies[3]:0.20, self.strategies[4]:0.20, self.strategies[5]: 0.20} composition_list = [] for i in range(len(self.strategies)): if i == 0: dict[self.strategies[i]] = FRACTION_RANDOM continue else: composition_list.append(random.randint(0,100)) sum_comp = sum(composition_list) sum_comp = sum_comp - sum_comp * FRACTION_RANDOM for i in range(len(self.strategies)): if i == 0: continue else: dict[self.strategies[i]] = composition_list[i-1] /sum_comp else: dict = {self.strategies[0]: 0.20, self.strategies[1]:0.20, self.strategies[2]:0.20, self.strategies[3]:0.20, self.strategies[4]:0.20} composition_list = [] for i in range(len(self.strategies)): composition_list.append(random.randint(0,100)) sum_comp = sum(composition_list) sum_comp = sum_comp for i in range(len(self.strategies)): dict[self.strategies[i]] = composition_list[i-1] /sum_comp return dict def make_attractions(self): """ Initialize attractions on fixed position.""" attractions = {} for i in range(self.N_attr): pos = (self.x_list[i], self.y_list[i]) if self.grid.is_cell_empty(pos): name = str(i) a = Attraction(i, self, pos, name, self.N_cust, self.weight) attractions[i] = a self.schedule_Attraction.add(a) self.grid.place_agent(a, pos) return attractions def get_attractions(self): """ Get a list with all attractions """ agents = self.grid.get_neighbors( mid_point, moore=True, radius=RADIUS, include_center=True) attractions = [] for agent in agents: if type(agent) == Attraction: attractions.append(agent) return attractions def add_customers(self, N_cust, added=False): """ Initialize customers on random positions.""" weights_list = [] if self.adaptive is True: for j in self.strategy_composition.keys(): for i in range(round(N_cust*self.strategy_composition[j])): weights_list.append(j) if len(weights_list) < self.N_cust: rand = random.choice(self.strategies) weights_list.append(rand) elif len(weights_list) > self.N_cust: rand = random.choice(weights_list) weights_list.remove(rand) else: if self.strategy is not "Random": # do what normally is done for i in range(round(N_cust)): weights_list.append(self.weight) cust_list = [] # weight_counter = 0 # pick_weight = 0 for i in range(N_cust): # pos_temp = random.choice(self.starting_positions) pos_temp = [random.randint(0,WIDTH-1), random.randint(0,HEIGHT-1)] rand_x, rand_y = pos_temp[0], pos_temp[1] pos = (rand_x, rand_y) if added is True: i = self.cust_ids if self.strategy == "Random_test_4": if weights_list[i] == "Random_test_4": strategy = "Random_test_4" else: strategy = "Closest_by" else: strategy = self.strategy # Deze if is omdat bij alleen random self.weight none is! if weights_list == []: weight = None else: weight = weights_list[i] a = Customer(i, self, pos, self.x_list, self.y_list, self.positions, strategy, weight, self.adaptive) self.schedule_Customer.add(a) self.grid.place_agent(a, pos) cust_list.append(a) return cust_list def calculate_people(self): """Calculate how many customers are in which attraction.""" counter_total = {} for attraction_pos in self.positions: agents = self.grid.get_neighbors( attraction_pos, moore=True, radius=0, include_center=True ) counter = 0 for agent in agents: if type(agent) is Customer: counter += 1 else: attraction = agent attraction.N_current_cust = counter counter_total[attraction.unique_id] = counter return list(counter_total.values()) def calc_waiting_time(self): counter_total = {} attractions = self.get_attractions() for attraction in attractions: counter_total[attraction.unique_id] = attraction.current_waitingtime return counter_total def calculate_people_sorted(self): """ Calculate how many customers are in which attraction. Returns a SORTED LIST. For example: indexes = [3, 2, 5, 1, 4] indicates that attraction3 has the least people waiting. """ counter_total = {} for attraction_pos in self.positions: agents = self.grid.get_neighbors( attraction_pos, moore=True, radius=0, include_center=True ) counter = 0 for agent in agents: if type(agent) is Customer: counter += 1 else: attraction = agent attraction.N_current_cust = counter self.attraction_history[attraction][self.totalTOTAL] = counter counter_total[attraction.unique_id] = counter return counter_total def make_route(self): """Draw coordinates of a possible path.""" for i in range(len(self.path_coordinates)): pos = self.path_coordinates[i] if pos not in self.positions: # Create path agent path = Route(i, self, pos) self.schedule.add(path) self.grid.place_agent(path, pos) def get_themepark_score(self): """ Get score of a themepark based on: - A total of all waitingtimes for every customer - TODO """ attractions = self.get_attractions() total_wait, total_rides = 0, 0 for attraction in attractions: total_wait += attraction.current_waitingtime if attraction.current_a is not None: total_rides += 1 if total_rides == 0: return total_rides return (total_wait / total_rides) def get_strategy_history(self): """ Update history with how many customers chose which strategy """ customers = self.get_customers() randomstrat, closebystrat = 0, 0 for customer in customers: if customer.strategy == "Random" or customer.strategy == "Random_test_4": randomstrat += 1 elif customer.strategy == "Closest_by": closebystrat += 1 self.hist_random_strat.append(randomstrat) self.hist_close_strat.append(closebystrat) def get_customers(self): agents = self.grid.get_neighbors( mid_point, moore=True, radius=RADIUS, include_center=True) customers = [] # Count customer agents for agent in agents: if type(agent) == Customer: customers.append(agent) return customers def get_data_customers(self): """ Return dictionary with data of customers """ data = {} agents = self.grid.get_neighbors( mid_point, moore=True, radius=RADIUS, include_center=True) for agent in agents: if type(agent) is Customer: data[agent.unique_id] = { "totalwaited": agent.total_ever_waited, "visited_attractions": agent.nmbr_attractions, "strategy": agent.strategy, "swapped_strat": agent.strategy_swap_hist } return data def calc_hapiness(self): """ Calculate mean hapiness of all customers, based on: - How many rides were taken - Number of times in the same attraction - Total waiting time """ customers = self.get_customers() scores = [] for customer in customers: history = customer.history values = list(history.values()) total_rides = sum(values) if total_rides != 0: scores.append(total_rides / self.N_attr - self.totalTOTAL / customer.total_ever_waited) else: return None scores = np.interp(scores, (min(scores), max(scores)), (1, 10)) return np.mean(scores) def get_history_list(self): customers = self.get_customers() histories = {} for customer in customers: history = customer.history values = list(history.values()) histories[customer.unique_id] = values return histories def final(self): """ Return data """ hist_list = [] agents = self.grid.get_neighbors( mid_point, moore=True, radius=RADIUS, include_center=True) attractions = self.get_attractions() self.all_rides_list = [0] * len(attractions[0].in_attraction_list) for attraction in attractions: for i in range(len(attraction.in_attraction_list)): self.all_rides_list[i] += attraction.in_attraction_list[i] for i in range(len(self.all_rides_list)): self.all_rides_list[i] /= self.N_attr print("ALL RIDES LIST", self.all_rides_list) cust_data = self.get_data_customers() for agent in agents: if type(agent) is Customer: sum_attr = sum(agent.history.values()) if sum_attr > 0: hist_list.append(agent.strategy_swap_hist) else: hist_list.append(agent.strategy_swap_hist) # print("swap:",agent.strategy_swap_hist , "sum:",sum_attr) # plt.hist(hist_list) # plt.show() histories = self.get_history_list() # save data try: pickle.dump(self.datacollector.get_model_vars_dataframe(), open("../data/strategy_history.p", 'wb')) pickle.dump(self.datacollector2.get_model_vars_dataframe(), open("../data/eff_score_history.p", 'wb')) pickle.dump(cust_data, open("../data/customers.p", 'wb')) pickle.dump(self.park_score[-1], open("../data/park_score.p", "wb")) pickle.dump(self.happinesses, open("../data/hapiness.p", "wb")) pickle.dump(histories, open("../data/cust_history.p", 'wb')) except: pickle.dump(self.datacollector.get_model_vars_dataframe(), open("data/strategy_history.p", 'wb')) pickle.dump(self.datacollector2.get_model_vars_dataframe(), open("data/eff_score_history.p", 'wb')) pickle.dump(cust_data, open("data/customers.p", 'wb')) pickle.dump(self.park_score[-1], open("data/park_score.p", "wb")) pickle.dump(self.happinesses, open("data/hapiness.p", "wb")) pickle.dump(histories, open("data/cust_history.p", 'wb')) try: pickle.dump(self.all_rides_list, open("../data/all_rides.p", "wb")) except: pickle.dump(self.all_rides_list, open("data/all_rides.p", "wb")) print() print("RUN HAS ENDED") print() def save_data(self): """Save data of all attractions and customers.""" # Get info waitinglines = self.calc_waiting_time() for i in range(len(self.attractions)): self.data_dict[i]["waiting_list"].append(waitinglines.get(i)) self.park_score.append(sum(waitinglines.values())) self.happinesses.append(self.calc_hapiness()) def step(self): """Advance the model by one step.""" if self.totalTOTAL < self.max_time: self.totalTOTAL += 1 self.schedule.step() self.datacollector.collect(self) self.datacollector2.collect(self) self.schedule_Attraction.step() self.schedule_Customer.step() # update memory of attractions # attractions = self.get_attractions() # for attraction in attractions: # attraction.update_memory() self.total_steps += 1 self.save_data() self.get_strategy_history() else: for key in self.attraction_history.keys(): y = self.attraction_history[key] x = list(range(0, self.max_time)) self.final()