Hey all,
For some context, I want to do some work with the Agents.jl package in which I want to try to keep track of the movement of the agents (so I can draw their paths and manipulate them later). The easiest way I think I can make this work is by writing a more specific agent type, with a specific move_agent!
method, and then use invoke to call the more generic move_agent!
methods that Agents.jl provides. The problem that I’m running into though is that I cannot get the invoke call which I think has to do with the way that parametric types work in Julia.
What I have right now is that I wrote a method with signature move_agent!(::T, ::Agents.ValidPos, ::ABM{S, T}) where {S <: ContinuousSpace, T <: AbstractTurtle}
. Now I want to call the method with signature move_agent!(::A, ::Agents.ValidPos, ::ABM{<:ContinuousSpace{D}, A}) where {D, A <: AbstractAgent}
. Now we have that Turtle <: AbstractTurtle <: AbstractAgent
, but the problem (I think) is that ABM{ContinuousSpace{2}, AbstractTurtle} <: ABM{ContinuousSpace{2}, AbstractAgent}
does not hold. This causes invoke
to give the error “argument type error”. However, if I make the type in the invoke
call more general it becomes ambiguous.
Is there a solution out of this problem, am I just using invoke
wrong, or is what I’m trying to do just impossible given the current type system and constraints? Copying the current definition of move_agent!(::A, ::Agents.ValidPos, ::ABM{<:ContinuousSpace{D}, A}) where {D, A <: AbstractAgent}
into move_agent!(::T, ::Agents.ValidPos, ::ABM{S, T}) where {S <: ContinuousSpace, T <: AbstractTurtle}
will of course work but a less brittle solution would have my preference.
The code that I have at the moment only depends on Agents.jl being installed and is:
using Agents
abstract type AbstractTurtle <: AbstractAgent end
@agent Turtle ContinuousAgent{2} AbstractTurtle begin end
function Agents.move_agent!(turtle::T, pos::Agents.ValidPos, model::ABM{S, T}) where {T <: AbstractTurtle, S <: ContinuousSpace}
start = turtle.pos
@invoke move_agent!(turtle::AbstractAgent, pos, model::ABM{S, AbstractAgent})
println("Turtle started at $start, ended at $(turtle.pos)")
end
model = AgentBasedModel(Turtle, ContinuousSpace((50, 50)))
agent = add_agent!(model, (1, 0))
move_agent!(agent, (1,1), model)
Julia version: 1.9.3
Agents.jl version: 5.17.1