How to simulate friends on a GridSpace in Agents.jl

The problem most likely lies in this statement possible_friends[begin:length(agent.friends).
If your list of possible_friends is too small (e.g. only 7 ids in there) but your agent should have more friends than that (e.g. the random draw between a and b was 16), then you will encounter such a BoundsError.
So what you’re facing here is the fact that you don’t know about the final length of the friends vector during the initialisation process (because it depends dynamically on a,b, age, c, and d). The preallocation that I’ve tried with the fill function will likely not work properly then.

Here’s how you could solve it:

# adjust the agent struct to save the maximum number of friends an agent can have
mutable struct Person <: AbstractAgent
    id::Int
    pos::NTuple{2, Int}
    age::Int
    max_friends::Int
    friends::Vector{Int}
end

# and inside the init function:
for n in 1:numagents
    agent = Person(
        n,
        (1, 1),
        rand(model.rng, 20:100),
        rand(model.rng, a:b), # random draw for maximum number of friends
        [] # initialise an empty vector of friends
    )
    add_agent!(agent, model)
end

for agent in allagents(model)
    possible_friends = @pipe collect(allids(model)) |>
        filter!(id -> id != agent.id, _) |>
        filter!(id -> agent.age - c < model[id].age < agent.age + d, _) |> 
        shuffle!(model.rng, _) # shuffle the list to randomise the draw
    for id in possible_friends
        push!(agent.friends, id) # add this id to the friends vector
        if length(agent.friends) == agent.max_friends # if friends vector has reached desired length
            break # break the for-loop
        end
    end
end
1 Like