Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/algebras/hall_algebra.py
8818 views
1
r"""
2
Hall Algebras
3
4
AUTHORS:
5
6
- Travis Scrimshaw (2013-10-17): Initial version
7
"""
8
9
#*****************************************************************************
10
# Copyright (C) 2013 Travis Scrimshaw <tscrim at ucdavis.edu>
11
#
12
# Distributed under the terms of the GNU General Public License (GPL)
13
# http://www.gnu.org/licenses/
14
#*****************************************************************************
15
16
from sage.misc.misc_c import prod
17
from sage.misc.cachefunc import cached_method
18
from sage.categories.algebras_with_basis import AlgebrasWithBasis
19
from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis
20
from sage.combinat.partition import Partition, Partitions
21
from sage.combinat.free_module import CombinatorialFreeModule
22
from sage.combinat.hall_polynomial import hall_polynomial
23
from sage.combinat.sf.sf import SymmetricFunctions
24
from sage.rings.all import ZZ
25
26
def transpose_cmp(x, y):
27
r"""
28
Compare partitions ``x`` and ``y`` in transpose dominance order.
29
30
We say partitions `\mu` and `\lambda` satisfy `\mu \prec \lambda`
31
in transpose dominance order if for all `i \geq 1` we have:
32
33
.. MATH::
34
35
l_1 + 2 l_2 + \cdots + (i-1) l_{i-1} + i(l_i + l_{i+1} + \cdots) \leq
36
m_1 + 2 m_2 + \cdots + (i-1) m_{i-1} + i(m_i + m_{i+1} + \cdots),
37
38
where `l_k` denotes the number of appearances of `k` in
39
`\lambda`, and `m_k` denotes the number of appearances of `k`
40
in `\mu`.
41
42
Equivalently, `\mu \prec \lambda` if the conjugate of the
43
partition `\mu` dominates the conjugate of the partition
44
`\lambda`.
45
46
Since this is a partial ordering, we fallback to lex ordering
47
`\mu <_L \lambda` if we cannot compare in the transpose order.
48
49
EXAMPLES::
50
51
sage: from sage.algebras.hall_algebra import transpose_cmp
52
sage: transpose_cmp(Partition([4,3,1]), Partition([3,2,2,1]))
53
-1
54
sage: transpose_cmp(Partition([2,2,1]), Partition([3,2]))
55
1
56
sage: transpose_cmp(Partition([4,1,1]), Partition([4,1,1]))
57
0
58
"""
59
if x == y:
60
return 0
61
xexp = x.to_exp()
62
yexp = y.to_exp()
63
n = min(len(xexp), len(yexp))
64
def check(m, l):
65
s1 = 0
66
s2 = 0
67
for i in range(n):
68
s1 += sum(l[i:])
69
s2 += sum(m[i:])
70
if s1 > s2:
71
return False
72
return sum(l) <= sum(m)
73
if check(xexp, yexp):
74
return 1
75
if check(yexp, xexp):
76
return -1
77
return cmp(x, y)
78
79
class HallAlgebra(CombinatorialFreeModule):
80
r"""
81
The (classical) Hall algebra.
82
83
The *(classical) Hall algebra* over a commutative ring `R` with a
84
parameter `q \in R` is defined to be the free `R`-module with
85
basis `(I_\lambda)`, where `\lambda` runs over all integer
86
partitions. The algebra structure is given by a product defined by
87
88
.. MATH::
89
90
I_\mu \cdot I_\lambda = \sum_\nu P^{\nu}_{\mu, \lambda}(q) I_\nu,
91
92
where `P^{\nu}_{\mu, \lambda}` is a Hall polynomial (see
93
:meth:`~sage.combinat.hall_polynomial.hall_polynomial`). The
94
unity of this algebra is `I_{\emptyset}`.
95
96
The (classical) Hall algebra is also known as the Hall-Steinitz
97
algebra.
98
99
We can define an `R`-algebra isomorphism `\Phi` from the
100
`R`-algebra of symmetric functions (see
101
:class:`~sage.combinat.sf.sf.SymmetricFunctions`) to the
102
(classical) Hall algebra by sending the `r`-th elementary
103
symmetric function `e_r` to `q^{r(r-1)/2} I_{(1^r)}` for every
104
positive integer `r`. This isomorphism used to transport the
105
Hopf algebra structure from the `R`-algebra of symmetric functions
106
to the Hall algebra, thus making the latter a connected graded
107
Hopf algebra. If `\lambda` is a partition, then the preimage
108
of the basis element `I_{\lambda}` under this isomorphism is
109
`q^{n(\lambda)} P_{\lambda}(x; q^{-1})`, where `P_{\lambda}` denotes
110
the `\lambda`-th Hall-Littlewood `P`-function, and where
111
`n(\lambda) = \sum_i (i - 1) \lambda_i`.
112
113
See section 2.3 in [Schiffmann]_, and sections II.2 and III.3
114
in [Macdonald1995]_ (where our `I_{\lambda}` is called `u_{\lambda}`).
115
116
.. WARNING::
117
118
We could work in a Laurent polynomial ring, but currently Laurent
119
polynomials do not simplify if possible. Instead we typically must
120
use the fraction field of `\ZZ[q]`. See :trac:`11726`. ::
121
122
sage: R.<q> = LaurentPolynomialRing(ZZ)
123
sage: H = HallAlgebra(R, q)
124
sage: I = H.monomial_basis()
125
sage: H(I[2,1])
126
H[2, 1] + ((-q^3+1)/(-q+1))*H[1, 1, 1]
127
sage: H[2]*H[2]
128
Traceback (most recent call last):
129
...
130
TypeError: unsupported operand parent(s) for '-':
131
'Hall algebra with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring'
132
and '<type 'NoneType'>'
133
134
EXAMPLES::
135
136
sage: R.<q> = ZZ[]
137
sage: H = HallAlgebra(R, q)
138
sage: H[2,1]*H[1,1]
139
H[3, 2] + (q+1)*H[3, 1, 1] + (q^2+q)*H[2, 2, 1] + (q^4+q^3+q^2)*H[2, 1, 1, 1]
140
sage: H[2]*H[2,1]
141
H[4, 1] + q*H[3, 2] + (q^2-1)*H[3, 1, 1] + (q^3+q^2)*H[2, 2, 1]
142
sage: H[3]*H[1,1]
143
H[4, 1] + q^2*H[3, 1, 1]
144
sage: H[3]*H[2,1]
145
H[5, 1] + q*H[4, 2] + (q^2-1)*H[4, 1, 1] + q^3*H[3, 2, 1]
146
147
We can rewrite the Hall algebra in terms of monomials of
148
the elements `I_{(1^r)}`::
149
150
sage: I = H.monomial_basis()
151
sage: H(I[2,1,1])
152
H[3, 1] + (q+1)*H[2, 2] + (2*q^2+2*q+1)*H[2, 1, 1]
153
+ (q^5+2*q^4+3*q^3+3*q^2+2*q+1)*H[1, 1, 1, 1]
154
sage: I(H[2,1,1])
155
I[3, 1] + (-q^3-q^2-q-1)*I[4]
156
157
The isomorphism between the Hall algebra and the symmetric
158
functions described above is implemented as a coercion::
159
160
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
161
sage: q = R.gen()
162
sage: H = HallAlgebra(R, q)
163
sage: e = SymmetricFunctions(R).e()
164
sage: e(H[1,1,1])
165
1/q^3*e[3]
166
167
We can also do computations with any special value of ``q``,
168
such as `0` or `1` or (most commonly) a prime power. Here
169
is an example using a prime::
170
171
sage: H = HallAlgebra(ZZ, 2)
172
sage: H[2,1]*H[1,1]
173
H[3, 2] + 3*H[3, 1, 1] + 6*H[2, 2, 1] + 28*H[2, 1, 1, 1]
174
sage: H[3,1]*H[2]
175
H[5, 1] + H[4, 2] + 6*H[3, 3] + 3*H[4, 1, 1] + 8*H[3, 2, 1]
176
sage: H[2,1,1]*H[3,1]
177
H[5, 2, 1] + 2*H[4, 3, 1] + 6*H[4, 2, 2] + 7*H[5, 1, 1, 1]
178
+ 19*H[4, 2, 1, 1] + 24*H[3, 3, 1, 1] + 48*H[3, 2, 2, 1]
179
+ 105*H[4, 1, 1, 1, 1] + 224*H[3, 2, 1, 1, 1]
180
sage: I = H.monomial_basis()
181
sage: H(I[2,1,1])
182
H[3, 1] + 3*H[2, 2] + 13*H[2, 1, 1] + 105*H[1, 1, 1, 1]
183
sage: I(H[2,1,1])
184
I[3, 1] - 15*I[4]
185
186
If `q` is set to `1`, the coercion to the symmetric functions
187
sends `I_{\lambda}` to `m_{\lambda}`::
188
189
sage: H = HallAlgebra(QQ, 1)
190
sage: H[2,1] * H[2,1]
191
H[4, 2] + 2*H[3, 3] + 2*H[4, 1, 1] + 2*H[3, 2, 1] + 6*H[2, 2, 2] + 4*H[2, 2, 1, 1]
192
sage: m = SymmetricFunctions(QQ).m()
193
sage: m[2,1] * m[2,1]
194
4*m[2, 2, 1, 1] + 6*m[2, 2, 2] + 2*m[3, 2, 1] + 2*m[3, 3] + 2*m[4, 1, 1] + m[4, 2]
195
sage: m(H[3,1])
196
m[3, 1]
197
198
We can set `q` to `0` (but should keep in mind that we don't get
199
the Schur functions this way)::
200
201
sage: H = HallAlgebra(QQ, 0)
202
sage: H[2,1] * H[2,1]
203
H[4, 2] + H[3, 3] + H[4, 1, 1] - H[3, 2, 1] - H[3, 1, 1, 1]
204
205
REFERENCES:
206
207
.. [Schiffmann] Oliver Schiffmann. *Lectures on Hall algebras*.
208
:arxiv:`0611617v2`.
209
"""
210
def __init__(self, base_ring, q, prefix='H'):
211
"""
212
Initialize ``self``.
213
214
EXAMPLES::
215
216
sage: R.<q> = ZZ[]
217
sage: H = HallAlgebra(R, q)
218
sage: TestSuite(H).run()
219
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
220
sage: q = R.gen()
221
sage: H = HallAlgebra(R, q)
222
sage: TestSuite(H).run()
223
"""
224
self._q = q
225
try:
226
q_inverse = q**-1
227
if not q_inverse in base_ring:
228
hopf_structure = False
229
else:
230
hopf_structure = True
231
except Exception:
232
hopf_structure = False
233
if hopf_structure:
234
category = HopfAlgebrasWithBasis(base_ring)
235
else:
236
category = AlgebrasWithBasis(base_ring)
237
CombinatorialFreeModule.__init__(self, base_ring, Partitions(),
238
prefix=prefix, bracket=False,
239
monomial_cmp=transpose_cmp,
240
category=category)
241
242
# Coercions
243
I = self.monomial_basis()
244
M = I.module_morphism(I._to_natural_on_basis, codomain=self,
245
triangular='upper', unitriangular=True,
246
inverse_on_support=lambda x: x.conjugate())
247
M.register_as_coercion()
248
(~M).register_as_coercion()
249
250
def _repr_(self):
251
"""
252
Return a string representation of ``self``.
253
254
EXAMPLES::
255
256
sage: R.<q> = ZZ[]
257
sage: HallAlgebra(R, q)
258
Hall algebra with q=q over Univariate Polynomial Ring in q over Integer Ring
259
"""
260
return "Hall algebra with q={} over {}".format(self._q, self.base_ring())
261
262
def one_basis(self):
263
"""
264
Return the index of the basis element `1`.
265
266
EXAMPLES::
267
268
sage: R.<q> = ZZ[]
269
sage: H = HallAlgebra(R, q)
270
sage: H.one_basis()
271
[]
272
"""
273
return Partition([])
274
275
def product_on_basis(self, mu, la):
276
"""
277
Return the product of the two basis elements indexed by ``mu``
278
and ``la``.
279
280
EXAMPLES::
281
282
sage: R.<q> = ZZ[]
283
sage: H = HallAlgebra(R, q)
284
sage: H.product_on_basis(Partition([1,1]), Partition([1]))
285
H[2, 1] + (q^2+q+1)*H[1, 1, 1]
286
sage: H.product_on_basis(Partition([2,1]), Partition([1,1]))
287
H[3, 2] + (q+1)*H[3, 1, 1] + (q^2+q)*H[2, 2, 1] + (q^4+q^3+q^2)*H[2, 1, 1, 1]
288
sage: H.product_on_basis(Partition([3,2]), Partition([2,1]))
289
H[5, 3] + (q+1)*H[4, 4] + q*H[5, 2, 1] + (2*q^2-1)*H[4, 3, 1]
290
+ (q^3+q^2)*H[4, 2, 2] + (q^4+q^3)*H[3, 3, 2]
291
+ (q^4-q^2)*H[4, 2, 1, 1] + (q^5+q^4-q^3-q^2)*H[3, 3, 1, 1]
292
+ (q^6+q^5)*H[3, 2, 2, 1]
293
sage: H.product_on_basis(Partition([3,1,1]), Partition([2,1]))
294
H[5, 2, 1] + q*H[4, 3, 1] + (q^2-1)*H[4, 2, 2]
295
+ (q^3+q^2)*H[3, 3, 2] + (q^2+q+1)*H[5, 1, 1, 1]
296
+ (2*q^3+q^2-q-1)*H[4, 2, 1, 1] + (q^4+2*q^3+q^2)*H[3, 3, 1, 1]
297
+ (q^5+q^4)*H[3, 2, 2, 1] + (q^6+q^5+q^4-q^2-q-1)*H[4, 1, 1, 1, 1]
298
+ (q^7+q^6+q^5)*H[3, 2, 1, 1, 1]
299
"""
300
# Check conditions for multiplying by 1
301
if len(mu) == 0:
302
return self.monomial(la)
303
if len(la) == 0:
304
return self.monomial(mu)
305
306
if all(x == 1 for x in la):
307
return self.sum_of_terms([(p, hall_polynomial(p, mu, la, self._q))
308
for p in Partitions(sum(mu) + len(la))],
309
distinct=True)
310
311
I = HallAlgebraMonomials(self.base_ring(), self._q)
312
mu = self.monomial(mu)
313
la = self.monomial(la)
314
return self(I(mu) * I(la))
315
316
def coproduct_on_basis(self, la):
317
"""
318
Return the coproduct of the basis element indexed by ``la``.
319
320
EXAMPLES::
321
322
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
323
sage: q = R.gen()
324
sage: H = HallAlgebra(R, q)
325
sage: H.coproduct_on_basis(Partition([1,1]))
326
H[] # H[1, 1] + 1/q*H[1] # H[1] + H[1, 1] # H[]
327
sage: H.coproduct_on_basis(Partition([2]))
328
H[] # H[2] + ((q-1)/q)*H[1] # H[1] + H[2] # H[]
329
sage: H.coproduct_on_basis(Partition([2,1]))
330
H[] # H[2, 1] + ((q^2-1)/q^2)*H[1] # H[1, 1] + 1/q*H[1] # H[2]
331
+ ((q^2-1)/q^2)*H[1, 1] # H[1] + 1/q*H[2] # H[1] + H[2, 1] # H[]
332
"""
333
S = self.tensor_square()
334
if all(x == 1 for x in la):
335
n = len(la)
336
return S.sum_of_terms([( (Partition([1]*r), Partition([1]*(n-r))), self._q**(-r*(n-r)) )
337
for r in range(n+1)], distinct=True)
338
339
I = HallAlgebraMonomials(self.base_ring(), self._q)
340
la = self.monomial(la)
341
return S(I(la).coproduct())
342
343
def antipode_on_basis(self, la):
344
"""
345
Return the antipode of the basis element indexed by ``la``.
346
347
EXAMPLES::
348
349
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
350
sage: q = R.gen()
351
sage: H = HallAlgebra(R, q)
352
sage: H.antipode_on_basis(Partition([1,1]))
353
1/q*H[2] + 1/q*H[1, 1]
354
sage: H.antipode_on_basis(Partition([2]))
355
-1/q*H[2] + ((q^2-1)/q)*H[1, 1]
356
"""
357
if all(x == 1 for x in la):
358
r = len(la)
359
q = (-1)**r * self._q**(-r*(r-1)/2)
360
return self._from_dict({p: q for p in Partitions(r)})
361
362
I = HallAlgebraMonomials(self.base_ring(), self._q)
363
return self(I(self.monomial(la)).antipode())
364
365
def counit(self, x):
366
"""
367
Return the counit of the element ``x``.
368
369
EXAMPLES::
370
371
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
372
sage: q = R.gen()
373
sage: H = HallAlgebra(R, q)
374
sage: H.counit(H.an_element())
375
2
376
"""
377
return x.coefficient(self.one_basis())
378
379
def monomial_basis(self):
380
"""
381
Return the basis of the Hall algebra given by monomials in the
382
`I_{(1^r)}`.
383
384
EXAMPLES::
385
386
sage: R.<q> = ZZ[]
387
sage: H = HallAlgebra(R, q)
388
sage: H.monomial_basis()
389
Hall algebra with q=q over Univariate Polynomial Ring in q over
390
Integer Ring in the monomial basis
391
"""
392
return HallAlgebraMonomials(self.base_ring(), self._q)
393
394
def __getitem__(self, la):
395
"""
396
Return the basis element indexed by ``la``.
397
398
EXAMPLES::
399
400
sage: R.<q> = ZZ[]
401
sage: H = HallAlgebra(R, q)
402
sage: H[[]]
403
H[]
404
sage: H[2]
405
H[2]
406
sage: H[[2]]
407
H[2]
408
sage: H[2,1]
409
H[2, 1]
410
sage: H[Partition([2,1])]
411
H[2, 1]
412
sage: H[(2,1)]
413
H[2, 1]
414
"""
415
if la in ZZ:
416
return self.monomial(Partition([la]))
417
return self.monomial(Partition(la))
418
419
class Element(CombinatorialFreeModule.Element):
420
def scalar(self, y):
421
r"""
422
Return the scalar product of ``self`` and ``y``.
423
424
The scalar product is given by
425
426
.. MATH::
427
428
(I_{\lambda}, I_{\mu}) = \delta_{\lambda,\mu}
429
\frac{1}{a_{\lambda}},
430
431
where `a_{\lambda}` is given by
432
433
.. MATH::
434
435
a_{\lambda} = q^{|\lambda| + 2 n(\lambda)} \prod_k
436
\prod_{i=1}^{l_k} (1 - q^{-i})
437
438
where `n(\lambda) = \sum_i (i - 1) \lambda_i` and
439
`\lambda = (1^{l_1}, 2^{l_2}, \ldots, m^{l_m})`.
440
441
Note that `a_{\lambda}` can be interpreted as the number
442
of automorphisms of a certain object in a category
443
corresponding to `\lambda`. See Lemma 2.8 in [Schiffmann]_
444
for details.
445
446
EXAMPLES::
447
448
sage: R.<q> = ZZ[]
449
sage: H = HallAlgebra(R, q)
450
sage: H[1].scalar(H[1])
451
1/(q - 1)
452
sage: H[2].scalar(H[2])
453
1/(q^2 - q)
454
sage: H[2,1].scalar(H[2,1])
455
1/(q^5 - 2*q^4 + q^3)
456
sage: H[1,1,1,1].scalar(H[1,1,1,1])
457
1/(q^16 - q^15 - q^14 + 2*q^11 - q^8 - q^7 + q^6)
458
sage: H.an_element().scalar(H.an_element())
459
(4*q^2 + 9)/(q^2 - q)
460
"""
461
q = self.parent()._q
462
f = lambda la: ~( q**(sum(la) + 2*la.weighted_size())
463
* prod(prod((1 - q**-i) for i in range(1,k+1))
464
for k in la.to_exp()) )
465
y = self.parent()(y)
466
ret = q.parent().zero()
467
for mx, cx in self:
468
cy = y.coefficient(mx)
469
if cy != 0:
470
ret += cx * cy * f(mx)
471
return ret
472
473
class HallAlgebraMonomials(CombinatorialFreeModule):
474
r"""
475
The classical Hall algebra given in terms of monomials in the
476
`I_{(1^r)}`.
477
478
We first associate a monomial `I_{(1^{r_1})} I_{(1^{r_2})} \cdots
479
I_{(1^{r_k})}` with the composition `(r_1, r_2, \ldots, r_k)`. However
480
since `I_{(1^r)}` commutes with `I_{(1^s)}`, the basis is indexed
481
by partitions.
482
483
EXAMPLES:
484
485
We could work in a Laurent polynomial ring, but pending :trac:`11726`,
486
we use the fraction field of `\ZZ[q]` instead.
487
488
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
489
sage: q = R.gen()
490
sage: H = HallAlgebra(R, q)
491
sage: I = H.monomial_basis()
492
493
We check that the basis conversions are mutually inverse::
494
495
sage: all(H(I(H[p])) == H[p] for i in range(7) for p in Partitions(i))
496
True
497
sage: all(I(H(I[p])) == I[p] for i in range(7) for p in Partitions(i))
498
True
499
500
We can also convert to the symmetric functions. The natural basis
501
corresponds to the Hall-Littlewood basis (up to a renormalization and
502
an inversion of the `q` parameter), and this basis corresponds
503
to the elementary basis (up to a renormalization)::
504
505
sage: Sym = SymmetricFunctions(R)
506
sage: e = Sym.e()
507
sage: e(I[2,1])
508
1/q*e[2, 1]
509
sage: e(I[4,2,2,1])
510
1/q^8*e[4, 2, 2, 1]
511
sage: HLP = Sym.hall_littlewood(q).P()
512
sage: H(I[2,1])
513
H[2, 1] + (q^2+q+1)*H[1, 1, 1]
514
sage: HLP(e[2,1])
515
(q^2+q+1)*HLP[1, 1, 1] + HLP[2, 1]
516
sage: all( e(H[lam]) == q**-sum([i * x for i, x in enumerate(lam)])
517
....: * e(HLP[lam]).map_coefficients(lambda p: p(q**(-1)))
518
....: for lam in Partitions(4) )
519
True
520
521
We can also do computations using a prime power::
522
523
sage: H = HallAlgebra(ZZ, 3)
524
sage: I = H.monomial_basis()
525
sage: I[2,1]*I[1,1]
526
I[2, 1, 1, 1]
527
sage: H(_)
528
H[4, 1] + 7*H[3, 2] + 37*H[3, 1, 1] + 136*H[2, 2, 1]
529
+ 1495*H[2, 1, 1, 1] + 62920*H[1, 1, 1, 1, 1]
530
"""
531
def __init__(self, base_ring, q, prefix='I'):
532
"""
533
Initialize ``self``.
534
535
EXAMPLES::
536
537
sage: R.<q> = ZZ[]
538
sage: I = HallAlgebra(R, q).monomial_basis()
539
sage: TestSuite(I).run()
540
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
541
sage: q = R.gen()
542
sage: I = HallAlgebra(R, q).monomial_basis()
543
sage: TestSuite(I).run()
544
"""
545
self._q = q
546
try:
547
q_inverse = q**-1
548
if not q_inverse in base_ring:
549
hopf_structure = False
550
else:
551
hopf_structure = True
552
except Exception:
553
hopf_structure = False
554
if hopf_structure:
555
category = HopfAlgebrasWithBasis(base_ring)
556
else:
557
category = AlgebrasWithBasis(base_ring)
558
CombinatorialFreeModule.__init__(self, base_ring, Partitions(),
559
prefix=prefix, bracket=False,
560
category=category)
561
562
# Coercions
563
if hopf_structure:
564
e = SymmetricFunctions(base_ring).e()
565
f = lambda la: q**sum(-(r*(r-1)/2) for r in la)
566
M = self.module_morphism(diagonal=f, codomain=e)
567
M.register_as_coercion()
568
(~M).register_as_coercion()
569
570
@cached_method
571
def _to_natural_on_basis(self, a):
572
"""
573
Return the basis element indexed by ``a`` converted into
574
the partition basis.
575
576
EXAMPLES::
577
578
sage: R.<q> = ZZ[]
579
sage: I = HallAlgebra(R, q).monomial_basis()
580
sage: I._to_natural_on_basis(Partition([3]))
581
H[1, 1, 1]
582
sage: I._to_natural_on_basis(Partition([2,1,1]))
583
H[3, 1] + (q+1)*H[2, 2] + (2*q^2+2*q+1)*H[2, 1, 1]
584
+ (q^5+2*q^4+3*q^3+3*q^2+2*q+1)*H[1, 1, 1, 1]
585
"""
586
H = HallAlgebra(self.base_ring(), self._q)
587
return reduce(lambda cur,r: cur * H.monomial(Partition([1]*r)), a, H.one())
588
589
def _repr_(self):
590
"""
591
Return a string representation of ``self``.
592
593
EXAMPLES::
594
595
sage: R.<q> = ZZ[]
596
sage: HallAlgebra(R, q).monomial_basis()
597
Hall algebra with q=q over Univariate Polynomial Ring in q over
598
Integer Ring in the monomial basis
599
"""
600
return "Hall algebra with q={} over {} in the monomial basis".format(self._q, self.base_ring())
601
602
def one_basis(self):
603
"""
604
Return the index of the basis element `1`.
605
606
EXAMPLES::
607
608
sage: R.<q> = ZZ[]
609
sage: I = HallAlgebra(R, q).monomial_basis()
610
sage: I.one_basis()
611
[]
612
"""
613
return Partition([])
614
615
def product_on_basis(self, a, b):
616
"""
617
Return the product of the two basis elements indexed by ``a``
618
and ``b``.
619
620
EXAMPLES::
621
622
sage: R.<q> = ZZ[]
623
sage: I = HallAlgebra(R, q).monomial_basis()
624
sage: I.product_on_basis(Partition([4,2,1]), Partition([3,2,1]))
625
I[4, 3, 2, 2, 1, 1]
626
"""
627
return self.monomial(Partition(sorted(list(a) + list(b), reverse=True)))
628
629
def coproduct_on_basis(self, a):
630
"""
631
Return the coproduct of the basis element indexed by ``a``.
632
633
EXAMPLES::
634
635
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
636
sage: q = R.gen()
637
sage: I = HallAlgebra(R, q).monomial_basis()
638
sage: I.coproduct_on_basis(Partition([1]))
639
I[] # I[1] + I[1] # I[]
640
sage: I.coproduct_on_basis(Partition([2]))
641
I[] # I[2] + 1/q*I[1] # I[1] + I[2] # I[]
642
sage: I.coproduct_on_basis(Partition([2,1]))
643
I[] # I[2, 1] + 1/q*I[1] # I[1, 1] + I[1] # I[2]
644
+ 1/q*I[1, 1] # I[1] + I[2] # I[1] + I[2, 1] # I[]
645
"""
646
S = self.tensor_square()
647
return S.prod(S.sum_of_terms([( (Partition([r]), Partition([n-r]) ), self._q**(-r*(n-r)) )
648
for r in range(n+1)], distinct=True) for n in a)
649
650
def antipode_on_basis(self, a):
651
"""
652
Return the antipode of the basis element indexed by ``a``.
653
654
EXAMPLES::
655
656
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
657
sage: q = R.gen()
658
sage: I = HallAlgebra(R, q).monomial_basis()
659
sage: I.antipode_on_basis(Partition([1]))
660
-I[1]
661
sage: I.antipode_on_basis(Partition([2]))
662
1/q*I[1, 1] - I[2]
663
sage: I.antipode_on_basis(Partition([2,1]))
664
-1/q*I[1, 1, 1] + I[2, 1]
665
"""
666
H = HallAlgebra(self.base_ring(), self._q)
667
cur = self.one()
668
for r in a:
669
q = (-1)**r * self._q**(-r*(r-1)/2)
670
cur *= self(H._from_dict({p: q for p in Partitions(r)}))
671
return cur
672
673
def counit(self, x):
674
"""
675
Return the counit of the element ``x``.
676
677
EXAMPLES::
678
679
sage: R = PolynomialRing(ZZ, 'q').fraction_field()
680
sage: q = R.gen()
681
sage: I = HallAlgebra(R, q).monomial_basis()
682
sage: I.counit(I.an_element())
683
2
684
"""
685
return x.coefficient(self.one_basis())
686
687
def __getitem__(self, a):
688
"""
689
Return the basis element indexed by ``a``.
690
691
EXAMPLES::
692
693
sage: R.<q> = ZZ[]
694
sage: I = HallAlgebra(R, q).monomial_basis()
695
sage: I[3,1,1] + 3*I[1,1]
696
3*I[1, 1] + I[3, 1, 1]
697
sage: I[Partition([3,2,2])]
698
I[3, 2, 2]
699
sage: I[2]
700
I[2]
701
sage: I[[2]]
702
I[2]
703
sage: I[[]]
704
I[]
705
"""
706
if a in ZZ:
707
return self.monomial(Partition([a]))
708
return self.monomial(Partition(a))
709
710
class Element(CombinatorialFreeModule.Element):
711
def scalar(self, y):
712
r"""
713
Return the scalar product of ``self`` and ``y``.
714
715
The scalar product is computed by converting into the
716
natural basis.
717
718
EXAMPLES::
719
720
sage: R.<q> = ZZ[]
721
sage: I = HallAlgebra(R, q).monomial_basis()
722
sage: I[1].scalar(I[1])
723
1/(q - 1)
724
sage: I[2].scalar(I[2])
725
1/(q^4 - q^3 - q^2 + q)
726
sage: I[2,1].scalar(I[2,1])
727
(2*q + 1)/(q^6 - 2*q^5 + 2*q^3 - q^2)
728
sage: I[1,1,1,1].scalar(I[1,1,1,1])
729
24/(q^4 - 4*q^3 + 6*q^2 - 4*q + 1)
730
sage: I.an_element().scalar(I.an_element())
731
(4*q^4 - 4*q^2 + 9)/(q^4 - q^3 - q^2 + q)
732
"""
733
H = HallAlgebra(self.parent().base_ring(), self.parent()._q)
734
return H(self).scalar(H(y))
735
736
737