When one presents a system of ODEs via a friendly, graphical data structure, such as a stock flow diagram or a Petri net with rates, one induces dynamics on some fixed set of variables. This post articulates how this syntax can be used to give a continuous dynamics on ACSets (with an eye towards agent-based modeling, where we wish to intregate continuous dynamics with stochastic ACSet rewriting events).

# Presentations of ODEs

Let’s take a Petri net with rates + mass-action kinetics as our example for a user-friendly syntax for presenting ODEs. The blue circles are called *species* and the orange boxes are called *transitions*. Consider the SIR epidemiological model for interactions between Susceptible, Infected, Recovered people:

This presents the chemical reaction network:

S+I \rightarrow 2I,\ \ \ \ I \rightarrow R

Which presents the ODE system:

\frac{d S}{d t} = -k_{inf}SI,\ \ \ \ \frac{d I}{d t} = k_{inf}SI - k_{rec}I,\ \ \ \ \frac{d R}{d t} = k_{rec}I

# Representations of the world

A straightforward means of declaring what a “state of the world” consists in is to provide a *schema*. This requires declaring *objects* (tables), *homs* (foreign keys), *attribute types* (datatypes), and *attributes* (attribute columns). A state of the world is an ACSet on this schema. In the example visualized below, objects will be in boxes and attribute types will be in circles.

Suppose the world is defined by a set of people who each have an associated number for their happiness and health. Furthermore, these people use social media, and there is a graph of people following other people, where each following has a given level of strength and a date at which the connection was made:

Here’s an example state of the world, Init, with three people and two follows, first as a database and then graphically:

Person | Happiness | Health |
---|---|---|

1 | 5.1 | 6.8 |

2 | 2.0 | 2.8 |

3 | 9.9 | 8.0 |

Follows | follower | followed | strength | since |
---|---|---|---|---|

1 | 1 | 3 | 1.3 | 3/4/16 |

2 | 3 | 2 | 2.8 | 9/2/19 |

In this case, there are 8 values of type \mathbb{R} at play. One could simply define a Petri Net with 8 species and obtain some dynamics for this model of the world, but then this model becomes useless if we try to simulate a different number of people (or if that number changes over time).

# A Solution

Let’s define some dynamics in an intuitive way:

Let’s give these four species some meaning via relating them to a *pattern* ACSet, Pat_1 (which uses variables rather than concrete attribute values):

Person | Happiness | Health |
---|---|---|

1 | Hap1 | Health1 |

2 | Hap2 | Health2 |

Follows | follower | followed | strength | since |
---|---|---|---|---|

1 | 1 | 2 | Strength1 | Date1 |

What is this saying? We’re crudely modeling that following someone on social media drains one’s happiness (a process which is accelerated by one’s own happiness, the happiness of the person being followed, and the strength of the follow). Furthermore, following someone on social media has the effect of draining one’s health exponentially. This equation isn’t for two *specific* people, but rather is for *any* two people where one follows the other.

If we consider the ACSet Init and how its 8 numeric values would change over time in light of this combination of a Petri net + a pattern ACSet Pat_1, we initially start out with all derivates set to 0:

\frac{\partial\ \text{happiness}(p_1)}{\partial t} = 0,\ \frac{\partial\ \text{health}(p_1)}{\partial t} = 0,\ ...,\ \frac{\partial\ \text{strength}(f_2)}{\partial t} = 0

But for each *pattern match* (i.e. morphism Pat_1\rightarrow Init), we add terms corresponding to the dynamics associated with Pat_1, e.g. if we just look at health dynamics, we have:

\frac{\partial\ \text{health}(p_1)}{\partial t} = -k_{sick}\text{health}(p_1),\frac{\partial\ \text{health}(p_2)}{\partial t} = 0,\frac{\partial\ \text{health}(p_3)}{\partial t} = -k_{sick}\text{health}(p_3)

This is because Persons 1 and 3 follow someone else, whereas Person 2 does not (there are only two morphisms Pat_1 \rightarrow Init).

We could define a positive feedback loop between health and happiness in general

associated with the pattern Pat_2 (which matches exactly once per person in a given world-state, such that these dynamics will always apply to everyone in the model):

Person | happiness | health |
---|---|---|

1 | Hap1 | Health1 |

Maybe it’s boring that Pat_1 matches exactly once per Follow and Pat_2 matches exactly once per Person, so to show the real power of this formalism, let’s consider a pattern, Pat_3 that matches once per consecutive pair of follows:

Person | happiness | health |
---|---|---|

1 | Hap1 | Health1 |

2 | Hap2 | Health2 |

3 | Hap3 | Health3 |

Follows | follower | followed | strength | since |
---|---|---|---|---|

1 | 1 | 2 | Strength1 | Date1 |

1 | 2 | 3 | Strength2 | Date2 |

Now the dynamics associated with this pattern:

This models how if you follow someone, p, the strength of your connection gets leached off into the people p follows (catalyzed by how strongly p follows them).

There is only one match Pat_3\rightarrow Init. If we now look at the overall strength dynamics, we have:

\frac{\partial\ \text{strength}(f_1)}{\partial t} = -k_{steal}\text{strength}(f_1)\text{strength}(f_2)

\frac{\partial\ \text{strength}(f_2)}{\partial t} = k_{steal}\text{strength}(f_1)\text{strength}(f_2)

If, in addition to these dynamics, the world state is coupled to an agent-based model, where the number of agents and their connectivity can change over time, by checking for incoming morphisms from P_1, P_2,P_3 we’ll know under what circumstances each of the three dynamics above will kick in.

# Conclusion

The modeler specifies pairs of pattern ACSets with dynamics on their attribute values, P_i \times Dyn_i (with dynamics specified via Petri Nets, Stock Flow models, or simply raw ODEs). We compute the rates of change for all these continuous attributes of an ACSet X by summing up, for each pattern ACSet P_i and for each match \alpha\in\text{Hom}(P_i,\ X), the interpretation of Dyn_i under the match \alpha.

This was an off-the-cuff idea, but it seems like a convenient means for allowing ODEs and ACSets to mix while still keeping all of the relevant data in a combinatorial form, rather than within arbitrary code expressions (meaning, we’re in position to do things like functorial data migration and (co)limits with our models).

Further bells and whistles: one could attach the usual application conditions (positive or negative) and optional monic constraints to these patterns. One could also define “to-\mathbb{R}” functions in order to incorporate other attribute types into the ODE dynamics.