Source papers
- Nguyen, Dinh & Tran (2026). Scaling Regenerative Supply Chains in Agriculture: An Integrated Framework of Digital MRV, Transition Finance and Socioecological Resilience. Systems Research and Behavioral Science. https://doi.org/10.1002/sres.70145
- Imtihan, Edinov & Suhaemi (2026). Analysis of 5R Waste Management on Green Economy using Causal Loop Diagram Model in West Sumatera. Indonesian J. Urban & Environmental Technology 9(2), 697–711. https://doi.org/10.25105/urbanenvirotech.v9i2.22457
Alert week: 2026-08-25 (see LITERATURE/2026-08-25.md, item H1).
Motivation
Nguyen et al. build a CLD with five reinforcing loops (R1–R5) and one balancing loop (B1), and their central result is not the loop inventory but the shift in loop dominance: B1 dominates the early transition phase, creating a temporal trap, before the reinforcing loops take over. Imtihan et al. likewise report a balancing loop (low public awareness) acting as the operative barrier.
find_loops() returns loops with reinforcing/balancing polarity as a flat, time-invariant list. It cannot answer "which loop is governing behaviour at step t?" — even though the linear-matrix iteration and Behaviour-Over-Time machinery needed to compute this already exist.
Proposal
Add loop_dominance(g, timesteps, weights=None) to sespy/network.py:
- For each loop from
find_loops(), compute loop gain as the product of signed edge weights around the cycle.
- Re-evaluate loop gain at each timestep of the existing linear-matrix iteration, using the current node-state-scaled edge contributions.
- Return a DataFrame indexed by (timestep x loop_id) with
gain, polarity, dominance_rank.
- Expose in the Loop Analysis module as an optional overlay annotating the Behaviour-Over-Time plot with the dominant loop per phase.
Related metric — ALC (in scope here, not a separate issue)
Adjusted Loop Centrality (Environmental Science & Policy 167:103996, 2026, https://doi.org/10.1016/j.envsci.2025.103996) weights a node by the loops it participates in — loop strength, and whether the node initiates or reinforces — instead of scoring nodes independently as the current z(betweenness)+z(eigenvector)+z(PageRank) composite does.
It is the node-side view of the same blind spot this issue attacks from the loop side, and it needs the same inputs: the find_loops() set plus per-node loop membership and a gain measure. Tracked here deliberately rather than as a rival issue — if loop_dominance() lands, emitting an ALC column alongside the per-timestep ranking should be nearly free.
Acceptance criteria
Effort: moderate.
Source papers
Alert week: 2026-08-25 (see
LITERATURE/2026-08-25.md, item H1).Motivation
Nguyen et al. build a CLD with five reinforcing loops (R1–R5) and one balancing loop (B1), and their central result is not the loop inventory but the shift in loop dominance: B1 dominates the early transition phase, creating a temporal trap, before the reinforcing loops take over. Imtihan et al. likewise report a balancing loop (low public awareness) acting as the operative barrier.
find_loops()returns loops with reinforcing/balancing polarity as a flat, time-invariant list. It cannot answer "which loop is governing behaviour at step t?" — even though the linear-matrix iteration and Behaviour-Over-Time machinery needed to compute this already exist.Proposal
Add
loop_dominance(g, timesteps, weights=None)tosespy/network.py:find_loops(), compute loop gain as the product of signed edge weights around the cycle.gain,polarity,dominance_rank.Related metric — ALC (in scope here, not a separate issue)
Adjusted Loop Centrality (Environmental Science & Policy 167:103996, 2026, https://doi.org/10.1016/j.envsci.2025.103996) weights a node by the loops it participates in — loop strength, and whether the node initiates or reinforces — instead of scoring nodes independently as the current
z(betweenness)+z(eigenvector)+z(PageRank)composite does.It is the node-side view of the same blind spot this issue attacks from the loop side, and it needs the same inputs: the
find_loops()set plus per-node loop membership and a gain measure. Tracked here deliberately rather than as a rival issue — ifloop_dominance()lands, emitting an ALC column alongside the per-timestep ranking should be nearly free.Acceptance criteria
Effort: moderate.