Path: blob/master/src/sage/combinat/descent_algebra.py
8817 views
"""1Descent Algebras23AUTHORS:45- Travis Scrimshaw (2013-07-28): Initial version6"""7#*****************************************************************************8# Copyright (C) 2013 Travis Scrimshaw <tscrim at ucdavis.edu>9#10# Distributed under the terms of the GNU General Public License (GPL)11# http://www.gnu.org/licenses/12#*****************************************************************************1314from sage.misc.cachefunc import cached_method15from sage.misc.bindable_class import BindableClass16from sage.misc.lazy_attribute import lazy_attribute17from sage.misc.misc import subsets18from sage.structure.parent import Parent19from sage.structure.unique_representation import UniqueRepresentation20from sage.categories.algebras import Algebras21from sage.categories.realizations import Realizations, Category_realization_of_parent22from sage.categories.all import FiniteDimensionalAlgebrasWithBasis23from sage.rings.all import ZZ, QQ24from sage.functions.other import factorial25from sage.combinat.free_module import CombinatorialFreeModule26from sage.combinat.permutation import Permutations27from sage.combinat.composition import Compositions28from sage.combinat.integer_matrices import IntegerMatrices29from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra30from sage.combinat.ncsf_qsym.ncsf import NonCommutativeSymmetricFunctions3132class DescentAlgebra(Parent, UniqueRepresentation):33r"""34Solomon's descent algebra.3536The descent algebra `\Sigma_n` over a ring `R` is a subalgebra of the37symmetric group algebra `R S_n`.3839There are three bases currently implemented for `\Sigma_n`:4041- the standard basis `D_S` of (sums of) descent classes, indexed by42subsets `S` of `\{1, 2, \ldots, n-1\}`,43- the subset basis `B_p`, indexed by compositions `p` of `n`,44- the idempotent basis `I_p`, indexed by compositions `p` of `n`,45which is used to construct the mutually orthogonal idempotents46of the symmetric group algebra.4748We follow the notations and conventions in [GR1989]_. In order to use49the idempotent basis, we require `R` to be a `\QQ`-algebra.5051INPUT:5253- ``R`` -- the base ring5455- ``n`` -- a nonnegative integer5657REFERENCES:5859.. [GR1989] C. Reutenauer, A. M. Garsia. *A decomposition of Solomon's60descent algebra.* Adv. Math. **77** (1989).61http://www.lacim.uqam.ca/~christo/Publi%C3%A9s/1989/Decomposition%20Solomon.pdf6263.. [Atkinson] M. D. Atkinson. *Solomon's descent algebra revisited.*64Bull. London Math. Soc. 24 (1992) 545-551.65http://www.cs.otago.ac.nz/staffpriv/mike/Papers/Descent/DescAlgRevisited.pdf6667.. [MR-Desc] C. Malvenuto, C. Reutenauer, *Duality between68quasi-symmetric functions and the Solomon descent algebra*,69Journal of Algebra 177 (1995), no. 3, 967-982.70http://www.lacim.uqam.ca/~christo/Publi%C3%A9s/1995/Duality.pdf7172EXAMPLES::7374sage: DA = DescentAlgebra(QQ, 4)75sage: D = DA.D(); D76Descent algebra of 4 over Rational Field in the standard basis77sage: B = DA.B(); B78Descent algebra of 4 over Rational Field in the subset basis79sage: I = DA.I(); I80Descent algebra of 4 over Rational Field in the idempotent basis81sage: basis_B = B.basis()82sage: elt = basis_B[Composition([1,2,1])] + 4*basis_B[Composition([1,3])]; elt83B[1, 2, 1] + 4*B[1, 3]84sage: D(elt)855*D{} + 5*D{1} + D{1, 3} + D{3}86sage: I(elt)877/6*I[1, 1, 1, 1] + 2*I[1, 1, 2] + 3*I[1, 2, 1] + 4*I[1, 3]8889There is the following syntatic sugar for calling elements of a basis, note90that for the empty set one must use ``D[[]]`` due to python's syntax::9192sage: D[[]] + D[2] + 2*D[1,2]93D{} + 2*D{1, 2} + D{2}94sage: I[1,2,1] + 3*I[4] + 2*I[3,1]95I[1, 2, 1] + 2*I[3, 1] + 3*I[4]9697TESTS:9899We check that we can go back and forth between our bases::100101sage: DA = DescentAlgebra(QQ, 4)102sage: D = DA.D()103sage: B = DA.B()104sage: I = DA.I()105sage: all(D(B(b)) == b for b in D.basis())106True107sage: all(D(I(b)) == b for b in D.basis())108True109sage: all(B(D(b)) == b for b in B.basis())110True111sage: all(B(I(b)) == b for b in B.basis())112True113sage: all(I(D(b)) == b for b in I.basis())114True115sage: all(I(B(b)) == b for b in I.basis())116True117"""118def __init__(self, R, n):119r"""120EXAMPLES::121122sage: TestSuite(DescentAlgebra(QQ, 4)).run()123"""124self._n = n125self._category = FiniteDimensionalAlgebrasWithBasis(R)126Parent.__init__(self, base=R, category=self._category.WithRealizations())127128def _repr_(self):129r"""130Return a string representation of ``self``.131132EXAMPLES::133134sage: DescentAlgebra(QQ, 4)135Descent algebra of 4 over Rational Field136"""137return "Descent algebra of {0} over {1}".format(self._n, self.base_ring())138139def a_realization(self):140r"""141Return a particular realization of ``self`` (the `B`-basis).142143EXAMPLES::144145sage: DA = DescentAlgebra(QQ, 4)146sage: DA.a_realization()147Descent algebra of 4 over Rational Field in the subset basis148"""149return self.B()150151class D(CombinatorialFreeModule, BindableClass):152r"""153The standard basis of a descent algebra.154155This basis is indexed by `S \subseteq \{1, 2, \ldots, n-1\}`,156and the basis vector indexed by `S` is the sum of all permutations,157taken in the symmetric group algebra `R S_n`, whose descent set is `S`.158159EXAMPLES::160161sage: DA = DescentAlgebra(QQ, 4)162sage: D = DA.D()163sage: list(D.basis())164[D{}, D{1}, D{2}, D{1, 2}, D{3}, D{1, 3}, D{2, 3}, D{1, 2, 3}]165166sage: DA = DescentAlgebra(QQ, 0)167sage: D = DA.D()168sage: list(D.basis())169[D{}]170"""171def __init__(self, alg, prefix="D"):172r"""173Initialize ``self``.174175EXAMPLES::176177sage: TestSuite(DescentAlgebra(QQ, 4).D()).run()178"""179self._prefix = prefix180self._basis_name = "standard"181p_set = subsets(range(1, alg._n))182CombinatorialFreeModule.__init__(self, alg.base_ring(),183map(tuple, p_set),184category=DescentAlgebraBases(alg),185bracket="", prefix=prefix)186187# Change of basis:188B = alg.B()189self.module_morphism(self.to_B_basis,190codomain=B, category=self.category()191).register_as_coercion()192193B.module_morphism(B.to_D_basis,194codomain=self, category=self.category()195).register_as_coercion()196197# Coercion to symmetric group algebra198SGA = SymmetricGroupAlgebra(alg.base_ring(), alg._n)199self.module_morphism(self.to_symmetric_group_algebra_on_basis,200codomain=SGA, category=Algebras(alg.base_ring())201).register_as_coercion()202203def _element_constructor_(self, x):204"""205Construct an element of ``self``.206207EXAMPLES::208209sage: D = DescentAlgebra(QQ, 4).D()210sage: D([1, 3])211D{1, 3}212"""213if isinstance(x, (list, set)):214x = tuple(x)215if isinstance(x, tuple):216return self.monomial(x)217return CombinatorialFreeModule._element_constructor_(self, x)218219# We need to overwrite this since our basis elements must be indexed by tuples220def _repr_term(self, S):221r"""222EXAMPLES::223224sage: DA = DescentAlgebra(QQ, 4)225sage: DA.D()._repr_term((1, 3))226'D{1, 3}'227"""228return self._prefix + '{' + repr(list(S))[1:-1] + '}'229230def product_on_basis(self, S, T):231r"""232Return `D_S D_T`, where `S` and `T` are subsets of `[n-1]`.233234EXAMPLES::235236sage: DA = DescentAlgebra(QQ, 4)237sage: D = DA.D()238sage: D.product_on_basis((1, 3), (2,))239D{} + D{1} + D{1, 2} + 2*D{1, 2, 3} + D{1, 3} + D{2} + D{2, 3} + D{3}240"""241return self(self.to_B_basis(S)*self.to_B_basis(T))242243@cached_method244def one_basis(self):245r"""246Return the identity element, as per247``AlgebrasWithBasis.ParentMethods.one_basis``.248249EXAMPLES::250251sage: DescentAlgebra(QQ, 4).D().one_basis()252()253sage: DescentAlgebra(QQ, 0).D().one_basis()254()255256sage: all( U * DescentAlgebra(QQ, 3).D().one() == U257....: for U in DescentAlgebra(QQ, 3).D().basis() )258True259"""260return tuple([])261262@cached_method263def to_B_basis(self, S):264r"""265Return `D_S` as a linear combination of `B_p`-basis elements.266267EXAMPLES::268269sage: DA = DescentAlgebra(QQ, 4)270sage: D = DA.D()271sage: B = DA.B()272sage: for b in D.basis(): B(b) # indirect doctest273B[4]274B[1, 3] - B[4]275B[2, 2] - B[4]276B[1, 1, 2] - B[1, 3] - B[2, 2] + B[4]277B[3, 1] - B[4]278B[1, 2, 1] - B[1, 3] - B[3, 1] + B[4]279B[2, 1, 1] - B[2, 2] - B[3, 1] + B[4]280B[1, 1, 1, 1] - B[1, 1, 2] - B[1, 2, 1] + B[1, 3] - B[2, 1, 1] + B[2, 2] + B[3, 1] - B[4]281"""282B = self.realization_of().B()283284if len(S) == 0:285return B.one()286287n = self.realization_of()._n288C = Compositions(n)289return B.sum_of_terms([(C.from_subset(T, n), (-1)**(len(S)-len(T))) for T in subsets(S)])290291def to_symmetric_group_algebra_on_basis(self, S):292"""293Return `D_S` as a linear combination of basis elements in the294symmetric group algebra.295296EXAMPLES::297298sage: D = DescentAlgebra(QQ, 4).D()299sage: for b in Subsets(3): D.to_symmetric_group_algebra_on_basis(tuple(b))300[1, 2, 3, 4]301[2, 1, 3, 4] + [3, 1, 2, 4] + [4, 1, 2, 3]302[1, 3, 2, 4] + [1, 4, 2, 3] + [2, 3, 1, 4] + [2, 4, 1, 3] + [3, 4, 1, 2]303[1, 2, 4, 3] + [1, 3, 4, 2] + [2, 3, 4, 1]304[3, 2, 1, 4] + [4, 2, 1, 3] + [4, 3, 1, 2]305[2, 1, 4, 3] + [3, 1, 4, 2] + [3, 2, 4, 1] + [4, 1, 3, 2] + [4, 2, 3, 1]306[1, 4, 3, 2] + [2, 4, 3, 1] + [3, 4, 2, 1]307[4, 3, 2, 1]308"""309n = self.realization_of()._n310SGA = SymmetricGroupAlgebra(self.base_ring(), n)311# Need to convert S to a list of positions by -1 for indexing312P = Permutations(descents=([x-1 for x in S], n))313return SGA.sum_of_terms([(p, 1) for p in P])314315def __getitem__(self, S):316"""317Return the basis element indexed by ``S``.318319INPUT:320321- ``S`` -- a subset of `[n-1]`322323EXAMPLES::324325sage: D = DescentAlgebra(QQ, 4).D()326sage: D[3]327D{3}328sage: D[1, 3]329D{1, 3}330sage: D[[]]331D{}332333TESTS::334335sage: D = DescentAlgebra(QQ, 0).D()336sage: D[[]]337D{}338"""339n = self.realization_of()._n340if S in ZZ:341if S >= n or S <= 0:342raise ValueError("({0},) is not a subset of {{1, ..., {1}}}".format(S, n-1))343return self.monomial((S,))344if len(S) == 0:345return self.one()346S = tuple(sorted(S))347if S[-1] >= n or S[0] <= 0:348raise ValueError("{0} is not a subset of {{1, ..., {1}}}".format(S, n-1))349return self.monomial(S)350351standard = D352353class B(CombinatorialFreeModule, BindableClass):354r"""355The subset basis of a descent algebra (indexed by compositions).356357The subset basis `(B_S)_{S \subseteq \{1, 2, \ldots, n-1\}}` of358`\Sigma_n` is formed by359360.. MATH::361362B_S = \sum_{T \subseteq S} D_T,363364where `(D_S)_{S \subseteq \{1, 2, \ldots, n-1\}}` is the365:class:`standard basis <DescentAlgebra.D>`. However it is more366natural to index the subset basis by compositions367of `n` under the bijection `\{i_1, i_2, \ldots, i_k\} \mapsto368(i_1, i_2 - i_1, i_3 - i_2, \ldots, i_k - i_{k-1}, n - i_k)`,369which is what Sage uses to index the basis.370371By using compositions of `n`, the product `B_p B_q` becomes a372sum over the non-negative-integer matrices `M` with column sum `p`373and row sum `q`. The summand corresponding to `M` is `B_c`, where `c`374is the composition obtained by reading `M` row-by-row from375left-to-right and top-to-bottom and removing all zeroes. This376multiplication rule is commonly called "Solomon's Mackey formula".377378EXAMPLES::379380sage: DA = DescentAlgebra(QQ, 4)381sage: B = DA.B()382sage: list(B.basis())383[B[1, 1, 1, 1], B[1, 1, 2], B[1, 2, 1], B[1, 3], B[2, 1, 1], B[2, 2], B[3, 1], B[4]]384"""385def __init__(self, alg, prefix="B"):386r"""387Initialize ``self``.388389EXAMPLES::390391sage: TestSuite(DescentAlgebra(QQ, 4).B()).run()392"""393self._prefix = prefix394self._basis_name = "subset"395CombinatorialFreeModule.__init__(self, alg.base_ring(),396Compositions(alg._n),397category=DescentAlgebraBases(alg),398bracket="", prefix=prefix)399400S = NonCommutativeSymmetricFunctions(alg.base_ring()).Complete()401self.module_morphism(self.to_nsym,402codomain=S, category=Algebras(alg.base_ring())403).register_as_coercion()404405def product_on_basis(self, p, q):406r"""407Return `B_p B_q`, where `p` and `q` are compositions of `n`.408409EXAMPLES::410411sage: DA = DescentAlgebra(QQ, 4)412sage: B = DA.B()413sage: p = Composition([1,2,1])414sage: q = Composition([3,1])415sage: B.product_on_basis(p, q)416B[1, 1, 1, 1] + 2*B[1, 2, 1]417"""418IM = IntegerMatrices(list(p), list(q))419P = Compositions(self.realization_of()._n)420to_composition = lambda m: P( filter(lambda x: x != 0, m.list()) )421return self.sum_of_monomials(map(to_composition, IM))422423@cached_method424def one_basis(self):425r"""426Return the identity element which is the composition `[n]`, as per427``AlgebrasWithBasis.ParentMethods.one_basis``.428429EXAMPLES::430431sage: DescentAlgebra(QQ, 4).B().one_basis()432[4]433sage: DescentAlgebra(QQ, 0).B().one_basis()434[]435436sage: all( U * DescentAlgebra(QQ, 3).B().one() == U437....: for U in DescentAlgebra(QQ, 3).B().basis() )438True439"""440n = self.realization_of()._n441P = Compositions(n)442if n == 0:443return P([])444return P([n])445446@cached_method447def to_I_basis(self, p):448r"""449Return `B_p` as a linear combination of `I`-basis elements.450451This is done using the formula452453.. MATH::454455B_p = \sum_{q \leq p} \frac{1}{\mathbf{k}!(q,p)} I_q,456457where `\leq` is the refinement order and `\mathbf{k}!(q,p)` is458defined as follows: When `q \leq p`, we can write `q` as a459concatenation `q_{(1)} q_{(2)} \cdots q_{(k)}` with each `q_{(i)}`460being a composition of the `i`-th entry of `p`, and then461we set `\mathbf{k}!(q,p)` to be462`l(q_{(1)})! l(q_{(2)})! \cdots l(q_{(k)})!`, where `l(r)`463denotes the number of parts of any composition `r`.464465EXAMPLES::466467sage: DA = DescentAlgebra(QQ, 4)468sage: B = DA.B()469sage: I = DA.I()470sage: for b in B.basis(): I(b) # indirect doctest471I[1, 1, 1, 1]4721/2*I[1, 1, 1, 1] + I[1, 1, 2]4731/2*I[1, 1, 1, 1] + I[1, 2, 1]4741/6*I[1, 1, 1, 1] + 1/2*I[1, 1, 2] + 1/2*I[1, 2, 1] + I[1, 3]4751/2*I[1, 1, 1, 1] + I[2, 1, 1]4761/4*I[1, 1, 1, 1] + 1/2*I[1, 1, 2] + 1/2*I[2, 1, 1] + I[2, 2]4771/6*I[1, 1, 1, 1] + 1/2*I[1, 2, 1] + 1/2*I[2, 1, 1] + I[3, 1]4781/24*I[1, 1, 1, 1] + 1/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/2*I[1, 3] + 1/6*I[2, 1, 1] + 1/2*I[2, 2] + 1/2*I[3, 1] + I[4]479"""480I = self.realization_of().I()481482def coeff(p, q):483ret = QQ.one()484last = 0485for val in p:486count = 0487s = 0488while s != val:489s += q[last+count]490count += 1491ret /= factorial(count)492last += count493return ret494495return I.sum_of_terms([(q, coeff(p, q)) for q in p.finer()])496497@cached_method498def to_D_basis(self, p):499r"""500Return `B_p` as a linear combination of `D`-basis elements.501502EXAMPLES::503504sage: DA = DescentAlgebra(QQ, 4)505sage: B = DA.B()506sage: D = DA.D()507sage: for b in B.basis(): D(b) # indirect doctest508D{} + D{1} + D{1, 2} + D{1, 2, 3} + D{1, 3} + D{2} + D{2, 3} + D{3}509D{} + D{1} + D{1, 2} + D{2}510D{} + D{1} + D{1, 3} + D{3}511D{} + D{1}512D{} + D{2} + D{2, 3} + D{3}513D{} + D{2}514D{} + D{3}515D{}516517TESTS:518519Check to make sure the empty case is handled correctly::520521sage: DA = DescentAlgebra(QQ, 0)522sage: B = DA.B()523sage: D = DA.D()524sage: for b in B.basis(): D(b)525D{}526"""527D = self.realization_of().D()528529if p == []:530return D.one()531532return D.sum_of_terms([(tuple(sorted(s)), 1) for s in p.to_subset().subsets()])533534def to_nsym(self, p):535"""536Return `B_p` as an element in `NSym`, the non-commutative537symmetric functions.538539This maps `B_p` to `S_p` where `S` denotes the Complete basis of540`NSym`.541542EXAMPLES::543544sage: B = DescentAlgebra(QQ, 4).B()545sage: S = NonCommutativeSymmetricFunctions(QQ).Complete()546sage: for b in B.basis(): S(b) # indirect doctest547S[1, 1, 1, 1]548S[1, 1, 2]549S[1, 2, 1]550S[1, 3]551S[2, 1, 1]552S[2, 2]553S[3, 1]554S[4]555"""556S = NonCommutativeSymmetricFunctions(self.base_ring()).Complete()557return S.monomial(p)558559subset = B560561class I(CombinatorialFreeModule, BindableClass):562r"""563The idempotent basis of a descent algebra.564565The idempotent basis `(I_p)_{p \models n}` is a basis for `\Sigma_n`.566Let `\lambda(p)` denote the partition obtained from a composition567`p` by sorting. This basis is called the idempotent basis since for568any `q` such that `\lambda(p) = \lambda(q)`, we have:569570.. MATH::571572I_p I_q = s(\lambda) I_q573574where `\lambda` denotes `\lambda(p) = \lambda(q)`, and where575`s(\lambda)` is the stabilizer of `\lambda` in `S_n`.576577It is also straightforward to compute the idempotents `E_{\lambda}`578for the symmetric group algebra by the formula579(Theorem 3.2 in [GR1989]_):580581.. MATH::582583E_{\lambda} = \frac{1}{k!} \sum_{\lambda(p) = \lambda} I_p.584585.. NOTE::586587The basis elements are not orthogonal idempotents.588589EXAMPLES::590591sage: DA = DescentAlgebra(QQ, 4)592sage: I = DA.I()593sage: list(I.basis())594[I[1, 1, 1, 1], I[1, 1, 2], I[1, 2, 1], I[1, 3], I[2, 1, 1], I[2, 2], I[3, 1], I[4]]595"""596def __init__(self, alg, prefix="I"):597r"""598Initialize ``self``.599600EXAMPLES::601602sage: TestSuite(DescentAlgebra(QQ, 4).B()).run()603"""604self._prefix = prefix605self._basis_name = "idempotent"606CombinatorialFreeModule.__init__(self, alg.base_ring(),607Compositions(alg._n),608category=DescentAlgebraBases(alg),609bracket="", prefix=prefix)610611## Change of basis:612B = alg.B()613self.module_morphism(self.to_B_basis,614codomain=B, category=self.category()615).register_as_coercion()616617B.module_morphism(B.to_I_basis,618codomain=self, category=self.category()619).register_as_coercion()620621def product_on_basis(self, p, q):622r"""623Return `I_p I_q`, where `p` and `q` are compositions of `n`.624625EXAMPLES::626627sage: DA = DescentAlgebra(QQ, 4)628sage: I = DA.I()629sage: p = Composition([1,2,1])630sage: q = Composition([3,1])631sage: I.product_on_basis(p, q)6320633sage: I.product_on_basis(p, p)6342*I[1, 2, 1]635"""636# These do not act as orthogonal idempotents, so we have to lift637# to the B basis to do the multiplication638# TODO: if the partitions of p and q match, return s*I_q where639# s is the size of the stabilizer of the partition of p640return self(self.to_B_basis(p)*self.to_B_basis(q))641642@cached_method643def one(self):644r"""645Return the identity element, which is `B_{[n]}`, in the `I` basis.646647EXAMPLES::648649sage: DescentAlgebra(QQ, 4).I().one()6501/24*I[1, 1, 1, 1] + 1/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/2*I[1, 3] + 1/6*I[2, 1, 1] + 1/2*I[2, 2] + 1/2*I[3, 1] + I[4]651sage: DescentAlgebra(QQ, 0).I().one()652I[]653654TESTS::655656sage: all( U * DescentAlgebra(QQ, 3).I().one() == U657....: for U in DescentAlgebra(QQ, 3).I().basis() )658True659"""660B = self.realization_of().B()661return B.to_I_basis(B.one_basis())662663def one_basis(self):664"""665The element `1` is not (generally) a basis vector in the `I`666basis, thus this returns a ``TypeError``.667668EXAMPLES::669670sage: DescentAlgebra(QQ, 4).I().one_basis()671Traceback (most recent call last):672...673TypeError: 1 is not a basis element in the I basis.674"""675raise TypeError("1 is not a basis element in the I basis.")676677@cached_method678def to_B_basis(self, p):679r"""680Return `I_p` as a linear combination of `B`-basis elements.681682This is computed using the formula (Theorem 3.4 in [GR1989]_)683684.. MATH::685686I_p = \sum_{q \leq p}687\frac{(-1)^{l(q)-l(p)}}{\mathbf{k}(q,p)} B_q,688689where `\leq` is the refinement order and `l(r)` denotes the number690of parts of any composition `r`, and where `\mathbf{k}(q,p)` is691defined as follows: When `q \leq p`, we can write `q` as a692concatenation `q_{(1)} q_{(2)} \cdots q_{(k)}` with each `q_{(i)}`693being a composition of the `i`-th entry of `p`, and then694we set `\mathbf{k}(q,p)` to be695`l(q_{(1)}) l(q_{(2)}) \cdots l(q_{(k)})`.696697EXAMPLES::698699sage: DA = DescentAlgebra(QQ, 4)700sage: B = DA.B()701sage: I = DA.I()702sage: for b in I.basis(): B(b) # indirect doctest703B[1, 1, 1, 1]704-1/2*B[1, 1, 1, 1] + B[1, 1, 2]705-1/2*B[1, 1, 1, 1] + B[1, 2, 1]7061/3*B[1, 1, 1, 1] - 1/2*B[1, 1, 2] - 1/2*B[1, 2, 1] + B[1, 3]707-1/2*B[1, 1, 1, 1] + B[2, 1, 1]7081/4*B[1, 1, 1, 1] - 1/2*B[1, 1, 2] - 1/2*B[2, 1, 1] + B[2, 2]7091/3*B[1, 1, 1, 1] - 1/2*B[1, 2, 1] - 1/2*B[2, 1, 1] + B[3, 1]710-1/4*B[1, 1, 1, 1] + 1/3*B[1, 1, 2] + 1/3*B[1, 2, 1] - 1/2*B[1, 3] + 1/3*B[2, 1, 1] - 1/2*B[2, 2] - 1/2*B[3, 1] + B[4]711"""712B = self.realization_of().B()713714def coeff(p, q):715ret = QQ.one()716last = 0717for val in p:718count = 0719s = 0720while s != val:721s += q[last+count]722count += 1723ret /= count724last += count725if (len(q) - len(p)) % 2 == 1:726ret = -ret727return ret728729return B.sum_of_terms([(q, coeff(p, q)) for q in p.finer()])730731def idempotent(self, la):732"""733Return the idemponent corresponding to the partition ``la``.734735EXAMPLES::736737sage: I = DescentAlgebra(QQ, 4).I()738sage: E = I.idempotent([3,1]); E7391/2*I[1, 3] + 1/2*I[3, 1]740sage: E*E == E741True742sage: E2 = I.idempotent([2,1,1]); E27431/6*I[1, 1, 2] + 1/6*I[1, 2, 1] + 1/6*I[2, 1, 1]744sage: E2*E2 == E2745True746sage: E*E2 == I.zero()747True748"""749from sage.combinat.permutation import Permutations750k = len(la)751C = Compositions(self.realization_of()._n)752return self.sum_of_terms([(C(x), ~QQ(factorial(k))) for x in Permutations(la)])753754idempotent = I755756class DescentAlgebraBases(Category_realization_of_parent):757r"""758The category of bases of a descent algebra.759"""760def __init__(self, base):761r"""762Initialize the bases of a descent algebra.763764INPUT:765766- ``base`` -- a descent algebra767768TESTS::769770sage: from sage.combinat.descent_algebra import DescentAlgebraBases771sage: DA = DescentAlgebra(QQ, 4)772sage: bases = DescentAlgebraBases(DA)773sage: DA.B() in bases774True775"""776Category_realization_of_parent.__init__(self, base)777778def _repr_(self):779r"""780Return the representation of ``self``.781782EXAMPLES::783784sage: from sage.combinat.descent_algebra import DescentAlgebraBases785sage: DA = DescentAlgebra(QQ, 4)786sage: DescentAlgebraBases(DA)787Category of bases of Descent algebra of 4 over Rational Field788"""789return "Category of bases of %s" % self.base()790791def super_categories(self):792r"""793The super categories of ``self``.794795EXAMPLES::796797sage: from sage.combinat.descent_algebra import DescentAlgebraBases798sage: DA = DescentAlgebra(QQ, 4)799sage: bases = DescentAlgebraBases(DA)800sage: bases.super_categories()801[Category of finite dimensional algebras with basis over Rational Field,802Category of realizations of Descent algebra of 4 over Rational Field]803"""804return [self.base()._category, Realizations(self.base())]805806class ParentMethods:807def _repr_(self):808"""809Text representation of this basis of a descent algebra.810811EXAMPLES::812813sage: DA = DescentAlgebra(QQ, 4)814sage: DA.B()815Descent algebra of 4 over Rational Field in the subset basis816sage: DA.D()817Descent algebra of 4 over Rational Field in the standard basis818sage: DA.I()819Descent algebra of 4 over Rational Field in the idempotent basis820"""821return "%s in the %s basis"%(self.realization_of(), self._basis_name)822823def __getitem__(self, p):824"""825Return the basis element indexed by ``p``.826827INPUT:828829- ``p`` -- a composition830831EXAMPLES::832833sage: B = DescentAlgebra(QQ, 4).B()834sage: B[Composition([4])]835B[4]836sage: B[1,2,1]837B[1, 2, 1]838sage: B[4]839B[4]840sage: B[[3,1]]841B[3, 1]842"""843C = Compositions(self.realization_of()._n)844if p in C:845return self.monomial(C(p)) # Make sure it's a composition846if p == []:847return self.one()848849if not isinstance(p, tuple):850p = [p]851return self.monomial(C(p))852853def is_field(self, proof = True):854"""855Return whether this descent algebra is a field.856857EXAMPLES::858859sage: B = DescentAlgebra(QQ, 4).B()860sage: B.is_field()861False862sage: B = DescentAlgebra(QQ, 1).B()863sage: B.is_field()864True865"""866if self.realization_of()._n <= 1:867return self.base_ring().is_field()868return False869870def is_commutative(self):871"""872Return whether this descent algebra is commutative.873874EXAMPLES::875876sage: B = DescentAlgebra(QQ, 4).B()877sage: B.is_commutative()878False879sage: B = DescentAlgebra(QQ, 1).B()880sage: B.is_commutative()881True882"""883return self.base_ring().is_commutative() \884and self.realization_of()._n <= 2885886@lazy_attribute887def to_symmetric_group_algebra(self):888"""889Morphism from ``self`` to the symmetric group algebra.890891EXAMPLES::892893sage: D = DescentAlgebra(QQ, 4).D()894sage: D.to_symmetric_group_algebra(D[1,3])895[2, 1, 4, 3] + [3, 1, 4, 2] + [3, 2, 4, 1] + [4, 1, 3, 2] + [4, 2, 3, 1]896sage: B = DescentAlgebra(QQ, 4).B()897sage: B.to_symmetric_group_algebra(B[1,2,1])898[1, 2, 3, 4] + [1, 2, 4, 3] + [1, 3, 4, 2] + [2, 1, 3, 4]899+ [2, 1, 4, 3] + [2, 3, 4, 1] + [3, 1, 2, 4] + [3, 1, 4, 2]900+ [3, 2, 4, 1] + [4, 1, 2, 3] + [4, 1, 3, 2] + [4, 2, 3, 1]901"""902SGA = SymmetricGroupAlgebra(self.base_ring(), self.realization_of()._n)903return self.module_morphism(self.to_symmetric_group_algebra_on_basis, codomain=SGA)904905def to_symmetric_group_algebra_on_basis(self, S):906"""907Return the basis element index by ``S`` as a linear combination908of basis elements in the symmetric group algebra.909910EXAMPLES::911912sage: B = DescentAlgebra(QQ, 3).B()913sage: for c in Compositions(3): B.to_symmetric_group_algebra_on_basis(c)914[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]915[1, 2, 3] + [2, 1, 3] + [3, 1, 2]916[1, 2, 3] + [1, 3, 2] + [2, 3, 1]917[1, 2, 3]918sage: I = DescentAlgebra(QQ, 3).I()919sage: for c in Compositions(3): I.to_symmetric_group_algebra_on_basis(c)920[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]9211/2*[1, 2, 3] - 1/2*[1, 3, 2] + 1/2*[2, 1, 3] - 1/2*[2, 3, 1] + 1/2*[3, 1, 2] - 1/2*[3, 2, 1]9221/2*[1, 2, 3] + 1/2*[1, 3, 2] - 1/2*[2, 1, 3] + 1/2*[2, 3, 1] - 1/2*[3, 1, 2] - 1/2*[3, 2, 1]9231/3*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] + 1/3*[3, 2, 1]924"""925D = self.realization_of().D()926return D.to_symmetric_group_algebra(D(self[S]))927928class ElementMethods:929def to_symmetric_group_algebra(self):930"""931Return ``self`` in the symmetric group algebra.932933EXAMPLES::934935sage: B = DescentAlgebra(QQ, 4).B()936sage: B[1,3].to_symmetric_group_algebra()937[1, 2, 3, 4] + [2, 1, 3, 4] + [3, 1, 2, 4] + [4, 1, 2, 3]938sage: I = DescentAlgebra(QQ, 4).I()939sage: elt = I(B[1,3])940sage: elt.to_symmetric_group_algebra()941[1, 2, 3, 4] + [2, 1, 3, 4] + [3, 1, 2, 4] + [4, 1, 2, 3]942"""943return self.parent().to_symmetric_group_algebra(self)944945946947