Abstract
In November 2024 we published a simulation of how anxiety and addiction reinforce each other. It used five variables (anxiety, addiction, dopamine, serotonin and tolerance) and a list of hand-set life events, and it concluded that breaking points often lead to recovery. An audit of the published code shows that recovery is guaranteed by design: once anxiety reaches 85, a scripted “breaking point” event lowers it by 25 to 35 points. In 50 seeded runs of 3,000 steps, 70% of the 1,369 threshold crossings ended this way, after a median of 6 steps and never more than 39. With the rule switched off, the same model spends 47% of its time above the threshold. Two of the five variables never influence the others, and the labels “dopamine = pleasure” and “serotonin = wellbeing” do not reflect current evidence. We restate the model as stocks and flows with explicit feedback loops, replace forced recovery with a balancing loop that can fail, and pre-specify a test for early-warning signals, rising variance and autocorrelation, before regime shifts. The same method applies to operational and KPI time series. This paper is not medical advice.
Zusammenfassung
Im November 2024 haben wir eine Simulation veröffentlicht, die zeigen sollte, wie sich Angst und Sucht gegenseitig verstärken. Sie arbeitete mit fünf Variablen (Angst, Sucht, Dopamin, Serotonin, Toleranz) und einer Liste von Lebensereignissen mit festgelegten Wirkungen und kam zu dem Schluss, dass Krisenpunkte oft zur Genesung führen. Der veröffentlichte Code zeigt jedoch, dass die Genesung fest eingebaut ist. Sobald die Angst den Wert 85 erreicht, senkt ein fest programmiertes Ereignis sie um 25 bis 35 Punkte. In 50 Läufen mit festen Seeds und je 3.000 Schritten endeten 70 % der 1.369 Schwellenüberschreitungen auf diese Weise, im Median nach 6 Schritten und nie später als nach 39. Ohne diese Regel verbringt dasselbe Modell 47 % der Zeit oberhalb der Schwelle. Zwei der fünf Variablen beeinflussen die übrigen nie, und die Gleichsetzungen „Dopamin = Vergnügen“ und „Serotonin = Wohlbefinden“ entsprechen nicht dem Stand der Forschung. Wir formulieren das Modell als Bestände und Flüsse mit ausdrücklich benannten Rückkopplungen und ersetzen die erzwungene Genesung durch eine ausgleichende Schleife, die auch versagen kann. Außerdem legen wir vorab einen Test auf Frühwarnsignale fest, nämlich auf steigende Varianz und Autokorrelation vor einem Regimewechsel. Dieselbe Methode lässt sich auf Betriebs- und KPI-Zeitreihen anwenden. Dieser Beitrag ist keine medizinische Beratung.
1. A model in which every crisis ends well
The 2024 post ended on hope. It said that even entrenched cycles of anxiety and addiction can shift, and that breaking points, “while painful, often create the conditions necessary for lasting change”. The simulation seemed to show it: anxiety climbed, crossed a red dashed line, the status switched to “Recovery Phase”, a green band appeared on the chart and the curves came down.
They came down because line 108 of the code told them to. We wrote a model in which every crisis resolves, ran it, and reported that crises resolve. This paper takes that apart, keeps the structure that was worth having, and replaces the scripted ending with a question that can come out either way: does this kind of system give warning before it tips?
2. The original model
The code is a single Python file of 676 lines with a Tkinter interface. Five numbers between 0 and 100 change each step: anxiety (start 20), addiction (30), dopamine (50), serotonin (50) and tolerance (10). Twenty life events, ten negative and ten positive, move them by fixed amounts. A job loss, for example, adds 25 to anxiety and 15 to addiction and subtracts 10 from dopamine and 15 from serotonin. Events fire at random, more often and more negatively when anxiety is high. On top of that sit a handful of threshold rules, applied every third step: addiction above 50 raises anxiety, anxiety above 60 sometimes triggers “use” that raises addiction and briefly lowers anxiety, anxiety above 70 erodes serotonin, serotonin above 60 lowers anxiety. Every number in these rules was chosen by us. None comes from data or literature.
3. Audit
3.1 Recovery by design
Two separate code paths turn high anxiety into recovery:
# addiction_anxiety_simulation.py (commit 7f0efeb)
anxiety_threshold = 85 # breaking point threshold (line 64)
recovery_events = [ # (lines 52-56)
{"name": "Breaking point: Seeking help", "anxiety": -30, "addiction": -25, ...},
{"name": "Breaking point: Lifestyle change", "anxiety": -35, "addiction": -30, ...},
{"name": "Breaking point: Support system", "anxiety": -25, "addiction": -20, ...}
]
# Path 1, inside trigger_life_event(), lines 106-109
if anxiety_level > anxiety_threshold and not in_recovery_phase:
# Trigger a recovery event at breaking point
event = random.choice(recovery_events)
enter_recovery_phase()
# Path 2, inside update_simulation(), lines 258-261, checked every third step
if anxiety_level >= anxiety_threshold and not in_recovery_phase and random.random() < 0.2:
# Trigger a recovery event
trigger_life_event(forced_event=random.choice(recovery_events))
Path 1 fires whenever a random life event comes due while anxiety is above 85, and it also starts a 60-step recovery phase in which negative events become rarer. Path 2 gives a 20% chance every third step. Either way, staying above the threshold for long is close to impossible.
To see how much of the model's behaviour this explains, we ran the published code headless, without the interface, for 50 seeds of 3,000 steps each. We then ran it again with the threshold set to 101, which anxiety can never reach because it is capped at 100. That switches both paths off and leaves everything else unchanged.
| Measure (50 runs × 3,000 steps) | Breaking-point rule on | Rule off |
|---|---|---|
| Upward crossings of 85 | 1,369 | not counted |
| Crossings ended by a scripted “Breaking point” event | 953 (70%) | 0 |
| Steps from crossing to that event: median, 90th percentile, maximum | 6, 17, 39 | n/a |
| Share of steps with anxiety ≥ 85, second half of each run (mean, range) | 6.5% (0.9-13.4%) | 46.9% (29.0-62.0%) |
| Mean anxiety, second half (mean, range) | 40.0 (19.3-60.6) | 80.1 (69.8-85.8) |
The remaining 30% of crossings fell back below 85 through random fluctuation or a positive event before the scripted event arrived. Without the rule, nothing in the model pulls anxiety back down for long: it spends almost half its time above the line and averages 80. The reinforcing rules dominate. The hopeful ending was a constant we typed in.
3.2 Two decorative variables
Dopamine rises with “use” and falls with tolerance. Tolerance rises when addiction is high. Neither is ever read by any rule that changes anxiety, addiction or serotonin. Delete both and the rules governing the other three variables stay exactly as they are. They were drawn on the chart and written up as neurochemistry, but they had no causal role in the simulation.
3.3 The neurochemistry labels
The post called dopamine “pleasure”. That reading has been out of date for three decades. Robinson and Berridge's incentive-sensitisation theory holds that mesolimbic dopamine mediates incentive salience, the “wanting” of a reward, rather than its hedonic impact, the “liking”, and that in addiction the wanting can grow while the liking does not [1]. Koob and Volkow describe addiction as a recurring cycle of three stages, binge and intoxication, withdrawal and negative affect, and preoccupation and anticipation, involving reward, stress and executive-control circuits [2]. A single gauge labelled pleasure is the wrong abstraction, and in this code it did nothing anyway.
The post called serotonin “wellbeing”. An umbrella review by Moncrieff and colleagues found no consistent evidence for an association between serotonin and depression [3]. That review has its critics, and the debate is not settled. Under any reading of it, one serotonin number standing for wellbeing is not defensible.
3.4 Rock bottom
The model encodes the idea that people recover after hitting bottom. The idea is common in recovery culture, but it has rarely been measured. Kirouac and Witkiewitz note that “hitting bottom” had not been formally operationalised before their own work, in which they developed a questionnaire to capture it [4]. A concept that research is still learning how to define should not be a law of a model. If it belongs in a simulation at all, it belongs there as a hypothesis with a switch.
3.5 Smaller points
- The post said that being in recovery “reduces the probability of negative events by 40%”. The code subtracts 0.4 from a probability that lies between 0.3 and 0.8, with a floor of 0.1. That is 40 percentage points, which for a starting probability of 0.5 is a reduction of 80%.
- The post linked to a GitHub address that does not exist. The code is at the address given in section 7.
- The post invoked strange loops, the ouroboros, samsara and Heidegger. We have dropped them. They did not do any work the feedback loops could not do more precisely.
4. Restated as stocks and flows
System dynamics describes a system by its stocks, the quantities that accumulate, the flows that fill and drain them, and the feedback loops that connect the two [5]. Restating the toy this way makes its assumptions visible and shows where the original was open-ended.
| Stock | Filled by | Drained by | In the 2024 code |
|---|---|---|---|
| Anxiety A | Stressors; withdrawal pressure from dependence | Coping; short-term relief from use | anxiety_level |
| Dependence H | Use, which is driven by anxiety | Slow extinction when use stops; treatment | addiction_level |
| Tolerance T | Use | Slow decay | tolerance, but with no effect |
| Coping capacity C | Support, treatment, sleep, social contact | Erosion under sustained high anxiety | Roughly serotonin |
Four loops connect these stocks:
- R1, the relief trap. Anxiety drives use, which relieves anxiety in the short run. Use also builds dependence, and dependence feeds anxiety back through withdrawal. Balancing in the short run, reinforcing in the long run. The 2024 rules “anxiety above 60 triggers use” and “addiction above 50 raises anxiety” are this loop.
- R2, erosion. High anxiety wears down coping capacity, and lower capacity lets anxiety rise. The 2024 serotonin rules are this loop.
- R3, tolerance. Use builds tolerance, tolerance reduces relief per use, and lower relief drives more use. The 2024 code had the first link and dropped the rest.
- B1, coping. Coping capacity drains anxiety and, more slowly, dependence. Help-seeking belongs here: its likelihood should rise with anxiety and with remaining capacity, because asking for help takes some capacity. Nothing guarantees it fires.
The forced breaking point is gone. Recovery, if it happens, has to come from B1 winning against R1 and R2.
5. Proposed design: no forced recovery, and a test for early warning
5.1 The model
Four stocks updated in small time steps, with the loops above as flows, additive noise on anxiety, and exogenous stress as a slowly changing input. Life events stay, but as shocks of random size rather than a fixed menu. No parameter value is presented as calibrated. Every parameter is sampled from a stated range and the results are reported across the range.
# Proposed structure, not yet run. Parameter values are sampled, not fitted.
use = sensitivity(A, T) * A # anxiety-driven use, damped by tolerance
relief = relief_per_use / (1 + T) * use
dA = stress(t) + withdrawal * H - coping * C * A - relief + noise()
dH = use - extinction * H - treatment(A, C) * H
dT = build * use - decay * T
dC = support(t) - erosion * max(0, A - A_tolerable) * C
5.2 Questions, in order
- Are there tipping points at all? Sweep stress slowly up and then down and look for hysteresis, a range where the system can sit either in a low-anxiety or in a high-anxiety, high-dependence state. If there is none for any plausible parameter range, there is nothing to warn about, and we will report that.
- Do warnings appear before the shift? Near a fold, a system recovers more slowly from small disturbances. This critical slowing down shows up as rising variance and rising lag-1 autocorrelation in the fluctuations [6]. Van de Leemput and colleagues found that higher autocorrelation and variance in self-recorded emotions were associated with an upcoming shift into depression and out of it [7]. We test both directions.
- How often do they lie? Indicators of this kind have error rates that are seldom reported. We follow Boettiger and Hastings and estimate false alarms and missed warnings directly [8].
- Drift or shock? A large life event can push the system across without any slowing down beforehand. We expect warnings for transitions caused by slow drift in stress and none for transitions caused by single shocks, and we test that separately.
5.3 Method
At least 200 runs per condition with published seeds. A transition is a move into the high-anxiety basin that lasts for a fixed minimum time. For each transition we take the series before it, remove the trend with a Gaussian kernel, and compute variance and lag-1 autocorrelation in a rolling window of half the series length. The trend of each indicator is summarised by Kendall's tau, following the toolbox of Dakos and colleagues [9]. The same statistics are computed on matched runs at constant stress that do not tip. Performance is reported as a ROC curve and its area. Window sizes, bandwidths and the transition rule are fixed before the first run.
What would count as a result. An area under the ROC curve clearly above 0.5, with a confidence interval, for drift-driven transitions, and close to 0.5 for shock-driven ones, would support the use of these indicators in this class of model. Anything else is also a result, and we will publish it.
6. What this means for enterprises
Most operational systems are stocks and flows. A support backlog is a stock filled by new tickets and drained by resolved ones. When waits grow, customers chase their tickets and open new ones, which feeds the backlog: a reinforcing loop, held in check by staffing, a balancing loop. Error budgets, technical debt, payment failure queues and churn have the same shape. Drawing the stocks and loops on a whiteboard before building a dashboard clarifies which loop a given KPI is actually watching.
The early-warning idea carries over directly. As the balancing loop weakens, the system takes longer to settle after small disturbances: the backlog takes three days instead of one to return to normal after a spike, or p95 latency stays high for longer after each deploy. In the data, that shows up as rising autocorrelation and variance before anyone crosses a threshold. A practical recipe:
- Pick a series with a clear stock behind it (backlog, queue depth, open incidents) rather than a ratio of ratios.
- Remove trend and seasonality first. Weekly cycles and release calendars mimic the signal.
- Compute rolling variance and lag-1 autocorrelation and summarise their trend with Kendall's tau.
- Calibrate on history: how often would the alarm have fired with no incident afterwards, and how often did an incident arrive unannounced.
- Use the signal as a prompt to look, alongside ordinary thresholds, never as an automatic action.
Two limits apply. Shocks, such as a large customer leaving or a major outage, give no warning by this route. Not every kind of transition is preceded by slowing down. The method helps with slow erosion, which is exactly the kind of decline that threshold alerts tend to catch late.
7. Reproducibility
Code. github.com/kim266/addiction_anxiety_simulation, commit 7f0efeb (9 April 2025), which matches our archived copy. The 2024 post linked to addiction_anxiety_simulation_simulation, which returns a 404.
Audit. We copied the file to a separate folder and imported it as a module; the interface only starts when the file is run directly. For each seed (0 to 49) we reloaded the module to reset its global state, called random.seed(seed) and called update_simulation() 3,000 times, recording anxiety after each step and the name of every triggered event. “Rule off” sets anxiety_threshold = 101 before the first step. A crossing is a step on which anxiety moves from below 85 to 85 or above. It counts as ended by the rule if a “Breaking point” event fires before anxiety falls below 85 again. The second-half statistics use steps 1,500 to 3,000. The audit runs in about one second.
Not run. Nothing in sections 4 and 5 has been run. The restated model and the early-warning analysis will be published with code and seeds when they are.
References
- Robinson, T. E., & Berridge, K. C. (1993). The neural basis of drug craving: An incentive-sensitization theory of addiction. Brain Research Reviews, 18(3), 247-291. doi:10.1016/0165-0173(93)90013-P
- Koob, G. F., & Volkow, N. D. (2010). Neurocircuitry of addiction. Neuropsychopharmacology, 35(1), 217-238. doi:10.1038/npp.2009.110
- Moncrieff, J., Cooper, R. E., Stockmann, T., Amendola, S., Hengartner, M. P., & Horowitz, M. A. (2023). The serotonin theory of depression: A systematic umbrella review of the evidence. Molecular Psychiatry, 28(8), 3243-3256. Published online 2022. doi:10.1038/s41380-022-01661-0
- Kirouac, M., & Witkiewitz, K. (2017). Identifying “hitting bottom” among individuals with alcohol problems: Development and evaluation of the Noteworthy Aspects of Drinking Important to Recovery (NADIR). Substance Use & Misuse, 52(12), 1602-1615. doi:10.1080/10826084.2017.1293104
- Sterman, J. D. (2000). Business Dynamics: Systems Thinking and Modeling for a Complex World. Irwin/McGraw-Hill. ISBN 978-0-07-231135-8. mheducation.com
- Scheffer, M., Bascompte, J., Brock, W. A., Brovkin, V., Carpenter, S. R., Dakos, V., Held, H., van Nes, E. H., Rietkerk, M., & Sugihara, G. (2009). Early-warning signals for critical transitions. Nature, 461(7260), 53-59. doi:10.1038/nature08227
- van de Leemput, I. A., Wichers, M., Cramer, A. O. J., Borsboom, D., Tuerlinckx, F., Kuppens, P., et al. (2014). Critical slowing down as early warning for the onset and termination of depression. Proceedings of the National Academy of Sciences, 111(1), 87-92. doi:10.1073/pnas.1312114110
- Boettiger, C., & Hastings, A. (2012). Quantifying limits to detection of early warning for critical transitions. Journal of the Royal Society Interface, 9(75), 2527-2539. doi:10.1098/rsif.2012.0125
- Dakos, V., Carpenter, S. R., Brock, W. A., Ellison, A. M., Guttal, V., Ives, A. R., et al. (2012). Methods for detecting early warnings of critical transitions in time series illustrated using simulated ecological data. PLoS ONE, 7(7), e41010. doi:10.1371/journal.pone.0041010
Changelog
- “Understanding Addiction & Anxiety: A Neurological Cycle Simulation” published on the Senva blog.
- Code published on GitHub (commit
7f0efeb). - Rewritten as this Labs paper. Forced recovery documented with a seeded audit and removed from the proposed design. Neurochemistry labels corrected. Model restated as stocks and flows. Early-warning test pre-specified. Philosophical framing removed. Not-medical-advice note added. Status set to exploratory.

