I'm trying to create an agent-based model using the mesa python framework. I want my agents to reproduce only on certain days of the year. Specifically, on days 203 through 209. Here is my model so far:
import mesa
import random
#set up class for agent
class Oyster(mesa.Agent):
"""An agent with randomly assigned initial energy & age."""
#define init values
def __init__(self, unique_id, model):
super().__init__(unique_id, model)
self.age = random.randint(0, 3649)
self.energy = random.randint(1,10)
#define what happens at each step
def step(self):
living = True
self.age += 1
self.energy += random.randint(-5, 5)
# Death
if self.energy < 0 or self.age > 3650:
self.model.grid.remove_agent(self)
self.model.schedule.remove(self)
living = False
# Repoduction
if living & self.energy >= 1.5 and self.age > 365:
for i in range(random.randint(1,6)):
babyOyster = Oyster(
self.model.next_id(), self.model, self.energy, self.age
)
self.model.grid.place_agent(babyOyster, self.pos)
self.model.schedule.add(babyOyster)
#set up class for model
class OysterModel(mesa.Model):
"""A model with some number of agents."""
#define init parameters
def __init__(self, N, width, height):
self.num_agents = N
self.grid = mesa.space.MultiGrid(width, height, True)
self.schedule = mesa.time.RandomActivation(self)
self.running = True
# Create agents
for i in range(self.num_agents):
a = Oyster(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)
self.grid.place_agent(a, (x, y))
#define step
def step(self):
"""Advance the model by one step."""
self.schedule.step()
I feel like the code should be something like "reproduce when the step number is divisible by 203-209" but I'm very new to python so I don't know how to get this. I also don't know how the agent can access the step number?
So this is my current solution!
First, I added a new attribute to the Model class called step_count
and I initialized it to be equal to 0. Then under the step function in the Model class, I added 1 to step-count
.
In the Agent class created an if statement where reproduction only happens if step_count
is divisible by my desired interval.
There was also an issue with next_id
which was preventing my reproduction code from working. I would get an error saying AttributeError: 'Model' object has no attribute 'current_id'
. I fixed that by setting current_id = 0
when I initialized the model. See code below:
#this tutorial uses the mesa package
import mesa
import random
#set up class for agent
class Oyster(mesa.Agent):
"""An agent with randomly assigned initial energy & age."""
#define init values
def __init__(self, unique_id, model, age = 0):
super().__init__(unique_id, model)
self.energy = random.randint(1,10)
self.age = age
#define what happens at each step
def step(self):
living = True
self.age += 1
self.energy += random.randint(-5, 5)
# Death
if (self.energy < 0) or (self.age > 3650):
self.model.grid.remove_agent(self)
self.model.schedule.remove(self)
living = False
#reproduction
if living & (self.age > 365) and (self.energy > 2) and self.model.step_count%50 == 0 :
for i in range(3):
babyOyster = Oyster(
self.model.next_id(), self.model
)
x = self.random.randrange(self.model.grid.width)
y = self.random.randrange(self.model.grid.height)
self.model.grid.place_agent(babyOyster, (x, y))
self.model.schedule.add(babyOyster)
#set up class for model
class OysterModel(mesa.Model):
"""A model with some number of agents."""
#define init parameters
def __init__(self, N, width, height):
self.num_agents = N
self.grid = mesa.space.MultiGrid(width, height, True)
self.schedule = mesa.time.RandomActivation(self)
self.running = True
self.step_count = 0
self.current_id = 0
# Create agents
for i in range(self.num_agents):
x = self.random.randrange(self.grid.width)
y = self.random.randrange(self.grid.height)
age = random.randint(1, 3649)
oyster = Oyster(self.next_id(), self, age)
self.grid.place_agent(oyster, (x, y))
self.schedule.add(oyster)
#definte step
def step(self):
"""Advance the model by one step."""
self.schedule.step()
self.step_count += 1
I also changed a few things to make sure baby wasn't staying in the same cell as the parent and the baby's age starts at 0. Hopefully this helps someone else, and if anyone finds a better solution let me know!