Child of Simulator_20260316-5_V8
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
WHAT IS IT?
This simulator models the co‑evolution of opinions, internal representations (memes), prevalence, influence, and network structure in a connected population of agents.
Each agent carries:
- an opinion in ([-1, +1])
- a prevalence value (0–99), representing the depth of its internal representations
- an influence level (0–1)
- meme quantities and meme weights
- a meta‑type (
structural,dynamic, ornone) - a set of social links that evolve over time
- a 3D position:
- X = opinion
- Y = prevalence
- Z = influence
- X = opinion
The model integrates:
- meme‑based opinion formation
- targeted meme injection
- endogenous and structural meta‑influencers
- homophily‑based network rewiring
- group effects
- reward‑based reinforcement
- exogenous events
- CSV import/export of agent states and statistics
- 3D visualization of social links
- full restoration of neighbor lists and 3D coordinates from Values CSV
- programmable meta‑link behavior via
meta-link-prog
3D REPRESENTATION
Agents are mapped to:
- X‑axis: opinion (−1 = left, +1 = right)
- Y‑axis: prevalence (0–99)
- Z‑axis: influence (0–1)
Colors:
- Red: left‑leaning
- Blue: right‑leaning
- White: center
- Yellow: meta‑influencers (structural or dynamic)
Links (visible when show-links? is ON):
- Green: same‑sign connections
- Gray: opposite‑sign connections
- Meta‑links: displayed according to
meta-link-progrules
The 3D view updates continuously as opinions, prevalence, influence, and network structure evolve.
HOW TO USE
- Choose population size with
pop. - Click Setup to initialize agents, networks, memes, and meta‑structure.
- Click Go to run or pause the simulation.
- Use
output,csv-export, andcsv-modeto record results. - Use
in_file_valuesto reload a saved state with full agent information. - Use
choice_iterto select which iteration to restore.
GENERAL CONTROLS
- Setup: initialize agents, networks, memes, meta‑structure
- Go: start/stop simulation
- in_file: load simple-format agent states
- infilevalues: load full agent states (Values CSV) including neighbors and 3D coordinates
- refresh: reset plots
- cumulative: if OFF, resets counters each tick
- output: None | Statistics | Values | File
POPULATION & ITERATIONS
pop: number of agentsnb_try: number of trialsmax_iter: iterations per trialthreshold: majority thresholdchoice_iter: iteration to restore when importing Values CSV
META‑INFLUENCERS (STRUCTURAL & DYNAMIC)
Two types of meta‑influencers exist:
Structural meta‑influencers
- Assigned at setup
- Controlled by
meta-influencers-selection(All / Left / Right) - Percentage set by
meta-influencers - Eligibility via
prev-low/prev-high - Influence = 1
- Persistent across imports
- Create meta‑links
- Protected by metablock (prevents sign switching)
- Restored when importing Values CSV
Dynamic meta‑influencers
- Emerge when influence rises to 1
- Yellow but not counted as structural
- Do not create structural meta‑links
- Fully exported/imported via
meta-type
Meta‑link programming (meta-link-prog)
This chooser determines how meta‑links are created:
- meta → non‑meta
- meta → meta
- mixed or restricted patterns
- structural vs dynamic behavior
This allows fine‑grained control over elite connectivity and structural influence.
SOCIAL NETWORK DYNAMICS
Links evolve through homophily and probabilistic rewiring.
Parameters:
link-removal-thresholdlink-formation-thresholdproblinksdown/linksupbridge-probshow-links?linktick
Structural metas may create meta‑links based on:
meta-min/meta-max/meta-linksmeta-okmeta-link-prog
3D Link Visualization
When show-links? is ON:
- All social links are drawn in the 3D view
- Colors reflect sign similarity
- Meta‑links follow the rules of
meta-link-prog - Links update dynamically as the network rewires
OPINION & PREVALENCE DYNAMICS
Opinion adoption depends on:
prevalence-weightpolarization-factoradoption-floornoise- group effects
- reward system
- meme dynamics
Prevalence adapts through:
mod-prevrate-mod
GROUP EFFECT
group-impact-mode: all or k-nearestgroup-kgroup-impact-weightgroup-impact-alpha
Interpretation of alpha:
- <1: small clusters matter more
- =1: linear
- >1: only large aligned groups matter
REWARD MECHANISM
Successful influencers receive a temporary tx‑bonus.
Parameters:
reward-stepreward-capreward-decayreward-scopereward-prev-delta
MEME‑BASED REPRESENTATION
When use-memes? is ON:
Prevalence
Derived from total meme quantity:
meme-plusmeme-minus
Opinion
Derived from meme weights:
[ \text{opinion} = \frac{meme_plus_w - meme_minus_w}{meme_plus_w + meme_minus_w} ]
Transmission
Receivers gain:
- meme quantity
- meme weight proportional to quantity
Parameters:
meme-weight-meanmeme-weight-sdmeme-weight-min/meme-weight-maxmeme-anti-leakmeme-decay
Meme-Based Representation (Weighted Memes + Targeted Injection)
When use-memes? is ON, opinions and prevalence are computed from internal “meme” stocks.
This version distinguishes meme quantity (how many representations an agent holds) from meme weight (how strongly each representation shapes the opinion).
1) Two levels: Quantity vs Weight
Meme quantity → Prevalence
meme-plus,meme-minusstore how many pro/anti memes the agent holds.- Prevalence (0–99) is derived from the total quantity:
meme-plus + meme-minusrescaled to 0–99.
Interpretation: prevalence approximates how “rich” an agent’s internal representation system is (how many arguments/frames are available).
Meme weight → Opinion
meme-plus-w,meme-minus-wstore the cumulative weighted strength of pro/anti memes.- Opinion is computed from the weighted balance:
[ opinion = \frac{meme\text{-}plus\text{-}w - meme\text{-}minus\text{-}w}{meme\text{-}plus\text{-}w + meme\text{-}minus\text{-}w} ]
- If pro-weights dominate → opinion moves toward +1
- If anti-weights dominate → opinion moves toward −1
- If balanced → opinion stays near 0
A tiny denominator safeguard is used to avoid division by zero.
2) Weighted transmission during interactions
When an agent is influenced, the receiver gets:
- a quantity increment (meme-gain) on the side of the emitter (plus or minus),
- and a weight increment proportional to that quantity.
Weight distribution parameters
meme-weight-mean(typical 0.2–3.0): average strength of newly acquired memes.- Low values → many memes are needed to polarize opinions.
- High values → opinions polarize faster, even with small meme quantities.
- Low values → many memes are needed to polarize opinions.
meme-weight-sd(typical 0.0–1.0): heterogeneity (memes differ in strength).- 0.0 → all memes are equally strong.
- Higher values → mixed populations with “weak” and “strong” memes.
- 0.0 → all memes are equally strong.
meme-weight-min / meme-weight-max: hard bounds preventing unrealistic weights.
3) Meme anti-leak and decay (optional)
meme-anti-leak(0–1): when one side grows, a fraction of the opposite stock is reduced.
High values create “winner-takes-more” dynamics (polarization reinforcement).meme-decay(0–0.05 typical): forgetting rate applied each tick to quantities and weights.
Meme Injection (Targeted diffusion of new representations)
Beyond “events” that shift opinions directly, the simulator can inject memes into a selected subgroup to simulate the introduction and diffusion of a new narrative, argument, or frame.
1) Targeting bounds (preferred controls)
Agents are eligible for injection if they satisfy:
inject-low_meme ≤ opinion ≤ inject-high_memeinject-low-prev ≤ prevalence ≤ inject-high-prev
This allows injection into: - moderates only (e.g., −0.2 to +0.2), - one camp only (e.g., +0.2 to +1), - low-prevalence agents only (e.g., 0 to 30).
2) Injection strength and reach
inject-prob-max(0–1): maximum share of eligible agents that actually receive the injected memes.inject-sign:"plus"or"minus"(which direction the injected memes support).inject-amount(typical 1–10): how many memes are injected (quantity → raises prevalence).inject-weight(typical 0.2–5.0): how strong injected memes are (weight → shifts opinion more sharply).
Rule of thumb:
- Increase inject-amount to raise prevalence (more representations).
- Increase inject-weight to raise polarization intensity (stronger conviction shift).
3) Scheduling injection
auto_inject?: if ON, injection occurs whenticks = inject-tick.inject-tick: the tick at which injection happens.repeat-inject?: if ON, injection repeats everyinject-paceticks.inject-pace: the interval between repeated injections.
Example scenarios
One-shot targeted campaign:
auto_inject? = ON,repeat-inject? = OFF,inject-tick = 50,inject-prob-max = 0.2,
inject-low_meme = -0.2,inject-high_meme = 0.2,inject-sign = "plus",
inject-amount = 3,inject-weight = 2.0.Slow diffusion of a weak but persistent narrative:
repeat-inject? = ON,inject-pace = 25,inject-prob-max = 0.05,
inject-amount = 1,inject-weight = 0.5.High-impact shock on a small subgroup:
inject-prob-max = 0.02,inject-amount = 2,inject-weight = 5.0,
targeting a narrow opinion band.
MEME INJECTION
Eligibility:
inject-low_meme≤ opinion ≤inject-high_memeinject-low-prev≤ prevalence ≤inject-high-prev
Parameters:
inject-prob-maxinject-signinject-amountinject-weightauto_inject?,inject-tickrepeat-inject?,inject-pace
EXOGENOUS EVENTS
Events shift:
- opinion (
event_size) - prevalence (
prev_change)
Targeting:
meme_set+to_left- or bounds:
low_meme/high_meme,low-prev/high-prev
Scheduling:
auto_eventevent-initrepeat-eventevent-paceevent-prob-maxevent-meme-change?
EXOGENOUS EVENTS (bounded & probabilistic)
Targeting
meme_set+to_left: if ON, structural targeting by camp (Left side / Right side).- Otherwise, use bounds:
low_meme/high_meme(opinion window) andlow-prev/high-prev(prevalence window).
Effects on targeted agents
event_size: opinion shift (toward the intended camp).prev_change: prevalence change (clamped to [0,99]).event-prob-max(0–1): maximum share of targeted agents that actually receive the shock (each agent drawsU(0,1)).
Triggering
eventbutton: one-shot shock (manual).auto_event+tick-event: scheduled automatic shock at iterationtick-event.
Repeated events (per your code)
event-init: initial offset of the first event (onsetupand at each new trial,tick-event ← event-init).repeat-event(switch): if ON, re-schedules the next event after each occurrence.event-pace(≥ 1 tick recommended): spacing between repeated events.Scheduling logic:
- If
auto_event= ON anditer = tick-event→ runevent. - If
repeat-event= ON →tick-event ← tick-event + event-pace. - Else (OFF) → no automatic re-scheduling (you may adjust
tick-eventmanually). - If
auto_event= OFF → each tick,tick-event ← iter + event-pace(the next time you switch ON, the event fires ≈event-paceticks later).
- If
Quick examples
- Single calibration shock:
auto_event=ON,repeat-event=OFF,event-init=2,event-prob-max=1.0. - Periodic pulses:
auto_event=ON,repeat-event=ON,event-init=50,event-pace=50,event-prob-max=0.30. - Diffuse perturbations:
repeat-event=ON,event-pace=100,event-prob-max=0.05.
Parameter Ranges — Key Sliders (Overview)
The table below summarizes the recommended value ranges for the nine main sliders governing opinion transmission, meme dynamics, and external shocks.
Ranges are indicative and meant to support exploratory, comparative, and pedagogical simulations rather than strict calibration.
| Slider name | Typical range | What it controls | Low values → expected effects | High values → expected effects | |------------|---------------|------------------|-------------------------------|--------------------------------| | prevalence-weight | 0.0 – 2.0 | Weight of prevalence differences in adoption probability | Opinion change weakly tied to representational depth; more random diffusion | Deeply rooted agents dominate transmission; strong inertia | | adoption-floor | 0.0 – 0.10 | Minimum probability of adoption regardless of distance | Near-impossible cross-camp adoption | Persistent low-level noise and occasional inversions | | polarization-factor | 0.0 – 1.0 | Penalty applied to large opinion gaps | Distance barely matters; smooth convergence | Strong ideological barriers; entrenched camps | | group-impact-weight | 0.0 – 1.0 | Strength of group alignment effect | Individual interactions dominate | Local majorities strongly condition adoption | | group-impact-alpha | 0.2 – 3.0 | Non-linearity of group effect | Small minorities exert strong influence | Only large aligned groups matter | | meme-max | 50 – 200 | Maximum stock of memes per agent (prevalence scale) | Shallow belief systems; fast saturation | Deep ideological accumulation; slow dynamics | | meme-gain | 0.5 – 2.0 | Meme increment per successful transmission | Slow learning; weak reinforcement | Rapid ideological buildup | | meme-anti-leak | 0.0 – 0.5 | Cross-erosion of opposite meme stock | Memes accumulate independently | Strong competition; winner-takes-more dynamics | | meme-decay | 0.0 – 0.05 | Forgetting rate of memes per tick | Stable long-term memory | Rapid erosion; volatile belief systems | | event-prob-max | 0.0 – 1.0 | Proportion of agents affected by an event | Micro-perturbations, local shocks | System-wide shocks |
Usage notes
- Low–mid ranges are recommended for exploratory runs and sensitivity analysis.
- Extreme values are useful to study boundary cases (lock-in, collapse, polarization).
- Parameters interact strongly: e.g., high
meme-gaincombined with highmeme-anti-leakaccelerates polarization.
This table is intended as a cheat sheet; empirical calibration should rely on systematic parameter sweeps.
Meme Injection — Slider Ranges, Effects, and Interactions
This table documents the nine sliders governing meme injection.
Together, they define when, how often, to whom, and with what strength new memes are introduced into the population, allowing controlled simulations of campaigns, rumors, or polarizing shocks.
Core Injection Parameters
| Slider | Typical range | Role in the model | Low values → effects | High values → effects | |------|---------------|-------------------|----------------------|----------------------| | inject-tick | 1 – max_iter | First tick at which meme injection can occur | Early priming of agents; long-run structural impact | Late shock; short-term perturbation with limited propagation | | inject-pace | 1 – 200 | Interval (ticks) between injections | Continuous or quasi-continuous pressure | Rare, punctuated shocks | | inject-prob-max | 0.0 – 1.0 | Maximum probability that an eligible agent receives a meme at an injection tick | Injection remains marginal or localized | Broad exposure; near-systemic dissemination | | inject-amount | 0 – meme-max | Quantity of meme stock added per injection | Subtle informational nudges | Strong narrative saturation or propaganda burst | | inject-weight | 0.0 – 2.0 (or higher) | Relative impact of injected memes on opinion vs. prevalence | Injected memes mainly increase prevalence (attention/salience) | Injected memes strongly bias opinion formation |
Targeting and Selectivity Parameters
| Slider | Typical range | Role in the model | Low values → effects | High values → effects | |------|---------------|-------------------|----------------------|----------------------| | inject-low_meme | −1.0 – 1.0 | Lower bound of opinion eligible for injection | Broad targeting across ideological spectrum | Injection limited to one side or a narrow ideological niche | | inject-high_meme | −1.0 – 1.0 | Upper bound of opinion eligible for injection | Narrow ideological window | Broad or opposing-side reach (depending on bounds) | | inject-low-prev | 0 – 99 | Minimum prevalence required to receive injected memes | Inclusion of low-salience or weakly engaged agents | Targeting already attentive or mobilized agents | | inject-high-prev | 0 – 99 | Maximum prevalence eligible for injection | Focus on low-to-mid engagement agents | Restriction to highly engaged elites |
Interaction Effects (Key Dynamics)
inject-tick × inject-pace
- Early + short pace → persistent campaign dynamics.
- Late + long pace → isolated shock events.
- Early + short pace → persistent campaign dynamics.
inject-prob-max × inject-amount
- Low prob + high amount → elite seeding (few agents, strong impact).
- High prob + low amount → mass diffusion (many agents, weak signal).
- Low prob + high amount → elite seeding (few agents, strong impact).
inject-weight × inject-amount
- High weight + high amount → rapid opinion polarization.
- Low weight + high amount → agenda-setting without strong persuasion.
- High weight + high amount → rapid opinion polarization.
inject-lowmeme / inject-highmeme × inject-low-prev / inject-high-prev
- Narrow opinion + high prevalence → echo-chamber reinforcement.
- Broad opinion + low prevalence → grassroots diffusion potential.
- Narrow opinion + high prevalence → echo-chamber reinforcement.
Conceptual Interpretation
- Low values generally model background noise, rumors, or weak informational exposure.
- High values approximate organized campaigns, disinformation bursts, or polarizing media events.
- Intermediate combinations allow exploration of threshold effects, diffusion delays, and nonlinear amplification.
These sliders are designed to be orthogonal but non-independent: meaningful experiments emerge from their joint configuration, not isolated tuning.
Preset — Campaign / Rumor / Polarizing shock (recommended default profile)
This preset is a ready-to-run parameter profile designed to reproduce a common empirical pattern in opinion dynamics:
1) a stable baseline (moderate homophily, limited cross-camp contact),
2) a rumor/campaign phase (repeated external shocks reaching only part of the population),
3) a polarizing outcome (network segmentation, fewer inversions, stronger within-camp reinforcement).
It is intended as a starting point for university-level experimentation (reproducible and interpretable), not as a calibrated model for a specific case.
A. Core idea
- Use repeat-event + event-pace to create a campaign/rumeur that reappears periodically.
- Use event-prob-max < 1 so the shock reaches only a subset of eligible agents, generating diffusion rather than an immediate global collapse.
- Keep bridge-prob low but non-zero so rare cross-camp bridges exist (possible inversions), while still allowing polarization to emerge.
- Activate group impact and a mild reward system to reproduce realistic “social proof” and reinforcement mechanisms.
B. Default values (Preset)
(Values assume your current sliders/switches; ranges remain adjustable by the operator.)
1) Events: “campaign / rumor” mechanics
- auto_event: ON
- repeat-event: ON
- event-init:
50(first shock after an initial stabilization period) - event-pace:
25(shock repeats every 25 iterations) - event-prob-max:
0.10(≈10% of eligible agents receive the shock each cycle)
Bounds & targeting
- meme_set: OFF (use bounds rather than structural Left/Right set)
- lowmeme / highmeme: -0.30 / +0.30 (targets the “convertible middle”)
- low-prev / high-prev: 10 / 60 (targets moderate-prevalence agents—reachable but not rigid)
Shock magnitude
- event_size: 0.25 (clear movement without saturating ±1 too fast)
- prev_change: +8 (moderate strengthening of prevalence in targeted agents; set 0 if you want “pure opinion shock”)
Interpretation - This reproduces a campaign/rumeur that repeatedly perturbs the middle rather than only extremes, and spreads indirectly through the network.
2) Network: controlled homophily + rare bridges
- network: ON
- link-formation-threshold:
0.20 - link-removal-threshold:
0.40 - prob:
0.30 - linksup / linksdown:
10 / 10(balanced churn) - bridge-prob:
0.05(rare but non-zero cross-camp bridges) - show-links?: optional (OFF for performance; ON for demonstrations)
Expected effect - The network remains mostly homophilous, but with occasional “bridges” allowing limited cross-camp exposure.
3) Opinion adoption: prevalence-driven, polarization-aware
- prevalence-weight:
1.40 - polarization-factor:
0.60 - adoption-floor:
0.03 - noise:
0.01(small background drift)
Expected effect - Adoption is mostly driven by prevalence differences, while strong polarization reduces cross-camp adoption without making it impossible.
4) Group impact: social proof (moderate strength)
- group-impact-mode:
k-nearest - group-k:
8 - group-impact-weight:
0.60 - group-impact-alpha:
1.20
Expected effect - Local neighbourhood alignment matters; majorities have slightly more weight than minorities (alpha > 1).
5) Reward: modest reinforcement (avoid runaway)
- reward-step:
0.03 - reward-cap:
0.30 - reward-decay:
0.005 - reward-scope:
both - reward-prev-delta:
0(keep prevalence effects attributable to memes/events; set 1–3 if you want “success breeds conviction”)
Expected effect - Successful influencers become moderately more effective over time, but decay prevents permanent dominance.
6) Memes: ON (recommended for this preset)
- use-memes?: ON
- meme-max:
120 - meme-gain:
1.0 - meme-anti-leak:
0.20 - meme-decay:
0.01
Expected effect - Agents gradually accumulate representations; anti-leak creates a mild competitive relation between pro/anti stocks, supporting polarization over repeated shocks.
7) Meta-influencers: optional, controlled
- meta-ok: ON (optional; ON reproduces real-world asymmetric reach)
- meta-link-prob: 0 (meta - non-meta) to 1 (meta - meta)
- meta-influencers-selection:
All - meta-influencers:
5% - prev-low / prev-high:
20 / 80 - meta-min / meta-max:
8 / 20 - metablock: ON (prevents sign switching for metas)
- vary-influence: OFF (recommended OFF to avoid meta inflation; turn ON only if studying endogenous influencer emergence)
Expected effect - A small set of highly connected agents accelerates diffusion while the metablock prevents metas from oscillating across camps.
C. What you should observe (typical outcomes)
- Early phase (before event-init): moderate clustering, limited movement.
- During repeated events: a growing asymmetry in meme stocks and prevalence among the targeted “middle”.
- Over time: stronger within-camp reinforcement, more gray links disappearing, fewer inversions.
- If you increase event-prob-max toward 0.30–0.50: faster and more global shifts.
- If you increase bridge-prob toward 0.10–0.20: more cross-camp exposure and more inversions (polarization weakens).
D. Minimal variant (if you want “shock-only”, no campaign)
- Set repeat-event = OFF and keep a single event-init (or press event once).
- Keep all other values unchanged to compare one-shot shock vs campaign repetition.
Meme Dynamics — Integrated Monitoring Indicators
This simulator includes eight dedicated monitors designed to track how memes (internal representations) shape opinion formation, prevalence, and polarization over time.
Each monitor is updated at every tick and provides a complementary analytical perspective on the meme–opinion coupling.
1. Mean Meme Stock
What it measures
The average total number of memes held by agents:
Mean Meme Stock = mean(meme-plus + meme-minus)
Why it matters
This indicator captures the global cognitive density of the population.
- Low values indicate weakly structured opinions (few internal representations).
- High values reflect ideologically “loaded” agents with many arguments.
Interpretation
- Rising values → accumulation of representations (learning, persuasion, repeated events).
- Falling values → forgetting or erosion (via meme-decay).
Implementation (monitor expression)
2. Meme Polarity Index
What it measures
The net ideological balance of all memes in the system.
It compares the total stock of positive memes to negative memes.
Interpretation
- Values close to +1 → dominance of pro (+) memes.
- Values close to -1 → dominance of contra (−) memes.
- Values near 0 → balanced or plural meme ecology.
Implementation (monitor expression)
3. Opinion–Meme Gap
What it measures
The average absolute difference between:
- the agent’s expressed opinion, and
- the opinion implied by its internal meme balance.
Why it matters
This indicator captures latent cognitive inconsistency:
agents may express an opinion that is not fully supported by their internal representations.
Interpretation
- Low gap → opinions are well grounded in memes.
- High gap → cognitive tension, instability, or transitional states.
Implementation (monitor expression)
Ideologization Indices (NEW – Dual Measure)
The simulator now exports two distinct ideologization indicators in the CSV Statistics output.
They capture complementary dimensions of ideological structuring and should not be interpreted as redundant.
4a. Ideologization Index (meme-based)
CSV column:
ideologization_index
What it measures
The average representational imbalance within agents, based on their internal meme stocks.
This indicator captures how strongly agents are cognitively oriented toward one side through the asymmetry of supporting arguments, independently of their expressed opinion.
Formal definition
For each agent i:
- Meme imbalance = | meme-plus − meme-minus |
The index is the population mean:
Interpretation
- Low values → weakly structured or ambivalent meme ecology
- High values → strong internal representational bias (ideological load)
This measure reflects ideological depth at the cognitive level, even if opinions remain moderate.
Use in the article
- Methods: introduced as a representational ideologization metric
- Results: used to compare cognitive polarization across experimental conditions (Exp1–Exp5)
- Helps explain cases where opinions remain stable despite intense internal meme accumulation
4b. Ideologization Index (opinion-based)
CSV column:
ideologization_opinion_based
What it measures
The degree to which expressed opinion extremity is supported by prevalence (i.e., conviction strength).
This index captures ideological entrenchment at the behavioral level, combining stance and commitment.
Formal definition
For each agent i:
The index is the population mean:
Interpretation
- Low values → weakly anchored opinions or pragmatic attitudes
- High values → extreme opinions supported by high conviction
This measure reflects expressed ideological rigidity, not internal argument diversity.
Use in the article
- Methods: introduced as an expressed ideologization indicator
- Results: contrasted with the meme-based index to distinguish:
- cognitive saturation without opinion radicalization
- versus explicit ideological alignment
How to read both indices together
The two measures should be interpreted jointly:
High meme-based / low opinion-based
→ cognitively loaded but behaviorally moderate agents (latent ideology)Low meme-based / high opinion-based
→ strong stance with limited internal justification (fragile extremism)High on both
→ fully ideologized population (entrenched opinions with deep representational support)
This distinction is central to the article’s argument on multi-layered ideologization dynamics in agent-based models.
5. Right Meme Polarization
What it measures
The internal ideological polarization of meme stocks among agents holding a positive opinion (opinion >= 0).
It compares reinforcing memes (meme-plus) to counter-memes (meme-minus) within the right-leaning subgroup only, independently of the left side.
Interpretation
- Values close to +1 → strong dominance of reinforcing (pro-right) memes.
- Values near 0 → balanced or internally plural meme structure.
- Values below 0 → erosion or counter-meme dominance inside the right camp.
This indicator reveals whether right-side opinions are: - deeply ideologized, - stable but weakly supported, - or vulnerable to counter-narratives.
Implementation (plot and monitor expression)
6. Left Meme Polarization
What it measures
The internal ideological polarization of meme stocks among agents holding a negative opinion (opinion < 0).
It measures the balance between reinforcing and counter-memes inside the left-leaning subgroup, independently from right-side dynamics.
Interpretation
- Values close to -1 → strong dominance of reinforcing (pro-left) memes.
- Values near 0 → plural or contested internal meme structure.
- Values above 0 → counter-meme pressure within the left camp.
This indicator is essential to detect: - asymmetric polarization, - minority radicalization, - or differential resistance to meme diffusion.
Implementation (plot and monitor expression)
7. Mean Meme-derived Opinion
What it measures
The average opinion value reconstructed from meme stocks, independently of the agents’ current explicit opinions.
This measure computes, for each agent, the opinion implied by the balance of its internal memes
(meme-plus vs meme-minus), then averages this value across the whole population.
Interpretation
- Values close to +1 → the meme ecology strongly supports the positive (right/pro) polarity.
- Values close to -1 → dominance of negative (left/contra) meme representations.
- Values near 0 → balanced or internally conflicting meme structures.
Comparing this indicator with the mean explicit opinion reveals latent ideological tensions:
- If meme-derived opinion is stronger than explicit opinion → opinions may soon shift.
- If explicit opinion is stronger than meme-derived opinion → opinions are weakly grounded and fragile.
Why it matters
This indicator captures the deep cognitive orientation of the population, beyond surface-level expressed opinions.
It helps distinguish:
- superficial opinion alignment,
- structurally grounded ideological states,
- and phases where internal representations lag behind observable behavior.
Implementation (monitor expression)
8. Meme Saturation (%)
What it measures
The overall saturation level of meme stocks in the population, expressed as a percentage of the maximum possible meme capacity.
It compares the total number of memes currently held by all agents to the theoretical maximum (meme-max × population).
Interpretation
- Values close to 0% → agents hold very few internal representations; opinions are shallow and weakly grounded.
- Intermediate values (30–60%) → active circulation of arguments with moderate cognitive load.
- Values close to 100% → saturated cognitive environment; agents are highly entrenched and resistant to change.
This indicator captures the cognitive density of the system and helps distinguish: - early diffusion phases, - mature ideological ecosystems, - and saturation-driven stabilization or lock-in effects.
Implementation (monitor expression)
(These indicators are computed only when use-memes? is ON.)
CSV EXPORT
Statistics mode
Exports per tick:
- mean/median opinion
- median prevalence
- median influence
- left/right shares
- link creation/removal
- inversion rate
- interaction counters
- fractal indicators
- ideologization indices
- meme polarity
- meme saturation
Values mode
Exports per agent:
- try
- tick
- who
- prevalence
- opinion
- influence
- meme-plus
- meme-minus
- meme-plus-w
- meme-minus-w
- meta-type
- neighbors
- pos-x, pos-y, pos-z
CSV IMPORT (VALUES MODE)
Pipeline:
- Read CSV
- Store rows
- Select tick =
choice_iter load-and-store-initial-staterestore-initial-state
Restores:
- opinions
- prevalence
- influence
- meme stocks
- meme weights
- meta-type
- neighbor lists
- 3D coordinates
- colors
- meta-links
Ensures perfect reproducibility of any saved state.
IMPORTING AGENT STATES
The simulator supports two distinct formats for importing agent states.
in_file (Simple format)
The in_file button loads a file containing a single snapshot of agents, typically corresponding to iteration 0.
Each line in the file must contain exactly:
- tick
- prevalence
- opinion
- influence
This format is intended for:
- handcrafted initial populations
- home made created datasets
- controlled experimental starting points
When loaded:
- agents are created once
- meme stocks are initialized from opinion and prevalence
- the social network is built by the system
infilevalues (CSV Values re-import)
The infilevalues button loads agents from a CSV file previously exported in Values mode or produce by a Generator
Usage:
- select the iteration to load using choice_iter
- click infilevalues
Behavior:
- agents are reconstructed exactly as they were at the selected iteration
- opinion, prevalence, influence, meme stocks, and meme weights are restored
- agents with influence = 1 are automatically recolored as meta-agents
This enables:
- replaying simulations from an intermediate state
- branching alternative scenarios
- counterfactual experiments
- reproducible analysis from archived runs
- running new kind of regime
MONITORING INDICATORS
- Mean Meme Stock
- Meme Polarity Index
- Opinion–Meme Gap
- Ideologization Index (meme-based)
- Ideologization Index (opinion-based)
- Right Meme Polarization
- Left Meme Polarization
- Mean Meme-derived Opinion
- Meme Saturation (%)
PRESET: CAMPAIGN / RUMOR / POLARIZING SHOCK
A ready-to-run configuration illustrating:
- baseline stabilization
- repeated targeted shocks
- meme accumulation
- polarization
- network segmentation
CONCEPTUAL INTERPRETATION
The model integrates:
- cognitive depth
- representational structure
- behavioral stance
- social reinforcement
- structural elites
- emergent influencers
- network homophily
- exogenous shocks
- targeted diffusion
Allows exploration of:
- polarization
- ideological saturation
- diffusion delays
- nonlinear amplification
- elite influence
- cognitive vs behavioral ideologization
- structural segmentation
- metastable attractors
USING THE SIMULATOR WITH AN EXTERNAL NETWORK GENERATOR
This simulator can be combined with an external Network Generator to explore how different network topologies shape opinion dynamics, meme propagation, and structural polarization. The Generator produces agent-level data and network structures in CSV format, which can be imported directly into the simulator through the Values CSV pipeline.
This section provides examples of workflows using the Generator and the simulator together.
1. Generating a Network Externally
An external Generator can create networks such as:
- homophilic networks
- heterophilic networks
- multi-cluster networks
- random networks
- small-world or scale-free networks
- custom networks with controlled degree distributions
The Generator typically outputs a CSV file containing, for each agent:
- opinion
- prevalence
- influence
- meme quantities
- meme weights
- meta-type
- neighbor list
- 3D coordinates (opinion, prevalence, influence)
This CSV can be loaded directly using infilevalues.
2. Importing a Generated Network into the Simulator
To load a network produced by the Generator:
- Place the CSV file in the NetLogo working directory.
- Select the file using infilevalues.
- Set choice_iter to the desired iteration (usually 1 for Generator outputs).
- Click Setup to initialize the import pipeline.
- Click Go to continue the simulation from the imported state.
The simulator will restore:
- all agent variables
- all meme stocks and weights
- meta-type assignments
- neighbor lists
- 3D positions
- meta-links (if present)
This ensures perfect reproducibility of the generated network inside the simulator.
3. Using Generator Statistics to Guide Experiments
The Generator can also produce statistical CSV files describing:
- degree distributions
- opinion distributions
- influence distributions
- prevalence distributions
- cluster sizes
- homophily or heterophily indices
- centrality measures
- structural signatures
These statistics can be used to:
- select networks with specific structural properties
- compare multiple network types
- identify networks with strong or weak polarization potential
- study the effect of hubs, bridges, or isolated clusters
- design controlled experiments with matched or contrasted topologies
4. Example Workflow: Homophilic vs Heterophilic Networks
Use the Generator to create two networks:
- a homophilic network with strong clustering
- a heterophilic network with distant clusters and few hubs
- a homophilic network with strong clustering
Export both as Values CSV.
Import each network separately using infilevalues.
Run identical simulation parameters on both networks.
Compare outcomes such as:
- convergence speed
- polarization level
- meme saturation
- influence concentration
- structural segmentation
- meta-influencer impact
- convergence speed
This workflow highlights how network topology shapes collective dynamics.
5. Example Workflow: Reconstructing a Simulation State
The Values CSV export allows the simulator to reconstruct any past state.
- Run a simulation and export Values CSV at a chosen tick.
- Modify the CSV externally (for example, by altering the network using the Generator).
- Re-import the modified CSV using infilevalues.
- Continue the simulation from the modified state.
This enables hybrid workflows combining:
- endogenous evolution inside the simulator
- exogenous structural transformations from the Generator
6. Example Workflow: Batch Analysis of Network Families
The Generator can produce a family of networks by varying parameters such as:
- homophily strength
- degree distribution
- cluster separation
- bridge probability
- meta-link density
For each generated network:
- Import the Values CSV.
- Run nb_try trials.
- Export Statistics CSV.
- Compare outcomes across the family of networks.
This approach supports systematic exploration of how structural features influence:
- opinion convergence
- meme propagation
- influence hierarchies
- metastable attractors
- resilience to shocks
7. Example Workflow: Using Generator Outputs for Visualization
The 3D coordinates provided by the Generator allow the simulator to display:
- initial ideological landscapes
- cluster separation
- influence gradients
- structural segmentation
- meta-influencer placement
By importing these coordinates, the simulator can visualize complex network structures before any dynamics occur.
8. Summary
Using the simulator together with an external Network Generator enables:
- controlled initialization of complex network structures
- reproducible experiments across multiple topologies
- hybrid workflows combining structural and cognitive dynamics
- systematic comparison of network families
- reconstruction and modification of simulation states
- integration of external statistical analysis
This combined approach supports advanced research on opinion dynamics, meme diffusion, polarization, and structural influence.
📊 Fractal and Constellation Measures - Complete Guide
📐 FRACTAL MEASURES (System Complexity)
topological_dim – Topological Dimension
What it is: Measures the structural complexity of the social network. Calculated by box-counting on the connection graph.
Interpretation: - > 2.0: Highly hierarchical network, nested clusters (rich structure) - 1.5 – 2.0: Typical "small-world" network - < 1.5: Linear or random network, poorly structured
What it reveals: The underlying social architecture – how agents are potentially connected.
dynamic_dim – Dynamic Dimension
What it is: Measures the complexity of influence cascades over time. Analyzed via the distribution of cascade sizes.
Interpretation: - 1.5 – 2.0: Cascades of all sizes, dynamically rich system (critical regime) - 1.0 – 1.5: Dominance of medium-sized cascades - < 1.0: Uniform cascades (either all small or all large)
What it reveals: How influence actually propagates – system memory and scaling laws.
criticality_gap – Criticality Gap
What it is: |dynamic_dim - topological_dim| / topological_dim
Interpretation: - < 0.2: ⭐ Self-organized criticality – Dynamics perfectly "match" the structure. Optimal propagation, small perturbations can cascade across all scales. - 0.2 – 0.5: Intermediate regime, exploration - > 0.5: Decoupling – either structure is underutilized or dynamics "overflow" (possible artifact)
What it reveals: The harmony between what is structurally possible and what actually happens.
Status – Joint Interpretation
Text message summarizing system state, for example:
- 🌟🌟 PERFECT CRITICALITY – Everything aligned
- ⚡ CRITICALITY – Structure and dynamics aligned
- 🌀 EXPLORATION – Intermediate regime
- ⚠️ DECOUPLING – Desynchronization
🌌 CONSTELLATIONS (Population Segmentation)
Constellation Definitions
The population is divided into 5 constellations based on opinion and prevalence:
- C1 (Left radicals): Very negative opinion (< -0.6) AND high prevalence (≥ 50)
- C2 (Left moderates): Moderately negative opinion (-0.6 to -0.2)
- C3 (Floating center): Opinion near zero (-0.2 to 0.2)
- C4 (Right moderates): Moderately positive opinion (0.2 to 0.6)
- C5 (Right radicals): Very positive opinion (> 0.6) AND high prevalence (≥ 50)
c1_size to c5_size – Constellation Sizes
Number of agents in each group.
What it reveals: Population distribution according to ideological positioning and intensity (prevalence).
c1_opinion_avg to c5_opinion_avg – Average Opinion per Constellation
Mean opinion of agents in each group.
Interpretation: - More extreme values indicate more radicalized groups - Evolution over time shows polarization or moderation
c1_prev_avg to c5_prev_avg – Average Prevalence per Constellation
Mean prevalence (engagement, intensity) in each group.
Interpretation: - Radicals (C1, C5) should have high prevalence - Center (C3) should have the lowest prevalence - Increasing prevalence in the center may signal "activation" of moderates
c1_polarization to c5_polarization – Internal Polarization
Standard deviation of opinions within each constellation.
Interpretation: - Low: Homogeneous group, internal consensus - High: Heterogeneous group, internal tensions - A highly polarized group may be about to split
🔄 TURNOVER (Membership Fluidity)
turnover_global – Global Turnover
Percentage of the population that changes constellation between two ticks.
Interpretation: - High (> 10%): Very fluid system, unstable opinions, high mobility - Medium (2-10%): Dynamic system with moderate renewal - Low (< 2%): Frozen system, stable segregation
turnover_c1 to turnover_c5 – Turnover per Constellation
Percentage of agents who left each constellation.
Interpretation: - Indicates the loyalty of each group - C3 (center) should have the highest turnover (transit zone) - C1/C5 (radicals) should have the lowest turnover (retention zones)
📈 GLOBAL METRICS
opinion_entropy – Opinion Entropy
Measures the diversity/dispersion of opinions in the population.
Interpretation: - Maximum (~4.32 for 20 bins): Opinions uniformly distributed - Minimum (0): Everyone has the same opinion - Increasing: Diversification, polarization? - Decreasing: Emerging consensus
center_volatility – Center Volatility
Measures the instability of the center's (C3) average opinion with exponential smoothing.
Interpretation: - High: Center "floats" a lot, moderate instability - Low: Stable center, system anchor point - May predict tipping points: high center volatility often precedes regime changes
📊 SYNTHESIS – WHAT THESE MEASURES REVEAL TOGETHER
| Measure Group | Reveals | Example Interpretation | |---------------|---------|------------------------| | Fractals | System global state | Criticality = system "at the edge of chaos", optimal for propagation | | Sizes | Ideological distribution | C3 > C1+C5? Centrist system. C1+C5 > C3? Polarization | | Average opinions | Group positioning | C1 moving toward 0? Deradicalization trend | | Prevalences | Engagement intensity | C1 and C5 with low prevalence? Weak radicals | | Polarizations | Internal cohesion | Highly polarized C3? Center splitting | | Turnovers | Fluidity | High C3 turnover? Center is a "crossroads" | | Entropy | Global diversity | Decreasing entropy? Emerging consensus | | Volatility | Center stability | High volatility before crisis? |
🔍 What the Fractal Variable Reveals in Conjunction with Other Variables
The fractal variable (classically calculated as ln(total)/ln(change) or according to the meme-adapted formula) is the original complexity measure of your model. Its conjunction with the new metrics reveals deep dimensions of the system.
📊 JOINT INTERPRETATION MATRIX
1. Fractal + Fractal Dimensions → Nature of Complexity
| Combination | Interpretation | Icon |
|-------------|----------------|------|
| fractal ≈ topological_dim ≈ dynamic_dim | Unified complexity – The process, structure, and dynamics share the same fractal signature. Perfect harmony. | 🎯 |
| fractal > topological_dim | Process more complex than structure – Interactions create complexity that exceeds what the network can explain. | 📈 |
| fractal < topological_dim | Underutilized structure – The network could support more complexity than what actually occurs. | 📉 |
2. Fractal + Criticality_gap → Position on the Criticality-Complexity Axis
| fractal | criticality_gap | Interpretation |
|-----------|-------------------|----------------|
| High (> 1.8) | Low (< 0.2) | Complex criticality – Very rich AND perfectly organized system. Ideal for emergence. |
| High (> 1.8) | High (> 0.5) | Disorganized complexity – Rich but decoupled, potentially chaotic. |
| Low (< 1.2) | Low (< 0.2) | Ordered simplicity – Simple but well-organized system. Stable, predictable. |
| Low (< 1.2) | High (> 0.5) | Dysfunctional simplicity – Simple AND disorganized. Inefficient. |
3. Fractal + Global Turnover → Stability vs. Renewal
- High fractal + High turnover: Complexity maintained by constant renewal. "Living", creative but unstable system.
- High fractal + Low turnover: Complexity maintained by deep interactions between stable actors. "Mature", structured system.
- Low fractal + High turnover: Simple but very fluid system. Possible transition or exploration phase.
- Low fractal + Low turnover: Frozen, sclerotic system. Risk of extinction.
4. Fractal + Opinion Entropy → Diversity vs. Complexity
| Case | Interpretation |
|------|----------------|
| fractal ↑ & entropy ↑ | Interaction complexity generates opinion diversity. This is an exploratory system, rich in possibilities. |
| fractal ↑ & entropy ↓ | Increasing complexity but converging opinions. Possible emerging consensus in a rich system. |
| fractal ↓ & entropy ↑ | Simple system but diverse opinions. May indicate a disintegration phase or individualism. |
| fractal ↓ & entropy ↓ | Simplification and convergence. Crystallization or "social freezing". |
5. Fractal + Center Volatility → Pivot Stability
- High fractal + High volatility: Complex system with an unstable center. Tipping risk – a small perturbation could flip the entire system.
- High fractal + Low volatility: Complexity with a stable center. Resilience – the system can absorb shocks without losing balance.
- Low fractal + High volatility: Simple system but unstable center. Immature – may evolve rapidly toward more complexity or collapse.
- Low fractal + Low volatility: Simple and stable system. Static equilibrium – predictable but without innovation potential.
6. Fractal + Constellation Sizes → Ideological Architecture
| Observation | Interpretation |
|-------------|----------------|
| fractal ↑ & c3_size ↑ | Complexity emerges from a large and active center. Moderates drive the dynamics. |
| fractal ↑ & c1_size + c5_size ↑ | Complexity driven by radicals. Polarization as a source of interactional richness. |
| fractal ↓ & c3_size ↑ | Simplicity associated with a dominant center. Soft consensus, low tension. |
| fractal ↓ & c1_size + c5_size ↑ | Simplicity but polarization. Frozen conflict – separated radicals without complex interactions. |
7. Fractal + Internal Polarization → Group Cohesion
- High fractal + Low internal polarization: Homogeneous groups interacting complexly. Coherent mosaic.
- High fractal + High internal polarization: Heterogeneous groups creating complexity through internal tensions. Explosive cocktail.
- Low fractal + Low internal polarization: Homogeneous isolated groups. Stable segregation.
- Low fractal + High internal polarization: Divided groups but few interactions. Latent tensions.
🎯 SYSTEM TYPOLOGY (COMPLETE DIAGNOSIS)
By cross-referencing fractal with other variables, you can diagnose your system's regime:
| Type | Fractal | Criticality | Turnover | Entropy | Volatility | Interpretation | |------|---------|-------------|----------|---------|------------|----------------| | 🌟 EMERGENT CRITICAL | High | Low gap | Moderate | High | Moderate | System at the edge of chaos, rich and diverse, ideal for social innovation | | 🏛️ MATURE STRUCTURED | High | Low gap | Low | Moderate | Low | Crystallized complexity, well-organized but inflexible society | | 🌪️ TURBULENT | High | High gap | High | High | High | Rich but disorganized, risk of collapse or transition | | 🧊 GLACIAL | Low | Low gap | Low | Low | Low | Frozen system, total consensus, absence of dynamics | | 🔥 PRE-ERUPTIVE | Moderate | Moderate gap | High | Moderate | High | Highly volatile center, warning signs of tipping | | 💥 EXPLOSIVE | Variable | Variable | Very high | Variable | Very high | Crisis underway, everything changing rapidly |
📈 CONCRETE ANALYSIS EXAMPLE
Imagine a simulation with:
fractal = 1.85 topologicaldim = 1.72 dynamicdim = 1.78 criticalitygap = 0.035 turnoverglobal = 12.5 opinionentropy = 3.95 centervolatility = 0.42 c3size = 280, c1size = 110, c5size = 110 c3volatility = 0.58
Diagnosis:
- fractal high (1.85) and very low gap → Perfect criticality
- High turnover (12.5%) → Great fluidity
- High entropy (3.95/4.32) → Maximum diversity
- Large center (280/500) but highly volatile (0.58) → Unstable center driving dynamics
Conclusion: System at the peak of criticality, extremely rich and diverse, with a very active "floating" center generating complexity. This is the ideal regime for observing emergent phenomena, rapid transitions, and great adaptability. The slightest perturbation can cascade throughout the entire system.
🔑 IN SUMMARY
The fractal variable is your complexity compass. By cross-referencing it with:
- Fractal dimensions → you see whether this complexity is structural, dynamic, or both
- Criticality gap → you see whether this complexity is organized or chaotic
- Turnover → you see whether it's maintained by renewal or stability
- Entropy → you see whether it generates diversity or consensus
- Volatility → you see whether it rests on a stable or unstable pivot
- Constellations → you see who carries this complexity (center, radicals, etc.)
It is the ultimate integrator that gives meaning to all other measures. Without it, you have indicators; with it, you have systemic understanding.
CREDITS
- Original concept: Public Opinion Research Group (GROP.CA)
- NetLogo implementation & enhancements: Pierre-Alain Cotnoir (2015–2026)
- AI-assisted design: GPT-5, Copilot & DeepSeek (2024–2026)
- Contact: pacotnoir@gmail.com
Comments and Questions
extensions [ sound nw ] globals [ ;; core min-prevalence max-prevalence memes-per-change meta-influencers-right meta-influencers-left inject-tick tick-event iter change total inversion try major fractale ordonnee abscisse profondeur network-animation? list_data file-in in_data repet_data links-dead links-create meta-agents meta-links meta-create Interactions %Major initial-turtles-data ;; Liste pour stocker l'état initial de toutes les tortues initial-tick-loaded ;; Le tick qui a été chargé initial-turtles-data-copy ;; Une copie séparée pour préserver l'original simple-initial-data ;; Pour stocker les données initiales du format simple simple-import-mode ;; Pour savoir si on est en mode simple file-imported? ;; Indique si un fichier a été importé import-format ;; CSV csv-file-stats csv-file-values csv-buffer csv-open? setup? ;; import Values CSV list_values_data values_file_in values_sep ;; Mode d'importation import-mode initial-tick-state ;; FRACTAL topological-dimension dynamic-dimension criticality-gap criticality-history box-sizes network-snapshots cascade-sizes last-cascade-id ;; CONSTELLATIONS constellation-1-size constellation-2-size constellation-3-size constellation-4-size constellation-5-size constellation-1-opinion-avg constellation-2-opinion-avg constellation-3-opinion-avg constellation-4-opinion-avg constellation-5-opinion-avg constellation-1-prev-avg constellation-2-prev-avg constellation-3-prev-avg constellation-4-prev-avg constellation-5-prev-avg constellation-1-polarization constellation-2-polarization constellation-3-polarization constellation-4-polarization constellation-5-polarization turnover-global turnover-c1 turnover-c2 turnover-c3 turnover-c4 turnover-c5 opinion-entropy center-volatility prev-constellation-list last-center-opinion c-opinion-extreme c-opinion-moderate c-prevalence-high c-prevalence-low ;; LYAPUNOV lyapunov-exponent perturbation-history reference-trajectory perturbed-trajectory divergence-history ] turtles-own [ meta-type ;; "structural" ou "dynamic" opinion prevalence agent-type influence opinion-previous influence-previous x3d y3d z3d meme-plus meme-minus meme-plus-w meme-minus-w old-opinion proposed-opinion tx-bonus cascade-id constellation-prev my-neighbors pos-x pos-y pos-z ] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LOCALE / FORMAT HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to-report col-sep ifelse locale-format = "FR" [ report ";" ] [ report "," ] end to-report replace-all [s old new] let out s while [ position old out != false ] [ let i position old out set out (word (substring out 0 i) new (substring out (i + length old) (length out))) ] report out end to-report fmt [x] if x = nobody [ report "" ] if not is-number? x [ report (word x) ] let s (word "" x) if locale-format = "FR" [ set s replace-all s "." "," ] report s end to-report join-cols [lst] let sep col-sep let out "" foreach lst [ val -> let s (word "" val) set out ifelse-value (out = "") [ s ] [ (word out sep s) ] ] report out end to-report split-by [s sep] let parts [] let rest s while [ position sep rest != false ] [ let i position sep rest set parts lput (substring rest 0 i) parts set rest substring rest (i + length sep) (length rest) ] set parts lput rest parts report parts end to-report to-number-locale [s sep] if s = "" [ report 0 ] let x s if sep = ";" [ set x replace-all x "," "." ] set x replace-all x " " "" report read-from-string x end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CONFIG IMPORT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to import-config-from-stats-csv let f user-file if f = false [ stop ] file-close-all let cfg-sep ";" carefully [ file-open f while [not file-at-end?] [ let line file-read-line if line != "" [ if (length line >= 7) [ if (substring line 0 7 = "CONFIG,") [ set cfg-sep "," ] if (substring line 0 7 = "CONFIG;") [ set cfg-sep ";" ] ] if (length line >= 12) [ if (substring line 0 12 = "CONFIG_BEGIN,") [ set cfg-sep "," ] if (substring line 0 12 = "CONFIG_BEGIN;") [ set cfg-sep ";" ] ] if (length line >= 10) and (substring line 0 10 = "CONFIG_END") [ file-close user-message "Configuration loaded from Statistics CSV. Press SETUP to rebuild." stop ] let prefix (word "CONFIG" cfg-sep) if (length line >= length prefix) and (substring line 0 (length prefix) = prefix) [ let cols split-config-line line cfg-sep if length cols >= 3 [ let p item 1 cols let v item 2 cols apply-config-param p v ] ] ] ] file-close user-message "No CONFIG_END marker found. Config rows applied." ] [ file-close-all user-message "Config import error: could not read or parse the file." ] end to-report split-config-line [s sep] let parts [] let rest s while [ position sep rest != false ] [ let i position sep rest set parts lput (substring rest 0 i) parts set rest substring rest (i + length sep) (length rest) ] set parts lput rest parts report parts end to-report trim-spaces [s] let out s while [ (length out > 0) and (substring out 0 1 = " ") ] [ set out substring out 1 (length out) ] while [ (length out > 0) and (substring out (length out - 1) (length out) = " ") ] [ set out substring out 0 (length out - 1) ] report out end to-report maybe-number-fr [s] let x trim-spaces s if x = "" [ report nobody ] set x replace-all x " " "" set x replace-all x "," "." let r nobody carefully [ set r read-from-string x ] [ set r nobody ] if is-number? r [ report r ] report nobody end to apply-config-param [param value] let p trim-spaces param let v trim-spaces value if p = "meta-type-definition" [ stop ] if v = "true" [ run (word "set " p " true") stop ] if v = "false" [ run (word "set " p " false") stop ] let n maybe-number-fr v if n != nobody [ run (word "set " p " " n) stop ] let vv replace-all v "\"" "'" run (word "set " p " \"" vv "\"") end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; SETUP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to setup set csv-open? false set csv-buffer [] clear-all set file-imported? false set repet_data false set iter 0 set min-prevalence 0 set max-prevalence 99 set-default-shape turtles "person" set try 1 set inject-tick inject-base set major 0 set setup? true if not is-string? locale-format [ set locale-format "FR" ] if (locale-format != "FR" and locale-format != "EN") [ set locale-format "FR" ] if not is-number? event-init [ set event-init 50 ] set tick-event event-init set links-dead 0 set links-create 0 set meta-create 0 set meta-agents 0 set change 0 set total 0 set inversion 0 set fractale 0 if (vary-influence = true) or (meta-ok = true) [ set meta-links meta-min ] if not is-boolean? csv-export [ set csv-export false ] if (not is-string? csv-basename) or (csv-basename = "") [ set csv-basename "run" ] if not is-string? csv-mode [ set csv-mode "Statistics" ] if (csv-mode != "Statistics" and csv-mode != "Values") [ set csv-mode "Statistics" ] if not is-number? csv-values-step [ set csv-values-step 10 ] if csv-values-step < 1 [ set csv-values-step 1 ] if not is-number? csv-values-start [ set csv-values-start 0 ] if csv-values-start < 0 [ set csv-values-start 0 ] set csv-file-stats "" set csv-file-values "" set csv-buffer [] set csv-open? false set list_values_data [] set values_file_in false set values_sep ";" set import-mode "simple" set initial-tick-state 1 if not is-boolean? inject-metas-only [ set inject-metas-only false ] if (not is-string? group-impact-mode) [ set group-impact-mode "all" ] if (not is-number? group-k) [ set group-k 10 ] if (not is-number? group-impact-weight) [ set group-impact-weight 0.5 ] if (not is-number? group-impact-alpha) [ set group-impact-alpha 1.0 ] if not is-boolean? show-links [ set show-links false ] if not is-boolean? metablock [ set metablock false ] if (not is-number? prevalence-weight) [ set prevalence-weight 1.5 ] if (not is-number? adoption-floor) [ set adoption-floor 0.02 ] if (not is-number? bridge-prob) [ set bridge-prob 0.10 ] if not is-number? reward-step [ set reward-step 0.05 ] if not is-number? reward-cap [ set reward-cap 0.50 ] if not is-string? reward-scope [ set reward-scope "both" ] if not is-number? reward-prev-delta [ set reward-prev-delta 0 ] if not is-number? reward-decay [ set reward-decay 0 ] if not is-boolean? use-memes? [ set use-memes? false ] if not is-number? meme-max [ set meme-max 100 ] if not is-number? meme-gain [ set meme-gain 1.0 ] if not is-number? meme-anti-leak [ set meme-anti-leak 0.0 ] if not is-number? meme-decay [ set meme-decay 0.0 ] if not is-number? meme-weight-mean [ set meme-weight-mean 1.0 ] if not is-number? meme-weight-sd [ set meme-weight-sd 0.0 ] if not is-number? meme-weight-min [ set meme-weight-min 0.05 ] if not is-number? meme-weight-max [ set meme-weight-max 5.0 ] if not is-boolean? auto_inject? [ set auto_inject? false ] if not is-boolean? repeat-inject? [ set repeat-inject? false ] if not is-number? inject-tick [ set inject-tick 50 ] if not is-number? inject-pace [ set inject-pace 50 ] if not is-string? inject-sign [ set inject-sign "plus" ] if not is-number? inject-amount [ set inject-amount 1 ] if not is-number? inject-weight [ set inject-weight 1.0 ] if not is-number? inject-prob-max [ set inject-prob-max 1.0 ] if not is-number? inject-low_meme [ set inject-low_meme -1.0 ] if not is-number? inject-high_meme [ set inject-high_meme 1.0 ] if not is-number? inject-low-prev [ set inject-low-prev 0.0 ] if not is-number? inject-high-prev [ set inject-high-prev 99.0 ] set-background-black set topological-dimension 0 set dynamic-dimension 0 set criticality-gap 0 set criticality-history [] set box-sizes [0.5 0.25 0.125 0.0625 0.03125 0.015625] set network-snapshots [] set cascade-sizes [] set last-cascade-id 0 set c-opinion-extreme 0.6 set c-opinion-moderate 0.2 set c-prevalence-high 50 set c-prevalence-low 30 set constellation-1-size 0 set constellation-2-size 0 set constellation-3-size 0 set constellation-4-size 0 set constellation-5-size 0 set constellation-1-opinion-avg 0 set constellation-2-opinion-avg 0 set constellation-3-opinion-avg 0 set constellation-4-opinion-avg 0 set constellation-5-opinion-avg 0 set constellation-1-prev-avg 0 set constellation-2-prev-avg 0 set constellation-3-prev-avg 0 set constellation-4-prev-avg 0 set constellation-5-prev-avg 0 set constellation-1-polarization 0 set constellation-2-polarization 0 set constellation-3-polarization 0 set constellation-4-polarization 0 set constellation-5-polarization 0 set turnover-global 0 set turnover-c1 0 set turnover-c2 0 set turnover-c3 0 set turnover-c4 0 set turnover-c5 0 set opinion-entropy 0 set center-volatility 0 set last-center-opinion 0 set prev-constellation-list [] set lyapunov-exponent 0 set perturbation-history [] set divergence-history [] set reference-trajectory [] set perturbed-trajectory [] create output-headers ask turtles [ set constellation-prev get-constellation self set prev-constellation-list lput (list who 0) prev-constellation-list ] capture-network-snapshot end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CREATE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to create if not file-imported? [create-turtles pop / 2 [ set agent-type "Right side" set opinion random-float 1 set color blue set prevalence random-float (opinion * 100) set influence random-float 1 set opinion-previous opinion set influence-previous influence set tx-bonus 0 set cascade-id 0 set constellation-prev 0 set meta-type "none" init-memes-from-state update-3d self ] create-turtles pop / 2 [ set agent-type "Left side" set opinion (random-float 1 - 1) set color red set prevalence random-float (abs opinion * 100) set influence random-float 1 set opinion-previous opinion set influence-previous influence set tx-bonus 0 set cascade-id 0 set constellation-prev 0 set meta-type "none" init-memes-from-state update-3d self ]] reset-ticks influencers set total 0 set change 0 set Interactions 0 set %Major 0 update-networks recolor-links apply-link-visibility end to output-headers if output = "Statistics" [ output-print join-cols (list "Try" "Iter" "Global Opinion" "Right side Opinion" "Left side Opinion" "Right side Prevalence" "Left side Prevalence" "Right side Influence" "Left side Influence" "Left %" "Right %" "Links-Remove" "Links-Create" "Inversion %" "change" "total" "fractal" ) ] if output = "Values" [ output-print join-cols (list "Try" "Ticks" "Agents" "Prevalence" "Opinion" "Influence" "meme plus" "meme minus" "meme plus w" "meme minus w" ) ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; META-INFLUENCERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to influencers if meta-mode = "Percent" [ if meta-influencers-selection = "All" [ let k round (count turtles * meta-influencers / 100) let candidates turtles with [(prevalence >= prev-low and prevalence <= prev-high)] if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] if meta-influencers-selection = "Right side" [ let k round (count turtles * meta-influencers / 100) let candidates turtles with [opinion > 0 and (prevalence >= prev-low and prevalence <= prev-high)] if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] if meta-influencers-selection = "Left side" [ let k round (count turtles * meta-influencers / 100) let candidates turtles with [opinion < 0 and (prevalence >= prev-low and prevalence <= prev-high)] if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] ] if meta-mode = "Number" [ if meta-influencers-selection = "All" [ let k meta-influencers let candidates turtles with [(prevalence >= prev-low and prevalence <= prev-high)] if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] if meta-influencers-selection = "Right side" [ let candidates turtles with [opinion > 0 and (prevalence >= prev-low and prevalence <= prev-high)] let k meta-influencers if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] if meta-influencers-selection = "Left side" [ let candidates turtles with [opinion < 0 and (prevalence >= prev-low and prevalence <= prev-high)] let k meta-influencers if k > 0 and any? candidates [ let n-to-take min (list k count candidates) ask up-to-n-of n-to-take candidates [ set influence 1 set color yellow set meta-agents meta-agents + 1 set meta-type "structural" ] ] ] ] end to-report meta? report (color = yellow) or (influence = 1) end to maybe-set-opinion [ new-op ] let old-op opinion let bounded-op max list -1 min list 1 new-op if metablock and meta? and (sign old-op != sign bounded-op) [ let mag max list (abs old-op) (abs bounded-op) set opinion (sign old-op) * mag stop ] set opinion bounded-op end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CSV ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to-report csv-filename [mode-tag] report (word csv-basename "-" try "-" mode-tag "-" locale-format ".csv") end to csv-begin set csv-buffer [] set csv-open? true ;; --- Mode STATISTICS --- if csv-mode = "Statistics" [ set csv-file-stats csv-filename "stats" if file-exists? csv-file-stats [ carefully [ file-delete csv-file-stats ] [ set csv-file-stats (word csv-file-stats "_locked_" (random 1000000)) ] ] file-open csv-file-stats set csv-buffer lput (join-cols (list "try" "iter" "tick" "left_pct" "right_pct" "avg_opinion" "med_op_right" "med_op_left" "med_prev_right" "med_prev_left" "med_infl_right" "med_infl_left" "links_remove" "links_create" "bridge_links" "inversion_pct" "change" "total" "fractal" "major" "interactions_per_iter" "majority_pct" "interactions_per_inversion" "meta_links" "meta_agents" "mean_prevalence" "median_prevalence" "median_opinion" "mean_abs_opinion" "mean_meme_stock" "mean_meme_derived_opinion" "mean_polarity_index" "meme_saturation_pct" "right_meme_polarization" "left_meme_polarization" "opinion_meme_gap" "ideologization_index" "ideologization_opinion_based" "topological_dim" "dynamic_dim" "criticality_gap" "Status" "c1_size" "c2_size" "c3_size" "c4_size" "c5_size" "c1_opinion_avg" "c2_opinion_avg" "c3_opinion_avg" "c4_opinion_avg" "c5_opinion_avg" "c1_prev_avg" "c2_prev_avg" "c3_prev_avg" "c4_prev_avg" "c5_prev_avg" "c1_polarization" "c2_polarization" "c3_polarization" "c4_polarization" "c5_polarization" "turnover_global" "turnover_c1" "turnover_c2" "turnover_c3" "turnover_c4" "turnover_c5" "opinion_entropy" "center_volatility" "regime_code" "lyapunov_exponent")) csv-buffer ] ;; --- Mode VALUES --- if csv-mode = "Values" [ set csv-file-values csv-filename "values" if file-exists? csv-file-values [ carefully [ file-delete csv-file-values ] [ set csv-file-values (word csv-file-values "_locked_" (random 1000000)) ] ] ;; En-têtes du fichier Values set csv-buffer lput (join-cols (list "try" "tick" "agent" "prevalence" "opinion" "influence" "meme_plus" "meme_minus" "meme_plus_w" "meme_minus_w" "meta-type" "neighbors" )) csv-buffer ] end to ensure-csv-ready if not csv-export [ stop ] if not csv-open? [ csv-begin ] end to csv-row-statistics let sys-status system-status let avg-opinion mean [opinion] of turtles let opR safe-median (turtles with [opinion >= 0]) "opinion" let opL safe-median (turtles with [opinion < 0]) "opinion" let prevR (safe-median (turtles with [opinion >= 0]) "prevalence") / 100 let prevL (safe-median (turtles with [opinion < 0]) "prevalence") / 100 let inflR safe-median (turtles with [opinion >= 0]) "influence" let inflL safe-median (turtles with [opinion < 0]) "influence" let leftpct (count turtles with [opinion < 0]) / (pop / 100) let rightpct (count turtles with [opinion >= 0]) / (pop / 100) let bridge_links count links with [ (sign [opinion] of end1) != (sign [opinion] of end2) ] let interactions-per-iter ifelse-value (iter > 0) [ total / iter ] [ 0 ] let majority-pct %Major let interactions-per-inversion ifelse-value (change > 0) [ total / change ] [ 0 ] let mean-prevalence ifelse-value (any? turtles) [ mean [prevalence] of turtles ] [ 0 ] let median-prevalence safe-median turtles "prevalence" let median-opinion safe-median turtles "opinion" let mean-abs-opinion ifelse-value (any? turtles) [ mean [abs opinion] of turtles ] [ 0 ] let mean-meme-stock ifelse-value (any? turtles) [ mean [meme-plus + meme-minus] of turtles ] [ 0 ] let mean-meme-derived-opinion ifelse-value (any? turtles) [ mean [ ifelse-value ((meme-plus-w + meme-minus-w) > 0) [ (meme-plus-w - meme-minus-w) / (meme-plus-w + meme-minus-w) ] [ 0 ] ] of turtles ] [ 0 ] let mean-pol-index mean-polarity-index let meme-sat meme-saturation-pct let right-den sum [meme-plus + meme-minus] of turtles with [opinion >= 0] let right-num (sum [meme-plus] of turtles with [opinion >= 0]) - (sum [meme-minus] of turtles with [opinion >= 0]) let right-meme-pol ifelse-value (right-den > 0) [ right-num / right-den ] [ 0 ] let left-den sum [meme-plus + meme-minus] of turtles with [opinion < 0] let left-num (sum [meme-plus] of turtles with [opinion < 0]) - (sum [meme-minus] of turtles with [opinion < 0]) let left-meme-pol ifelse-value (left-den > 0) [ left-num / left-den ] [ 0 ] let opinion-meme-gap ifelse-value (any? turtles) [ mean [ abs (opinion - (ifelse-value ((meme-plus-w + meme-minus-w) > 0) [ (meme-plus-w - meme-minus-w) / (meme-plus-w + meme-minus-w) ] [ 0 ])) ] of turtles ] [ 0 ] let ideologization-index ifelse-value (any? turtles) [ ideologization-meme-based ] [ 0 ] let ideologization-opinion-based-val ifelse-value (any? turtles) [ ideologization-opinion-based ] [ 0 ] let d_top ifelse-value (topological-dimension > 0) [ topological-dimension ] [ 0 ] let d_dyn ifelse-value (dynamic-dimension > 0) [ dynamic-dimension ] [ 0 ] let c_gap ifelse-value (criticality-gap > 0) [ criticality-gap ] [ 0 ] let regime-code system-regime-code set csv-buffer lput (join-cols (list fmt try fmt iter fmt ticks fmt leftpct fmt rightpct fmt avg-opinion fmt opR fmt opL fmt prevR fmt prevL fmt inflR fmt inflL fmt links-dead fmt links-create fmt bridge_links fmt inversion fmt change fmt total fmt fractale fmt major fmt interactions-per-iter fmt majority-pct fmt interactions-per-inversion fmt meta-links fmt meta-agents fmt mean-prevalence fmt median-prevalence fmt median-opinion fmt mean-abs-opinion fmt mean-meme-stock fmt mean-meme-derived-opinion fmt mean-pol-index fmt meme-sat fmt right-meme-pol fmt left-meme-pol fmt opinion-meme-gap fmt ideologization-index fmt ideologization-opinion-based-val fmt d_top fmt d_dyn fmt c_gap fmt sys-status fmt constellation-1-size fmt constellation-2-size fmt constellation-3-size fmt constellation-4-size fmt constellation-5-size fmt constellation-1-opinion-avg fmt constellation-2-opinion-avg fmt constellation-3-opinion-avg fmt constellation-4-opinion-avg fmt constellation-5-opinion-avg fmt constellation-1-prev-avg fmt constellation-2-prev-avg fmt constellation-3-prev-avg fmt constellation-4-prev-avg fmt constellation-5-prev-avg fmt constellation-1-polarization fmt constellation-2-polarization fmt constellation-3-polarization fmt constellation-4-polarization fmt constellation-5-polarization fmt turnover-global fmt turnover-c1 fmt turnover-c2 fmt turnover-c3 fmt turnover-c4 fmt turnover-c5 fmt opinion-entropy fmt center-volatility fmt regime-code fmt lyapunov-exponent )) csv-buffer end to csv-add-config-snapshot if not csv-export [ stop ] if csv-mode != "Statistics" [ stop ] if not csv-open? [ stop ] set csv-buffer lput "" csv-buffer set csv-buffer lput (join-cols (list "CONFIG_BEGIN" (word "try=" try) (word "last_tick=" ticks))) csv-buffer let rows (list (list "pop" pop) (list "nb_try" nb_try) (list "max_iter" max_iter) (list "threshold" threshold) (list "cumulative" cumulative) (list "refresh" refresh) (list "output" output) (list "locale-format" locale-format) (list "csv-basename" csv-basename) (list "csv-mode" csv-mode) (list "csv-values-start" csv-values-start) (list "csv-values-step" csv-values-step) (list "network" network) (list "link-removal-threshold" link-removal-threshold) (list "link-formation-threshold" link-formation-threshold) (list "prob" prob) (list "linksdown" linksdown) (list "linksup" linksup) (list "bridge-prob" bridge-prob) (list "show-links" show-links) (list "linktick" linktick) (list "polarization-factor" polarization-factor) (list "prevalence-weight" prevalence-weight) (list "adoption-floor" adoption-floor) (list "noise" noise) (list "mode_prev" mode_prev) (list "rate-mod" rate-mod) (list "rate-infl" rate-infl) (list "group-impact-mode" group-impact-mode) (list "group-k" group-k) (list "group-impact-weight" group-impact-weight) (list "group-impact-alpha" group-impact-alpha) (list "reward-step" reward-step) (list "reward-cap" reward-cap) (list "reward-scope" reward-scope) (list "reward-prev-delta" reward-prev-delta) (list "reward-decay" reward-decay) (list "meta-ok" meta-ok) (list "meta-mode" meta-mode) (list "meta-influencers-selection" meta-influencers-selection) (list "meta-influencers" meta-influencers) (list "prev-low" prev-low) (list "prev-high" prev-high) (list "meta-min" meta-min) (list "meta-max" meta-max) (list "meta-links" meta-links) (list "meta-type-definition" "structural/dynamic/none") (list "metablock" metablock) (list "vary-influence" vary-influence) (list "auto_event" auto_event) (list "repeat_event" repeat_event) (list "event-init" event-init) (list "event-pace" event-pace) (list "event-prob-max" event-prob-max) (list "event_size" event_size) (list "prev_change" prev_change) (list "meme_set" meme_set) (list "to_left" to_left) (list "low_meme" low_meme) (list "high_meme" high_meme) (list "low-prev" low-prev) (list "high-prev" high-prev) (list "use-memes?" use-memes?) (list "meme-max" meme-max) (list "meme-gain" meme-gain) (list "meme-anti-leak" meme-anti-leak) (list "meme-decay" meme-decay) (list "meme-weight-mean" meme-weight-mean) (list "meme-weight-sd" meme-weight-sd) (list "meme-weight-min" meme-weight-min) (list "meme-weight-max" meme-weight-max) (list "auto_inject?" auto_inject?) (list "repeat-inject?" repeat-inject?) (list "inject-metas-only" inject-metas-only) (list "inject-tick" inject-tick) (list "inject-pace" inject-pace) (list "inject-sign" inject-sign) (list "inject-amount" inject-amount) (list "inject-weight" inject-weight) (list "inject-prob-max" inject-prob-max) (list "inject-low_meme" inject-low_meme) (list "inject-high_meme" inject-high_meme) (list "inject-low-prev" inject-low-prev) (list "inject-high-prev" inject-high-prev) (list "c-opinion-extreme" c-opinion-extreme) (list "c-opinion-moderate" c-opinion-moderate) (list "c-prevalence-high" c-prevalence-high) (list "c-prevalence-low" c-prevalence-low) ) foreach rows [ r -> let k item 0 r let v item 1 r set csv-buffer lput (join-cols (list "CONFIG" (word k) (fmt v))) csv-buffer ] set csv-buffer lput (join-cols (list "CONFIG_END" (word "try=" try) "")) csv-buffer end to csv-row-values if ticks < csv-values-start [ stop ] if (ticks mod csv-values-step) != 0 [ stop ] foreach sort turtles [ t -> ;; Construire la chaîne de voisins "id1|id2|id3" let neigh-ids [who] of [link-neighbors] of t let neigh-str "" foreach neigh-ids [ nid -> ifelse neigh-str = "" [ set neigh-str (word nid) ] [ set neigh-str (word neigh-str "|" nid) ] ] set csv-buffer lput (join-cols (list fmt try fmt ticks fmt [who] of t fmt [prevalence] of t fmt [opinion] of t fmt [influence] of t fmt [meme-plus] of t fmt [meme-minus] of t fmt [meme-plus-w] of t fmt [meme-minus-w] of t fmt [meta-type] of t neigh-str )) csv-buffer ] end to csv-flush if empty? csv-buffer [ stop ] file-close-all let target "" if csv-mode = "Statistics" [ set target csv-file-stats ] if csv-mode = "Values" [ set target csv-file-values ] file-open target foreach csv-buffer [ line -> file-print line ] file-close set csv-buffer [] end to csv-end if csv-open? [ csv-flush ] file-close-all set csv-buffer [] set csv-open? false end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GO - VERSION CORRIGÉE AVEC ENCHAÎNEMENT AUTOMATIQUE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GO - Version avec enchaînement automatique des essais ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to go ;; Vérifier s'il y a des tortues if not any? turtles or count turtles != pop or setup? = 0 [ user-message "Please click SETUP first to create the population!" stop ] ifelse (iter < max_iter) [ ;; ======================================================================== ;; DÉROULEMENT D'UN ESSAI ;; ======================================================================== ;; Initialisation CSV if csv-export [ ensure-csv-ready ] if ticks mod 500 = 0 [ diagnose-system ] ;; Mise à jour des statistiques if iter > 0 [ set Interactions (total / iter) ] if iter > 0 [ set %Major (major / iter * 100) ] set iter iter + 1 set meta-create 0 ;; Événements if auto_event [ if (iter = tick-event) [ event if repeat_event [ set tick-event (tick-event + event-pace) ] ] ] ;; Injection de mèmes if auto_inject? [ if (iter = inject-tick) [ inject-memes if repeat-inject? [ set inject-tick (inject-tick + inject-pace) ] ] ] ;; Mise à jour des métriques if meta-ok = true [ meta ] update-opinions if network = true [ update-networks ] recolor-links apply-link-visibility capture-network-snapshot ;; Calculs périodiques if ticks mod 100 = 0 and ticks > 0 [ compute-fractal-dimensions if ticks mod 500 = 0 [ output-print (word "SYSTEM STATUS at tick " ticks ": " system-status) ] compute-lyapunov-exponent ] ;; Suivi des perturbations if ticks = 1 [ initialize-perturbation ] if ticks > 1 [ update-perturbation ] ;; Mise à jour des constellations update-constellations ;; Sortie statistiques if output = "Statistics" [ let avg-opinion mean [opinion] of turtles let positive-opinion safe-median (turtles with [opinion >= 0]) "opinion" let negative-opinion safe-median (turtles with [opinion < 0]) "opinion" let positive-prevalence (safe-median (turtles with [opinion >= 0]) "prevalence") / 100 let negative-prevalence (safe-median (turtles with [opinion < 0]) "prevalence") / 100 let positive-influence safe-median (turtles with [opinion >= 0]) "influence" let negative-influence safe-median (turtles with [opinion < 0]) "influence" let Left% (count turtles with [opinion < 0]) / (pop / 100) let Right% (count turtles with [opinion >= 0]) / (pop / 100) let ti iter output-print join-cols (list fmt try fmt ti fmt avg-opinion fmt positive-opinion fmt negative-opinion fmt positive-prevalence fmt negative-prevalence fmt positive-influence fmt negative-influence fmt Left% fmt Right% fmt links-dead fmt links-create fmt inversion fmt change fmt total fmt fractale ) ] ;; Avancer le temps tick ;; Mise à jour des métriques fractales ifelse use-memes? [ if (change > 1 and iter > 1) [ set fractale (ln total / ln change) ] ] [ if (change > 1 and total > 1) [ set fractale (ln total) / (ln change) ] ] if (cumulative = false) [ set change 0 set total 0 ] colorer if (refresh = true) [ if ticks > 200 [ reset-ticks clear-plot ] ] if threshold <= (count turtles with [opinion > 0]) / (pop / 100) [ set major major + 1 ] ;; Écriture CSV if csv-export [ if csv-mode = "Statistics" [ csv-row-statistics ] if csv-mode = "Values" [ csv-row-values ] ] ;; ======================================================================== ;; FIN DE L'ESSAI EN COURS ;; ======================================================================== ] [ ifelse (try < nb_try) [ ;; ====================================================================== ;; PRÉPARATION DU PROCHAIN ESSAI ;; ====================================================================== ;; TUER LES TURTLES IMMÉDIATEMENT clear-turtles clear-links ;; Sauvegarde CSV si nécessaire if csv-export [ if csv-mode = "Statistics" [ csv-add-config-snapshot ] csv-end ] ;; Réinitialisation des variables globales set try try + 1 set major 0 clear-turtles clear-plot set change 0 set total 0 set fractale 0 set meta-links meta-min set iter 0 set links-create 0 set links-dead 0 set meta-create 0 set meta-agents 0 set min-prevalence 0 set max-prevalence 99 set tick-event event-init set inject-tick inject-base ;; Rechargement des données selon le mode d'importation if (repet_data = true) [ if (import-mode = "values") [ restore-initial-state reset-ticks ;; NE PAS appeler go ici - le bouton Forever s'en charge ] if (import-mode = "simple") [ data-simple reset-ticks ;; NE PAS appeler go ici - le bouton Forever s'en charge ] ] ;; Création d'une nouvelle population aléatoire (seulement si pas de fichier importé) if not file-imported? [ create reset-ticks ] ;; Création d'une nouvelle population aléatoire ;;create ;;reset-ticks ;;go ;; <<< LANCEMENT AUTOMATIQUE DU PROCHAIN ESSAI ;; ====================================================================== ;; FIN DE TOUS LES ESSAIS ;; ====================================================================== ] [ if csv-export [ if csv-mode = "Statistics" [ csv-add-config-snapshot ] csv-end ] sound:play-note "Tubular Bells" 60 64 1 stop ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DATA IMPORT - VERSIONS CORRIGÉES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to in_file if setup? = 0 [user-message "Please click SETUP first before loading file!" stop] in_file_simple end ;; CORRECTION de in_file_simple to in_file_simple carefully [ set file-in user-file if (file-in != false) [ set list_data [] file-open file-in while [not file-at-end?] [ set list_data sentence list_data (list (list file-read file-read file-read file-read)) ] file-close ;; Stocker une copie des données initiales set simple-initial-data [] foreach list_data [ row -> set simple-initial-data lput (copy-list row) simple-initial-data ] user-message (word "File uploaded (simple format)! " length list_data " lines loaded.") set import-mode "simple" set in_data true set repet_data true ] ] [ user-message "File read error" ] set choice_iter 0 data-simple set file-imported? true end ;; NOUVELLE PROCÉDURE pour charger et stocker l'état initial ;; CORRECTION de load-and-store-initial-state ;; CORRECTION de load-and-store-initial-state pour s'assurer que les données sont correctes ;; MODIFICATION de load-and-store-initial-state pour vérifier les données chargées ;; CORRECTION de load-and-store-initial-state ;; CORRECTION de load-and-store-initial-state avec copie profonde to load-and-store-initial-state print "STEP 0: Entering load-and-store-initial-state" let tick-to-load initial-tick-loaded print (word "STEP 1: Tick-to-load = " tick-to-load) let initial-rows [] print "STEP 2: Initial-rows initialized" ;; Sélection des lignes correspondant au tick demandé foreach list_values_data [ row -> if is-list? row [ let tick-courant to-number-locale (item 1 row) values_sep if tick-courant = tick-to-load [ set initial-rows lput row initial-rows ] ] ] print (word "STEP 3: Length initial-rows = " length initial-rows) if empty? initial-rows [ user-message (word "No data found for tick " tick-to-load " in the file!") stop ] ;; Tri par ID d’agent print "STEP 4: Start of sorting" set initial-rows sort-by [ [a b] -> (to-number-locale (item 2 a) values_sep) < (to-number-locale (item 2 b) values_sep) ] initial-rows print "STEP 5: Sorting completed" set initial-turtles-data [] set initial-turtles-data-copy [] print "STEP 6: Lists initialized" print "STEP A: Start of line processing" foreach initial-rows [ row -> print "STEP 7: Start of line" ;; --- Extraction des valeurs numériques --- let prev-val to-number-locale (item 3 row) values_sep let opin-val to-number-locale (item 4 row) values_sep let infl-val to-number-locale (item 5 row) values_sep let mplus-val to-number-locale (item 6 row) values_sep let mminus-val to-number-locale (item 7 row) values_sep let mplusw-val to-number-locale (item 8 row) values_sep let mminusw-val to-number-locale (item 9 row) values_sep let meta-val item 10 row print "STEP 8: Numerical values read" ;; --- Parsing des voisins --- let neigh-str "" if length row > 11 [ set neigh-str item 11 row ] let neigh-list [] if neigh-str != "" [ let raw split-by neigh-str "|" set raw filter [ x -> x != "" ] raw foreach raw [ x -> let v -1 carefully [ set v read-from-string x ] [ set v -1 ] if v >= 0 [ set neigh-list lput v neigh-list ] ] ] print (word "STEP 9: Neighbors read = " neigh-list) ;; --- Positions --- let posx 0 let posy 0 let posz 0 ;; Format générateur → colonnes 12, 13, 14 if import-format = "generator" and length row > 14 [ set posx to-number-locale (item 12 row) values_sep set posy to-number-locale (item 13 row) values_sep set posz to-number-locale (item 14 row) values_sep ] ;; --- Construction de agent-data --- let agent-data (list prev-val opin-val infl-val mplus-val mminus-val mplusw-val mminusw-val meta-val neigh-list posx posy posz ) set initial-turtles-data lput agent-data initial-turtles-data set initial-turtles-data-copy lput (copy-list agent-data) initial-turtles-data-copy print "STEP 10: End of line" ] print "STEP B: End of processing" end ;; Network links visualization. to animate-network-layout repeat network-steps [ layout-spring turtles links 0.3 5 1 display ] end ;; Nouvelle fonction pour copier une liste en profondeur ;; Alternative avec la syntaxe ? ;; Correction de la fonction copy-list to-report copy-list [lst] let new-list [] foreach lst [ un-element -> ;; Renommé de "item" à "un-element" ifelse is-list? un-element [ set new-list lput (copy-list un-element) new-list ] [ set new-list lput un-element new-list ] ] report new-list end ;; NOUVELLE PROCÉDURE pour restaurer l'état initial ;; CORRECTION de restore-initial-state to restore-initial-state if setup? = 0 [ user-message "Please click SETUP first before loading file!" stop ] if not file-imported? [ user-message "First import CSV file." stop ] clear-turtles reset-ticks ;; Création des agents foreach initial-turtles-data [ agent-data -> create-turtles 1 [ ;; --- Restauration des valeurs numériques brutes --- set prevalence item 0 agent-data set opinion item 1 agent-data set influence item 2 agent-data set meme-plus item 3 agent-data set meme-minus item 4 agent-data set meme-plus-w item 5 agent-data set meme-minus-w item 6 agent-data ;; --- Interprétation stricte de meta-type --- let mt item 7 agent-data ifelse member? mt ["dynamic" "structural"] [ set meta-type mt ] [ set meta-type "none" ] ;; --- Voisins et position --- set my-neighbors item 8 agent-data set pos-x item 9 agent-data set pos-y item 10 agent-data set pos-z item 11 agent-data setxy pos-x pos-y ;; --- Valeurs internes du modèle --- set opinion-previous opinion set influence-previous influence set tx-bonus 0 set cascade-id 0 set constellation-prev 0 ;; --- Couleur initiale cohérente avec le reste du modèle --- ifelse meta-type != "none" or influence = 1 [ set color yellow set meta-agents meta-agents + 1 ] [ ifelse opinion < 0 [ set color red set agent-type "Left side" ] [ ifelse opinion > 0 [ set color blue set agent-type "Right side" ] [ set color white set agent-type "Center" ] ] ] ] ] ;; Reconstruction des liens ask turtles [ let neigh my-neighbors foreach neigh [ n -> if n != who [ if turtle n != nobody [ create-link-with turtle n ] ] ] ] user-message "Initial state restore." end ;; CORRECTION de in_file_values to in_file_values if setup? = 0 [ user-message "Please click SETUP first before loading file!" stop ] carefully [ set values_file_in user-file if values_file_in = false [ stop ] set list_values_data [] file-open values_file_in if file-at-end? [ user-message "Empty file" file-close stop ] ;; Lire l'en-tête let header file-read-line ;; Détecter le séparateur ifelse (position ";" header != false) [ set values_sep ";" ] [ set values_sep "," ] ;; Lire toutes les lignes while [not file-at-end?] [ let line file-read-line if line != "" [ let cols parse-csv-line line values_sep set list_values_data lput cols list_values_data ] ] file-close if empty? list_values_data [ user-message "No data found in file" stop ] ;; Détection automatique du format let first-row first list_values_data let nb-cols length first-row if nb-cols = 12 [ set import-format "simulator" ] if nb-cols = 15 [ set import-format "generator" ] if nb-cols != 12 and nb-cols != 15 [ user-message (word "Unsupported CSV format: " nb-cols " columns.") stop ] set import-mode "values" set repet_data true set initial-tick-loaded choice_iter user-message (word "File uploaded (values CSV)! " length list_values_data " lines loaded. Using tick " initial-tick-loaded " as initial state.") load-and-store-initial-state ] [ user-message (word "Values file read error: " error-message) stop ] set file-imported? true user-message "Import done. Now click 'Restore state'." end to-report parse-csv-line [line sep] let raw (word line) ;; force conversion propre let cols [] let tmp raw while [ tmp != "" ] [ let pos position sep tmp if pos = false [ set cols lput (trim-string tmp) cols set tmp "" ] if pos != false [ let token substring tmp 0 pos set cols lput (trim-string token) cols set tmp substring tmp (pos + 1) length tmp ] ] report cols end to-report trim-string [s] report remove "\r" remove "\n" remove " " s end to data ifelse import-mode = "values" [ data-values ] [ data-simple ] end ;; CORRECTION de data-simple to data-simple clear-turtles clear-links ;; Utiliser les données stockées dans simple-initial-data if not is-list? simple-initial-data or empty? simple-initial-data [ user-message "No simple data loaded! Please import a file first." stop ] let tick-to-load choice_iter ;; Filtrer les données pour le tick demandé let filtered-data filter [ row -> first row = tick-to-load ] simple-initial-data if empty? filtered-data [ let available remove-duplicates map [row -> first row] simple-initial-data user-message (word "No data for tick " tick-to-load ". Available ticks: " available) stop ] let n min list pop length filtered-data let selected-data sublist filtered-data 0 n set meta-agents 0 create-turtles n [ let agent-data item who selected-data set prevalence item 1 agent-data set opinion item 2 agent-data set influence item 3 agent-data if influence = 1 [ set meta-agents meta-agents + influence ] set opinion-previous opinion set influence-previous influence set tx-bonus 0 set cascade-id 0 set constellation-prev 0 ;; Initialiser les mèmes init-memes-from-state ;; Définir la couleur ifelse opinion < 0 [ set color red set agent-type "Left side" ] [ ifelse opinion > 0 [ set color blue set agent-type "Right side" ] [ set color white set agent-type "Center" ] ] if influence = 1 [ set color yellow ] update-3d self ] ;; Diagnostic output-print "=== RESTORE SIMPLE INITIAL STATE ===" output-print (word "Total agents: " count turtles) output-print (word "Current tick: " ticks) let left-agents turtles with [opinion < 0] let right-agents turtles with [opinion > 0] output-print (word "Left side (opinion < 0): " count left-agents " agents") output-print (word "Right side (opinion > 0): " count right-agents " agents") output-print (word "Influencers: " meta-agents " agents") ;; Afficher des exemples output-print "Examples of left agents (opinion < 0):" ifelse any? left-agents [ let sample-size min (list 3 count left-agents) let samples sort [who] of n-of sample-size left-agents foreach samples [ id -> ask turtle id [ output-print (word " Agent " who ": opinion=" precision opinion 6 " color=" color) ] ] ] [ output-print " NO LEFT AGENTS FOUND!" ] output-print "Examples of right agents (opinion > 0):" ifelse any? right-agents [ let sample-size min (list 3 count right-agents) let samples sort [who] of n-of sample-size right-agents foreach samples [ id -> ask turtle id [ output-print (word " Agent " who ": opinion=" precision opinion 6 " color=" color) ] ] ] [ output-print " NO RIGHT AGENTS FOUND!" ] output-print "================================" update-networks apply-link-visibility recolor-links set repet_data true set import-mode "simple" set tick-event event-init set inject-tick inject-base set iter 0 reset-ticks end to data-values ;; Cette procédure ne fait que restaurer l'état initial stocké restore-initial-state end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; UPDATE OPINIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to update-opinions ask turtles [ set opinion-previous opinion let target one-of link-neighbors if target != nobody [ let raw-dprev ([prevalence] of target) - prevalence if raw-dprev < 1 [ set raw-dprev 0 ] let dprev raw-dprev / max-prevalence if dprev > 0 [ let dmem abs(abs(opinion) - abs([opinion] of target)) let base-prob dprev * prevalence-weight let pol-penalty max list adoption-floor (1 - polarization-factor * dmem) let p-adopt base-prob * pol-penalty * [influence] of target * (1 + [tx-bonus] of target) let sgn-emitter sign ([opinion] of target) let gprob group-alignment-effective self sgn-emitter let w group-impact-weight let alpha group-impact-alpha set p-adopt p-adopt * ((1 - w) + (w * (gprob ^ alpha))) if p-adopt < 0 [ set p-adopt 0 ] if p-adopt > 1 [ set p-adopt 1 ] if random-float 1 < p-adopt [ set old-opinion opinion set proposed-opinion [opinion] of target ifelse use-memes? [ transmit-memes target recompute-from-memes ] [ maybe-set-opinion proposed-opinion ] if opinion = old-opinion [ stop ] set total total + 1 if opinion != old-opinion [ if [cascade-id] of target != 0 [ set cascade-id [cascade-id] of target ] if cascade-id = 0 [ set last-cascade-id last-cascade-id + 1 set cascade-id last-cascade-id ] set cascade-sizes lput (list ticks who [opinion] of target cascade-id) cascade-sizes if length cascade-sizes > 1000 [ let start length cascade-sizes - 1000 set cascade-sizes sublist cascade-sizes start length cascade-sizes ] ] let emitter-sign sign ([opinion] of target) let eligible? (reward-scope = "both") or (reward-scope = "left-only" and emitter-sign < 0) or (reward-scope = "right-only" and emitter-sign >= 0) if eligible? [ ask target [ set tx-bonus min (list reward-cap (tx-bonus + reward-step)) ] ] if reward-prev-delta > 0 [ set prevalence min (list max-prevalence (prevalence + reward-prev-delta)) ] set influence-previous influence if vary-influence = true [ if abs(old-opinion) > abs(opinion) [ set influence min (list 1 (influence + rate-infl)) if (influence-previous < 1 and influence = 1) [ ;; L’agent devient méta dynamique set meta-type "dynamic" if meta-ok = true [ if meta-links < meta-max [ set meta-links meta-links + 1 ] set meta-agents meta-agents + 1 ] set color yellow ] ] if abs(old-opinion) < abs(opinion) [ set influence max (list 0 (influence - rate-infl)) if (influence < influence-previous and influence-previous = 1) [ ;; Si c’est un méta dynamique → il perd son statut if meta-type = "dynamic" [ set meta-type "none" if meta-ok = true [ set meta-agents meta-agents - 1 ifelse opinion >= 0 [ set color blue ] [ set color red ] ] ] ;; Si c’est un méta structurel → il reste méta if meta-type = "structural" [ ;; on restaure son influence à 1 set influence 1 set color yellow ] ] ] ] if (sign old-opinion) != (sign opinion) [ set change change + 1 ] if change > 0 [ set memes-per-change (((sum [meme-plus + meme-minus] of turtles) / change) / pop) ] ] ] ] if mode_prev = true [ if prevalence > abs opinion * 100 [ set prevalence prevalence - abs(opinion - opinion-previous) * influence * rate-mod ] if prevalence < abs opinion * 100 [ set prevalence prevalence + abs(opinion - opinion-previous) * influence * rate-mod ] if prevalence < min-prevalence [ set prevalence min-prevalence ] if prevalence > max-prevalence [ set prevalence max-prevalence ] ] if random-float 1 < noise [ let delta (random-float 0.4 - 0.2) maybe-set-opinion (opinion + delta) ] if use-memes? [ decay-memes ] update-3d self if (output = "Values") [ compute-statistics ] ] if reward-decay > 0 [ ask turtles [ set tx-bonus max (list 0 (tx-bonus - reward-decay)) ] ] ifelse (total > 0) [ set inversion (100 * change / total) ] [ set inversion 0 ] if ticks mod 1000 = 0 [ ask turtles [ set cascade-id 0 ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CONSTELLATIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to update-constellations compute-turnover compute-constellation-membership compute-constellation-stats compute-entropy compute-volatility end to compute-constellation-membership set constellation-1-size 0 set constellation-2-size 0 set constellation-3-size 0 set constellation-4-size 0 set constellation-5-size 0 let total-op-c1 0 let total-op-c2 0 let total-op-c3 0 let total-op-c4 0 let total-op-c5 0 let total-prev-c1 0 let total-prev-c2 0 let total-prev-c3 0 let total-prev-c4 0 let total-prev-c5 0 ask turtles [ let const get-constellation self if const = 1 [ set constellation-1-size constellation-1-size + 1 set total-op-c1 total-op-c1 + opinion set total-prev-c1 total-prev-c1 + prevalence ] if const = 2 [ set constellation-2-size constellation-2-size + 1 set total-op-c2 total-op-c2 + opinion set total-prev-c2 total-prev-c2 + prevalence ] if const = 3 [ set constellation-3-size constellation-3-size + 1 set total-op-c3 total-op-c3 + opinion set total-prev-c3 total-prev-c3 + prevalence ] if const = 4 [ set constellation-4-size constellation-4-size + 1 set total-op-c4 total-op-c4 + opinion set total-prev-c4 total-prev-c4 + prevalence ] if const = 5 [ set constellation-5-size constellation-5-size + 1 set total-op-c5 total-op-c5 + opinion set total-prev-c5 total-prev-c5 + prevalence ] set constellation-prev const ] set constellation-1-opinion-avg ifelse-value (constellation-1-size > 0) [ total-op-c1 / constellation-1-size ] [ 0 ] set constellation-2-opinion-avg ifelse-value (constellation-2-size > 0) [ total-op-c2 / constellation-2-size ] [ 0 ] set constellation-3-opinion-avg ifelse-value (constellation-3-size > 0) [ total-op-c3 / constellation-3-size ] [ 0 ] set constellation-4-opinion-avg ifelse-value (constellation-4-size > 0) [ total-op-c4 / constellation-4-size ] [ 0 ] set constellation-5-opinion-avg ifelse-value (constellation-5-size > 0) [ total-op-c5 / constellation-5-size ] [ 0 ] set constellation-1-prev-avg ifelse-value (constellation-1-size > 0) [ total-prev-c1 / constellation-1-size ] [ 0 ] set constellation-2-prev-avg ifelse-value (constellation-2-size > 0) [ total-prev-c2 / constellation-2-size ] [ 0 ] set constellation-3-prev-avg ifelse-value (constellation-3-size > 0) [ total-prev-c3 / constellation-3-size ] [ 0 ] set constellation-4-prev-avg ifelse-value (constellation-4-size > 0) [ total-prev-c4 / constellation-4-size ] [ 0 ] set constellation-5-prev-avg ifelse-value (constellation-5-size > 0) [ total-prev-c5 / constellation-5-size ] [ 0 ] end to compute-constellation-stats let var-op-c1 0 let var-op-c2 0 let var-op-c3 0 let var-op-c4 0 let var-op-c5 0 ask turtles [ let const get-constellation self if const = 1 [ set var-op-c1 var-op-c1 + ((opinion - constellation-1-opinion-avg) ^ 2) ] if const = 2 [ set var-op-c2 var-op-c2 + ((opinion - constellation-2-opinion-avg) ^ 2) ] if const = 3 [ set var-op-c3 var-op-c3 + ((opinion - constellation-3-opinion-avg) ^ 2) ] if const = 4 [ set var-op-c4 var-op-c4 + ((opinion - constellation-4-opinion-avg) ^ 2) ] if const = 5 [ set var-op-c5 var-op-c5 + ((opinion - constellation-5-opinion-avg) ^ 2) ] ] set constellation-1-polarization ifelse-value (constellation-1-size > 1) [ sqrt (var-op-c1 / constellation-1-size) ] [ 0 ] set constellation-2-polarization ifelse-value (constellation-2-size > 1) [ sqrt (var-op-c2 / constellation-2-size) ] [ 0 ] set constellation-3-polarization ifelse-value (constellation-3-size > 1) [ sqrt (var-op-c3 / constellation-3-size) ] [ 0 ] set constellation-4-polarization ifelse-value (constellation-4-size > 1) [ sqrt (var-op-c4 / constellation-4-size) ] [ 0 ] set constellation-5-polarization ifelse-value (constellation-5-size > 1) [ sqrt (var-op-c5 / constellation-5-size) ] [ 0 ] end to-report get-constellation [agent] let op [opinion] of agent let prev [prevalence] of agent if op < (- c-opinion-extreme) and prev >= c-prevalence-high [ report 1 ] if op < (- c-opinion-moderate) and op >= (- c-opinion-extreme) [ report 2 ] if op >= (- c-opinion-moderate) and op <= c-opinion-moderate [ report 3 ] if op > c-opinion-moderate and op <= c-opinion-extreme [ report 4 ] if op > c-opinion-extreme and prev >= c-prevalence-high [ report 5 ] if op < 0 [ report 2 ] if op > 0 [ report 4 ] report 3 end to compute-turnover let changes 0 let changes-c1 0 let changes-c2 0 let changes-c3 0 let changes-c4 0 let changes-c5 0 let prev-size-c1 0 let prev-size-c2 0 let prev-size-c3 0 let prev-size-c4 0 let prev-size-c5 0 ask turtles [ let current-const get-constellation self let prev-const constellation-prev if prev-const > 0 [ if prev-const != current-const [ set changes changes + 1 if prev-const = 1 [ set changes-c1 changes-c1 + 1 ] if prev-const = 2 [ set changes-c2 changes-c2 + 1 ] if prev-const = 3 [ set changes-c3 changes-c3 + 1 ] if prev-const = 4 [ set changes-c4 changes-c4 + 1 ] if prev-const = 5 [ set changes-c5 changes-c5 + 1 ] ] if prev-const = 1 [ set prev-size-c1 prev-size-c1 + 1 ] if prev-const = 2 [ set prev-size-c2 prev-size-c2 + 1 ] if prev-const = 3 [ set prev-size-c3 prev-size-c3 + 1 ] if prev-const = 4 [ set prev-size-c4 prev-size-c4 + 1 ] if prev-const = 5 [ set prev-size-c5 prev-size-c5 + 1 ] ] ] set turnover-global ifelse-value (pop > 0) [ 100 * changes / pop ] [ 0 ] set turnover-c1 ifelse-value (prev-size-c1 > 0) [ 100 * changes-c1 / prev-size-c1 ] [ 0 ] set turnover-c2 ifelse-value (prev-size-c2 > 0) [ 100 * changes-c2 / prev-size-c2 ] [ 0 ] set turnover-c3 ifelse-value (prev-size-c3 > 0) [ 100 * changes-c3 / prev-size-c3 ] [ 0 ] set turnover-c4 ifelse-value (prev-size-c4 > 0) [ 100 * changes-c4 / prev-size-c4 ] [ 0 ] set turnover-c5 ifelse-value (prev-size-c5 > 0) [ 100 * changes-c5 / prev-size-c5 ] [ 0 ] end to compute-entropy let bins (list -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0) let counts [] let i 0 while [i < 20] [ let lower item i bins let upper item (i + 1) bins let in-bin count turtles with [opinion >= lower and opinion < upper] set counts lput in-bin counts set i i + 1 ] let last-bin item 20 bins let in-last count turtles with [opinion >= last-bin] set counts replace-item 19 counts (in-last) let total-pop pop let entropy 0 foreach counts [ c -> if c > 0 [ let p c / total-pop set entropy entropy - (p * log p 2) ] ] set opinion-entropy entropy end to compute-volatility let center-opinion ifelse-value (constellation-3-size > 0) [ constellation-3-opinion-avg ] [ 0 ] if ticks > 1 [ let delta abs (center-opinion - last-center-opinion) set center-volatility 0.3 * delta + 0.7 * center-volatility ] set last-center-opinion center-opinion end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; FRACTAL DIMENSIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to capture-network-snapshot if ticks mod 50 = 0 [ let snapshot get-current-network set network-snapshots lput (list ticks snapshot) network-snapshots if length network-snapshots > 20 [ set network-snapshots but-first network-snapshots ] ] end to-report get-current-network let edges [] ask links [ set edges lput (list [who] of end1 [who] of end2) edges ] report edges end to compute-fractal-dimensions set topological-dimension compute-topological-dimension set dynamic-dimension compute-dynamic-dimension if topological-dimension > 0 [ set criticality-gap abs(dynamic-dimension - topological-dimension) / topological-dimension ] if ticks mod 500 = 0 [ output-print (word "Ticks: " ticks " | D_top: " topological-dimension " | D_dyn: " dynamic-dimension " | Gap: " criticality-gap) ] end to-report compute-topological-dimension let edges get-current-network if length edges < 10 [ report 0 ] let results [] foreach box-sizes [ r -> let box-radius max list 1 (round (r * pop / 10)) let unvisited sort [who] of turtles let n-boxes 0 while [not empty? unvisited] [ let seed first unvisited let in-box [who] of bfs-reachable (turtle seed) box-radius set unvisited filter [ [x] -> not member? x in-box ] unvisited set n-boxes n-boxes + 1 ] set results lput (list (ln (1 / r)) (ln n-boxes)) results ] report regression-slope results end to-report bfs-reachable [start-node max-dist] if start-node = nobody [ report no-turtles ] let visited (turtle-set start-node) let frontier (turtle-set start-node) let dist 0 while [dist < max-dist and any? frontier] [ let new-frontier (turtle-set) ask frontier [ let neighbors-set link-neighbors set new-frontier (turtle-set new-frontier neighbors-set) ] set visited (turtle-set visited new-frontier) set frontier new-frontier set dist dist + 1 ] report visited end to-report compute-dynamic-dimension if length cascade-sizes < 100 [ report 0 ] let sizes [] let current-cascade 0 let current-size 0 let sorted-cascades sort-by [ [a b] -> item 3 a < item 3 b ] cascade-sizes foreach sorted-cascades [ evt -> let cid item 3 evt ifelse cid != current-cascade [ if current-size > 0 [ set sizes lput current-size sizes ] set current-cascade cid set current-size 1 ] [ set current-size current-size + 1 ] ] if current-size > 0 [ set sizes lput current-size sizes ] set sizes filter [x -> x > 1] sizes if length sizes < 20 [ report 0 ] let unique-sizes remove-duplicates sort sizes let ccdf [] foreach unique-sizes [ s -> let count-greater length filter [x -> x >= s] sizes if count-greater > 0 [ set ccdf lput (list (ln s) (ln count-greater)) ccdf ] ] if length ccdf < 5 [ report 0 ] let slope regression-slope ccdf if slope < -10 or slope > 10 [ report 0 ] report abs slope end to-report regression-slope [points] let n length points if n < 2 [ report 0 ] let sum-x 0 let sum-y 0 let sum-xy 0 let sum-x2 0 foreach points [ p -> let x item 0 p let y item 1 p set sum-x sum-x + x set sum-y sum-y + y set sum-xy sum-xy + x * y set sum-x2 sum-x2 + x * x ] let slope (n * sum-xy - sum-x * sum-y) / (n * sum-x2 - sum-x * sum-x) report slope end to-report self-organization-evidence if length criticality-history < 10 [ report false ] let first-gap item 2 (item 0 criticality-history) let last-gap item 2 (item (length criticality-history - 1) criticality-history) report last-gap < first-gap * 0.7 end to-report system-status let f fractale let d_top topological-dimension let d_dyn dynamic-dimension let gap criticality-gap if d_top = 0 or d_dyn = 0 [ report "Initializing..." ] if gap < 0.2 [ if abs(f - d_dyn) < 0.3 [ if abs(f - d_top) < 0.3 [ report "🌟🌟 PERFECT CRITICALITY: structure, dynamics AND process aligned" ] report "⭐ DYNAMIC CRITICALITY: good process↔dynamics alignment" ] if abs(f - d_top) < 0.3 [ report "⭐ STRUCTURAL CRITICALITY: good process↔network alignment" ] report "⚡ CRITICALITY: structure and dynamics aligned, autonomous process" ] if gap < 0.5 [ if f > 1.5 [ report "🌀 EXPLORATION: complex process in moderately adapted structure" ] if f < 1 [ report "🌀 SIMPLICITY: linear process, structure adapting" ] report "🌀 INTERMEDIATE REGIME: system exploring possibility space" ] if d_dyn > d_top * 1.5 [ report "⚠️ DECOUPLING: dynamics richer than structure (check measurements)" ] if d_dyn < d_top * 0.5 [ report "⚠️ UNDERUTILIZATION: rich structure but little influence" ] report "⚠️ OUTSIDE CRITICALITY: structure and dynamics desynchronized" end to-report system-status-code let gap criticality-gap if gap < 0.2 [ report 3 ] if gap < 0.5 [ report 2 ] report 1 end to-report system-regime let f fractale let d_top topological-dimension let d_dyn dynamic-dimension let gap criticality-gap let turn turnover-global let entr opinion-entropy let volt center-volatility if d_top = 0 or d_dyn = 0 or ticks < 100 [ report "⚪ INITIALIZATION: System stabilizing, waiting for sufficient data" ] let f-high-threshold 1.6 let f-low-threshold 1.3 let gap-low-threshold 0.2 let gap-high-threshold 0.5 let turn-low-threshold 3.0 let turn-mod-high-threshold 8.0 let turn-high-threshold 15.0 let entr-low-threshold 2.5 let entr-high-threshold 3.5 let volt-low-threshold 0.2 let volt-mod-high-threshold 0.4 let volt-high-threshold 0.6 let f-qual ifelse-value (f >= f-high-threshold) [ "High" ] [ ifelse-value (f <= f-low-threshold) [ "Low" ] [ "Moderate" ] ] let gap-qual ifelse-value (gap <= gap-low-threshold) [ "Low" ] [ ifelse-value (gap >= gap-high-threshold) [ "High" ] [ "Moderate" ] ] let turn-qual ifelse-value (turn >= turn-high-threshold) [ "Very High" ] [ ifelse-value (turn >= turn-mod-high-threshold) [ "High" ] [ ifelse-value (turn >= turn-low-threshold) [ "Moderate" ] [ "Low" ] ] ] let entr-qual ifelse-value (entr >= entr-high-threshold) [ "High" ] [ ifelse-value (entr <= entr-low-threshold) [ "Low" ] [ "Moderate" ] ] let volt-qual ifelse-value (volt >= volt-high-threshold) [ "Very High" ] [ ifelse-value (volt >= volt-mod-high-threshold) [ "High" ] [ ifelse-value (volt >= volt-low-threshold) [ "Moderate" ] [ "Low" ] ] ] if (f-qual = "High") and (gap-qual = "Low") and (turn-qual = "Moderate") and (entr-qual = "High") and (volt-qual = "Moderate") [ report (word "🌟 EMERGENT CRITICAL: " "System at the edge of chaos, rich and diverse, ideal for social innovation " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] if (f-qual = "High") and (gap-qual = "Low") and (turn-qual = "Low") and (entr-qual = "Moderate") and (volt-qual = "Low") [ report (word "🏛️ MATURE STRUCTURED: " "Crystallized complexity, well-organized but inflexible society " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] if (f-qual = "High") and (gap-qual = "High") and (turn-qual = "High" or turn-qual = "Very High") and (entr-qual = "High") and (volt-qual = "High" or volt-qual = "Very High") [ report (word "🌪️ TURBULENT: " "Rich but disorganized, risk of collapse or transition " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] if (f-qual = "Low") and (gap-qual = "Low") and (turn-qual = "Low") and (entr-qual = "Low") and (volt-qual = "Low") [ report (word "🧊 GLACIAL: " "Frozen system, total consensus, absence of dynamics " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] if (f-qual = "Moderate") and (gap-qual = "Moderate") and (turn-qual = "High") and (entr-qual = "Moderate") and (volt-qual = "High" or volt-qual = "Very High") [ report (word "🔥 PRE-ERUPTIVE: " "Highly volatile center, warning signs of tipping " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] if (turn-qual = "Very High") and (volt-qual = "Very High") [ report (word "💥 EXPLOSIVE: " "Crisis underway, everything changing rapidly " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") ] report (word "🔄 MIXED REGIME: System in transition or intermediate state " "[Fractal: " f-qual ", Criticality: " gap-qual ", Turnover: " turn-qual ", Entropy: " entr-qual ", Volatility: " volt-qual "]") end to-report system-regime-code let f fractale let d_top topological-dimension let d_dyn dynamic-dimension let gap criticality-gap let turn turnover-global let entr opinion-entropy let volt center-volatility if d_top = 0 or d_dyn = 0 or ticks < 100 [ report 0 ] let f-high 1.6 let f-low 1.3 let gap-low 0.2 let gap-high 0.5 let turn-mod 3.0 let turn-high 8.0 let turn-vhigh 15.0 let entr-low 2.5 let entr-high 3.5 let volt-mod 0.2 let volt-high 0.4 let volt-vhigh 0.6 if (f >= f-high) and (gap <= gap-low) and (turn >= turn-mod and turn < turn-high) and (entr >= entr-high) and (volt >= volt-mod and volt < volt-high) [ report 1 ] if (f >= f-high) and (gap <= gap-low) and (turn < turn-mod) and (entr >= entr-low and entr < entr-high) and (volt < volt-mod) [ report 2 ] if (f >= f-high) and (gap >= gap-high) and (turn >= turn-high) and (entr >= entr-high) and (volt >= volt-high) [ report 3 ] if (f <= f-low) and (gap <= gap-low) and (turn < turn-mod) and (entr <= entr-low) and (volt < volt-mod) [ report 4 ] if (f > f-low and f < f-high) and (gap > gap-low and gap < gap-high) and (turn >= turn-high) and (entr > entr-low and entr < entr-high) and (volt >= volt-high) [ report 5 ] if (turn >= turn-vhigh) and (volt >= volt-vhigh) [ report 6 ] report 0 end to calibrate-regime-thresholds output-print "==================================================" output-print "Current regime thresholds:" output-print (word "Fractal High: " 1.6 " | Low: " 1.3) output-print (word "Criticality Gap Low: " 0.2 " | High: " 0.5) output-print (word "Turnover Low: " 3.0 "% | Mod-High: " 8.0 "% | High: " 15.0 "%") output-print (word "Entropy Low: " 2.5 " | High: " 3.5) output-print (word "Volatility Low: " 0.2 " | Mod-High: " 0.4 " | High: " 0.6) output-print "==================================================" output-print "To modify thresholds, edit the values in system-regime procedure" end to diagnose-system output-print "==================================================" output-print (word "SYSTEM DIAGNOSIS at tick " ticks) output-print "==================================================" output-print system-regime output-print "" output-print "--- Detailed Values ---" output-print (word "Fractal: " fractale) output-print (word "Topological Dim: " topological-dimension) output-print (word "Dynamic Dim: " dynamic-dimension) output-print (word "Criticality Gap: " criticality-gap) output-print (word "Global Turnover: " turnover-global "%") output-print (word "Opinion Entropy: " opinion-entropy) output-print (word "Center Volatility: " center-volatility) output-print (word "Lyapunov Exponent: " lyapunov-exponent) output-print "" output-print "--- Constellation Sizes ---" output-print (word "C1 (Left Radicals): " constellation-1-size) output-print (word "C2 (Left Moderates): " constellation-2-size) output-print (word "C3 (Center): " constellation-3-size) output-print (word "C4 (Right Moderates): " constellation-4-size) output-print (word "C5 (Right Radicals): " constellation-5-size) output-print "==================================================" end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LYAPUNOV PROCEDURES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to compute-lyapunov-exponent let n length divergence-history if n < 10 [ stop ] let points [] foreach divergence-history [ d -> set points lput (list (ln (item 0 d)) (ln (item 1 d))) points ] set lyapunov-exponent regression-slope points end to initialize-perturbation set reference-trajectory [] set perturbed-trajectory [] let ref-state [] ask turtles [ set ref-state lput (list who opinion prevalence influence) ref-state ] set reference-trajectory lput (list ticks ref-state) reference-trajectory ask turtles [ set opinion opinion + random-float 2e-6 - 1e-6 set opinion max list -1 min list 1 opinion ] let pert-state [] ask turtles [ set pert-state lput (list who opinion prevalence influence) pert-state ] set perturbed-trajectory lput (list ticks pert-state) perturbed-trajectory end to update-perturbation if length reference-trajectory = 0 [ stop ] let last-ref last reference-trajectory let last-pert last perturbed-trajectory let divergence 0 let n 0 foreach (item 1 last-ref) [ ref-state -> let who-ref item 0 ref-state let match filter [p -> item 0 p = who-ref] (item 1 last-pert) if not empty? match [ let pert-state first match let d-opinion (item 1 ref-state) - (item 1 pert-state) let d-prevalence (item 2 ref-state) - (item 2 pert-state) let d-influence (item 3 ref-state) - (item 3 pert-state) set divergence divergence + (d-opinion ^ 2 + d-prevalence ^ 2 + d-influence ^ 2) set n n + 1 ] ] if n > 0 [ set divergence sqrt (divergence / n) if divergence = 0 [ set divergence 0.0000001 ] set divergence-history lput (list ticks divergence) divergence-history if ticks mod 10 = 0 [ rescale-perturbation ] ] let new-ref [] let new-pert [] ask turtles [ set new-ref lput (list who opinion prevalence influence) new-ref ] ask turtles [ set new-pert lput (list who opinion prevalence influence) new-pert ] set reference-trajectory lput (list ticks new-ref) reference-trajectory set perturbed-trajectory lput (list ticks new-pert) perturbed-trajectory if length reference-trajectory > 100 [ set reference-trajectory but-first reference-trajectory set perturbed-trajectory but-first perturbed-trajectory ] end to rescale-perturbation if length reference-trajectory = 0 [ stop ] let last-ref last reference-trajectory ask turtles [ let my-ref filter [p -> item 0 p = who] (item 1 last-ref) if not empty? my-ref [ let ref-state first my-ref let d-opinion opinion - (item 1 ref-state) let d-prevalence prevalence - (item 2 ref-state) let d-influence influence - (item 3 ref-state) let scale 0.01 set opinion (item 1 ref-state) + d-opinion * scale set prevalence (item 2 ref-state) + d-prevalence * scale set influence (item 3 ref-state) + d-influence * scale set opinion max list -1 min list 1 opinion set prevalence max list 0 min list 99 prevalence set influence max list 0 min list 1 influence ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; VALUES OUTPUT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to compute-statistics if output = "Values" [ output-print join-cols (list fmt try fmt ticks fmt who fmt prevalence fmt opinion fmt influence fmt meme-plus fmt meme-minus fmt meme-plus-w fmt meme-minus-w ) ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; COLORING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to colorer ask turtles [ ifelse meta? [ set color yellow set influence 1] [ ifelse opinion >= 0 [ set color blue ] [ set color red ] ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; NETWORK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to update-networks let doomed links with [ abs([opinion] of end1 - [opinion] of end2) > (link-removal-threshold / 100) ] let doomedProb doomed with [ random-float 1 < prob ] let n-remove min (list linksdown count doomedProb) if n-remove > 0 [ ask n-of n-remove doomedProb [ die ] set links-dead links-dead + n-remove ] let j linksup while [j > 0] [ let t one-of turtles if t = nobody [ stop ] ask t [ let myop opinion let candidates other turtles with [ not link-neighbor? myself ] let pool-homo candidates with [ abs(opinion - myop) < (link-formation-threshold / 100) ] let pool-bridge candidates with [ (sign opinion) != (sign myop) ] let friend nobody if any? pool-bridge and (random-float 1 < bridge-prob) [ set friend max-one-of pool-bridge [ abs(opinion - myop) ] ] if (friend = nobody) and any? pool-homo [ set friend min-one-of pool-homo [ abs(opinion - myop) ] ] if friend != nobody and (random-float 1 < prob) [ create-link-with friend set links-create links-create + 1 let same-sign? (sign opinion) = (sign [opinion] of friend) ask link-with friend [ set color (ifelse-value same-sign? [ green ] [ gray ]) set thickness linktick if show-links [ show-link ] ] ] ] set j j - 1 ] ask turtles with [ influence >= 1 and meta-type = "none" ] [ set meta-type "dynamic" set color yellow ] end to meta if not network [ stop ] ask turtles with [meta-type = "structural"] [ ;; déterminer le mode actuel selon la probabilité let mode meta-mode-auto ;; choisir si on cible un méta ou un non-méta let choose-meta? ifelse-value (mode = "non-meta") [ false ] ;; déterministe : méta → non-méta [ ifelse-value (mode = "meta") [ true ] ;; déterministe : méta → méta [ random-float 1 < meta-link-prob ] ;; probabiliste : mixte ] ;; construire le pool selon le choix let pool other turtles with [ (ifelse-value choose-meta? [ color = yellow ] ;; méta → méta [ color != yellow ] ;; méta → non-méta ) and not link-neighbor? myself and (count link-neighbors) < meta-links ] ;; créer le lien si possible if any? pool [ let friend one-of pool create-link-with friend let same-sign? (sign opinion) = (sign [opinion] of friend) ask link-with friend [ set color (ifelse-value same-sign? [ green ] [ gray ]) set thickness linktick if show-links [ show-link ] ] ] ] end to-report meta-mode-auto if meta-link-prob = 0 [ report "non-meta" ] if meta-link-prob = 1 [ report "meta" ] report "mixed" end to apply-link-visibility ifelse show-links [ ask links [ show-link ] ] [ ask links [ hide-link ] ] end to recolor-links ask links [ let s1 sign [opinion] of end1 let s2 sign [opinion] of end2 ifelse s1 = s2 [ set color green ] [ set color gray ] set thickness linktick ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; EVENT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to event ask turtles [ let event-prob random-float 1 if event-prob <= event-prob-max [ ifelse meme_set = true [ if (to_left = false) [ if agent-type = "Right side" [ if opinion < 0 [ maybe-set-opinion (opinion + event_size) ] ] ] if (to_left = true) [ if agent-type = "Left side" [ if opinion > 0 [ maybe-set-opinion (opinion - event_size) ] ] ] ] [ if (to_left = false) [ if (opinion < high_meme and opinion > low_meme and prevalence < high-prev and prevalence > low-prev) [ maybe-set-opinion (opinion + event_size) if (prev_change != 0) [ set prevalence min (list max-prevalence (prevalence + prev_change)) ] ] ] if (to_left = true) [ if (opinion > low_meme and opinion < high_meme and prevalence > low-prev and prevalence < high-prev) [ maybe-set-opinion (opinion - event_size) if (prev_change != 0) [ set prevalence min (list max-prevalence (prevalence + prev_change)) ] ] ] ] if use-memes? and event-meme-change? [ init-memes-from-state ] ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; MISCELLANEOUS UTILITIES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to set-background-black ask patches [ set pcolor black ] end to update-3d [agt] ask agt [ set x3d opinion * 16 set y3d prevalence / 6 set z3d influence * 16 setxyz x3d y3d z3d ] end to-report safe-median [agentset varname] if not any? agentset [ report 0 ] report median [ runresult varname ] of agentset end to-report sign [x] ifelse x > 0 [ report 1 ] [ ifelse x < 0 [ report -1 ] [ report 0 ] ] end to-report meme-saturation-pct if not use-memes? [ report 0 ] if not any? turtles [ report 0 ] let total-memes sum [meme-plus + meme-minus] of turtles let capacity meme-max * count turtles if capacity <= 0 [ report 0 ] report 100 * total-memes / capacity end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GROUP IMPACT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to-report group-alignment-all [agt sign-ref] let nbrs [link-neighbors] of agt if not any? nbrs [ report 0.5 ] let same count nbrs with [ (sign opinion) = sign-ref ] report same / count nbrs end to-report group-alignment-k [agt sign-ref k] let nbrs [link-neighbors] of agt let deg count nbrs if deg = 0 [ report 0.5 ] let kk max list 1 min list deg floor k let agop [opinion] of agt let pool min-n-of kk nbrs [ abs(opinion - agop) ] if not any? pool [ report 0.5 ] let same count pool with [ (sign opinion) = sign-ref ] report same / count pool end to-report group-alignment-effective [agt sign-ref] ifelse (group-impact-mode = "k-nearest") [ report group-alignment-k agt sign-ref group-k ] [ report group-alignment-all agt sign-ref ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; MEMES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to-report initial-prevalence-to-memes [prev] report (prev / 99) * meme-max end to init-memes-from-state let totq initial-prevalence-to-memes prevalence ifelse opinion >= 0 [ set meme-plus totq * (0.5 + 0.5 * abs opinion) set meme-minus totq - meme-plus ] [ set meme-minus totq * (0.5 + 0.5 * abs opinion) set meme-plus totq - meme-minus ] set meme-plus-w meme-plus * meme-weight-mean set meme-minus-w meme-minus * meme-weight-mean if meme-plus < 0 [ set meme-plus 0 ] if meme-minus < 0 [ set meme-minus 0 ] if meme-plus-w < 0 [ set meme-plus-w 0 ] if meme-minus-w < 0 [ set meme-minus-w 0 ] end to-report draw-meme-weight let w meme-weight-mean if meme-weight-sd > 0 [ set w (meme-weight-mean + (random-float (2 * meme-weight-sd) - meme-weight-sd)) ] if w < meme-weight-min [ set w meme-weight-min ] if w > meme-weight-max [ set w meme-weight-max ] report w end to recompute-from-memes let totw meme-plus-w + meme-minus-w if totw < 1e-6 [ set totw 1e-6 ] set proposed-opinion ((meme-plus-w - meme-minus-w) / totw) maybe-set-opinion proposed-opinion let totq meme-plus + meme-minus let scaled (totq / meme-max) * 99 if scaled < 0 [ set scaled 0 ] if scaled > 99 [ set scaled 99 ] set prevalence scaled end to decay-memes if meme-decay <= 0 [ stop ] let f (1 - meme-decay) set meme-plus max list 0 (meme-plus * f) set meme-minus max list 0 (meme-minus * f) set meme-plus-w max list 0 (meme-plus-w * f) set meme-minus-w max list 0 (meme-minus-w * f) end to transmit-memes [emitter] let sgn sign ([opinion] of emitter) let w draw-meme-weight let leak (meme-anti-leak * meme-gain) ifelse sgn >= 0 [ set meme-plus meme-plus + meme-gain set meme-plus-w meme-plus-w + (w * meme-gain) set meme-minus max list 0 (meme-minus - leak) set meme-minus-w max list 0 (meme-minus-w - (w * leak)) ] [ set meme-minus meme-minus + meme-gain set meme-minus-w meme-minus-w + (w * meme-gain) set meme-plus max list 0 (meme-plus - leak) set meme-plus-w max list 0 (meme-plus-w - (w * leak)) ] let totq meme-plus + meme-minus if totq > meme-max [ let factor meme-max / totq set meme-plus meme-plus * factor set meme-minus meme-minus * factor set meme-plus-w meme-plus-w * factor set meme-minus-w meme-minus-w * factor ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; INJECTION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to inject-memes let base-pool turtles with [ opinion >= inject-low_meme and opinion <= inject-high_meme and prevalence >= inject-low-prev and prevalence <= inject-high-prev ] let pool base-pool if inject-metas-only [ set pool base-pool with [ color = yellow ] ] ask pool [ if random-float 1 <= inject-prob-max [ let w inject-weight if w < meme-weight-min [ set w meme-weight-min ] if w > meme-weight-max [ set w meme-weight-max ] if inject-amount < 0 [ stop ] if inject-sign = "plus" [ set meme-plus meme-plus + inject-amount set meme-plus-w meme-plus-w + (w * inject-amount) ] if inject-sign = "minus" [ set meme-minus meme-minus + inject-amount set meme-minus-w meme-minus-w + (w * inject-amount) ] let totq meme-plus + meme-minus if totq > meme-max [ let factor meme-max / totq set meme-plus meme-plus * factor set meme-minus meme-minus * factor set meme-plus-w meme-plus-w * factor set meme-minus-w meme-minus-w * factor ] if use-memes? [ recompute-from-memes ] ] ] end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Additional reporters ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to-report mean-polarity-index let total-plus sum [meme-plus] of turtles let total-minus sum [meme-minus] of turtles ifelse (total-plus + total-minus > 0) [ report (total-plus - total-minus) / (total-plus + total-minus) ] [ report 0 ] end to-report ideologization-meme-based if not any? turtles [ report 0 ] report mean [ (abs (meme-plus - meme-minus) / 100) ] of turtles end to-report ideologization-opinion-based if not any? turtles [ report 0 ] report mean [ (abs opinion) * (prevalence / 99) ] of turtles end
There is only one version of this model, created 14 days ago by Pierre-Alain Cotnoir.
Attached files
No files
Download this model