Forecast & the swarm¶
The W(M, T, R) survival forecast — the engine behind the IDE's forecast card — ported line for line into both libraries, plus the client for the bundled swarm: a stratified council of 256 professional agents and a society simulator.
The W(M, T, R) model¶
An entity's viability W is a Cobb–Douglas blend of three capitals:
M is material capital, T effective productive time, R
relational capital (family, belief, and a bell-shaped spatial term in
floor space per resident). Each year, Poisson-arriving shocks with
Normal severities hit the capitals; a Cox-style hazard
h = 0.02 · (W/W₀)⁻² accumulates survival; each Monte Carlo path ends
classified grew / stabilized / declined / collapsed (collapse =
below 30 % of W₀ for five consecutive years, by default).
The random stream is Mulberry32 — the same generator, bit for bit, as
Scelo IDE and the swarm. wmtr(..., seed=42) in Python, R, or the
IDE's forecast card produce identical tables; both packages assert this
against a fixture generated by the TypeScript engine, to 1e-9.
Running a forecast¶
The engine is local — no server needed.
r = sc.wmtr("pension scheme with a weakening sponsor covenant")
r.survival # 0.5399… — mean survival at the horizon
r.outcome_fractions # {'grew': 0.0, 'stabilized': 0.7, 'declined': 0.3, …}
r.drivers # exact decomposition of Δln W into M, T, R
r.table # year-by-year Table: mean_W, percentile band, survival
sc.sensitivity("…scenario…") # the same forecast under mild / moderate / severe
sc.wmtr(alphaM=0.5, shock="severe", horizon=60, nPaths=1000) # explicit dials
sc.wmtr(sc.sample("wmtr-scenarios")) # a scenario row from a file
WMTR · moderate · 30y · 200 paths · survival@horizon 0.540 · W/W₀ 0.96 · dominant stabilized · driver M
year mean_W p10_W p25_W ... survival mean_M mean_T mean_R
0 0 0.724584 0.724584 0.724584 ... 1.000000 1.000000 0.430000 0.757362
...
30 30 0.696157 0.585848 0.640730 ... 0.539900 0.762330 0.376571 0.972046
— WMTR forecast · moderate shocks · 30y · 200 paths · seed 7830
basis: α = (0.35, 0.25, 0.4) · w = (0.4, 0.3, 0.3) · shock moderate
· Outcomes: grew 0% · stabilized 70% · declined 30% · collapsed 0% (dominant: stabilized).
· Drivers (Σ = mean Δln W = -0.0480): M -0.1130 · T -0.0346 · R +0.0996; dominant M.
Exact Cobb-Douglas decomposition, accumulated per path then averaged.
· W = M^αM·T^αT·R^αR; hazard h = 0.02·(W/W₀)^−2; shocks ~ Poisson(λ) with Normal
severities clipped to (0.01, 0.9). Same Mulberry32 stream as Scelo IDE / the swarm.
Scenario text is parsed, deterministically. Word-bounded cues set the shock environment (pandemic, crisis, severe → severe; calm, benign → mild), the capital weights (pension scheme leans relational; reserving leans material; rural village re-weights and widens the floor space; urban tightens it), and the horizon (long-term → 60y). The seed is a hash of the text itself, so the same sentence always gives the same forecast — and the note prints every derived parameter. Nothing is a language model: the parser is a fixed cue list, the same one the IDE uses.
driver_contributions(r) decomposes ln W_T − ln W_0 exactly into the
three capitals' contributions (they sum to the net, to machine
precision); apply_intervention(params, "pFamily", "increase", "large")
shifts one dial by 0.07 / 0.20 for what-if runs; classify,
derive_config, wmtr_params and even mulberry32 itself are exported
for when you want the pieces.
The swarm¶
Scelo IDE 0.1.6+ bundles the swarm and starts it with the app on
127.0.0.1:3010; from a checkout, bun run dev:swarm runs the same
server. The client functions speak to its HTTP API with the standard
library / base R only.
sc.swarm_status() # is it up, which model providers
c = sc.council("raise the guarantee fee to 80bps", subset=32)
c.summary # trust / distrust / consensus / risks
c.votes # one row per agent: profession, MBTI, stance
c.interventions # the parameter changes the council proposes
sc.intervene(c.run_id, "pFamily", "increase", "small") # apply one, re-convene
sc.justify(c.run_id, "agent_017") # why that agent voted that way
soc = sc.society("a 3-month fuel shortage", size=200) # one row per simulated person
aug = sc.augment(book, "the same shortage") # sim_* columns joined to your own rows
sc.connect("http://other-host:3010") # or export SCELO_SWARM_URL
sc_swarm_status()
c <- sc_council("raise the guarantee fee to 80bps", subset = 32)
c$summary; c$votes; c$interventions
sc_intervene(c$run_id, "pFamily", "increase", "small")
sc_justify(c$run_id, "agent_017")
soc <- sc_society("a 3-month fuel shortage", size = 200)
aug <- sc_augment(book, "the same shortage")
sc_connect("http://other-host:3010")
- The council is a stratified sample of the full 256-agent body — 8
professions × 16 MBTI types × 2 genders — deliberating with the WMTR
evidence injected.
subset=32convenes 32 of them; results carry the votes, the consensus score, the ranked risks, and the interventions they propose, each traceable to agents you can ask to justify themselves. - The society simulates a population's response to a scenario, one
row per person (20–2000 of them), with the macro roll-up — workdays
lost, GDP drag, excess mortality, insurer claims — in the notes.
The echoed
seedreproduces a run exactly. - Augment matches your own rows to the simulated cohort on the age /
sex / comorbidity each row states (a row that states none gets the
whole cohort's figures;
sim_bucket_matchsays which) and joinssim_*outcome columns on (capped at 100,000 rows, the IDE's limit).
When the swarm is not running
The client does not pretend. Every swarm call fails with one clear
message — cannot reach the swarm at http://127.0.0.1:3010. Start
Scelo IDE (it bundles the swarm) or run bun run dev:swarm, or
connect(url) — and nothing else in the libraries depends on it.
wmtr and sensitivity are local and always work.
Function list¶
wmtr run_wmtr derive_config wmtr_params classify sensitivity
driver_contributions dominant_driver apply_intervention
mulberry32 · connect swarm_url swarm_status council
council_run intervene justify chat_log swarm_wmtr society
augment — each with the sc_ twin in R (WmtrParams is the Python
dataclass; sc_wmtr_params() the R constructor).