Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Persefone.jl
Manage
Activity
Members
Plan
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Package registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Repository analytics
Insights
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Persefone
Persefone.jl
Commits
71a01dca
Commit
71a01dca
authored
2 years ago
by
xo30xoqa
Browse files
Options
Downloads
Patches
Plain Diff
Wrote functions and macros for intialisation, reproduction & death
parent
ccb4e0ff
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/nature/lifehistory.jl
+52
-5
52 additions, 5 deletions
src/nature/lifehistory.jl
src/nature/nature.jl
+43
-10
43 additions, 10 deletions
src/nature/nature.jl
src/nature/species/skylark.jl
+10
-7
10 additions, 7 deletions
src/nature/species/skylark.jl
with
105 additions
and
22 deletions
src/nature/lifehistory.jl
+
52
−
5
View file @
71a01dca
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
### Persephone - a socio-economic-ecological model of European agricultural landscapes.
###
###
### This file contains a set of utility functions needed by species.
### This file contains a set of
life-history related
utility functions needed by species.
###
###
#TODO initrandompopulation
"""
initrandompopulation(popsize, asexual=true)
#TODO killanimal!
A simplified version of `initpopulation()`. Creates a function that initialises
`popsize` individuals, spread at random across the landscape. If `popsize` is less
than 1, it is interpreted as a population density (i.e. 1 animal per `popsize` pixels).
"""
function
initrandompopulation
(
popsize
::
Float64
,
asexual
::
Bool
=
true
)
initfunc
=
function
(
species
::
Dict
{
String
,
Any
},
model
::
AgentBasedModel
)
if
popsize
<
1.0
x
,
y
=
size
(
model
.
landscape
)
popsize
=
Int
(
round
(
x
*
y
*
popsize
))
end
for
i
in
1
:
popsize
sex
=
asexual
?
hermaphrodite
:
rand
([
male
,
female
])
add_agent!
(
Animal
,
model
,
species
,
sex
,
0
)
end
@debug
"Initialised
$(popsize) $
(species["
name
"])s."
end
return
initfunc
end
#TODO
reproduce!
#TODO
initpopulation
#TODO parentsalive?
"""
reproduce!(animal, model, n=1)
Produce one or more offspring for the given animal at its current location.
"""
function
reproduce!
(
animal
::
Animal
,
model
::
AgentBasedModel
,
n
::
Int64
=
1
)
# XXX at the moment we don't have intra-specific variation, so currently we
# don't need sexual recombination here
for
i
in
1
:
n
sex
=
animal
.
sex
==
hermaphrodite
?
hermaphrodite
:
rand
([
male
,
female
])
add_agent!
(
animal
.
pos
,
Animal
,
model
,
animal
.
traits
,
sex
,
0
)
end
@debug
"
$
(animal.traits["
name
"])
$
(animal.id) has reproduced."
end
"""
kill(animal, model, probability=1.0, cause="")
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
()
<
probability
postfix
=
isempty
(
cause
)
?
"."
:
" from
$
cause."
@debug
"
$
(animal.traits["
name
"])
$
(animal.id) has died
$(postfix)
"
kill_agent!
(
animal
,
model
)
return
true
end
return
false
end
This diff is collapsed.
Click to expand it.
src/nature/nature.jl
+
43
−
10
View file @
71a01dca
...
@@ -6,6 +6,9 @@
...
@@ -6,6 +6,9 @@
## An enum used to assign a sex to each animal
## An enum used to assign a sex to each animal
@enum
Sex
hermaphrodite
male
female
@enum
Sex
hermaphrodite
male
female
## This will be prepended to the names of the functions created by @species
const
SPECIESPREFIX
=
"speciesfunction_"
"""
"""
Animal
Animal
...
@@ -19,6 +22,7 @@ by trait dictionaries passed by them during initialisation.
...
@@ -19,6 +22,7 @@ by trait dictionaries passed by them during initialisation.
traits
::
Dict
{
String
,
Any
}
traits
::
Dict
{
String
,
Any
}
sex
::
Sex
sex
::
Sex
age
::
Int32
age
::
Int32
#XXX keep track of parents and/or offspring?
end
end
...
@@ -33,7 +37,7 @@ custom syntax to describe species' biology:
...
@@ -33,7 +37,7 @@ custom syntax to describe species' biology:
```julia
```julia
@species name begin
@species name begin
initialise! = init
random
population()
initialise! = initpopulation()
phase = "
phase1
"
phase = "
phase1
"
...
...
@phase phase1 begin
@phase phase1 begin
...
@@ -51,14 +55,18 @@ life cycle (see the documentation to `@phase` for details).
...
@@ -51,14 +55,18 @@ life cycle (see the documentation to `@phase` for details).
There are two parameters that all species must define:
There are two parameters that all species must define:
- `initialise!` should specify a function that will be used to create
- `initialise!` should specify a function that will be used to create
the starting population for this species. This function must take
the starting population for this species. This function must take
exactly one argument (an `AgentBasedModel` object).
two arguments, a species dict and an `AgentBasedModel` object.
The easiest way to create this function is by using `initpopultion()`.
- `phase` should be a string specifying the name of the first phase
- `phase` should be a string specifying the name of the first phase
that individuals of this species will be assigned to on birth.
that individuals of this species will be assigned to on birth.
Access to the rest of the model is given by the `model` variable (an object
of type `AgentBasedModel`).
"""
"""
macro
species
(
name
,
body
)
macro
species
(
name
,
body
)
funcname
=
"speciesfunction_"
*
name
funcname
=
Symbol
(
SPECIESPREFIX
*
string
(
name
))
quote
quote
Core
.
@__doc__
function
$
(
esc
(
funcname
))()
Core
.
@__doc__
function
$
(
esc
(
funcname
))(
model
::
AgentBasedModel
)
$
(
esc
(
:
name
))
=
string
(
$
(
QuoteNode
(
name
)))
$
(
esc
(
:
name
))
=
string
(
$
(
QuoteNode
(
name
)))
$
(
esc
(
body
))
$
(
esc
(
body
))
vardict
=
Base
.
@locals
vardict
=
Base
.
@locals
...
@@ -91,13 +99,14 @@ variables:
...
@@ -91,13 +99,14 @@ variables:
`model.landscape` (a two-dimensional array of pixels containing geographic
`model.landscape` (a two-dimensional array of pixels containing geographic
information).
information).
The
utility macros
`@respond`, `@trait`, and `@here`
can be used within the body of
Several
utility macros can be used within the body of
`@phase` as a short-hand for
`@phase` as short-hand for common expressions.
common expressions: `@respond`, `@trait`, `@here`, `@kill`, `@reproduce`
To transition an individual to another phase, simply redefine its phase variable:
To transition an individual to another phase, simply redefine its phase variable:
`@trait(phase) = "
newphase
"`.
`@trait(phase) = "
newphase
"`.
"""
"""
macro
phase
(
name
,
body
)
macro
phase
(
name
,
body
)
#XXX Using an undeclared variable in the body doesn't throw an error?
:
(
$
(
esc
(
name
))
=
function
(
animal
::
Animal
,
model
::
AgentBasedModel
)
$
body
end
)
:
(
$
(
esc
(
name
))
=
function
(
animal
::
Animal
,
model
::
AgentBasedModel
)
$
body
end
)
end
end
...
@@ -122,7 +131,11 @@ A utility macro to quickly access an animal's trait value.
...
@@ -122,7 +131,11 @@ A utility macro to quickly access an animal's trait value.
This can only be used nested within `@phase`.
This can only be used nested within `@phase`.
"""
"""
macro
trait
(
traitname
)
macro
trait
(
traitname
)
:
(
animal
.
traits
[
string
(
$
(
QuoteNode
(
name
)))])
if
traitname
in
fieldnames
(
Animal
)
:
(
animal
.$
(
traitname
))
else
:
(
animal
.
traits
[
string
(
$
(
QuoteNode
(
traitname
)))])
end
end
end
"""
"""
...
@@ -135,6 +148,26 @@ macro here(property)
...
@@ -135,6 +148,26 @@ macro here(property)
:
(
model
.
landscape
[
animal
.
pos
...
]
.$
(
property
))
:
(
model
.
landscape
[
animal
.
pos
...
]
.$
(
property
))
end
end
"""
@kill
Kill this animal. This is a thin wrapper around `kill!()`, and passes on any arguments.
This can only be used nested within `@phase`.
"""
macro
kill
(
args
...
)
:
(
kill!
(
animal
,
model
,
$
(
args
...
)))
end
"""
@reproduce
Let this animal reproduce. This is a thin wrapper around `reproduce!()`, and passes on
any arguments. This can only be used nested within `@phase`.
"""
macro
reproduce
(
args
...
)
:
(
reproduce!
(
animal
,
model
,
$
(
args
...
)))
end
### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE
### FUNCTIONS INTEGRATING THE NATURE MODEL WITH THE REST OF PERSEPHONE
...
@@ -156,9 +189,9 @@ Initialise the model with all simulated animal populations.
...
@@ -156,9 +189,9 @@ Initialise the model with all simulated animal populations.
function
initnature!
(
model
::
AgentBasedModel
)
function
initnature!
(
model
::
AgentBasedModel
)
# The config file determines which species are simulated in this run
# The config file determines which species are simulated in this run
for
s
in
param
(
"nature.targetspecies"
)
for
s
in
param
(
"nature.targetspecies"
)
funcname
=
Symbol
(
"speciesfunction_"
*
s
)
funcname
=
Symbol
(
SPECIESPREFIX
*
s
)
species
=
@eval
$
funcname
()
species
=
@eval
$
funcname
(
$
model
)
species
[
"initialise!"
](
model
)
species
[
"initialise!"
](
species
,
model
)
end
end
# Initialise the data output
# Initialise the data output
initecologicaldata
()
initecologicaldata
()
...
...
This diff is collapsed.
Click to expand it.
src/nature/species/skylark.jl
+
10
−
7
View file @
71a01dca
...
@@ -8,18 +8,21 @@
...
@@ -8,18 +8,21 @@
@species
Skylark
begin
@species
Skylark
begin
initialise!
=
initrandompopulation
()
popdensity
=
1
/
10000
phase
=
"egg"
lifeexpectancy
=
365
*
5
lifeexpectancy
=
365
*
5
eggharvestmortality
=
0.9
eggharvestmortality
=
0.9
eggpredationmortality
=
0.1
initialise!
=
initrandompopulation
(
popsize
)
phase
=
"egg"
@phase
egg
begin
@phase
egg
begin
if
!
parentsalive
(
animal
)
@kill
(
@trait
(
eggpredationmortality
),
"predation"
)
killanimal
(
animal
)
end
@respond
harvest
killanimal
(
animal
,
eggharvestmortality
)
#TODO dies if parents die
@respond
harvest
@kill
(
@trait
(
eggharvestmortality
),
"harvest"
)
if
animal
.
age
==
14
if
animal
.
age
==
14
@trait
(
phase
)
=
"nestling"
@trait
(
phase
)
=
"nestling"
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment