JuliaDynamics/Agents.jl

Make `EventQueueABM` work with `Union` types

Opened this issue · 7 comments

This is useful because even if multiple dispatch can't be used in stepping function of Agents because there aren't really any in this type of model, having multiple dispatch for small unions could be useful anyway when implementing the event functions, or even for some more specific functions inside the event functions. This is also something which we allow in a StandardABM so I think that allowing it also here is good for consistency

But there is no way to specify multiple dispatch in the event model. Or at least, there is no meaning to do so.

You need to specify a function corresponding to an event, and the "kinds" it can be applied to. If we allow Unions, what changes is that we specify the "types" it applies to instead of "kinds". but it's not like we can actually use multiple dispatch to specify this. The specification is demanded as input, it can't be deduced by multiple dispatch.

Say you have 2 types and an event attack! which works differently for the two types. So, yes you need to register anyway the fact that this attack! is applied to those two types, but you can implement attack! as

function attack!(agent::AT1, model)
    ...
end

function attack!(agent::AT2, model)
    ...
end

also, you can dispatch inside the attack! function itself, based e.g. on the other type of agent the activated agent attacks

What's the benefit of doing all this? Is there in general any benefit in using union types for event based? Besides the fact that "you can use the same name for the different actions"?

I would say the same reasoning applies to StandardABM as well though, you can have an agent_step! which internally works out its way through the specific version by if branching with @multiagent. It seems analogous to the situation of EventQueueABM to me.

Actually, also, with a StandardABM I noticed that for 2 types the dispatch mechanism beats the if-else strategy you need to employ with @multiagent in terms of performance in WolfSheep by about 30%. But I'm not sure if this applies with EventQueueABM because having types internally slows down a bit the computations.

In general I would expect that there should be needed very few changes to make this working also with types anyway

I would say the same reasoning applies to StandardABM as well though, you can have an agent_step! which internally works out its way through the specific version by if branching with @multiagent

This is not the same. Because, in contrast to StandardABM, this if clause is "mandatory" in EventQueue, because the user has to explicitly say which action is for which agent. It is unavoidable. in StandardABM it is avoidable through multiple dispathc.

But sure, if you can make it work with a few changes and it doesn't cost much of your time, go for it!

I guess it is easy: we make a boolean typed parameter UT for "UsesTypes". So EventQueue{A, ..., UT} UT itself is either true or false. When the user gives input, if the specification of the Event is with a symbol, then it is using kinds. if it is a type, it uses types. Via this UT type parameter we know whether to use the kindof or typeof function in the code. Only two changes are needed, so yeah it is easy.

I fail to see which if clause is "mandatory" though, can you please point me out in https://github.com/JuliaDynamics/Agents.jl/blob/main/examples/event_rock_paper_scissors.jl what would be it? In this case it doesn't seem necessary any additional if clause

I guess it is easy: we make a boolean typed parameter UT for "UsesTypes". So EventQueue{A, ..., UT} UT itself is either true or false. When the user gives input, if the specification of the Event is with a symbol, then it is using kinds. if it is a type, it uses types. Via this UT type parameter we know whether to use the kindof or typeof function in the code. Only two changes are needed, so yeah it is easy.

seems a good way to me!

I fail to see which if clause is "mandatory" though,

it was a figure of speech, the 'if' clause is implicit in the fact that we specify the target agent kinds when creating the event type. :D