diff --git a/examples/boltzmann_wealth_model_experimental/Readme.md b/examples/boltzmann_wealth_model_experimental/Readme.md index fc27fdb2..a5f92669 100644 --- a/examples/boltzmann_wealth_model_experimental/Readme.md +++ b/examples/boltzmann_wealth_model_experimental/Readme.md @@ -1,44 +1,67 @@ -# Boltzmann Wealth Model (Tutorial) +# Модель Розподілу Багатства за Болцманом💰 -## Summary +Цей проєкт моделює розподіл багатства серед агентів у суспільстві за допомогою моделі, натхненної розподілом Болцмана. Агенти взаємодіють, передаючи гроші сусідам, сплачуючи податки та отримуючи допомогу, коли вони бідніють. Програма відстежує нерівність у розподілі багатства за допомогою коефіцієнта Джині та візуалізує динаміку системи. -A simple model of agents exchanging wealth. All agents start with the same amount of money. Every step, each agent with one unit of money or more gives one unit of wealth to another random agent. This is the model described in the [Intro Tutorial](https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html), with the completed code. +## Особливості💡 -If you want to go over the step-by-step tutorial, please go and run the [Jupyter Notebook](https://github.com/projectmesa/mesa/blob/main/docs/tutorials/intro_tutorial.ipynb). The code here runs the finalized code in the last cells directly. +- **Агентне моделювання (ABM)**: Модель складається з агентів із індивідуальним багатством та поведінкою, зокрема переміщенням на сітці, обміном грошима та сплатою податків. +- **Оподаткування та перерозподіл**: Агенти сплачують податки залежно від свого багатства, а зібрані податки перерозподіляються серед агентів, які втратили всі свої кошти. +- **Коефіцієнт Джині**: Вираховується для відстеження нерівності в розподілі багатства з часом. +- **Візуалізація**: Поведінка системи візуалізується через графічне зображення положення агентів і їх багатства, а також графік коефіцієнта Джині. -As the model runs, the distribution of wealth among agents goes from being perfectly uniform (all agents have the same starting wealth), to highly skewed -- a small number have high wealth, more have none at all. +## Як це працює🧠 -## How to Run +1. **Агенти**: Кожен агент починає з початковим багатством, що дорівнює 1. Вони випадково переміщуються на 2D-сітці та взаємодіють із сусідами, передаючи частину свого багатства. +2. **Оподаткування**: Агенти сплачують податки за фіксованою ставкою. Зібрані податки зберігаються у податковому фонді, який використовується для підтримки агентів, що втратили всі свої кошти. +3. **Перерозподіл**: Коли багатство агента знижується до 0, він отримує допомогу з податкового фонду, якщо там є ресурси. +4. **Обмін багатством**: Агенти, які знаходяться в одній комірці сітки, можуть випадково обмінюватися багатством, що призводить до змін у його розподілі. +5. **Вимірювання нерівності**: На кожному кроці обчислюється коефіцієнт Джині для вимірювання рівня нерівності в розподілі багатства. -To follow the tutorial example, launch the Jupyter Notebook and run the code in ``Introduction to Mesa Tutorial Code.ipynb`` which you can find in the main mesa repo [here](https://github.com/projectmesa/mesa/blob/main/docs/tutorials/intro_tutorial.ipynb) +## Візуалізація 📊 -Make sure to install the requirements first: +- **Простір агентів**: Показує агентів на сітці, де розмір і колір агента відображають його багатство. Агенти з багатством відображаються синім кольором, а ті, хто не має багатства, — червоним. +- **Графік коефіцієнта Джині**: Показує еволюцію коефіцієнта Джині з часом, що демонструє рівень нерівності в популяції. -``` +## Як запустити🚀 + +1. Встановіть залежності: + ```bash pip install -r requirements.txt -``` + ``` + +2. Запустіть візуалізацію: + ```bash + solara run app.py + ``` + +3. Відкрийте надане посилання у вашому браузері, щоб побачити симуляцію. Ви побачите простір агентів та графік коефіцієнта Джині. -To launch the interactive server, as described in the [last section of the tutorial](https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html#adding-visualization), run: +## Параметри📉 -``` - $ solara run app.py -``` +Наступні параметри можуть бути змінені: -If your browser doesn't open automatically, point it to [http://127.0.0.1:8765/](http://127.0.0.1:8765/). When the visualization loads, click on the Play button. +- **N**: Кількість агентів у моделі (від 10 до 100). +- **Ставка податку**: Податкова ставка, яка застосовується до багатства агентів (від 0.0 до 1.0). +- **Розміри сітки**: Ширина і висота сітки, по якій переміщуються агенти (за замовчуванням: 10x10). +Ці параметри можна налаштувати у веб-інтерфейсі за допомогою повзунків, наданих Solara. -## Files +## Збір даних🧮 -* ``model.py``: Final version of the model. -* ``app.py``: Code for the interactive visualization. +Модель використовує `DataCollector` з бібліотеки Mesa для відстеження: -## Further Reading +- **Багатства** кожного агента на кожному кроці. +- **Коефіцієнта Джині** для всієї моделі, щоб спостерігати зміни в нерівності з часом. -The full tutorial describing how the model is built can be found at: -https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html +## Структура коду📑 -This model is drawn from econophysics and presents a statistical mechanics approach to wealth distribution. Some examples of further reading on the topic can be found at: +- **BoltzmannWealthModel**: Основний клас моделі, де налаштовується сітка, агенти та податкова система. +- **MoneyAgent**: Агенти, які можуть переміщуватися, сплачувати податки, передавати гроші сусідам і отримувати допомогу. +- **compute_gini**: Функція для обчислення коефіцієнта Джині на основі розподілу багатства агентів. +- **Візуалізація**: Використовуються Solara та Matplotlib для візуалізації агентів та нерівності в розподілі багатства. -[Milakovic, M. A Statistical Equilibrium Model of Wealth Distribution. February, 2001.](https://editorialexpress.com/cgi-bin/conference/download.cgi?db_name=SCE2001&paper_id=214) +## Майбутні покращення🤙 -[Dragulescu, A and Yakovenko, V. Statistical Mechanics of Money, Income, and Wealth: A Short Survey. November, 2002](http://arxiv.org/pdf/cond-mat/0211175v1.pdf) +- **Індивідуальні стратегії переміщення**: Додати складніші схеми переміщення або поведінку агентів. +- **Динамічні податкові ставки**: Реалізувати зміни податкових ставок залежно від багатства агентів або інших економічних чинників. +- **Економічні політики**: Випробувати вплив різних економічних політик на розподіл багатства. \ No newline at end of file diff --git a/examples/boltzmann_wealth_model_experimental/app.py b/examples/boltzmann_wealth_model_experimental/app.py index 199b3a1a..e1d26700 100644 --- a/examples/boltzmann_wealth_model_experimental/app.py +++ b/examples/boltzmann_wealth_model_experimental/app.py @@ -24,10 +24,19 @@ def agent_portrayal(agent): "max": 100, "step": 1, }, + "tax_rate": { + "type": "SliderFloat", + "value": 0.1, + "label": "Tax Rate:", + "min": 0.0, + "max": 1.0, + "step": 0.01, + }, "width": 10, "height": 10, } + # Create initial model instance model1 = BoltzmannWealthModel(50, 10, 10) diff --git a/examples/boltzmann_wealth_model_experimental/model.py b/examples/boltzmann_wealth_model_experimental/model.py index ac091a6c..ea47082c 100644 --- a/examples/boltzmann_wealth_model_experimental/model.py +++ b/examples/boltzmann_wealth_model_experimental/model.py @@ -2,76 +2,101 @@ def compute_gini(model): + # Compute Gini coefficient based on agents' wealth agent_wealths = [agent.wealth for agent in model.agents] - x = sorted(agent_wealths) + x = sorted(agent_wealths) # Sort the wealth values N = model.num_agents + # Calculate the Gini coefficient using the sorted wealth values B = sum(xi * (N - i) for i, xi in enumerate(x)) / (N * sum(x)) return 1 + (1 / N) - 2 * B class BoltzmannWealthModel(mesa.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=100, width=10, height=10): + def __init__(self, N=100, width=10, height=10, tax_rate=0.1): super().__init__() self.num_agents = N self.grid = mesa.space.MultiGrid(width, height, True) + self.tax_fund = 0 + self.tax_rate = tax_rate # Store the tax rate + # Data collector to track Gini coefficient and agents' wealth self.datacollector = mesa.DataCollector( model_reporters={"Gini": compute_gini}, agent_reporters={"Wealth": "wealth"} ) - # Create agents - for _ in range(self.num_agents): - a = MoneyAgent(self) - # Add the agent to a random grid cell - x = self.random.randrange(self.grid.width) - y = self.random.randrange(self.grid.height) - self.grid.place_agent(a, (x, y)) + # Create and place agents on the grid + for _ in range(self.num_agents): + a = MoneyAgent(self) # Instantiate a MoneyAgent + x = self.random.randrange(self.grid.width) # Random x position + y = self.random.randrange(self.grid.height) # Random y position + self.grid.place_agent(a, (x, y)) # Place agent on the grid self.running = True self.datacollector.collect(self) + def distribute_taxes(self): + # Distribute the tax fund among agents with zero wealth + for agent in self.agents: + if agent.wealth == 0 and self.tax_fund > 0: + agent.receive_aid() + self.tax_fund -= 1 + + def pay_taxes(self): + for agent in self.agents: + if agent.wealth > 0: + agent.pay_taxes() # Call pay_taxes method for each agent + def step(self): - self.agents.shuffle_do("step") - # collect data + self.agents.shuffle_do("step") # Randomize agent execution order + self.distribute_taxes() self.datacollector.collect(self) - def run_model(self, n): - for i in range(n): - self.step() - class MoneyAgent(mesa.Agent): - """An agent with fixed initial wealth.""" + """Agent with initial wealth and taxation function.""" def __init__(self, model): super().__init__(model) - self.wealth = 1 + self.wealth = 1 # Initialize wealth def move(self): + # Get possible neighboring positions to move possible_steps = self.model.grid.get_neighborhood( self.pos, moore=True, include_center=False ) - new_position = self.random.choice(possible_steps) - self.model.grid.move_agent(self, new_position) + new_position = self.random.choice( + possible_steps + ) # Randomly choose a new position + self.model.grid.move_agent(self, new_position) # Move agent to new position def give_money(self): - cellmates = self.model.grid.get_cell_list_contents([self.pos]) - cellmates.pop( - cellmates.index(self) - ) # Ensure agent is not giving money to itself - if len(cellmates) > 0: - other = self.random.choice(cellmates) + # Give money to a random neighbor (cellmate) + cellmates = self.model.grid.get_cell_list_contents( + [self.pos] + ) # Get agents in the same cell + cellmates.pop(cellmates.index(self)) # Remove self from the list of cellmates + if len(cellmates) > 0 and self.wealth > 0: + other = self.random.choice( + cellmates + ) # Choose a random agent to give money to other.wealth += 1 self.wealth -= 1 + def pay_taxes(self): + tax_rate = 0.1 + tax_amount = self.wealth * tax_rate # Calculate tax amount + if tax_amount > self.wealth: # Ensure agent has enough wealth to pay taxes + tax_amount = self.wealth # Pay what they have + self.wealth -= tax_amount + self.model.tax_fund += tax_amount + + def receive_aid(self): + # Aid is received if the agent's wealth is zero + if self.wealth == 0: + self.wealth += 1 + def step(self): self.move() + self.pay_taxes() # Pay taxes based on current wealth if self.wealth > 0: - self.give_money() + self.give_money() # Give money to another agent if wealthy diff --git a/examples/boltzmann_wealth_model_experimental/requirements.txt b/examples/boltzmann_wealth_model_experimental/requirements.txt index 479011dd..c94a3662 100644 --- a/examples/boltzmann_wealth_model_experimental/requirements.txt +++ b/examples/boltzmann_wealth_model_experimental/requirements.txt @@ -1,3 +1,3 @@ -mesa~=2.0 +mesa==3.0.0b0 solara git+https://github.com/projectmesa/mesa-examples \ No newline at end of file