JuliaDynamics / Agents.jl

Agent-based modeling framework in Julia
https://juliadynamics.github.io/Agents.jl/stable/
MIT License
731 stars 118 forks source link

BoundsError when moving an agent with Periodic boundary conditions #561

Closed mbruna closed 2 years ago

mbruna commented 2 years ago

I am getting an out-of-bounds error in the agent_step! of my model, which is ContinuousSpace with periodic boundary conditions. I think the issue is related to this one, although I don't quite understand why as in my case the Agent is only deleted to be reinserted just later (so I presume the agent ids stay the same).

The error I get is:

ERROR: LoadError: BoundsError: attempt to access 2×2 Array{Array{Int64,1},2} at index [0, 2]
Stacktrace:
 [1] getindex at ./array.jl:810 [inlined]
 [2] remove_agent_from_space!(::ActiveDisk, ::AgentBasedModel{ContinuousSpace{2,true,Float64,typeof(Agents.defvel)},ActiveDisk,typeof(Agents.Schedulers.randomly),Dict{Symbol,Real},MersenneTwister}) at /Users/mbruna/.julia/packages/Agents/HGute/src/spaces/continuous.jl:85
 [3] move_agent!(::ActiveDisk, ::Tuple{Float64,Float64}, ::AgentBasedModel{ContinuousSpace{2,true,Float64,typeof(Agents.defvel)},ActiveDisk,typeof(Agents.Schedulers.randomly),Dict{Symbol,Real},MersenneTwister}) at /Users/mbruna/.julia/packages/Agents/HGute/src/spaces/continuous.jl:96
 [4] agent_step!(::ActiveDisk, ::AgentBasedModel{ContinuousSpace{2,true,Float64,typeof(Agents.defvel)},ActiveDisk,typeof(Agents.Schedulers.randomly),Dict{Symbol,Real},MersenneTwister}) at /Users/mbruna/Documents/People/Burger_Martin/active_particles/ActiveParticles/src/ABM_model.jl:207
 [5] step!(::AgentBasedModel{ContinuousSpace{2,true,Float64,typeof(Agents.defvel)},ActiveDisk,typeof(Agents.Schedulers.randomly),Dict{Symbol,Real},MersenneTwister}, ::typeof(agent_step!), ::typeof(model_step!), ::Int64, ::Bool) at /Users/mbruna/.julia/packages/Agents/HGute/src/simulations/step.jl:55
 [6] step!(::AgentBasedModel{ContinuousSpace{2,true,Float64,typeof(Agents.defvel)},ActiveDisk,typeof(Agents.Schedulers.randomly),Dict{Symbol,Real},MersenneTwister}, ::Function, ::Function, ::Int64) at /Users/mbruna/.julia/packages/Agents/HGute/src/simulations/step.jl:48

I was also wondering if someone could help me understand why the agent gets deleted and reinserted when using periodic boundary conditions. What would be wrong with doing this in move_agent! (for Periodic BCs)?

a. pos = mod.(pos, model.space.extent)
function move_agent!(
    a::A,
    pos::Tuple,
    model::ABM{<:ContinuousSpace{D,periodic},A},
) where {A<:AbstractAgent,D,periodic}
    remove_agent_from_space!(a, model)
    if periodic
        pos = mod.(pos, model.space.extent)
    end
    a.pos = pos
    add_agent_to_space!(a, model)
end
Libbum commented 2 years ago

The ContinuousSpace goes from (and includes 0) in all dimensions and goes up to (but does not include) the extent.

If you place an agent manually at the exact position of the boundary, you'll actually be exceeding the space.

Can you show us the code you're using to do the move? This shouldn't happen with velocity updates in periodic continuous space.

Libbum commented 2 years ago

The delete/move is for internal reasons so we can track nearest-neighbours quicker, and have a general API for all space types. This is not just for the periodic case.

Let me know if you want a deeper explanation than that, but it's really just the way we position agents in the space. Move is not a concept, disappear and appear is. Very Zeno's paradox-esque.