Date:

Share:

# Egglog 2: Automatically Proving the Pullback of a Monic is Monic

### Stuck on a Bug? Here’s What to Do Next | by Michelle Soedal | Nov, 2021

Eglog https://github.com/philzook58/egglog Is a prologue-like syntax I deal with for egg Box Library. Check out the online demo here http://www.philipzucker.com/egglog/ (Rust attaches to wasm)

Last time I stopped, I just had a syntax to the usual egg structures of written rules that are actually protected. Turns out I was not that far from accepting a prototype of rules like Prologue that work. And from that it was just a short jump and skip doing something really cool. So here we go.

### Chasing Category Diagram

A dragon I’ve been chasing for a while is how to do categorical thinking automatically. From the very beginning I tried to prove that Monique’s retreat is Monique https://www.philipzucker.com/category-theory-in-the-e-automated-theorem-prover/. I have reason to doubt that this exact coding was sound, but I did not go back to it.

I have already used fists to do equation thinking in monoid categories https://www.philipzucker.com/rust-category/ But I did not realize that they can also be very useful in logic regarding universal features.

In principle the pursuit of diagrams should be easy. In a conversation with Cody Rowe, he described his catnapp project https://github.com/codyroux/catnapp And how was to solve such problems. According to him, the pursuit of diagrams involves the discovery / construction of new objects, the discovery / construction of new morphisms, the drawing of equality and the examination of known morphisms and equals in order to create known universal properties. You can go about it customized, but I think this procedure can be coded neatly into the egglog mechanisms, since the foundation clauses encode building new things and discovering new equality, and egglog strongly supports the idea of ​​equality that seems useful here.

Well, now I have a custom sentence proof that I built exactly to the purpose!

And here is my big sentence for today: e attract Of a Monique Morphism is also monastic.

To prove this we:

• Define composition and identity as structures
• Make associativity and identity absorption as axioms to rewrite
• Set up all the morphisms and arrows to create a square
• Define one arrow to be monique by providing the universal monique feature
• Define the square as a retreat in the statement that it is commutative (equality) and its universal state
• Display the query by defining two new arbitrary morphisms and asking if they are equal.

Here is a small assistant diagram to show what the morphisms and objects look like.

``````/* Axioms of category */

/* Typing rules */
/* identity exists */
type(id(A)) = hom(A,A) :- ob = type(A).

/* Composition exists if types work out */
type(comp(F,G)) = hom(A,C) :- hom(A,B) = type(F), hom(B,C) = type(G).

/*
Identity abosrption
*/
F <- comp(id(A), F).
F <- comp(F, id(A)).

/* associativity of composition */
comp(comp(F,G),H) <-> comp(F, comp(G,H)).

/* specify types */
type(a) = ob.
type(b) = ob.
type(c) = ob.
type(d) = ob.

type(f) = hom(a,b).
type(g) = hom(b,d).
type(h) = hom(a,c).
type(k) = hom(c,d).

/* assume g is monic. I could possibly dispense with the type conditions as an optimization. */
F = H :- comp(F,g) = comp(H,g), hom(A,b) = type(F), hom(A,b) = type(H).

/* square is pullback */
comp(f,g) = comp(h,k). /* square commutes */

/* universal triangle 1. There is a skolemization at play here */
comp(univ(F,H,E),h) = H
:- comp(F,g) = comp(H,k), hom(E,b) = type(F), hom(E,c) = type(H).

/* universal triangle 2 */
comp(univ(F,H,E),f) = F
:- comp(F,g) = comp(H,k), hom(E,b) = type(F), hom(E,c) = type(H).

/* uniqueness given square and triangles */
U = univ(F,H,E) :-
comp(F,g) = comp(H,k), comp(U,h) = H, comp(U,f) = F, hom(E,b) = type(F), hom(E,c) = type(H).

/* Theorem:
h is monic. === forall P Q, comp(P,h) = comp(Q,h), dom(P) = dom(Q) => P = Q

We can take p and q to left of sequent, or intro them.
They are arbitrary symbols. We introduce the domain as z.
*/
type(z) = ob.
type(p) = hom(z,a).
type(q) = hom(z,a).
comp(p,h) = comp(q,h).

?- p = q

``````

Note that this encoding relies heavily on the fact that only well-typed terms are inserted into the box.

It does bring it back `p=q`. I was alone when it worked. It’s also very fast. Fractions of a second. I hope something went wrong. You can try it for yourself on the egglog demo site http://www.philipzucker.com/egglog/ If you select this example from the drop-down menu.

I also threw away the box for visualization for this example. What is there makes sense to me. It’s actually quite interesting. Right-click to open it in the New tab to really show ## Egg pieces

General written egg built around `Searchers` and `Appliers`, Two features that define functions for checking and modifying the box. The right side of `:-` Need to adjust no `Searcher` And left side to an `Applier`. The interface defined by egg is a bit awkward for this purpose because it was designed with the rules of rewriting in mind. To make multipatterns work I defined the obvious structure.

``````struct MultiPattern<L>
patterns: Vec<EqWrap<Pattern<L>>>,

``````

And implemented the search feature for both `EqWrap` and `MultiPattern`. As a stopping gap, the way I did it was just by using each of the holdings `Pattern` Have `Searcher`, And then merge the variable bindings obtained using the following function.

``````fn merge_subst2(s1: &Subst, s2: &Subst) -> Option<Subst> {
let mut s1 = s1.clone();
for (v, i) in s2.vec.iter()
match s1.insert(*v, *i)
// Oh actually we should check
Some(i1) =>
if *i != i1
return None;

None => (),

return Some(s1);
}
``````

It’s extremely wasteful, but doing better requires me to dig deeper into the egg library, because I do not think the right guts are exposed for me to do better. What I need is that a pattern when composed will absorb a set of already known variables and the `search_eclass` Functions to absorb already known sub-binding. This is a problem that can be overcome.

In addition, I have added two new appliqués corresponding to equality on the left `:-` And an exposed term. `IgnoreApply` It is necessary that the default `Applier` To `Pattern` Will merge with the incoming eclass ID, which is not the semantics I want.

``````struct EqApply<L>
l: Pattern<L>,
r: Pattern<L>,

struct IgnoreApply<L>(Pattern<L>);
``````

After that it was just a matter of wiring it to the front. It seems simple now, but it all took a bit of digging.

• I thought there might be some fun and useful partial assessment by using the rust and mac machine mac commands. Although it does not help me since in egglog everything is defined dynamically.
• Something similar to the Lambda prologue in the sense of the supportive harrop formula seems feasible and useful for expression. It is possible in principle to fit on the box to add new rules to the rules system, and the gensym facility would be very nice and these are natural semantics of any quantity. I need some sort of abstraction mechanism at least. Writing the definition of withdrawal each time will not fly. I’m not sure what the answer is here.
• Patterns in queries will be good and easy. I just need to execute Multipatterns queries and return the array of ematches.
• I can add existing-unique also as a basic structure that expands and expands. It will go a lot.
• I set up my queries in a silly way.
• Back will be cool. https://rust-cli.github.io/book/index.html I need to improve the command line interface
• S-exp input, command and output format would be nice.

Source