diff --git a/examples/ideology_diffusion/Readme.md b/examples/ideology_diffusion/Readme.md new file mode 100644 index 00000000..d14f2909 --- /dev/null +++ b/examples/ideology_diffusion/Readme.md @@ -0,0 +1,27 @@ +# Ideological Diffusion Under Economic Stress + +--- + +## Overview + +Historical analysis reveals that authoritarian regimes often gain momentum by exploiting acute **socio-economic crises**. These movements leverage public dissatisfaction to shift political paradigms and consolidate power by convincing the population that radical measures are the only solution to systemic failures. + +This **Agent-Based Model (ABM)** simulates how a population, when faced with adverse conditions such as high unemployment and economic instability, becomes vulnerable to extremist influence. The model explores the transition from neutral or moderate positions to radical ideologies, highlighting how external stressors and propaganda can drive political alignment—often as a desperate response to environmental pressure. + +--- + +## Key Features + +* **Ideological Evolution:** Agents move through three stages (Neutral, Moderate, and Radical) based on cumulative pressure. +* **Socio-Economic Stressors:** Global variables like economic crises and unemployment rates act as catalysts for dissatisfaction. +* **Media Influence:** Simulates the impact of propaganda based on individual susceptibility. +* **State Dynamics:** Includes government repression logic, which can either suppress or inadvertently accelerate radicalization (the "backfire effect"). + +--- + +## How to Run + +To run the model interactively, ensure you have `mesa` and `solara` installed, then run the following command in the project root: + +```bash +solara run app.py \ No newline at end of file diff --git a/examples/ideology_diffusion/__init__.py b/examples/ideology_diffusion/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/examples/ideology_diffusion/agents.py b/examples/ideology_diffusion/agents.py new file mode 100644 index 00000000..927e62ee --- /dev/null +++ b/examples/ideology_diffusion/agents.py @@ -0,0 +1,31 @@ +from mesa import Agent + + +class Person(Agent): + def __init__(self, model, opinion="neutral"): + super().__init__(model) + self.opinion = opinion + self.resistance = self.random.uniform(0.2, 0.8) + self.susceptibility = self.random.uniform(0.0, 1.0) + + def step(self): + # External pressure + external_pressure = ( + self.model.economic_crisis + self.model.propaganda + ) * self.susceptibility + + # Social pressure + neighbors = self.model.grid.get_neighbors(self.pos, moore=True) + if neighbors: + radicals = sum(1 for n in neighbors if n.opinion == "radical") + social_pressure = radicals / len(neighbors) + else: + social_pressure = 0 + + influence = external_pressure + social_pressure - self.resistance + + if influence > 0.4: + if self.opinion == "neutral": + self.opinion = "moderate" + elif self.opinion == "moderate": + self.opinion = "radical" diff --git a/examples/ideology_diffusion/app.py b/examples/ideology_diffusion/app.py new file mode 100644 index 00000000..a577d39b --- /dev/null +++ b/examples/ideology_diffusion/app.py @@ -0,0 +1,46 @@ +import solara +from mesa.experimental.solara_viz import ( + SolaraViz, + make_plot_component, + make_space_component, +) +from model import IdeologyModel + + +def agent_portrayal(agent): + color = { + "neutral": "gray", + "moderate": "orange", + "radical": "red", + }[agent.opinion] + + return { + "color": color, + "size": 40, + } + + +model_params = { + "N": solara.SliderInt(10, 300, value=120, label="Population"), + "economic_crisis": solara.SliderFloat(0.0, 1.0, value=0.5, label="Economic Crisis"), + "propaganda": solara.SliderFloat(0.0, 1.0, value=0.2, label="Propaganda"), +} + +space = make_space_component(agent_portrayal) +plot = make_plot_component( + { + "Neutrals": "gray", + "Moderates": "orange", + "Radicals": "red", + } +) + + +@solara.component +def App(): + SolaraViz( + IdeologyModel, + components=[space, plot], + model_params=model_params, + name="Ideology Diffusion Model", + ) diff --git a/examples/ideology_diffusion/model.py b/examples/ideology_diffusion/model.py new file mode 100644 index 00000000..eb74ad20 --- /dev/null +++ b/examples/ideology_diffusion/model.py @@ -0,0 +1,50 @@ +from agents import Person +from mesa import Model +from mesa.datacollection import DataCollector +from mesa.space import MultiGrid +from mesa.time import RandomActivation + + +class IdeologyModel(Model): + def __init__( + self, + n=120, + width=15, + height=15, + economic_crisis=0.5, + propaganda=0.2, + seed=None, + ): + super().__init__(seed=seed) + + self.grid = MultiGrid(width, height, torus=True) + self.schedule = RandomActivation(self) + + self.economic_crisis = economic_crisis + self.propaganda = propaganda + + for _ in range(n): + agent = Person(self) + self.schedule.add(agent) + + x = self.random.randrange(width) + y = self.random.randrange(height) + self.grid.place_agent(agent, (x, y)) + + self.datacollector = DataCollector( + { + "Neutrals": lambda m: sum( + a.opinion == "neutral" for a in m.schedule.agents + ), + "Moderates": lambda m: sum( + a.opinion == "moderate" for a in m.schedule.agents + ), + "Radicals": lambda m: sum( + a.opinion == "radical" for a in m.schedule.agents + ), + } + ) + + def step(self): + self.datacollector.collect(self) + self.schedule.step()