MK1
MK1

Reputation: 11

Problems Implementing Infection Dynamics in Agent-Based Model with Julia's Agents.jl Package

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:

  1. Splitting it up in multiple functions:

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
  1. Having only one array and check for infection status while eating:
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

Answers (1)

crazyraptor
crazyraptor

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

Related Questions