Tracking population vs agent level attributes in Agents.jl

I am translating an ABM model from NetLogo to Julia (i.e. Agents.jl).

The model, “particle world” is described in Paul Smaldino’s Modeling Social Behavior, where it is used to introduce basic NetLogo functionality. Agents perform correlated random walks and when they encounter another agent, they change direction. These “collision” events are tracked over time. In NetLogo collisions can be introduced as global variables, which allows us to track the cumulative number of collision events over time, regardless of which agents are involved (we do not need to track collisions at an agent level).

In my version of this model with Agents.jl, I have managed to get the desired collisions over time by adding a .collisions property to agents, which I then update at every step particle.collisions += new_collisions. I can then get the sum of these agent-level level collision records at each time-step.
Actually writing this I now realize I am double-counting… :expressionless:

My question is if it is possible in Agents.jl to track global attributes, similar to NetLogo, in cases where agent-level information is unnecessary and we are only interested in general model level aggregates.

The NetLogo version
The Agents.jl version

Welcome @amynang !

Global variables are generally speaking bad practice for performant code, but in Agents.jl a “global” variable is most naturally represented as a model property. In this way, during any collision you simply increment this model property. For example, as in Schelling model in our docs, if you have the model properties

properties = Dict(:total_collisions => 0)

then inside your agent stepping function and/or the model stepping function you can do:

function agent_step!(agent, model)
    if collision
        model.total_colisions += 1
    end
end
1 Like

p.s.: reading from the docs instructions on getting help, in the future please open questions in the category “Modelling and simulations” and use agents not agentsjl as a tag. I saw this post out of pure luck!

Thank you @Datseris!

This seems to get me what I want.

mdata = [:total_collisions]
mdf = run!(model, 100; mdata)