A symmetric graph is a Graph with an involution reversing arrows:
Every arrow comes paired with its reverse, so a symmetric graph is a model of an undirected graph. Like graphs, symmetric graphs are the instances (-sets) of a small indexing category : objects , generating arrows and , with the three equations above as path equivalences (CTfS Exercise 4.2.1.21). Morphisms of symmetric graphs are the natural transformations — graph homomorphisms commuting with .
Sources: CTfS §4.2.1.19 (Exercises 4.2.1.21–4.2.1.23); Catlab’s
SymmetricGraph(the schemaSchSymmetricGraph, with calledinv).
Examples
- Undirected graphs: an undirected edge with becomes the pair of arrows , swapped by . A loop at can be encoded either by one arrow fixed by or by two arrows swapped by — symmetric graphs distinguish these “half-edge” and “full” loops, a subtlety plain undirected graphs hide.
- Road networks, friendship graphs, molecules — anywhere “adjacent to” is a symmetric relation. The graph used for the automorphism group in Endomorphism Monoid is the symmetric 4-cycle.
- The 1-skeleton of a Simplicial Complex is a symmetric graph without loops.
- Which graphs are symmetric? (CTfS Exercise 4.2.1.22) Being symmetric is structure, a choice of : a graph admits one iff for every pair of vertices there are as many arrows as . (one vertex, one arrow) is symmetric with ; the doubled 4-cycle of CTfS Exercise 4.2.1.11 is symmetric; a graph with an arrow but none back is not.
Relating graphs and symmetric graphs
The inclusion of the graph-indexing category into induces, by precomposition, the forgetful functor taking a symmetric graph to its underlying graph, which has both directions of each edge (CTfS Exercise 4.2.1.23c). This is a Data Migration Functor; its left adjoint symmetrizes a graph by freely adding a reverse for each arrow.
Counting functors (CTfS Exercise 4.2.1.23). There are exactly 9 functors : the hom-sets of are , (since ), , . Sending gives choices for ; gives another ; gives ; and gives . The “reasonable” one, , , is ; another sends both to , and precomposition with it takes a symmetric graph to the graph with one loop per arrow at its source.
Docs: C-set morphisms · Graphs
using Catlab
# Catlab's symmetric graphs: every edge is stored with its reverse, `inv` is the involution ρ
g = path_graph(SymmetricGraph, 3) # the undirected path 1 — 2 — 3
nv(g), ne(g) # (3, 4): two edges, each in both directions
all(g[g[e, :inv], :inv] == e for e in edges(g)) # ρ ∘ ρ = id
all(g[g[e, :inv], :src] == g[e, :tgt] for e in edges(g)) # src ∘ ρ = tgt
# the underlying graph Δ_i (forget ρ): the migration along i : SchGraph → SchSymmetricGraph
U = Graph(nv(g)); add_edges!(U, g[:src], g[:tgt])
ne(U) # 4 directed arrows
# the symmetric 4-cycle of CTfS Exercise 4.2.1.11
length(isomorphisms(cycle_graph(SymmetricGraph, 4), cycle_graph(SymmetricGraph, 4))) # 8import Mathlib
-- Mathlib's undirected graphs are symmetric irreflexive relations:
#check SimpleGraph -- Adj : V → V → Prop, symm, loopless
#check @SimpleGraph.Dart -- an arrow of the associated symmetric graph
#check @SimpleGraph.Dart.symm -- the involution ρ reversing a dart
#check @SimpleGraph.Dart.symm_symm -- ρ ∘ ρ = id-- a symmetric graph: arrows are stored with their reversal ρ
data SymGraph = SymGraph { nV :: Int, arrows :: [(Int, Int)], rho :: Int -> Int }
-- symmetrize: freely add a reverse for each arrow (the left adjoint Σ_i)
symmetrize :: Int -> [(Int, Int)] -> SymGraph
symmetrize n es = SymGraph n (es ++ map swap es) r
where k = length es
r j = if j < k then j + k else j - k
swap (x, y) = (y, x)
-- laws: rho (rho j) == j; fst (arrows !! rho j) == snd (arrows !! j)