Exemplo n.º 1
1
class ForestFire(Model):
    '''
    Simple Forest Fire model.
    '''
    def __init__(self, height, width, density):
        '''
        Create a new forest fire model.

        Args:
            height, width: The size of the grid to model
            density: What fraction of grid cells have a tree in them.
        '''
        # Initialize model parameters
        self.height = height
        self.width = width
        self.density = density

        # Set up model objects
        self.schedule = RandomActivation(self)
        self.grid = Grid(height, width, torus=False)

        self.datacollector = DataCollector(
            {"Fine": lambda m: self.count_type(m, "Fine"),
             "On Fire": lambda m: self.count_type(m, "On Fire"),
             "Burned Out": lambda m: self.count_type(m, "Burned Out")})

        # Place a tree in each cell with Prob = density
        for (contents, x, y) in self.grid.coord_iter():
            if random.random() < self.density:
                # Create a tree
                new_tree = TreeCell((x, y))
                # Set all trees in the first column on fire.
                if x == 0:
                    new_tree.condition = "On Fire"
                self.grid._place_agent((x, y), new_tree)
                self.schedule.add(new_tree)
        self.running = True

    def step(self):
        '''
        Advance the model by one step.
        '''
        self.schedule.step()
        self.datacollector.collect(self)

        # Halt if no more fire
        if self.count_type(self, "On Fire") == 0:
            self.running = False

    @staticmethod
    def count_type(model, tree_condition):
        '''
        Helper method to count trees in a given condition in a given model.
        '''
        count = 0
        for tree in model.schedule.agents:
            if tree.condition == tree_condition:
                count += 1
        return count
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
class BoltzmannWealthModelNetwork(Model):
    """A model with some number of agents."""

    def __init__(self, num_agents=7, num_nodes=10):

        self.num_agents = num_agents
        self.num_nodes = num_nodes if num_nodes >= self.num_agents else self.num_agents
        self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=0.5)
        self.grid = NetworkGrid(self.G)
        self.schedule = RandomActivation(self)
        self.datacollector = DataCollector(
            model_reporters={"Gini": compute_gini},
            agent_reporters={"Wealth": lambda _: _.wealth}
        )

        list_of_random_nodes = self.random.sample(self.G.nodes(), self.num_agents)

        # Create agents
        for i in range(self.num_agents):
            a = MoneyAgent(i, self)
            self.schedule.add(a)
            # Add the agent to a random node
            self.grid.place_agent(a, list_of_random_nodes[i])

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)

    def run_model(self, n):
        for i in range(n):
            self.step()
Exemplo n.º 4
0
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()
Exemplo n.º 5
0
class SchellingModel(Model):
    '''
    Model class for the Schelling segregation model.
    '''

    def __init__(self, height, width, density, minority_pc, homophily):
        '''
        '''

        self.height = height
        self.width = width
        self.density = density
        self.minority_pc = minority_pc
        self.homophily = homophily

        self.schedule = RandomActivation(self)
        self.grid = Grid(height, width, torus=True)

        self.happy = 0
        self.datacollector = DataCollector(
            {"happy": lambda m: m.happy}, # Model-level count of happy agents
            # For testing purposes, agent's individual x and y
            {"x": lambda a: a.x, "y": lambda a: a.y}) 

        self.running = True

        # Set up agents
        for x in range(self.width):
            for y in range(self.height):
                if random.random() < self.density:
                    if random.random() < self.minority_pc:
                        agent_type = 1
                    else:
                        agent_type = 0

                    agent = SchellingAgent((x,y), x, y, agent_type)
                    self.grid[y][x] = agent
                    self.schedule.add(agent)

    def get_empty(self):
        '''
        Get a list of coordinate tuples of currently-empty cells.
        '''
        empty_cells = []
        for x in range(self.width):
            for y in range(self.height):
                if self.grid[y][x] is None:
                    empty_cells.append((x, y))
        return empty_cells

    def step(self):
        '''
        Run one step of the model. If All agents are happy, halt the model.
        '''
        self.happy = 0 # Reset counter of happy agents
        self.schedule.step()
        self.datacollector.collect(self)

        if self.happy == self.schedule.get_agent_count():
            self.running = False
Exemplo n.º 6
0
class WorldModel(Model):
    def __init__(self, N, width, height):
        self.grid = SingleGrid(height, width, True)

        self.schedule = RandomActivation(self)
        self.num_agents = N
        self.running = True
        
        for i in range(self.num_agents):
            ethnicity = random.choice(Ethnicities)
            a = PersonAgent(unique_id=i,
                            model=self,
                            ethnicity=int(ethnicity)
                            )
            self.schedule.add(a)
            # Add the agent to a random grid cell

            self.grid.position_agent(a)
            
        self.datacollector = DataCollector(
            agent_reporters={
                "Nationalism": lambda a: a.nationalism,
                "X": lambda a: a.pos[0],
                "Y": lambda a: a.pos[1]
            }
        )

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
Exemplo n.º 7
0
Arquivo: model.py Projeto: GeoESW/mesa
class ShapesModel(Model):
    def __init__(self, N, width=20, height=10):
        self.running = True
        self.N = N    # num of agents
        self.headings = ((1, 0), (0, 1), (-1, 0), (0, -1))  # tuples are fast
        self.grid = SingleGrid(width, height, torus=False)
        self.schedule = RandomActivation(self)
        self.make_walker_agents()

    def make_walker_agents(self):
        unique_id = 0
        while True:
            if unique_id == self.N:
                break
            x = random.randrange(self.grid.width)
            y = random.randrange(self.grid.height)
            pos = (x, y)
            heading = random.choice(self.headings)
            # heading = (1, 0)
            if self.grid.is_cell_empty(pos):
                print("Creating agent {2} at ({0}, {1})"
                      .format(x, y, unique_id))
                a = Walker(unique_id, self, pos, heading)
                self.schedule.add(a)
                self.grid.place_agent(a, pos)
                unique_id += 1

    def step(self):
        self.schedule.step()
Exemplo n.º 8
0
Arquivo: model.py Projeto: GeoESW/mesa
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 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)
Exemplo n.º 10
0
class Foraging(Model):
    
    number_of_bean = 0
    number_of_corn = 0
    number_of_soy = 0
    
    def __init__(self, width=50, height=50, torus=True, num_bug=50, seed=42, strategy=None):
        super().__init__(seed=seed)
        self.number_of_bug = num_bug
        if not(strategy in ["stick", "switch"]):
            raise TypeError("'strategy' must be one of {stick, switch}")
        self.strategy = strategy
        
        self.grid = SingleGrid(width, height, torus)
        self.schedule = RandomActivation(self)
        data = {"Bean": lambda m: m.number_of_bean,
                "Corn": lambda m: m.number_of_corn,
                "Soy": lambda m: m.number_of_soy,
                "Bug": lambda m: m.number_of_bug,
                }
        self.datacollector = DataCollector(data)
        
        # create foods
        self._populate(Bean)
        self._populate(Corn)
        self._populate(Soy)
        
        # create bugs
        for i in range(self.number_of_bug):
            pos = self.grid.find_empty()
            bug = Bug(i, self)
            bug.strategy = self.strategy
            self.grid.place_agent(bug, pos)
            self.schedule.add(bug)
    
    def step(self):
        self.schedule.step()
        self.datacollector.collect(self)
        
        if not(self.grid.exists_empty_cells()):
            self.running = False
    
    def _populate(self, food_type):
        prefix = "number_of_{}"
        
        counter = 0
        while counter < food_type.density * (self.grid.width * self.grid.height):
            pos = self.grid.find_empty()
            food = food_type(counter, self)
            self.grid.place_agent(food, pos)
            self.schedule.add(food)
            food_name = food_type.__name__.lower()
            attr_name = prefix.format(food_name)
            val = getattr(self, attr_name)
            val += 1
            setattr(self, attr_name, val)
            counter += 1
Exemplo n.º 11
0
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()
Exemplo n.º 12
0
class Schelling(Model):
    '''
    Model class for the Schelling segregation model.
    '''

    def __init__(self, height=20, width=20, density=0.8, minority_pc=0.2, homophily=3):
        '''
        '''

        self.height = height
        self.width = width
        self.density = density
        self.minority_pc = minority_pc
        self.homophily = homophily

        self.schedule = RandomActivation(self)
        self.grid = SingleGrid(height, width, torus=True)

        self.happy = 0
        self.datacollector = DataCollector(
            {"happy": "happy"},  # Model-level count of happy agents
            # For testing purposes, agent's individual x and y
            {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]})

        # Set up agents
        # We use a grid iterator that returns
        # the coordinates of a cell as well as
        # its contents. (coord_iter)
        for cell in self.grid.coord_iter():
            x = cell[1]
            y = cell[2]
            if self.random.random() < self.density:
                if self.random.random() < self.minority_pc:
                    agent_type = 1
                else:
                    agent_type = 0

                agent = SchellingAgent((x, y), self, agent_type)
                self.grid.position_agent(agent, (x, y))
                self.schedule.add(agent)

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        '''
        Run one step of the model. If All agents are happy, halt the model.
        '''
        self.happy = 0  # Reset counter of happy agents
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)

        if self.happy == self.schedule.get_agent_count():
            self.running = False
Exemplo n.º 13
0
Arquivo: model.py Projeto: GeoESW/mesa
class BoidModel(Model):
    '''
    Flocker model class. Handles agent creation, placement and scheduling.
    '''

    def __init__(self,
                 population=100,
                 width=100,
                 height=100,
                 speed=1,
                 vision=10,
                 separation=2,
                 cohere=0.025,
                 separate=0.25,
                 match=0.04):
        '''
        Create a new Flockers model.

        Args:
            population: Number of Boids
            width, height: Size of the space.
            speed: How fast should the Boids move.
            vision: How far around should each Boid look for its neighbors
            separation: What's the minimum distance each Boid will attempt to
                    keep from any other
            cohere, separate, match: factors for the relative importance of
                    the three drives.        '''
        self.population = population
        self.vision = vision
        self.speed = speed
        self.separation = separation
        self.schedule = RandomActivation(self)
        self.space = ContinuousSpace(width, height, True,
                                     grid_width=10, grid_height=10)
        self.factors = dict(cohere=cohere, separate=separate, match=match)
        self.make_agents()
        self.running = True

    def make_agents(self):
        '''
        Create self.population agents, with random positions and starting headings.
        '''
        for i in range(self.population):
            x = random.random() * self.space.x_max
            y = random.random() * self.space.y_max
            pos = np.array((x, y))
            velocity = np.random.random(2) * 2 - 1
            boid = Boid(i, self, pos, self.speed, velocity, self.vision,
                        self.separation, **self.factors)
            self.space.place_agent(boid, pos)
            self.schedule.add(boid)

    def step(self):
        self.schedule.step()
Exemplo n.º 14
0
class SchellingModel(Model):
    """
    Model class for the Schelling segregation model.
    """

    def __init__(self, height, width, density, minority_pc, homophily):
        """
        """

        self.height = height
        self.width = width
        self.density = density
        self.minority_pc = minority_pc
        self.homophily = homophily

        self.schedule = RandomActivation(self)
        self.grid = SingleGrid(height, width, torus=True)

        self.happy = 0
        self.total_agents = 0
        self.datacollector = DataCollector(
            {"unhappy": lambda m: m.total_agents - m.happy},
            # For testing purposes, agent's individual x and y
            {"x": lambda a: a.pos[X], "y": lambda a: a.pos[Y]},
        )

        self.running = True

        # Set up agents
        # We use a grid iterator that returns
        # the coordinates of a cell as well as
        # its contents. (coord_iter)
        for cell, x, y in self.grid.coord_iter():
            if random.random() < self.density:
                if random.random() < self.minority_pc:
                    agent_type = 1
                else:
                    agent_type = 0

                agent = SchellingAgent(self.total_agents, agent_type)
                self.grid.position_agent(agent, x, y)
                self.schedule.add(agent)
                self.total_agents += 1

    def step(self):
        """
        Run one step of the model. If All agents are happy, halt the model.
        """
        self.happy = 0  # Reset counter of happy agents
        self.schedule.step()
        self.datacollector.collect(self)

        if self.happy == self.total_agents:
            self.running = False
Exemplo n.º 15
0
class MoneyModel(Model):
    """A model with some number of agents."""
    def __init__(self, N):
        self.num_agents = N
        self.schedule = RandomActivation(self)
        # Create agents
        for i in range(self.num_agents):
            a = MoneyAgent(i)
            self.schedule.add(a)

    def step(self):
        '''Advance the model by one step.'''
        self.schedule.step()
Exemplo n.º 16
0
class InspectionModel(Model):
    '''
    Simple Restaurant Inspection model.
    '''
    def __init__(self, height, width, density):
        '''
        Create a new restaurant inspection model.

        Args:
            height, width: The size of the grid to model
            density: What fraction of grid cells have a restaurant in them.
        '''
        # Initialize model parameters
        self.height = height
        self.width = width
        self.density = density

        # Set up model objects
        self.schedule = RandomActivation(self)
        self.grid = Grid(height, width, torus=False)

        self.datacollector = DataCollector(
            {"Good": lambda m: self.count_type(m, "Good"),
             "Bad": lambda m: self.count_type(m, "Bad")})

        # Place a restaurant in each cell with Prob = density
        for (contents, x, y) in self.grid.coord_iter():
            if random.random() < self.density:
                # Create a restaurant
                new_restaurant = RestaurantCell((x, y))
                self.grid._place_agent((x, y), new_restaurant)
                self.schedule.add(new_restaurant)
        self.running = True

    def step(self):
        '''
        Advance the model by one step.
        '''
        self.schedule.step()
        self.datacollector.collect(self)

    @staticmethod
    def count_type(model, restaurant_hygiene):
        '''
        Helper method to count restaurants in a given condition in a given model.
        '''
        count = 0
        for restaurant in model.schedule.agents:
            if restaurant.hygiene == restaurant_hygiene and restaurant.rating != 'Closed':
                count += 1
        return count
Exemplo n.º 17
0
class VirusOnNetwork(Model):
    """A virus model with some number of agents"""

    def __init__(self, num_nodes=10, avg_node_degree=3, initial_outbreak_size=1, virus_spread_chance=0.4,
                virus_check_frequency=0.4, recovery_chance=0.3, gain_resistance_chance=0.5):

        self.num_nodes = num_nodes
        prob = avg_node_degree / self.num_nodes
        self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
        self.grid = NetworkGrid(self.G)
        self.schedule = RandomActivation(self)
        self.initial_outbreak_size = initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes
        self.virus_spread_chance = virus_spread_chance
        self.virus_check_frequency = virus_check_frequency
        self.recovery_chance = recovery_chance
        self.gain_resistance_chance = gain_resistance_chance

        self.datacollector = DataCollector({"Infected": number_infected,
                                            "Susceptible": number_susceptible,
                                            "Resistant": number_resistant})

        # Create agents
        for i, node in enumerate(self.G.nodes()):
            a = VirusAgent(i, self, State.SUSCEPTIBLE, self.virus_spread_chance, self.virus_check_frequency,
                           self.recovery_chance, self.gain_resistance_chance)
            self.schedule.add(a)
            # Add the agent to the node
            self.grid.place_agent(a, node)

        # Infect some nodes
        infected_nodes = self.random.sample(self.G.nodes(), self.initial_outbreak_size)
        for a in self.grid.get_cell_list_contents(infected_nodes):
            a.state = State.INFECTED

        self.running = True
        self.datacollector.collect(self)

    def resistant_susceptible_ratio(self):
        try:
            return number_state(self, State.RESISTANT) / number_state(self, State.SUSCEPTIBLE)
        except ZeroDivisionError:
            return math.inf

    def step(self):
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)

    def run_model(self, n):
        for i in range(n):
            self.step()
Exemplo n.º 18
0
class SchellingModel(Model):
    '''
    Model class for the Schelling segregation model.
    '''

    def __init__(self, height, width, density, type_pcs=[.2, .2, .2, .2, .2]):
        '''
        '''

        self.height = height
        self.width = width
        self.density = density
        self.type_pcs = type_pcs

        self.schedule = RandomActivation(self)
        self.grid = SingleGrid(height, width, torus=False)

        self.happy = 0
        self.datacollector = DataCollector(
            {"happy": lambda m: m.happy},  # Model-level count of happy agents
            # For testing purposes, agent's individual x and y
            {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]})

        self.running = True

        # Set up agents
        # We use a grid iterator that returns
        # the coordinates of a cell as well as
        # its contents. (coord_iter)

        total_agents = self.height * self.width * self.density
        agents_by_type = [total_agents*val for val in self.type_pcs]

        for loc, types in enumerate(agents_by_type):
            for i in range(int(types)):
                pos = self.grid.find_empty()
                agent = SchellingAgent(pos, self, loc)
                self.grid.position_agent(agent, pos)
                self.schedule.add(agent)

    def step(self):
        '''
        Run one step of the model. If All agents are happy, halt the model.
        '''
        self.happy = 0  # Reset counter of happy agents
        self.schedule.step()
        self.datacollector.collect(self)

        if self.happy == self.schedule.get_agent_count():
            self.running = False
Exemplo n.º 19
0
class BoidModel(Model):
    '''
    Flocker model class. Handles agent creation, placement and scheduling.
    '''
    N = 100
    width = 100
    height = 100

    def __init__(self, N, width, height, speed, vision, separation):
        '''
        Create a new Flockers model.

        Args:
            N: Number of Boids
            width, height: Size of the space.
            speed: How fast should the Boids move.
            vision: How far around should each Boid look for its neighbors
            separtion: What's the minimum distance each Boid will attempt to
                       keep from any other
        '''
        self.N = N
        self.vision = vision
        self.speed = speed
        self.separation = separation
        self.schedule = RandomActivation(self)
        self.space = ContinuousSpace(width, height, True,
            grid_width=10, grid_height=10)
        self.make_agents()
        self.running = True

    def make_agents(self):
        '''
        Create N agents, with random positions and starting headings.
        '''
        for i in range(self.N):
            x = random.random() * self.space.x_max
            y = random.random() * self.space.y_max
            pos = (x, y)
            heading = np.random.random(2) * 2 - np.array((1, 1))
            heading /= np.linalg.norm(heading)
            boid = Boid(i, pos, self.speed, heading, self.vision, self.separation)
            self.space.place_agent(boid, pos)
            self.schedule.add(boid)

    def step(self):
        self.schedule.step()
class MoneyModel(Model):
    """A model with some number of agents."""
    def __init__(self, N):
        self.running = True
        self.num_agents = N
        self.schedule = RandomActivation(self)
        self.create_agents()
        agent_reporters = {"Wealth": lambda a: a.wealth}
        model_reporters = {"Gini": compute_gini}
        self.dc = DataCollector(model_reporters=model_reporters,
                                agent_reporters=agent_reporters)

    def create_agents(self):
        """Method to create all the agents."""
        for i in range(self.num_agents):
            a = MoneyAgent(i)
            self.schedule.add(a)

    def step(self):
        self.schedule.step()
        self.dc.collect(self)
Exemplo n.º 21
0
class LifeTimeModel(Model):
    '''Simple model for running models with a finite life'''
    def __init__(self, agent_lifetime = 1, n_agents = 10):
        super().__init__()
        
        self.agent_lifetime = agent_lifetime
        self.n_agents = n_agents

        ## keep track of the the remaining life of an agent and
        ## how many ticks it has seen
        self.datacollector = DataCollector(
            agent_reporters = {"remaining_life" : lambda a: a.remaining_life,
                               "steps" : lambda a: a.steps})
        
        self.current_ID = 0
        self.schedule = RandomActivation(self)
        
        for _ in range(n_agents):
            self.schedule.add(FiniteLifeAgent(self.next_id(),
                                              self.agent_lifetime,
                                              self))

    def step(self):
        '''Add agents back to n_agents in each step'''
        
        self.datacollector.collect(self)
        self.schedule.step()
        
        if len(self.schedule.agents) < self.n_agents:
            for _ in range(self.n_agents - len(self.schedule.agents)):
                self.schedule.add(FiniteLifeAgent(self.next_id(),
                                                  self.agent_lifetime,
                                                  self))

    def run_model(self, step_count = 100):
        for _ in range(step_count):
            self.step()
Exemplo n.º 22
0
class Movement(Model):

    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)

    def step(self):
        # necessary; tells model to move forward
        self.time += (1/73)
        self.step_in_year += 1
        if self.step_in_year > 73:
            self.step_in_year = 1  # start new year
        self.schedule.step()

    def _readASCII(self, text):
        # reads in a text file that determines the environmental grid setup
        f = open(text, 'r')
        body = f.readlines()
        width = body[0][-4:]  # last 4 characters of line that contains the 'width' value
        height = body[1][-5:]
        abody = body[6:]  # ASCII file with a header
        f.close()
        abody = reversed(abody)
        cells = []
        for line in abody:
            cells.append(line.split(" "))
        return [cells, int(width), int(height)]

    def _populate(self, masterdict, grid, land_type, width, height):
        # places land tiles on the grid - connects color/land cover category with ASCII file values
        counter = 0  # sets agent ID - not currently used
        for y in range(height):  # for each pixel,
            for x in range(width):
                value = float(grid[y][x])  # value from the ASCII file for that coordinate/pixel, e.g. 1550 elevation
                land_grid_coordinate = x, y
                land = land_type(counter, self)
                if land_type.__name__ == 'Elevation_Out_of_Bound':
                    if (value < land_type.lower_bound or value > land_type.upper_bound) and value != -9999:
                        # if elevation is not 1000-2200, but is within the bounds of the FNNR, mark as 'elevation OOB'
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1
                elif land_type.__name__ == 'Forest':
                    if land_type.type == value:
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1
                elif land_type.__name__ == 'PES':
                    if land_type.type == value:
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1
                elif land_type.__name__ == 'Farm':
                    if land_type.type == value:
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1
                elif land_type.__name__ == 'Household':
                    if land_type.type == value:
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1
                else:  # vegetation background
                    if land_type.type == value:
                        self.grid.place_agent(land, land_grid_coordinate)
                        masterdict[land.__class__.__name__].append(land_grid_coordinate)
                        counter += 1

    def saveLoad(self, pickled_file, name, option):
        """ This function pickles an object, which lets it be loaded easily later.
        I haven't figured out how to utilize pickle to pickle class objects (if possible). """
        if option == "save":
            f = open(name, 'wb')
            pickle.dump(pickled_file, f)
            f.close()
        elif option == "load":
            f = open(name, 'rb')
            new_pickled_file = pickle.load(f)
            return new_pickled_file
        else:
            print('Invalid saveLoad option')
Exemplo n.º 23
0
class DiseaseModel(Model):
    def __init__(self, no_people, total_area, no_agents, Nc_N, n, all_x, all_y,
                 centers, infection_rate, city_label):
        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)
            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"})

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
Exemplo n.º 24
0
class BoltzmannWealthModelNetwork(Model):
    """A model with some number of agents."""
    def __init__(self,
                 b=35.98,
                 a=0.6933,
                 beta=0.95,
                 delta=0.08,
                 theta=0.8,
                 N=100):  #N- number of agents
        self.N = N
        self.b = b
        self.a = a
        self.agents = []
        self.fit_alpha = 0
        self.fit_loc = 0
        self.fit_beta = 0
        self.t = 0
        self.beta = 0.95
        self.delta = 0.08
        self.theta = 0.8
        self.time = 1  #for sensitivity analysis
        self.G = nx.barabasi_albert_graph(n=N, m=1)
        nx.set_edge_attributes(
            self.G, 1, 'weight')  #setting all initial edges with a weight of 1
        self.nodes = np.linspace(0, N - 1, N,
                                 dtype='int')  #to keep track of the N nodes
        self.schedule = RandomActivation(self)
        self.datacollector = DataCollector(model_reporters={
            'beta': 'b',
            'a': 'a',
            'fit_alpha': 'fit_alpha',
            'fit_beta': 'fit_beta',
            'loc': 'fit_loc',
            'TotalSwitch': 'total',
            'Threshold': 't'
        },
                                           agent_reporters={
                                               "k": 'k',
                                               'lamda': 'lamda',
                                               'abilitity': 'alpha',
                                               'technology': 'tec'
                                           })

        for i, node in enumerate(self.G.nodes()):
            agent = MoneyAgent(i, self)
            self.schedule.add(agent)

        self.running = True
        self.datacollector.collect(self)

    def Global_Attachment(self):
        #print("Global Attachment no: {}".format(self.count))
        node1 = random.choice(self.nodes)
        node2 = random.choice(self.nodes)
        while (self.G.has_edge(node1, node2) == True):
            node2 = random.choice(self.nodes)
            node1 = random.choice(self.nodes)
        #adding the edge node1-node2
        for agent in self.agents:
            if (agent.unique_id == node1):
                node1_a = agent
            if (agent.unique_id == node2):
                node2_a = agent
        self.G.add_edge(node1,
                        node2,
                        weight=Edge_Weight(node1_a, node2_a, self.b, self.a))

    def step(self):
        #print(self.time)
        self.schedule.step()
        # collect data
        self.Global_Attachment()  #for sensitivity analysis
        self.datacollector.collect(self)
        agent_df = self.datacollector.get_agent_vars_dataframe()
        agent_df.reset_index(level=['Step', 'AgentID'], inplace=True)
        k = agent_df.k.to_numpy()
        self.t = np.percentile(k, q=10)
        #print("Threshold = ", self.t)
        count = 0
        trap = []
        agents = []
        for agent in self.nodes:
            df = agent_df.loc[(agent_df["AgentID"] == agent)
                              & (agent_df['k'] < self.t)].reset_index(
                                  drop=True)
            if (not df.empty):
                agents.append(agent)
                j = int(df.loc[0].Step)
                count = 0
                while (j < len(df) - 1):
                    if (int(df.loc[j + 1].Step) - int(df.loc[j].Step) == 1):
                        count += 1
                    j += 1
                    #print("i = ", i)
                trap.append(count)
                self.Count = count
        self.fit_alpha, self.fit_loc, self.fit_beta = stats.gamma.fit(trap)
        self.time += 1  #
        #counting number of switches
        switch = {'Agent': [], 'Total': []}
        for agent in self.nodes:
            df = agent_df.loc[agent_df.AgentID == agent].reset_index(drop=True)
            tech = df.technology.to_numpy()
            count = 0
            for i in range(len(tech) - 1):
                if ((tech[i] == 'L' and tech[i + 1] == 'H')
                        or (tech[i] == 'H' and tech[i + 1] == 'L')):
                    count += 1
            if (count):
                switch['Agent'].append(agent)
                switch['Total'].append(count)
        switch = pd.DataFrame(switch)
        no_switch = switch.Total.unique()
        no_switch.sort()
        total = {no_switch[i]: [] for i in range(len(no_switch))}
        #print(total)
        for i in no_switch:
            total[i] = len(switch.loc[switch.Total == i])
        #print(total)
        self.total = total

    def run_model(self, n):
        for i in tqdm(range(n)):
            self.time = i + 1
            self.step()
Exemplo n.º 25
0
class ciudad(Model):
    "Inicialización del modelo"
    "Se necesita incluir la base de datos, suponiendo que tendremos varias ciudades para que la inicialización sea genérica"

    def __init__(self, n, m, width, height, porcentaje_infectados, densidad,
                 acumedad, sexo, edades, transporte, Casillas_zona,
                 acummovilidad, movilidad, dias_cuarentena, long_paso,
                 porcentaje_en_cuarentena, pruebas_disponibles,
                 activacion_testing_aleatorio, activacion_contact_tracing,
                 activación_cuarentena_acordeon, dia_inicio_acordeon,
                 intervalo_acordeon, tiempo_zonificacion):
        self.total_agentes = n  #número de agentes a iniciar
        self.schedule = RandomActivation(
            self)  #inicialización en paralelo de todos los agentes
        self.grid = MultiGrid(width, height,
                              True)  #creación de la grilla genérica

        global PRUEBAS_DISPONIBLES
        global ACTIVACION_CONTACT_TRACING
        global ACTIVACION_TESTING_ALEATORIO
        global OLAS
        global ACTIVACION_CUARENTENA_ACORDEON
        global DIA_INICIO_ACORDEON
        global INTERVALO_ACORDEON
        global ACTIVACION_CUARENTENA
        global DURACION_CUARENTENA
        global PORCENTAJE_EN_CUARENTENA
        global ACTIVACION_CUARENTENA_ZONIFICADA
        global DURACION_CUARENTENA_ZONIFICADA
        global PORCENTAJE_EN_CUARENTENA_ZONIFICADA
        global TIEMPO_ZONIFICACION

        #Inicialización de las variables globales
        PRUEBAS_DISPONIBLES = pruebas_disponibles
        ACTIVACION_CONTACT_TRACING = activacion_contact_tracing
        ACTIVACION_TESTING_ALEATORIO = activacion_testing_aleatorio
        OLAS = round(PRUEBAS_DISPONIBLES / 12)
        ACTIVACION_CUARENTENA_ACORDEON = activación_cuarentena_acordeon
        DIA_INICIO_ACORDEON = dia_inicio_acordeon
        INTERVALO_ACORDEON = intervalo_acordeon
        ACTIVACION_CUARENTENA = (True if dias_cuarentena > 0 else False)
        DURACION_CUARENTENA = dias_cuarentena
        PORCENTAJE_EN_CUARENTENA = porcentaje_en_cuarentena
        TIEMPO_ZONIFICACION = tiempo_zonificacion

        "Creación de cada agente"
        for i in range(self.total_agentes):
            n_id = random.random()
            estado = (2 if n_id > porcentaje_infectados else 1
                      )  ################ Preguntar esta linea ###############
            tcontagio = (random.randint(5, 9) if estado == 2 else 0)
            nuevo = personas(i, self, self.total_agentes, m, estado, tcontagio,
                             densidad, acumedad, sexo, edades, transporte,
                             Casillas_zona, acummovilidad, movilidad,
                             dias_cuarentena, long_paso,
                             porcentaje_en_cuarentena)  #asignación del id
            self.schedule.add(nuevo)  #creación del agente en el sistema

        "Asignación del hogar"
        for i in Casillas_zona:
            values = Casillas_zona.get(i)
            for j in values:
                agentes = self.grid.get_cell_list_contents(j)
                if len(agentes) > 0:
                    num_hogares = (1 if round(len(agentes) / 4) == 0 else
                                   round(len(agentes) / 4))
                    lista = [e for e in range(0, num_hogares)]
                    for z in agentes:
                        z.hogar = random.choice(lista)

        "Configurar el recolector de datos"
        self.datacollector = DataCollector(
            model_reporters={
                "Susceptibles": susceptibles,
                "Total infectados": total_infectados,
                "Graves": infectados_graves,
                "Críticos": infectados_criticos,
                "Leves": infectados_leves,
                "Recuperados": recuperados,
                "Rt": rt,
                "Recuento_zonas": recuento_zonas,
                "0-4": recuento_ge1,
                "5-19": recuento_ge2,
                "20-39": recuento_ge3,
                "40-59": recuento_ge4,
                ">60": recuento_ge5,
                "En_cuarentena": en_cuarentena,
                "Vivos": agentes_vivos,
                "Día": dia,
                "Contactos_prom_trabajo": prom_contactos_trabajo,
                "Contactos_prom_transporte": prom_contactos_transporte,
                "Contactos_prom_casa": prom_contactos_casa,
                "Nuevos_infectados": nuevos_infectados,
                "Detectados": detectados,
                "En_testing": en_testing,
                "En_cama": en_cama,
                "En_UCI": en_uci,
                "Detectados_por_intervencion": detectados_interv,
                "#Intervenidos": intervenidos
            })
        self.running = True

    "Avanzar el modelo"

    def step(self):
        global PRUEBAS_DISPONIBLES
        global ACTIVACION_TESTING_ALEATORIO
        global ACTIVACION_CONTACT_TRACING
        global OLAS
        global ACTIVACION_CUARENTENA_ACORDEON
        global DIA_INICIO_ACORDEON
        global INTERVALO_ACORDEON
        global ACTIVACION_CUARENTENA
        global DIA_INICIO_CUARENTENA
        global DURACION_CUARENTENA
        global PORCENTAJE_EN_CUARENTENA

        self.datacollector.collect(self)
        self.cuarentena_regular(ACTIVACION_CUARENTENA, DIA_INICIO_CUARENTENA,
                                DURACION_CUARENTENA, PORCENTAJE_EN_CUARENTENA)
        self.cuarentena_acordeon(ACTIVACION_CUARENTENA_ACORDEON,
                                 DIA_INICIO_ACORDEON, INTERVALO_ACORDEON)
        self.schedule.step()
        self.dinamica_hospitales()
        self.testing_aleatorio(PRUEBAS_DISPONIBLES,
                               ACTIVACION_TESTING_ALEATORIO)
        self.contact_tracing(ACTIVACION_CONTACT_TRACING)
        self.cuarentena_zonificada(0.2)

    def cuarentena_zonificada(self, porcentaje_cierre):
        global TIEMPO_ZONIFICACION
        agentes = [agent for agent in self.schedule.agents]
        zonas = []
        #Saca la lista de zonas
        for i in agentes:
            zonas.append(i.zona)
        zonas = unique(zonas)

        #Cálculo del porcentaje de detectados para cada zona
        for i in range(len(zonas)):
            suma_agentes_en_zona = 0
            suma_detectados = 0
            for j in agentes:
                if j.zona == i:
                    suma_agentes_en_zona += 1
                    suma_detectados += j.detectado
            porcentaje = suma_detectados / suma_agentes_en_zona
            if porcentaje > porcentaje_cierre:
                for j in agentes:
                    if j.cuarentena == 0:
                        j.activar_zonificacion(i, TIEMPO_ZONIFICACION)

    def cuarentena_regular(self, activacion, inicio, duracion, porcentaje):
        if activacion == True:
            t = self.schedule.time
            if t == inicio:
                agentes = [agent for agent in self.schedule.agents]
                print(activacion, inicio, duracion, porcentaje)
                for i in agentes:
                    i.activar_cuarentena(activacion, porcentaje, duracion)
                    print(i.cuarentena, " t:", i.tcuarentena, " dt:",
                          i.dias_cuarentena)

    def cuarentena_acordeon(self, activacion, inicio, intervalo):
        global DIA_INICIO_ACORDEON
        global INTERVALO_ACORDEON
        global PORCENTAJE_EN_CUARENTENA
        if activacion == True:
            t = self.schedule.time
            if t == inicio:
                agentes = [agent for agent in self.schedule.agents]
                for i in agentes:
                    i.activar_cuarentena(activacion, PORCENTAJE_EN_CUARENTENA,
                                         intervalo)
                DIA_INICIO_ACORDEON += 2 * INTERVALO_ACORDEON

    def contact_tracing(self, activacion):
        global PRUEBAS_DISPONIBLES
        if activacion == True:
            if PRUEBAS_DISPONIBLES > 0:
                lista_para_contact_tracing = []
                lista_para_intervenir = []
                agentes = [agent for agent in self.schedule.agents]
                for i in agentes:
                    if i.para_contact == 1 and i.detectado == 1:
                        lista_para_contact_tracing.append(i)
                if len(lista_para_contact_tracing) > 0:
                    for i in lista_para_contact_tracing:
                        i.recopilar_contactos(lista_para_intervenir)
                    if len(lista_para_intervenir) > 0:
                        lista_para_intervenir = unique(lista_para_intervenir)
                        for i in lista_para_intervenir:
                            if PRUEBAS_DISPONIBLES > 1:
                                i.contact_tracing()
                                PRUEBAS_DISPONIBLES -= 1

    def testing_aleatorio(self, pruebas, activacion):
        global TIEMPO
        global PRUEBAS_DISPONIBLES
        global OLAS
        if activacion == True:
            t = self.schedule.time
            agentes = [agent for agent in self.schedule.agents]
            if t == TIEMPO and pruebas > 0 and OLAS > 0:
                disponibles = pruebas / OLAS
                if OLAS == 1:
                    for i in range(pruebas):
                        n_agente = random.choice(agentes)
                        n_agente = self.agente_valido(n_agente)
                        n_agente.testeado = 1
                        n_agente.intervencion = 1
                        PRUEBAS_DISPONIBLES -= 1
                else:
                    for i in range(round(disponibles)):
                        n_agente = random.choice(agentes)
                        n_agente = self.agente_valido(n_agente)
                        n_agente.testeado = 1
                        n_agente.intervencion = 1
                        PRUEBAS_DISPONIBLES -= 1
                TIEMPO += 3
                OLAS -= 1

    def dinamica_hospitales(self):
        global CAMAS_DISPONIBLES
        global UCIS_DISPONIBLES
        agentes = [agent for agent in self.schedule.agents
                   ]  #recopila los agentes del modelo
        agentes_para_hospital = []

        #0. trabajar solo con el arreglo de agentes graves o críticos
        for i in agentes:
            if i.estado == 3 or i.estado == 4:
                agentes_para_hospital.append(i)

        liberar_cama = []
        liberar_uci = []
        requerir_cama = []
        if len(agentes_para_hospital) > 0:
            for i in agentes_para_hospital:
                #crear arreglos para priorizar salidas sobre ingresos en la orden de ejecución
                if i.estado == 3 and i.en_cama == 0:  #ingresa a los graves a hospitalización
                    requerir_cama.append(i)
                if i.estado == 3 and i.en_cama == 1 and i.thospitalizado == 8:  #sale de hospitalización
                    liberar_cama.append(i)
                if i.estado == 4 and i.en_cama == 1 and i.thospitalizado >= 6:  #sale de hospitalización a UCI
                    liberar_cama.append(i)
                if i.estado == 4 and i.en_uci == 1 and i.tuci >= 10:
                    liberar_uci.append(i)
                if i.estado == 4 and i.en_cama == 1 and i.thospitalizado == 6 and i.tcontagio >= 24:
                    liberar_cama.append(i)

        #Se van a liberar las personas de la cama
        if len(liberar_cama) > 0:
            for i in liberar_cama:
                if i.estado == 3 and i.en_cama == 1:  #libero cama si son solo hospitalizados
                    i.en_cama = 0
                    CAMAS_DISPONIBLES += 1
                if i.estado == 4:
                    if i.en_cama == 1 and i.thospitalizado == 6 and i.tcontagio >= 24:  #libero la cama de segunda estancia
                        i.en_cama = 0
                        CAMAS_DISPONIBLES += 1
                    else:
                        if i.en_cama == 1:
                            suma = UCIS_DISPONIBLES - 1
                            if suma >= 0:  #libero cama si lo puedo meter en UCI
                                i.procesado = 1
                                i.en_cama = 0
                                i.thospitalizado = 0
                                CAMAS_DISPONIBLES += 1
                                i.en_uci = 1
                                UCIS_DISPONIBLES -= 1
                            else:
                                i.procesado = 0
        #Se van a liberar las UCIs y se meten en camas si hay disponibles
        if len(liberar_uci) > 0:
            #print("liberando UCIs")
            for i in liberar_uci:
                if i.en_uci == 1:
                    suma = CAMAS_DISPONIBLES - 1
                    if suma >= 0:
                        i.en_uci = 0
                        UCIS_DISPONIBLES += 1
                        i.en_cama = 1
                        CAMAS_DISPONIBLES -= 1
        #Se van a asignar cama para los que las necesitan
        if len(requerir_cama) > 0:
            #print("asignado camas")
            for i in requerir_cama:
                if i.en_cama == 0:
                    suma = CAMAS_DISPONIBLES - 1
                    if suma >= 0:
                        i.en_cama = 1
                        i.procesado = 1
                        CAMAS_DISPONIBLES -= 1

    def agente_valido(self, n_agente):
        if n_agente.testeado == 0 and n_agente.detectado == 0 and n_agente.edad > 17 and n_agente.edad < 70:
            return n_agente
        else:
            agentes = [agent for agent in self.schedule.agents]
            return self.agente_valido(random.choice(agentes))
class TransportationModel(Model):
    """The base model"""
    def __init__(self, transportation_graph):
        self.schedule = RandomActivation(self)
        self._transportation_graph = transportation_graph
        self._countermeasures = [
        ]  # a list of active countermeasures. tp model will not update this.
        # Create agents
        agent_id = 0
        # TODO: Seeding..., if not known, is random for now
        seed_location = random.choice(
            list(self._transportation_graph.graph.nodes()))
        self._transportation_graph = transportation_graph
        for loc in list(self._transportation_graph.graph.nodes()):
            agent_id += 1  # we will keep agent ids different from location for now.
            loc_passenger_flow = self._transportation_graph.graph.nodes[loc][
                'flow']
            if loc_passenger_flow == 0:
                print('making up passenger flow (10000) for location', loc)
                loc_passenger_flow = 10000
            a = SEIR_Agent(agent_id, self, loc, loc_passenger_flow)
            if loc == seed_location:
                a.population[AgentParams.STATUS_INFECTED] += 1
                a.population[AgentParams.STATUS_SUSCEPTIBLE] -= 1
            self.schedule.add(a)

    def update_countermeasures(self):
        return None

    # Decay the viral loads in the environment. just wipes them for now.
    def decay_viral_loads(self):
        nx.set_node_attributes(self._transportation_graph.graph, 0,
                               'viral_load')
        for a in self.schedule.agents:
            self._transportation_graph.graph.nodes[a.location][
                'infected'] = a.population[AgentParams.STATUS_INFECTED]
        return None

    def increment_viral_loads(self):
        for a in self.schedule.agents:
            a.infect()
        return None

    def step(self):
        self.decay_viral_loads(
        )  #TODO: yes, this belongs at the end of a step. but i need my snapshot to be mid-day
        self.increment_viral_loads()
        self.schedule.step()
        self._transportation_graph.update_hotspots(
            self.schedule.agents)  #TODO: repair this later
        self.update_countermeasures()

    def calculate_SEIR(self, print_results=False):
        sick, exposed, infected, recovered = 0, 0, 0, 0
        for a in self.schedule.agents:
            sick += a.population[AgentParams.STATUS_SUSCEPTIBLE]
            exposed += a.population[AgentParams.STATUS_EXPOSED]
            infected += a.population[AgentParams.STATUS_INFECTED]
            recovered += a.population[AgentParams.STATUS_RECOVERED]
        if print_results:
            print('S,E,I,R:', sick, exposed, infected, recovered)
        return [sick, exposed, infected, recovered]

    @property
    def transportation_graph(self):
        return self._transportation_graph

    @transportation_graph.setter
    def transportation_graph(self, value):
        self._transportation_graph = value

    @property
    def countermeasures(self):
        return self._countermeasures

    @countermeasures.setter
    def countermeasures(self, value):
        self._countermeasures = value
Exemplo n.º 27
0
class SensorBlockchainNetwork(Model):
    def __init__(
            self,
            num_sensors=20,
            stochasticity=0.05,

            # Blockchain vars:
            # blockchain_gas_price=20,
            block_gas_limit=9000000,
            gas_per_byte=625,
            gas_per_second=75000000,
            avg_block_time=13,
            # gas_per_byte and gas_per_second calculated based on
            # https://hackernoon.com/ether-purchase-power-df40a38c5a2f

            # Sensor vars:
        battery_life=1000,
            record_cost=1,
            record_freq=1,
            record_bytes=32,
            compute_cost_per_byte=1,
            info_reduction=1,
            sign_cost=0.1,
            transmit_cost_per_byte=1,
            transmit_freq=1,
            sensor_gas_price=20,
            mortal=True,

            # Model vars:
            verbose=False,
            info_currency_window=1):

        super().__init__()

        self.verbose = verbose
        if self.verbose:
            print('Verbose model')
        self.info_currency_window = info_currency_window
        self.running = True
        self.schedule = RandomActivation(self)
        self.datacollector = DataCollector(model_reporters={
            "active_sensors":
            get_active_sensors_at_current_tick,
        },
                                           agent_reporters={
                                               "gwei_spent":
                                               'gwei_spent',
                                               "battery_life":
                                               'battery_life',
                                               "data_collected":
                                               get_total_data_collected,
                                               "informational_currency":
                                               get_informational_currency
                                           })

        self.blockchain = Blockchain(
            self.next_id(),
            # blockchain_gas_price,
            block_gas_limit,
            gas_per_byte,
            gas_per_second,
            avg_block_time,
            self)

        for i in range(num_sensors):
            sensor = Sensor(
                self.next_id(),
                battery_life,
                mortal,
                record_cost,
                record_freq,
                record_bytes,
                compute_cost_per_byte,
                info_reduction,
                sign_cost,
                transmit_cost_per_byte,
                transmit_freq,
                sensor_gas_price,
                self.blockchain,
                stochasticity,  # << each sensor gets the same amount of stochasticity?
                self)

            self.schedule.add(sensor)

        # Mine genesis block
        self.blockchain.chain.loc[1] = [
            False for col in self.blockchain.chain.columns
        ]

        if self.verbose:
            print(num_sensors, "instantiated and added to schedule.")

    def step(self):
        self.schedule.step()
        if self.schedule.steps > 1:
            self.blockchain.mine_block()
        self.datacollector.collect(self)
Exemplo n.º 28
0
class CivilViolenceModel(Model):
    """
    Model 1 from "Modeling civil violence: An agent-based computational
    approach," by Joshua Epstein.
    http://www.pnas.org/content/99/suppl_3/7243.full
    Attributes:
        height: grid height
        width: grid width
        citizen_density: approximate % of cells occupied by citizens.
        cop_density: approximate % of calles occupied by cops.
        citizen_vision: number of cells in each direction (N, S, E and W) that
            citizen can inspect
        cop_vision: number of cells in each direction (N, S, E and W) that cop
            can inspect
        legitimacy:  (L) citizens' perception of regime legitimacy, equal
            across all citizens
        max_jail_term: (J_max)
        active_threshold: if (grievance - (risk_aversion * arrest_probability))
            > threshold, citizen rebels
        arrest_prob_constant: set to ensure agents make plausible arrest
            probability estimates
        movement: binary, whether agents try to move at step end
        max_iters: model may not have a natural stopping point, so we set a
            max.

    """

    def __init__(self, height, width, citizen_density, cop_density,
                 citizen_vision, cop_vision, legitimacy,
                 max_jail_term, active_threshold=.1, arrest_prob_constant=2.3,
                 movement=True, max_iters=1000):
        super(CivilViolenceModel, self).__init__()
        self.height = height
        self.width = width
        self.citizen_density = citizen_density
        self.cop_density = cop_density
        self.citizen_vision = citizen_vision
        self.cop_vision = cop_vision
        self.legitimacy = legitimacy
        self.max_jail_term = max_jail_term
        self.active_threshold = active_threshold
        self.arrest_prob_constant = arrest_prob_constant
        self.movement = movement
        self.running = True
        self.max_iters = max_iters
        self.iteration = 0
        self.schedule = RandomActivation(self)
        self.grid = Grid(height, width, torus=True)
        model_reporters = {
            "Quiescent": lambda m: self.count_type_citizens(m, "Quiescent"),
            "Active": lambda m: self.count_type_citizens(m, "Active"),
            "Jailed": lambda m: self.count_jailed(m)}
        agent_reporters = {
            "x": lambda a: a.pos[0],
            "y": lambda a: a.pos[1],
            'breed': lambda a: a.breed,
            "jail_sentence": lambda a: getattr(a, 'jail_sentence', None),
            "condition": lambda a: getattr(a, "condition", None),
            "arrest_probability": lambda a: getattr(a, "arrest_probability",
                                                    None)
        }
        self.dc = DataCollector(model_reporters=model_reporters,
                                agent_reporters=agent_reporters)
        unique_id = 0
        if self.cop_density + self.citizen_density > 1:
            raise ValueError(
                'Cop density + citizen density must be less than 1')
        for (contents, x, y) in self.grid.coord_iter():
            if random.random() < self.cop_density:
                cop = Cop(unique_id, (x, y), vision=self.cop_vision,
                          model=self)
                unique_id += 1
                self.grid[y][x] = cop
                self.schedule.add(cop)
            elif random.random() < (
                    self.cop_density + self.citizen_density):
                citizen = Citizen(unique_id, (x, y),
                                  hardship=random.random(),
                                  regime_legitimacy=self.legitimacy,
                                  risk_aversion=random.random(),
                                  threshold=self.active_threshold,
                                  vision=self.citizen_vision, model=self)
                unique_id += 1
                self.grid[y][x] = citizen
                self.schedule.add(citizen)

    def step(self):
        """
        Advance the model by one step and collect data.
        """
        self.schedule.step()
        self.dc.collect(self)
        self.iteration += 1
        if self.iteration > self.max_iters:
            self.running = False

    @staticmethod
    def count_type_citizens(model, condition, exclude_jailed=True):
        """
        Helper method to count agents by Quiescent/Active.
        """
        count = 0
        for agent in model.schedule.agents:
            if agent.breed == 'cop':
                continue
            if exclude_jailed and agent.jail_sentence:
                continue
            if agent.condition == condition:
                count += 1
        return count

    @staticmethod
    def count_jailed(model):
        """
        Helper method to count jailed agents.
        """
        count = 0
        for agent in model.schedule.agents:
            if agent.breed == 'citizen' and agent.jail_sentence:
                count += 1
        return count
Exemplo n.º 29
0
class CommerceModel(Model):
    """
    A simple model of an E-Commerce where Consumer agent, Company(include Offline Retailer,
    Online Retailer, Platform E-commerce, Settled Shop) Agent compete with each other.
    """
    model_type = "China"  # China or American
    product_quality_list = [
        ProductQuality.low_quality, ProductQuality.high_quality
    ]

    offline_retailer_policy = [
        CommerceType.offline_retailer, CommerceType.online_retailer,
        CommerceType.settled_shop
    ]
    online_retailer_policy = [
        CommerceType.online_retailer, CommerceType.settled_shop
    ]
    settled_shop_policy = [
        CommerceType.platform_commerce, CommerceType.online_retailer,
        CommerceType.offline_retailer
    ]

    def __init__(self,
                 model_type="China",
                 num_consumer_agents=50,
                 num_category_agents=100,
                 num_offline_retailer_agents=100,
                 num_online_retailer_agents=90,
                 num_platform_e_commerce_agents=40,
                 num_settled_shop_agents=200):
        self.model_type = model_type
        self.num_consumer_agents = num_consumer_agents
        self.num_category_agents = num_category_agents
        self.num_offline_retailer_agents = num_offline_retailer_agents
        self.num_online_retailer_agents = num_online_retailer_agents
        self.num_platform_e_commerce_agents = num_platform_e_commerce_agents
        self.num_settled_shop_agents = num_settled_shop_agents
        self.running = True

        self.category_schedule = RandomActivation(self)
        self.consumer_schedule = RandomActivation(self)
        self.offline_retailer_schedule = RandomActivation(self)
        self.online_retailer_schedule = RandomActivation(self)
        self.platform_e_commerce_schedule = RandomActivation(self)
        self.settled_shop_schedule = RandomActivation(self)
        self.datacollector = DataCollector(model_reporters={
            "num_offline_retailer_agents":
            compute_offline_retailer_num,
            "num_online_retailer_agents":
            compute_online_retailer_num,
            "num_platform_e_commerce_agents":
            compute_platform_e_commerce_num,
            "num_settled_shop_agents":
            compute_settled_shop_num
        },
                                           agent_reporters={"": ""})

        # Init the Agents List
        self.__init_category_agents(self.num_consumer_agents)
        self.__init_consumer_agents(self.num_consumer_agents)
        self.__init_offline_retailer_agents(self.num_offline_retailer_agents)
        self.__init_online_retailer_agents(self.num_online_retailer_agents)
        self.__init_platform_e_commerce_agents(
            self.num_platform_e_commerce_agents)
        self.__init_settled_shop_agents(self.num_settled_shop_agents)

    def __init_consumer_agents(self, num_consumer_agents):
        """ Init the Consumer Agent List"""
        for i in range(num_consumer_agents):
            unique_id = "consumer" + i
            price_sensitivity = 10
            social_economic_negative_factor = -8
            quality_sensitivity = 4
            social_economic_positive_factor = 8
            advertise_sensitivity = 5
            herd_sensitivity = 8
            variety_sensitivity = 8
            offline_experience_factor = 5
            consumer_agent = ConsumerAgent(
                unique_id, self, price_sensitivity,
                social_economic_negative_factor, quality_sensitivity,
                social_economic_positive_factor, advertise_sensitivity,
                herd_sensitivity, variety_sensitivity,
                offline_experience_factor)
            self.consumer_schedule.add(consumer_agent)

    def __init_category_agents(self, num_category_agents):
        """ Init the Category Agent List"""
        for i in range(num_category_agents):
            unique_id = "category" + i
            agents = []
            high_quality = 10
            low_quality = 1

            # 产品种类高低价格区间
            high_cost = random.randint(50, 100)
            low_cost = random.randint(5, 25)
            category_agent = CategoryAgent(unique_id, self, agents,
                                           high_quality, low_quality,
                                           high_cost, low_cost)
            self.category_schedule.add(category_agent)

    def __init_offline_retailer_agents(self, num_offline_retailer_agents):
        """ Init the Offline Retailer Agent List"""
        for i in range(num_offline_retailer_agents):
            unique_id = "offline_retailer_" + i
            rental_cost = 100
            offline_retailer_agent = OfflineRetailerAgent(
                unique_id, self, CommerceType.offline_retailer, rental_cost)
            self.offline_retailer_schedule.add(offline_retailer_agent)

    def __init_online_retailer_agents(self, num_online_retailer_agents):
        """ Init the Online Retailer Agent List """
        for i in range(num_online_retailer_agents):
            unique_id = "online_retailer_" + i
            technical_cost = 100
            online_retailer_agent = OnlineRetailerAgent(
                unique_id, self, CommerceType.online_retailer, 0,
                technical_cost, 0, [])
            self.online_retailer_schedule.add(online_retailer_agent)

    def __init_platform_e_commerce_agents(self,
                                          num_platform_e_commerce_agents):
        """ Init the Platform E-Commerce Agent List"""
        for i in range(num_platform_e_commerce_agents):
            unique_id = "platform_e_commerce_" + i
            technical_cost = 200
            subsidy_cost = 80
            platform_e_commerce_agent = PlatformECommerceAgent(
                unique_id, self, technical_cost, subsidy_cost)
            self.platform_e_commerce_schedule.add(platform_e_commerce_agent)

    def __init_settled_shop_agents(self, num_settled_shop_agents):
        """ Init the Settled Shop Agent List"""
        for i in range(num_settled_shop_agents):
            unique_id = "settled_shop_" + i
            subsidy_cost = 10
            rental_cost = 40  # 入驻平台电商成本
            # 随机选取一个平台电商,作为Settled Shop所依赖的电商平台
            platform_e_commerce_agent = choice(
                self.platform_e_commerce_schedule.agents)
            settled_shop_agent = SettledShopAgent(unique_id, self, rental_cost,
                                                  subsidy_cost,
                                                  platform_e_commerce_agent)
            self.settled_shop_schedule.add(settled_shop_agent)

    def __commerce_purchase(self):
        """ 厂商从产品种类中采购商品 """
        self.__commerce_purchase_products(
            self.offline_retailer_schedule.agents)
        self.__commerce_purchase_products(self.online_retailer_schedule.agents)
        self.__commerce_purchase_products(self.settled_shop_schedule.agents)

    def __commerce_purchase_products(self, e_commerce_agents):
        """ 厂商从产品种类中采购商品 """
        for e_commerce_agent in e_commerce_agents:
            product_diversity = random.randint(1, 15)
            if product_diversity >= len(self.category_schedule.agents):
                for category_agent in self.category_schedule.agents:
                    self.__generate_product(e_commerce_agent, category_agent)
            else:
                selected_category_agents = random.sample(
                    self.category_schedule.agents, product_diversity)
                for category_agent in selected_category_agents:
                    self.__generate_product(e_commerce_agent, category_agent)

    @classmethod
    def choose_quality(cls):
        return choice(cls.product_quality_list)

    def __generate_product(self, e_commerce_agent, category_agent):
        """ Generate product for E-Commerce Agent and Category Agent"""
        product_num = 0
        # 随机选择高低质量
        quality = CommerceModel.choose_quality()
        if quality == ProductQuality.high_quality:
            product_quality = random.randint(6, 10)
            product_cost = random.randint(category_agent.high_cost - 5,
                                          category_agent.high_cost + 5)
        elif quality == ProductQuality.low_quality:
            product_quality = random.randint(1, 5)
            product_cost = random.randint(category_agent.low_cost - 5,
                                          category_agent.low_cost + 5)
        tax_cost = product_cost * 0.03  # 假设tax_cost = product_cost * 3%
        product_price = product_cost * (e_commerce_agent.addition_rate + 1)
        sales_cost = product_cost * 0.05  # sales_cost = product_cost * 5%
        logistics_cost = product_cost * 0.04  # logistics_cost = product_cost * 4%
        product = Product(category_agent, product_num, product_price,
                          product_cost, product_quality, tax_cost, sales_cost,
                          logistics_cost)
        e_commerce_agent.add_product(product)
        category_agent.add_commerce_agent(e_commerce_agent)

    def __clear_schedule_agents(self):
        """ After every step, clear the original data and init the params."""
        for offline_retailer in self.offline_retailer_schedule.agents:
            offline_retailer.clear()

        for online_retailer in self.online_retailer_schedule.agents:
            online_retailer.clear()

        for settled_shop in self.settled_shop_schedule.agents:
            settled_shop.clear()

    def step(self):
        self.datacollector.collect(self)
        if self.offline_retailer_schedule.steps > 0:
            self.__clear_schedule_agents()
        # all E-Commerce Agents randomly purchase products from all Category Agents.
        self.__commerce_purchase()
        # all Consumer Agents randomly purchase products from E-Commerce Agents
        self.consumer_schedule.step()
        # After Consumer Agents purchase products, all E-Commerce Agents
        # compute total income and cost, then gain the profit
        self.offline_retailer_schedule.step()
        self.online_retailer_schedule.step()
        self.settled_shop_schedule.step()

    def run_model(self, n):
        for i in range(n):
            self.step()
Exemplo n.º 30
0
class VirusOnNetwork(Model):
    """A virus model with some number of agents"""

    def __init__(
        self,
        num_nodes=10,
        avg_node_degree=3,
        initial_outbreak_size=1,
        virus_spread_chance=0.4,
        virus_check_frequency=0.4,
        recovery_chance=0.3,
        gain_resistance_chance=0.5,
    ):

        self.num_nodes = num_nodes
        prob = avg_node_degree / self.num_nodes
        self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
        self.grid = NetworkGrid(self.G)
        self.schedule = RandomActivation(self)
        self.initial_outbreak_size = (
            initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes
        )
        self.virus_spread_chance = virus_spread_chance
        self.virus_check_frequency = virus_check_frequency
        self.recovery_chance = recovery_chance
        self.gain_resistance_chance = gain_resistance_chance

        self.datacollector = DataCollector(
            {
                "Infected": number_infected,
                "Susceptible": number_susceptible,
                "Resistant": number_resistant,
            }
        )

        # Create agents
        for i, node in enumerate(self.G.nodes()):
            a = VirusAgent(
                i,
                self,
                State.SUSCEPTIBLE,
                self.virus_spread_chance,
                self.virus_check_frequency,
                self.recovery_chance,
                self.gain_resistance_chance,
            )
            self.schedule.add(a)
            # Add the agent to the node
            self.grid.place_agent(a, node)

        # Infect some nodes
        infected_nodes = self.random.sample(self.G.nodes(), self.initial_outbreak_size)
        for a in self.grid.get_cell_list_contents(infected_nodes):
            a.state = State.INFECTED

        self.running = True
        self.datacollector.collect(self)

    def resistant_susceptible_ratio(self):
        try:
            return number_state(self, State.RESISTANT) / number_state(
                self, State.SUSCEPTIBLE
            )
        except ZeroDivisionError:
            return math.inf

    def step(self):
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)

    def run_model(self, n):
        for i in range(n):
            self.step()
Exemplo n.º 31
0
class BoidFlockers(Model):
    # ABOUT PAGE GOES HERE
    """
    Flocker model class. Handles agent creation, placement and scheduling.\n
\n
    How Illness works...\n 
    The lifecycle (from what we know) is where someone can truly be healthy, somehow pick up the virus and not know if they are infected unless symptoms show or a test is taken, and then after finding out that an individual might be infected, their behaviour changes to distance themselves from other. This can be visualized with this lifecycle:
    
    Healthy -> Unknowingly sick -> Knowingly sick -> Unknowingly Sick -> Healthy


    Other notes:

    Tried adding images to the custom built "SimpleContinuouosModule", apparently it does not take image paths...
    """
    def __init__(
            self,
            population=100,
            width=100,
            height=100,
            speed=1,
            vision=10,
            separation=2,
            cohere=0.025,
            separate=0.25,
            match=0.04,
            # slider vars
            transmitDistance=5,
            unknownSickTime=5,
            sickTime=10,
            healthyButContaigious=2,
            timeToSusceptible=90,
            deathPercentage=.034):
        """
        Create a new Flockers model.

        Args:
            population: Number of Boids
            width, height: Size of the space.
            speed: How fast should the Boids move.
            vision: How far around should each Boid look for its neighbors
            separation: What's the minimum distance each Boid will attempt to
                    keep from any other
            cohere, separate, match: factors for the relative importance of
                    the three drives.        
        """
        self.population = population
        self.vision = np.rint(transmitDistance * .65)
        self.speed = speed
        self.separation = separation
        self.schedule = RandomActivation(self)
        self.space = ContinuousSpace(width, height, True)
        self.factors = dict(cohere=cohere, separate=separate, match=match)
        #self.transmitDistance = transmitDistance
        self.unknownSickTime = unknownSickTime
        self.sickTime = sickTime
        self.healthyButContaigious = healthyButContaigious
        self.timeToSusceptible = timeToSusceptible
        self.deathPercentage = deathPercentage

        self.make_agents()
        self.redCount = 0
        self.yellowCount = 1
        self.greenCount = population - 1
        self.yellowCount2 = 0
        self.greenCount2 = 0
        self.ded = 0
        self.running = True
        self.datacollector = datacollection.DataCollector({
            "Boids":
            lambda m: m.schedule.get_agent_count(),
            "infected":
            lambda m: m.redCount,
            "unkowingly_contaigious":
            lambda m: m.yellowCount,
            "Healthy":
            lambda m: m.greenCount,
            "Died":
            lambda m: m.ded,
            "unknowingly_contaigious-recovering":
            lambda m: m.yellowCount2,
            "Recovered":
            lambda m: m.greenCount2,
        })

    def make_agents(self):
        """
        Create self.population agents, with random positions and starting headings.
        """
        for i in range(self.population):
            x = self.random.random() * self.space.x_max
            y = self.random.random() * self.space.y_max
            pos = np.array((x, y))
            velocity = np.random.random(2) * 2 - 1
            # this just makes the first node infected.
            if i == 1:
                boid = Boid(
                    i,  # unique id
                    2,  # color, 1 = green/healthy, and 2 = yellow/contaigious, 3 = red/sick
                    self,  # model
                    pos,  # pos
                    self.speed,  # speed
                    velocity,  # velocity
                    self.vision,  # self.vision
                    self.separation,  # separation
                    self.
                    unknownSickTime,  # time before the host understands they are sick (yellow)
                    self.sickTime,
                    self.healthyButContaigious,
                    self.timeToSusceptible,
                    **self.factors  # cohere, separate, match
                )
            else:
                boid = Boid(i, 1, self, pos, self.speed, velocity, self.vision,
                            self.separation, self.unknownSickTime,
                            self.sickTime, self.healthyButContaigious,
                            self.timeToSusceptible, **self.factors)
            self.space.place_agent(boid, pos)
            self.schedule.add(boid)

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
class CivilViolenceModel(Model):
    """ Civil violence model class """
    def __init__(self,
                 max_iter=200,
                 height=40,
                 width=40,
                 agent_density=0.7,
                 agent_vision=7,
                 active_agent_density=0.01,
                 cop_density=0.04,
                 cop_vision=7,
                 inf_threshold=40,
                 tackle_inf=False,
                 k=2.3,
                 graph_type=GraphType.BARABASI_ALBERT.name,
                 p=0.1,
                 p_ws=0.1,
                 directed=False,
                 max_jail_term=30,
                 active_threshold_t=0.1,
                 initial_legitimacy_l0=0.82,
                 movement=True,
                 seed=None):
        """
        Create a new civil violence model.

        :param max_iter: Maximum number of steps in the simulation.
        :param height: Grid height.
        :param width: Grid width.
        :param agent_density: Approximate percentage of cells occupied by citizen agents.
        :param agent_vision: Radius of the agent vision in every direction.
        :param active_agent_density: Enforce initial percentage of cells occupied by active agents.
        :param cop_density: Approximate percentage of cells occupied by cops.
        :param cop_vision: Radius of the cop vision in every direction.
        :param initial_legitimacy_l0: Initial legitimacy of the central authority.
        :param inf_threshold: Amount of nodes that need to be connected before an agent is considered an influencer.
        :param tackle_inf: Remove influencer when outbreaks starting
        :param max_jail_term: Maximal jail term.
        :param active_threshold_t: Threshold where citizen agent became active.
        :param k: Arrest term constant k.
        :param graph_type: Graph used to build network
        :param p: Probability for edge creation
        :param directed: Is graph directed
        :param movement: Can agent move at end of an iteration
        :param seed: random seed

        Additional attributes:
            running : is the model running
            iteration : current step of the simulation
            citizen_list : a list storing the citizen agents added to the model.   
            influencer_list : a list storing the citizien agents that are influencers

            grid : A 2D cellular automata representing the real world space environment
            network : A NetworkGrid with as many nodes as (citizen) agents representing the social network.
            Agent in the NetworkGrid are deep copy of agent in the MultiGrid has Mesa implementation is based on
            the usage of a single space. (Example: NetworkGrid place_agent method will change "pos" attribute from agent
            meaning one agent can't be on both MultiGrid and NetworkGrid).
            We maintain a dictionary of agent position instead.

        """
        super().__init__()

        # =============================
        # === Initialize attributes ===
        # =============================

        self.seed = seed
        self.random.seed(self.seed)

        # Initialize Model grid and schedule
        self.height = height
        self.width = width
        self.grid = MultiGrid(self.width, self.height,
                              torus=True)  # Grid or MultiGrid ?
        self.schedule = RandomActivation(self)
        self.max_iter = max_iter
        self.iteration = 0  # Simulation iteration counter
        self.movement = movement

        # Set Model main attributes
        self.max_jail_term = max_jail_term
        self.active_threshold_t = active_threshold_t
        self.initial_legitimacy_l0 = initial_legitimacy_l0
        self.legitimacy = initial_legitimacy_l0
        self.k = k
        self.graph_type = graph_type

        self.agent_density = agent_density
        self.agent_vision = agent_vision
        self.active_agent_density = active_agent_density
        self.cop_density = cop_density
        self.cop_vision = cop_vision
        self.inf_threshold = inf_threshold

        self.citizen_list = []
        self.cop_list = []
        self.influencer_list = []
        self.jailings_list = [0, 0, 0, 0]
        self.outbreaks = 0
        self.outbreak_now = 0
        self.outbreak_influencer_now = False
        self.tackle_inf = tackle_inf

        date = datetime.now()
        self.path = f'output/{self.graph_type}_{date.month}_{date.day}_{date.hour}_{date.minute}_'

        # === Set Data collection ===
        self.datacollector = DataCollector(
            model_reporters=self.get_model_reporters(),
            agent_reporters=self.get_agent_reporters())

        # ==============================
        # === Initialize environment ===
        # ==============================

        # Add agents to the model
        unique_id = 0
        for (contents, x, y) in self.grid.coord_iter():
            random_x = self.random.random()
            if random_x < self.agent_density:
                # Add agents
                agent = Citizen(unique_id=unique_id,
                                model=self,
                                pos=(x, y),
                                hardship=self.random.random(),
                                susceptibility=self.random.random(),
                                influence=self.random.random(),
                                expression_intensity=self.random.random(),
                                legitimacy=self.initial_legitimacy_l0,
                                risk_aversion=self.random.random(),
                                threshold=self.active_threshold_t,
                                vision=self.agent_vision)

                unique_id += 1
                self.citizen_list.append(agent)
                self.grid.place_agent(agent,
                                      (x, y))  # Place agent in the MultiGrid
                self.schedule.add(agent)

            elif random_x < (self.agent_density + self.active_agent_density):
                # Enforce an initial proportion of active agents
                agent = Citizen(unique_id=unique_id,
                                model=self,
                                pos=(x, y),
                                hardship=self.random.random(),
                                susceptibility=self.random.random(),
                                influence=self.random.random(),
                                expression_intensity=self.random.random(),
                                legitimacy=self.initial_legitimacy_l0,
                                risk_aversion=self.random.random(),
                                threshold=0,
                                vision=self.agent_vision)

                unique_id += 1
                self.citizen_list.append(agent)
                self.grid.place_agent(agent,
                                      (x, y))  # Place agent in the MultiGrid
                self.schedule.add(agent)

            elif random_x < (self.agent_density + self.active_agent_density +
                             self.cop_density):
                # Add law enforcement officer
                agent = Cop(unique_id=unique_id,
                            model=self,
                            pos=(x, y),
                            vision=self.cop_vision)

                unique_id += 1
                self.cop_list.append(agent)
                self.grid.place_agent(agent,
                                      (x, y))  # Place agent in the MultiGrid
                self.schedule.add(agent)

        # Generate a social network composed of every civilian agents
        self.G, self.network_dict = generate_network(self.citizen_list,
                                                     graph_type, p, p_ws,
                                                     directed, seed)
        # print_network(self.G, self.network_dict)  # Uncomment to print the network.

        # With network in place, set the influencers.
        self.set_influencers(self.inf_threshold)

        # Create the graph show the frequency of degrees for the nodes
        create_fig(self.G.degree, draw=False)  # Set draw=True to draw a figure

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        """
        One step in agent-based model simulation
        """

        self.schedule.step()
        self.iteration += 1
        self.update_legitimacy()

        self.outbreak_score_monitoring()
        self.datacollector.collect(self)

        # Save initial values
        if self.iteration == 1:
            self.save_initial_values(save=False)

        # Stop the model after a certain amount of iterations.
        if self.iteration > self.max_iter:
            self.save_data(save=False)
            self.running = False

    def outbreak_score_monitoring(self):
        if self.tackle_inf:
            if self.count_type_citizens(
                    "ACTIVE") > 30 and not self.outbreak_influencer_now:
                self.jail_influencer()
                self.outbreak_influencer_now = True

            if self.count_type_citizens("ACTIVE") < 30:
                self.outbreak_influencer_now = False

        # Count amount of outbreaks
        if self.count_type_citizens("ACTIVE") > 50 and self.outbreak_now == 0:
            self.outbreaks += 1  # Total number of outbreak
            self.outbreak_now = 1  # Indicate if outbreak now

        if self.count_type_citizens("ACTIVE") < 50:
            self.outbreak_now = 0

    def save_data(self, save=True):

        if save is not False:
            df_end = self.datacollector.get_agent_vars_dataframe()
            name = self.path + 'run_values.csv'
            df_end.to_csv(name)
        else:
            pass

    def save_initial_values(self, save=False):

        if save is not False:
            dictionary_data = {
                'agent_density': self.agent_density,
                'agent_vision': self.agent_vision,
                'active_agent_density': self.active_agent_density,
                'cop_density': self.cop_density,
                'initial_legitimacy_l0': self.initial_legitimacy_l0,
                'inf_threshold': self.inf_threshold,
                'max_iter': self.max_iter,
                'max_jail_term': self.max_jail_term,
                'active_threshold_t': self.active_threshold_t,
                'k': self.k,
                'graph_type': self.graph_type,
            }

            name = self.path + 'ini_values.json'
            a_file = open(name, "w")
            json.dump(dictionary_data, a_file)
            a_file.close()
        else:
            pass

    def update_legitimacy(self):
        """
        Compute legitimacy (Epstein Working Paper 2001)
        """
        self.jailings_list[3] = self.jailings_list[2]
        self.jailings_list[2] = self.jailings_list[1]
        nb_active_and_quiescent = self.count_type_citizens(
            "ACTIVE") + self.count_type_citizens("QUIESCENT")
        self.jailings_list[1] = self.jailings_list[
            0] / nb_active_and_quiescent  # + 1 to avoid division by zero
        self.jailings_list[0] = 0

        sum_jailed = self.jailings_list[1] - self.jailings_list[
            2]**2 - self.jailings_list[3]**3
        self.legitimacy = self.initial_legitimacy_l0 * (1 - sum_jailed)
        if self.legitimacy <= 0:
            self.legitimacy = 0

    def get_model_reporters(self):
        """
        Dictionary of model reporter names and attributes/funcs
        Reference to functions instead of lambda are provided to handle multiprocessing case.
        Multiprocessing pool cannot directly handle lambda.
        """
        return {
            "QUIESCENT": compute_quiescent,
            "ACTIVE": compute_active,
            "JAILED": compute_active,
            "LEGITIMACY": compute_legitimacy,
            "INFLUENCERS": compute_influencers,
            "OUTBREAKS": compute_outbreaks
        }

    def get_agent_reporters(self):
        """
        Dictionary of agent reporter names and attributes/funcs
        """

        return {
            "Grievance": "grievance",
            "Hardship": "hardship",
            "State": "state",
            "Influencer": "influencer",
            "N_connections": "network_neighbors",
            "InfluencePi": "influence"
        }

    def count_type_citizens(self, state_req):
        """
        Helper method to count agents.
        Cop agents can't disappear from the map, so number of cops can be retrieved from model attributes.
        """
        count = 0
        for agent in self.citizen_list:
            if type(agent).__name__.upper() == 'COP':
                continue
            if agent.jail_sentence and state_req == 'JAILED':
                count += 1
            else:
                if agent.state is State.ACTIVE and state_req == 'ACTIVE':
                    count += 1
                elif agent.state == State.QUIESCENT and state_req == 'QUIESCENT':
                    count += 1
        return count

    def remove_agent_grid(self, agent):
        """
        Removes an agent from the grid.
        """
        self.grid.remove_agent(agent)

    def add_jailed(self, agent):
        """
        Un-jail an agent
        If the sentence of a jailed agent is over, place him back on a random empty cell in the grid.
        """

        if len(self.grid.empties) == 0:
            raise Exception("There are no empty cells.")

        new_pos = self.random.choice(list(self.grid.empties))
        self.grid.place_agent(agent, new_pos)

    def set_influencers(self, inf_threshold=150):
        """
        If an agent in the network is connected to a large amount of nodes, this agent can
        be considered an influencer and receives a corresponding tag.
        :param inf_threshold: determine how many connections a node needs to be considered an influencer
        """
        for agent in self.citizen_list:
            agent.set_influencer(
                len(list(self.G.neighbors(agent.network_node))), inf_threshold)
            if agent.influencer:
                self.influencer_list.append(agent)

    def remove_influencer(self):
        """
        Removes a random agent with the influencer tag from the grid.
        Gives manual control over the model to evaluate the influence of influencers.
        """
        if self.influencer_list:
            for i in range(len(self.influencer_list)):
                to_remove = self.random.choice(self.influencer_list)
                if to_remove.pos:  # Check if influencer is jailed.
                    self.grid.remove_agent(to_remove)
                self.influencer_list.remove(to_remove)
                self.citizen_list.remove(to_remove)
                self.schedule.remove(to_remove)
                self.G.remove_node(to_remove.network_node)

    def jail_influencer(self):
        """
        Jail a random agent with the influencer tag from the grid.
        Gives manual control over the model to evaluate the influence of influencers.
        """
        if self.influencer_list:
            for i in range(len(self.influencer_list)):
                arrestee = self.random.choice(self.influencer_list)
                if arrestee.state == State.JAILED:  # Check if influencer is jailed.
                    continue
                sentence = random.randint(1, self.max_jail_term)
                arrestee.jail_sentence = sentence
                arrestee.state = State.JAILED
                self.jailings_list[0] += 1
                if sentence > 0:
                    self.remove_agent_grid(arrestee)

                print(arrestee.unique_id,
                      ' was an influencer and has been jailed.')
Exemplo n.º 33
0
class GTModel(Model):
    def __init__(self, debug, size, i_n_agents, i_strategy, i_energy,
                 child_location, movement, k, T, M, p, d, strategies_to_count,
                 count_tolerance, mutation_type, death_threshold, n_groups):
        self.grid = SingleGrid(size, size, torus=True)
        self.schedule = RandomActivation(self)
        self.running = True
        self.debug = debug
        self.size = size
        self.agent_idx = 0
        self.i_energy = i_energy

        # Payoff matrix in the form (my_move, op_move) : my_reward
        self.payoff = {
            ('C', 'C'): 2,
            ('C', 'D'): -3,
            ('D', 'C'): 3,
            ('D', 'D'): -1,
        }
        # Constant for max population control (cost of surviving)
        self.k = k
        # Constant for controlling dying of old age
        self.M = M
        # Minimum lifespan
        self.T = T
        # Minimum energy level to reproduce
        self.p = p
        # Mutation "amplitude"
        self.d = d
        # Whether to spawn children near parents or randomly
        self.child_location = child_location
        # Specify the type of movement allowed for the agents
        self.movement = movement
        # Specify how the agents mutate
        self.mutation_type = mutation_type
        # The minimum total_energy needed for an agent to survive
        self.death_threshold = death_threshold

        # Vars regarding which strategies to look for
        self.strategies_to_count = strategies_to_count
        self.count_tolerance = count_tolerance

        # Add agents (one agent per cell)
        all_coords = [(x, y) for x in range(size) for y in range(size)]
        agent_coords = self.random.sample(all_coords, i_n_agents)

        for _ in range(i_n_agents):
            group_idx = (None if n_groups is None else self.random.choice(
                range(n_groups)))
            agent = GTAgent(self.agent_idx, group_idx, self, i_strategy.copy(),
                            i_energy)
            self.agent_idx += 1
            self.schedule.add(agent)
            self.grid.place_agent(agent, agent_coords.pop())

        # Collect data
        self.datacollector = DataCollector(
            model_reporters={
                **{
                    'strategies': get_strategies,
                    'n_agents': total_n_agents,
                    'avg_agent_age': avg_agent_age,
                    'n_friendlier': n_friendlier,
                    'n_aggressive': n_aggressive,
                    'perc_cooperative_actions': perc_cooperative_actions,
                    'n_neighbors': n_neighbor_measure,
                    'avg_delta_energy': avg_delta_energy,
                    'perc_CC': perc_CC_interactions,
                    'lin_fit_NC': coop_per_neig,
                    'lin_fit_NC_intc': coop_per_neig_intc,
                },
                **{
                    label: strategy_counter_factory(strategy, count_tolerance)
                    for label, strategy in strategies_to_count.items()
                }
            })

    def alpha(self):
        # Return the cost of surviving, alpha
        DC = self.payoff[('D', 'C')]
        CC = self.payoff[('C', 'C')]
        N = len(self.schedule.agents)

        return self.k + 4 * (DC + CC) * N / (self.size * self.size)

    def time_to_die(self, agent):
        # There is a chance every iteration to die of old age: (A - T) / M
        # There is a 100% to die if the agents total energy reaches 0
        return (agent.total_energy < self.death_threshold
                or self.random.random() < (agent.age - self.T) / self.M)

    def get_child_location(self, agent):
        if self.child_location == 'global':
            return self.random.choice(sorted(self.grid.empties))

        elif self.child_location == 'local':
            # Iterate over the radius, starting at 1 to find empty cells
            for rad in range(1, int(self.size / 2)):
                possible_steps = [
                    cell for cell in self.grid.get_neighborhood(
                        agent.pos,
                        moore=False,
                        include_center=False,
                        radius=rad,
                    ) if self.grid.is_cell_empty(cell)
                ]

                if possible_steps:
                    return self.random.choice(possible_steps)

            # If no free cells in radius size/2 pick a random empty cell
            return self.random.choice(sorted(self.grid.empties))

    def maybe_mutate(self, agent):
        # Mutate by adding a random d to individual Pi's
        if self.mutation_type == 'stochastic':
            # Copy the damn list
            new_strategy = agent.strategy.copy()
            # There is a 20% chance of mutation
            if self.random.random() < 0.2:
                # Each Pi is mutated uniformly by [-d, d]
                for i in range(4):
                    mutation = self.random.uniform(-self.d, self.d)
                    new_val = new_strategy[i] + mutation
                    # Keep probabilities in [0, 1]
                    new_val = (0 if new_val < 0 else
                               1 if new_val > 1 else new_val)
                    new_strategy[i] = new_val

        # Mutate by choosing a random strategy from the list set
        elif self.mutation_type == 'fixed':
            new_strategy = random.choice(
                list(self.strategies_to_count.values()))

        elif self.mutation_type == 'gaussian_sentimental':
            # Copy the damn list
            new_strategy = agent.strategy.copy()
            # There is a 20% chance of mutation
            if self.random.random() < 0.2:
                # Each Pi is mutated by a value drawn from a gaussian
                # with mean=delta_energy
                for i in range(4):
                    mutation = self.random.normalvariate(
                        (agent.delta_energy + self.alpha()) / 14, self.d)
                    new_val = new_strategy[i] + mutation
                    # Keep probabilities in [0, 1]
                    new_val = (0 if new_val < 0 else
                               1 if new_val > 1 else new_val)
                    new_strategy[i] = new_val

        return new_strategy

    def maybe_reproduce(self, agent):
        # If we have the energy to reproduce, do so
        if agent.total_energy >= self.p:
            # Create the child
            new_strategy = self.maybe_mutate(agent)
            child = GTAgent(self.agent_idx, agent.group_id, self, new_strategy,
                            self.i_energy)
            self.agent_idx += 1

            # Set parent and child energy levels to p/2
            child.total_energy = self.p / 2
            agent.total_energy = self.p / 2

            # Place child (Remove agent argument for global child placement)
            self.schedule.add(child)
            self.grid.place_agent(child, self.get_child_location(agent))

    def step(self):
        if self.debug:
            print('\n\n==================================================')
            print('==================================================')
            print('==================================================')
            pprint(vars(self))

        # First collect data
        self.datacollector.collect(self)

        # Then check for dead agents and for new agents
        for agent in self.schedule.agent_buffer(shuffled=True):
            # First check if dead
            if self.time_to_die(agent):
                self.grid.remove_agent(agent)
                self.schedule.remove(agent)

            # Otherwise check if can reproduce
            else:
                self.maybe_reproduce(agent)

        # Finally, step each agent
        self.schedule.step()

    def check_strategy(self, agent):
        # Helper function to check which strategy an agent would count as
        def is_same(strategy, a_strategy):
            tol = self.count_tolerance
            return all(strategy[i] - tol < a_strategy[i] < strategy[i] + tol
                       for i in range(4))

        return [
            name for name, strat in self.strategies_to_count.items()
            if is_same(strat, agent.strategy)
        ]
Exemplo n.º 34
0
class EconomicSystemModel(Model):
    """ A simple model of an economic system.

    All agents begin with certain revenue, each time step the agents
    execute its expenditures and sell its production. If they retain a
    healthy revenue, they can choose to hire and grow;
    otherwise they can choose to shrink;
    if too much debt is acquired the agent goes bankrupt.
    Let's see what happens to the system.
    """
    def __init__(self,
                 width=10,
                 height=10,
                 industry_pc=0.8,
                 services_pc=0.6,
                 tax_industry=0.1,
                 tax_services=0.2,
                 nsteps=60):
        """ Initialization method of economic system model class

        Parameters
        ----------
        width : int
            Grid width
        height : int
            Grid height
        industry_pc : float
            Industry percentage in the system
        services_pc : float
            Services percentage in the industry
        tax_industry : float
            Tax rate for industry sector
        tax_services : float
            Tax rate for services sector
        nsteps : int
            Number of time steps in months
        """

        # Model input attributes
        self.width = width
        self.height = height
        self.industry_pc = industry_pc
        self.services_pc = services_pc
        self.nsteps = nsteps

        # Order in which agents perform their steps,
        # random activation means no particular preference
        self.schedule = RandomActivation(self)

        # Grid initialization
        self.grid = SingleGrid(width, height, torus=True)

        # Data to be located per time step
        self.datacollector = DataCollector(model_reporters={
            "GDP": compute_gdp,
            "Employment": compute_employment
        },
                                           agent_reporters={
                                               "Employees": "employees",
                                               "Value": "value",
                                               "Industry": "type"
                                           })

        # Set up agents using a grid iterator that returns
        # the coordinates of a cell as well as its contents
        for cell in self.grid.coord_iter():

            # Cell coordinates
            x = cell[1]
            y = cell[2]

            # Assign industry type
            if self.random.random() < self.industry_pc:
                if self.random.random() < self.services_pc:
                    agent_type = 1
                else:
                    agent_type = 0

                # Initialize agent
                tax_rates = [tax_industry, tax_services]
                agent = IndustryAgent((x, y), self, agent_type, tax_rates)
                self.grid.position_agent(agent, (x, y))
                self.schedule.add(agent)

        # Running set to true and collect initial conditions
        self.running = True
        self.datacollector.collect(self)

        # Computed initial conditions of the model
        self.gdp = compute_gdp(self)
        self.employment = compute_employment(self)
        self.max_size_services = max_size_industry(self, 1)
        self.max_size_industry = max_size_industry(self, 0)
        self.max_size_industries = max_size_industry(self, -2)

    def step(self):
        '''
        Method to run one time step of the model
        '''

        # Run time step
        self.schedule.step()

        # Collect data
        self.datacollector.collect(self)

        # Computed metrics
        self.gdp = compute_gdp(self)
        self.employment = compute_employment(self)
        self.max_size_services = max_size_industry(self, 1)
        self.max_size_industry = max_size_industry(self, 0)
        self.max_size_industries = max_size_industry(self, -2)

        # Halt model after maximum number of time steps
        if self.schedule.steps == self.nsteps:
            self.running = False
Exemplo n.º 35
0
class HITLAdopt(Model):

    #modify init method to accout for new parameters and constants
    def __init__(self, height, width, density, wms, wts, wus, td, ve, ae):

        # Initialize model parameters
        self.height = height
        self.width = width
        self.density = density
        self.weeklyCampaignSpend = wms
        self.weeklyTrainingSpend = wts
        self.weeklyUsabilitySpend = wus

        #initialize HITL related parameters
        self.trainingDataWeeklyInput = td
        self.vizEffect = ve

        self.learningRate = 0
        self.dataInstances = 10000
        self.algoAccuracy = ae

        self.algoEffect = self.algoAccuracy * 0.1

        # Set up model objects

        #this sets the activation order of the agents (when they make their moves) to be random each step
        self.schedule = RandomActivation(self)

        #this creates the physical grid we are using to simulate word of mouth spread of the model
        self.grid = Grid(height, width, torus=False)

        #these use the Mesa DataCollector method to create several trackers to collect data from the model run
        self.dc_output = DataCollector(
            model_reporters={
                "Avg Output Value Per Person Per Week": compute_avg_output
            })
        self.dc_tracker = DataCollector(
            model_reporters={"Average IA": compute_avg_ia})
        self.dc_adoption = DataCollector({
            "Potential Trialer":
            lambda m: self.count_type(m, "Potential Trialer"),
            "Trialer":
            lambda m: self.count_type(m, "Trialer"),
            "Adopter":
            lambda m: self.count_type(m, "Adopter"),
            "Defector":
            lambda m: self.count_type(m, "Defector"),
            "Evangelist":
            lambda m: self.count_type(m, "Evangelist")
        })
        self.dc_trialers = DataCollector(
            {"Trialer": lambda m: self.count_type(m, "Trialer")})
        self.dc_algo = DataCollector({"Learning Rate": compute_learning_rate})

        self.dc_master = DataCollector({
            "Potential Trialer":
            lambda m: self.count_type(m, "Potential Trialer"),
            "Trialer":
            lambda m: self.count_type(m, "Trialer"),
            "Adopter":
            lambda m: self.count_type(m, "Adopter"),
            "Defector":
            lambda m: self.count_type(m, "Defector"),
            "Evangelist":
            lambda m: self.count_type(m, "Evangelist"),
            "Avg Output Value Per Person":
            compute_avg_output,
            "Total Differential in Population":
            hitl_adv_differential,
            "Algo Accuracy":
            compute_algo_accuracy,
            "Algo Accuracy Increase":
            compute_learning_rate,
            "Total Dataset Size":
            compute_data_instances,
            "Algorithm Effect":
            compute_algo_effect,
            "Avg Data Collection Ouput":
            compute_avg_dc,
            "Avg Data Interpretation/Analysis Output":
            compute_avg_di,
            "Avg Interpreting Actions Output":
            compute_avg_ia,
            "Avg Coaching Output":
            compute_avg_coaching,
            "Avg Review Output":
            compute_avg_review
        })

        #the logic for the creation of the agents, as well as setting the initial values of the agent parameters
        for x in range(self.width):
            for y in range(self.height):
                if random.random() < self.density:
                    new_consultant = Consultant(self, (x, y),
                                                np.random.normal(60, 10),
                                                np.random.normal(70, 10), 0)
                    if y == 0:
                        new_consultant.condition = "Trialer"
                    self.grid[y][x] = new_consultant
                    self.schedule.add(new_consultant)

        #run the model when the class is called
        self.running = True

    #define logic of what happens with each time step model-wide
    def step(self):

        ##update algorithm accuracy, data instances, and effect for new weekly data input
        self.learningRate = 10000 / self.dataInstances / 13 - (
            (self.count_type(self, "Trialer") + self.count_type(
                self, "Adopter") + self.count_type(self, "Evangelist")) /
            2000000)
        self.algoAccuracy += self.learningRate
        self.dataInstances += self.trainingDataWeeklyInput
        self.algoEffect = self.algoAccuracy * 0.1

        #logic for adoption from marketing, For every 1000 of additional weekly marketing spend, we get 1 new trialer consultant each week
        for i in range(1, (int(self.weeklyCampaignSpend / 100))):
            prospect = random.choice(self.schedule.agents)
            #change that agent's state to the next one up
            if prospect.condition == "Potential Trialer":
                prospect.condition = "Trialer"
            if prospect.condition == "Trialer":
                prospect.condition = "Adopter"

    #an abandoned idea for trial abandonment...I instead decided to model this at an agent level in that class (See above)
        '''for i in range (1,(int(self.weeklyMarketingSpend/50))):
            #take a random agent that's a trialer and log their x y location
            prospect = random.choice(model.schedule.agents)
            #change that agent's state to the next one up depending on what it is
            random_num = np.random.randint(1,100)
            if prospect.condition == "Trialer":
                if (prospect.techFluencyScore <70):
                    if random_num > 50:
                        prospect.condition = "PotentialTrialer"
        '''

        #sets the step count
        self.schedule.step()

        #logs appropriate data in each of the data collectors
        self.dc_output.collect(self)
        self.dc_adoption.collect(self)
        self.dc_tracker.collect(self)
        self.dc_algo.collect(self)
        self.dc_trialers.collect(self)
        self.dc_master.collect(self)

        #abandoned logic for stopping model - it was originally when there were no more trialers, now we just give it a set number of steps
        '''
        if self.count_type(self, "Trialer") == 0:
           self.running = False
        '''

    #method for counting the agents and their conditions so we can track adoption methods

    @staticmethod
    def count_type(model, consultant_condition):
        count = 0
        for consultant in model.schedule.agents:
            if consultant.condition == consultant_condition:
                count += 1
        return count
Exemplo n.º 36
0
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)
Exemplo n.º 37
0
class EconMod(Model):
    '''
    Model class for arming model.
    '''

    def __init__(self, height, width, density, 
    domestic_min, domestic_max, 
    domestic_mean, domestic_sd,
    num_adversaries, expenditures):
        '''
        '''

        self.height = height
        self.width = width
        self.density = density
        self.domestic_min = domestic_min
        self.domestic_max = domestic_max
        self.domestic_mean = domestic_mean
        self.domestic_sd = domestic_sd
        self.num_adversaries = num_adversaries
        self.expenditures = expenditures

        self.schedule = RandomActivation(self)  # All agents act at once
        self.grid = SingleGrid(height, width, torus=True)
        self.datacollector = DataCollector(
            # Collect data on each agent's arms levels
            agent_reporters = {
                "Arms": "arms",
                "Military_Burden": "mil_burden",
                "Econ": "econ",
                "Domestic": "domestic"
                })

        # Set up agents
        for cell in self.grid.coord_iter():
            x = cell[1]
            y = cell[2]
            if random.random() < self.density:
                ## Set starting economy for all
                ##econ_start = 10
                # Draw from pareto -- parameter set to 3, arbitrary
                econ_start = pareto.rvs(3,1)
                econ_growth = 0.03
                # domestic need -- determines econ variation
                #domestic_need = np.random.uniform(
                #    self.domestic_min,
                #    self.domestic_max
                #    )
                #https://stackoverflow.com/questions/18441779/how-to-specify-upper-and-lower-limits-when-using-numpy-random-normal
                lower, upper = self.domestic_min, self.domestic_max
                mu, sigma = self.domestic_mean, self.domestic_sd
                X = truncnorm(
                    (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
                domestic_need = X.rvs(1)

                
                expenditures = self.expenditures
                # starting percent of wealth spent on weapons
                arms_start_perc = np.random.uniform(0, 0.06) 
                arms = arms_start_perc * econ_start

                # create agent
                agent = state((x, y), self, econ_start = econ_start,
                            econ_growth = econ_growth, arms = arms,
                            domestic_need = domestic_need,
                            num_adversaries = num_adversaries,
                            expenditures = expenditures)

                # place agent in grid
                self.grid.position_agent(agent, (x, y))
                # add schedule
                self.schedule.add(agent)

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        '''
        Run one step of the model.
        '''
        # Collect data
        self.datacollector.collect(self)
        self.schedule.step()       
Exemplo n.º 38
0
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()
Exemplo n.º 39
0
class CancerModel(Model):
    def __init__(self,cancer_cells_number,cure_number,eat_values, verovatnoca_mutacije):
        self.counter = 0
        self.cure_number = cure_number
        radoznalosti = list(np.arange(0.01,KILLING_PROBABILITY,0.01))
        print(radoznalosti)
        self.datacollector = DataCollector(
        model_reporters = {"FitnessFunction":fitness_funkcija,
                           "SpeedSum":overall_speed,"SmartMedicine":num_of_smart_medicine,
                           "RadoznalostSum":radoznalost_sum  })
        grid_size = math.ceil(math.sqrt(cancer_cells_number*4))
        self.grid = MultiGrid(grid_size,grid_size,False)
        speeds = list(range(grid_size//2)) #popravi te boje TODO
        print(speeds)

        poss = self.generate_cancer_cell_positions(grid_size,cancer_cells_number)
        num_CSC = math.ceil(percentage(1,cancer_cells_number))
        pos_CSC = [self.random.choice(poss) for i in range(num_CSC)]
        self.schedule = RandomActivation(self)
        self.running = True
        for i in range(cancer_cells_number):
            pos = poss[i]
            c = CancerStemCell(uuid.uuid4(),self,value = eat_values[CancerStemCell.__class__]) if pos in pos_CSC else CancerCell(i,self,value=eat_values[CancerCell.__class__])
            self.grid.place_agent(c,pos)
            self.schedule.add(c)
        for i in range(cure_number):
            #pos = self.grid.find_empty()
            pos = (0,0)
            radoznalost = self.random.choice(radoznalosti)
            speed = self.random.choice(speeds)
            a = CureAgent(uuid.uuid4(),self,speed = speed,radoznalost=radoznalost) if i< cure_number//2 else SmartCureAgent(uuid.uuid4(),self,speed=speed,radoznalost = radoznalost)
            self.grid.place_agent(a,pos)
            self.schedule.add(a)

        for (i,(contents, x,y)) in enumerate(self.grid.coord_iter()):
            if not contents:
                c = HealthyCell(uuid.uuid4(),self,eat_values[HealthyCell.__class__])
                self.grid.place_agent(c,(x,y))
                self.schedule.add(c)

    def generate_cancer_cell_positions(self,grid_size,cancer_cells_number):
        center = grid_size//2
        poss = [(center,center)]
        for pos in poss:
            poss+=[n for n in self.grid.get_neighborhood(pos,moore=True,include_center=False) if n not in poss]
            if len(set(poss))>=cancer_cells_number:
                break
        poss = list(set(poss))
        return poss


    def duplicate_or_kill(self):
        koliko = math.ceil(percentage(5,self.cure_number)) # TODO igor javlja kako biramo procena
        cureagents = [c for c in self.schedule.agents if isinstance(c,CureAgent)]
        sortirani = sorted(cureagents, key=lambda x: x.points, reverse=True)
        poslednji = sortirani[-koliko:]
        prvi = sortirani[:koliko]
        assert(len(prvi)==len(poslednji))
        self.remove_agents(poslednji)
        self.duplicate_agents(prvi)

    def remove_agents(self,agents):
        for a in agents:
            self.schedule.remove(a)
            self.grid.remove_agent(a)
    def duplicate_agents(self,agents):
        for a in agents:
            a_new = a.__class__(uuid.uuid4(),model=self,speed = a.speed,radoznalost = a.radoznalost) #TODO ostale parametre isto poistoveti
            self.grid.place_agent(a_new,(1,1))
            self.schedule.add(a_new)

    def step(self):
        self.datacollector.collect(self)
        self.counter+=1
        self.schedule.step()
        if self.counter%10 ==0: # TODO ovo menjamo, parameter TODO
            #TODO sredi boje i
            #TODO sredi ovo pucanje zbog nule u latin hypercube
            #TODO napravi da je R promenljivo
            self.duplicate_or_kill()
Exemplo n.º 40
0
class GenModel(Model):
    """A model with some number of agents."""
    def __init__(self, N, width, height):
        self.running = True
        self.num_agents = N
        self.grid = MultiGrid(width, height, True)
        self.schedule = RandomActivation(self)
        self.uid = self.num_agents

        #model para
        #self.r1, self.r2 = 1.0, 1.0
        #self.her_max = MAX_CAPACITY
        #self.ver_max = MAX_CAPACITY
        #self.alpha12, self.alpha21 = 0.5, 0.5
        self.env_press = (np.sin(
            np.linspace(0, np.pi * 2 * ENV_PRESS_PERIOD, MAX_GEN_TICK) -
            0.5 * np.pi) + 1) / 2 * ENV_STRESS_COF  #?????

        #self.env_press = (np.sin(np.linspace(0, np.pi * 2 * ENV_PRESS_PERIOD, MAX_GEN_TICK)) +1 ) / 2 * ENV_STRESS_COF#?????
        #this is how enviroment values generated
        #all values are chosen from a rescaled sin functions
        #total periods for this sin is ENV_PRESS_PERIOD
        #total values number's are MAX_GEN_TICK

        # Create agents
        for i in range(self.num_agents):
            a = GenAgent(i, self, 0, gen_info=np.random.random(GEN_INFO_SIZE))
            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))

        #collect data
        self.datacollector = DataCollector(
            model_reporters={
                "two type ratio (hor/total)": compute_type_ratio,
                "env press": get_cur_press,
                "vertical generate env prob": compute_mean_ver_env_prob,
                "vertical generate self prob": compute_mean_ver_self_prob,
                "horizontal generate env prob": compute_mean_her_env_prob,
                "horizontal generate self prob": compute_mean_her_self_prob,
                "horizontal generate mean prob": compute_mean_her_prob,
                "horizontal num": compute_her_num,
                "vertical generate mean prob": compute_mean_ver_prob,
                "vertical num": compute_ver_num,
                "horizontal gene mean info": compute_mean_her_geneinfo,
                "vertical gene mean info": compute_mean_ver_geneinfo,
                "horizontal gene max info": compute_max_her_geneinfo,
                "vertical gene max info": compute_max_ver_geneinfo,
                "horizontal gene min info": compute_min_her_geneinfo,
                "vertical gene min info": compute_min_ver_geneinfo
            })

# def get_r(self):
#   env = self.cur_press
#    r1, r2 = 1 - two_curve(env), 1 - two_curve(env, 0.8)
#  return r1, r2

    def get_uid(self):
        uid = self.uid
        self.uid += 1
        return uid

    def get_ver_popu_size(self):
        return self.schedule.get_agent_count() - \
                np.sum([agent.gen_type for agent in self.schedule.agents])

    def get_her_popu_size(self):
        return np.sum([agent.gen_type for agent in self.schedule.agents])

    def get_popu_size(self):
        return self.schedule.get_agent_count()


#    def get_gr_rate(self):
#        cur_popu = self.get_popu_size()
#        her_popu = self.get_her_popu_size()
#        ver_popu = self.get_ver_popu_size()
#        #r1, r2 = self.get_r()
#        #ver_rate = r1 * (self.ver_max - ver_popu - self.alpha21 * her_popu)/self.ver_max
#        #her_rate = r2 * (self.her_max - her_popu - self.alpha12 * ver_popu)/self.her_max
#        ver_rate = (self.ver_max - ver_popu - self.alpha21 * her_popu)/self.ver_max
#        her_rate = (self.her_max - her_popu - self.alpha12 * ver_popu)/self.her_max
#        #print("popu and rate:")
#        #print(ver_popu, ver_rate)
#        #print(her_popu, her_rate)
#        return (ver_rate, her_rate)

    def init_env(self):
        self.cur_press, self.env_press = self.env_press[0], self.env_press[1:]

    def step(self):
        #if (self.schedule.steps + 1) % 3 == 0:
        #   self.press = True
        #else:
        #   self.press = False##selection every step, but can explore selection every k step
        self.press = True
        self.init_env()
        self.datacollector.collect(self)
        print("population size: ", self.get_popu_size())
        print("env pressure", self.cur_press)
        #self.gr_rate = self.get_gr_rate()
        #if self.press:print("env die")
        self.schedule.step()
Exemplo n.º 41
0
class GroupModel(Model):
    """
    The Group model

    Attributes:
        agents (dict or list of dicts):
            if passing a list of dictionaries -> [ {'epa' : [e,p,a],
                                                  'initial_tension': i_t},...]
            if passing  a single dictionary -> {'N': N, 'epa' : [e,p,a],
                                                'initial_tension': i_t,
                                                'individuality': ind}
        data_model (string):
            Determines which set of ACT equations to use for the simulation.
            Current options are: 'us_unisex', 'us_male', 'us_female',
            'canada_unisex', 'canada_male', 'canada_female', 'china_unisex',
            'ger_unisex'
        reciprocity_rate (float, optional):
            Probabilty for the an action to be reciprocal. Default 0.2.
        actor_choice (string, optional):
            sets the criterion on which the next actor is chosen.
            The default is 'max self-tension' which is currently also the only
            one implemented. In the future we might implement other options.
        object_choice (string, optional):
            sets the criterion on which the next object is chosen.
            The default is 'min event-tension' which selects object and behavior
            so that the sum of deflections for actor, behavior and object after
            the event is minimized relative to their fundamentals.
            'max deflection-reduction' selects object and behavior so that
            as much deflection as possible is reduced relative to before the event.
            'random' selects randomly among object candidates.
        action_on_group (Bool, optional):
            determines whether actions on the whole group are possible
        group_action_rate (float, optional):
            if passed, sets the propability for the next action to be on the
            whole group only makes sense if action_on_group is True.
        network_structure (tuple, optional):
            if interactions are restricted to a certain network structure,
            pass adjacency matrix in the form tuple of tuples ((),...())
        discrete_actions (list, optional):
            list of allowed actions of format [[e,p,a],...]
            if there is a network restriction on the actions the format is
            [[[e,p,a], network],...]
        seed (int, optional):
            seed passed to numpy.random to make simulation reproducible
    """

    def __init__(self, agents, data_model,
                 reciprocity_rate = 0.0,
                 actor_choice = "max self-tension",
                 object_choice = "min event-tension",
                 action_on_group = False,
                 group_action_rate = 0.0,
                 network_structure = None,
                 discrete_actions = None,
                 seed = None,
                 IPAs = IPA_EPAs_1978):
        self.running = True
        #set random seed, if given, to make simulations reproducible
        np.random.seed(seed=seed)
        #create agent list
        if isinstance(agents,list) or isinstance(agents, tuple):
            self.initial_agents = agents
            for i,ag in enumerate(self.initial_agents):
                if 'individuality' not in ag:
                    ag['individuality'] = 0.0
            self.num_agents = len(agents)
        elif isinstance(agents, dict):
            self.num_agents = agents['N']
            self.initial_agents = [{"epa": agents["epa"],
                                   "initial_tension": agents['initial_tension'],
                                   "individuality": agents["individuality"]}
                                   for i in range(agents["N"])]
        else:
            print("""as agents pass either a list of dictionaries
                     [ {'epa' : [e,p,a], 'initial_tension': i_t},...]
                     or a single dictionary
                     {'N': N, 'epa' : [e,p,a], 'initial_tension': i_t,
                      'individuality': ind}
                  """)
        self.schedule = RandomActivation(self)
        self.reciprocity_rate= reciprocity_rate
        self.reciprocal = False
        self.abo_coefficients = abo_coefficients_dict[data_model]
        self.network_matrix = np.zeros((self.num_agents,self.num_agents))
        self.actor_choice = actor_choice
        self.object_choice = object_choice
        self.action_on_group = action_on_group
        self.group_action_rate = group_action_rate
        # initialize network structure
        if network_structure is None:
            self.network_structure = None
        else:
            self.network_structure = np.array(network_structure)
        # set of allowed actions, if all (continous) actions are allowed
        # discrete_actions is set to None (default)
        self.discrete_actions = discrete_actions

        # Create agents
        for i, agent in enumerate(self.initial_agents):
            a = GroupMember(i, self, agent['epa'], agent['individuality'],
                            agent['initial_tension'])
            self.schedule.add(a)

        # if actions on the whole group are allowed, initialize the group
        if action_on_group:
            fundamentals = np.mean(
                [ag.fundamentals for ag in self.schedule.agents],
                axis=0)
            self.group = Group(fundamentals, fundamentals)

        # initial values
        self.actor = np.random.choice(self.schedule.agents)
        if self.action_on_group:
            # this prevents reciprocal action as first action
            self.object=self.group
        else:
            # random object
            self.object = np.random.choice(self.schedule.agents)
        self.action = np.zeros(3)

        # collect data
        self.datacollector = DataCollector(
            model_reporters={"actor": lambda x: x.actor.unique_id,
                             "action_E": lambda x: x.action[0],
                             "action_P": lambda x: x.action[1],
                             "action_A": lambda x: x.action[2],
                             "bales_category": lambda x: compute_bales(x.action, IPAs),
                             "object": lambda x: x.object.unique_id,
                            "reciprocal": "reciprocal"},
            agent_reporters={"Deflection": "personal_deflection",
                             "E": lambda x: x.current_transients[0],
                             "P": lambda x: x.current_transients[1],
                             "A": lambda x: x.current_transients[2]}
        )

        # record initial data of agents
        agent_records = self.datacollector._record_agents(self)
        self.datacollector._agent_records[self.schedule.steps] = list(agent_records)

    def select_actor(self):
        """ select next actor according to actor selection criterion,
            reciprocity probability and network structure.
            Next actor is determined by setting self.actor and subsequently
            self.actor.action = True"""
        # check actor choice exists and use default if not
        possible_actor_choices = ['max self-tension']
        if self.actor_choice not in possible_actor_choices:
            print('actor choice ', self.actor_choice,
                  'does not exist. fall back to max self-tension' )
            self.actor_choice = 'max self-tension'
        self.reciprocal = False
        if self.actor_choice == 'max self-tension':
            # check that last action was not on group
            # check that network structure permits reciprocal action
            if (self.action_on_group and self.object.unique_id != -1
                    and not (self.network_structure is None)
                    and ( self.network_structure[self.object.unique_id,
                                                 self.actor.unique_id] == 0) ):
                reciprocal_ok = False
            else:
                reciprocal_ok = True
            if (self.object.unique_id != -1
                    and reciprocal_ok
                    and np.random.random_sample() < self.reciprocity_rate):
                #reciprocal action
                self.actor, self.object  =  self.object, self.actor
                self.actor.acting = True
                self.reciprocal = True
            else:
                #non-reciprocal action
                self.actor = max(self.schedule.agents,
                                 key=lambda ag: ag.personal_deflection)
                self.actor.acting = True

    def step(self):
        self.select_actor()
        self.schedule.step()
        self.datacollector.collect(self)
Exemplo n.º 42
0
class SocialDistancing_Model(Model):
    """
    A model that creates an isolated neighbourhood on a grid. Individuals are placed arbitrarily on the grid initially, and with each step they are allowed to move to a neighbouring cell.
    A certain percentage of the initial population infected at random to characterise the initial outbreak. 
    As each individual agent moves across the grid, if they occupy a cell with another agent whos is already sick, there will be a certain probability (Transmission Rate) of themselves also being infected. 
    Infected individual agents can recover from the Virus after a certain duration of time (denoted as the Recovery Time). 
    A certain portion of the infected individuals die and are chosen randomly baseed on the Mortatlity Rate.
    Movement of individuals can be employed to indicate social distancing measures. 
    """
    def __init__(self, N, width, height, Initial_Outbreak, TR, RT, MR, Policy):
        self.num_agents = N
        self.grid = MultiGrid(width, height, False)
        self.Init_OB = Initial_Outbreak
        # self.TR = Transmission_Rate
        self.schedule = RandomActivation(self)
        self.running = True

        self.Transmission = TR  #Transmission Rate
        self.IP = 0  #Incubation Period
        self.Recovery = RT  #Recovery Time
        self.Mortality = MR

        self.policy = Policy  # Percentage Immobile

        # Create agents
        for i in range(self.num_agents):
            a = Individual(i, self)
            self.schedule.add(a)
            # Add the agent to a random grid cell
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)

            if self.random.random() < self.Init_OB:
                a.condition = 'Sick'
                a.infection_time = 1

            self.grid.place_agent(a, (x, y))

            model_reporters = {
                'Total': lambda m: m.schedule.get_agent_count(),
                'Healthy': lambda m: self.count_type(m, 'Healthy'),
                'Sick': lambda m: self.count_type(m, 'Sick'),
                'Immune': lambda m: self.count_type(m, 'Immune')
            }

        self.datacollector = DataCollector(model_reporters=model_reporters)

    def step(self):
        self.datacollector.collect(
            self)  #Ensuring the data is stored from all agents for all models.
        self.schedule.step()

        if self.schedule.time == 100:
            self.running = False

    @staticmethod
    def count_type(model, individual_condition):
        """
        Helper method to count trees in a given condition in a given model.
        """
        count = 0
        for individual in model.schedule.agents:
            if individual.condition == individual_condition:
                count += 1
        return count
Exemplo n.º 43
0
class Modelo(Model):
    #Algunas constantes
    SUCEPTIBLE = 0
    EXPUESTO = 1
    INFECTADO = 2
    RECUPERADO = 3
    salud_to_str={0:'Suceptible', 1:'Expuesto', 2:'Infectado', 3:'Recuperado'}
    pp_dia = 4 ## Son los pasos dados por dia simulado
    def __init__(self, N, city_object, agent_object):
        super().__init__()
        self.num_ind = N
        self.city_object = city_object
        self.agent_object = agent_object
        self.schedule = RandomActivation(self)
        self.crearciudad()
        self.n_paso = 0
        
        ## Se define el grid que se representará en la 
        self.grid = self.ciudad.nodes['ciudad']['espacio']
        self.datacollector = DataCollector(
            model_reporters = {'Suceptibles': self.conteo_func(self.SUCEPTIBLE),
                               'Expuestos': self.conteo_func(self.EXPUESTO),
                               'Infectados': self.conteo_func(self.INFECTADO),
                               'Recuperados': self.conteo_func(self.RECUPERADO)})
        self.conteo_instantaneo = [N,0,0,0]
    
    def crearciudad(self):
        self.ciudad = self.city_object(self, self.agent_object)
        for ind in self.ciudad.generarindividuos():
            self.schedule.add(ind)
        
        #Se planta un infectado en la simulación
        for ind in choices(self.schedule.agents, k = 10):
            ind.salud = self.EXPUESTO
        
        #Se crean las casas distribuyendo los individuos
        self.ciudad.crear_hogares()
        
        
        #Se agrega una tienda a la ciudad y se conecta con todas las casas
        self.ciudad.crear_nodo('ciudad', tipo='ciudad', tamano=75)
        self.ciudad.conectar_a_casas('ciudad')
    
    def step(self):
        self.momento = self.n_paso % self.pp_dia #es el momento del dia
        self.conteo()
        self.datacollector.collect(self)
        self.schedule.step()
        self.n_paso += 1

    
    def conteo(self):
        #Una función para contar los casos actuales en la ciudad
        self.conteo_instantaneo = [0,0,0,0]
        for a in self.schedule.agents:
            self.conteo_instantaneo[a.salud] += 1
        return self.conteo_instantaneo

    def conteo_func(self, tipo):
        def contar(modelo):
            return modelo.conteo_instantaneo[tipo]
        return contar
Exemplo n.º 44
0
class Forest (Model): 
    def __init__ (self,  
                endophytism = True, ## allow endophyte life style in model run
                ws = 30, ## initial num of wood
                endodisp=2.0, ## dispersal of endos
                decompdisp=10.0, ## dispersal of decomps
                leafdisp = 4.0, ## how well do leaves disperse
                leaffall = 1, ## how frequently do leaves disperse
                numdecomp=1, ## initial number of decomposers
                numendo=1,   ## initial number of endos
                endoloss=0.05,   ## rate of loss of endophyte infect per step
                newwood = 15, ## total energy added in new logs each step
                woodfreq = 1, ## how often to put new logs onto the landscape 
                width = 100, ## grid dimensions, only one (squares only)
                kappa = 0.03, ## average rate of parent tree clusters per unit distance 
                sigma = 3.0, ## variance of child tree clusters, +/- spread of child clusters
                mu = 2.2, ## average rate of child tree clusters per unit distance 
                nuke = False, ## make landscape, but no agents
                ): 

        self.endophytism = endophytism 
        self.nwood = ws 
        self.endodisp = endodisp 
        self.decompdisp = decompdisp 
        self.leafdisp = leafdisp
        self.leaffall = leaffall 
        self.numdecomp = numdecomp 
        self.numendo = numendo 
        self.endoloss = endoloss 
        self.newwood = newwood 
        self.woodfreq = woodfreq
        self.schedule = RandomActivation(self) 
        self.grid = MultiGrid(width, width, torus = True)
        self.running = True
        self.width = width 
        self.kappa = kappa
        self.sigma = sigma
        self.mu = mu
        self.decompspor = 0 ## sporulation events this turn
        self.endospor = 0 ## sporulation events this turn
        self.datacollector = DataCollector(
            model_reporters={
                "Endophytes": sumendos,
                "Endo_subs": Endo_subs,
                "Decomposers": sumdecomps,
                "Decomp_subs": Decomp_subs,
                "Infected_trees": bluetrees,
                "decompspor_count": decompspor_count,
                "endospor_count": endospor_count,
                "Trees": tracktrees,
                })

        ## make initial agents:
        if not nuke: ## if not a nuclear holocaust where life is devoid
            self.make_trees()
            for i in range(self.nwood): self.add_wood() ## no make_woods method
            self.make_fungi()

    def make_trees(self):
        ## let's use our thomas process module
        tname = 1

        positions = tp.makepos(tp.ThomasPP(kappa = self.kappa, 
                                sigma=self.sigma, 
                                mu=self.mu, 
                                Dx=self.grid.width-1))
        for i in positions:
                try:
                    tree = Tree(tname, self, i, 
                                disp = self.leafdisp, 
                                leaffall = self.leaffall,
                                endoloss = self.endoloss,
                                infection = False)
                    self.schedule.add(tree) 
                    self.grid.place_agent(tree, i)
                    tname += 1
                except IndexError:
                    print ("Tree out-of-bounds, ipos=",i,"grid dim=", self.grid.width, self.grid.height)

    ## add initial wood to landscape
    def add_wood(self): 
        wname = len(self.getall(Wood)) + 1 
        x = random.randrange(self.grid.width)
        y = random.randrange(self.grid.height)
        pos = (x, y)
        ## wood already present? then just add to the pile
        if any([ type(i)==Wood for i in self.grid.get_cell_list_contents(pos) ]):
            for i in self.grid.get_cell_list_contents(pos):
                if type(i)==Wood: 
                    i.energy += random.randrange(self.newwood) ## 
        else:
            wood = Wood(wname, self, pos, energy = random.randrange(self.newwood)+1) ## 
            self.grid.place_agent(wood, (x,y))
            self.schedule.add(wood)
            wname += 1 

    ## non-initial, step addition of wood
    def cwd(self): 
        cwdlist = [round(random.randrange(self.newwood))+1] ## our first log of the step, at least 1 
        while sum(cwdlist) < round(self.newwood*.9)-1 : ## until we get at 90% of our assigned cwd...
            newlog=round(random.randrange(self.newwood-sum(cwdlist)))+1 ## new log, at least 1 kg
            cwdlist.append(newlog) ## put newlog on the list, until newwood reached)
        wname = len(self.getall(Wood)) + 1 
        for i in cwdlist:
            self.add_wood()

    def make_fungi(self):
        fname = len(self.getall(Fungus)) + 1 

        ## decomposers first:
        decomps=0
        while decomps < self.numdecomp:
            pos = self.findsubstrate(Wood)
            if any([ type(i)==Fungus for i in self.grid.get_cell_list_contents(pos) ]):
                pass 
            else:
                fungus = Fungus(fname, self, pos, energy=10, endocomp=False, disp = self.decompdisp)
                self.schedule.add(fungus) 
                self.grid.place_agent(fungus, pos)
                fname += 1; decomps += 1

        ## then endophytes:
        endos=0
        while endos < self.numendo:
            pos = self.findsubstrate(Wood)
            if any([ type(i)==Fungus for i in self.grid.get_cell_list_contents(pos) ]):
                pass
            else:
                fungus = Fungus(fname, self, pos, energy=10, endocomp=True, disp = self.endodisp)
                self.schedule.add(fungus) 
                self.grid.place_agent(fungus, pos)
                fname += 1; endos += 1


    def findsubstrate (self, substrate):
        Subs = self.getall(substrate)
        try:
            somestick = (random.choice(Subs).pos) ## pick from these, return position
            return(somestick) ## pick from these, return position
        except IndexError:
            print("no substrates")
            pass

    def selthin(self, intensity):
        ## intensity should be in the form of a percentage
        aa=self.getall(Tree)
        if intensity > 1 or intensity < 0:
                print("too intense! (or not intense enough)")
                pass
        else:
            bb=random.sample(aa, int(len(aa)*intensity))
            [ i.die() for i in bb ]




    def getall(self, typeof):
        if not any([ type(i)==typeof for i in self.schedule.agents ]):
            return([])
        else:
            istype = np.array([ type(i)==typeof for i in self.schedule.agents ])
            ags = np.array(self.schedule.agents)
            return list(ags[istype])


############### deforestation functions ###########

## forest fragmentation:

    def fragcenters(self,cens):
    ## cens=number of forest fragments
        centers=[]
        for i in range(cens):
            x=int(random.random()*self.width) ## self.width instead
            y=int(random.random()*self.width) ## self.width instead
            z=(x,y)
            centers.append(z)
        return(centers)


    def onefrag(self, center, ags, rad=10):
    ## center=center of fragment
    ## ags = list of trees
    ## rad = radius of fragment to be protected
        survivors = []
        for i in ags:
            distf=((center[0]-i.pos[0])**2 + (center[1]-i.pos[1])**2)**(1/2)
            if distf <= rad: survivors.append(i)
        return(survivors)

    def fragup(self, centers, rad):
        ## 1 - get trees
        alltrees = self.getall(Tree)
        ## 2 - get centers
        fcenters = self.fragcenters(centers)
        ## 3 - designate survivors
        remnants = []
        for i in fcenters:
            surv=self.onefrag(i, alltrees, rad)
            remnants.extend(surv)
        ## kill everything else
        cuttrees = set(alltrees) - set(remnants)
        for i in cuttrees: i.die()
        ## maybe useful for plotting, return the objects
        return({"alltrees":alltrees,
                "centers":fcenters,
                "remnants":remnants,
                "cuttrees":cuttrees,
                })

## Selective thinning:

    def selthin(self, intensity):
        ## intensity should be in the form of a percentage
        aa=self.getall(Tree)
        if intensity > 1:
                print("too intense!")
                pass
        else:
            bb=random.sample(aa, int(len(aa)*intensity))
        for i in bb: i.die() ## kill em
    ## plot data:
        return({"alltrees":aa,
                "centers":None,
                "remnants":self.getall(Tree),
                "cuttrees":bb,
                })

############################################################# 
## step


    def step(self): 
        if self.schedule.time % self.woodfreq ==  self.woodfreq - 1: ##  = delay from start
            self.cwd() ## add wood
        self.schedule.step() ## agents do their thing
        self.datacollector.collect(self) ## collect data
        self.decompspor = 0 ## reset sporulation event tally
        self.endospor = 0 ## reset sporulation event tally
Exemplo n.º 45
0
class SeqRosModel(Model):
    def __init__(self):
        self.speed_model_plus = Net(4096)
        self.speed_model_plus.load_state_dict(
            torch.load('./trained_models/TMM.pkl',
                       map_location=lambda storage, loc: storage))
        self.file_path = NUCLEI_DATA_PATH + 't%03d-nuclei'

        print('Parsing the Embryo...')
        self.embryo = Embryo(NUCLEI_DATA_PATH)
        self.embryo.read_data()
        self.embryo.get_embryo_visual_params()

        self.embryo.volume = 2500578

        self.ai_cell = AI_CELL

        self.start_point = START_POINT
        self.end_point = END_POINT

        self.ticks = 0
        self.tick_resolution = TICK_RESOLUTION
        self.end_tick = (self.end_point -
                         self.start_point) * self.tick_resolution
        self.stage_destination_point = self.start_point

        self.plane_resolution = PLANE_RESOLUTION

        self.current_cell_list = []
        self.dividing_cell_overall = []
        self.next_stage_destination_list = {}
        self.schedule = RandomActivation(self)

        self.init_env()
        self.update_stage_destination()

        self.plane = DrawPlane(width=self.embryo.width,
                               height=self.embryo.height,
                               w_offset=self.embryo.wid_offset,
                               h_offset=self.embryo.hei_offset,
                               scale_factor=CANVAS_DISPLAY_SCALE_FACTOR)
        self.canvas = self.plane.canvas
        self.plane_draw = PLANE_DRAW
        self.draw(self.plane_draw)

    def draw(self, n_plane):
        self.canvas.delete("all")
        draw_range = np.arange(n_plane - PLANE_THRESHOLD,
                               n_plane + PLANE_THRESHOLD + 1, 1)
        draw_range = draw_range.tolist()
        draw_range.reverse()

        for n in draw_range:
            angle = np.pi * 0.5 / (PLANE_THRESHOLD + 1) * np.abs(n - n_plane)
            level = None
            for cell in self.schedule.agents:
                if cell.cell_name == self.ai_cell:
                    type = 'AI'
                else:
                    type = 'NUMB'
                if round(cell.location[2]) == n:
                    self.plane.draw_cell(center=cell.location[0:2],
                                         radius=cell.diameter / 2.0 *
                                         np.cos(angle),
                                         type=type,
                                         level=level)
        self.canvas.pack()
        self.canvas.update()
        time.sleep(FRESH_TIME)

    def radis_ratio(self, cn):
        r = -1
        if cn[0:2] == "AB":
            r = 0.55 * (0.5**(len(cn) - 2))
        elif cn == "P1":
            r = 0.45
        elif cn == "EMS":
            r = 0.45 * 0.54
        elif cn == "P2":
            r = 0.45 * 0.46
        elif cn[0:2] == "MS":
            r = 0.45 * 0.54 * 0.5 * (0.5**(len(cn) - 2))
        elif cn == "E":
            r = 0.45 * 0.54 * 0.5
        elif cn[0] == "E" and len(cn) >= 2 and cn[1] != "M":
            r = 0.45 * 0.54 * 0.5 * (0.5**(len(cn) - 1))
        elif cn[0] == "C":
            r = 0.45 * 0.46 * 0.53 * (0.5**(len(cn) - 1))
        elif cn == "P3":
            r = 0.45 * 0.46 * 0.47
        elif cn[0] == "D":
            r = 0.45 * 0.46 * 0.47 * 0.52 * (0.5**(len(cn) - 1))
        elif cn == "P4":
            r = 0.45 * 0.46 * 0.47 * 0.48
        if r == -1:
            return 0.00000001
        return r**(1.0 / 3)

    def get_radius(self, cell_name):
        if cell_name[0:2] == "AB":
            v = 0.55 * (0.5**(len(cell_name) - 2))
        elif cell_name == "P1":
            v = 0.45
        elif cell_name == "EMS":
            v = 0.45 * 0.54
        elif cell_name == "P2":
            v = 0.45 * 0.46
        elif cell_name[0:2] == "MS":
            v = 0.45 * 0.54 * 0.5 * (0.5**(len(cell_name) - 2))
        elif cell_name == "E":
            v = 0.45 * 0.54 * 0.5
        elif cell_name[0] == "E" and len(
                cell_name) >= 2 and cell_name[1] != "M":
            v = 0.45 * 0.54 * 0.5 * (0.5**(len(cell_name) - 1))
        elif cell_name[0] == "C":
            v = 0.45 * 0.46 * 0.53 * (0.5**(len(cell_name) - 1))
        elif cell_name == "P3":
            v = 0.45 * 0.46 * 0.47
        elif cell_name[0] == "D":
            v = 0.45 * 0.46 * 0.47 * 0.52 * (0.5**(len(cell_name) - 1))
        elif cell_name == "P4":
            v = 0.45 * 0.46 * 0.47 * 0.48
        elif cell_name in ['Z2', 'Z3']:
            v = 0.45 * 0.46 * 0.47 * 0.48 * 0.5
        else:
            print('ERROR!!!!! CELL NOT FOUND IN CALCULATING HER RADIUS!!!!',
                  cell_name)
            print('Use an average value.')
            v = v = 0.55 * (0.5**(9 - 2))  #ABarppppa

        radius = pow(self.embryo.volume * v / (4 / 3.0 * np.pi), 1 / 3.0)
        radius = radius

        return radius

    def get_cell_daughter(self, cell_name, cell_dict):
        daughter = []
        if cell_name == 'P0':
            daughter = ['AB', 'P1']
        elif cell_name == 'P1':
            daughter = ['EMS', 'P2']
        elif cell_name == 'P2':
            daughter = ['C', 'P3']
        elif cell_name == 'P3':
            daughter = ['D', 'P4']
        elif cell_name == 'P4':
            daughter = ['Z2', 'Z3']
        elif cell_name == 'EMS':
            daughter = ['MS', 'E']
        ## standard name ###
        else:
            for cell in cell_dict.keys():
                if cell.startswith(cell_name) and len(
                        cell) == len(cell_name) + 1:
                    daughter.append(cell)
            daughter = sorted(daughter)
        if daughter == []:
            daughter = ['', '']
        return daughter

    def init_env(self):
        with open(self.file_path % self.start_point) as file:
            for line in file:
                line = line[:len(line) - 1]
                vec = line.split(', ')
                id = int(vec[0])
                location = np.array(
                    (float(vec[5]), float(vec[6]), float(vec[7])))
                ########### add noise to initial location##################
                location_noise = np.random.normal(0, 0.1, 2)
                location[0:2] = location[0:2] + location_noise
                ########### add noise to initial location##################
                diameter = float(vec[8])
                cell_name = vec[9]
                if cell_name[0:3] == 'Nuc':
                    continue
                if cell_name != '':
                    self.current_cell_list.append(cell_name)
                    a = CellAgent(id, self, cell_name, location, diameter)
                    self.schedule.add(a)

    def set_cell_next_location(self):
        for cell in self.schedule.agents:
            if cell.cell_name in self.next_stage_destination_list:
                cell.next_location = (self.next_stage_destination_list[cell.cell_name][0:3] - cell.location) \
                    / (self.tick_resolution - self.ticks % self.tick_resolution) + cell.location
                cell.diameter = self.next_stage_destination_list[
                    cell.cell_name][3]
            else:
                ### new cell born ###
                mother = cell.cell_name
                daughter = self.get_cell_daughter(
                    cell.cell_name, self.next_stage_destination_list)
                if daughter[0] == '':
                    print('ERROR!!!!! NO DAUGHTER FOUND!!!!!')
                cell.cell_name = daughter[0]
                cell.diameter = self.next_stage_destination_list[
                    daughter[0]][3]
                cell.next_location = (self.next_stage_destination_list[daughter[0]][0:3] - cell.location) \
                    / (self.tick_resolution - self.ticks % self.tick_resolution) + cell.location
                new_id = len(self.schedule.agents) + 1
                new_diameter = self.next_stage_destination_list[daughter[1]][3]
                a = CellAgent(new_id, self, daughter[1], cell.location,
                              new_diameter)
                self.schedule.add(a)
                a.next_location = (self.next_stage_destination_list[daughter[1]][0:3] - a.location) \
                    / (self.tick_resolution - self.ticks % self.tick_resolution) + a.location

                self.dividing_cell_overall.append(mother)

    def update_stage_destination(self):
        current_stage_destination_point = self.start_point + 1 + int(
            self.ticks / self.tick_resolution)
        if self.stage_destination_point == current_stage_destination_point:
            return
        else:
            self.stage_destination_point = current_stage_destination_point
            self.next_stage_destination_list.clear()
            with open(self.file_path % self.stage_destination_point) as file:
                for line in file:
                    line = line[:len(line) - 1]
                    vec = line.split(', ')
                    id = int(vec[0])
                    loc_and_dia = np.array((float(vec[5]), float(vec[6]),
                                            float(vec[7]), float(vec[8])))
                    cell_name = vec[9]
                    if cell_name != '':
                        self.next_stage_destination_list[
                            cell_name] = loc_and_dia

    def render(self):
        if self.ticks % FRESH_PERIOD == 0:
            self.draw(self.plane_draw)

    def reset(self):
        self.ticks = 0

        self.start_point = START_POINT
        self.end_point = END_POINT

        self.end_tick = (self.end_point -
                         self.start_point) * self.tick_resolution
        self.stage_destination_point = self.start_point
        self.current_cell_list = []
        self.dividing_cell_overall = []
        self.next_stage_destination_list = {}

        del self.schedule.agents[:]
        self.init_env()
        self.update_stage_destination()
        s = self.get_state()

        return s

    def get_state(self):
        s = []
        low_plane = PLANE_DRAW - INPUT_PLANE_RANGE
        if low_plane <= 1:
            low_plane = 1
        high_plane = PLANE_DRAW + INPUT_PLANE_RANGE + 1
        for p in range(low_plane, high_plane):
            image = Image.new('RGB',
                              (self.embryo.width - self.embryo.wid_offset,
                               self.embryo.height - self.embryo.hei_offset))
            draw = ImageDraw.Draw(image)
            for cell in self.schedule.agents:
                if cell.cell_name == self.ai_cell:
                    fill_color = 'red'
                else:
                    fill_color = 'green'
                cell_loc = np.array((cell.location[0], cell.location[1], \
                    cell.location[2] * self.plane_resolution))
                radius = self.get_radius(cell.cell_name)
                z_diff = cell_loc[2] - p * self.plane_resolution
                if abs(z_diff) < radius:
                    radius *= 0.5
                    z_diff *= 0.5
                    radius_projection = (radius**2 - z_diff**2)**0.5
                    draw.ellipse((cell_loc[0] - radius_projection -
                                  self.embryo.wid_offset, cell_loc[1] -
                                  radius_projection - self.embryo.hei_offset,
                                  cell_loc[0] + radius_projection -
                                  self.embryo.wid_offset, cell_loc[1] +
                                  radius_projection - self.embryo.hei_offset),
                                 fill=fill_color,
                                 outline='black')

            image = image.resize((128, 128))
            image_np = np.array(image).astype(
                np.float32) / 255  #widthxheightx3
            image_np = np.rollaxis(image_np, 2)  #3x2widthxheight
            if len(s) == 0:
                s = image_np
            else:
                s = np.concatenate((s, image_np), axis=0)

        return s

    def step(self):
        r = 0
        done = False
        sg_done = False
        if self.ticks > 0 and self.ticks % self.tick_resolution == 0:
            self.update_stage_destination()

        self.set_cell_next_location()
        self.schedule.step()
        self.ticks += 1

        s_ = self.get_state()
        ai_location = np.zeros(3)

        for cell in self.schedule.agents:
            if cell.cell_name == self.ai_cell:
                ai_location = np.array((cell.location[0], cell.location[1], \
                    cell.location[2] * self.plane_resolution))

        if self.ticks == self.end_tick:
            done = True

        return s_, r, sg_done, done
Exemplo n.º 46
0
class SeparationBarrierModel(Model):
    def __init__(self, height, width, palestinian_density, settlement_density,
                 settlers_violence_rate, settlers_growth_rate, suicide_rate, greed_level,
                 settler_vision=1, palestinian_vision=1, 
                 movement=True, max_iters=1000):

        super(SeparationBarrierModel, self).__init__()
        self.height = height
        self.width = width
        self.palestinian_density = palestinian_density
        self.settler_vision = settler_vision
        self.palestinian_vision = palestinian_vision
        self.settlement_density = settlement_density
        self.movement = movement
        self.running = True
        self.max_iters = max_iters
        self.iteration = 0
        self.schedule = RandomActivation(self)
        self.settlers_violence_rate = settlers_violence_rate
        self.settlers_growth_rate = settlers_growth_rate
        self.suicide_rate = suicide_rate
        self.greed_level = greed_level

        self.total_violence = 0

        self.grid = SingleGrid(height, width, torus=False)

        model_reporters = {
        }
        agent_reporters = {
#           "x": lambda a: a.pos[0],
#           "y": lambda a: a.pos[1],
        }
        self.dc = DataCollector(model_reporters=model_reporters,
                                agent_reporters=agent_reporters)
        self.unique_id = 0

        # Israelis and palestinans split the region in half
        for (contents, x, y) in self.grid.coord_iter():
            if random.random() < self.palestinian_density:
                palestinian = Palestinian(self.unique_id, (x, y), vision=self.palestinian_vision, breed="Palestinian",
                          model=self)
                self.unique_id += 1
                self.grid.position_agent(palestinian, x,y)
                self.schedule.add(palestinian)
            elif ((y > (self.grid.height) * (1-self.settlement_density)) and random.random() < self.settlement_density):
                settler = Settler(self.unique_id, (x, y),
                                  vision=self.settler_vision, model=self, breed="Settler")
                self.unique_id += 1
                self.grid.position_agent(settler, x,y)
                self.schedule.add(settler)

    def add_settler(self, pos):
        settler = Settler(self.unique_id, pos,
                          vision=self.settler_vision, model=self, breed="Settler")
        self.unique_id += 1
        self.grid.position_agent(settler, pos[0], pos[1])
        self.schedule.add(settler)

    def set_barrier(self,victim_pos, violent_pos):
        #print("Set barrier - Greed level", self.greed_level)
        visible_spots = self.grid.get_neighborhood(victim_pos,
                                                        moore=True, radius=self.greed_level + 1)
        furthest_empty  = self.find_furthest_empty_or_palestinian(victim_pos, visible_spots)
        x,y = furthest_empty
        current = self.grid[y][x]
        #print ("Set barrier!!", pos, current)
        free = True
        if (current is not None and current.breed == "Palestinian"):
            #print ("Relocating Palestinian")
           free =  self.relocate_palestinian(current, current.pos)

        if (free):
            barrier = Barrier(-1, furthest_empty, model=self)
            self.grid.position_agent(barrier, x,y)
        
        # Relocate the violent palestinian
        #violent_x, violent_y = violent_pos
        #if violent_pos != furthest_empty:
        #    violent_palestinian = self.grid[violent_y][violent_x]
        #    self.relocate_palestinian(violent_palestinian, furthest_empty)

    def relocate_palestinian(self, palestinian, destination):
        #print ("Relocating Palestinian in ", palestinian.pos, "To somehwhere near ", destination)
        visible_spots = self.grid.get_neighborhood(destination,
                                                        moore=True, radius=palestinian.vision)
        nearest_empty = self.find_nearest_empty(destination, visible_spots)
        #print("First Nearest empty to ", palestinian.pos, " Is ", nearest_empty)
        if (nearest_empty):
            self.grid.move_agent(palestinian, nearest_empty)
        else:
            #print ("Moveing to random empty")
            if (self.grid.exists_empty_cells()):
                self.grid.move_to_empty(palestinian)
            else:
                return False

        return True

    def find_nearest_empty(self, pos, neighborhood):
        nearest_empty = None
        sorted_spots = self.sort_neighborhood_by_distance(pos, neighborhood)
        index = 0
        while (nearest_empty is None and index < len(sorted_spots)):
            if self.grid.is_cell_empty(sorted_spots[index]):
                nearest_empty = sorted_spots[index]
            index += 1

        return nearest_empty

    def find_furthest_empty_or_palestinian(self, pos, neighborhood):
        furthest_empty = None
        sorted_spots = self.sort_neighborhood_by_distance(pos, neighborhood)
        sorted_spots.reverse()
        index = 0
        while (furthest_empty is None and index < len(sorted_spots)):
            spot = sorted_spots[index]
            if self.grid.is_cell_empty(spot) or self.grid[spot[1]][spot[0]].breed == "Palestinian" :
                furthest_empty = sorted_spots[index]
            index += 1

        return furthest_empty



    def sort_neighborhood_by_distance(self, from_pos, neighbor_spots):
        from_x, from_y = from_pos
        return sorted(neighbor_spots, key = lambda spot: self.eucledean_distance(from_x, spot[0], from_y, spot[1], self.grid.width, self.grid.height))


    def eucledean_distance(self, x1,x2,y1,y2,w,h):
        # http://stackoverflow.com/questions/2123947/calculate-distance-between-two-x-y-coordinates
        return math.sqrt(min(abs(x1 - x2), w - abs(x1 - x2)) ** 2 + min(abs(y1 - y2), h - abs(y1-y2)) ** 2)
        

    def step(self):
        """
        Advance the model by one step and collect data.
        """
        self.violence_count = 0
      #  for i in range(100):
        self.schedule.step()
        self.total_violence += self.violence_count
      #  average = self.violence_count / 100
        #print("Violence average %f " % average)
        print("Total Violence: ", self.total_violence)
Exemplo n.º 47
0
class Anthill(Model):
    def __init__(self):

        self.grid = SingleGrid(WIDTH, HEIGHT, False)
        self.schedule = RandomActivation(self)
        self.running = True
        self.internalrate = 0.2
        self.ant_id = 1
        self.tau = np.zeros((WIDTH,HEIGHT))
        self.datacollector = DataCollector({"Total number of Ants": lambda m: self.get_total_ants_number(),
                                            "mean tau": lambda m: self.evaluation1(),
                                            "sigma": lambda m: self.evaluation2(),
                                            "sigma*" :  lambda m: self.evaluation3(),
                                            })

        # List containing all coordinates of the boundary, initial ants location and brood location
        self.bound_vals = []
        self.neigh_bound = []
        self.middle=[]
        self.datacollector.collect(self)
        self.passage_to_right = []
        self.passage_to_left = []

        # for i in range(WIDTH):
        #     for j in range(HEIGHT):
        #         if i == 0 or j == 0 or i == WIDTH-1 or j == HEIGHT-1:
        #             self.bound_vals.append((i,j))
        #         if i == 1 or i == WIDTH - 2 or j == 1 or j == HEIGHT-2:
        #             self.neigh_bound.append((i,j))
        ##

        for i in range(WIDTH):
            for j in range(HEIGHT):
                ##make boundary
                if i == 0 or j == 0 or i == WIDTH - 1 or j == HEIGHT - 1:
                    self.bound_vals.append((i,j))
                if i == MIDDLE and 0<j<WIDTH - 1:
                    self.bound_vals.append((i,j))
                    self.middle.append((i,j))

                ##save neighbor
                if j ==1 and 1<= i <= MIDDLE-2:
                    self.neigh_bound.append((i,j))
                if j ==1 and MIDDLE+2<=i<=WIDTH - 2:
                    self.neigh_bound.append((i,j))
                if j ==HEIGHT - 1 and 1<= i <= MIDDLE-2:
                    self.neigh_bound.append((i,j))
                if j ==HEIGHT - 1 and MIDDLE+2<=i<=WIDTH - 2:
                    self.neigh_bound.append((i,j))
                if i == 1 and 2<= j<= MIDDLE-3:
                    self.neigh_bound.append((i, j))
                if i == HEIGHT - 2 and 2<= j<= MIDDLE-3:
                    self.neigh_bound.append((i, j))

                ## we let the columns next to th middle become the entrance to next chamber
                if i == MIDDLE-1 and 0<j<WIDTH-1:
                    self.passage_to_left.append((i, j))
                if i == MIDDLE + 1 and 0 < j < WIDTH - 1:
                    self.passage_to_right.append((i, j))




        # Make a Fence boundary
        b = 0
        for h in self.bound_vals:
            br = Fence(b,self)

            self.grid.place_agent(br,(h[0],h[1]))
            b += 1



    def step(self):
        '''Advance the model by one step.'''

        # Add new ants into the internal area ont he boundary
        for xy in self.neigh_bound:
            # Add with probability internal rate and if the cell is empty
            if self.random.uniform(0, 1) < self.internalrate and self.grid.is_cell_empty(xy) == True:

                a = Ant(self.ant_id, self)

                self.schedule.add(a)
                self.grid.place_agent(a,xy)

                self.ant_id += 1

        # Move the ants
        self.schedule.step()
        self.datacollector.collect(self)

        # with open("data/p02_b0_tau.txt", "a") as myfile:
        #     myfile.write(str(self.mean_tau_ant) + '\n')
        # with open("data/p02_b0_sigma.txt", "a") as myfile:
        #     myfile.write(str(self.sigma) + '\n')
        # with open("data/p02_b0_sigmastar.txt","a") as myfile:
        #     myfile.write(str(self.sigmastar) + "\n")

    def get_total_ants_number(self):
        total_ants=0
        for (agents, _, _) in self.grid.coord_iter():
            if type(agents) is Ant:
                total_ants += 1
        return total_ants

    def evaluation1(self):
        ##creat a empty grid to store currently information
        total_ants = np.zeros((WIDTH,HEIGHT))

        ## count the number of currently information
        for (agents, i, j) in self.grid.coord_iter():
            if type(agents) is Ant:
                total_ants[i][j] = 1
            else:
                total_ants[i][j] = 0
        ##update the tau
        self.tau = self.tau + total_ants
        ##calcualte the mean tau
        self.mean_tau_ant = self.tau.sum()/((WIDTH-2)**2)
        return self.mean_tau_ant

    def evaluation2(self):


        ## we need to minus the mean tau so we need to ensure the result of boundary is zero
        ## so we let the bounday equal mean_tau_ant in this way the (tau-mean_tau_ant) is zero of boundary
        for site in self.bound_vals:
            self.tau[site[0]][site[1]] = self.mean_tau_ant


        ##calculate the sigmaa
        self.sigma = ((self.tau-self.mean_tau_ant)**2).sum()/((WIDTH-2)**2)

        ## rechange the boundaryy
        for site in self.bound_vals:
            self.tau[site[0]][site[1]] = 0

        return np.sqrt(self.sigma)

    def evaluation3(self):
        ##calculate the sigmastar
        self.sigmastar = np.sqrt(self.sigma)/self.mean_tau_ant

        return self.sigmastar
Exemplo n.º 48
0
class HungerModel(Model):
    """A model with some number of agents."""
    # boje = ["red","yellow","green","blue"]
    # ukusi = ["kiselo","ljuto","gorko","slatko"]
    # oblici = ["zvezda","kvadrat","krug","trougao"]
    boje = range(0, 100)
    ukusi = range(0, 100)
    oblici = range(0, 100)
    sve_kombinacije = list(
        starmap(KombinacijaTuple, product(boje, ukusi, oblici)))

    def __init__(self,
                 N,
                 size,
                 br_hrane_po_stepenu,
                 br_stepena_otrovnosti,
                 agent_memory_size=32,
                 agent_walk_energy=0.2):
        import math
        start = timer()
        br_hrane = br_hrane_po_stepenu * br_stepena_otrovnosti
        self.kombinacije = self.sve_kombinacije[:br_hrane]
        self.check_input(agent_memory_size, br_stepena_otrovnosti, br_hrane)

        self.food_dict = self.raspodeli_hranu(self.kombinacije,
                                              br_stepena_otrovnosti,
                                              br_hrane_po_stepenu)
        if br_hrane > len(self.kombinacije):  #moramo napraviti duplikate
            dodatak = [
                self.random.choice(self.kombinacije)
                for i in range(br_hrane - len(self.kombinacije))
            ]
            assert (len(dodatak) == br_hrane - len(self.sve_kombinacije))
            self.kombinacije = self.sve_kombinacije + dodatak
        self.br_stepena_otrovnosti = br_stepena_otrovnosti
        self.num_agents = N
        self.num_food = br_hrane
        self.grid = MultiGrid(size, size, True)
        self.schedule = RandomActivation(self)
        self.running = True
        for i in range(self.num_agents):
            a = HungryAgent(i,
                            self,
                            memory_size=agent_memory_size,
                            br_stepena_otrovnosti=br_stepena_otrovnosti,
                            walk_energy=agent_walk_energy)
            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))

        for i in range(self.num_food):
            kombinacija = self.kombinacije[i]
            id_offset = i + 1000
            f = FoodAgent(id_offset, self, kombinacija[0], kombinacija[1],
                          kombinacija[2])
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(f, (x, y))

        self.datacollector = DataCollector(
            model_reporters={
                "TotalKnowledge": compute_knowledge,
                "TotalEnergy": total_energy,
                "TotalExperience": measure_experience,
                "TotalFood": total_pojedena_hrana,
                "TotalPoison": total_pojedeni_otrovi,
                "AverageEnergyPerCapita": average_energy_per_capita
            })
        #      agent_reporters = {"Knowledge":"knowledge"})
        end = timer()
        print("time elapsed on Model.__init__ function : {}".format(end -
                                                                    start))

    def check_input(self, agent_memory_size, br_stepena_otrovnosti, br_hrane):
        if agent_memory_size <= 0:
            raise SmallMemoryError("Agent memory must be positive!")
        if br_stepena_otrovnosti <= 1 or (br_stepena_otrovnosti % 2) != 0:
            raise PoisonError(
                "Broj stepena otrovnosti mora biti paran i pozitivan!")
        #ovih num_of_food random bira TODO
        if br_hrane <= 0:
            raise HranaError("Nedovoljan broj hrane/otrova")
        if br_hrane < br_stepena_otrovnosti:
            raise HranaError("Manje hrane od stepena otrovnosti!!")
        if br_stepena_otrovnosti > len(self.sve_kombinacije):
            raise PoisonError("Ima vise stepena otrovnosti nego hrane!!")

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()

    def raspodeli_hranu(self, kombinacije, br_stepena_otrovnosti,
                        br_hrane_po_stepenu):
        """Od svih mogucih kombinacija hrane, on ih svrstava po otrovnosti. znaci ako imamo 64 hrane i 8 nivoa otrovnosti svaki nivo ce imati 8 stvari"""
        from math import ceil

        def chunks(lst, n):
            """Yield successive n-sized chunks from lst."""
            for i in range(0, len(lst), n):
                yield lst[i:i + n]

        food_dict = dict()
        chunks_kombinacija = list(chunks(kombinacije, br_hrane_po_stepenu))
        nivo = -br_stepena_otrovnosti // 2

        for (i, chunk) in enumerate(chunks_kombinacija):

            if nivo == 0:
                nivo += 1
            for tpl in chunk:
                food_dict[tpl] = nivo
            nivo += 1
        assert (len(food_dict.keys()) == len(kombinacije))
        return food_dict
Exemplo n.º 49
0
class Apocalypse(Model):
    """Apocalypse model.

    Model holds all the data and functions for the simulation to work. It is
    a subclass of the mesa framework.
    """

    def __init__(self, height=50, width=50, density=0.1, infected_chance=0.05,
                 map_id=5, city_id=0, province="", human_kill_agent_chance=0.6,
                 patient_zero=False, door_width=5, seed=None,
                 incubation_time=3, server=None, grouping=True, iteration=-1):
        """Initializes the apocalypse object, makes the grid and puts agents on
        that grid.

        Args:
            height (int): Grid height.
            width (int): Grid width.
            density (float): Percentage of the amount of agents in an area.
            infected_chance (float): Percentage of agents in an area to be
                                     infected.
            map_id (int): Index to choose from a list of maps in
                          maps_layout.py.
            city_id (int): Index of the city where the outbreak happens.
            province (string): On the Netherlands map, this is the province
                               where the outbreak starts.
            human_kill_agent_chance (float): Chance for a human to kill a
                                             zombie.
            patient_zero (bool): If only one person should be infected.
            door_width (int): Width of the door way.
            seed (string): Seed that decides all randomness in the model, so
                           you can repeat the exact same experiments.
            incubation_time (int): Number of steps it takes for an infected
                                   human to turn into a zombie.
            server (:obj:): Server instance, used to pause the server.
            grouping (bool): Allow humans to form groups.

        """

        self._seed = seed
        self.server = server
        self.height = height
        self.width = width
        self.density = density
        self.infected_chance = infected_chance
        self.carrier = 0
        self.infected = 0
        self.susceptible = 0
        self.recovered = 0
        self.total = 0
        self.patient_zero = patient_zero
        self.human_kill_zombie_chance = human_kill_agent_chance
        self.grouping = grouping
        self.door = [(-1, -1)]
        self.door_coords = []
        self.door_width = door_width
        self.incubation_time = incubation_time
        self.fsm = Automaton(self)

        # Set agents step function in a schedule to be called in random order.
        self.schedule = RandomActivation(self)

        # Makes multigrid, grid which can hold multiple agents on one cell.
        self.grid = MultiGrid(width, height, torus=False)

        # Collects data each step and plots it in server.py.
        self.datacollector = DataCollector(
            {"infected": "infected",
             "susceptible": "susceptible",
             "recovered": "recovered"},
            {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]})

        # Creates agents and map layouts.
        self.map = MapGen(map_id, city_id, infected_chance, province, self)

        # If there is a door in the map you get the coordinates.
        if self.door[0] != (-1, -1):
            self.get_door_coords()

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        """Step function.

        Call all agents and collect data, stop if there are no more zombies
        or no more humans.
        """
        if ((self.susceptible == 0) or
            (self.infected == 0 and self.carrier == 0)):

            self.running = False
            self.server.model.running = False

        self.schedule.step()
        self.datacollector.collect(self)

    def get_door_coords(self):
        """Door range to coordinates.

        Model gets a range for the door, this turns that into a list of
        coordinates and gives it to the model.
        """
        xs = range(self.door[0][0], self.door[1][0] + 1)
        ys = [self.door[0][1] for _ in range(len(xs))]
        self.door_coords = list(zip(xs, ys))
Exemplo n.º 50
0
class AmongUs(Model):
    def __init__(self,
                 map_name,
                 n_crew,
                 starting_positions,
                 num_tasks_crewmate=4,
                 injob_time=(70, 100),
                 impostor_cooldown=214,
                 impostor_vents=True,
                 just_killed_cooldown=5,
                 sus_kill=np.inf,
                 sus_vent=np.inf,
                 sus_task=-.1,
                 sus_group=-.01,
                 sus_default=.0005,
                 gamma1=0.04,
                 gamma2=-0.02,
                 n_iterated_games=1,
                 var_name='',
                 data_path='generated_data/unsorted'):
        super().__init__()

        # changable parameters
        self.injob_time = injob_time
        self.num_tasks_crewmate = num_tasks_crewmate
        self.starting_positions = starting_positions
        self.impostor_tactic = None
        self.impostor_behavior = None
        self.impostor_cooldown = impostor_cooldown
        self.impostor_vents = impostor_vents
        self.just_killed_cooldown = just_killed_cooldown
        self.n_iterated_games = n_iterated_games

        # changable sus matrix parameters
        self.sus_kill = sus_kill
        self.sus_vent = sus_vent
        self.sus_task = sus_task
        self.sus_group = sus_group
        self.sus_default = sus_default

        #changable trust matrix parameters
        self.gamma1 = gamma1
        self.gamma2 = gamma2

        # reset to 0 every game for indexing which agent is which in social matrices
        self.index_agent = 0

        # generate grid
        self.height = 138
        self.width = 242
        self.grid = MultiGrid(self.width, self.height, torus=True)

        # generate map
        self.generate_map(map_name)

        # generate tasks
        self.generate_tasks(map_name)

        # load vision dict for impostors
        self.vision_dict = np.load('the_skeld/vision_dict.pkl',
                                   allow_pickle=True)

        # create schedulers for agents
        self.schedule_Crewmate = RandomActivation(self)
        self.schedule_Impostor = RandomActivation(self)

        # initialize agents
        self.n_crew = n_crew
        self.n_impo = 1
        self.n_run = 0
        self.dead_players = []
        self.tasks_counter = 0
        self.crew_done = 0
        self.dead_crewmates = []
        self.respawn_players()

        # Generate trust and sus matrix
        n_players = n_crew + self.n_impo
        self.sus_matrix = np.full((n_players, n_players), .5)
        self.trust_list = np.load(f'{data_path}/social_matrices/trust_0.npy',
                                  allow_pickle=True)
        self.data_path = data_path
        self.var_name = var_name

    def generate_map(self, map_name):
        hard_walls = np.load(f'{map_name}/hardwalls.npy')
        vents = np.load(f'{map_name}/vents.npy', allow_pickle=True)
        obstructions = np.load(f'{map_name}/obstructions.npy',
                               allow_pickle=True)

        for coord in hard_walls:
            self.new_agent(Wall, tuple(coord))

        self.vents_dict = {}
        self.vents = []

        for connection in vents:
            connection = connection.tolist()
            self.vents_dict[tuple(connection[0])] = tuple(connection[1])
            self.vents_dict[tuple(connection[1])] = tuple(connection[0])

            if len(connection) == 3:
                self.vents_dict[tuple(connection[0])] = tuple(connection[2])
                self.vents_dict[tuple(connection[1])] = tuple(connection[2])
                self.vents_dict[tuple(connection[2])] = tuple(connection[0])
                self.vents_dict[tuple(connection[2])] = tuple(connection[1])

        for coord in self.vents_dict:
            self.new_agent(Vent, tuple(coord))

        for coord in obstructions:
            self.new_agent(Obstruction, tuple(coord))

    def generate_tasks(self, map_name):
        # load the image + coordinates of the short tasks and common tasks
        short_tasks = np.load(f'{map_name}/shorttasks.npy', allow_pickle=True)
        common_tasks = np.load(f'{map_name}/commontasks.npy',
                               allow_pickle=True)

        self.short_tasks = short_tasks
        self.s_tasks = []

        self.common_tasks = common_tasks
        self.c_tasks = []

        self.all_tasks = []

        # load all the short_tasks into the map (all possible task locations), first create tuples
        for i in range(len(short_tasks)):
            if i == 3:
                self.new_agent(ShortTask, tuple(short_tasks[i][0][0]))
                for parttwo in range(8):
                    self.new_agent(ShortTask,
                                   tuple(short_tasks[i][1][parttwo]))
            elif i == 6:
                for partone in range(5):
                    self.new_agent(ShortTask,
                                   tuple(short_tasks[i][0][partone]))
                self.new_agent(ShortTask, tuple(short_tasks[i][1][0]))

            else:
                self.new_agent(ShortTask, tuple(short_tasks[i][0]))

        # Do the same for common tasks
        self.new_agent(CommonTask, tuple(common_tasks[0][0]))
        for i in range(len(common_tasks[1])):
            self.new_agent(CommonTask, tuple(common_tasks[1][i][0]))

    def respawn_players(self):
        for crewmate in self.schedule_Crewmate.agents:
            self.remove_agent(crewmate)
        for impostor in self.schedule_Impostor.agents:
            self.remove_agent(impostor)

        for dead_crewmate in self.dead_crewmates:
            self.grid.remove_agent(dead_crewmate)
            self.dead_crewmates.remove(dead_crewmate)

        self.activated_agents = []
        self.crew_done = 0

        # Assign agent to impostor
        impostor_index = self.n_run % 4

        if impostor_index == 0:
            self.impostor_tactic = 'active'
            self.impostor_behavior = 'aggressive'
        if impostor_index == 1:
            self.impostor_tactic = 'passive'
            self.impostor_behavior = 'aggressive'
        if impostor_index == 2:
            self.impostor_tactic = 'active'
            self.impostor_behavior = 'careful'
        if impostor_index == 3:
            self.impostor_tactic = 'passive'
            self.impostor_behavior = 'careful'

        for i in range(self.n_crew + self.n_impo):
            if i == impostor_index:
                self.new_agent(Impostor,
                               random.choice(self.starting_positions))
            else:
                self.new_agent(Crewmate,
                               random.choice(self.starting_positions))

    def new_agent(self, agent_type, pos):
        '''
        Method that creates a new agent, and adds it to the correct scheduler.
        '''
        agent = agent_type(self.next_id(), self, pos)

        self.grid.place_agent(agent, pos)

        if agent_type == Crewmate or agent_type == Impostor:
            getattr(self, f'schedule_{agent_type.__name__}').add(agent)
            agent.injob_time = self.injob_time
            agent.num_tasks = self.num_tasks_crewmate
            self.activated_agents.append(agent)
            self.index_agent += 1

        if agent_type == Dead_crewmate:
            self.dead_crewmates.append(agent)

        if agent_type == Vent:
            self.vents.append(agent)

        if agent_type == ShortTask:
            self.s_tasks.append(agent)
            self.all_tasks.append(agent)

        if agent_type == CommonTask:
            self.c_tasks.append(agent)
            self.all_tasks.append(agent)

    def remove_agent(self, agent):
        '''
        Method that removes an agent from the grid and the correct scheduler.
        '''
        self.grid.remove_agent(agent)
        getattr(self, f'schedule_{type(agent).__name__}').remove(agent)

    def vote_off(self):
        '''
        Method that determines which player gets voted off. 
        Player with highest trust*sus score gets voted off, if difference is significant with number two value
        '''

        # Sus matrix; row (R) is what player R thinks of players (C1, C2, C3, C4, C5)
        for player in self.dead_players:
            self.sus_matrix[player, :] = -np.inf
            self.sus_matrix[:, player] = -np.inf

        for i in range(len(self.sus_matrix)):
            self.sus_matrix[i, i] = -np.inf

        # Create vote_matrix (value between 0 and 1)
        vote_matrix = self.sus_matrix.copy()
        for i in range(len(vote_matrix)):
            for j in range(len(vote_matrix[i])):
                vote_matrix[i][j] = .5 + .5 * np.tanh(vote_matrix[i][j])

        # Check trust matrix and sus matrux to determine who gets voted off
        trust_list = self.trust_list
        trust_score = trust_list.copy()
        total_scores = trust_score @ vote_matrix

        # Determine who is voted out
        voted_out = random.choice(
            np.argwhere(total_scores[0] == np.amax(total_scores[0])))[0]
        self.dead_players.append(voted_out)

        # remove agent form game and activated agent list
        self.remove_agent(self.activated_agents[voted_out])

        # finish task of voted out agent
        if type(self.activated_agents[voted_out]) == Crewmate:
            if not self.activated_agents[voted_out].done:
                self.crew_done += 1
                self.activated_agents[voted_out].done = True

        # Change trust matrix depenending on correct choices, trust increases for correct sus, decreases for wrong sus (max with factor 0.05)
        for player_trust in range(len(self.trust_list[0])):

            vote_list = vote_matrix[player_trust]
            # Determine who the player voted for
            player_vote = np.argmax(vote_list, axis=0)

            # Check if the vote was correct, lower or increase trust value accordingly
            if type(self.activated_agents[player_vote]) == Impostor:
                self.trust_list[0][player_trust] += self.gamma1
                round(self.trust_list[0][player_trust], 3)

                if self.trust_list[0][player_trust] > 1:
                    self.trust_list[0][player_trust] = 1

            if type(self.activated_agents[player_vote]) == Crewmate:
                self.trust_list[0][player_trust] += self.gamma2
                round(self.trust_list[0][player_trust], 3)

                if self.trust_list[0][player_trust] < 0:
                    self.trust_list[0][player_trust] = 0

        # set players to base
        for i in range(len(self.activated_agents)):
            if i not in self.dead_players:
                self.activated_agents[i].path = [(130, 100)]
                for impostor in self.schedule_Impostor.agents:
                    impostor.cooldown = self.impostor_cooldown
                    impostor.just_killed = 0

    def step(self):
        '''
        Method that steps every agent. 
        
        Prevents applying step on new agents by creating a local list.
        '''

        self.schedule_Crewmate.step()
        self.schedule_Impostor.step()

        # update sus matrix every step
        self.sus_matrix += self.sus_default

    def play_match(self, iterations=0, match_num=0):
        '''
        Method that runs a single match.
        '''
        #reset to 0 every game for indexing which agent is which in social matrices
        self.index_agent = 0
        self.dead_players = []
        self.crew_done = 0
        self.tasks_counter = 0

        n_players = self.n_crew + self.n_impo
        self.sus_matrix = np.full((n_players, n_players), .5)
        #make sure the trust matrix is reset after 'new players' enter a game
        if self.n_run % self.n_iterated_games == 0:
            self.trust_list = np.load(
                f'{self.data_path}/social_matrices/trust_0.npy',
                allow_pickle=True)

        self.respawn_players()
        i = 1
        while len(self.schedule_Crewmate.agents) > self.n_impo and len(
                self.schedule_Impostor.agents
        ) > 0 and self.crew_done != self.n_crew:
            print(f'Match: {match_num+1}/{iterations}')
            print(f' Step: {i}')
            clear_output(wait=True)
            i += 1
            self.step()

        print(f'Ended at iteration: {i}')
        print(f'Number of tasks completed: {self.tasks_counter}')
        print(f'Number of crewmates finished: {self.crew_done}')
        #save the trust matrix to be loaded later
        self.n_run += 1
        np.save(
            f'{self.data_path}/social_matrices/trust_{self.var_name}_{self.n_run}.npy',
            self.trust_list)

        # load previous wins
        self.win_matrix = np.load(
            f'{self.data_path}/win_matrices/win_matrix_{self.var_name}_{self.n_run - 1}.npy',
            allow_pickle=True)

        # crewmates win
        if len(self.schedule_Impostor.agents
               ) == 0 or self.crew_done == self.n_crew:
            print('The crewmates won!')
            for player in self.activated_agents:
                if type(player) != Impostor:
                    self.win_matrix[player.index, 0] += 1

        # impostor wins
        else:
            print('The impostor won!')
            impostor = self.schedule_Impostor.agents[0]
            self.win_matrix[impostor.index, 1] += 1

        # add wins
        np.save(
            f'{self.data_path}/win_matrices/win_matrix_{self.var_name}_{self.n_run}.npy',
            self.win_matrix)

        # NEW save thins
        iteration_data = np.load(
            f'{self.data_path}/misc_data/iteration_data.npy',
            allow_pickle=True)
        iteration_data = np.append(iteration_data, i)
        np.save(f'{self.data_path}/misc_data/iteration_data.npy',
                iteration_data)

        tasks_data = np.load(f'{self.data_path}/misc_data/tasks_data.npy',
                             allow_pickle=True)
        tasks_data = np.append(tasks_data, self.tasks_counter)
        np.save(f'{self.data_path}/misc_data/tasks_data.npy', tasks_data)

        crewmates_done_data = np.load(
            f'{self.data_path}/misc_data/crewmates_done_data.npy',
            allow_pickle=True)
        crewmates_done_data = np.append(crewmates_done_data, self.crew_done)
        np.save(f'{self.data_path}/misc_data/crewmates_done_data.npy',
                crewmates_done_data)

        win_data = np.load(f'{self.data_path}/misc_data/win_data.npy',
                           allow_pickle=True)
        if len(self.schedule_Impostor.agents
               ) == 0 or self.crew_done == self.n_crew:
            win_data = np.append(win_data, 0)
        else:
            win_data = np.append(win_data, 1)
        np.save(f'{self.data_path}/misc_data/win_data.npy', win_data)

        dead_data = np.load(f'{self.data_path}/misc_data/dead_data.npy',
                            allow_pickle=True)
        dead_data = np.append(dead_data, len(self.dead_players))
        np.save(f'{self.data_path}/misc_data/dead_data.npy', dead_data)

    def run(self, iterations):
        '''
        Method that runs multiple matches.
        '''
        for match_num in range(iterations):
            self.play_match(iterations, match_num)
            clear_output(wait=True)
Exemplo n.º 51
0
class BoltzmannWealthModelNetwork(Model):
    """A model with some number of agents."""
    def __init__(self, b, a, N=500):  #N- number of agents

        self.N = N
        self.b = b
        self.a = a
        self.agents = []
        self.gini = 0
        self.time = 0
        self.G = nx.barabasi_albert_graph(n=N, m=1)
        nx.set_edge_attributes(
            self.G, 1, 'weight')  #setting all initial edges with a weight of 1
        self.nodes = np.linspace(0, N - 1, N,
                                 dtype='int')  #to keep track of the N nodes

        self.schedule = RandomActivation(self)
        self.datacollector = DataCollector(model_reporters={"Gini": 'gini'},
                                           agent_reporters={
                                               "k_t": 'k',
                                               'income': 'income',
                                               'H': 'front',
                                               'consumption': 'consum',
                                               'lamda': 'lamda',
                                               'alpha': 'alpha',
                                               'technology': 'tec'
                                           })
        for i, node in enumerate(self.G.nodes()):
            agent = MoneyAgent(i, self)
            self.schedule.add(agent)

        self.running = True
        self.datacollector.collect(self)

    def Global_Attachment(self):
        #print("Global Attachment no: {}".format(self.count))
        node1 = random.choice(self.nodes)
        node2 = random.choice(self.nodes)
        while (self.G.has_edge(node1, node2) == True):
            node2 = random.choice(self.nodes)
            node1 = random.choice(self.nodes)
        #adding the edge node1-node2
        for agent in self.agents:
            if (agent.unique_id == node1):
                node1_a = agent
            if (agent.unique_id == node2):
                node2_a = agent
        self.G.add_edge(node1,
                        node2,
                        weight=Edge_Weight(node1_a, node2_a, self.b, self.a))

    def compute_gini(self):
        agent_wealths = [agent.k for agent in self.schedule.agents]
        x = sorted(agent_wealths)
        B = sum(xi * (self.N - i)
                for i, xi in enumerate(x)) / (self.N * sum(x))
        return 1 + (1 / self.N) - 2 * B

    def step(self):
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)

    def run_model(self, n):
        for i in tqdm(range(n)):
            #print("Step:", i+1)
            self.time = i + 1
            self.step()
            self.Global_Attachment()
            self.gini = self.compute_gini()
Exemplo n.º 52
0
class BaileyPikeModel(Model):
    def __init__(self, parameters):
        super().__init__(Model)

        if parameters == None:
            parameters = {
                'population': 2380,
                'steps': 90,
                'ptrans': 0.25,
                'progression_period': 3,
                'social-distancing': '0.3',
                'mask-wearing': '0.33',
                'severe': 0.18,
                'immunity': '0.03',
                'I0': 0.01,
                'interactions': 12,
                'reinfection_rate': 0.0,
                'death_rate': 0.0193,
                'recovery_days': 21,
                'recovery_sd': 7,
                'progression_sd': 2
            }
        else:
            parameter = int(parameters['population'])

            if parameter < 0 or parameter > 3000:
                parameters['population'] = 2390
            else:
                parameters['population'] = parameter

            parameter = float(parameters['I0'])

            if parameter < 0 or parameter > 1:
                parameters['I0'] = 0.01
            else:
                parameters['I0'] = parameter

            parameter = float(parameters['ptrans'])

            if parameter < 0 or parameter > 1:
                parameters['ptrans'] = 0.25
            else:
                parameters['ptrans'] = parameter

            parameter = int(parameters['progression_period'])

            if parameter < 0 or parameter > 100:
                parameters['progression_period'] = 3
            else:
                parameters['progression_period'] = parameter

            parameter = int(parameters['progression_sd'])

            if parameter < 0 or parameter > 100:
                parameters['progression_sd'] = 2
            else:
                parameters['progression_sd'] = parameter

            parameter = int(parameters['interactions'])

            if parameter < 0 or parameter > 100:
                parameters['interactions'] = 12
            else:
                parameters['interactions'] = parameter

            parameter = float(parameters['reinfection_rate'])

            if parameter < 0 or parameter > 1:
                parameters['reinfection_rate'] = 0.00
            else:
                parameters['reinfection_rate'] = parameter

            parameter = float(parameters['death_rate'])

            if parameter < 0 or parameter > 1:
                parameters['death_rate'] = 0.0193
            else:
                parameters['death_rate'] = parameter

            parameter = int(parameters['recovery_days'])

            if parameter < 0 or parameter > 100:
                parameters['recovery_days'] = 21
            else:
                parameters['recovery_days'] = parameter

            parameter = int(parameters['recovery_sd'])

            if parameter < 0 or parameter > 100:
                parameters['recovery_sd'] = 7
            else:
                parameters['recovery_sd'] = parameter

            parameter = float(parameters['severe'])

            if parameter < 0 or parameter > 1:
                parameters['severe'] = 0.18
            else:
                parameters['severe'] = parameter

        self.susceptible = 0
        self.dead = 0
        self.recovered = 0
        self.infected = 0
        interactions = parameters['interactions']
        self.population = parameters['population']
        self.SIR_instance = SIR.Infection(
            self,
            ptrans=parameters['ptrans'],
            reinfection_rate=parameters['reinfection_rate'],
            I0=parameters["I0"],
            severe=parameters["severe"],
            progression_period=parameters["progression_period"],
            progression_sd=parameters["progression_sd"],
            death_rate=parameters["death_rate"],
            recovery_days=parameters["recovery_days"],
            recovery_sd=parameters["recovery_sd"])

        # G = scale_free_graph(self.population)
        G = SIR.build_network(interactions, self.population)
        self.grid = NetworkGrid(G)
        self.schedule = RandomActivation(self)
        self.dead_agents = []
        self.running = True

        ### load the geojson that contains the census tracts and population
        all_tracts = gpd.read_file('static/data/leon_tracts.geojson')

        # get list of random long lat points
        point_list = self.get_point_list(all_tracts, self.population, ['073'])
        row_index = 0

        for node in range(self.population):
            denizen = Denizen(node, self)  #what was self.next_id()
            denizen.census_tract_id = point_list.AFFGEOID.iloc[row_index]
            point = point_list.geometry.iloc[row_index]
            point
            denizen.lat = point.y
            denizen.lng = point.x
            self.grid.place_agent(denizen, node)
            self.schedule.add(denizen)
            row_index += 1

        self.datacollector = DataCollector(
            model_reporters={
                "infected": lambda m: c_p.compute(m, 'infected'),
                "recovered": lambda m: c_p.compute(m, 'recovered'),
                "susceptible": lambda m: c_p.compute(m, "susceptible"),
                "dead": lambda m: c_p.compute(m, "dead"),
                "R0": lambda m: c_p.compute(m, "R0"),
                "severe_cases": lambda m: c_p.compute(m, "severe")
            })
        self.datacollector.collect(self)

    def step(self):
        self.schedule.step()

        self.datacollector.collect(self)
        '''
        for a in self.schedule.agents:
            if a.alive == False:
                self.schedule.remove(a)
                self.dead_agents.append(a.unique_id)
        '''

        if self.dead == self.schedule.get_agent_count():
            self.running = False
        else:
            self.running = True

    def run_model(self, steps):

        for i in range(steps):
            self.step()

    #function to evaluate whether or not point is in boundary
    def get_random_point_in_polygon(self, poly):
        minx, miny, maxx, maxy = poly.bounds

        while True:
            point = Point(random.uniform(minx, maxx),
                          random.uniform(miny, maxy))

            if poly.contains(point):
                break

        return point

    def get_point_list(self, gdf, num_of_points, county_FP_list):
        # gdf should be a geopandas dataframe containing a geomety definition
        # num_of_points is how many Point(lon,Lat) to randomly return
        # coutny_FP_list is a list of all census County FP id numbers

        # restrict the counties to only those of interest
        gdf = gdf[gdf.COUNTYFP.isin(county_FP_list)]
        #generate a weighted sample of tracts based on population
        tracts = gdf.sample(
            n=num_of_points,
            weights=gdf['Estimate!!RACE!!Total population'].tolist(),
            replace=True)[['AFFGEOID', 'geometry']]
        tracts = gpd.GeoDataFrame(tracts)
        point_list = pd.DataFrame(columns=(['AFFGEOID', 'geometry']))

        # for each tract, pick a random point within the geometry of the tract and append
        for row in tracts.itertuples():
            df2 = pd.DataFrame([[
                row.AFFGEOID,
                self.get_random_point_in_polygon(row.geometry)
            ]],
                               columns=(['AFFGEOID', 'geometry']))
            point_list = point_list.append(df2, ignore_index=True)

        point_list = gpd.GeoDataFrame(point_list)

        return point_list
Exemplo n.º 53
0
class BankReservesModel(Model):
    # id generator to track run number in batch run data
    id_gen = itertools.count(1)

    # 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.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 = random.randrange(self.width)
            # set y coordinate as a random number within the height of the grid
            y = 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 step(self):
        # collect data
        self.datacollector.collect(self)
        # tell all the agents in the model to run their step function
        self.schedule.step()

    def run_model(self):
        for i in range(self.run_time):
            self.step()
Exemplo n.º 54
0
class DeliveryModel(Model):
    """
    Model class for the Delivery model.
    """
    def __init__(self,
                 space_size=32,
                 jobs=30,
                 agents=1,
                 warehouses=1,
                 split=0.4,
                 use_seed=True,
                 seed: int = 42,
                 obstacle_map: str = "maps/random-32-32-20.map",
                 allocation: str = "HungarianMethod",
                 collision=False):
        if use_seed:
            self.random.seed(seed)
        else:
            self.random.seed(None)
        self.space_size = space_size
        self.tasks_left = jobs
        self.warehouses = []
        self.num_agents = agents
        self.agents = []
        self.collision = collision

        self.allocation_flag = True
        self.allocator = getattr(sys.modules["task_allocation"], allocation)
        self.allocation = None

        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(space_size, space_size, torus=False)

        self.obstacle_matrix = generate_map(obstacle_map)
        self.obstacles = self.__set_obstacle__()
        self.__set_up__(agents, warehouses, split)

        self.hidden_tasks = self.__preload_jobs__()
        # self.available_tasks = self.__add_jobs__(min(2*agents, jobs))
        self.available_tasks = self.__add_jobs__(min(10, jobs))

        self.task_allocator = None
        self.score = PrioritisedTaskTime()

        self.datacollector = DataCollector(
            {
                "tasks_left": "tasks_left",
                "Overall Wait Time": lambda m: m.score.get_score(),
                "High": lambda m: m.score.get_avg_wait_time().get(1),
                "Med": lambda m: m.score.get_avg_wait_time().get(2),
                "Low": lambda m: m.score.get_avg_wait_time().get(3),
            },
            {
                "x": lambda a: a.pos[0],
                "y": lambda a: a.pos[1]
            },
        )

        self.running = True
        self.datacollector.collect(self)

    def __preload_jobs__(self):
        jobs = []
        samples = self.random.choices(list(self.grid.empties),
                                      k=self.tasks_left)

        for sample in samples:
            i, j = sample
            job = Job((i, j), self.random.randint(1, 9),
                      self.random.randint(1, 3), self)
            jobs.append(job)
        return jobs

    def find_closest_warehouse(self, pos):
        min_dist = np.inf
        closest = None
        for w in self.warehouses:
            dist = np.sum(np.abs(np.array(w.pos) - np.array(pos)))
            if dist < min_dist:
                min_dist = dist
                closest = w
        return closest

    def step(self):
        # if len(self.available_tasks) < 2*self.num_agents and self.tasks_left > len(self.available_tasks):
        if len(self.available_tasks) < 10 and self.tasks_left > len(
                self.available_tasks):
            self.available_tasks += self.__add_jobs__(
                self.num_agents - len(self.available_tasks))

        if self.allocation_flag:
            self.allocation_flag = False
            self.allocation = self.allocator(
                self.random, self.agents,
                self.available_tasks).get_allocation()

        self.schedule.step()

        for j in self.available_tasks:
            j.step()

        self.datacollector.collect(self)
        if self.tasks_left == 0:
            self.running = False
            print(self.score.get_score())
            print(self.score.get_avg_wait_time())

    def __set_obstacle__(self):
        obstacles = []
        for i, j in zip(*np.where(self.obstacle_matrix == 1)):
            obs = Obstacle((i, j))
            obstacles.append(obs)
            self.grid.place_agent(obs, (i, j))
        return obstacles

    def __set_up__(self, agents, warehouses, split):

        # Pick empty spots for warehouses
        conv = convolve2d(self.obstacle_matrix, np.ones((3, 3)), mode="valid")
        free_indices = np.argwhere(conv == 0)
        samples = self.random.choices(free_indices, k=warehouses)

        for sample in samples:
            i, j = sample + 1
            warehouse = Warehouse((i, j))
            self.grid.place_agent(warehouse, (i, j))
            self.warehouses.append(warehouse)

        # Pick empty spots for agents
        samples = self.random.choices(list(self.grid.empties), k=agents)

        for a, sample in enumerate(samples):
            i, j = sample
            if a < split * agents:
                # Add Truck agent
                agent = Truck(a, (i, j), self)
            else:
                # Add Car agent
                agent = Car(a, (i, j), self)
            self.grid.place_agent(agent, (i, j))
            self.schedule.add(agent)
            self.agents.append(agent)

    def __add_jobs__(self, jobs):
        new_jobs = self.hidden_tasks[:jobs]
        self.hidden_tasks = self.hidden_tasks[jobs:]
        for job in new_jobs:
            job.is_available = True
            self.grid.place_agent(job, job.pos)
        return new_jobs
class Virus(Model):
    '''
    Model class for the Virus model.
    '''

    # id generator to track run numner in batch run data
    id_gen = itertools.count(1)

    def __init__(self,
                 grid_area="Demo",
                 num_agents=100,
                 infectious_seed_pc=INFECTIOUS_PREVALENCE,
                 recovered_seed_pc=0.2,
                 high_risk_pc=FRACTION_HI_RISK,
                 house_init="Random",
                 release_strat="Random individual houses",
                 mobility_speed="low",
                 weeks_to_second_release=4):
        # model is seeded with default parameters
        # can also change defaults with user settable parameter slider in GUI

        self.uid = next(self.id_gen)
        self.grid_area = grid_area
        self.house_init = house_init
        self.release_strat = release_strat
        self.weeks_to_second_release = weeks_to_second_release
        if grid_area == "Demo":
            self.height = GRID_HEIGHT_DEMO  # height and width of grid
            self.width = GRID_WIDTH_DEMO
        elif grid_area == "Small":
            self.height = GRID_HEIGHT_SMALL
            self.width = GRID_WIDTH_SMALL
        elif grid_area == "Large":
            self.height = GRID_HEIGHT_LARGE
            self.width = GRID_WIDTH_LARGE
        self.num_agents = num_agents  # number of agents to initializse
        self.infectious_seed_pc = infectious_seed_pc  # percent of infectious agents at start of simulation
        self.recovered_seed_pc = recovered_seed_pc  # percent of recovered agents at start of simulation
        self.high_risk_pc = high_risk_pc  # percent of agents catergorized as high risk for severe disease

        self.schedule = RandomActivation(
            self)  # controls the order that agents are activated and step
        self.grid = MultiGrid(self.width, self.height,
                              torus=True)  # multiple agents per cell

        self.infectious_count = 0
        self.infectious_percent = 0
        self.dead_count = 0
        self.susceptible_count = 0
        self.exposed_count = 0
        self.recovered_count = 0
        self.step_count = 0

        self.tick = 0
        self.people_dict = dict(
        )  # keys: house_ids, value: people_ids of people at that house
        self.house_dict = dict(
        )  # keys: low/high risk houses, value: house_ids of corresponding houses
        self.release_strat = release_strat

        if mobility_speed == "low":
            self.mobility = 5
        elif mobility_speed == "high":
            self.mobility = 20
        else:
            self.mobility = 1

        self.days_to_second_release = 7 * weeks_to_second_release

        ### Set up agents and houses ###
        # First initialize vec defining number of agents per cell/house (between 1-4)
        agents_per_cell = []
        agents_sum = 0

        while agents_sum < (num_agents - 4):
            agents_per_cell.append(random.randint(1, 4))
            agents_sum = sum(agents_per_cell)

        while agents_sum != num_agents:
            temp = num_agents - agents_sum
            agents_per_cell.append(random.randint(1, temp))
            agents_sum = sum(agents_per_cell)

        # Now initialize these agents on the grid in houses
        person_id = 0
        house_id = 2500

        high_risk_houses = []
        low_risk_houses = []

        # For uniform neighborhood, approximate with square packing of circles
        # in a rectangle
        # Getting indices of where houses should be
        # Initialing array of tuples with random grid coordinates
        num_houses = len(agents_per_cell)
        house_locations = []
        if house_init == "Neighborhood":
            grid_area = self.grid.width * self.grid.height
            circle_radius = math.sqrt(grid_area / (4.0 * num_houses))
            circle_diameter = 2.0 * circle_radius
            floor_radius = math.floor(circle_radius)
            floor_diameter = math.floor(circle_diameter)
            # Checking for feasibility:
            if floor_diameter < 1:
                raise ValueError("Too many agents to fit on grid.")
            # number of houses for each row of grid
            num_each_row = 1 + math.floor(
                (self.grid.width - floor_radius) / floor_diameter)
            # number of houses for each column of grid
            num_each_col = 1 + math.floor(
                (self.grid.height - floor_radius) / floor_diameter)
            for j in range(num_each_col):
                for i in range(num_each_row):
                    xpos = floor_radius + i * floor_diameter
                    ypos = floor_radius + j * floor_diameter
                    if xpos < self.grid.width and ypos < self.grid.height:
                        house_locations.append((xpos, ypos))

        # Initializing different household styles
        # Neighborhood = households laid out in uniform pattern on grid
        # Rural = households widely spread out
        # Clusters = households grouped in two clusters with larger space in between
        cell_counter = 0
        for cell in agents_per_cell:
            if house_init == "Random":
                x = self.random.randrange(self.grid.width)
                y = self.random.randrange(self.grid.height)
            elif house_init == "Neighborhood":
                x = house_locations[cell_counter][0]
                y = house_locations[cell_counter][1]
                cell_counter += 1
            else:  #house_init == "Clusters"
                # Households will be created on first 9th and last 9th
                # of grid (torus wrap turned off)
                one_sixth_width = int(self.grid.width / 6)
                x_low = self.random.randrange(one_sixth_width,
                                              2 * one_sixth_width)
                x_high = self.random.randrange(4 * one_sixth_width,
                                               5 * one_sixth_width)
                x = random.choice([x_low, x_high])
                one_sixth_height = int(self.grid.height / 6)
                y_low = self.random.randrange(one_sixth_height,
                                              2 * one_sixth_height)
                y_high = self.random.randrange(4 * one_sixth_height,
                                               5 * one_sixth_height)
                y = random.choice([y_low, y_high])

            people_here = []
            high_risk_house = False
            # Initialize people at house at (x,y)
            for person in range(cell):
                if self.random.random() < self.high_risk_pc:
                    risk_group = "high"
                    high_risk_house = True
                else:
                    risk_group = "low"

                if self.random.random() < self.infectious_seed_pc:
                    # From Joshua Weitz paper
                    # Basic epi parameters, 0.1% total prevalence
                    # (90% asymptomatic, 10% symptomatic)
                    agent_compartment = random.choices(
                        ["infectious_asymptomatic", "infectious_symptomatic"],
                        [(1.0 - FRACTION_SYMPTOMATIC), FRACTION_SYMPTOMATIC
                         ])[0]
                    self.infectious_count += 1

                elif self.random.random() < self.recovered_seed_pc:
                    agent_compartment = "recovered"
                    self.recovered_count += 1

                else:
                    agent_compartment = "susceptible"
                    self.susceptible_count += 1

                agent = VirusModelAgent((x, y), self, agent_compartment,
                                        risk_group, person_id)
                self.grid.place_agent(agent, (x, y))
                self.schedule.add(agent)
                people_here.append(person_id)
                person_id += 1

            if high_risk_house == False:
                low_risk_houses.append(house_id)
            else:
                high_risk_houses.append(house_id)
            house = HouseAgent((x, y), self, house_id, high_risk_house)
            self.grid.place_agent(house, (x, y))
            self.schedule.add(house)
            self.people_dict[house_id] = people_here
            house_id += 1

        self.house_dict["low risk houses"] = low_risk_houses
        self.house_dict["high risk houses"] = high_risk_houses

        # uses DataCollector built in module to collect data from each model run
        self.s_datacollector = DataCollector(
            {"susceptible": "susceptible_count"}, {
                "x": lambda m: m.pos[0],
                "y": lambda m: m.pos[1]
            })
        self.s_datacollector.collect(self)

        self.e_datacollector = DataCollector({"exposed": "exposed_count"}, {
            "x": lambda m: m.pos[0],
            "y": lambda m: m.pos[1]
        })
        self.e_datacollector.collect(self)

        self.i_datacollector = DataCollector(
            {"infectious": "infectious_count"}, {
                "x": lambda m: m.pos[0],
                "y": lambda m: m.pos[1]
            })
        self.i_datacollector.collect(self)

        self.r_datacollector = DataCollector({"recovered": "recovered_count"},
                                             {
                                                 "x": lambda m: m.pos[0],
                                                 "y": lambda m: m.pos[1]
                                             })
        self.r_datacollector.collect(self)

        self.datacollector = DataCollector(
            model_reporters={
                "Step": "step_count",
                "Susceptible": "susceptible_count",
                "Exposed": "exposed_count",
                "Infectious": "infectious_count",
                "Recovered": "recovered_count",
                "Dead": "dead_count",
                "Model Params": track_params,
                "Run": track_run
            })
        self.datacollector.collect(self)

        self.running = True

    def step(self):
        '''
        Run one step of the model. If all agents are happy, halt the model.
        '''
        self.infectious_count = 0  # Reset counters each step
        #self.infectious_percent = 0
        self.dead_count = 0
        self.susceptible_count = 0
        self.exposed_count = 0
        self.schedule.step()
        self.step_count += 1
        # collect data
        self.datacollector.collect(self)

        # run until no more agents are infectious
        # if self.infectious_count == 0 and self.exposed_count == 0:
        #     self.running = False

        self.tick += 1
Exemplo n.º 56
0
class EpsteinCivilViolence(Model):
    """
    Model 1 from "Modeling civil violence: An agent-based computational
    approach," by Joshua Epstein.
    http://www.pnas.org/content/99/suppl_3/7243.full
    Attributes:
        height: grid height
        width: grid width
        citizen_density: approximate % of cells occupied by citizens.
        cop_density: approximate % of calles occupied by cops.
        citizen_vision: number of cells in each direction (N, S, E and W) that
            citizen can inspect
        cop_vision: number of cells in each direction (N, S, E and W) that cop
            can inspect
        legitimacy:  (L) citizens' perception of regime legitimacy, equal
            across all citizens
        max_jail_term: (J_max)
        active_threshold: if (grievance - (risk_aversion * arrest_probability))
            > threshold, citizen rebels
        arrest_prob_constant: set to ensure agents make plausible arrest
            probability estimates
        movement: binary, whether agents try to move at step end
        max_iters: model may not have a natural stopping point, so we set a
            max.

    """

    def __init__(self, height=40, width=40, citizen_density=0.7, cop_density=0.074,
                 citizen_vision=7, cop_vision=7, legitimacy=0.8,
                 max_jail_term=1000, active_threshold=.1, arrest_prob_constant=2.3,
                 movement=True, max_iters=1000):
        super().__init__()
        self.height = height
        self.width = width
        self.citizen_density = citizen_density
        self.cop_density = cop_density
        self.citizen_vision = citizen_vision
        self.cop_vision = cop_vision
        self.legitimacy = legitimacy
        self.max_jail_term = max_jail_term
        self.active_threshold = active_threshold
        self.arrest_prob_constant = arrest_prob_constant
        self.movement = movement
        self.max_iters = max_iters
        self.iteration = 0
        self.schedule = RandomActivation(self)
        self.grid = Grid(height, width, torus=True)
        model_reporters = {
            "Quiescent": lambda m: self.count_type_citizens(m, "Quiescent"),
            "Active": lambda m: self.count_type_citizens(m, "Active"),
            "Jailed": lambda m: self.count_jailed(m)}
        agent_reporters = {
            "x": lambda a: a.pos[0],
            "y": lambda a: a.pos[1],
            'breed': lambda a: a.breed,
            "jail_sentence": lambda a: getattr(a, 'jail_sentence', None),
            "condition": lambda a: getattr(a, "condition", None),
            "arrest_probability": lambda a: getattr(a, "arrest_probability",
                                                    None)
        }
        self.datacollector = DataCollector(model_reporters=model_reporters,
                                           agent_reporters=agent_reporters)
        unique_id = 0
        if self.cop_density + self.citizen_density > 1:
            raise ValueError(
                'Cop density + citizen density must be less than 1')
        for (contents, x, y) in self.grid.coord_iter():
            if random.random() < self.cop_density:
                cop = Cop(unique_id, self, (x, y), vision=self.cop_vision)
                unique_id += 1
                self.grid[y][x] = cop
                self.schedule.add(cop)
            elif random.random() < (
                    self.cop_density + self.citizen_density):
                citizen = Citizen(unique_id, self, (x, y),
                                  hardship=random.random(),
                                  regime_legitimacy=self.legitimacy,
                                  risk_aversion=random.random(),
                                  threshold=self.active_threshold,
                                  vision=self.citizen_vision)
                unique_id += 1
                self.grid[y][x] = citizen
                self.schedule.add(citizen)

        self.running = True
        self.datacollector.collect(self)

    def step(self):
        """
        Advance the model by one step and collect data.
        """
        self.schedule.step()
        # collect data
        self.datacollector.collect(self)
        self.iteration += 1
        if self.iteration > self.max_iters:
            self.running = False

    @staticmethod
    def count_type_citizens(model, condition, exclude_jailed=True):
        """
        Helper method to count agents by Quiescent/Active.
        """
        count = 0
        for agent in model.schedule.agents:
            if agent.breed == 'cop':
                continue
            if exclude_jailed and agent.jail_sentence:
                continue
            if agent.condition == condition:
                count += 1
        return count

    @staticmethod
    def count_jailed(model):
        """
        Helper method to count jailed agents.
        """
        count = 0
        for agent in model.schedule.agents:
            if agent.breed == 'citizen' and agent.jail_sentence:
                count += 1
        return count
Exemplo n.º 57
0
class WolfSheepPredation(Model):
    '''
    Wolf-Sheep Predation Model
    '''

    initial_sheep = 100
    initial_wolves = 50
    sheep_gain_from_food = 4

    grass = False

    wolf_gain_from_food = 20
    sheep_reproduce = 0.04
    wolf_reproduce = 0.05

    height = 20
    width = 20

    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 step(self):
        self.schedule.step()
Exemplo n.º 58
0
class SchellingModel(Model):
    '''Model class for Schelling segregation model'''

    def __init__(self, height=20, width=20, density=.8, group_ratio=.66, minority_ratio=.5, homophily=3):
        self.height = height
        self.width = width
        self.density = density
        self.group_ratio = group_ratio
        self.minority_ratio = minority_ratio
        self.homophily = homophily
        self.happy = 0
        self.segregated = 0

        self.schedule = RandomActivation(self)
        self.grid = SingleGrid(height, width, torus=False)

        self.place_agents()
        self.datacollector = DataCollector( {'happy': (lambda m: m.happy), 'segregated': (lambda m: m.segregated)})
        self.running = True


    def step(self):
        '''Run one step of model'''
        self.schedule.step()
        self.calculate_stats()
        self.datacollector.collect(self)

        if self.happy == self.schedule.get_agent_count():
            self.running = False


    def place_agents(self):
        for cell in self.grid.coord_iter():
            x, y = cell[1:3]
            if random.random() < self.density:
                if random.random() < self.group_ratio:
                    if random.random() < self.minority_ratio:
                        group = 0
                    else:
                        group = 1
                else:
                    group = 2

                agent = SchellingAgent((x,y), group)
                self.grid.position_agent(agent, (x,y))
                self.schedule.add(agent)

        for agent in self.schedule.agents:
            count = 0
            for neighbour in self.grid.iter_neighbors(agent.pos, moore=False):
                if neighbour.group == agent.group:
                    count += 1
            agent.similar = count


    def calculate_stats(self):
        happy_count = 0
        avg_seg = 0
        for agent in self.schedule.agents:
            avg_seg += agent.similar
            if agent.similar >= self.homophily:
                happy_count += 1

        self.happy = happy_count
        self.segregated = avg_seg/self.schedule.get_agent_count()