# We need to tell Catlab how to convert our `LGraph` type into the normal `Graph` type by taking just the edges and vertices. This could be computed with Functorial Data Migration, but that is left for another sketch.

to_graph(g::LGraph)=begin

h=Graphs.Graph(nparts(g,:V))

foreinedges(g)

add_edge!(h,g[e,:src],g[e,:tgt])

end

returnh

h=Graphs.Graph(nparts(g,:V))

foreinedges(g)

add_edge!(h,g[e,:src],g[e,:tgt])

end

returnh

end

# Graphviz doesn't automatically know how we want to draw the labels, so we have to explicitly provide code that converts them to colors on the vertices. Note that we aren't calling these colored graphs, because that would imply some connectivity constraints on which vertices are allowed to be colored with the same colors. These labels are arbitrary, but we use color to visually encode them.

# Now we can start making some `LGraph` instances.

G=@acsetLGraphbegin

V=4

E=4

L=4

src=[1,1,2,3]

tgt=[2,3,4,4]

label=[1,2,3,4]

V=4

E=4

L=4

src=[1,1,2,3]

tgt=[2,3,4,4]

label=[1,2,3,4]

end

draw(G)

# The graph `G` has a 1-1 map between vertices and labels. That isn't necessary.

H=@acsetLGraphbegin

V=4

E=4

L=3

src=[1,1,2,3]

tgt=[2,3,4,4]

label=[1,2,2,3]

V=4

E=4

L=3

src=[1,1,2,3]

tgt=[2,3,4,4]

label=[1,2,2,3]

end

draw(H)

# We can look at some homomorphisms from G to H by their action on the labels or on the vertices.

homsᵥ(G,H)=map(homomorphisms(G,H))doα

components(α).V

end

homsₗ(G,H)=map(homomorphisms(G,H))doα

components(α).L

end

homsᵥ(G,H)=map(α->α[:V],homomorphisms(G,H))

homsₗ(G,H)=map(α->α[:L],homomorphisms(G,H))

# αₗ: G→ H

homsₗ(G,H)

@ -100,23 +94,23 @@ homsᵥ(H,G)

# We can build some bigger examples like A.

A=@acsetLGraphbegin

V=6

E=7

L=3

src=[1,1,2,3,2,5,4]

tgt=[2,3,4,4,5,6,6]

label=[1,2,2,3,2,3]

V=6

E=7

L=3

src=[1,1,2,3,2,5,4]

tgt=[2,3,4,4,5,6,6]

label=[1,2,2,3,2,3]

end

draw(A)

# and B.

B=@acsetLGraphbegin

V=6

E=7

L=4

src=[1,1,2,3,2,5,4]

tgt=[2,3,4,4,5,6,6]

label=[1,2,4,3,2,3]

V=6

E=7

L=4

src=[1,1,2,3,2,5,4]

tgt=[2,3,4,4,5,6,6]

label=[1,2,4,3,2,3]

end

draw(B)

@ -142,42 +136,44 @@ draw(apex(product(G,G)))

# The graph above looks weirdly disconnected and probably wasn't what you expected to see as the product. When we compose with products, we often want to add the reflexive edges in order to get the expected notion of product.

add_loops!(G::LGraph)=begin

forvinparts(G,:V)

add_edge!(G,v,v)

end

returnG

forvinparts(G,:V)

add_edge!(G,v,v)

end

returnG

end

add_loops(G::LGraph)=add_loops!(copy(G))

Gᵣ=add_loops(G)

P=apex(product(Gᵣ,G))

draw(apex(product(Gᵣ,G)))

# We can look at the shape of commuting triangle, which is our favorite 3-vertex graph.

T=@acsetLGraphbegin

V=3

E=3

L=3

src=[1,1,2]

tgt=[2,3,3]

label=[1,2,3]

V=3

E=3

L=3

src=[1,1,2]

tgt=[2,3,3]

label=[1,2,3]

end

Tᵣ=add_loops(T)

draw(Tᵣ)

E=@acsetLGraphbegin

V=2

E=1

L=2

src=[1]

tgt=[2]

label=[1,2]

V=2

E=1

L=2

src=[1]

tgt=[2]

label=[1,2]

end

Eᵣ=add_loops(E)

draw(Eᵣ)

# We can draw the product of the edge graph and the triangle graph to get the shape of a triangular prism. You can view this product as extruding `Tᵣ` along `Eᵣ`. Catlab provides a `ReflexiveGraph` as a type that handles these self-loops more intelligently than we are here. Graphviz struggles with the layout here because the product graph will include edges that are a step in both directions. This [blog post](https://www.algebraicjulia.org/blog/post/2021/04/cset-graphs-3/) does a good job explaining products in differnt kinds of graph categories.

draw(apex(product(Tᵣ,Eᵣ)))

components(legs(product(Tᵣ,Eᵣ))[1]).V|>collect

legs(product(Tᵣ,Eᵣ))[1][:V]|>collect

# Another limit is the pullback. If you have a cospan, which is a diagram of the shape `X ⟶ A ⟵ Y`, you can pull back one arrow along the other by solving a system of equations.

# In order to illustrate this we will be gluing triangles together to make a mesh. We start by defining the point `X`, which is the shape of the boundary along which we will glue and the morphism `ℓ₁`, which is the place in `T` that we consider as the boundary.

X=@acsetLGraphbegin

E=0

V=1

L=3

label=[2]

E=0

V=1

L=3

label=[2]

end

ℓ₁=ACSetTransformation(X,T,V=[2],L=1:3)

draw(X)

@ -209,9 +205,9 @@ draw(apex(P))

# Now we want to repeat the gluing process to get a bigger mesh. So we are going to need a bigger interface.