Skip to content

Commit f150aa8

Browse files
author
Kris Brown
committed
factoring morphisms into composites in C-Set as well as slice cats.
update for HomSearch split
1 parent 05cfe2a commit f150aa8

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

src/categorical_algebra/CSets.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import ...Theories: ob, hom, dom, codom, compose, ⋅, id,
2727
using ..FreeDiagrams, ..Limits, ..Subobjects, ..Sets, ..FinSets, ..FinCats
2828
using ..FinSets: VarFunction, LooseVarFunction, IdentityFunction, VarSet
2929
import ..Limits: limit, colimit, universal
30+
import ...Theories: compose, , id, meet, , join, , top, ⊤, bottom, ⊥
31+
using ..FreeDiagrams, ..Limits, ..Subobjects, ..FinSets, ..FinCats
32+
import ..Limits: limit, colimit, universal, factorize
3033
import ..Subobjects: Subobject, implies, , subtract, \, negate, ¬, non, ~
3134
import ..Sets: SetOb, SetFunction, TypeSet
3235
using ..Sets
@@ -666,7 +669,6 @@ end
666669
@cartesian_monoidal_instance ACSet ACSetTransformation
667670
@cocartesian_monoidal_instance ACSet ACSetTransformation
668671

669-
670672
# Limits and colimits
671673
#####################
672674

src/categorical_algebra/HomSearch.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using ...Theories, ..CSets, ..FinSets, ..FreeDiagrams, ..Subobjects
1616
using ...Graphs.BasicGraphs
1717
using ..CSets: map_components
1818
using ACSets.DenseACSets: attrtype_type, delete_subobj!
19+
import ..Limits: factorize
1920

2021
using Random
2122
using CompTime
@@ -471,6 +472,59 @@ function escape_assignment_lhs(expr)
471472
end
472473

473474

475+
476+
# Factorization
477+
###############
478+
479+
""" factorize(s::Span; initial=Dict(), single=true, kw...)
480+
481+
Factor a morphism f: A->C by finding a morphism h: B → C such that f=g⋅h.
482+
483+
B
484+
g ↗ ↘ h = ?
485+
A ⟶ C
486+
f
487+
488+
This function assumes that the general form of factorizing involves creating an
489+
"initial" dict for homomorphism search. In some categories this may not be the
490+
case, which would mean factorize_constraints should actually return a dictionary
491+
that gets passed as kwargs to homomorphism search.
492+
"""
493+
function factorize(s::Span; initial=Dict(), single::Bool=true, kw...)
494+
f, g = s
495+
init = factorize_constraints(f,g; initial=initial)
496+
if isnothing(init) return single ? nothing : typeof(f)[] end
497+
search = single ? homomorphism : homomorphisms
498+
search(codom(g), codom(f); initial=NamedTuple(init), kw...)
499+
end
500+
501+
"""
502+
Use the data of f:A->C and g:A->B to initialize search for Hom(B,C)
503+
if f(a) = c, then g(a) must equal c.
504+
"""
505+
function factorize_constraints(f::ACSetTransformation,
506+
g::ACSetTransformation;
507+
initial=Dict())
508+
dom(f) == dom(g) || error("f and g are not a span: $jf \n$jg")
509+
S = acset_schema(dom(f))
510+
res = Dict{Symbol, Dict{Int,Int}}()
511+
for o in ob(S)
512+
init = haskey(initial, o) ? initial[o] : Dict{Int,Int}()
513+
for (a, g_a) in enumerate(collect(g[o]))
514+
f_a = f[o](a)
515+
if haskey(init, g_a)
516+
if init[g_a] != f_a
517+
return nothing
518+
end
519+
else
520+
init[g_a] = f_a
521+
end
522+
end
523+
res[o] = init
524+
end
525+
return res
526+
end
527+
474528
# Maximum Common C-Set
475529
######################
476530

src/categorical_algebra/Slices.jl

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ using ...Theories: ThCategory
99
import ...Theories: dom, codom, compose, id
1010
import ..Limits: limit, colimit, universal
1111
import ..FinSets: force
12-
12+
import ..CSets: is_natural, components
13+
import ..HomSearch: factorize_constraints, homomorphism, homomorphisms, factorize
1314
"""
1415
The data of the object of a slice category (say, some category C sliced over an
1516
object X in Ob(C)) is the data of a homomorphism in Hom(A,X) for some ob A.
@@ -86,6 +87,9 @@ function slice_diagram(f::FreeDiagram)::FreeDiagram
8687
FreeDiagram(obs,homs)
8788
end
8889

90+
factorize_constraints(f::SliceHom,g::SliceHom; initial=Dict()) =
91+
factorize_constraints(f.f,g.f; initial=initial)
92+
8993
"""
9094
Convert a limit problem in the slice category to a limit problem of the
9195
underlying category.
@@ -132,4 +136,51 @@ function universal(lim::SliceLimit, sp::Multispan)
132136
return SliceHom(apx, apx2, u)
133137
end
134138

139+
is_natural(x::SliceHom) = is_natural(x.f)
140+
components(x::SliceHom) = components(x.f)
141+
Base.getindex::SliceHom, c) = x.f[c]
142+
143+
"""
144+
This could be made more efficient as a constraint *during* homomorphism finding.
145+
146+
This would require implementing a new constraint to homomorphism search that
147+
restricts the codomain for each part of A, i.e. ∀ a ∈ A: h(a) ∈ g⁻¹(f(a)).
148+
"""
149+
function homomorphisms(X::Slice,Y::Slice; kw...)
150+
map(filter(h->force(X.slice)==force(compose(h,Y.slice)),
151+
homomorphisms(dom(X), dom(Y); kw...)) ) do h
152+
SliceHom(X, Y, h)
153+
end |> collect
154+
end
155+
156+
"""
157+
Because the constraint isn't incorporated into the search process, we cannot
158+
stop early.
159+
"""
160+
function homomorphism(X::Slice,Y::Slice; kw...)
161+
hs = homomorphisms(X,Y; kw...)
162+
return isempty(hs) ? nothing : first(hs)
163+
end
164+
165+
"""
166+
Factorizing a cospan is equivalent to looking for a slice morphism. f->g
167+
168+
B
169+
h = ? ↗ ↘ g
170+
A ⟶ C
171+
f
172+
"""
173+
function factorize(s::Cospan; initial=Dict(), single::Bool=true, kw...)
174+
f, g = Slice.(s)
175+
search = single ? homomorphism : homomorphisms
176+
res = search(f, g; initial=NamedTuple(initial), kw...)
177+
if isnothing(res)
178+
return nothing
179+
else
180+
return [x.f for x in res]
181+
end
182+
end
183+
184+
185+
135186
end # module

test/categorical_algebra/HomSearch.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,20 @@ end
148148
@test_throws ErrorException @acset_transformation g h begin V = [4,3,2,1]; E = [1,2,3,4] end
149149

150150

151+
# Factorizing morphisms
152+
#----------------------
153+
154+
p2, p3 = path_graph(Graph, 2), path_graph(Graph, 3)
155+
loop = apex(terminal(Graph))
156+
f = ACSetTransformation(Graph(2), p3; V=[2,1])
157+
g1 = ACSetTransformation(Graph(2), p2; V=[1,2])
158+
g2 = ACSetTransformation(Graph(2), p2; V=[2,1])
159+
@test isnothing(factorize(Span(f, g1)))
160+
@test length(factorize(Span(f, g2); single=false)) == 1
161+
f2 = homomorphism(Graph(2), loop)
162+
@test isnothing(factorize(Span(f2, id(Graph(2))); monic=true))
163+
@test factorize(Span(f2, id(Graph(2)))) == f2
164+
151165
# Enumeration of subobjects
152166
###########################
153167

test/categorical_algebra/Slices.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,32 @@ slice_dia = FreeDiagram{Slice,SliceHom}(Multispan(A, [f, g]))
5959
clim = colimit(slice_dia)
6060
@test is_isomorphic(dom(apex(clim)), d)
6161

62+
63+
# Factorizing morphisms (morally same tests as in CSets)
64+
#-------------------------------------------------------
65+
p2G, p3G = [path_graph(Graph, x) for x in [3,5]]
66+
p2, p3 = [Slice(homomorphism(p, two)) for p in [p2G,p3G]] # ⊚→□→⊚ and ⊚→□→⊚□→⊚
67+
loop = Slice(id(two)) # ⊚ ↔ □
68+
g2G = Slice(ACSetTransformation(Graph(2), two; V=[1,1])) # ⊚ ⊚
69+
f = SliceHom(g2G, p3, ACSetTransformation(Graph(2), p3G; V=[3,1]))
70+
g1 = SliceHom(g2G, p2, CSetTransformation(Graph(2), p2G; V=[1,3]))
71+
g2 = SliceHom(g2G, p2, CSetTransformation(Graph(2), p2G; V=[3,1]))
72+
@test isnothing(factorize(Span(f, g1)))
73+
@test length(factorize(Span(f, g2); single=false)) == 1
74+
f2 = homomorphism(g2G, loop)
75+
@test isnothing(factorize(Span(f2, id(g2G)); monic=true))
76+
@test factorize(Span(f2, id(g2G))) == f2
77+
78+
# Factorize C-set morphisms where the second one is known
79+
#--------------------------------------------------------
80+
81+
A = path_graph(Graph, 2)
82+
B = @acset Graph begin V=4; E=3; src=[1,1,3]; tgt=[2,4,4] end
83+
C = @acset Graph begin V=2; E=2; src=1; tgt=2 end
84+
85+
f = ACSetTransformation(A, C; V=[1,2], E=[1])
86+
g = ACSetTransformation(B, C; V=[1,2,1,2], E=[1,2,1])
87+
88+
@test length(factorize(Cospan(f,g); single=false)) == 2
89+
6290
end # module

0 commit comments

Comments
 (0)