From 7c8b7287d910eab1b31de858161d5c154e2d1f98 Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Fri, 3 Feb 2023 12:22:44 +0100 Subject: [PATCH] Added @shuffle! macro --- src/Persephone.jl | 1 + src/core/input.jl | 30 ++++++++++++++++++++++++++---- src/nature/nature.jl | 11 ----------- src/nature/populations.jl | 10 +++++----- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/Persephone.jl b/src/Persephone.jl index cdf484f..58c1b36 100644 --- a/src/Persephone.jl +++ b/src/Persephone.jl @@ -60,6 +60,7 @@ export @distancetoedge, @countanimals, @rand, + @shuffle!, #functions simulate, simulate!, diff --git a/src/core/input.jl b/src/core/input.jl index d950738..7b39605 100644 --- a/src/core/input.jl +++ b/src/core/input.jl @@ -7,7 +7,7 @@ ## (https://github.com/CCTB-Ecomods/gemm/blob/master/src/input.jl) """ -The file that stores all default parameters. +The file that stores all default parameters: `src/parameters.toml` """ const PARAMFILE = joinpath(pkgdir(Persephone), "src/parameters.toml") ## (DO NOT CHANGE THIS VALUE! Instead, specify simulation-specific configuration files @@ -19,11 +19,11 @@ const PARAMFILE = joinpath(pkgdir(Persephone), "src/parameters.toml") Return a configuration parameter from the global settings. The argument should be in the form `<domain>.<parameter>`, for example `@param(core.outdir)`. Possible values for -<domain> are `core`, `nature`, `farm`, or `crop`. For a full +`<domain>` are `core`, `nature`, `farm`, or `crop`. For a full list of parameters, see `src/parameters.toml`. -Note that this macro only works in a context where the `model` -object is available. +Note: this macro only works in a context where the `model` +object is available! """ macro param(domainparam) domain = String(domainparam.args[1]) @@ -112,6 +112,28 @@ function flattenTOML(tomldict) flatdict end +""" + @rand(args...) + +Return a random number or element from the sample, using the model RNG. +This is a utility wrapper that can only be used a context where the +`model` object is available. +""" +macro rand(args...) + :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...))) +end + +""" + @shuffle!(collection) + +Shuffle the given collection in place, using the model RNG. +This is a utility wrapper that can only be used a context where the +`model` object is available. +""" +macro shuffle!(collection) + :($(esc(:shuffle!))($(esc(:model)).rng, $(esc(collection)))) +end + """ parsecommandline() diff --git a/src/nature/nature.jl b/src/nature/nature.jl index a02f984..97885d0 100644 --- a/src/nature/nature.jl +++ b/src/nature/nature.jl @@ -375,17 +375,6 @@ macro countanimals(args...) :(countanimals($(esc(:pos)), $(esc(:model)); $(map(esc, args)...))) end -""" - @rand(args...) - -Return a random number or element from the sample, using the model RNG. -This is a utility wrapper that can only be used nested within `@phase` or `@habitat` -(or in other contexts where the `model` object is available). -""" -macro rand(args...) - :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...))) -end - ##TODO @chance macro: @chance(0.5) => rand(model.rng) < 0.5 ##TODO add movement macros diff --git a/src/nature/populations.jl b/src/nature/populations.jl index a760088..4e213e3 100644 --- a/src/nature/populations.jl +++ b/src/nature/populations.jl @@ -40,15 +40,15 @@ function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing (!isnothing(phase)) && (species["phase"] = phase) width, height = size(model.landscape) while n == 0 || n < popsize - for x in shuffle!(model.rng, Vector(1:width)) - for y in shuffle!(model.rng, Vector(1:height)) + for x in @shuffle!(Vector(1:width)) + for y in @shuffle!(Vector(1:height)) if habitatdescriptor((x,y), model) if pairs add_agent!((x,y), Animal, model, deepcopy(species), female, 0) add_agent!((x,y), Animal, model, deepcopy(species), male, 0) n += 2 else - sex = asexual ? hermaphrodite : rand(model.rng, [male, female]) + sex = asexual ? hermaphrodite : @rand([male, female]) add_agent!((x,y), Animal, model, deepcopy(species), sex, 0) n += 1 end @@ -88,7 +88,7 @@ Produce one or more offspring for the given animal at its current location. """ function reproduce!(animal::Animal, model::AgentBasedModel, n::Int64=1) for i in 1:n - sex = (animal.sex == hermaphrodite) ? hermaphrodite : rand(model.rng, [male, female]) + sex = (animal.sex == hermaphrodite) ? hermaphrodite : @rand([male, female]) # We need to generate a fresh species dict here species = @eval $(Symbol(animal.traits["name"]))($model) add_agent!(animal.pos, Animal, model, species, sex, 0) @@ -103,7 +103,7 @@ Kill this animal, optionally with a given percentage probability. Returns true if the animal dies, false if not. """ function kill!(animal::Animal, model::AgentBasedModel, probability::Float64=1.0, cause::String="") - if rand(model.rng) < probability + if @rand() < probability postfix = isempty(cause) ? "." : " from $cause." @debug "$(animalid(animal)) has died$(postfix)" kill_agent!(animal, model) -- GitLab