passagemath-groups 10.6.41__cp314-cp314t-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. passagemath_groups/__init__.py +3 -0
  2. passagemath_groups-10.6.41.dist-info/METADATA +113 -0
  3. passagemath_groups-10.6.41.dist-info/RECORD +36 -0
  4. passagemath_groups-10.6.41.dist-info/WHEEL +5 -0
  5. passagemath_groups-10.6.41.dist-info/top_level.txt +3 -0
  6. sage/all__sagemath_groups.py +21 -0
  7. sage/geometry/all__sagemath_groups.py +1 -0
  8. sage/geometry/palp_normal_form.cpython-314t-x86_64-linux-musl.so +0 -0
  9. sage/geometry/palp_normal_form.pyx +401 -0
  10. sage/groups/abelian_gps/all.py +25 -0
  11. sage/groups/all.py +5 -0
  12. sage/groups/all__sagemath_groups.py +32 -0
  13. sage/groups/artin.py +1074 -0
  14. sage/groups/braid.py +3806 -0
  15. sage/groups/cactus_group.py +1001 -0
  16. sage/groups/cubic_braid.py +2052 -0
  17. sage/groups/finitely_presented.py +1896 -0
  18. sage/groups/finitely_presented_catalog.py +27 -0
  19. sage/groups/finitely_presented_named.py +592 -0
  20. sage/groups/fqf_orthogonal.py +579 -0
  21. sage/groups/free_group.py +944 -0
  22. sage/groups/group_exp.py +360 -0
  23. sage/groups/group_semidirect_product.py +504 -0
  24. sage/groups/kernel_subgroup.py +231 -0
  25. sage/groups/lie_gps/all.py +1 -0
  26. sage/groups/lie_gps/catalog.py +8 -0
  27. sage/groups/lie_gps/nilpotent_lie_group.py +945 -0
  28. sage/groups/misc_gps/all.py +1 -0
  29. sage/groups/misc_gps/misc_groups.py +11 -0
  30. sage/groups/misc_gps/misc_groups_catalog.py +33 -0
  31. sage/groups/raag.py +866 -0
  32. sage/groups/semimonomial_transformations/all.py +1 -0
  33. sage/groups/semimonomial_transformations/semimonomial_transformation.cpython-314t-x86_64-linux-musl.so +0 -0
  34. sage/groups/semimonomial_transformations/semimonomial_transformation.pxd +9 -0
  35. sage/groups/semimonomial_transformations/semimonomial_transformation.pyx +346 -0
  36. sage/groups/semimonomial_transformations/semimonomial_transformation_group.py +512 -0
sage/groups/raag.py ADDED
@@ -0,0 +1,866 @@
1
+ # sage_setup: distribution = sagemath-groups
2
+ # sage.doctest: needs sage.graphs sage.rings.number_field
3
+ r"""
4
+ Right-Angled Artin Groups
5
+
6
+ A *right-angled Artin group* (often abbreviated as RAAG) is a group which
7
+ has a presentation whose only relations are commutators between generators.
8
+ These are also known as graph groups, since they are (uniquely) encoded by
9
+ (simple) graphs, or partially commutative groups.
10
+
11
+ AUTHORS:
12
+
13
+ - Travis Scrimshaw (2013-09-01): Initial version
14
+ - Travis Scrimshaw (2018-02-05): Made compatible with
15
+ :class:`~sage.groups.artin.ArtinGroup`
16
+ """
17
+ # ***************************************************************************
18
+ # Copyright (C) 2013,2018 Travis Scrimshaw <tcscrims at gmail.com>
19
+ #
20
+ # This program is free software: you can redistribute it and/or modify
21
+ # it under the terms of the GNU General Public License as published by
22
+ # the Free Software Foundation, either version 2 of the License, or
23
+ # (at your option) any later version.
24
+ # https://www.gnu.org/licenses/
25
+ # ****************************************************************************
26
+ from sage.libs.gap.element import GapElement
27
+
28
+ from sage.misc.cachefunc import cached_method
29
+ from sage.structure.richcmp import richcmp
30
+ from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
31
+ from sage.groups.free_group import FreeGroup
32
+ from sage.groups.artin import ArtinGroup, ArtinGroupElement
33
+ from sage.graphs.graph import Graph
34
+ from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix
35
+ from sage.combinat.root_system.coxeter_group import CoxeterGroup
36
+
37
+ from sage.combinat.free_module import CombinatorialFreeModule
38
+ from sage.categories.fields import Fields
39
+ from sage.categories.groups import Groups
40
+ from sage.categories.algebras_with_basis import AlgebrasWithBasis
41
+ from sage.algebras.clifford_algebra_element import CohomologyRAAGElement
42
+ from sage.typeset.ascii_art import ascii_art
43
+ from sage.typeset.unicode_art import unicode_art
44
+
45
+
46
+ class RightAngledArtinGroup(ArtinGroup):
47
+ r"""
48
+ The right-angled Artin group defined by a graph `G`.
49
+
50
+ Let `\Gamma = \{V(\Gamma), E(\Gamma)\}` be a simple graph.
51
+ A *right-angled Artin group* (commonly abbreviated as RAAG) is the group
52
+
53
+ .. MATH::
54
+
55
+ A_{\Gamma} = \langle g_v : v \in V(\Gamma)
56
+ \mid [g_u, g_v] \text{ if } \{u, v\} \notin E(\Gamma) \rangle.
57
+
58
+ These are sometimes known as graph groups or partially commutative groups.
59
+ This RAAG's contains both free groups, given by the complete graphs,
60
+ and free abelian groups, given by disjoint vertices.
61
+
62
+ .. WARNING::
63
+
64
+ This is the opposite convention of some papers.
65
+
66
+ Right-angled Artin groups contain many remarkable properties and have a
67
+ very rich structure despite their simple presentation. Here are some
68
+ known facts:
69
+
70
+ - The word problem is solvable.
71
+ - They are known to be rigid; that is for any finite simple graphs
72
+ `\Delta` and `\Gamma`, we have `A_{\Delta} \cong A_{\Gamma}` if and
73
+ only if `\Delta \cong \Gamma` [Dro1987]_.
74
+ - They embed as a finite index subgroup of a right-angled Coxeter group
75
+ (which is the same definition as above except with the additional
76
+ relations `g_v^2 = 1` for all `v \in V(\Gamma)`).
77
+ - In [BB1997]_, it was shown they contain subgroups that satisfy the
78
+ property `FP_2` but are not finitely presented by considering the
79
+ kernel of `\phi : A_{\Gamma} \to \ZZ` by `g_v \mapsto 1` (i.e. words of
80
+ exponent sum 0).
81
+ - `A_{\Gamma}` has a finite `K(\pi, 1)` space.
82
+ - `A_{\Gamma}` acts freely and cocompactly on a finite dimensional
83
+ `CAT(0)` space, and so it is biautomatic.
84
+ - Given an Artin group `B` with generators `s_i`, then any subgroup
85
+ generated by a collection of `v_i = s_i^{k_i}` where `k_i \geq 2` is a
86
+ RAAG where `[v_i, v_j] = 1` if and only if `[s_i, s_j] = 1` [CP2001]_.
87
+
88
+ The normal forms for RAAG's in Sage are those described in [VW1994]_ and
89
+ gathers commuting groups together.
90
+
91
+ INPUT:
92
+
93
+ - ``G`` -- a graph
94
+ - ``names`` -- string or list of generator names
95
+
96
+ EXAMPLES::
97
+
98
+ sage: Gamma = Graph(4)
99
+ sage: G = RightAngledArtinGroup(Gamma)
100
+ sage: a,b,c,d = G.gens()
101
+ sage: a*c*d^4*a^-3*b
102
+ v0^-2*v1*v2*v3^4
103
+
104
+ sage: Gamma = graphs.CompleteGraph(4)
105
+ sage: G = RightAngledArtinGroup(Gamma)
106
+ sage: a,b,c,d = G.gens()
107
+ sage: a*c*d^4*a^-3*b
108
+ v0*v2*v3^4*v0^-3*v1
109
+
110
+ sage: Gamma = graphs.CycleGraph(5)
111
+ sage: G = RightAngledArtinGroup(Gamma)
112
+ sage: G
113
+ Right-angled Artin group of Cycle graph
114
+ sage: a,b,c,d,e = G.gens()
115
+ sage: d*b*a*d
116
+ v1*v3^2*v0
117
+ sage: e^-1*c*b*e*b^-1*c^-4
118
+ v2^-3
119
+
120
+ We create the previous example but with different variable names::
121
+
122
+ sage: G.<a,b,c,d,e> = RightAngledArtinGroup(Gamma)
123
+ sage: G
124
+ Right-angled Artin group of Cycle graph
125
+ sage: d*b*a*d
126
+ b*d^2*a
127
+ sage: e^-1*c*b*e*b^-1*c^-4
128
+ c^-3
129
+
130
+ REFERENCES:
131
+
132
+ - [Cha2006]_
133
+ - [BB1997]_
134
+ - [Dro1987]_
135
+ - [CP2001]_
136
+ - [VW1994]_
137
+
138
+ - :wikipedia:`Artin_group#Right-angled_Artin_groups`
139
+ """
140
+ @staticmethod
141
+ def __classcall_private__(cls, G, names=None):
142
+ """
143
+ Normalize input to ensure a unique representation.
144
+
145
+ TESTS::
146
+
147
+ sage: G1 = RightAngledArtinGroup(graphs.CycleGraph(5))
148
+ sage: Gamma = Graph([(0,1),(1,2),(2,3),(3,4),(4,0)])
149
+ sage: G2 = RightAngledArtinGroup(Gamma)
150
+ sage: G3 = RightAngledArtinGroup([(0,1),(1,2),(2,3),(3,4),(4,0)])
151
+ sage: G4 = RightAngledArtinGroup(Gamma, 'v')
152
+ sage: G1 is G2 and G2 is G3 and G3 is G4
153
+ True
154
+
155
+ Handle the empty graph::
156
+
157
+ sage: RightAngledArtinGroup(Graph())
158
+ Traceback (most recent call last):
159
+ ...
160
+ ValueError: the graph must not be empty
161
+ """
162
+ if not isinstance(G, Graph):
163
+ G = Graph(G, immutable=True)
164
+ else:
165
+ G = G.copy(immutable=True)
166
+ if G.num_verts() == 0:
167
+ raise ValueError("the graph must not be empty")
168
+ if names is None:
169
+ names = 'v'
170
+ if isinstance(names, str):
171
+ if ',' in names:
172
+ names = [x.strip() for x in names.split(',')]
173
+ else:
174
+ names = [names + str(v) for v in G.vertices(sort=False)]
175
+ names = tuple(names)
176
+ if len(names) != G.num_verts():
177
+ raise ValueError("the number of generators must match the"
178
+ " number of vertices of the defining graph")
179
+ return super().__classcall__(cls, G, names)
180
+
181
+ def __init__(self, G, names):
182
+ """
183
+ Initialize ``self``.
184
+
185
+ TESTS::
186
+
187
+ sage: G = RightAngledArtinGroup(graphs.CycleGraph(5))
188
+ sage: TestSuite(G).run()
189
+ sage: G.category()
190
+ Category of infinite groups
191
+ """
192
+ self._graph = G
193
+ F = FreeGroup(names=names)
194
+ CG = Graph(G).complement() # Make sure it's mutable
195
+ CG.relabel() # Standardize the labels
196
+ cm = [[-1] * CG.num_verts() for _ in range(CG.num_verts())]
197
+ for i in range(CG.num_verts()):
198
+ cm[i][i] = 1
199
+ for u, v in CG.edge_iterator(labels=False):
200
+ cm[u][v] = 2
201
+ cm[v][u] = 2
202
+ self._coxeter_group = CoxeterGroup(CoxeterMatrix(cm, index_set=G.vertices(sort=True)))
203
+ rels = tuple(F([i + 1, j + 1, -i - 1, -j - 1])
204
+ for i, j in CG.edge_iterator(labels=False)) # +/- 1 for indexing
205
+ FinitelyPresentedGroup.__init__(self, F, rels,
206
+ category=Groups().Infinite())
207
+
208
+ def _repr_(self) -> str:
209
+ """
210
+ Return a string representation of ``self``.
211
+
212
+ TESTS::
213
+
214
+ sage: RightAngledArtinGroup(graphs.CycleGraph(5))
215
+ Right-angled Artin group of Cycle graph
216
+ """
217
+ return "Right-angled Artin group of {}".format(self._graph)
218
+
219
+ def gen(self, i):
220
+ """
221
+ Return the ``i``-th generator of ``self``.
222
+
223
+ EXAMPLES::
224
+
225
+ sage: Gamma = graphs.CycleGraph(5)
226
+ sage: G = RightAngledArtinGroup(Gamma)
227
+ sage: G.gen(2)
228
+ v2
229
+ """
230
+ return self.element_class(self, ([i, 1],))
231
+
232
+ def gens(self) -> tuple:
233
+ """
234
+ Return the generators of ``self``.
235
+
236
+ EXAMPLES::
237
+
238
+ sage: Gamma = graphs.CycleGraph(5)
239
+ sage: G = RightAngledArtinGroup(Gamma)
240
+ sage: G.gens()
241
+ (v0, v1, v2, v3, v4)
242
+ sage: Gamma = Graph([('x', 'y'), ('y', 'zeta')])
243
+ sage: G = RightAngledArtinGroup(Gamma)
244
+ sage: G.gens()
245
+ (vx, vy, vzeta)
246
+ """
247
+ return tuple(self.gen(i) for i in range(self._graph.num_verts()))
248
+
249
+ def ngens(self):
250
+ """
251
+ Return the number of generators of ``self``.
252
+
253
+ EXAMPLES::
254
+
255
+ sage: Gamma = graphs.CycleGraph(5)
256
+ sage: G = RightAngledArtinGroup(Gamma)
257
+ sage: G.ngens()
258
+ 5
259
+ """
260
+ return self._graph.num_verts()
261
+
262
+ def graph(self):
263
+ """
264
+ Return the defining graph of ``self``.
265
+
266
+ EXAMPLES::
267
+
268
+ sage: Gamma = graphs.CycleGraph(5)
269
+ sage: G = RightAngledArtinGroup(Gamma)
270
+ sage: G.graph()
271
+ Cycle graph: Graph on 5 vertices
272
+ """
273
+ return self._graph
274
+
275
+ @cached_method
276
+ def one(self):
277
+ """
278
+ Return the identity element `1`.
279
+
280
+ EXAMPLES::
281
+
282
+ sage: Gamma = graphs.CycleGraph(5)
283
+ sage: G = RightAngledArtinGroup(Gamma)
284
+ sage: G.one()
285
+ 1
286
+ """
287
+ return self.element_class(self, ())
288
+
289
+ one_element = one
290
+
291
+ def _element_constructor_(self, x):
292
+ """
293
+ Construct an element of ``self`` from ``x``.
294
+
295
+ TESTS::
296
+
297
+ sage: Gamma = graphs.CycleGraph(5)
298
+ sage: G = RightAngledArtinGroup(Gamma)
299
+ sage: elt = G([[0,3], [3,1], [2,1], [1,1], [3,1]]); elt
300
+ v0^3*v3*v2*v1*v3
301
+ sage: G(elt)
302
+ v0^3*v3*v2*v1*v3
303
+ sage: G(1)
304
+ 1
305
+ """
306
+ if isinstance(x, RightAngledArtinGroup.Element):
307
+ raise ValueError("there is no coercion from {} into {}".format(x.parent(), self))
308
+ if x == 1:
309
+ return self.one()
310
+ verts = self._graph.vertices(sort=True)
311
+ x = [[verts.index(s[0]), s[1]] for s in x]
312
+ return self.element_class(self, self._normal_form(x))
313
+
314
+ def _normal_form(self, word):
315
+ """
316
+ Return the normal form of the word ``word``.
317
+
318
+ Helper function for creating elements.
319
+
320
+ EXAMPLES::
321
+
322
+ sage: Gamma = graphs.CycleGraph(5)
323
+ sage: G = RightAngledArtinGroup(Gamma)
324
+ sage: G._normal_form([[0,2], [3,1], [2,1], [0,1], [1,1], [3,1]])
325
+ ([0, 3], [3, 1], [2, 1], [1, 1], [3, 1])
326
+ sage: a,b,c,d,e = G.gens()
327
+ sage: a^2 * d * c * a * b * d
328
+ v0^3*v3*v2*v1*v3
329
+ sage: a*b*d == d*a*b and a*b*d == a*d*b
330
+ True
331
+ sage: a*c*a^-1*c^-1
332
+ 1
333
+ sage: (a*b*c*d*e)^2 * (a*b*c*d*e)^-2
334
+ 1
335
+ """
336
+ pos = 0
337
+ G = self._graph
338
+ v = G.vertices(sort=True)
339
+ w = [list(x) for x in word] # Make a (2 level) deep copy
340
+ while pos < len(w):
341
+ comm_set = [w[pos][0]]
342
+ # The current set of totally commuting elements
343
+ i = pos + 1
344
+
345
+ while i < len(w):
346
+ letter = w[i][0] # The current letter
347
+ # Check if this could fit in the commuting set
348
+ if letter in comm_set:
349
+ # Try to move it in
350
+ if any(G.has_edge(v[w[j][0]], v[letter])
351
+ for j in range(pos + len(comm_set), i)):
352
+ # We can't, so go onto the next letter
353
+ i += 1
354
+ continue
355
+ j = comm_set.index(letter)
356
+ w[pos + j][1] += w[i][1]
357
+ w.pop(i)
358
+ i -= 1 # Since we removed a syllable
359
+ # Check cancellations
360
+ if w[pos + j][1] == 0:
361
+ w.pop(pos + j)
362
+ comm_set.pop(j)
363
+ i -= 1
364
+ if not comm_set:
365
+ pos = 0
366
+ # Start again since cancellation can be pronounced effects
367
+ break
368
+ elif all(not G.has_edge(v[w[j][0]], v[letter])
369
+ for j in range(pos, i)):
370
+ j = 0
371
+ for x in comm_set:
372
+ if x > letter:
373
+ break
374
+ j += 1
375
+ w.insert(pos + j, w.pop(i))
376
+ comm_set.insert(j, letter)
377
+
378
+ i += 1
379
+ pos += len(comm_set)
380
+ return tuple(w)
381
+
382
+ def cohomology(self, F=None):
383
+ """
384
+ Return the cohomology ring of ``self`` over the field ``F``.
385
+
386
+ EXAMPLES::
387
+
388
+ sage: C4 = graphs.CycleGraph(4)
389
+ sage: A = groups.misc.RightAngledArtin(C4)
390
+ sage: A.cohomology()
391
+ Cohomology ring of Right-angled Artin group of Cycle graph
392
+ with coefficients in Rational Field
393
+ """
394
+ if F is None:
395
+ from sage.rings.rational_field import QQ
396
+ F = QQ
397
+ return CohomologyRAAG(F, self)
398
+
399
+ class Element(ArtinGroupElement):
400
+ """
401
+ An element of a right-angled Artin group (RAAG).
402
+
403
+ Elements of RAAGs are modeled as lists of pairs ``[i, p]`` where
404
+ ``i`` is the index of a vertex in the defining graph (with some
405
+ fixed order of the vertices) and ``p`` is the power.
406
+ """
407
+ def __init__(self, parent, lst):
408
+ """
409
+ Initialize ``self``.
410
+
411
+ TESTS::
412
+
413
+ sage: Gamma = graphs.CycleGraph(5)
414
+ sage: G = RightAngledArtinGroup(Gamma)
415
+ sage: elt = G.prod(G.gens())
416
+ sage: TestSuite(elt).run()
417
+
418
+ sage: g = G([[0,-3], [2,2], [3,-1], [2,4]])
419
+ sage: h = G.element_class(G, g.gap())
420
+ sage: assert g.gap() == h.gap()
421
+ sage: assert g._data == h._data
422
+
423
+ sage: g = G.one()
424
+ sage: h = G.element_class(G, g.gap())
425
+ sage: assert g.gap() == h.gap()
426
+ sage: assert g._data == h._data
427
+ """
428
+ if isinstance(lst, GapElement):
429
+ # e.g. direct call from GroupLibGAP
430
+ FinitelyPresentedGroupElement.__init__(self, parent, lst)
431
+ data = []
432
+ j = None
433
+ mult = 0
434
+ for i in self.Tietze():
435
+ if j is None:
436
+ j = i
437
+ mult = 1
438
+ elif j == i:
439
+ mult += 1
440
+ else:
441
+ if j < 0:
442
+ data.append([-j - 1, -mult])
443
+ else:
444
+ data.append([j - 1, mult])
445
+ j = i
446
+ mult = 1
447
+ if j is not None:
448
+ if j < 0:
449
+ data.append([-j - 1, -mult])
450
+ else:
451
+ data.append([j - 1, mult])
452
+ self._data = tuple(data)
453
+ else:
454
+ self._data = lst
455
+ elt = []
456
+ for i, p in lst:
457
+ if p > 0:
458
+ elt.extend([i + 1] * p)
459
+ elif p < 0:
460
+ elt.extend([-i - 1] * -p)
461
+ FinitelyPresentedGroupElement.__init__(self, parent, elt)
462
+
463
+ def __reduce__(self):
464
+ """
465
+ Used in pickling.
466
+
467
+ TESTS::
468
+
469
+ sage: Gamma = graphs.CycleGraph(5)
470
+ sage: G = RightAngledArtinGroup(Gamma)
471
+ sage: elt = G.prod(G.gens())
472
+ sage: loads(dumps(elt)) == elt
473
+ True
474
+ """
475
+ P = self.parent()
476
+ V = P._graph.vertices(sort=True)
477
+ return (P, ([[V[i], p] for i, p in self._data],))
478
+
479
+ def _repr_(self) -> str:
480
+ """
481
+ Return a string representation of ``self``.
482
+
483
+ TESTS::
484
+
485
+ sage: Gamma = graphs.CycleGraph(5)
486
+ sage: G = RightAngledArtinGroup(Gamma)
487
+ sage: a,b,c,d,e = G.gens()
488
+ sage: a * b^2 * e^-3
489
+ v0*v1^2*v4^-3
490
+ sage: Gamma = Graph([('x', 'y'), ('y', 'zeta')])
491
+ sage: G = RightAngledArtinGroup(Gamma)
492
+ sage: x,y,z = G.gens()
493
+ sage: z * y^-2 * x^3
494
+ vzeta*vy^-2*vx^3
495
+ sage: G.<a,b,c> = RightAngledArtinGroup(Gamma)
496
+ sage: c * b^-2 * a^3
497
+ c*b^-2*a^3
498
+ """
499
+ if not self._data:
500
+ return '1'
501
+ v = self.parent().variable_names()
502
+
503
+ def to_str(name, p):
504
+ if p == 1:
505
+ return "{}".format(name)
506
+ return "{}^{}".format(name, p)
507
+
508
+ return '*'.join(to_str(v[i], p) for i, p in self._data)
509
+
510
+ def _latex_(self) -> str:
511
+ r"""
512
+ Return a LaTeX representation of ``self``.
513
+
514
+ TESTS::
515
+
516
+ sage: Gamma = graphs.CycleGraph(5)
517
+ sage: G = RightAngledArtinGroup(Gamma)
518
+ sage: a,b,c,d,e = G.gens()
519
+ sage: latex(a*b*e^-4*d^3)
520
+ \sigma_{0}\sigma_{1}\sigma_{4}^{-4}\sigma_{3}^{3}
521
+ sage: latex(G.one())
522
+ 1
523
+ sage: Gamma = Graph([('x', 'y'), ('y', 'zeta')])
524
+ sage: G = RightAngledArtinGroup(Gamma)
525
+ sage: x,y,z = G.gens()
526
+ sage: latex(x^-5*y*z^3)
527
+ \sigma_{\text{\texttt{x}}}^{-5}\sigma_{\text{\texttt{y}}}\sigma_{\text{\texttt{zeta}}}^{3}
528
+ """
529
+ if not self._data:
530
+ return '1'
531
+
532
+ from sage.misc.latex import latex
533
+ latexrepr = ''
534
+ v = self.parent()._graph.vertices(sort=True)
535
+ for i, p in self._data:
536
+ latexrepr += "\\sigma_{{{}}}".format(latex(v[i]))
537
+ if p != 1:
538
+ latexrepr += "^{{{}}}".format(p)
539
+ return latexrepr
540
+
541
+ def _mul_(self, y):
542
+ """
543
+ Return ``self`` multiplied by ``y``.
544
+
545
+ TESTS::
546
+
547
+ sage: Gamma = graphs.CycleGraph(5)
548
+ sage: G = RightAngledArtinGroup(Gamma)
549
+ sage: a,b,c,d,e = G.gens()
550
+ sage: a * b
551
+ v0*v1
552
+ sage: b * a
553
+ v1*v0
554
+ sage: a*b*c*d*e
555
+ v0*v1*v2*v3*v4
556
+ sage: a^2*d*c*a*b*d
557
+ v0^3*v3*v2*v1*v3
558
+ sage: e^-1*a*b*d*c*a^-2*e*d*b^2*e*b^-3
559
+ v4^-1*v0*v3*v1*v0^-2*v2*v1^-1*v4*v3*v4
560
+ """
561
+ P = self.parent()
562
+ lst = self._data + y._data
563
+ return self.__class__(P, P._normal_form(lst))
564
+
565
+ def __pow__(self, n):
566
+ """
567
+ Implement exponentiation.
568
+
569
+ TESTS::
570
+
571
+ sage: Gamma = graphs.CycleGraph(5)
572
+ sage: G = RightAngledArtinGroup(Gamma)
573
+ sage: elt = G.prod(G.gens())
574
+ sage: elt**3
575
+ v0*v1*v2*v3*v4*v0*v1*v2*v3*v4*v0*v1*v2*v3*v4
576
+ sage: elt^-2
577
+ v4^-1*v3^-1*v2^-1*v1^-1*v0^-1*v4^-1*v3^-1*v2^-1*v1^-1*v0^-1
578
+ sage: elt^0
579
+ 1
580
+ """
581
+ P = self.parent()
582
+ if not n:
583
+ return P.one()
584
+
585
+ if n < 0:
586
+ lst = sum((self._data for i in range(-n)), ()) # Positive product
587
+ lst = [[x[0], -x[1]] for x in reversed(lst)] # Now invert
588
+ return self.__class__(P, P._normal_form(lst))
589
+
590
+ lst = sum((self._data for i in range(n)), ())
591
+ return self.__class__(self.parent(), P._normal_form(lst))
592
+
593
+ def __invert__(self):
594
+ """
595
+ Return the inverse of ``self``.
596
+
597
+ TESTS::
598
+
599
+ sage: Gamma = graphs.CycleGraph(5)
600
+ sage: G = RightAngledArtinGroup(Gamma)
601
+ sage: a,b,c,d,e = G.gens()
602
+ sage: (a * b)^-2
603
+ v1^-1*v0^-1*v1^-1*v0^-1
604
+ """
605
+ P = self.parent()
606
+ lst = [[x[0], -x[1]] for x in reversed(self._data)]
607
+ return self.__class__(P, P._normal_form(lst))
608
+
609
+ def _richcmp_(self, other, op) -> bool:
610
+ """
611
+ Compare ``self`` and ``other``.
612
+
613
+ TESTS::
614
+
615
+ sage: A = ArtinGroup(['B',3])
616
+ sage: x = A([1, 2, 1])
617
+ sage: y = A([2, 1, 2])
618
+ sage: x == y
619
+ True
620
+ sage: x < y^(-1)
621
+ True
622
+ sage: A([]) == A.one()
623
+ True
624
+ sage: x = A([2, 3, 2, 3])
625
+ sage: y = A([3, 2, 3, 2])
626
+ sage: x == y
627
+ True
628
+ sage: x < y^(-1)
629
+ True
630
+ """
631
+ return richcmp(self._data, other._data, op)
632
+
633
+
634
+ class CohomologyRAAG(CombinatorialFreeModule):
635
+ r"""
636
+ The cohomology ring of a right-angled Artin group.
637
+
638
+ The cohomology ring of a right-angled Artin group `A`, defined by
639
+ the graph `G`, with coefficients in a field `F` is isomorphic to
640
+ the exterior algebra of `F^N`, where `N` is the number of vertices
641
+ in `G`, modulo the quadratic relations `e_i \wedge e_j = 0` if and
642
+ only if `(i, j)` is an edge in `G`. This algebra is sometimes also
643
+ known as the Cartier-Foata algebra.
644
+
645
+ REFERENCES:
646
+
647
+ - [CQ2019]_
648
+ """
649
+ def __init__(self, R, A):
650
+ """
651
+ Initialize ``self``.
652
+
653
+ TESTS::
654
+
655
+ sage: C4 = graphs.CycleGraph(4)
656
+ sage: A = groups.misc.RightAngledArtin(C4)
657
+ sage: H = A.cohomology()
658
+ sage: TestSuite(H).run()
659
+
660
+ sage: A.cohomology(ZZ)
661
+ Traceback (most recent call last):
662
+ ...
663
+ NotImplementedError: only implemented with coefficients in a field
664
+ """
665
+ if R not in Fields():
666
+ raise NotImplementedError("only implemented with coefficients in a field")
667
+ self._group = A
668
+
669
+ names = tuple(['e' + name[1:] for name in A.variable_names()])
670
+ from sage.graphs.independent_sets import IndependentSets
671
+ from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
672
+ indices = [tuple(ind_set) for ind_set in IndependentSets(A._graph)]
673
+ indices = FiniteEnumeratedSet(indices)
674
+ cat = AlgebrasWithBasis(R.category()).Super().Graded().FiniteDimensional()
675
+ CombinatorialFreeModule.__init__(self, R, indices, category=cat, prefix='H')
676
+ self._assign_names(names)
677
+
678
+ def _repr_(self) -> str:
679
+ """
680
+ Return a string representation of ``self``.
681
+
682
+ EXAMPLES::
683
+
684
+ sage: C4 = graphs.CycleGraph(4)
685
+ sage: A = groups.misc.RightAngledArtin(C4)
686
+ sage: A.cohomology()
687
+ Cohomology ring of Right-angled Artin group of Cycle graph
688
+ with coefficients in Rational Field
689
+ """
690
+ return "Cohomology ring of {} with coefficients in {}".format(self._group, self.base_ring())
691
+
692
+ def _repr_term(self, m) -> str:
693
+ """
694
+ Return a string representation of the basis element indexed by ``m``.
695
+
696
+ EXAMPLES::
697
+
698
+ sage: C4 = graphs.CycleGraph(4)
699
+ sage: A = groups.misc.RightAngledArtin(C4)
700
+ sage: H = A.cohomology()
701
+ sage: H._repr_term((0,1,3))
702
+ 'e0*e1*e3'
703
+ sage: w,x,y,z = H.algebra_generators()
704
+ sage: y*w + x*z
705
+ -e0*e2 + e1*e3
706
+ """
707
+ if not m:
708
+ return '1'
709
+ return '*'.join('e' + str(i) for i in m)
710
+
711
+ def _ascii_art_term(self, m):
712
+ r"""
713
+ Return ascii art for the basis element indexed by ``m``.
714
+
715
+ EXAMPLES::
716
+
717
+ sage: C4 = graphs.CycleGraph(4)
718
+ sage: A = groups.misc.RightAngledArtin(C4)
719
+ sage: H = A.cohomology()
720
+ sage: H._ascii_art_term((0,1,3))
721
+ e0/\e1/\e3
722
+ sage: w,x,y,z = H.algebra_generators()
723
+ sage: ascii_art(y*w + 2*x*z)
724
+ -e0/\e2 + 2*e1/\e3
725
+ """
726
+ if not m:
727
+ return ascii_art('1')
728
+ wedge = '/\\'
729
+ return ascii_art(*['e' + str(i) for i in m], sep=wedge)
730
+
731
+ def _unicode_art_term(self, m):
732
+ """
733
+ Return unicode art for the basis element indexed by ``m``.
734
+
735
+ EXAMPLES::
736
+
737
+ sage: C4 = graphs.CycleGraph(4)
738
+ sage: A = groups.misc.RightAngledArtin(C4)
739
+ sage: H = A.cohomology()
740
+ sage: H._unicode_art_term((0,1,3))
741
+ e0∧e1∧e3
742
+ sage: w,x,y,z = H.algebra_generators()
743
+ sage: unicode_art(y*w + x*z)
744
+ -e0∧e2 + e1∧e3
745
+ """
746
+ if not m:
747
+ return unicode_art('1')
748
+ import unicodedata
749
+ wedge = unicodedata.lookup('LOGICAL AND')
750
+ return unicode_art(*['e' + str(i) for i in m], sep=wedge)
751
+
752
+ def _latex_term(self, m):
753
+ r"""
754
+ Return a `\LaTeX` representation of the basis element indexed by ``m``.
755
+
756
+ EXAMPLES::
757
+
758
+ sage: C4 = graphs.CycleGraph(4)
759
+ sage: A = groups.misc.RightAngledArtin(C4)
760
+ sage: H = A.cohomology()
761
+ sage: H._latex_term((0,1,3))
762
+ 'e_{0} \\wedge e_{1} \\wedge e_{3}'
763
+ """
764
+ if not m:
765
+ return '1'
766
+ from sage.misc.latex import latex
767
+ return " \\wedge ".join('e_{{{}}}'.format(latex(i)) for i in m)
768
+
769
+ def gen(self, i):
770
+ """
771
+ Return the ``i``-th standard generator of the algebra ``self``.
772
+
773
+ This corresponds to the ``i``-th vertex in the graph
774
+ (under a fixed ordering of the vertices).
775
+
776
+ EXAMPLES::
777
+
778
+ sage: C4 = graphs.CycleGraph(4)
779
+ sage: A = groups.misc.RightAngledArtin(C4)
780
+ sage: H = A.cohomology()
781
+ sage: H.gen(0)
782
+ e0
783
+ sage: H.gen(1)
784
+ e1
785
+ """
786
+ return self._from_dict({(i,): self.base_ring().one()}, remove_zeros=False)
787
+
788
+ @cached_method
789
+ def one_basis(self):
790
+ """
791
+ Return the basis element indexing `1` of ``self``.
792
+
793
+ EXAMPLES::
794
+
795
+ sage: C4 = graphs.CycleGraph(4)
796
+ sage: A = groups.misc.RightAngledArtin(C4)
797
+ sage: H = A.cohomology()
798
+ sage: H.one_basis()
799
+ ()
800
+ """
801
+ return ()
802
+
803
+ @cached_method
804
+ def algebra_generators(self):
805
+ """
806
+ Return the algebra generators of ``self``.
807
+
808
+ EXAMPLES::
809
+
810
+ sage: C4 = graphs.CycleGraph(4)
811
+ sage: A = groups.misc.RightAngledArtin(C4)
812
+ sage: H = A.cohomology()
813
+ sage: H.algebra_generators()
814
+ Finite family {0: e0, 1: e1, 2: e2, 3: e3}
815
+ """
816
+ V = self._group._graph.vertices(True)
817
+ d = {x: self.gen(i) for i, x in enumerate(V)}
818
+ from sage.sets.family import Family
819
+ return Family(V, lambda x: d[x])
820
+
821
+ def gens(self) -> tuple:
822
+ r"""
823
+ Return the generators of ``self`` (as an algebra).
824
+
825
+ EXAMPLES::
826
+
827
+ sage: C4 = graphs.CycleGraph(4)
828
+ sage: A = groups.misc.RightAngledArtin(C4)
829
+ sage: H = A.cohomology()
830
+ sage: H.gens()
831
+ (e0, e1, e2, e3)
832
+ """
833
+ return tuple(self.algebra_generators())
834
+
835
+ def ngens(self):
836
+ """
837
+ Return the number of algebra generators of ``self``.
838
+
839
+ EXAMPLES::
840
+
841
+ sage: C4 = graphs.CycleGraph(4)
842
+ sage: A = groups.misc.RightAngledArtin(C4)
843
+ sage: H = A.cohomology()
844
+ sage: H.ngens()
845
+ 4
846
+ """
847
+ return self._group._graph.num_verts()
848
+
849
+ def degree_on_basis(self, I):
850
+ """
851
+ Return the degree on the basis element ``clique``.
852
+
853
+ EXAMPLES::
854
+
855
+ sage: C4 = graphs.CycleGraph(4)
856
+ sage: A = groups.misc.RightAngledArtin(C4)
857
+ sage: H = A.cohomology()
858
+ sage: sorted([H.degree_on_basis(I) for I in H.basis().keys()])
859
+ [0, 1, 1, 1, 1, 2, 2]
860
+ """
861
+ return len(I)
862
+
863
+ class Element(CohomologyRAAGElement):
864
+ """
865
+ An element in the cohomology ring of a right-angled Artin group.
866
+ """