Skip to content

Commit 9be1db0

Browse files
committed
Deduplicate code in fundamental group and universal cover
1 parent 59b4f54 commit 9be1db0

File tree

2 files changed

+54
-72
lines changed

2 files changed

+54
-72
lines changed

src/sage/categories/simplicial_sets.py

Lines changed: 53 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def fundamental_group(self, simplify=True):
317317
sage: Sigma3 = groups.permutation.Symmetric(3)
318318
sage: BSigma3 = Sigma3.nerve()
319319
sage: pi = BSigma3.fundamental_group(); pi
320-
Finitely presented group < e0, e1 | e0^2, e1^3, (e0*e1^-1)^2 >
320+
Finitely presented group < e1, e2 | e2^2, e1^3, (e2*e1)^2 >
321321
sage: pi.order()
322322
6
323323
sage: pi.is_abelian()
@@ -331,19 +331,27 @@ def fundamental_group(self, simplify=True):
331331
"""
332332
# Import this here to prevent importing libgap upon startup.
333333
from sage.groups.free_group import FreeGroup
334-
skel = self.n_skeleton(2)
334+
if not self.n_cells(1):
335+
return FreeGroup([]).quotient([])
336+
FG = self._universal_cover_dict()[0]
337+
if simplify:
338+
return FG.simplified()
339+
else:
340+
return FG
335341

342+
def _universal_cover_dict(self):
343+
r"""
344+
Return the fundamental group and dictionary sending each edge to
345+
the corresponding group element
346+
"""
347+
from sage.groups.free_group import FreeGroup
348+
skel = self.n_skeleton(2)
336349
graph = skel.graph()
337350
if not skel.is_connected():
338351
graph = graph.subgraph(skel.base_point())
339-
340-
edges = [e[2] for e in graph.edges(sort=True)]
352+
edges = [e[2] for e in graph.edges(sort=False)]
341353
spanning_tree = [e[2] for e in graph.min_spanning_tree()]
342354
gens = [e for e in edges if e not in spanning_tree]
343-
344-
if not gens:
345-
return FreeGroup([]).quotient([])
346-
347355
gens_dict = dict(zip(gens, range(len(gens))))
348356
FG = FreeGroup(len(gens), 'e')
349357
rels = []
@@ -361,10 +369,13 @@ def fundamental_group(self, simplify=True):
361369
# sigma is not in the correct connected component.
362370
z[i] = FG.one()
363371
rels.append(z[0]*z[1].inverse()*z[2])
364-
if simplify:
365-
return FG.quotient(rels).simplified()
366-
else:
367-
return FG.quotient(rels)
372+
G = FG.quotient(rels)
373+
char = {g : G.gen(i) for i,g in enumerate(gens)}
374+
for e in edges:
375+
if not e in gens:
376+
char[e] = G.one()
377+
return (G, char)
378+
368379

369380
def universal_cover_map(self):
370381
r"""
@@ -382,48 +393,18 @@ def universal_cover_map(self):
382393
To: RP^2
383394
Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] --> [1, 1, f, f, f * f, f * f]
384395
sage: phi.domain().face_data()
385-
{(f, 1): ((1, e), (1, 1)),
386-
(f, e): ((1, 1), (1, e)),
387-
(f * f, 1): ((f, e), s_0 (1, 1), (f, 1)),
388-
(f * f, e): ((f, 1), s_0 (1, e), (f, e)),
389-
(1, e): None,
390-
(1, 1): None}
396+
{(1, 1): None,
397+
(1, e): None,
398+
(f, 1): ((1, e), (1, 1)),
399+
(f, e): ((1, 1), (1, e)),
400+
(f * f, 1): ((f, e), s_0 (1, 1), (f, 1)),
401+
(f * f, e): ((f, 1), s_0 (1, e), (f, e))}
391402
392403
"""
393-
from sage.groups.free_group import FreeGroup
394-
skel = self.n_skeleton(2)
395-
graph = skel.graph()
396-
if not skel.is_connected():
397-
graph = graph.subgraph(skel.base_point())
398-
edges = [e[2] for e in graph.edges(sort=False)]
399-
spanning_tree = [e[2] for e in graph.min_spanning_tree()]
400-
gens = [e for e in edges if e not in spanning_tree]
401-
402-
if not gens:
403-
return self
404-
405-
gens_dict = dict(zip(gens, range(len(gens))))
406-
FG = FreeGroup(len(gens), 'e')
407-
rels = []
408-
409-
for f in skel.n_cells(2):
410-
z = dict()
411-
for i, sigma in enumerate(skel.faces(f)):
412-
if sigma in spanning_tree:
413-
z[i] = FG.one()
414-
elif sigma.is_degenerate():
415-
z[i] = FG.one()
416-
elif sigma in edges:
417-
z[i] = FG.gen(gens_dict[sigma])
418-
else:
419-
# sigma is not in the correct connected component.
420-
z[i] = FG.one()
421-
rels.append(z[0]*z[1].inverse()*z[2])
422-
G = FG.quotient(rels)
423-
char = {g : G.gen(i) for i,g in enumerate(gens)}
424-
for e in edges:
425-
if not e in gens:
426-
char[e] = G.one()
404+
edges = self.n_cells(1)
405+
if not edges:
406+
return self.identity()
407+
G, char = self._universal_cover_dict()
427408
return self.covering_map(char)
428409

429410
def covering_map(self, character):
@@ -445,6 +426,7 @@ def covering_map(self, character):
445426
sage: S1 = simplicial_sets.Sphere(1)
446427
sage: W = S1.wedge(S1)
447428
sage: G = CyclicPermutationGroup(3)
429+
sage: a, b = W.n_cells(1)
448430
sage: C = W.covering_map({a : G.gen(0), b : G.one()})
449431
sage: C
450432
Simplicial set morphism:
@@ -454,15 +436,15 @@ def covering_map(self, character):
454436
sage: C.domain()
455437
Simplicial set with 9 non-degenerate simplices
456438
sage: C.domain().face_data()
457-
{(sigma_1, ()): ((*, ()), (*, ())),
458-
(sigma_1, (1,2,3)): ((*, (1,2,3)), (*, (1,2,3))),
459-
(sigma_1, (1,3,2)): ((*, (1,3,2)), (*, (1,3,2))),
439+
{(*, ()): None,
440+
(*, (1,2,3)): None,
441+
(*, (1,3,2)): None,
442+
(sigma_1, ()): ((*, (1,2,3)), (*, ())),
460443
(sigma_1, ()): ((*, ()), (*, ())),
444+
(sigma_1, (1,2,3)): ((*, (1,3,2)), (*, (1,2,3))),
461445
(sigma_1, (1,2,3)): ((*, (1,2,3)), (*, (1,2,3))),
462-
(sigma_1, (1,3,2)): ((*, (1,3,2)), (*, (1,3,2))),
463-
(*, ()): None,
464-
(*, (1,3,2)): None,
465-
(*, (1,2,3)): None}
446+
(sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))),
447+
(sigma_1, (1,3,2)): ((*, (1,3,2)), (*, (1,3,2)))}
466448
467449
"""
468450
from sage.topology.simplicial_set import AbstractSimplex, SimplicialSet
@@ -531,17 +513,17 @@ def cover(self, character):
531513
sage: W = S1.wedge(S1)
532514
sage: G = CyclicPermutationGroup(3)
533515
sage: (a, b) = W.n_cells(1)
534-
sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2}).domain()
516+
sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2})
535517
sage: C.face_data()
536-
{(sigma_1, ()): ((*, (1,2,3)), (*, ())),
537-
(sigma_1, (1,2,3)): ((*, (1,3,2)), (*, (1,2,3))),
538-
(sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))),
518+
{(*, ()): None,
519+
(*, (1,2,3)): None,
520+
(*, (1,3,2)): None,
521+
(sigma_1, ()): ((*, (1,2,3)), (*, ())),
539522
(sigma_1, ()): ((*, (1,3,2)), (*, ())),
523+
(sigma_1, (1,2,3)): ((*, (1,3,2)), (*, (1,2,3))),
540524
(sigma_1, (1,2,3)): ((*, ()), (*, (1,2,3))),
541-
(sigma_1, (1,3,2)): ((*, (1,2,3)), (*, (1,3,2))),
542-
(*, (1,2,3)): None,
543-
(*, ()): None,
544-
(*, (1,3,2)): None}
525+
(sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))),
526+
(sigma_1, (1,3,2)): ((*, (1,2,3)), (*, (1,3,2)))}
545527
sage: C.homology(1)
546528
Z x Z x Z x Z
547529
sage: C.fundamental_group()
@@ -563,14 +545,14 @@ def universal_cover(self):
563545
sage: C
564546
Simplicial set with 8 non-degenerate simplices
565547
sage: C.face_data()
566-
{(f, 1): ((1, e), (1, 1)),
548+
{(1, 1): None,
549+
(1, e): None,
550+
(f, 1): ((1, e), (1, 1)),
567551
(f, e): ((1, 1), (1, e)),
568552
(f * f, 1): ((f, e), s_0 (1, 1), (f, 1)),
569553
(f * f, e): ((f, 1), s_0 (1, e), (f, e)),
570554
(f * f * f, 1): ((f * f, e), s_0 (f, 1), s_1 (f, 1), (f * f, 1)),
571-
(f * f * f, e): ((f * f, 1), s_0 (f, e), s_1 (f, e), (f * f, e)),
572-
(1, e): None,
573-
(1, 1): None}
555+
(f * f * f, e): ((f * f, 1), s_0 (f, e), s_1 (f, e), (f * f, e))}
574556
sage: C.fundamental_group()
575557
Finitely presented group < | >
576558

src/sage/topology/simplicial_set.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
sage: Sigma3 = groups.permutation.Symmetric(3)
174174
sage: BSigma3 = Sigma3.nerve()
175175
sage: pi = BSigma3.fundamental_group(); pi
176-
Finitely presented group < e0, e1 | e0^2, e1^3, (e0*e1^-1)^2 >
176+
Finitely presented group < e1, e2 | e2^2, e1^3, (e2*e1)^2 >
177177
sage: pi.order()
178178
6
179179
sage: pi.is_abelian()

0 commit comments

Comments
 (0)