 Difficulties with the step function

Here I have a 6 X 3 array of agents. Each line has agents with the same age: the first line with age 20 and the last with age 25.

I think I have no problems with the initialize function. But when I try to advance a step I start to have multiple problems, so I think I am doing something really wrong.

I put comments in the code but what I want is: in each step I want to kill that last line (agents with 25 years) and the agents with age >= age.death (is own age.death which is known).

Last, I want create a new first row of agents with 20 years and put them in the first row.

using Agents
using Random
import DrWatson: @dict

mutable struct Person <: AbstractAgent
id::Int
pos::NTuple{2, Int}
age::Int
death_age::Int
end

function initialize(; numagents = 18, seed = 125,
max_age = 25, min_age = 20,
griddims = ((max_age - min_age) + 1, Int(numagents/((max_age - min_age) + 1))))
space = GridSpace(griddims, periodic = false)
rng = Random.MersenneTwister(seed)
properties = @dict max_age min_age griddims
model = ABM(
Person, space; properties,
rng, scheduler = Schedulers.randomly
)

grid = collect(positions(model))
num_positions = prod(griddims)
#println(grid)

age = collect(repeat(min_age:max_age, griddims))

i = 1
for p in grid
agent = Person(
i,
p,
age[i],
rand(model.rng, 24:25)
)
println(agent.id, " p ", p, " age ", age[i], " death ", agent.death_age)
i += 1
end

return model
end

function agent_step!(agent, model)
# Delete the last line of agents
if agent.age == model.max_age
kill_agent!(agent, model)
end
agent.age += 1 # each agent becomes older one year

# kill all agent that are older than their death.age
if agent.age >= agent.death_age
kill_agent!(agent, model)
end

agent.pos = (agent.pos + 1, agent.pos) # move each agent down one position

# create model.griddims new agents with age model.min_age and position them in the first row (1,k)
for k in 1:model.griddims
agent = Person(
nextid(model),
(1, k),
model.min_age,
rand(model.rng, 24:25)
)
end

return
end

model = initialize()

#step!(model, agent_step!)

That’s not how you move agents in Agents.jl. You use the move_agent! function. Agent location is stored both in the agent pos field but also in teh spatial structure to accelerate searches. Changing the position arbitrarily like that instead of using the API would lead to all sorts of nonsensical things happen, which I think is what you see here?

Also, better to use size(model.space) rather than model.griddims

1 Like

Thanks. I already tried move_agent! without sucess. But I will try it again.

No hope with these changes of the agent_step! function.

function agent_step!(agent, model)
# Delete the last line of agents
if agent.age == model.max_age
kill_agent!(agent, model)
end
agent.age += 1 # each agent becomes older one year

kill all agent that are older than their death.age
if agent.age >= agent.death_age
kill_agent!(agent, model)
end

new_pos = (agent.pos + 1, agent.pos)
move_agent!(agent, new_pos, model) # move each agent down one position

# create size(model.space) new agents with age model.min_age and position them in the first row (1,k)
for k in 1:size(model.space)
agent = Person(
nextid(model),
(1, k),
model.min_age,
rand(model.rng, 24:25)
)
end

return
end

Thank you, George. I think I have managed everything now. I have used another possibility for add_agent! that I’ve read in the documentation: add_agent!(agent, pos, model). But I also have tried add_agent_pos! as well.

This is my complete solution (I have some difficulty to understand why I have to use restrictions like if agent.pos < 6 or if isempty((1,1), model), but I am sure there are other cleaner solutions for this problem):

using Agents
using Random
import DrWatson: @dict

mutable struct Person <: AbstractAgent
id::Int
pos::NTuple{2, Int}
age::Int
death_age::Int
end

function initialize(; numagents = 18, seed = 125,
max_age = 25, min_age = 20,
griddims = ((max_age - min_age) + 1, Int(numagents/((max_age - min_age) + 1))))
space = GridSpace(griddims, periodic = false)
rng = Random.MersenneTwister(seed)
properties = @dict max_age min_age
model = ABM(
Person, space; properties,
rng, scheduler = Schedulers.randomly
)

grid = collect(positions(model))

age = collect(repeat(min_age:max_age, size(model.space)))

for (i, pos) in enumerate(grid)
agent = Person(
i,
pos,
age[i],
rand(model.rng, 24:25)
)
end

return model
end

function agent_step!(agent, model)
# Delete the last line of agents
# kill all agent that are older than their death.age
if agent.age == model.max_age | agent.age >= agent.death_age
kill_agent!(agent, model)
end
agent.age += 1 # each agent becomes older one year

# move each agent down one position
if agent.pos < 6
new_pos = (agent.pos + 1, agent.pos)
move_agent!(agent, new_pos, model)
end

# create size(model.space) new agents with age model.min_age
# and position them in the first row (1,k)
if isempty((1,1), model)
for k in 1:size(model.space)
agent = Person(
nextid(model),
(1, k),
model.min_age,
rand(model.rng, 24:25)
)