Hello people! I am building a simulation model with agents.jl of a city where any moment, there is an area that can be affected by an emergency with a specific probability, so if this is the case, I want to move an ambulance to that point and come back to the started point. I am taking the example of zombies in a city for maps and location and predator for having more than one agent, so my start point is this:
using Agents
using Random
using Distributions
@agent Area OSMAgent begin
emergency::Bool
probability::Float64
end
mutable struct Area <: AbstractAgent
id::Int
pos::Tuple{Int, Int, Float64}
emergency::Bool
probability::Float64
end
@agent Ambulance OSMAgent begin
speed::Float64
end
mutable struct Ambulance <: AbstractAgent
id::Int
pos::Tuple{Int, Int, Float64}
speed::Float64
end
function initialise(seed = 1234, n_areas = 100, n_ambulances =2)
#Set space
map_path = OSM.test_map()
properties = Dict(:dt => 1/60)
model = ABM(
Union{Area, Ambulance},
OpenStreetMapSpace(map_path);
properties = properties,
rng = Random.MersenneTwister(seed)
)
#Develop initial states for each node
for id in 1:n_areas
start = random_position(model) # At an intersection
probability = 0.001#rand(1:2) # Random probability
emergency = Area(id, start, false, probability,)
add_agent!(emergency, model)
end
#Allocate ambulance at random
for id in 1:n_ambulances
start = random_position(model)
speed = rand(model.rng) + 60.0
ambulances = Ambulance(id+n_areas, start, speed)
add_agent!(ambulances, model)
end
return model
end
if I initialize then I have this:
julia> initialise()
[ Info: Created OSMGraph object with kwargs: `network_type=drive`, `weight_type=distance`, `graph_type=static`, `precompute_dijkstra_states=false`, `largest_connected_component=true`
┌ Warning: AgentType is not concrete. If your agent is parametrically typed, you're probably
│ seeing this warning because you gave `Agent` instead of `Agent{Float64}`
│ (for example) to this function. You can also create an instance of your agent
│ and pass it to this function. If you want to use `Union` types for mixed agent
│ models, you can silence this warning.
└ @ Agents ~/.julia/packages/Agents/QtIUJ/src/core/model.jl:299
AgentBasedModel with 102 agents of type Union{Ambulance, Area}
space: OpenStreetMapSpace with 598 ways and 2177 nodes
scheduler: fastest
properties: dt
But my problem start when I want to make specific actions with one of the two agents. This function shouldn’t do anything useful for now more than setting in every frame the emergency boolean
function agent_step!(agent::Area, model)
#If every area nothing happen then launch a random bernoully distribution otherwise keep
#the emergency activated
if agent.emergency == false
agent.emergency = rand(Bernoulli(agent.probability))
end
return
end
If I want visualize the model:
using InteractiveDynamics
using CairoMakie
CairoMakie.activate!() # hide
ac(agent::Area) = agent.emergency ? :red : :black
ac(agent::Ambulance) = :green
as(agent) = 10
model = initialise()
abmvideo("emergency_system.mp4", model, agent_step!;
title = "Emergency in a city", framerate = 5, frames = 300, as, ac)
I got this error:
┌ Warning: Since there are a lot of edges (3639 > 500), they will be drawn as straight lines even though they contain curvy edges. If you really want to plot them as bezier curves pass `edge_plottype=:beziersegments` explicitly. This will have much worse performance!
└ @ GraphMakie ~/.julia/packages/GraphMakie/wRCZ6/src/recipes.jl:409
ERROR: MethodError: no method matching agent_step!(::Ambulance, ::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister})
Closest candidates are:
agent_step!(::Area, ::Any) at ~/Desktop/projects/data-analisis/02-emergency-sim/src/sim.jl:62
Stacktrace:
[1] step!(model::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}, agent_step!::typeof(agent_step!), model_step!::typeof(dummystep), n::Int64, agents_first::Bool)
@ Agents ~/.julia/packages/Agents/QtIUJ/src/simulations/step.jl:55
[2] step!
@ ~/.julia/packages/Agents/QtIUJ/src/simulations/step.jl:48 [inlined]
[3] step!(abmobs::ABMObservable{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}, typeof(agent_step!), typeof(dummystep), Nothing, Nothing, Nothing, Nothing, Bool}, n::Int64; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/EThtU/src/agents/model_observable.jl:53
[4] step!
@ ~/.julia/packages/InteractiveDynamics/EThtU/src/agents/model_observable.jl:51 [inlined]
[5] (::InteractiveDynamics.var"#93#96"{Int64, Int64, ABMObservable{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}, typeof(agent_step!), typeof(dummystep), Nothing, Nothing, Nothing, Nothing, Bool}, Observable{Int64}})(io::VideoStream)
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/EThtU/src/agents/convenience.jl:152
[6] Record(func::InteractiveDynamics.var"#93#96"{Int64, Int64, ABMObservable{AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}, typeof(agent_step!), typeof(dummystep), Nothing, Nothing, Nothing, Nothing, Bool}, Observable{Int64}}, figlike::Figure; framerate::Int64)
@ Makie ~/.julia/packages/Makie/Ppzqh/src/display.jl:583
[7] #record#957
@ ~/.julia/packages/Makie/Ppzqh/src/display.jl:577 [inlined]
[8] abmvideo(file::String, model::AgentBasedModel{Agents.OSM.OpenStreetMapSpace, Union{Ambulance, Area}, typeof(Agents.Schedulers.fastest), Dict{Symbol, Float64}, MersenneTwister}, agent_step!::typeof(agent_step!), model_step!::typeof(dummystep); spf::Int64, framerate::Int64, frames::Int64, title::String, showstep::Bool, figure::NamedTuple{(:resolution,), Tuple{Tuple{Int64, Int64}}}, axis::NamedTuple{(), Tuple{}}, recordkwargs::NamedTuple{(:compression,), Tuple{Int64}}, kwargs::Base.Pairs{Symbol, Function, Tuple{Symbol, Symbol}, NamedTuple{(:as, :ac), Tuple{typeof(as), typeof(ac)}}})
@ InteractiveDynamics ~/.julia/packages/InteractiveDynamics/EThtU/src/agents/convenience.jl:149
[9] top-level scope
@ ~/Desktop/projects/data-analisis/02-emergency-sim/src/sim.jl:90
Why in agent_step! select also the ambulance agent? It shouldn’t only select the Area if I specify in the arguments of the function?