Systems and
Formalisms Lab

Rewriting modulo SAADD for string diagrams

Final project report about string diagram rewriting in Coq for CS-628 Interactive Theorem Proving, Spring 2024

tl;dr: String diagrams are an intuitive diagrammatic representation of some pretty useful math. This being Interactive Theorem Proving, of course, I want to formalize that math in a proof assistant (Coq), in such a way that formal proofs still work like paper proofs using all the nifty properties of the diagrammatic representation. And, of course, a naïve formalization runs into problems that make the system painful to use. So this project explores how we might overcome those problems and restore the convenience of string diagrams in a formal setting.

What are string diagrams?

Many other people have done a much better job of explaining what string diagrams (and their underlying mathematics, a.k.a. symmetric monoidal categories) are than I can—see, for instance, [Selinger2010], or [Sobociński2015]—so here, I’ll just do the minimum required for the rest of this article.

The kinds of string diagrams I’m interested in are made up of boxes/morphisms that have some wires on their left and right sides. (A term described as “A/B” means “A” is the diagrammatic representation of the formal mathematical entity “B”.) The wires are labelled (in blue below) but sometimes you might not write the labels.

{static}illustrations-1.png

The source and target of a box are the labels of the wires on its left and right, respectively, but written with the stack/product operator ⊗ between them. Above, f has source A ⊗ B and target C ⊗ D ⊗ E, which we write as f: A ⊗ B → C ⊗ D ⊗ E.

There are two kinds of primitive boxes: the identity box idA: A → A for any label A, and the swap box βA,B: A ⊗ B → B ⊗ A for any labels A, B.

{static}illustrations-3-crop.png

The stack operator has a second meaning: it also applies to boxes by stacking them vertically. So you can make f ⊗ g: A ⊗ B ⊗ D ⊗ E → C ⊗ D ⊗ E ⊗ F.

{static}illustrations-2.png

The last thing you can do with boxes is to connect/compose them by joining wires with the same label. This is denoted with ·, like f · idC ⊗ g (note that ⊗ binds tighter than ·, just like multiplication binds tighter than addition in 2 + 3 × 5), which has source A ⊗ B and target C ⊗ F. The only restriction is that you can’t introduce loops.

{static}illustrations-4.png

So those are all the constructors of our diagrammatic calculus. A calculus also needs some axioms to make deductions about its terms. In our case, the axioms allow you to rewrite a diagram in any way that “graphically makes sense”, i.e. moving boxes around, swapping and unswapping wires, etc., while maintaining the connectivity of the diagram, i.e. what is connected to what. Two of these axioms, relating to swapping, bear special mention. They are called naturality and the hexagon axiom respectively:

{static}illustrations-5.png

The hexagon axiom is a little tricky. It says that swapping A and B, and then swapping A and C, is the same as swapping A and the product B ⊗ C. But you, the astute reader, should be a little concerned at this point. We aren’t being fully precise, because we aren’t accounting for parenthesization/association: the left-hand side is (A ⊗ B) ⊗ C → B ⊗ (C ⊗ A) while the right-hand side is A ⊗ (B ⊗ C) → (B ⊗ C) ⊗ A. That brings us to…

What is SAADD and why do we want to factor it out?

SAADD stands for Symmetry, Associativity (of ⊗), Associativity (of ·), and Double Distributivity (of ⊗ and ·).

When we stack A ⊗ B ⊗ C or f ⊗ g ⊗ h diagrammatically, we don’t care how they’re associated; the stack looks the same either way. And we don’t bother indicating where or how the association changes in diagrams like the hexagon axiom. This is because, in the underlying mathematics, we have an isomorphism αA,B,C between (A ⊗ B) ⊗ C and A ⊗ (B ⊗ C). For connections with ·, the property is even stronger, because · is defined to be such that (f · g) · h is equal to f · (g · h) for all morphisms. These are the two associativity properties.

Further, stacking and connecting distribute over each other. This is easiest to illustrate with a picture. (“Double distributivity” is probably not the right word, because it’s not like the distributivity of arithmetic × over +, where a × (b + c) = a × b + a × c, and a + b × c is irreducible. The right word is something like “bifunctoriality” but I don’t know enough category theory to say for sure. SAADD makes a nice acronym for the time being.)

{static}illustrations-6.png

(corporate needs you to find the differences between this diagram and this diagram) – (they’re the same diagram)

Lastly, symmetry means that there is a self-inverse isomorphism between A ⊗ B and B ⊗ A, illustrated with a swap in our diagrammatic notation. Which means, for instance, that if you have g: A → C and f: B → D, stacked as g ⊗ f; and you know that f ⊗ g = h; then you can rewrite with that known equation as follows:

{static}illustrations-7-crop.png

The point is, none of these SAADD properties matter when you’re doing diagrammatic rewriting, because they are obvious equalities or isomorphisms in the world of diagrams. You would not think of them as separate steps of your proof and you would not want to have to write them down. And in math papers, you don’t. But this is Interactive Theorem Proving, after all, where things are different…

Challenges with associativity

Let’s take a case study: the Yang-Baxter equation. It states

{static}illustrations-8.png

A diagrammatic proof

Proof by rewriting the left-hand side to the right-side side with axioms.

{static}illustrations-9.png

Easy.

A formal proof

Let’s write the left-hand side in mathematical terms. It looks like it’s the composition of three pieces:

  • L1:= βC,B ⊗ idA of type (C ⊗ B) ⊗ A → (B ⊗ C) ⊗ A

  • L2:= idB ⊗ βC,A of type B ⊗ (C ⊗ A) → B ⊗ (A ⊗ C)

  • L3:= βB,A ⊗ idC of type (B ⊗ A) ⊗ C → (A ⊗ B) ⊗ C

Hmm, the source and target types don’t quite match up. We need to interpose reassociation isomorphisms αB,C,A: (B ⊗ C) ⊗ A → B ⊗ (C ⊗ A) between the first two and αB,A,C-1: B ⊗ (A ⊗ C) → (B ⊗ A) ⊗ C between the second two. So we get

(((βC,B ⊗ idA · αB,C,A) · idB ⊗ βC,A) · αB,A,C-1) · βB,A ⊗ idC

The first step in the diagrammatic proof was to apply the hexagon axiom. Actually, why is it called that? The answer becomes clear when it is stated formally:

{static}illustrations-10.png

The whole diagram commutes, which means that any two paths between the same two objects are equal, i.e. the composition of the three morphisms on top equals the composition of the three on the bottom.

We can spot the left-hand side of the hexagon axiom in the left-hand side we wrote down previously. Let’s rewrite it with the right-hand side of the hexagon axiom.

(((αB,C,A · βC,B⊗A) · αB,A,C) · αB,A,C-1) · βB,A ⊗ idC

And we can reassociate and simplify:

= ((αB,C,A · βC,B⊗A) · (αB,A,C · αB,A,C-1)) · βB,A ⊗ idC

= ((αB,C,A · βC,B⊗A) · idB⊗A⊗C) · βB,A ⊗ idC

= (αB,C,A · βC,B⊗A) · βB,A ⊗ idC

= αB,C,A · (βC,B⊗A · βB,A ⊗ idC)

Apply the naturality of swapping:

= αB,C,A · (idC ⊗ βB,A · βC,B⊗A)

Now we want to reverse rewrite the right-hand side of the hexagon axiom with the left-hand side, but we only have one of the terms, βC,B⊗A. We’d need to compose it on both sides with the identity, then split the identity into the correct association isomorphisms and their inverses, then reassociate to isolate exactly the bottom side of the hexagon axiom, then rewrite, then… you get the idea. I’m not going to write this proof out in full because it’s tedious and not particularly illuminating. We have to worry ourselves with things like cancelling associativity operators which is far from the elegance of the diagrammatic proof we’re trying to emulate.

Challenges with symmetry and distributivity

In case you aren’t convinced yet, symmetry and distributivity properties pose exactly the same sort of problem in a formal setting—you don’t want to have to think about them but they keep popping up. Take, for instance, a simple monoidal law, where for all f: A → B and g: C → D,

f ⊗ idC · idB ⊗ g = idA ⊗ g · f ⊗ idD

{static}illustrations-11-crop.png

Diagrammatically, this seems obvious and trivial. But formally, the equalities we want to rewrite with are of the form id · f = f = f · id, and those terms don’t appear in the formula we wrote above. We first have to redistribute the composition over the product:

= (f · idB) ⊗ (idC · g) = (idA · f) ⊗ (g · idD)

Then apply the id properties, and finally redistribute the other way to get the formula we want. Ideally, we’d be able to rewrite f · id = id · f directly, or taking it even further, since this is a pretty basic identity, we’d be able to dispatch the whole goal with a single tactic.

Towards possible solutions

My first step was to set up the theory above in Coq exactly as described in [Selinger2010]. The style of formalization was inspired by ViCAR [ShahEtAl2024]. I started by formalizing a category as a typeclass with the basic constructors (like composition), together with a category coherence typeclass with the requisite properties (like associativity of composition). I extended those to monoidal categories by adding products and then to symmetric monoidal categories by adding swaps. (Remember that string diagrams represent morphisms in symmetric monoidal categories.)

Second, I registered morphism equality as an instance of an equivalence (with reflexivity, symmetry, and transitivity) as understood by Coq’s “generalized rewriting” mechanism, also known as setoid_rewrite. This lets you use the rewrite and setoid_rewrite tactics to rewrite equations with your own equivalences beyond Coq’s built-in syntactic equality =. I also had to register composition and products as operations compatible with morphism equality. This means we can “rewrite under” them, so to speak; or in other words, allowing us, for instance, to rewrite a = z in the term a ⊗ b · c, even though a is nested inside compositions and products.

Then, I decided to do the two proofs from before (the Yang-Baxter equation and the monoidal law) in full detail, without automation, just to confirm that they were possible, and to see just how tedious they got. Results: 26 Coq tactic steps for the first, 4 for the second. Here’s an excerpt from the first:

rewrite <- compose_associativity.
apply compose_compatibility; try reflexivity.
rewrite compose_associativity.
rewrite <- (compose_associativity (MC.(product_associativity) b c a).(b2a) _ _).
rewrite (product_associativity b c a).(inverse_a).
rewrite <- compose_associativity.

rewrite right_identity.

rewrite 4 compose_associativity.
rewrite <- compose_associativity with (f:=((identity _) ~⊗~ (SMC.(symmetry) a b).(a2b))).
rewrite <- compose_associativity with
  (f:=((identity _) ~⊗~ (SMC.(symmetry) a b).(a2b) ·
    (MC.(product_associativity) c a b).(a2b))).
rewrite <- compose_associativity with (h:=((identity _) ~⊗~ (SMC.(symmetry) b c).(a2b))).

rewrite symmetry_hexagon.

Autorewrite and normalization

Naturally, with all this repetitive rewriting, you might ask, why not use Coq’s autorewrite facilities? autorewrite works similarly to auto in that you register rewrite rules in a hints database, and applicable ones are applied automatically as long as the goal makes progress. Of course, this hangs if your rewrite rules have a loop. Or viewed differently, this process stops when the term reaches a normal form (that cannot be rewritten/“simplified” further) according to your rewrite rules.

We might try to define a normal form for string diagrams as one where all compositions and products are left-associated and compositions are always outside products. But as we’ve seen, we often need to reassociate or redistribute to isolate the terms we want to rewrite in the middle of a chain of compositions or products, and autorewrite normalization would not make this easier. Alternatively, all rewrite rules, whether axioms of the system or premises of a particular proof, would have to be phrased in this normal form. Something like:

Lemma embedded_inverse_a: forall a b c L (l: _ ~-> L),
  (l · (product_associativity a b c))
    · (product_associativity a b c).(inverse_a)  l.
Proof. (* by the inverse_a axiom *) Qed.

Ideally, though, we would like to avoid having to phrase rewrite rules in an unidiomatic or convoluted way just to make the formal proof work—this is just shifting the problem elsewhere. Still, with this approach and some automation, I was able to shorten the Yang-Baxter proof quite a bit:

Proof.
  intros.
  do 2 rewrite_hexagon.
  repeat cancel_assocs.
  rewrite symmetry_natural.
  reflexivity.
Qed.

And the monoidal law proof remains essentially the same length, but a tiny bit nicer.

Proof.
  intros.
  rewrite <- 2 morphism_product_bifunctor_compose. (* redistributes terms *)
  rewrite ?left_identity, ?right_identity.
  reflexivity.
Qed.

A/AC and commutative ring tactics

The A/AC tactics [BraibantPous2011] are a Coq library that enable reasoning modulo Associativity or Associativity and Commutativity, such as with matrix multiplication (only A) or addition on natural numbers (AC). Unfortunately, they aren’t applicable in our case, for several reasons:

  • A key assumption for the tactics to work is that all operators are of type A → A → A for some A. Addition is like this but morphism composition fundamentally isn’t.

  • The double distributivity problem is not addressed at all.

  • There’s a subtle but important difference between commutativity (a + b is equal to b + a) and symmetry (a + b is isomorphic to b + a). String diagrams have the latter, not the former. We want to explicitly represent and reason about the swap isomorphisms.

    • Thinking ahead a bit, if we want to generalize to the slightly weaker mathematical notion of braided monoidal categories, swaps become a bit trickier because they are not self-inverse. Which wire is “on top” in the swap matters.

Relatedly, there’s some nice older work on tactics for deciding propositions about commutative rings [GrégoireMahboubi2005] but it’s even less applicable in our setting of string diagrams.

ViCAR

ViCAR [ShahEtAl2024], or Visualizing Categories with Automated Rewriting in Coq, is recent in-progress work on exactly this problem of making string diagram rewriting more convenient in Coq, with a different approach. Instead of saying that SAADD properties should be completely transparent to the proof writer, ViCAR tries to provide (i) visualizations of string diagrams that show the inductive structure of nested compositions and products, integrated into the proof assistant via coq-lsp [CoqLSP2023]; (ii) high-level tactics that try to massage the goal into an equivalent form such that a given rewrite rule is applicable; and (iii) other high-level tactics that deal with simplification, such as cancelling out adjacent inverse morphisms and identity morphisms. Here’s an example of a ViCAR visualization (taken from their paper):

{static}triangle.png

I tried doing the Yang-Baxter proof in ViCAR and it was pretty nifty!

Proof.
  intros.
  do 2 partners_rw hexagon_1.
  cat_cleanup.
  rewrite braiding_natural.
  reflexivity.
Qed.

And the monoidal law proof:

Proof.
  intros.
  rewrite <- 2 tensor_compose. (* redistributes terms *)
  cat_easy.
Qed.

Although I was also able to achieve similar proof length and convenience with much simpler automation, I think that’s just because my examples are quite simple, and to really evaluate ViCAR, I would need to try my hand at more complicated category theory proofs.

Something ViCAR does not currently aim to automate away is redistribution, as evidenced by the explicit second proof step in the monoidal law proof. This seems to be difficult to build into the current tactic-based approach. So the authors are working on an alternative with e-graph equality saturation to explore a graph of terms that are equivalent under rewriting, find a path that rearranges the term into an appropriate shape to apply a rule, and exports the proof back to Coq [ShahLehmann2024].

Chyp

Chyp [Chyp2023] is a graphical interactive theorem prover for string diagrams based on an alternative category-theoretical internal representation [BonchiEtAl2022] that enables “a convenient rewrite theory for string diagrams that automatically handles the extra ‘bureaucracy’ that comes from working with sequential and parallel composition together.” Sounds like exactly the problem we’re exploring. Let’s try it out:

{static}chyp-1.png

The first notable thing is that the left- and right-hand sides of the equation are displayed the same! In Chyp’s internal representation, they really appear to be the same diagram. The “proof” that they’re equal (we know it succeeded, because the rewrite rule is highlighted in green) is trivial. In Chyp, each step in a derivation needs a justifying by clause; if omitted, as here, the default is by reflexivity. Indeed, Chyp’s whole premise is that

only connectivity matters. So, if two terms give the same diagram, like a * b ; c * d and (a ; c) * (b ; d), Chyp treats them as identical. Since under the hood, Chyp does everything with graph rewriting and not term rewriting, the prover handles all of this extra book-keeping for you.”

I couldn’t get it to produce a diagram with three separate swaps like my drawings above. At best, with two swaps, it produces

{static}chyp-2.png

Which makes me question whether we ideally even want the three separate swaps in the first place, or Chyp’s “3-spider” representation is the correct one…

Chyp seems really powerful given how trivial our first example seems. I don’t have even the most basic grasp of the graph rewriting theory it is based on, so I don’t have anything intelligent to say further.

Conclusion

String diagrams are an intuitive and convenient representation for symmetric monoidal categories, and we’d like to do formal proofs with them in a proof assistant. But the very properties that make them so nice to use, captured naturally in the diagrammatic calculus—symmetry, associativity of the two operators, and double distributivity of each over the other—pose challenges for formal proof. In this project, I took a closer look at what those challenges are, why they arise, and what possible approaches to address them might be, including a brief survey of related work. Although I didn’t make any progress towards actually solving the problem, I understand it a lot better and I hope I will be able to share that understanding here.

Aside: I claimed at the beginning that the mathematics of string diagrams was “pretty useful”, without justification, because that was beside the point. But in case you’re curious about where they’re used, here are some directions to explore.

References

[BonchiEtAl2022]

Bonchi, Filippo and Fabio Gadducci, Aleks Kissinger, Paweł Sobociński, Fabio Zanasi. (2022). “String Diagram Rewrite Theory II: Rewriting with Symmetric Monoidal Structure”. Preprint on arXiv. https://arxiv.org/abs/2104.14686

[BraibantPous2011]

Braibant, Thomas and Damien Pous. (2011). “Tactics for Reasoning modulo AC in Coq”, in Certified Proofs and Programs, Taiwan, 2011, pp. 167–182. https://doi.org/10.1007/978-3-642-25379-9_14

[CastelloEtAl2024]

Castello, Jonathan and Patrick Redmond, Lindsey Kuper. (2024). “Inductive diagrams for causal reasoning”. In Proceedings of the ACM on Programming Languages, vol. 8, no. OOPSLA2, 2024. https://doi.org/10.48550/arXiv.2307.10484

[Chyp2023]

Chyp developers. (2023). “akissinger/chyp: An interactive theorem prover for string diagrams”. GitHub. https://github.com/akissinger/chyp

[CoeckeDuncan2011]

Coecke, Bob and Ross Duncan. (2011). “Interacting quantum observables: categorical algebra and diagrammatics”. In New Journal of Physics, vol. 13, no. 4, p. 043016, Apr. 2011. https://doi.org/10.1088/1367-2630/13/4/043016

[CoqLSP2023]

Coq LSP developers. (2023). “ejgallego/coq-lsp: Visual Studio Code Extension and Language Server Protocol for Coq”. GitHub. https://github.com/ejgallego/coq-lsp

[GrégoireMahboubi2005]

Grégoire, Benjamin and Assia Mahboubi. (2005). “Proving Equalities in a Commutative Ring Done Right in Coq”. In: J. Hurd and T. Melham (eds), Theorem Proving in Higher Order Logics, Springer, Berlin, Heidelberg, 2005, pp. 98–113. https://doi.org/10.1007/11541868_7

[Selinger2010] (1,2)

Selinger, P. (2010). A Survey of Graphical Languages for Monoidal Categories. In: Coecke, B. (eds), New Structures for Physics. Lecture Notes in Physics, vol. 813. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-642-12821-9_4

[ShahEtAl2024] (1,2)

Shah, Bhakti and William Spencer, Laura Zielinski, Ben Caldwell, Adrian Lehmann, Robert Rand. (2024). “ViCAR: Visualizing Categories with Automated Rewriting in Coq”. Preprint on arXiv. https://arxiv.org/abs/2404.08163

[ShahLehmann2024]

Shah, Bhakti and Adrian Lehmann. (2024). Personal correspondence via email.

[Sobociński2015] (1,2)

Sobociński, Paweł. (2015). Graphical Linear Algebra. https://graphicallinearalgebra.net/

[Ştefănescu2000]

Ştefănescu, Gheorghe. (2000). Network Algebra. In Discrete Mathematics and Theoretical Computer Science, Springer, London, 2000. https://doi.org/10.1007/978-1-4471-0479-7