# The Epidemiology of a Cognitive Virus

> Source: <https://data4sci.substack.com/p/the-epidemiology-of-a-cognitive-virus>
> Published: 2026-09-21 20:16:21+00:00

In the latest epidemiology post, we are inspired by the release of the latest version of epidemik and a recent paper on “LLM addiction” to take a look at epidemic models with quadratic dependencies.

This is the latest in one of the epidemic modeling thread, the longest-running series in this publication. Feel free to take a look at previous posts as well:

Every post comes with an associated notebook that you can find in the

And of course don’t forget to

to be the first to get the next post, and please

and help us grow!

A few days ago I came across an arXiv preprint with a spicy title: *[Large-Language Models as a Cognitive Virus](https://arxiv.org/abs/2609.03344)*. It models our collective relationship with LLMs the way we’d model a disease. People move between not using them, using them casually, and being unable to function without them, complete with tipping points, runaway lock-in, and a prescribed “cognitive immunization.” 

As luck would have it, [version 0.2.0](https://pypi.org/project/epidemik) of `epidemik` has just been released, so why not play around with some fun ideas?

# A simplified model of dependence

The paper introduces a quadratic term to produce a [hysteresis](https://en.wikipedia.org/wiki/Hysteresis) curve. Here, we explore a simpler way to achieve the same effect.

Let us define a *small-ish* variation of the usual SIR model, with the three compartments defined by the authors: **Uncoupled** (U, doesn’t use LLMs, corresponding to the usual Susceptible compartment), **Coupled** (C, casual/occasional use, equivalent to **mildly*** Infectious*), and **Dependent** (D, persistent dependence, equivalent to ***very** Infectious*). Transitions between compartments differ from the usual SIR model, as we include 4 different effects:

- **Social transmission** (β): a non-user starts using through contact with a user.
- **Collective reinforcement** (α): a casual user becomes dependent through contact with the already-dependent. This is the central mechanism we’re studying: how dependence normalizes dependence.
- **Casual recovery** (γ): casual users drift away on their own.
- **Slow de-escalation** (δ): dependence decays only back to casual use, never straight to zero.

Graphically, we can represent the model as:

Which corresponds to a system of coupled ODEs:

Where lowercase letters correspond to population fractions. From these equations, we can already derive some interesting results.

## Long-Term Equilibrium

Let us start by exploring the dd/dt=0 equilibrium. There are two solutions to this equation:

- No dependents: d=0
- Internal equilibrium: c=c0 and d>0

If we assume that there are no Dependents, so that *d=0,* then we have:

which is just the usual *SIS* model. 

From these equations, we find the first threshold in our model. For the “disease” to be able to spread, we must have

or, equivalently:

giving us the first threshold. In other words, with D=0, if γ > β, people recover faster than they can get infected, and the disease dies out. However, if β > γ, we end up with an endemic state with:

## Dependent seeding

Now consider the opposite case, and assume we start with some dependents in the system, d>0. We still need that dd/dt>0, and this only happens if:

And we get, as the long term equilibrium state:

meaning we expect c to overshoot c<sub>0</sub> before coming back down.

## Epidemik Implementation

We can implement this model in `epidemik` in just a few lines of Python:

```
GAMMA, ALPHA, DELTA = 0.3, 1.0, 0.2   # baseline; c0 = delta/alpha = 0.2

def build_model(beta, alpha=ALPHA, gamma=GAMMA, delta=DELTA, seed=None, 
    dependent_recruit=False):
    m = EpiModel(compartments=["U", "C", "D"], seed=seed)
    m.add_interaction("U", "C", "C", beta=beta)          # casual users recruit
    if dependent_recruit:
        m.add_interaction("U", "C", "D", rate="beta")    # dependent users recruit too
    m.add_interaction("C", "D", "D", alpha=alpha)        # collective reinforcement
    m.add_spontaneous("C", "U", gamma=gamma)             # casual recovery
    m.add_spontaneous("D", "C", delta=delta)             # slow de-escalation

    return m
```

Where we also include the `dependent_recruit` flag in our utility model definition function.  `dependent_recruit` defines whether or not Dependent users recruit non-users. These two versions of the model will behave very differently. For now, let us focus on the case where dependents don’t recruit, `dependent_recruit=False.`

To run the model, we can just do:

```
GAMMA, ALPHA, DELTA = 0.3, 1.0, 0.2
N = 10_000

model=build_model(0.45, dependent_recruit=False)
print(model)
```

which outputs the structure of the model we just created:

```
# Epidemic Model with 3 compartments and 4 transitions:

Compartments: [U, C, D]

Parameters:
  beta: 0.45
  alpha: 1.0
  gamma: 0.3
  delta: 0.2

Transitions:
  - U + C = C beta
  - C + D = D alpha
  - C -> U gamma
  - D -> C delta

# R0=1.50
```

Now we can integrate the equations of this model with two different initial conditions:

```
m0 = build_model(beta, dependent_recruit=False)
m0.integrate(300, U=N - 20, C=10, D=0, )

m1 = build_model(beta, dependent_recruit=False)
m1.integrate(300, U=N - 20, C=10, D=10)
```

And compare the results. As expected, we see the impact that adding just a few dependents has on the course of the epidemic. While the population of *u* remains unaffected, the “infected” population is now split between the *Coupled* and the *Dependent.*

# Infectious Dependents

Now let us turn to the flat that lets dependents recruit. With the flat turned on, the shape of our model changes. For simplicity, we make the dependents recruit at the same rate, β, as the coupled. Relaxing this would give us another way to explore the model.

Mathematically, our equations also change, with one extra term in the *u* and *c* ODEs

This seemingly innocuous change makes a huge difference by adding a quadratic term. If you remember that *1=u+c+d*, then we can write:

At the first equilibrium point, when c=c<sub>0</sub> and dd/dt=0, we have, for the long term equilibrium:

Solving, we find:

which has two real solutions only when:

This quadratic equation is where the hysteresis comes from. We can observe it in epidemik by sweeping β up from zero and back down from the locked state. The first step is to define a function to calculate the equilibrium value for the various compartments:

``` python
def equilibrium(beta, U0, C0, D0, T=6000, **kw):
    m = build_model(beta, dependent_recruit=True, **kw)
    m.integrate(T, U=U0, C=C0, D=D0)
    eq = m.values_.iloc[-1]
    return eq
```

And then we can use it to compute the equilibrium values as we cycle over the values of β:

```
betas = np.linspace(0.16, 0.50, 35)

# Sweep up starting from the initial state
state = (N - 2, 1.0, 1.0)
forward = []
for b in betas:
    eq = equilibrium(b, *state)
    forward.append(eq["D"] / N)
    state = (max(eq["U"], 0.0), max(eq["C"], 1.0), max(eq["D"], 1.0))

# Sweep down starting from the locked state
state = (N * 0.1, N * 0.2, N * 0.7)
backward = []
for b in betas[::-1]:
    eq = equilibrium(b, *state)
    backward.append(eq["D"] / N)
    state = (max(eq["U"], 0.0), max(eq["C"], 1.0), max(eq["D"], 1.0))
backward = backward[::-1]
```

# The hysteresis curve

Now we can plot the equilibrium-dependent fraction as a function of β, as β increases and then decreases, and compare it with our analytical solutions above.

In the figure above, we also plotted the threshold we calculated previously:

Look at the figure from left to right: nothing, nothing, nothing — then at β<sub>inv</sub> the dependent fraction jumps from zero to about 60% without any warning. Continuing to increase β, will keep us moving along the upper branch. However, if we now decide to turn back around and start decreasing β, we follow a different path.  The system “*remembers*” that it was in the locked-in state all the way down to β<sub>sn</sub>, including a  region where before we had seen no sustained casual use.

In other words: It’s easier to keep mass dependency than it is to create it. This memory effect is what produces the asymmetry in both paths, and is known as [hysteresis](https://en.wikipedia.org/wiki/Hysteresis).

## Network effects

The ODE equations we have been exploring so far correspond to the idealized mean-field case. The mean field approximation assumes that everyone interacts with everyone equally. However, reality is a lot more complex. We live in societies where we interact with only a small number of the people around us. We can explore this effect by implementing this [model on a network](https://data4sci.substack.com/p/network-models) with the `NetworkEpiModel` module. 

In addition to the number of contacts we have, who we interact with is also important. This becomes obvious when we compare [the spread of the epidemic on two graphs](https://data4sci.substack.com/p/epidemic-models) with the *same* average degree: an Erdős–Rényi graph, with a narrow degree distribution, and a Barabási–Albert graph with a heavy-tailed, hub-dominated.  When we sweeping the per-contact transmission probability, λ:

The BA network sustains locked-in dependence at transmission probabilities where the ER graph remains unaffected. The hubs that are the defining feature of a BA network act both as super-recruiters and reinforcement chambers. As soon as a hub is infected, it quickly infects its neighbors, which in turn infect their neighbors, and so on. The mean-field model is unable to account for this effect, as it treats every individual the same way.

We can also see that time spent dependent increases as degree increases.

## The two levers aren’t equal

How can we immunize the population? The original paper proposes a “cognitive immunization” strategy that reduces to two levers: lower β (add friction to social transmission) or raise δ (make dependence easier to walk back from). Hysteresis show that these two approaches are very different. After we cross into the locked-in state the only way to drop back out is when δ > αβ/4γ, a boundary that’s linear in δ but requires *reducing β by half* to cross from the transmission side alone:

From a locked-in society, transmission control alone has to drag β below roughly 0.27 before the dependent state stops existing at all — a huge lift. Raising reversibility, on the other hand, moves the escape boundary toward you in a straight line. Cognitive immunization is ony possible by engineering an off-ramp: exportable workflows, retained skills, and the ability to still function when the tool no longer does.

Congratulations on making it through another post in this series. You can find all the code necessary to implement the models described above and to generate the figures in all posts. You can find it in the series GitHub repository:

and don’t forget to:

to be the first to see new posts as they are published.
