Reputation: 11
Thank you in advance to everyone who reads through this. I have no idea how to make this shorter in order to explain my problem. I also apologize for the vague title, as I have no idea where the root of this problem lies.
I created an Agent Based Model using Julias Agents.jl package, consisting of 5 Agents. For this question, 3 are relevant: Sticklebacks, Copepods and Parasites. Lifecycle as follows: Parasites infect copepods -> Stickleback prey on infected Copepods and therefore get infected themselves. The agents are realised as a mutable struct (Abstract Agents) with certain fields - one of which is the infection status.
mutable struct CopepodGrazerParasitePhytoplankton <: AbstractAgent
id::Int
pos::NTuple{2, Float64}
type::Symbol
infected::Int # 0 = false, 1 = true
end
The Sticklebacks prey upon Copepods (infected and uninfected) and eventually get infected themselves. My Problem:
I can't get the Sticklebacks to get infected while simultaneously continue the "normal hunt" of Copepods. This is my current stickleback_eat! function:
function stickleback_eat!(stickleback, model)
infection = [inf_copepod for inf_copepod in nearby_agents(stickleback, model, model.stickleback_vision) if inf_copepod.infected == 1]
if !isempty(infection)
stickleback.infected = 1
end
eat = [x for x in nearby_agents(stickleback, model, model.stickleback_vision) if x.type == :copepod || x.type == :grazer]
if !isempty(eat)
for x in eat
remove_agent!(x, model, model.pathfinder)
end
end
end
Stickleback_vision is set to 8 and is not changed on any iteration of the model.
Agents that are in the vicinity of the Stickleback get preyed upon and killed, but no infection of sticklebacks is seen whatsoever.
Weirdly, if I remove the eat part of the function (as in the following), the infection of Sticklebacks works perfectly (proven by logging and dataframes):
function stickleback_eat!(stickleback, model)
infection = [inf_copepod for inf_copepod in nearby_agents(stickleback, model, model.stickleback_vision) if inf_copepod.infected == 1]
if !isempty(infection)
stickleback.infected = 1
end
But i also need the Sticklebacks to remove the copepods and grazers in its vicinity from the model.
Therefore what I've tried so far to fix this:
function stickleback_infection!(stickleback, model)
infection = [y for y in nearby_agents(stickleback, model, model.stickleback_vision) if y.infected == 1]
if !isempty(infection)
stickleback.infected = 1
remove_agent!(y, model, model.pathfinder)
end
end
function stickleback_eat!(stickleback, model)
eat = [x for x in nearby_agents(stickleback, model, model.stickleback_vision) if x.type == :copepod || x.type == :grazer]
if !isempty(eat)
for x in eat
remove_agent!(x, model, model.pathfinder)
end
end
end
function stickleback_eat!(stickleback, model)
eat = [x for x in nearby_agents(stickleback, model, model.stickleback_vision) if x.type == :copepod || x.type == :grazer]
if !isempty(eat)
for x in eat
if x.infected == 1
stickleback.infected = 1
end
remove_agent!(x, model, model.pathfinder)
end
end
end
Both (and many other smaller) changes don't work and I feel like i'm having a big hole in understanding any of these structures, which i cant identify yet. It's as if the eat part prohibits the infection of Sticklebacks and I just cant figure out why. Thank you again for any help.
Upvotes: 1
Views: 94
Reputation: 203
Weirdly, I don't have this issue extending GridAgents. For example, this code (which is pretty much identical to the original post with the exception of how the agent is defined) doesn't have an error:
using Agents
space = GridSpaceSingle((10, 10); periodic = false)
@agent simpleAgent GridAgent{2} begin
type::Symbol
infected::Int # 0 = false, 1 = true
end
function stickleback_eat!(stickleback, model)
infection = [inf_copepod for inf_copepod in nearby_agents(stickleback, model, model.stickleback_vision) if inf_copepod.infected == 1]
if !isempty(infection)
stickleback.infected = 1
end
eat = [x for x in nearby_agents(stickleback, model, model.stickleback_vision) if x.type == :copepod || x.type == :grazer]
if !isempty(eat)
for x in eat
remove_agent!(x, model)
end
end
end
properties = Dict(:stickleback_vision => 8)
model = ABM(simpleAgent, space; properties)
copepod1 = simpleAgent(1, (1.0, 1.0), :copepod, 0)
copepod2 = simpleAgent(3, (3.0, 3.0), :copepod, 1)
stickleback = simpleAgent(4, (10.0, 10.0), :stickleback, 0)
add_agent!(copepod1, model)
add_agent!(copepod2, model)
add_agent!(stickleback, model)
println("Stickleback infection: ", stickleback.infected)
println("Number of agents: ", nagents(model))
stickleback_eat!(stickleback, model)
println("Stickleback infection: ", stickleback.infected)
println("Number of agents: ", nagents(model))
The output here is:
Stickleback infection: 0
Number of agents: 3
Stickleback infection: 1
Number of agents: 1
which shows that the eating and the infection is done in the same step. For OP, I'd ask two questions: could you confirm this setup works in your installation, and share any other details that could help identify how the model setup is different?
Upvotes: 0