In The Incidence Reduction, we showed that ODE steady-state values recover exact integers from the net topology — incidence degrees to terminal transitions. In Tropical Petri Nets, we showed that timed event graphs are max-plus linear systems, and that the tropical eigenvalue compresses an entire reachability graph to a single scalar, the cycle time. Both analyses start from the same object: the incidence matrix C.
Both are also compressions, and of the same structure. Add a third analysis — zero-knowledge proofs — and all three draw the same line through the net. The long form is a draft paper, papers/earned-compression/main.tex in pflow-rs; this post follows it, and says where the code behind it agrees and where it doesn't.
Revised 2026-08-22. The original defined "observer" once and then used the word for two different things; see From Games to Finance for the correction, and The Category Settle for the full version. Revised again 2026-10-18 against the code; see What Changed.
Every Petri net we've built — tic-tac-toe, coffee shop, Texas Hold'em — has a natural split. There's a part that does things (moves pieces, brews coffee, deals cards) and a part that watches (detects wins, checks completion, validates hands). We call the first part the core and the second part the observer.
The split isn't just organizational. It has a precise structural definition: observer transitions consume from core places but never produce into them. This is the sink property. The observer reads the core's state destructively — it takes tokens to make a verdict — but it never feeds tokens back. If no observer transition ever fires, the core evolves identically whether or not the observer exists.
That is one definition, and it is the one every section below uses until the payment example. It is an algebraic definition — it is read off the columns of C. In tic-tac-toe it picks out exactly the transitions with ρ > 1; in general the two can come apart, since a sink that takes one core token and makes one verdict token has ρ = 1. Hold on to that, because the payment example will turn out to need a second definition.
The tic-tac-toe net here is the 33-place, 35-transition pilot_ttt fixture in pflow-tropical's ttt_fixtures.rs, whose dimensions and turn wiring conjecture1.rs asserts. It decomposes as:
Core: 18 play transitions (9 cells × 2 players). Each consumes an empty-cell token and a turn token, and produces a marked-cell token, the opposite turn token and one move_tokens token — the counter the draw detector reads. The cell invariant p_ij + x_ij + o_ij = 1 and the turn invariant x_turn + o_turn = 1 hold across every play.
Observer: 17 transitions (8 win lines × 2 players + 1 draw). Each win transition consumes 3 cell tokens + the game_active flag + a turn token, and produces a single verdict token. Five tokens in, one token out. The draw consumes nine move_tokens and game_active. The board state is destroyed. Only the verdict survives.
With ρ(t) as tokens consumed over tokens produced, the wins have ρ = 5 and the draw ρ = 10: more is consumed than produced, and the difference is the earned compression — the state the verdict makes irrelevant. The plays have ρ = 2/3, not the ρ = 1 this post used to claim: they consume two tokens and produce three, the third being the move counter. Drop the counter, as the 29-place core in the same file (builder_ttt_turns) does, and each play is exactly ρ = 1. The line falls in the same place either way — plays at or below 1, verdicts at 5 and above — but "core means ρ = 1" is true of the counter-free core, not of the net this post counts.
JPEG is lossy — it throws away information and hopes you won't notice. Gzip is lossless — it exploits redundancy but preserves everything. Earned compression is something else: it throws away information and proves that what it threw away doesn't matter for the target property.
Formally, a map κ: S → S' is an earned compression with respect to a property π if:
The tightness condition is what distinguishes this from approximation: the claim is the shortest description from which the target property can be recovered, not one that is close enough. For the tropical eigenvalue the paper rests tightness on Baccelli et al.; for the other stages below, and for C itself, it is asserted, not proved. Read condition 3 as what each stage has to earn rather than something it already has.
The paper's central claim is that three analyses — each with different mathematical foundations, different computational models, and different target properties — put the same transitions on the core side and the same on the observer side. Its proof is a sketch, and read against the code the three legs hold up to different degrees.
The mass-action ODE system ẋ = C · v(x) evolves the core to a stable equilibrium. This is what we explored in integer reduction: set all rates to 1.0, let the topology speak, and the steady state reveals the incidence degrees.
The observer's transitions are sinks — they pull tokens out of the system and feed none back. That much is the definition. The paper goes further: the core reaches equilibrium on its own and the observer is only evaluated at that equilibrium. That holds when the ODE runs over the core alone. It is not what the tic-tac-toe ODE on this blog does. There the win detectors fire inside the solve, and because they consume the turn token they stop the flow — the game-halting fix, which changed the scores. A sink can't feed the core, but it can drain it.
The core-observer boundary, from the ODE's perspective, is direction of flow: nothing comes back out of the observer.
The tropical eigenvalue compresses the core's entire reachability dynamics to a single scalar λ — the asymptotic cycle time (throughput is 1/λ; at λ = 1 the two coincide). For tic-tac-toe's core, λ = 1: one X-play then one O-play, alternating. The critical circuit has length 2 (an X-play followed by an O-play), total weight 2, mean = 1. No test computes this for the tic-tac-toe core. conjecture1.rs asserts λ = 1 on a two-transition loop, and on pilot_ttt it only spot-checks the max-plus wiring (an X-play and an O-play enable each other through the turn places). And since every delay in the core is 1, every circuit in it has mean 1, so λ = 1 here says the plays form a cycle more than it says anything about alternation.
The eigenvalue means something because of the theorem behind it, which needs a timed event graph: every place with exactly one producer and one consumer. Strictly the core isn't one. Each empty-cell place p_ij has two consumers (x_play_ij, o_play_ij) and no producer, and the turn places have nine of each. The paper's position is that one turn token serializes all of that, so the core behaves like an event graph; The Turn Place Problem below takes it up.
The observer breaks the property more visibly. Place x11 (X's mark on the center cell) has four consumers — the win transitions for the four lines through the center. With several consumers per place the event-graph theorem no longer applies, and the max-plus equation stops describing the dynamics.
The core-observer boundary, from tropical analysis: the core's fan-out is serialized by the turn token, and the observer's is supposed not to be. Of the three legs this is the weakest; the turn-place section says why.
The incidence matrix compiles directly into an R1CS constraint system for ZK proofs. A Groth16 proof of a transition says: "a valid move occurred from marking m to marking m'" — in 128 bytes, verifiable in constant time. It reveals which transition fired and the two state roots, and hides the board. The transition id is a public input in both circuits we run, and Zero-Knowledge Proofs for Petri Nets says so; an earlier version of this post said the proof revealed nothing about the move.
The paper's ZK leg says core transitions compile to uniform R1CS — m' = m + Δ_t, with a boolean multiplexer selecting the right column of C — while observer transitions consume from places shared with other observer transitions and need auxiliary witness variables to prove non-interference. The circuit in pflow-rs doesn't do that. circuit.rs in pflow-zk-arkworks puts every transition of the net, win detectors and draw included, through the same selector multiplexer, with one remainder witness per input-arc slot; the gnark circuit in the zk-petri-nets post has the same shape. The observer's one visible cost is width. A win has five input arcs where a play has two, and the enabledness block is padded to the widest transition, so the observer sets the size of every step's circuit. That is a real asymmetry, but it is not the non-uniform witness the theorem names, and nothing measures it.
The core-observer boundary, from ZK encoding as built: padding, not a different encoding.
No single formalism can prove the boundary is structural. The ODE analysis might be an artifact of mass-action kinetics. The tropical analysis might be an artifact of event-graph restrictions. The ZK encoding might be an artifact of R1CS structure.
The paper's answer is that three formalisms sharing no mathematical machinery — real-valued differential equations, the max-plus semiring, and finite-field arithmetic — converge on the same partition. Its own proof sketch shows why that is weaker than it sounds: each leg is derived from the one sink property, so the agreement is three readings of one definition rather than three independent experiments. Read against the code, the legs also agree less cleanly than the theorem says. The ODE sees direction of flow, the tropical leg needs the turn-place argument to keep the core on its side, and the circuit as built treats every transition alike. Nothing yet runs the three classifications on one net and compares the partitions.
What they do share is the thing they read: ρ, or the sink property that tracks it here. The ODE sees ρ > 1 as a sink, the tropical analysis sees it as a broken event-graph property, the circuit as built sees it only as a wider row of input arcs. None of them can see an arc that isn't in C at all — which is exactly what the next kind of observer is made of.
The incidence matrix C is the central object. Each analysis is a compression — a map that discards information irrelevant to a specific target property while preserving that property exactly.
| Stage | Input | Output | Ratio | Property preserved |
|---|---|---|---|---|
| Domain → Net | Game rules | C ∈ ℤ^{33×35} (places × transitions) | — | All firing semantics |
| Net → Eigenvalue | C (1155 integers) | λ ∈ ℝ (1 scalar) | 1155 | Throughput |
| Net → Invariants | C | ker(C), ker(C^T) | P | |
| Net → Observation | m, t_obs | verdict ∈ {w,l,d} | 5–10 | Game outcome |
| Net → ZK proof | C, m, t | π ∈ {0,1}^1024 (128 bytes) | ~10⁴ | Transition validity |
The paper calls every row earned. The first two conditions can be checked row by row; the third, that no smaller output suffices, is argued for the eigenvalue and asserted for the rest. The ratio column is input size over output size, a different quantity from the per-transition ρ above, and the ~10⁴ for the proof is the paper's round figure, not a derivation.
A 33×35 matrix — 1155 integers — goes in, and a single real number λ = 1 comes out: the core's cycle time, one turn per unit delay. Strictly the eigenvalue is computed from the 18×18 max-plus matrix of the core, not from C itself; 1155 is the size of what we started with. Within the event-graph caveat above, that one number is all of C that matters for throughput.
The ZK row has the largest ratio. The entire statement "transition t is valid from marking m to marking m'" — which involves the full incidence matrix, the current state, the enabledness conditions — compresses to 128 bytes. The verifier learns that the transition was valid and which transition it was, and nothing about the marking beyond its two hashes.
There is a thermodynamic reading of the decomposition.
The core loses nothing. The cell invariant p_ij + x_ij + o_ij = 1 says each cell is always exactly one of empty, X-marked, or O-marked, and x_turn + o_turn = 1 holds alongside it. In the 33-place net each play also adds a move_tokens token, so the total grows by one per move rather than staying fixed, but nothing is thrown away: the counter is history, and it is what the draw later consumes.
The observer is irreversible. A win transition consumes 5 tokens and produces 1. The board state — which cells formed the winning line — is destroyed. Only the verdict survives. The game cannot be "un-won."
This is the same pattern as measurement in physics — a measurement apparatus couples irreversibly to a reversible system, producing a classical outcome that cannot be undone. The mechanisms differ (no Born rule, no non-commutativity here), but the structural pattern is shared: observation that claims to be passive is actually irreversible, and the irreversibility is what produces a definite outcome.
The compression ratio ρ quantifies the irreversibility. Plays: ρ = 2/3 here, 1 without the counter (nothing destroyed). Wins: ρ = 5 (five tokens in, one verdict out). Draw: ρ = 10 (nine moves of history and the game flag compressed to "nobody won" — which this net scores as a point for O). The destroyed information is exactly the information irrelevant to the verdict — the specific cells that formed the winning line don't matter once you know who won.
| Observer transition | Consumed | Produced | ρ | Information discarded |
|---|---|---|---|---|
| x_win_* (8 transitions) | 5 | 1 | 5 | Which 3 cells formed the line |
| o_win_* (8 transitions) | 5 | 1 | 5 | Which 3 cells formed the line |
| draw | 10 | 1 | 10 | Full move history (9 moves) |
| Play transitions (18) | 2 | 3 | 2/3 | None (the extra token is the move counter) |
There's a subtlety that exposes the limits of structural analysis. The turn-control places (x_turn, o_turn) have 9 producers and 9 consumers — every play transition for one player produces into the other's turn place. Structurally, this violates the timed event graph property.
Behaviorally they're fine. One token moves between the two turn places, so exactly one play fires per turn, and the token ping-pongs 1-to-1 through reachable markings even though the structure has 9:9 fan. The empty-cell places are the same story in miniature: two consumers each, and the turn token only ever enables one of them.
The three analyses see the turn places differently. The ODE treats the turn token as a concentration that all nine x_play flows draw on at once; it has no mutual exclusion to enforce and never needed one producer per consumer, so 9:9 costs it nothing — the same concurrency that, in the tic-tac-toe post's correction, keeps it from seeing a race. The tropical analysis sees all nine producers and nine consumers and reports causal paths between transitions that can never actually co-fire: it overapproximates. The discrete firing rule enforces alternation exactly, and an RNN trained on discrete trajectories never sees anything else. rnn_petri.rs asserts that all 200 training games on the 29-place core alternate, and that 50 of 50 self-play games do (not re-run for this revision).
So the turn places are where the discrete analysis is exact, the continuous one is indifferent, and the structural one overapproximates. The incidence matrix C — which all three formalisms share as input — is insufficient to classify tropicality at the turn-control layer. That takes reachability information, and reachability is discrete.
The argument also cuts the other way, which is why the tropical leg is the weakest. Every win and the draw consume the one game_active token, so at most one observer transition ever fires, and the observer's shared cell places are serialized by a single token just as the core's are. We have not worked out why the reachability argument should keep the core on the event-graph side and not the observer.
Whether there exists a useful formal weakening — "tropical under mutual exclusion" — that captures this behavioral property without full state-space enumeration is an open question.
The core-observer pattern isn't specific to games. It appears anywhere a computational core is monitored by an observation layer.
Consider a payment settlement network with three parties: Alice → Bob → Carol → Alice. Each channel has a send transition (debit sender, create pending) and a settle transition (clear pending, credit receiver).
The circular structure is visible in the net: tokens flow from alice_bal through send_ab to pending_ab, then settle_ab credits bob_bal, and so on around the cycle. Each place has exactly one producer and one consumer — a timed event graph. The core incidence matrix, printed transposed (rows are transitions, columns places — so this is Cᵀ, with C itself 6 × 6 places-by-transitions as everywhere else on this blog):
a b c p_ab p_bc p_ca
send_ab -1 0 0 1 0 0
settle_ab 0 1 0 -1 0 0
send_bc 0 -1 0 0 1 0
settle_bc 0 0 1 0 -1 0
send_ca 0 0 -1 0 0 1
settle_ca 1 0 0 0 0 -1
This core really is a timed event graph — every place has one producer and one consumer. With unit delays the tropical eigenvalue is λ = 1: every channel takes the same time, so none is a bottleneck. The P-invariant a + b + c + p_ab + p_bc + p_ca = const is the accounting identity: total money in the system is conserved. Double-entry bookkeeping is a theorem of the incidence matrix, not a policy imposed on it.
The observer checks business rules: overdraft guards read balance places (catalytically — without consuming), and if the guard fails, the candidate payment is never committed. Not rolled back, not compensated — it never enters the event log.
Notice that this observer fails the definition this post opened with. The sink property says an observer consumes from core places; the overdraft guard consumes nothing. It has ρ = 1. Under the three formalisms above it is invisible — it is not a column of C, so the ODE, the eigenvalue and the uniform circuit all look straight through it. It is an observer for a different reason: a read arc is a contextual arc, and contextual nets do not form the free symmetric monoidal category that ordinary nets do (Montanari & Rossi, 1995). The win detector in tic-tac-toe is an observer because it breaks the algebra and composes fine; the overdraft guard is an observer because it breaks composition and leaves the algebra alone. The original version of this post called both "the observer" and let the reader assume one boundary. There are two, and they are stacked, not equal. The Category Settle works this out.
The same formalism serves both domains, but the tropical eigenvalue transforms from a structural curiosity (tic-tac-toe: λ = 1 at unit delay) to a design parameter (payments: with real channel delays, 1/λ is the maximum sustainable settlement rate).
This three-party cycle is just one instance. Settlement networks form a sub-SMC of open Petri nets — The Category Settle — where channels compose along shared boundary places. Conservation and the ZK circuit compose with them outright; throughput composes as a bound (λ of the whole is at least the max of the parts, and gluing can create cycles that beat both).
A single 33×35 integer matrix — 33 places by 35 transitions — encodes the full tic-tac-toe game:
The paper's strongest claim is that C is the maximally compressed description of the domain — the shortest from which all behavioral, structural, and cryptographic properties can be recovered without loss. It is argued, not proved. And for this net it holds partly because of how the net is built: tic-tac-toe has no self-loops and no read arcs, so C determines both the input and the output arcs. A net with a read arc — the overdraft guard above — has a firing rule that C cannot recover.
This is the Kolmogorov-flavored claim at the heart of the paper: a domain is understood when its shortest description is also its most useful description. The paper proposes the incidence matrix as that description for Petri-net-structured domains with ordinary arcs.
The claim we care most about is that the boundary between what compresses and what doesn't is itself the most informative structural feature.
The core compresses because it has clean algebraic structure: fan-out a single turn token serializes, and conservation laws. The observer doesn't compress — at least not in the same ways — because it has irreducible complexity: cells participate in multiple win lines, and there's no cheaper way to check all of them.
That irreducible complexity is also what makes the observer useful: its non-tropical structure is a feature of the domain rather than a failure of analysis. Win detection in tic-tac-toe is irreducibly non-tropical because a single cell participates in multiple win lines. The fan-out is the point — it's what makes the measurement informative.
The generalization we would like to make — unproved, and checked only on the two nets in this post — is that in any system with a computational core and an observation layer, the core admits algebraic compression (throughput, conservation, proofs) and the observer admits only discrete compression (reachability, enabledness), and that any sufficiently expressive analysis of C will find the ρ boundary. The contextual boundary is not theirs to find — it sits outside C by construction — and it has to be declared. Tic-tac-toe (move execution watched by win and draw detection) is worked above, and so is the payment ring (settlement watched by an overdraft guard, the contextual kind). Workflows, with task execution watched by timeout and error detection, and protocols, with message passing watched by violation and completion checks, look like the same shape, but we have not built either.
In both worked cases the incidence matrix is the specification and the analysis input, and the boundary tells you where the algebraic tools work and where you need discrete reasoning. Whether the three formalisms' agreement shows that the boundary is structure rather than a modeling choice is still open. The agreement follows from one definition, the tropical leg needs an argument we have only made for the core, and the circuit leg is not built the way the theorem describes.
Revised 2026-10-18 against the code — the pilot_ttt fixture, the pflow-tropical tests, the arkworks circuit and the paper source. None of it was re-run for this revision.
move_tokens token as well as the mark and the turn: 2 in, 3 out, ρ = 2/3. The post said 3 in, 3 out, ρ = 1, which is only true (as 2 in, 2 out) of the 29-place core without the counter. The boundary doesn't move.game_active too. λ = 1 for the core has no test, and at unit delay it says little. λ is now the cycle time, with throughput 1/λ, as in Tropical Petri Nets.For the tropical algebra that makes this possible: Tropical Petri Nets
For the ODE analysis that started it: The Incidence Reduction
For how settlement networks compose categorically: The Category Settle
For the categorical structure underneath: Symmetric Monoidal Categories
For the temporal interpretation of the core-observer boundary — past as tropical accumulation, present as marking, future as predicate constraint: The Zipper Whose Hole Is a Universe