Hybrid opinion dynamics — an LLM + ABM population on one kernel¶
studies/hisim_roe/ · reference: true · Path B (from scratch on the core
kernel)
On a Twitter-like platform, after the news "the Supreme Court overturns Roe v. Wade" fires, how do the opinions of LLM-driven core users and ABM-driven ordinary users evolve — and which cohort actually moves the aggregate? This case is the pattern for a hybrid population: two cohorts sharing one environment, one panel and one metric set, but running completely different behaviour functions. It is also the pattern for porting a published external simulator (Mou et al., 2024) natively onto the core interfaces rather than wrapping it.
What the v0.2.0 repository ships
In the open-source repository hisim_roe is an imported reference
(rerunnable: false). Its shipped report leads with the technical report's
social-movement case: the published hybrid trajectory scored against
observed Twitter sentiment over 14 rounds, rebuilt by
build_from_techreport.py (pass metoo or blm to switch the scenario).
The 4-step, 20-agent live-LLM port this page walks through is preserved in
the report's last section, and its code (model.py, reporting.py) is the
template for a real run: start a new study from it.
P / E / B¶
| what it is | where it comes from | |
|---|---|---|
| P | 20 agents: 8 core-* (LLM role-play) + 12 ord-* (bounded-confidence rule). Opinions initialized uniformly on [-1, 1], deterministic under seed: 42. Interaction is explicit_network — a 16-edge directed ring over the core users only; propagation contagion. |
population/population.json (materialized_count: 20) |
| E | Three layers, one scheduled event and one broadcast — see below. Provider hisim.twitter_env with n_core: 8, n_ord: 12, alpha: 0.3, bc_bound: 0.1, target: "the protection of Abortion Rights". |
environment/environment.json |
| B | Decision hisim.hybrid_decision (mode: llm, gpt-4o-mini). Core users role-play and act; their opinion is then mirrored off the tweet they produced. Ordinary users run the Deffuant rule. |
model.py |
| layer | modality | scope | dynamics | content |
|---|---|---|---|---|
tweet_feed |
information | local | endogenous | the audience timeline of recent tweets |
trigger_news |
information | macro | scheduled | the offline event news broadcast |
peer_opinion |
physical | macro | endogenous | global confidence-band peer opinions (BCM) |
At step 2 a scheduled event sets trigger_news.content, and broadcast N1
("News- a major event concerning the protection of Abortion Rights occurs.")
goes out to audience: "all" with ttl 4.
A later intervention here would be a branch
This study is from-scratch (Path B) and runs interaction_rounds: 1, which
is exactly the eligibility condition for a counterfactual branch: a new
version that only adds an intervention at at_step >= t* and leaves the
population, the behaviour function, the seed and every earlier environment
entry untouched. Adding a second news wave at step 3, on top of the step-2
event, is that shape — steps 0–2 are replayed from the parent run with no
LLM calls, and only steps 3–4 are computed and paid for. Moving the existing
news to step 1 instead edits the environment before the fork step, so it
is a new version and runs cold from step 0. See
Intervention and counterfactual branching.
The two behaviour paths, precisely:
- Core (LLM) — one role-play call per core user per step, producing an
action and a stance; the agent's opinion is rewritten to
sign(stance) · |sentiment|. Observed action kinds across the run:retweet18,post10,like2,do_nothing2. - Ordinary (ABM) — the Deffuant bounded-confidence update
new = x + alpha · (peer − x)applied only when|peer − x| < bc_bound(alpha0.3,bc_bound0.1). 48update_opinionactions over the run — 12 agents × 4 decided steps.
The LLM path is a variance source (an opinion can jump, even flip sign); the rule path is a contraction operator (it only pulls neighbours closer). Which one wins is an empirical question, and this study answers it.
One step, and the horizon¶
One step is one platform turn: core users see their timeline plus any live
broadcast and act; ordinary users assimilate toward peers inside the confidence
band; metrics are then computed over all 20 agents. n_steps: 4, seed: 42,
so five metric rows (t=0 plus four decided steps).
This study runs one interaction round per step
The committed simulation/simulation.json has interaction_rounds: 1,
even though the study's demonstrates list mentions multi-round messaging.
What ships and what ran is single-round. If you want several message
exchanges inside one step, that is a config change — see
Multi-Round Interaction.
Results¶

| step | bias |
diversity |
mean_core |
mean_ordinary |
n_active |
n_post |
|---|---|---|---|---|---|---|
| 0 | -0.2223 | 0.32156 | -0.1112 | -0.2964 | 0 | 0 |
| 1 | -0.1170 | 0.22357 | +0.1559 | -0.2990 | 6 | 6 |
| 2 (news) | -0.1474 | 0.19541 | +0.0885 | -0.3047 | 8 | 7 |
| 3 | -0.1543 | 0.19324 | +0.0749 | -0.3070 | 8 | 7 |
| 4 | -0.1590 | 0.19076 | +0.0653 | -0.3085 | 8 | 8 |
Net over the horizon: bias +0.0633, diversity −0.1308 (the population
converges). The two cohorts diverge sharply — core moved +0.1765 while
ordinary moved only −0.0121.
The instructive detail is when the movement happened. The largest single-step
change in bias is step 1 at +0.1053 — before the news fires. The news
step itself moves bias by only −0.0304, and core activity was already 6/8
at step 1 before saturating at 8/8. At this scale the LLM cohort's own
expression dominates the aggregate, not the exogenous shock: the target topic
is present in the core users' prompts from the start, so they express
immediately and the one-off news is marginal on top of an already-high activity
level.
The second reading is the mirror image: high activity is not large movement.
Core activity is saturated from step 2 on, but bias is nearly flat from step
2 to step 4 — because eight core opinions of mixed sign partly cancel, and the
12 ordinary users (60% of the panel, ending at −0.3085) barely move and anchor
the aggregate near their starting level.
Grounding¶
Four sourced facts, three declared assumptions, two implementation references.
| entry | basis | role |
|---|---|---|
| Dobbs v. Jackson overturned Roe on 2022-06-24 (SCOTUSblog) | sourced |
the real exogenous shock trigger_news stands for |
| Pew: ~61% said abortion should be legal in all/most cases (pre-decision) | sourced |
the real prior the uniform initialization deliberately does not use |
| Pew post-decision: 57% disapprove / 41% approve, n = 6,174 | sourced |
the net-negative attitude the demo's bias must not be read as predicting |
the published ROE configuration: 1000 ordinary agents, alpha 0.3, 14 turns (Mou et al., 2024) |
sourced |
the reference scale this showcase is a reduction of |
| 8 core + 12 ordinary over 4 steps instead of 1000 over 14 | assumed |
exercises the full real-LLM path at demo cost; counts are declared adjustable_params |
| uniform [-1, 1] initial opinions rather than a Pew-skewed prior | assumed |
the published study's real ROE user data is not bundled here, so the real-data path cannot run |
| TextBlob polarity as the sentiment function in the att mirror | assumed |
a light stand-in faithful to the sign-times-magnitude mirror shape |
Implementation references: Mou et al. (2024), Unveiling the Truth and Facilitating Change (ACL 2024 Findings) — the paper this study ports; and Deffuant, Neau, Amblard & Weisbuch (2000), Mixing beliefs among interacting agents — the bounded-confidence rule behind the ordinary cohort.
Because the initial opinions are uniform rather than Pew-calibrated, the
absolute level of bias carries no polling claim. What transfers is the
relative mechanism: cohort divergence, convergence in diversity, and the
timing of the shock.
What you can change¶
| param | the question it opens |
|---|---|
n_core / n_ord |
at 8 vs 12 the LLM cohort dominates. Push the ratio toward the published 1000 ordinary users and the silent majority should reassert itself — at what mix does the crossover happen? |
alpha |
how fast the silent majority assimilates; the anchor's stiffness. |
bc_bound |
0.1 is narrow. Sweep to ~0.5 for the classic bounded-confidence transition from fragmentation to consensus — and check whether the LLM cohort shifts the critical point. |
| news schedule | fire the news at step 1 — that rewrites an environment entry at an earlier step, so it is a new version, cold from step 0. Adding a second wave at a later step keeps everything before it identical, so it is a branch off the run above. Either way the question is whether bias shows a genuine second inflection once the topic is not already saturated. |
target |
the same hybrid machinery on a different issue. |
The report's own first recommendation is a parity check: run the same study
with a deterministic scripted decision instead of the LLM, and measure whether
role-play introduces a systematic shift versus the rule stub. That swaps the
behaviour function f, so it is a new version and runs cold from step 0 —
see Iterate: versions and branches.
Structure and mechanics of building this way are in
Build a Study from Scratch (Path B).