matpopmod.examples

This module provides ready-made models that can be used to get familiar with the library or for pedagogical purposes.

>>> from matpopmod.examples import orcinus_orca
>>> orcinus_orca
MPM(
  S = [[0.    , 0.    , 0.    , 0.    ],
       [0.9775, 0.9111, 0.    , 0.    ],
       [0.    , 0.0736, 0.9534, 0.    ],
       [0.    , 0.    , 0.0452, 0.9804]],
  F = [[0.    , 0.0043, 0.1132, 0.    ],
       [0.    , 0.    , 0.    , 0.    ],
       [0.    , 0.    , 0.    , 0.    ],
       [0.    , 0.    , 0.    , 0.    ]],
  metadata = {
    'ModelName': 'orcinus_orca',
    'Species': 'Orcinus orca',
    'CommonName': 'Killer whale',
    'Classes': ['Newborns', 'Juveniles', 'Reproductive adults',
'Post-reproductive adults'],
    'Source': 'Example 5.1 from Caswell H. (2000). Matrix
Population Models: Construction, Analysis, and Interpretation.',
    'Comments': 'The projection matrix is not irreducible due
to the presence of a post-reproductive class.\n\nExample of a
K-strategy, with high survival and low fertility.'
  }
)

Only a handful of models of specific interest are given. For a much larger collection of models, see the module compadre, which provides an interface to the COMPADRE and COMADRE databases.

Complete list of models

matpopmod.examples.orcinus_orca

Stage-based model for the killer whale Orcinus orca (Example 5.1 in [Casw00], based on data from [BrCa93]). The projection matrix is

\[\begin{split}\mathbf{A} = \begin{pmatrix} 0 & 0.0043 & 0.1132 & 0 \\ 0.9775 & 0.9111 & 0 & 0 \\ 0 & 0.0736 & 0.9534 & 0 \\ 0 & 0 & 0.0452 & 0.9804 \end{pmatrix},\end{split}\]

and the classes correspond to newborns, juveniles, reproductive adults and post-reproductive adults. This is an example of what refer to as an Usher model, that is, the survival probabilities are on the diagonal and subdiagonal entries of the projection matrix, and the fertilities on its first row.

>>> orcinus_orca.usher
True

An interesting feature of the model is that it is reducible due to the presence of a post-reproductive class:

>>> orcinus_orca.irreducible
False
>>> orcinus_orca.postreproductive_classes
array([0., 0., 0., 1.])
>>> orcinus_orca.v # reproductive values
array([ 1.14163164,  1.19762278,  1.79386902, -0.        ])

It also is an example of a K-strategy, i.e. of a life-cycle with a very high survival and a low fertility. This results in long lifespans, but because individuals do not reproduce during their whole life the generation time remains comparatively short.

>>> orcinus_orca.life_expectancy
69.41056244644568
>>> orcinus_orca.T_a # generation time (mean age of mothers)
23.69204811243964
>>> orcinus_orca.T_R0 # R0 generation time
27.850790932634087
matpopmod.examples.bernardelli_beetle

The famous model for Bernardelli’s fictitious beetle, from [Bern41] (partially reprinted in [SmKe77]). In this influential paper, Bernardelli imagined a population of beetles whose dynamics are governed by the projection matrix

\[\begin{split}\mathbf{A} = \begin{pmatrix} 0 & 0 & 6 \\ \frac{1}{2} & 0 & 0 \\ 0 & \frac{1}{3} & 0 \end{pmatrix},\end{split}\]

(although he does point out that the numerical values are irrelevant), and showed that the population would be subject to sustained oscillations, which he termed “population waves”. And, indeed:

traj = bernardelli_beetle.trajectory([100, 0, 0], 40)
matpopmod.plot.trajectory(traj) 
../_images/examples-1.png

This is because the projection matrix is periodic, with index of imprimitivity 3:

>>> bernardelli_beetle.aperiodic
False
>>> bernardelli_beetle.index_of_imprimitivity
3

As a result, there is no stable distribution in the usual sense. However, since the projection matrix is irreducible, it has a well-defined Perron vector (that is, a unique non-negative eigenvector associated to λ) and it remains possible to compute quantities such as the elasticities.

>>> bernardelli_beetle.w
UserWarning: A is not quasi-primitive. Most descriptors are
ill-defined. They will be set to NaN.
array([nan, nan, nan])
>>> bernardelli_beetle.right_eigenvectors[0]
array([0.6, 0.3, 0.1])
>>> bernardelli_beetle.elasticities
array([[0.        , 0.        , 0.33333333],
       [0.33333333, 0.        , 0.        ],
       [0.        , 0.33333333, 0.        ]])
matpopmod.examples.passerine_postbreeding

A generic model for passerine birds, using a post-breeding census. The projection matrix is

\[\begin{split}\mathbf{A} = \begin{pmatrix} \sigma s_0 f_1 & \sigma s f_2 & \sigma \nu f_2 \\ s_0 & 0 & 0 \\ 0 & s & \nu \end{pmatrix},\end{split}\]

where \(s_0\) (resp. \(s\), \(\nu\)) is the survival probability of newborns (resp. yearlings, adults); \(f_1\) (resp. \(f_2\)) is the fecundity of female yearlings (resp. adults), i.e. the expected number of chicks they produce; and \(\sigma\) is the primary sex ratio, i.e. the proportion of females at birth. The numerical values used here are from the model passa_0 shipped with the ULM software.

The output of this model can be compared with that of the corresponding pre-breeding model, passerine_prebreeding.

>>> passerine_postbreeding.w # stable distribution
array([0.77777778, 0.14077741, 0.08144481])
>>> passerine_prebreeding.w
array([0.63349835, 0.36650165])
>>> passerine_postbreeding.elasticities
array([[0.37947486, 0.12019835, 0.09934154],
       [0.21953989, 0.        , 0.        ],
       [0.        , 0.09934154, 0.08210381]])
>>> passerine_prebreeding.elasticities
array([[0.37947486, 0.21953989],
       [0.21953989, 0.18144535]])
matpopmod.examples.passerine_prebreeding

A generic model for passerine birds, using a pre-breeding census. The projection matrix is

\[\begin{split}\mathbf{A} = \begin{pmatrix} \sigma s_0 f_2 & \sigma s_0 f_2 \\ s & \nu \end{pmatrix}.\end{split}\]

See passerine_postbreeding for more information.

matpopmod.examples.dipsacus_sylvestris

Complex life-cycle for the common teasel Dipsacus fullonum (also referred to as Dispacus sylvestris by most publications citing this model) from [Casw00], Example 5.2. Based on the original publication [CaWe78].

matpopmod.plot.life_cycle(dipsacus_sylvestris)
../_images/examples-2.png

The classes are, from 0 to 5: first-year dormant seeds, second-year dormant seeds, small rosettes, medium rosettes, rosettes and flowering plants.

This is an example of a model with ill-defined newborn classes: classes 3, 4 and 5 can be reached either by following a reproductive transition or by following a survival one. As a result, it is not possible to know if individuals in those classes are newborns or not.

>>> dipsacus_sylvestris.newborn_classes
array([ 1.,  0., nan, nan, nan,  0.])

However, this does not affect the calculation of the descriptors implemented in this library. It is also possible to compute the fraction of individuals that are newborns in each class in the stable class structure population:

>>> dipsacus_sylvestris.proportion_newborns
array([1.        , 0.        , 0.5611508 ,
       0.86103652, 0.139299  , 0.        ])
matpopmod.examples.homo_sapiens_USA

Leslie model with a 5-year projection interval for the population of the United States in 1966, from [KeCa05], Example 7.2. (also in [Casw00] and based on [KeFl71]). The life-table is:

Age class

Survival probability

Fertility

0–4

0.99670

0

5–9

0.99837

0.00102

10–14

0.99780

0.08515

15–19

0.99672

0.30574

20–24

0.99607

0.40002

25–29

0.99472

0.28061

30–34

0.99240

0.15260

35–39

0.98867

0.06420

40–44

0.98274

0.01483

45–49

0.00089

Because the projection interval is 5 years, one must be careful when interpreting the descriptors. For instance, the yearly growth rate is \(\sqrt[5]{\lambda} \approx 1.01\), and not \(\lambda \approx 1.05\):

>>> PI = homo_sapiens_USA.metadata["ProjectionInterval"]
>>> PI
5.0
>>> homo_sapiens_USA.lmbd
1.0497530435202165
>>> homo_sapiens_USA.lmbd ** (1 / PI)
1.0097582926164328

Similarly, quantities such as the generation time should be multiplied by the length of the projection interval.

>>> homo_sapiens_USA.T_a * PI
25.935182726205607
>>> homo_sapiens_USA.T_R0 * PI
26.14245390652162
matpopmod.examples.thalia_democratica

Two-sex model for the small salp Thalia democratica, from [HSES15].

../_images/examples-3.png

The classes are, from 1 to 4: females (>1 mm), males (>4 mm), juvenile oozoids (3-10 mm) and post-release oozoids (>10 mm).

Despite the name “two-sex model”, males have no impact on the dynamics of the population. Mathematically, they correspond to a post-reproductive class. It is never possible to have a two-sex matrix population model where the frequency of males and females influences the dynamics of the population. This is because this would require introducing non-linearities, whereas matrix population models are by definition linear.

This is an example of a model where the classic measure of \(R_0\) – namely, the dominant eigenvalue of the next generation matrix – and its usual interpretation (the expected per-capita reproductive output of a cohort of newborns at the stable class distribution) differ markedly:

>>> thalia_democratica.R0
4.001730883164397
>>> thalia_democratica.cohort_R0
5.222416673531084

The reason for this discrepancy is that at the stable stage distribution, 28% of the new individuals produced in a year are juvenile oozoids and 72% are females. By contrast, if we sample a newborn according to the dominant eigenvector of next generation matrix, it only has a 20% chance of being a juvenile oozoid. Since juvenile oozoids have a higher reproductive value than females, this explains that a stable cohort of newborns will have a higher expected reproductive output.

matpopmod.examples.astrocaryum_mexicanum

Usher model for the palm tree Astrocaryum mexicanum (Table A2 in [CoEl92], based on data from [PiMS84]).

../_images/examples-4.png

The stages are, from 1 to 10: fruits, infants, juveniles, immature adults, mature adults 1–6.

This is an example of a model where the three classic measures of generation time \((\mu_1\), the mean age of parents of offspring produced by a cohort, also frequently referred to as the cohort generation time; \(T_a\), the mean age of mothers in the stable population; and \(T_{R_0}\), the \(R_0\) generation time) differs greatly.

>>> astrocaryum_mexicanum.mu1
275.1594139265308
>>> astrocaryum_mexicanum.T_a
152.5908805755843
>>> astrocaryum_mexicanum.T_R0
197.61963152089652

This models highlights problems with the interpretation of \(\mu_1\) (and of the related measure \(T_G\) introduced by [StTC14]). Indeed, \(\mu_1\) is often claimed to be a measure of the mean age at reproduction for a typical individual, but in reality it systematically overestimates it, as explained in [Bien19]. In fact, \(\mu_1\) differs can even exceed the life expectancy conditional on reproduction, as is the case here:

>>> astrocaryum_mexicanum.mu1
275.1594139265308
>>> mpm.set_rng_seed(0) # for reproducibility
>>> astrocaryum_mexicanum.mean_age_repro() # ~20 mins 
152.61792711532627
>>> astrocaryum_mexicanum.life_expectancy_repro
232.18934046629712
matpopmod.examples.second_order_oscillations

An example of a projection matrix with non-trivial second order oscillations:

\[\begin{split}\mathbf{A} = \begin{pmatrix} 0 & 2 & 2 & 1 \\ \frac{1}{4} & 0 & 0 & 0 \\ 0 & \frac{3}{4} & 0 & 0 \\ 0 & 0 & \frac{2}{3} & 0 \\ \end{pmatrix}\end{split}\]

The eigenvalues of A are \(\big\{1, -\frac{1}{2}, \frac{1}{2} e^{2i\pi/3}, \frac{1}{2} e^{-2i\pi/3}\big\}\). Thus, there are three eigenvalues on the second spectral circle: \(-\frac{1}{2}\) generates oscillations with period 2 and the pair \((\frac{1}{2} e^{2i\pi/3}, \frac{1}{2} e^{-2i\pi/3})\) generates oscillations with period 3. Since there exist positive integers \((k, k')\) such that \(2k = 3 k'\), the second-order dynamic of this model is periodic, with period \(\mathrm{lcm}(2, 3) = 6\).

>>> second_order_oscillations.transient_period
5.999999999999999

The periodic component of the second-order dynamics can be illustrated by plotting it. Note that here we rescale the second order term by \(1/2^t\) to compensate the damping of the oscillations and make the periodicity more apparent.

traj = second_order_oscillations.trajectory(
  n0 = [1, 1, 1, 1],
  t_max = 30 
)

matpopmod.plot.trajectory(
  traj,
  second_order = True,
  rescale = True,
  show_period = True
)
../_images/examples-5.png