@@ -317,7 +317,7 @@ def fundamental_group(self, simplify=True):
317
317
sage: Sigma3 = groups.permutation.Symmetric(3)
318
318
sage: BSigma3 = Sigma3.nerve()
319
319
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 >
321
321
sage: pi.order()
322
322
6
323
323
sage: pi.is_abelian()
@@ -331,19 +331,35 @@ def fundamental_group(self, simplify=True):
331
331
"""
332
332
# Import this here to prevent importing libgap upon startup.
333
333
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
335
341
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
+ TESTS::
348
+
349
+ sage: RP2 = simplicial_sets.RealProjectiveSpace(2)
350
+ sage: RP2._universal_cover_dict()
351
+ (Finitely presented group < e | e^2 >, {f: e})
352
+ sage: RP2.nondegenerate_simplices()
353
+ [1, f, f * f]
354
+ """
355
+ from sage .groups .free_group import FreeGroup
356
+ skel = self .n_skeleton (2 )
336
357
graph = skel .graph ()
337
358
if not skel .is_connected ():
338
359
graph = graph .subgraph (skel .base_point ())
339
-
340
- edges = [e [2 ] for e in graph .edges (sort = True )]
360
+ edges = [e [2 ] for e in graph .edges (sort = False )]
341
361
spanning_tree = [e [2 ] for e in graph .min_spanning_tree ()]
342
362
gens = [e for e in edges if e not in spanning_tree ]
343
-
344
- if not gens :
345
- return FreeGroup ([]).quotient ([])
346
-
347
363
gens_dict = dict (zip (gens , range (len (gens ))))
348
364
FG = FreeGroup (len (gens ), 'e' )
349
365
rels = []
@@ -361,10 +377,192 @@ def fundamental_group(self, simplify=True):
361
377
# sigma is not in the correct connected component.
362
378
z [i ] = FG .one ()
363
379
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 )
380
+ G = FG .quotient (rels )
381
+ char = {g : G .gen (i ) for i ,g in enumerate (gens )}
382
+ for e in edges :
383
+ if e not in gens :
384
+ char [e ] = G .one ()
385
+ return (G , char )
386
+
387
+
388
+ def universal_cover_map (self ):
389
+ r"""
390
+ Return the universal covering map of the simplicial set.
391
+
392
+ It requires the fundamental group to be finite.
393
+
394
+ EXAMPLES::
395
+
396
+ sage: RP2 = simplicial_sets.RealProjectiveSpace(2)
397
+ sage: phi = RP2.universal_cover_map()
398
+ sage: phi
399
+ Simplicial set morphism:
400
+ From: Simplicial set with 6 non-degenerate simplices
401
+ To: RP^2
402
+ Defn: [(1, 1), (1, e), (f, 1), (f, e), (f * f, 1), (f * f, e)] --> [1, 1, f, f, f * f, f * f]
403
+ sage: phi.domain().face_data()
404
+ {(1, 1): None,
405
+ (1, e): None,
406
+ (f, 1): ((1, e), (1, 1)),
407
+ (f, e): ((1, 1), (1, e)),
408
+ (f * f, 1): ((f, e), s_0 (1, 1), (f, 1)),
409
+ (f * f, e): ((f, 1), s_0 (1, e), (f, e))}
410
+
411
+ """
412
+ edges = self .n_cells (1 )
413
+ if not edges :
414
+ return self .identity ()
415
+ G , char = self ._universal_cover_dict ()
416
+ return self .covering_map (char )
417
+
418
+ def covering_map (self , character ):
419
+ r"""
420
+ Return the covering map associated to a character.
421
+
422
+ The character is represented by a dictionary that assigns an
423
+ element of a finite group to each nondegenerate 1-dimensional
424
+ cell. It should correspond to an epimorphism from the fundamental
425
+ group.
426
+
427
+ INPUT:
428
+
429
+ - ``character`` -- a dictionary
430
+
431
+
432
+ EXAMPLES::
433
+
434
+ sage: S1 = simplicial_sets.Sphere(1)
435
+ sage: W = S1.wedge(S1)
436
+ sage: G = CyclicPermutationGroup(3)
437
+ sage: a, b = W.n_cells(1)
438
+ sage: C = W.covering_map({a : G.gen(0), b : G.one()})
439
+ sage: C
440
+ Simplicial set morphism:
441
+ From: Simplicial set with 9 non-degenerate simplices
442
+ To: Wedge: (S^1 v S^1)
443
+ Defn: [(*, ()), (*, (1,2,3)), (*, (1,3,2)), (sigma_1, ()), (sigma_1, ()), (sigma_1, (1,2,3)), (sigma_1, (1,2,3)), (sigma_1, (1,3,2)), (sigma_1, (1,3,2))] --> [*, *, *, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1, sigma_1]
444
+ sage: C.domain()
445
+ Simplicial set with 9 non-degenerate simplices
446
+ sage: C.domain().face_data()
447
+ {(*, ()): None,
448
+ (*, (1,2,3)): None,
449
+ (*, (1,3,2)): None,
450
+ (sigma_1, ()): ((*, (1,2,3)), (*, ())),
451
+ (sigma_1, ()): ((*, ()), (*, ())),
452
+ (sigma_1, (1,2,3)): ((*, (1,3,2)), (*, (1,2,3))),
453
+ (sigma_1, (1,2,3)): ((*, (1,2,3)), (*, (1,2,3))),
454
+ (sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))),
455
+ (sigma_1, (1,3,2)): ((*, (1,3,2)), (*, (1,3,2)))}
456
+ """
457
+ from sage .topology .simplicial_set import AbstractSimplex , SimplicialSet
458
+ from sage .topology .simplicial_set_morphism import SimplicialSetMorphism
459
+ char = {a : b for (a ,b ) in character .items ()}
460
+ G = list (char .values ())[0 ].parent ()
461
+ if not G .is_finite ():
462
+ raise NotImplementedError ("can only compute universal covers of spaces with finite fundamental group" )
463
+ cells_dict = {}
464
+ faces_dict = {}
465
+
466
+ for s in self .n_cells (0 ):
467
+ for g in G :
468
+ cell = AbstractSimplex (0 ,name = "({}, {})" .format (s , g ))
469
+ cells_dict [(s ,g )] = cell
470
+ char [s ] = G .one ()
471
+
472
+ for d in range (1 , self .dimension () + 1 ):
473
+ for s in self .n_cells (d ):
474
+ if s not in char .keys ():
475
+ if d == 1 and s .is_degenerate ():
476
+ char [s ] = G .one ()
477
+ elif s .is_degenerate ():
478
+ if 0 in s .degeneracies ():
479
+ char [s ] = G .one ()
480
+ else :
481
+ char [s ] = char [s .nondegenerate ()]
482
+ else :
483
+ char [s ] = char [self .face (s , d )]
484
+ if s .is_nondegenerate ():
485
+ for g in G :
486
+ cell = AbstractSimplex (d ,name = "({}, {})" .format (s , g ))
487
+ cells_dict [(s ,g )] = cell
488
+ fd = []
489
+ faces = self .faces (s )
490
+ f0 = faces [0 ]
491
+ for h in G :
492
+ if h == g * char [s ]:
493
+ lifted = h
494
+ break
495
+ grelems = [cells_dict [(f0 .nondegenerate (), lifted )].apply_degeneracies (* f0 .degeneracies ())]
496
+ for f in faces [1 :]:
497
+ grelems .append (cells_dict [(f .nondegenerate (), g )].apply_degeneracies (* f .degeneracies ()))
498
+ faces_dict [cell ] = grelems
499
+ cover = SimplicialSet (faces_dict , base_point = cells_dict [(self .base_point (), G .one ())])
500
+ cover_map_data = {c : s [0 ] for (s ,c ) in cells_dict .items ()}
501
+ return SimplicialSetMorphism (data = cover_map_data , domain = cover , codomain = self )
502
+
503
+ def cover (self , character ):
504
+ r"""
505
+ Return the cover of the simplicial set associated to a character
506
+ of the fundamental group.
507
+
508
+ The character is represented by a dictionary, that assigns an
509
+ element of a finite group to each nondegenerate 1-dimensional
510
+ cell. It should correspond to an epimorphism from the fundamental
511
+ group.
512
+
513
+ INPUT:
514
+
515
+ - ``character`` -- a dictionary
516
+
517
+ EXAMPLES::
518
+
519
+ sage: S1 = simplicial_sets.Sphere(1)
520
+ sage: W = S1.wedge(S1)
521
+ sage: G = CyclicPermutationGroup(3)
522
+ sage: (a, b) = W.n_cells(1)
523
+ sage: C = W.cover({a : G.gen(0), b : G.gen(0)^2})
524
+ sage: C.face_data()
525
+ {(*, ()): None,
526
+ (*, (1,2,3)): None,
527
+ (*, (1,3,2)): None,
528
+ (sigma_1, ()): ((*, (1,2,3)), (*, ())),
529
+ (sigma_1, ()): ((*, (1,3,2)), (*, ())),
530
+ (sigma_1, (1,2,3)): ((*, (1,3,2)), (*, (1,2,3))),
531
+ (sigma_1, (1,2,3)): ((*, ()), (*, (1,2,3))),
532
+ (sigma_1, (1,3,2)): ((*, ()), (*, (1,3,2))),
533
+ (sigma_1, (1,3,2)): ((*, (1,2,3)), (*, (1,3,2)))}
534
+ sage: C.homology(1)
535
+ Z x Z x Z x Z
536
+ sage: C.fundamental_group()
537
+ Finitely presented group < e0, e1, e2, e3 | >
538
+ """
539
+ return self .covering_map (character ).domain ()
540
+
541
+ def universal_cover (self ):
542
+ r"""
543
+ Return the universal cover of the simplicial set.
544
+ The fundamental group must be finite in order to ensure that the
545
+ universal cover is a simplicial set of finite type.
546
+
547
+ EXAMPLES::
548
+
549
+ sage: RP3 = simplicial_sets.RealProjectiveSpace(3)
550
+ sage: C = RP3.universal_cover()
551
+ sage: C
552
+ Simplicial set with 8 non-degenerate simplices
553
+ sage: C.face_data()
554
+ {(1, 1): None,
555
+ (1, e): None,
556
+ (f, 1): ((1, e), (1, 1)),
557
+ (f, e): ((1, 1), (1, e)),
558
+ (f * f, 1): ((f, e), s_0 (1, 1), (f, 1)),
559
+ (f * f, e): ((f, 1), s_0 (1, e), (f, e)),
560
+ (f * f * f, 1): ((f * f, e), s_0 (f, 1), s_1 (f, 1), (f * f, 1)),
561
+ (f * f * f, e): ((f * f, 1), s_0 (f, e), s_1 (f, e), (f * f, e))}
562
+ sage: C.fundamental_group()
563
+ Finitely presented group < | >
564
+ """
565
+ return self .universal_cover_map ().domain ()
368
566
369
567
def is_simply_connected (self ):
370
568
"""
0 commit comments