Source code for whynot.simulators.civil_violence.simulator

"""Simulate and analyze runs from the civil violence model."""
import dataclasses

from mesa.datacollection import DataCollector
import numpy as np

from whynot.simulators.civil_violence.model import CivilViolenceModel


[docs]@dataclasses.dataclass class Agent: # pylint: disable-msg=too-few-public-methods """Covariates for a single agent in the simulation. Examples -------- >>> # An agent with low risk aversion and high hardship >>> civil_violence.Agent(hardship=0.99, risk_aversion=0.01) """ #: How aggrieved is the agent by external circumstances. hardship: float = 0.5 #: How legitimate does the agent perceive the current regime. legitimacy: float = 0.5 #: Threshold above which agent starts to openly rebell active_threshold: float = 0.1 #: How likely the agent is to rebel for a fixed greviance level. risk_aversion: float = 0.5 #: How many adjacent squares an agent sees and uses to determine probability of arrest. vision: int = 3
[docs]@dataclasses.dataclass class Config: # pylint: disable-msg=too-few-public-methods """Metaparameters for a single run of the civil violence simulator.""" #: Vertical grid size grid_height: int = 50 #: Horizontal grid size grid_width: int = 50 #: What fraction of the agents are police cop_fraction: float = 0.05 #: How many adjacent squares a cop can see when determining who to arrest. cop_vision: int = 5 # What's the longest time a citizen can stay in jail? max_jail_term: int = 5 #: How strongly other agent grievances affect each agent in prison. prison_interaction: float = 0.1 #: A fixed parameter to calibrate arrest likelihood. arrest_prob_constant: float = 2.3
def count_type_citizens(model, condition, exclude_jailed=True): """Count agents as either 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 def count_jailed(model): """Count number of jailed agents.""" count = 0 for agent in model.schedule.agents: if agent.breed == "citizen" and agent.jail_sentence: count += 1 return count def simulate(agents, config, seed=None, max_steps=1000): """Simulate a run of the civil violence model. Parameters ---------- agents: list List of whynot.simulators.civil_violence.Agent to populate the model config: whynot.simulators.civil_violence.Config Simulation parameters seed: int (Optional) Seed for all randomness in model setup and execution. max_steps: int Maximum number of steps to run the civil_violence model. Returns ------- observations: pd.DataFrame Pandas dataframe containing the "observations" recorded for each agent. Observations are defined in the `agent_reporter` and include agent attributes along with: "pos" # position on the grid "jail_sentence" # agent's jail sentence at model end "condition" # agent's condition (rebelling or acquiesent) at model end "arrest_probability" # agent's probability of arrest "arrests" # number of time agent has been arrested "days_active" # how long as the agent spent in rebellion """ # Ensure everything will fit on the grid num_cells = config.grid_height * config.grid_width num_cops = int(np.floor(len(agents) * config.cop_fraction)) assert len(agents) + num_cops < num_cells model = CivilViolenceModel( height=config.grid_height, width=config.grid_width, cop_vision=config.cop_vision, max_jail_term=config.max_jail_term, prison_interaction=config.prison_interaction, arrest_prob_constant=config.arrest_prob_constant, max_steps=max_steps, seed=seed, ) # Place agents on grid for i, agent in enumerate(agents): model.add_agent( i, model.find_empty(), agent.hardship, agent.legitimacy, agent.risk_aversion, agent.active_threshold, agent.vision, ) for i in range(num_cops): model.add_cop(i + len(agents), model.find_empty()) # Which attributes to report agent_reporters = { "pos": "pos", "breed": "breed", "jail_sentence": "jail_sentence", "condition": "condition", "arrest_probability": "arrest_probability", "arrests": "arrests", "hardship": "hardship", "regime_legitimacy": "regime_legitimacy", "days_active": "days_active", "risk_aversion": "risk_aversion", "threshold": "threshold", "arrest_parameter": "arrest_parameter", "vision": "vision", } datacollector = DataCollector(agent_reporters=agent_reporters) while model.running: model.step() datacollector.collect(model) dataframe = datacollector.get_agent_vars_dataframe() observations = dataframe[dataframe.breed == "citizen"].drop(columns="breed") return observations