# Difficulties with the step function

**URL:** <https://discourse.julialang.org/t/difficulties-with-the-step-function/74603>\
**Category:** Modelling & Simulations\
**Tags:** agents\
**Created:** [January 14, 2022, 10:46am UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603 "2022-01-14T10:46:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [January 14, 2022, 10:46am UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603/1 "2022-01-14T10:46:25Z")

</div>

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.

```julia
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[2]))

    i = 1
    for p in grid
        agent = Person(
            i,
            p,
            age[i],
            rand(model.rng, 24:25)
            )
        add_agent!(agent, model)
        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] + 1, agent.pos[2]) # move each agent down one position

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

    return
end

model = initialize()

#step!(model, agent_step!)

adata = [:pos, :age, :death_age]

adf, _ = run!(model, agent_step!, dummystep, 3; adata)

```

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [January 14, 2022, 12:31pm UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603/2 "2022-01-14T12:31:30Z")

</div>

> [@sbacelar](#):
>
> ` agent.pos = (agent.pos[1] + 1, agent.pos[2]) # move each agent down one position`

That’s not how you move agents in Agents.jl. You use the [`move_agent!`](https://juliadynamics.github.io/Agents.jl/dev/api/#Agents.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`

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [January 14, 2022, 12:37pm UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603/3 "2022-01-14T12:37:56Z")

</div>

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

No hope with these changes of the `agent_step!` function.

```julia
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] + 1, agent.pos[2])
    move_agent!(agent, new_pos, model) # move each agent down one position

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

    return
end

```

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [January 16, 2022, 8:36am UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603/4 "2022-01-16T08:36:06Z")

</div>

> [@sbacelar](#):
>
> ```julia
> # create model.griddims[2] new agents with age model.min_age and position them in the first row (1,k)
> for k in 1:model.griddims[2]
> agent = Person(
> nextid(model),
> (1, k),
> model.min_age,
> rand(model.rng, 24:25)
> )
> add_agent!(agent, model)
> end
> 
> ```

please read the documentation string of `add_agent!`. If you don’t specify a position, the agent is added to a random position. You want to use the function `add_agent_pos!` instead.

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [January 16, 2022, 2:23pm UTC](https://discourse.julialang.org/t/difficulties-with-the-step-function/74603/5 "2022-01-16T14:23:01Z")

</div>

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[1] < 6` or `if isempty((1,1), model)`, but I am sure there are other cleaner solutions for this problem):

```julia
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)[2]))

    for (i, pos) in enumerate(grid)
        agent = Person(
            i,
            pos,
            age[i],
            rand(model.rng, 24:25)
            )
        add_agent!(agent, pos, model)
    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[1] < 6
        new_pos = (agent.pos[1] + 1, agent.pos[2])
        move_agent!(agent, new_pos, model)
    end
    
    # create size(model.space)[2] 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)[2]
            agent = Person(
                nextid(model),
                (1, k),
                model.min_age,
                rand(model.rng, 24:25)
                )
            add_agent!(agent, (1,k), model)
        end
    end
end

```
