Dear Julia and the Agents.jl community,
I’m currently working on a multispecies agent-based model (ABM) with sardine and anchovy superindividuals, and I’m planning to transition to the multi-agent framework soon. My model includes numerous properties because it is a bioenergetic model with over 50 parameters for each species. These parameters change depending on the agent species, and I need my step functions to access them.
To organize these properties, I tried to set up a nested dictionary structure for the model parameters. Here’s a simplified version of my property function generator:
@agent struct Fish(NoSpaceAgent)
# Basic characteristics
species::Symbol # :sardine, :anchovy
type::Symbol # :eggmass, :juvenile, :adult
end
function create_params_dict(Meggsardine, Megganchovy)
# Define the dictionary
model_parameters = Dict(
:natural_mortalities => Dict(
:sardine => Dict(
:M_egg => Meggsardine,
:Madults => 4.0),
:anchovy => Dict(
:M_egg => Megganchovy,
:M0 => 5.0)
),
:bioparams => Dict(
:sardine => Dict(
:energy => 5.0,
:growth=> 2.5),
:anchovy => Dict(
:energy => 3,0,
:growth => 8.0)
),
:output => Dict(
:sardine => Dict(
:TotB => 0.0),
:anchovy => Dict(
:TotB => 0.0)
))
return model_parameters
end
In this approach, I can provide different function arguments depending on the simulation goal, initialize fixed parameters, and set output keys to zero. The motivation behind using nested dictionaries is to avoid adding suffixes to parameter names to distinguish which species they refer to. As mentioned, I have many more parameters in the full model.
I have several different step functions in my model. While I initially considered using function dispatch based on the agent type, the code was becoming quite lengthy and functions were doing the same job just with different set of parameters. Instead, I opted to structure my step functions so that they access the appropriate subset of model properties depending on the agent’s :species
. This way, each species-specific data is retrieved dynamically within the corresponding step function.
function egghatch!(Fish, model)
if is_sardine(Fish)
deb_species = NamedTuple(model.bioparams[:sardine])
else
deb_species = NamedTuple(model.bioparams[:anchovy])
end
* function code*
end
However, I’m running into issues when using functions like init_model_data()
and collect_model_data()
. The problem arises because the model data (mdata
) can be either a vector or a generator function, and I’m unsure how to handle this effectively with my current dictionary structure.
Has anyone else dealt with a similar challenge? Any advice on how to improve the structure for better compatibility with init_model_data()
and collect_model_data()
in a multi-agent context would be greatly appreciated.
I’m sure there’s a more efficient and scalable way to structure the simulation framework.
Thanks in advance!