Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Wolf Sheep example to include PropertyLayer #2564

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
10 changes: 6 additions & 4 deletions mesa/examples/advanced/wolf_sheep/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def step(self):
"""Execute one step of the animal's behavior."""
# Move to random neighboring cell
self.move()

self.energy -= 1

# Try to feed
Expand Down Expand Up @@ -125,11 +124,15 @@ def fully_grown(self, value: bool) -> None:
if not value: # If grass was just eaten
self.model.simulator.schedule_event_relative(
setattr,
self.grass_regrowth_time,
int(
self.model.grid.grass_regrowth_time.data[self.cell.coordinate[0]][
self.cell.coordinate[1]
]
),
function_args=[self, "fully_grown", True],
)

def __init__(self, model, countdown, grass_regrowth_time, cell):
def __init__(self, model, countdown, cell):
"""Create a new patch of grass.

Args:
Expand All @@ -140,7 +143,6 @@ def __init__(self, model, countdown, grass_regrowth_time, cell):
"""
super().__init__(model)
self._fully_grown = countdown == 0
self.grass_regrowth_time = grass_regrowth_time
self.cell = cell

# Schedule initial growth if not fully grown
Expand Down
49 changes: 45 additions & 4 deletions mesa/examples/advanced/wolf_sheep/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@

import math

import numpy as np
from scipy.ndimage import gaussian_filter

from mesa import Model
from mesa.datacollection import DataCollector
from mesa.examples.advanced.wolf_sheep.agents import GrassPatch, Sheep, Wolf
from mesa.experimental.cell_space import OrthogonalVonNeumannGrid
from mesa.experimental.cell_space.property_layer import PropertyLayer
from mesa.experimental.devs import ABMSimulator


Expand All @@ -38,7 +42,7 @@ def __init__(
wolf_reproduce=0.05,
wolf_gain_from_food=20,
grass=True,
grass_regrowth_time=30,
max_grass_regrowth_time=30,
sheep_gain_from_food=4,
seed=None,
simulator: ABMSimulator = None,
Expand Down Expand Up @@ -71,7 +75,10 @@ def __init__(

# Create grid using experimental cell space
self.grid = OrthogonalVonNeumannGrid(
[self.height, self.width],
(
self.height,
self.width,
), # use tuple instead of list, otherwise it would fail the dimension check in add_property_layer
torus=True,
capacity=math.inf,
random=self.random,
Expand All @@ -89,6 +96,33 @@ def __init__(

self.datacollector = DataCollector(model_reporters)

def generate_grass_regrowth_time_array(): # Using Gaussian filter to make it look like spatial distribution
rows, cols = height, width

seeds = np.zeros((rows, cols))
num_seeds = max_grass_regrowth_time

for _ in range(num_seeds):
x, y = np.random.randint(0, rows), np.random.randint(0, cols)
seeds[x, y] = np.random.randint(1, num_seeds)

# Smooth the array to create clustered patterns using SciPy's Gaussian filter
filtered_array = gaussian_filter(seeds, sigma=10)

# Normalize the array to the range [1, num_seeds]
filtered_array = (filtered_array - np.min(filtered_array)) / (
np.max(filtered_array) - np.min(filtered_array)
) * (num_seeds - 1) + 1
filtered_array = filtered_array.astype(int)

return filtered_array

grass_regrowth_time_array = generate_grass_regrowth_time_array()

self.grid.add_property_layer(
PropertyLayer.from_data("grass_regrowth_time", grass_regrowth_time_array)
)

# Create sheep:
Sheep.create_agents(
self,
Expand All @@ -114,9 +148,16 @@ def __init__(
for cell in self.grid:
fully_grown = self.random.choice(possibly_fully_grown)
countdown = (
0 if fully_grown else self.random.randrange(0, grass_regrowth_time)
0
if fully_grown
else self.random.randrange(
0,
grass_regrowth_time_array[cell.coordinate[0]][
cell.coordinate[1]
],
)
)
GrassPatch(self, countdown, grass_regrowth_time, cell)
GrassPatch(self, countdown, cell)

# Collect initial data
self.running = True
Expand Down
Loading