You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Developing and validating the assembly / attractor machinery in regnans
(community_demography, community_selection_gradient, community_solve_singularity_1D, community_fitness_landscape, the births_*/deaths/assembler loop) is slow and hard to verify because every
fitness or equilibrium evaluation runs the full plant SCM (run_scm), which
dominates test wall-clock (see test-solve-attractors.R) and has no
closed-form answer to check the algorithms against.
We want one or more fast toy models with analytic (or near-analytic) invasion
fitness to plug into the same community interface, so we can:
iterate on algorithms in milliseconds rather than SCM-seconds;
validate numerics against known answers — singular strategies, branching
points, and viable bounds that are analytically derivable;
This is the detailed version of the placeholder #21 (which has an empty body) and
feeds the epic #22. Suggest closing #21 as superseded by this.
Integration point
A toy model only needs to satisfy the abstraction the community object already
assumes. community$model_support + the plant_community_* aliases in R/community_plant.R are explicitly designed to be swappable (AGENTS.md: "This
indirection is so the plant-specific layer could in principle be swapped"). A toy
backend supplies:
fitness_function(x_new, x, y) → invasion fitness of mutant(s) x_new in
resident community (x, y);
a demographic-equilibrium solver for y (analytic where possible, else the
existing equilibrium_iteration on the difference equation y_i(t+1) = y_i(t)(1 + f(x_i, x, y))).
The job is to add a non-plant model_support backend (e.g. toy_model_support(make_dieckmann_1999())) and confirm the whole community
pipeline runs against it unchanged. The old traitecoevo/Revolve package
(x_misc/Revolve) already implements several of these as make_* closures
returning exactly fitness / equilibrium / single_equilibrium — they can be
ported with light adaptation.
Second analytic 1D check; asymmetric kernel exercises a different regime than DD99. Top pick.
Fox & Vasseur 2008 — competition for two essential (Tilman) resources
✅ fox-2008.R
1D trait
Character convergence (not branching); ODE/resource-explicit with analytic resource equilibria
A non-branching counterpoint, and a resource-explicit (R*) structure closer to plant's mechanism. Good.
Geritz et al. seed-size in safe sites (1988/1995/1999)
❌ (described only)
1D
Polymorphism in seed size; patch/Poisson safe-site structure
Most plant-relevant: patch-structured invasion fitness conceptually parallel to plant's patch model, on a real plant trait. Higher implementation cost (Poisson sum over patch occupancy). Recommended.
Ito & Dieckmann 2007 — multi-trait, directional + disruptive
❌ (described only)
2D
Branching in one trait, directional selection in another; recurrent radiations
Directly fills #22's nD attractor gap — the cheapest way to test 2D gradients/singularities. Recommended.
R* (Tilman / Huisman–Weissing)
✅ rstar.R
nD resources
Resource competition; can give oscillations/chaos with ≥3 resources
Useful later as a non-point-attractor stress test; heavier (RefClass, ODE).
Multi-resource DD99 (Ito & Dieckmann 2007)
❌
nD
nD branching
Alternative nD case; parameters never published, so less attractive than Ito 2D directional.
Also present: mutation.R (mvnorm mutation generator — directly reusable by the
stochastic assembler) and utils.R (equilibrium_sys, ODE/iteration helpers).
Recommendation — start with two well-understood "successful" examples
Begin with two models whose outcomes are clean, classic, and analytically
verifiable — one convergence to a stable endpoint, one branching — so the
core algorithms can be validated against known answers before tackling harder
cases:
Starter 1 — Migratory-bird arrival time (Brännström et al. 2013, §4)
A discrete-time, single-trait model (trait x = arrival time) with
frequency dependence via competition for K territories. Fully analytic — every
quantity below can be checked in a unit test. Outcome: convergence to a single continuously stable strategy (CSS), no branching — the canonical "clean
success" case.
Singular strategyx* = x_opt - a·σ² — provably convergence-stable and an
ESS (a CSS).
Why first: trivial to implement, exercises the discrete-time equilibrium path and community_selection_gradient / community_solve_singularity_1D, and gives an
exact x* to assert against. A nice ecological story too (tragedy of the
commons — birds arrive earlier than the population optimum).
Starter 2 — Geritz seed-size in safe sites (branching)
The Geritz seed-size / asymmetric-competition-for-safe-sites model (Geritz et al.
1988/1995/1999; the canonical AD treatment is Geritz, Kisdi, Meszéna & Metz
1998, Evol. Ecol. Res. 12:35–57). A 1D evolutionary-branching case on a real
plant trait (seed size), with an explicit PIP and a convergence-stable fitness-minimum singular strategy — the standard demonstration that the
machinery detects branching, complementing the bird model's CSS endpoint. Also
the most plant-relevant toy model (patch-structured, seed size).
An implementation already exists — Daniel's MATLAB version reproducing
Geritz et al. 1999 Fig. 5 PIPs, at OneDrive-UNSW/research/directions/Offspring-SmithFretwellReview/models/Geritz/.
The task is a MATLAB→R port. The pieces map directly onto the toy-model
interface and match x_misc/Revolve/doc/models.md:
establishment g(m', m, N) = Σ_k e^{-N} N^k/k! · c(m')/(c(m') + k·c(m))
— Poisson sum over seeds arriving per safe site (g.m);
invasion fitness f̂ = (R/m')·s(m')·g(m', m, N) (Fit.m);
resident equilibrium density N* by 1D root-find on the self-competition
balance (res_DE.m + g_res.m).
So invasion fitness is effectively analytic (a truncated Poisson sum) and the
resident solve is a cheap 1D uniroot — no SCM, fast.
Gotcha for assembly: the MATLAB g() handles a single resident only. For
multi-species communities (which regnans assembles) the establishment term needs
the full multi-resident Poisson product-sum from models.md eq. (g). Start with
the 1-resident case (enough for the PIP / singular-strategy / branching tests),
then generalise.
(If the Poisson form proves fiddly to port, the Revolve-implemented DD99 / Kisdi
1999 below are drop-in stand-ins for a branching test.)
Follow-ups (after the two starters work)
Dieckmann & Doebeli 1999 + Kisdi 1999 — near-free ports of dieckmann-1999.R / kisdi-1999.R; extra analytic branching checks.
Other suggestions from the literature (beyond models.md)
MacArthur–Roughgarden L–V competition kernel (MacArthur 1970; Roughgarden
1972) — the fully-analytic mechanistic ancestor of DD99; the simplest possible
limiting-similarity test.
Rosenzweig–MacArthur predator–prey AD (Dieckmann, Marrow & Law 1995;
Dercole & Rinaldi 2008) — produces evolutionary limit cycles / Red Queen
dynamics; a point-attractor solver should fail here, so a valuable
robustness/negative test (leave for later, not a "successful example").
Doebeli & Dieckmann 2000 (Nature) / Doebeli 2011 Adaptive
Diversification — competition along an environmental gradient; many small
worked examples.
Brännström, Johansson & von Festenberg 2013, "The Hitchhiker's Guide to
Adaptive Dynamics", Games 4:304–328 — the source of Starter 1; tutorial
review with worked models and pseudocode for PIPs, branching, the canonical
equation, and trait-evolution (dimorphic) plots. The best implementation /
diagnostic reference to follow throughout.
Acceptance criteria
A non-plant model_support backend exists; the core community pipeline
(community_start → community_add → community_demography → community_selection_gradient) runs against a toy model with no SCM call.
Starter 1 — bird arrival-time model implemented; a test asserts the
recovered singular strategy matches x* = x_opt - a·σ² (a CSS / clean
convergence).
Starter 2 — Geritz seed-size safe-site model ported from MATLAB to R; a
test confirms a convergence-stable fitness-minimum singular strategy
(branching detected) and reproduces the Geritz et al. 1999 Fig. 5 PIP.
(Follow-up) DD99 / Kisdi 1999 ported as extra branching checks.
Problem statement
Developing and validating the assembly / attractor machinery in
regnans(
community_demography,community_selection_gradient,community_solve_singularity_1D,community_fitness_landscape, thebirths_*/deaths/assemblerloop) is slow and hard to verify because everyfitness or equilibrium evaluation runs the full
plantSCM (run_scm), whichdominates test wall-clock (see
test-solve-attractors.R) and has noclosed-form answer to check the algorithms against.
We want one or more fast toy models with analytic (or near-analytic) invasion
fitness to plug into the same
communityinterface, so we can:points, and viable bounds that are analytically derivable;
attractor solver (an unmet acceptance criterion in [evol assembly] Enable evolutionary dynamics & community assembly #22) and the
non-branching / convergence and non-point-attractor cases.
This is the detailed version of the placeholder #21 (which has an empty body) and
feeds the epic #22. Suggest closing #21 as superseded by this.
Integration point
A toy model only needs to satisfy the abstraction the
communityobject alreadyassumes.
community$model_support+ theplant_community_*aliases inR/community_plant.Rare explicitly designed to be swappable (AGENTS.md: "Thisindirection is so the plant-specific layer could in principle be swapped"). A toy
backend supplies:
fitness_function(x_new, x, y)→ invasion fitness of mutant(s)x_newinresident community
(x, y);y(analytic where possible, else theexisting
equilibrium_iterationon the difference equationy_i(t+1) = y_i(t)(1 + f(x_i, x, y))).The job is to add a non-plant
model_supportbackend (e.g.toy_model_support(make_dieckmann_1999())) and confirm the whole communitypipeline runs against it unchanged. The old
traitecoevo/Revolvepackage(
x_misc/Revolve) already implements several of these asmake_*closuresreturning exactly
fitness/equilibrium/single_equilibrium— they can beported with light adaptation.
Review of the Revolve catalogue
Source:
x_misc/Revolve/doc/models.md+x_misc/Revolve/R/.R/?dieckmann-1999.Rkisdi-1999.Rfox-2008.Rrstar.RAlso present:
mutation.R(mvnorm mutation generator — directly reusable by thestochastic assembler) and
utils.R(equilibrium_sys, ODE/iteration helpers).Recommendation — start with two well-understood "successful" examples
Begin with two models whose outcomes are clean, classic, and analytically
verifiable — one convergence to a stable endpoint, one branching — so the
core algorithms can be validated against known answers before tackling harder
cases:
Starter 1 — Migratory-bird arrival time (Brännström et al. 2013, §4)
A discrete-time, single-trait model (trait
x= arrival time) withfrequency dependence via competition for
Kterritories. Fully analytic — everyquantity below can be checked in a unit test. Outcome: convergence to a single
continuously stable strategy (CSS), no branching — the canonical "clean
success" case.
C(x) = exp(-a·x)(early arrivers win territories).R(x) = R₀·exp(-(x - x_opt)² / 2σ²)(peaks atx_opt).p; resident demographyn_{t+1} = K·R(x) + p·n_t,so
n* = K·R(x)/(1-p).w=1at equilibrium):w_x(x') = (1-p)·C(x')R(x') / (C(x)R(x)) + p.D(x) = -(1-p)·(a + (x - x_opt)/σ²).x* = x_opt - a·σ²— provably convergence-stable and anESS (a CSS).
Why first: trivial to implement, exercises the discrete-time equilibrium path and
community_selection_gradient/community_solve_singularity_1D, and gives anexact
x*to assert against. A nice ecological story too (tragedy of thecommons — birds arrive earlier than the population optimum).
Starter 2 — Geritz seed-size in safe sites (branching)
The Geritz seed-size / asymmetric-competition-for-safe-sites model (Geritz et al.
1988/1995/1999; the canonical AD treatment is Geritz, Kisdi, Meszéna & Metz
1998, Evol. Ecol. Res. 12:35–57). A 1D evolutionary-branching case on a real
plant trait (seed size), with an explicit PIP and a convergence-stable
fitness-minimum singular strategy — the standard demonstration that the
machinery detects branching, complementing the bird model's CSS endpoint. Also
the most plant-relevant toy model (patch-structured, seed size).
An implementation already exists — Daniel's MATLAB version reproducing
Geritz et al. 1999 Fig. 5 PIPs, at
OneDrive-UNSW/research/directions/Offspring-SmithFretwellReview/models/Geritz/.The task is a MATLAB→R port. The pieces map directly onto the toy-model
interface and match
x_misc/Revolve/doc/models.md:s(m) = max(0, 1 - 2·exp(-β·m))(f.m);c(m) = exp(α·m)(c.m);g(m', m, N) = Σ_k e^{-N} N^k/k! · c(m')/(c(m') + k·c(m))— Poisson sum over seeds arriving per safe site (
g.m);f̂ = (R/m')·s(m')·g(m', m, N)(Fit.m);N*by 1D root-find on the self-competitionbalance (
res_DE.m+g_res.m).So invasion fitness is effectively analytic (a truncated Poisson sum) and the
resident solve is a cheap 1D
uniroot— no SCM, fast.Gotcha for assembly: the MATLAB
g()handles a single resident only. Formulti-species communities (which regnans assembles) the establishment term needs
the full multi-resident Poisson product-sum from
models.mdeq. (g). Start withthe 1-resident case (enough for the PIP / singular-strategy / branching tests),
then generalise.
(If the Poisson form proves fiddly to port, the Revolve-implemented DD99 / Kisdi
1999 below are drop-in stand-ins for a branching test.)
Follow-ups (after the two starters work)
dieckmann-1999.R/kisdi-1999.R; extra analytic branching checks.models.md); the cheap case to build and validate the nD attractor solver([evol assembly] Enable evolutionary dynamics & community assembly #22) and 2D fitmax births (
find_max_fitness_2d, unverified — [evol assembly] Error in find_max_fitness_2d if trait value on the boundary #9).Other suggestions from the literature (beyond models.md)
1972) — the fully-analytic mechanistic ancestor of DD99; the simplest possible
limiting-similarity test.
Dercole & Rinaldi 2008) — produces evolutionary limit cycles / Red Queen
dynamics; a point-attractor solver should fail here, so a valuable
robustness/negative test (leave for later, not a "successful example").
Diversification — competition along an environmental gradient; many small
worked examples.
Adaptive Dynamics", Games 4:304–328 — the source of Starter 1; tutorial
review with worked models and pseudocode for PIPs, branching, the canonical
equation, and trait-evolution (dimorphic) plots. The best implementation /
diagnostic reference to follow throughout.
Acceptance criteria
model_supportbackend exists; the core community pipeline(
community_start → community_add → community_demography → community_selection_gradient) runs against a toy model with no SCM call.recovered singular strategy matches
x* = x_opt - a·σ²(a CSS / cleanconvergence).
test confirms a convergence-stable fitness-minimum singular strategy
(branching detected) and reproduces the Geritz et al. 1999 Fig. 5 PIP.
nD attractor path (ties to [evol assembly] Enable evolutionary dynamics & community assembly #22).
wall-clock cost.
Refs: #21 (supersedes), #22 (epic), #9 (
find_max_fitness_2don boundary).Source material:
x_misc/Revolve/doc/models.md,x_misc/Revolve/R/.