solution

Solutions to the exercises of 7 Sketches, Chapter 6: 7S Chapter 6 Exercises. Index: Map of Content.

Solution 6.3

example — Exercise 6.3

  1. The Discrete Preorder on (only and ): neither nor , so no element has a morphism to every other.
  2. The Walking Arrow : is the unique initial object.
  3. The Codiscrete Preorder ( and ): both and are initial. Note that they are isomorphic, as 7S Exercise 6.10 predicts.

Sources: 7 Sketches, Exercise 6.3 and Solution A.6.

Solution 6.6

example — Exercise 6.6

The objects of a free category are the vertices and the morphisms are paths, so an initial object is a vertex with exactly one path to every vertex (including itself).

  1. Yes: , whose only path to itself is the empty path.
  2. Yes: has a unique path to , , .
  3. No: there is no path from to nor from to .
  4. No: has infinitely many paths to itself (the loop iterated times), so the hom-set is not a singleton.

Sources: 7 Sketches, Exercise 6.6 and Solution A.6.

Solution 6.7

proof — Exercise 6.7

  1. and .
  2. The Natural Numbers rig . Given any rig , a homomorphism must send , , and by additivity

so is determined. This formula also preserves multiplication: by distributivity, ( times) ( times) expands to the sum of copies of , which is . Hence there is exactly one rig homomorphism , i.e. is initial.

import Mathlib
-- ℕ is the initial semiring: the unique ring hom is the canonical cast.
#check @Nat.castRingHom            -- (R : Type) [NonAssocSemiring R] : ℕ →+* R
#check @RingHom.eq_natCast         -- every f : ℕ →+* R equals Nat.cast
-- the unique rig homomorphism from Nat into any semiring
fromNat :: Num r => Integer -> r
fromNat 0 = 0
fromNat n = 1 + fromNat (n - 1)

Sources: 7 Sketches, Exercise 6.7 and Solution A.6.

Solution 6.8

annotation — Exercise 6.8

The initial object is the universal thing. Since the property quantifies over all objects of , every object counts as a “comparable object”. The Universal Property then reads: for every there is a unique morphism .

Sources: 7 Sketches, Exercise 6.8 and Solution A.6.

Solution 6.10

proof — Exercise 6.10

Since is initial there is a unique ; since is initial there is a unique . Now has a unique morphism because is initial, and both and are such morphisms, so . Symmetrically . Hence is an isomorphism, and it is the unique isomorphism between them: initial objects are unique up to unique isomorphism.

import Mathlib
open CategoryTheory Limits
#check @Limits.initialIsoIsInitial   -- IsInitial X → (⊥_ C ≅ X)
#check @Limits.IsInitial.uniqueUpToIso

Sources: 7 Sketches, Exercise 6.10 and Solution A.6.

Solution 6.13

proof — Exercise 6.13

A preorder is a category with at most one morphism between any two objects, so every diagram commutes. Unfolding the definition of coproduct: is an element with and (the inclusions), such that whenever and we have (the unique copairing). That is exactly the least upper bound .

Dually Products are Meets, and the Initial Object is the bottom element.

Sources: 7 Sketches, Exercise 6.13 and Solution A.6.

Solution 6.16

example — Exercise 6.16

applebananapearcherryorangeappletomatomango
abpcoeoo

The Coproduct in is the disjoint union, so the two apples are distinct elements with different images.

using Catlab
A = FinSet(5); B = FinSet(3); T = FinSet(26)            # letters as 1..26
letter(c) = Int(c) - Int('a') + 1
f = FinFunction(letter.(['a','b','p','c','o']), 26)     # first letters
g = FinFunction(letter.(['e','o','o']), 26)             # last letters
cp = coproduct(A, B)
h = copair(cp, f, g)                                    # [f, g] : 8 → 26
collect(h)                                              # [1, 2, 16, 3, 15, 5, 15, 15]
copair :: (a -> t) -> (b -> t) -> Either a b -> t
copair = either
-- either (head) (last) :: Either String String -> Char

Sources: 7 Sketches, Exercise 6.16 and Solution A.6.

Solution 6.17

proof — Exercise 6.17

1–2. These are exactly the two commuting triangles in the diagram defining the copairing . 3. Both and are morphisms whose precompositions with are and (by 1–2). The Universal Property says such a morphism is unique, so they are equal. 4. satisfies and ; by uniqueness of the copairing, .

import Mathlib
open CategoryTheory Limits
#check @Limits.coprod.inl_desc   -- coprod.inl ≫ coprod.desc f g = f
#check @Limits.coprod.inr_desc
#check @Limits.coprod.desc_comp  -- coprod.desc f g ≫ h = coprod.desc (f ≫ h) (g ≫ h)
#check @Limits.coprod.desc_inl_inr
-- either f g . Left  == f
-- either f g . Right == g
-- h . either f g == either (h . f) (h . g)
-- either Left Right == id

Sources: 7 Sketches, Exercise 6.17 and Solution A.6.

Solution 6.18

proof — Exercise 6.18

  1. On objects take the coproduct; on a morphism set . Identities are preserved: by 7S Exercise 6.17 (4). Composition is preserved because both and equal by uniqueness of copairing.
  2. Let be the unique map. The copairing is inverse to : , and (using that and are both maps out of the initial object). Symmetrically for .
  3. (a) with inverse . (b) where , are the inclusions of the other coproduct; its inverse is the analogous map , and by 7S Exercise 6.17 (3–4).

The same argument dualised shows that finite Products give a symmetric monoidal structure (Cartesian Category).

using Catlab
f = FinFunction([1, 2], 3); g = FinFunction([1], 2)
fg = oplus(f, g)                       # f + g : 3 → 5 in the prop FinSet
collect(fg)                            # [1, 2, 4]
import Mathlib
open CategoryTheory
-- Mathlib packages exactly this: coproducts give a monoidal structure.
#check @CategoryTheory.monoidalOfHasFiniteCoproducts
import Data.Bifunctor (bimap)          -- bimap f g :: Either a b -> Either c d
assoc :: Either (Either a b) c -> Either a (Either b c)
assoc = either (either Left (Right . Left)) (Right . Right)
swap :: Either a b -> Either b a
swap = either Right Left

Sources: 7 Sketches, Exercise 6.18 and Solution A.6.

Solution 6.24

proof — Exercise 6.24

  1. A span in consists of identities, so , and the square of identities on is a pushout: any cocone consists of two equal maps (both identities, so ), and the identity is the unique mediating map.
  2. Exactly when . If there is no object at all; if are two objects there is no morphism .

Sources: 7 Sketches, Exercise 6.24 and Solution A.6.

Solution 6.26

example program — Exercise 6.26

The pushout is the set of connected components of under the relation generated by : , , , . The classes are , , , : the pushout is , with given by and given by .

using Catlab
f = FinFunction([1, 3, 5, 5], 5)
g = FinFunction([1, 1, 2, 3], 3)
P = pushout(f, g)
ob(P)                     # FinSet(4)
collect.(legs(P))         # ([1, 2, 1, 3, 4], [1, 4, 4])
-- pushout of finite functions via union-find on the disjoint union
import Data.List (nub)
pushout :: Int -> Int -> [Int] -> [Int] -> [[Int]]   -- classes of 5 ⊔ 3, elements of Y offset
pushout nx ny f g = classes (zip f (map (+ nx) g)) [1 .. nx + ny]
  where classes rel xs = nub [ closure [x] | x <- xs ]
          where step cs = nub (cs ++ [ b | (a,b) <- rel, a `elem` cs ] ++ [ a | (a,b) <- rel, b `elem` cs ])
                closure cs = let cs' = step cs in if length cs' == length cs then cs else closure cs'
-- pushout 5 3 [1,3,5,5] [1,1,2,3] gives 4 classes

Sources: 7 Sketches, Exercise 6.26 and Solution A.6; Kittenlab lecture on colimits (union-find).

Solution 6.28

proof — Exercise 6.28

  1. The square , commutes because there is only one map ; so .
  2. Given , (the square with commutes automatically), the universal property of the coproduct gives a unique with and .
  3. Conversely, if the pushout exists then for any as above, the outer square commutes (again because is initial), so the pushout property gives a unique with , . This is exactly the universal property of the coproduct.

Sources: 7 Sketches, Exercise 6.28 and Solution A.6.

Solution 6.35

proof — Exercise 6.35

Suppose is a Cocone on the original diagram: maps from to making the two squares with and commute. Since is the pushout of there is a unique compatible with ; since is the pushout of there is a unique compatible with . Both agree with the given map on , so forms a cocone on , and the pushout gives a unique making everything commute. Hence is the colimit. This is the mechanism behind Finite Colimits in Set: an initial object and pushouts give all finite colimits.

import Mathlib
open CategoryTheory Limits
-- finite colimits from an initial object and pushouts
#check @CategoryTheory.Limits.hasFiniteColimits_of_hasInitial_and_pushouts

Sources: 7 Sketches, Exercise 6.35 and Solution A.6.

Solution 6.41

proof — Exercise 6.41

Theorem 6.37 says the colimit is the quotient of by the equivalence relation generated by if and if . Every is related to , so each class contains an element of ; thus the quotient equals the quotient of by the relation generated by , which is exactly Example 6.25.

Sources: 7 Sketches, Exercise 6.41 and Solution A.6.

Solution 6.48

example — Exercise 6.48

The monoidal product of cospans and is the cospan : one simply stacks the two wiring pictures vertically (disjoint union of apices and of feet). See Hypergraph Category for the general structure.

using Catlab
c1 = Cospan(FinFunction([1, 1], 2), FinFunction([2], 2))       # A=2 → N=2 ← B=1
c2 = Cospan(FinFunction([1], 3), FinFunction([1, 2, 3], 3))   # B=1 → P=3 ← C=3
c12 = Cospan(oplus(left(c1), left(c2)), oplus(right(c1), right(c2)))
apex(c12)                                                     # FinSet(5) = N + P

Sources: 7 Sketches, Exercise 6.48 and Solution A.6.

Solution 6.49

annotation — Exercise 6.49

Concatenate the two wire diagrams along the shared foot . (i) The apex of the composite has one element for each connected component of the concatenated picture (this is the Pushout as a set of connected components, cf. Colimits and Connection). (ii) Each element of the outer feet , is wired to the element representing the component it belongs to.

Sources: 7 Sketches, Exercise 6.49 and Solution A.6.

Solution 6.57

example — Exercise 6.57

By Theorem 6.55 (the spider theorem: a connected Frobenius diagram is determined by its number of inputs and outputs), two connected diagrams with the same inputs and outputs are equal, and a disconnected diagram is determined by its partition of the ports. Morphisms 1, 4 and 6 are equal (a single connected spider ); morphisms 3 and 5 are equal (the same disconnected pattern); morphism 2 is not equal to any other.

Sources: 7 Sketches, Exercise 6.57 and Solution A.6.

Solution 6.59

example — Exercise 6.59

  1. : the wire into comes from a spider whose other legs are labelled , and spiders connect only wires of the same type.
  2. , since and ‘s output shares a spider with ‘s outputs.
  3. as well, for the same reason.

Sources: 7 Sketches, Exercise 6.59 and Solution A.6.

Solution 6.62

example — Exercise 6.62

cospanwiring
multiplication two wires merging into one
unit a wire starting from nothing
comultiplication one wire splitting into two
counit a wire ending in nothing

The empty set is depicted as blank space.

using Catlab
μ = Cospan(FinFunction([1, 1], 1), FinFunction([1], 1))
η = Cospan(FinFunction(Int[], 1), FinFunction([1], 1))
δ = Cospan(FinFunction([1], 1), FinFunction([1, 1], 1))
ε = Cospan(FinFunction([1], 1), FinFunction(Int[], 1))

Sources: 7 Sketches, Exercise 6.62 and Solution A.6.

Solution 6.63

proof — Exercise 6.63

The composite is the cospan , so it suffices to show that the square with at the top left, two copies of , and two identities is a Pushout. It commutes trivially. Given with , precomposing with and using (7S Exercise 6.17) gives . Then is the unique map from the apex making the cocone commute. Hence the pushout apex is with identity legs, i.e. .

using Catlab
X = FinSet(2)
δ = Cospan(id(X), FinFunction([1, 2, 1, 2], 2))
μ = Cospan(FinFunction([1, 2, 1, 2], 2), id(X))
P = pushout(right(δ), left(μ))
ob(P)                                # FinSet(2): the special law holds

Sources: 7 Sketches, Exercise 6.63 and Solution A.6.

Solution 6.67

proof — Exercise 6.67

The cup is and the cap is . The snake equation is proved by the chain: apply the Frobenius law (6.53) to move the past the , obtaining ; the missing diagram is this middle step, in which the unit and counit are attached to the multiplication and comultiplication respectively. Then the unit law and its opposite reduce it to .

Sources: 7 Sketches, Exercise 6.67 and Solution A.6.

Solution 6.70

proof — Exercise 6.70

Let , . Then

so the square commutes.

Sources: 7 Sketches, Exercise 6.70 and Solution A.6.

Solution 6.78

annotation — Exercise 6.78

Take constant at the singleton ; it is lax symmetric monoidal (all structure maps are the unique map into ). A morphism in is a cospan together with an element of , i.e. no extra choice. Composition is the usual pushout composition since the decoration is forced. Hence via the identity-on-objects functor that decorates each cospan with ; category theorists happily call these “equal”.

Sources: 7 Sketches, Exercise 6.78 and Solution A.6.

Solution 6.79

example program — Exercise 6.79

, , with

dluluruldl
ulurdrurdr

A -circuit is precisely an edge-labelled Graph (C-Set on the schema of graphs with a label attribute).

using Catlab
@present SchCircuit <: SchGraph begin
  Label::AttrType
  label::Attr(E, Label)
end
@acset_type Circuit(SchCircuit, index=[:src, :tgt])
# vertices 1=ul 2=ur 3=dl 4=dr
c = @acset Circuit{String} begin
  V = 4; E = 5
  src = [3, 1, 2, 1, 3]; tgt = [1, 2, 4, 2, 4]
  label = ["1Ω", "2Ω", "1Ω", "3F", "1H"]
end
data Circuit v l = Circuit { arrows :: [(v, v, l)] }   -- (s a, t a, ℓ a)
c :: Circuit String String
c = Circuit [("dl","ul","1Ω"),("ul","ur","2Ω"),("ur","dr","1Ω"),("ul","ur","3F"),("dl","dr","1H")]

Sources: 7 Sketches, Exercise 6.79 and Solution A.6.

Solution 6.80

example — Exercise 6.80

The decoration functor acts on a function by relabelling vertices: . So has vertices and the resistor now runs from the merged vertex to ; the wire from ends at .

using Catlab
# Circ(f) is the pushforward of the vertex set: Σ-migration along f on V
@present SchCircuit <: SchGraph begin Label::AttrType; label::Attr(E, Label) end
@acset_type Circuit(SchCircuit, index=[:src, :tgt])
c = @acset Circuit{String} begin V = 4; E = 1; src = [3]; tgt = [4]; label = ["3Ω"] end
f = [1, 2, 2, 3]                                    # 4 → 3, identifies 2 and 3
c′ = @acset Circuit{String} begin V = 3; E = 1; src = f[c[:src]]; tgt = f[c[:tgt]]; label = c[:label] end

Sources: 7 Sketches, Exercise 6.80 and Solution A.6.

Solution 6.82

example — Exercise 6.82

takes the disjoint union of labelled graphs: is the 4-vertex circuit consisting of the battery between vertices and the switch between vertices , with no connection between them. This laxator is what makes a lax Monoidal Functor, and thus a Hypergraph Category (Decorated Cospan).

using Catlab
@present SchCircuit <: SchGraph begin Label::AttrType; label::Attr(E, Label) end
@acset_type Circuit(SchCircuit, index=[:src, :tgt])
b = @acset Circuit{Symbol} begin V = 2; E = 1; src = [1]; tgt = [2]; label = [:battery] end
s = @acset Circuit{Symbol} begin V = 2; E = 1; src = [1]; tgt = [2]; label = [:switch] end
ψ = ob(coproduct(b, s))          # ψ₂,₂(b, s): 4 vertices, 2 edges

Sources: 7 Sketches, Exercise 6.82 and Solution A.6.

Solution 6.84

example — Exercise 6.84

The cospan is with , . The decoration is the -circuit with , , : an open battery whose two terminals are exposed on the left and right. See the Julia snippet in Decorated Cospan.

Sources: 7 Sketches, Exercise 6.84 and Solution A.6.

Solution 6.86

example program — Exercise 6.86

The first is the cospan , , , decorated by the circuit of 7S Exercise 6.79. The second is with , , , , decorated by with (), ().

Composing: the Pushout of identifies into one vertex , giving (five vertices), and the composite cospan has and . The decoration is of the pushout applied to : arrows , , , , , , . This matches Eq. (6.74).

using Catlab
@present SchCircuit <: SchGraph begin Label::AttrType; label::Attr(E, Label) end
@acset_type Circuit(SchCircuit, index=[:src, :tgt])
const OpenCircuitOb, OpenCircuit = OpenACSetTypes(Circuit, :V)
# vertices 1=ul 2=ur 3=dl 4=dr
C = @acset Circuit{String} begin V = 4; E = 5
  src = [3, 1, 2, 1, 3]; tgt = [1, 2, 4, 2, 4]; label = ["1Ω", "2Ω", "1Ω", "3F", "1H"] end
C′ = @acset Circuit{String} begin V = 3; E = 2       # 1=l 2=r 3=d
  src = [1, 2]; tgt = [2, 3]; label = ["5Ω", "8Ω"] end
x = OpenCircuit{String}(C, FinFunction([1], 4), FinFunction([2, 2], 4))
y = OpenCircuit{String}(C′, FinFunction([1, 3], 3), FinFunction([2, 2], 3))
xy = compose(x, y)
nparts(apex(xy), :V), nparts(apex(xy), :E)          # (5, 7)

Sources: 7 Sketches, Exercise 6.86 and Solution A.6.

Solution 6.88

example — Exercise 6.88

identifies the two left terminals of into one vertex (a wire closing the left side); then also identifies the two right terminals. The result is a cospan decorated with the circuit of in which the left pair and the right pair of terminals are each merged: a closed loop with no exposed terminals. Such closed circuits are the scalars of the Hypergraph Category.

using Catlab
@present SchCircuit <: SchGraph begin Label::AttrType; label::Attr(E, Label) end
@acset_type Circuit(SchCircuit, index=[:src, :tgt])
const OpenCircuitOb, OpenCircuit = OpenACSetTypes(Circuit, :V)
x = @acset Circuit{Symbol} begin V = 4; E = 2; src = [1, 3]; tgt = [2, 4]; label = [:battery, :resistor] end
ox = OpenCircuit{Symbol}(x, FinFunction([1, 3], 4), FinFunction([2, 4], 4))
empty1 = @acset Circuit{Symbol} begin V = 1 end
η = OpenCircuit{Symbol}(empty1, FinFunction(Int[], 1), FinFunction([1, 1], 1))
ε = OpenCircuit{Symbol}(empty1, FinFunction([1, 1], 1), FinFunction(Int[], 1))
closed = compose(η, ox, ε)
nparts(apex(closed), :V), nparts(apex(closed), :E)   # (2, 2): a closed loop

Sources: 7 Sketches, Exercise 6.88 and Solution A.6.

Solution 6.96

example program — Exercise 6.96

  1. Two inner circles with two ports each, an outer circle with two ports, and three links: one port of the first circle is wired to a port of the second; the remaining port of each inner circle is wired to an outer port.
  2. Three inner circles with two ports each, no outer ports; the links connect the circles in a chain.
  3. substitutes into the first circle of ; the operad composition is a pushout of the apices along the shared foot . Its arity is : four inner circles and no outer ports.
  4. The drawing shows ‘s two circles sitting where the first circle of used to be — literally substitution of one wiring diagram into a circle of another.
using Catlab
f = UndirectedWiringDiagram(2)        # outer circle with 2 ports
add_box!(f, 2); add_box!(f, 2)        # two inner circles, 2 ports each
add_junctions!(f, 3)                  # apex 3
set_junction!(f, [1, 2, 2, 3])        # box ports → junctions
set_junction!(f, [1, 3], outer=true)  # outer ports → junctions
g = UndirectedWiringDiagram(0)
add_box!(g, 2); add_box!(g, 2); add_box!(g, 2)
add_junctions!(g, 3)
set_junction!(g, [1, 2, 2, 3, 3, 1])
h = ocompose(g, 1, f)                 # substitute f into box 1 of g
nboxes(h), length(ports(h, outer=true)), njunctions(h)   # (4, 0, 4)

Sources: 7 Sketches, Exercise 6.96 and Solution A.6.