From 65af64ebcf0012a5cb5dfdb2bdacff93464deccc Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 27 Dec 2014 18:41:16 -0800 Subject: [PATCH 1/3] Added (quantum) Mobius algebras and KL polynomials of posets. --- src/doc/en/reference/combinat/module_list.rst | 1 + src/sage/combinat/posets/__init__.py | 2 + src/sage/combinat/posets/lattices.py | 32 + src/sage/combinat/posets/mobius_algebra.py | 729 ++++++++++++++++++ src/sage/combinat/posets/posets.py | 133 ++++ 5 files changed, 897 insertions(+) create mode 100644 src/sage/combinat/posets/mobius_algebra.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index e84dc84733e..e6603763e14 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -155,6 +155,7 @@ Comprehensive Module list sage/combinat/posets/hasse_diagram sage/combinat/posets/lattices sage/combinat/posets/linear_extensions + sage/combinat/posets/mobius_algebra sage/combinat/posets/poset_examples sage/combinat/posets/posets sage/combinat/q_analogues diff --git a/src/sage/combinat/posets/__init__.py b/src/sage/combinat/posets/__init__.py index 8b6b80ea2eb..15767a01964 100644 --- a/src/sage/combinat/posets/__init__.py +++ b/src/sage/combinat/posets/__init__.py @@ -13,6 +13,8 @@ - :ref:`sage.combinat.posets.linear_extensions` +- :ref:`sage.combinat.posets.mobius_algebra` + - :ref:`sage.combinat.tamari_lattices` - :ref:`sage.combinat.interval_posets` diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 2e637c71b9f..2635c368da4 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -16,6 +16,7 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** + from sage.categories.finite_lattice_posets import FiniteLatticePosets from sage.combinat.posets.posets import Poset, FinitePoset from sage.combinat.posets.elements import (LatticePosetElement, @@ -722,6 +723,37 @@ def is_lower_semimodular(self): for a in range(n) for b in range(a+1, n)) return True + def mobius_algebra(self, R): + """ + Return the Mobius algebra of ``self`` over ``R``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: L.mobius_algebra(QQ) + Mobius algebra of Finite lattice containing 16 elements over Rational Field + """ + from sage.combinat.posets.mobius_algebra import MobiusAlgebra + return MobiusAlgebra(R, self) + + def quantum_mobius_algebra(self, q=None): + """ + Return the quantum Mobius algebra of ``self`` with parameter ``q``. + + INPUT: + + - ``q`` -- (optional) the deformation parameter `q` + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: L.quantum_mobius_algebra() + Quantum Mobius algebra of Finite lattice containing 16 elements + with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring + """ + from sage.combinat.posets.mobius_algebra import QuantumMobiusAlgebra + return QuantumMobiusAlgebra(self, q) + #################################################################################### FiniteMeetSemilattice._dual_class = FiniteJoinSemilattice diff --git a/src/sage/combinat/posets/mobius_algebra.py b/src/sage/combinat/posets/mobius_algebra.py new file mode 100644 index 00000000000..7d49dd2e4c7 --- /dev/null +++ b/src/sage/combinat/posets/mobius_algebra.py @@ -0,0 +1,729 @@ +r""" +Mobius Algebras +""" +#***************************************************************************** +# Copyright (C) 2014 Travis Scrimshaw , +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# This code is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# The full text of the GPL is available at: +# +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.cachefunc import cached_method +from sage.misc.bindable_class import BindableClass +from sage.misc.lazy_attribute import lazy_attribute +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation +from sage.categories.algebras import Algebras +from sage.categories.realizations import Realizations, Category_realization_of_parent +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.combinat.posets.lattices import LatticePoset +from sage.combinat.free_module import CombinatorialFreeModule +from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing +from sage.rings.all import ZZ + +class BasisAbstract(CombinatorialFreeModule, BindableClass): + """ + Abstract base class for a basis. + """ + def __getitem__(self, x): + """ + Return the basis element indexed by ``x``. + + INPUT: + + - ``x`` -- an element of the lattice + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: E = L.mobius_algebra(QQ).E() + sage: E[5] + E[5] + sage: C = L.quantum_mobius_algebra().C() + sage: C[5] + C[5] + """ + L = self.realization_of()._lattice + return self.monomial(L(x)) + +class MobiusAlgebra(Parent, UniqueRepresentation): + r""" + The Mobius algebra of a lattice. + + Let `L` be a lattice. The *Mobius algebra* `M_L` was originally + constructed by Solomon and has a natural basis + `\{ E_x \mid x \in L \}` with multiplication given by + `E_x \cdot E_y = E_{x \vee y}`. Moreover this has a basis given by + orthogonal idempotents `\{ I_x \mid x \in L \}` (so + `I_x I_y = \delta_{xy} I_x` where `\delta` is the Kronecker delta) + related to the natural basis by + + .. MATH:: + + I_x = \sum_{y \leq x} \mu_L(y, x) E_x, + + where `\mu_L` is the Mobius function of `L`. + + REFERENCES: + + .. [Greene73] Curtis Greene. + *On the Mobius algebra of a partially ordered set*. + Advances in Mathematics, **10**, 1973. + :doi:`10.1016/0001-8708(73)90106-0`. + + .. [Etienne98] Gwihen Etienne. + *On the Mobius algebra of geometric lattices*. + European Journal of Combinatorics, **19**, 1998. + :doi:`10.1006/eujc.1998.0227`. + """ + def __init__(self, R, L): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.mobius_algebra(QQ) + sage: TestSuite(M).run() + """ + if not L.is_lattice(): + raise ValueError("L must be a lattice") + cat = Algebras(R).Commutative().WithBasis() + if L in FiniteEnumeratedSets(): + cat = cat.FiniteDimensional() + self._lattice = L + self._category = cat + Parent.__init__(self, base=R, category=self._category.WithRealizations()) + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: L.mobius_algebra(QQ) + Mobius algebra of Finite lattice containing 16 elements over Rational Field + """ + return "Mobius algebra of {} over {}".format(self._lattice, self.base_ring()) + + def a_realization(self): + r""" + Return a particular realization of ``self`` (the `B`-basis). + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.mobius_algebra(QQ) + sage: M.a_realization() + Mobius algebra of Finite lattice containing 16 elements + over Rational Field in the natural basis + """ + return self.E() + + def lattice(self): + """ + Return the defining lattice of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.mobius_algebra(QQ) + sage: M.lattice() + Finite lattice containing 16 elements + sage: M.lattice() == L + True + """ + return self._lattice + + class E(BasisAbstract): + r""" + The natural basis of a Mobius algebra. + + Let `E_x` and `E_y` be basis elements of `M_L` for some lattice `L`. + Multiplication is given by `E_x E_y = E_{x \vee y}`. + """ + def __init__(self, M, prefix='E'): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.mobius_algebra(QQ) + sage: TestSuite(M.E()).run() + """ + self._basis_name = "natural" + CombinatorialFreeModule.__init__(self, M.base_ring(), + tuple(M._lattice), + prefix=prefix, + category=MobiusAlgebraBases(M)) + + @cached_method + def _to_idempotent_basis(self, x): + """ + Convert the element indexed by ``x`` to the idempotent basis. + + EXAMPLES:: + + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: E = M.E() + sage: all(E(E._to_idempotent_basis(x)) == E.monomial(x) + ....: for x in E.basis().keys()) + True + """ + M = self.realization_of() + I = M.idempotent() + return I.sum_of_monomials(M._lattice.order_ideal([x])) + + def product_on_basis(self, x, y): + """ + Return the product of basis elements indexed by ``x`` and ``y``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: E = L.mobius_algebra(QQ).E() + sage: E.product_on_basis(5, 14) + E[15] + sage: E.product_on_basis(2, 8) + E[10] + """ + return self.monomial(self.realization_of()._lattice.join(x, y)) + + @cached_method + def one(self): + """ + Return the element ``1`` of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: E = L.mobius_algebra(QQ).E() + sage: E.one() + E[0] + """ + elts = self.realization_of()._lattice.minimal_elements() + return self.sum_of_monomials(elts) + + natural = E + + class I(BasisAbstract): + """ + The (orthogonal) idempotent basis of a Mobius algebra. + + Let `I_x` and `I_y` be basis elements of `M_L` for some lattice `L`. + Multiplication is given by `I_x I_y = \delta_{xy} I_x` where + `\delta_{xy}` is the Kronecker delta. + """ + def __init__(self, M, prefix='I'): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.mobius_algebra(QQ) + sage: TestSuite(M.I()).run() + """ + self._basis_name = "idempotent" + CombinatorialFreeModule.__init__(self, M.base_ring(), + tuple(M._lattice), + prefix=prefix, + category=MobiusAlgebraBases(M)) + + ## Change of basis: + E = M.E() + self.module_morphism(self._to_natural_basis, + codomain=E, category=self.category(), + triangular='upper', unitriangular=True + ).register_as_coercion() + + E.module_morphism(E._to_idempotent_basis, + codomain=self, category=self.category(), + triangular='upper', unitriangular=True + ).register_as_coercion() + + + @cached_method + def _to_natural_basis(self, x): + """ + Convert the element indexed by ``x`` to the natural basis. + + EXAMPLES:: + + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: I = M.I() + sage: all(I(I._to_natural_basis(x)) == I.monomial(x) + ....: for x in I.basis().keys()) + True + """ + M = self.realization_of() + N = M.natural() + mobius = M._lattice.mobius_function + return N.sum_of_terms((y, mobius(y,x)) for y in M._lattice.order_ideal([x])) + + def product_on_basis(self, x, y): + """ + Return the product of basis elements indexed by ``x`` and ``y``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: I = L.mobius_algebra(QQ).I() + sage: I.product_on_basis(5, 14) + 0 + sage: I.product_on_basis(2, 2) + I[2] + """ + if x == y: + return self.monomial(x) + return self.zero() + + @cached_method + def one(self): + """ + Return the element ``1`` of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: I = L.mobius_algebra(QQ).I() + sage: I.one() + I[0] + I[1] + I[2] + I[3] + I[4] + I[5] + I[6] + I[7] + I[8] + + I[9] + I[10] + I[11] + I[12] + I[13] + I[14] + I[15] + """ + return self.sum_of_monomials(self.realization_of()._lattice) + + def __getitem__(self, x): + """ + Return the basis element indexed by ``x``. + + INPUT: + + - ``x`` -- an element of the lattice + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: I = L.mobius_algebra(QQ).I() + sage: I[5] + I[5] + """ + L = self.realization_of()._lattice + return self.monomial(L(x)) + + idempotent = I + +class QuantumMobiusAlgebra(Parent, UniqueRepresentation): + r""" + The quantum Mobius algebra of a lattice. + + Let `L` be a lattice, and we define the *quantum Mobius algebra* `M_L(q)` + as the algebra with basis `\{ E_x \mid x \in L \}` with + multiplication given by + + .. MATH:: + + E_x E_y = \sum_{z \geq a \geq x \vee y} \mu_L(a, z) + q^{\operatorname{crk} a} E_z, + + where `\mu_L` is the Mobius function of `L` and `\operatorname{crk}` + is the corank function (i.e., `\operatorname{crk} a = + \operatorname{rank} L - \operatorname{rank}` a). At `q = 1`, this + reduces to the multiplication formula originally given by Solomon. + """ + def __init__(self, L, q=None): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.quantum_mobius_algebra() + sage: TestSuite(M).run() # long time + """ + if not L.is_lattice(): + raise ValueError("L must be a lattice") + if q is None: + q = LaurentPolynomialRing(ZZ, 'q').gen() + self._q = q + R = q.parent() + cat = Algebras(R).WithBasis() + if L in FiniteEnumeratedSets(): + cat = cat.Commutative().FiniteDimensional() + self._lattice = L + self._category = cat + Parent.__init__(self, base=R, category=self._category.WithRealizations()) + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: L.quantum_mobius_algebra() + Quantum Mobius algebra of Finite lattice containing 16 elements + with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring + """ + return "Quantum Mobius algebra of {} with q={} over {}".format( + self._lattice, self._q, self.base_ring()) + + def a_realization(self): + r""" + Return a particular realization of ``self`` (the `B`-basis). + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.quantum_mobius_algebra() + sage: M.a_realization() + Quantum Mobius algebra of Finite lattice containing 16 elements + with q=q over Univariate Laurent Polynomial Ring in q + over Integer Ring in the natural basis + """ + return self.E() + + def lattice(self): + """ + Return the defining lattice of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.quantum_mobius_algebra() + sage: M.lattice() + Finite lattice containing 16 elements + sage: M.lattice() == L + True + """ + return self._lattice + + class E(BasisAbstract): + r""" + The natural basis of a Mobius algebra. + + Let `E_x` and `E_y` be basis elements of `M_L` for some lattice `L`. + Multiplication is given by + + .. MATH:: + + E_x E_y = \sum_{z \geq a \geq x \vee y} \mu_L(a, z) + q^{\operatorname{crk} a} E_z, + + where `\mu_L` is the Mobius function of `L` and `\operatorname{crk}` + is the corank function (i.e., `\operatorname{crk} a = + \operatorname{rank} L - \operatorname{rank}` a). + """ + def __init__(self, M, prefix='E'): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.quantum_mobius_algebra() + sage: TestSuite(M.E()).run() # long time + """ + self._basis_name = "natural" + CombinatorialFreeModule.__init__(self, M.base_ring(), + tuple(M._lattice), + prefix=prefix, + category=MobiusAlgebraBases(M)) + + def product_on_basis(self, x, y): + """ + Return the product of basis elements indexed by ``x`` and ``y``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: E = L.quantum_mobius_algebra().E() + sage: E.product_on_basis(5, 14) + E[15] + sage: E.product_on_basis(2, 8) + q^2*E[10] + (q-q^2)*E[11] + (q-q^2)*E[14] + (1-2*q+q^2)*E[15] + """ + L = self.realization_of()._lattice + q = self.realization_of()._q + mobius = L.mobius_function + rank = L.rank_function() + R = L.rank() + j = L.join(x,y) + return self.sum_of_terms(( z, mobius(a,z) * q**(R - rank(a)) ) + for z in L.order_filter([j]) + for a in L.closed_interval(j, z)) + + @cached_method + def one(self): + """ + Return the element ``1`` of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: E = L.quantum_mobius_algebra().E() + sage: all(E.one() * b == b for b in E.basis()) + True + """ + L = self.realization_of()._lattice + q = self.realization_of()._q + mobius = L.mobius_function + rank = L.rank_function() + R = L.rank() + return self.sum_of_terms((x, mobius(y,x) * q**(rank(y) - R)) + for x in L for y in L.order_ideal([x])) + + natural = E + + class C(BasisAbstract): + r""" + The characteristic basis of a Mobius algebra. + + The characteristic basis `\{ C_x \mid x \in L \}` of `M_L` + for some lattice `L` is defined by + + .. MATH:: + + C_x = \sum_{a \geq x} P(I^x; q) E_a, + + where `I^x = \{ y \in L \mid y \geq x \}` is the order filter and + `P(I^x; q)` is the characteristic polynomial of the (sub)poset `I^x`. + """ + def __init__(self, M, prefix='C'): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(3) + sage: M = L.quantum_mobius_algebra() + sage: TestSuite(M.C()).run() # long time + """ + self._basis_name = "characteristic" + CombinatorialFreeModule.__init__(self, M.base_ring(), + tuple(M._lattice), + prefix=prefix, + category=MobiusAlgebraBases(M)) + + ## Change of basis: + E = M.E() + phi = self.module_morphism(self._to_natural_basis, + codomain=E, category=self.category(), + triangular='lower', unitriangular=True) + + phi.register_as_coercion() + (~phi).register_as_coercion() + + @cached_method + def _to_natural_basis(self, x): + """ + Convert the element indexed by ``x`` to the natural basis. + + EXAMPLES:: + + sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: C = M.C() + sage: all(C(C._to_natural_basis(x)) == C.monomial(x) + ....: for x in C.basis().keys()) + True + """ + M = self.realization_of() + N = M.natural() + q = M._q + R = M.base_ring() + L = M._lattice + poly = lambda x,y: L.subposet(L.closed_interval(x, y)).characteristic_polynomial() + # This is a workaround until #17554 is fixed... + subs = lambda p,q: R.sum( c * q**e for e,c in enumerate(p.list()) ) + # ...at which point, we can do poly(x,y)(q=q) + return N.sum_of_terms((y, subs(poly(x,y), q)) + for y in L.order_filter([x])) + + characteristic_basis = C + + class KL(BasisAbstract): + """ + The Kazhdan-Lusztig basis of a quantum Mobius algebra. + + The Kazhdan-Lusztig basis `\{ B_x \mid x \in L \}` of `M_L` + for some lattice `L` is defined by + + .. MATH:: + + B_x = \sum_{y \geq x} P_{x,y}(q) E_a, + + where `P_{x,y}(q)` is the Kazhdan-Lusztig polynomial of `L`, + following the definition given in [EPW14]_. + + EXAMPLES: + + We construct some examples of Proposition 4.5 of [EPW14]_:: + + sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: KL = M.KL() + sage: KL[4] * KL[5] + (q^2+q^3)*KL[5] + (q+2*q^2+q^3)*KL[7] + (q+2*q^2+q^3)*KL[13] + (1+3*q+3*q^2+q^3)*KL[15] + sage: KL[4] * KL[15] + (1+3*q+3*q^2+q^3)*KL[15] + sage: KL[4] * KL[10] + (q+3*q^2+3*q^3+q^4)*KL[14] + (1+4*q+6*q^2+4*q^3+q^4)*KL[15] + """ + def __init__(self, M, prefix='KL'): + """ + Initialize ``self``. + + TESTS:: + + sage: L = posets.BooleanLattice(4) + sage: M = L.quantum_mobius_algebra() + sage: TestSuite(M.KL()).run() # long time + """ + self._basis_name = "Kazhdan-Lusztig" + CombinatorialFreeModule.__init__(self, M.base_ring(), + tuple(M._lattice), + prefix=prefix, + category=MobiusAlgebraBases(M)) + + ## Change of basis: + E = M.E() + phi = self.module_morphism(self._to_natural_basis, + codomain=E, category=self.category(), + triangular='lower', unitriangular=True) + + phi.register_as_coercion() + (~phi).register_as_coercion() + + @cached_method + def _to_natural_basis(self, x): + """ + Convert the element indexed by ``x`` to the natural basis. + + EXAMPLES:: + + sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: KL = M.KL() + sage: all(KL(KL._to_natural_basis(x)) == KL.monomial(x) # long time + ....: for x in KL.basis().keys()) + True + """ + M = self.realization_of() + L = M._lattice + E = M.E() + q = M._q + R = M.base_ring() + rank = L.rank_function() + # This is a workaround until #17554 is fixed... + subs = lambda p,q: R.sum( c * q**e for e,c in enumerate(p.list()) ) + return E.sum_of_terms((y, q**(rank(y) - rank(x)) * + subs(L.kazhdan_lusztig_polynomial(x, y), q**-2)) + for y in L.order_filter([x])) + + kazhdan_lusztig = KL + +class MobiusAlgebraBases(Category_realization_of_parent): + r""" + The category of bases of a Mobius algebra. + + INPUT: + + - ``base`` -- a Mobius algebra + + TESTS:: + + sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: bases = MobiusAlgebraBases(M) + sage: M.E() in bases + True + """ + def _repr_(self): + r""" + Return the representation of ``self``. + + EXAMPLES:: + + sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: MobiusAlgebraBases(M) + Category of bases of Mobius algebra of Finite lattice + containing 16 elements over Rational Field + """ + return "Category of bases of {}".format(self.base()) + + def super_categories(self): + r""" + The super categories of ``self``. + + EXAMPLES:: + + sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: bases = MobiusAlgebraBases(M) + sage: bases.super_categories() + [Category of finite dimensional commutative algebras with basis over Rational Field, + Category of realizations of Mobius algebra of Finite lattice + containing 16 elements over Rational Field] + """ + return [self.base()._category, Realizations(self.base())] + + class ParentMethods: + def _repr_(self): + """ + Text representation of this basis of a Mobius algebra. + + EXAMPLES:: + + sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: M.E() + Mobius algebra of Finite lattice containing 16 elements + over Rational Field in the natural basis + sage: M.I() + Mobius algebra of Finite lattice containing 16 elements + over Rational Field in the idempotent basis + """ + return "{} in the {} basis".format(self.realization_of(), self._basis_name) + + def product_on_basis(self, x, y): + """ + Return the product of basis elements indexed by ``x`` and ``y``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: C = L.quantum_mobius_algebra().C() + sage: C.product_on_basis(5, 14) + q^3*C[15] + sage: C.product_on_basis(2, 8) + q^4*C[10] + """ + R = self.realization_of().a_realization() + return self(R(self.monomial(x)) * R(self.monomial(y))) + + @cached_method + def one(self): + """ + Return the element ``1`` of ``self``. + + EXAMPLES:: + + sage: L = posets.BooleanLattice(4) + sage: C = L.quantum_mobius_algebra().C() + sage: all(C.one() * b == b for b in C.basis()) + True + """ + R = self.realization_of().a_realization() + return self(R.one()) + + class ElementMethods: + pass + diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index e0a21339b58..445872cd53f 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -139,6 +139,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod +from sage.functions.other import floor from sage.categories.category import Category from sage.categories.sets_cat import Sets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets @@ -150,6 +151,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.polynomial.polynomial_ring import polygen +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.graphs.digraph import DiGraph from sage.graphs.digraph_generators import digraphs from sage.combinat.posets.hasse_diagram import HasseDiagram @@ -5003,6 +5005,137 @@ def p_partition_enumerator(self, tup, R, check=False): res += QR.Fundamental()(Composition(from_subset=(descents, n))) return res + @cached_method(key=lambda self,x,y,l: (x,y)) + def _kl_poly(self, x=None, y=None, canonical_labels=None): + r""" + Cached Kazhdan-Lusztig polynomial of ``self`` for generic `q`. + + .. SEEALSO:: + + :meth:`kazhdan_lusztig_polynomial` + + EXAMPLES:: + + sage: L = posets.SymmetricGroupWeakOrderPoset(4) + sage: L._kl_poly() + 1 + sage: x = '2314' + sage: y = '3421' + sage: L._kl_poly(x, y) + -q + 1 + + AUTHORS: + + - Travis Scrimshaw (27-12-2014) + """ + R = PolynomialRing(ZZ, 'q') + q = R.gen(0) + + # Handle some special cases + if self.cardinality() == 0: + return q.parent().zero() + if not self.rank(): + return q.parent().one() + + if canonical_labels is None: + canonical_labels = x is None and y is None + + if x is not None or y is not None: + if x == y: + return q.parent().one() + if x is None: + x = self.minimal_elements()[0] + if y is None: + y = self.maximal_elements()[0] + if not self.le(x, y): + return q.parent().zero() + P = self.subposet(self.interval(x, y)) + return P.kazhdan_lusztig_polynomial(q=q, canonical_labels=canonical_labels) + + min_elt = self.minimal_elements()[0] + if canonical_labels: + sublat = lambda P: self.subposet(P).canonical_label() + else: + sublat = lambda P: self.subposet(P) + poly = -sum(sublat(self.order_ideal([x])).characteristic_polynomial() + * sublat(self.order_filter([x])).kazhdan_lusztig_polynomial() + for x in self if x != min_elt) + tr = floor(self.rank()/2) + 1 + ret = poly.truncate(tr) + return ret(q=q) + + def kazhdan_lusztig_polynomial(self, x=None, y=None, q=None, canonical_labels=None): + r""" + Return the Kazhdan-Lusztig polynomial `P_{x,y}(q)` of ``self``. + + We follow the definition given in [EPW14]_. Let `G` denote a + graded poset with unique minimal and maximal elements and `\chi_G` + denote the characteristic polynomial of `G`. Let `I_x` and `F^x` + denote the order ideal and filter of `x` respectively. Define the + *Kazhdan-Lusztig polynomial* of `G` as the unique polynomial + `P_G(q)` satisfying the following: + + 1. If `\operatorname{rank} G = 0`, then `P_G(q) = 1`. + 2. If `\operatorname{rank} G > 0`, then `\deg P_G(q) < + \frac{1}{2} \operatorname{rank} G`. + 3. We have + + .. MATH:: + + q^{\operatorname{rank} G} P_G(q^{-1}) + = \sum_{x \in G} \chi_{I_x}(q) P_{F^x}(q). + + We then extend this to `P_{x,y}(q)` by considering the subposet + corresponding to the (closed) interval `[x, y]`. We also + define `P_{\emptyset}(q) = 0` (so if `x \not\leq y`, + then `P_{x,y}(q) = 0`). + + INPUT: + + - ``q`` -- (default: `q \in \ZZ[q]`) the indeterminate `q` + - ``x`` -- (default: the minimal element) the element `x` + - ``y`` -- (default: the maximal element) the element `y` + - ``canonical_labels`` -- (optional) for subposets, use the + canonical labeling (this can limit recursive calls for posets + with large amounts of symmetry, but producing the labeling + takes time); if not specified, this is ``True`` if ``x`` + and ``y`` are both not specified and ``False`` otherwise + + EXAMPLES:: + + sage: L = posets.BooleanLattice(3) + sage: L.kazhdan_lusztig_polynomial() + 1 + + :: + + sage: L = posets.SymmetricGroupWeakOrderPoset(4) + sage: L.kazhdan_lusztig_polynomial() + 1 + sage: x = '2314' + sage: y = '3421' + sage: L.kazhdan_lusztig_polynomial(x, y) + -q + 1 + sage: L.kazhdan_lusztig_polynomial(x, y, var('t')) + -t + 1 + + REFERENCES: + + .. [EPW14] Ben Elias, Nicholas Proudfoot, and Max Wakefield. + *The Kazhdan-Lusztig polynomial of a matroid*. 2014. + :arxiv:`1412.7408`. + + AUTHORS: + + - Travis Scrimshaw (27-12-2014) + """ + if not self.is_ranked(): + raise ValueError("poset is not ranked") + if q is None: + q = PolynomialRing(ZZ, 'q').gen(0) + poly = self._kl_poly(x, y, canonical_labels) + return poly(q=q) + FinitePoset._dual_class = FinitePoset ##### Posets ##### From 852fc7b91ce687cfe2e92fb501f9a034170c47cc Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 30 Apr 2015 19:57:37 -0700 Subject: [PATCH 2/3] Adding to the catalog and fixing bad mergeing. --- src/sage/algebras/catalog.py | 2 + src/sage/combinat/posets/posets.py | 165 ++++++++++++++++++----------- 2 files changed, 106 insertions(+), 61 deletions(-) diff --git a/src/sage/algebras/catalog.py b/src/sage/algebras/catalog.py index 88a30534497..4a8cb39e407 100644 --- a/src/sage/algebras/catalog.py +++ b/src/sage/algebras/catalog.py @@ -23,6 +23,7 @@ - :class:`algebras.Incidence ` - :class:`algebras.IwahoriHecke ` +- :class:`algebras.Mobius ` - :class:`algebras.NilCoxeter ` - :func:`algebras.Quaternion @@ -48,5 +49,6 @@ lazy_import('sage.algebras.shuffle_algebra', 'ShuffleAlgebra', 'Shuffle') lazy_import('sage.algebras.commutative_dga', 'GradedCommutativeAlgebra', 'GradedCommutative') lazy_import('sage.combinat.posets.incidence_algebras', 'IncidenceAlgebra', 'Incidence') +lazy_import('sage.combinat.posets.mobius_algebra', 'MobiusAlgebra', 'Mobius') del lazy_import # We remove the object from here so it doesn't appear under tab completion diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index f7d9a4d114e..10b47a095b4 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -80,6 +80,7 @@ :meth:`~FinitePoset.is_incomparable_chain_free` | Returns whether the poset is `(m+n)`-free. :meth:`~FinitePoset.is_ranked` | Returns whether this poset is ranked. :meth:`~FinitePoset.is_slender` | Returns whether the poset ``self`` is slender or not. + :meth:`~FinitePoset.kazhdan_lusztig_polynomial` | Return the Kazhdan-Lusztig polynomial `P_{x,y}(q)` of ``self``. :meth:`~FinitePoset.lequal_matrix` | Computes the matrix whose ``(i,j)`` entry is 1 if ``self.linear_extension()[i] < self.linear_extension()[j]`` and 0 otherwise :meth:`~FinitePoset.level_sets` | Returns a list l such that l[i+1] is the set of minimal elements of the poset obtained by removing the elements in l[0], l[1], ..., l[i]. :meth:`~FinitePoset.linear_extension` | Returns a linear extension of this poset. @@ -5337,91 +5338,133 @@ def incidence_algebra(self, R, prefix='I'): @cached_method(key=lambda self,x,y,l: (x,y)) def _kl_poly(self, x=None, y=None, canonical_labels=None): r""" - Return the list of cuts of the poset ``self``. + Cached Kazhdan-Lusztig polynomial of ``self`` for generic `q`. - A cut is a subset `A` of ``self`` such that the set of lower - bounds of the set of upper bounds of `A` is exactly `A`. + .. SEEALSO:: - The cuts are computed here using the maximal independent sets in the - auxiliary graph defined as `P \times [0,1]` with an edge - from `(x, 0)` to `(y, 1)` if - and only if `x \not\geq_P y`. See the end of section 4 in [JRJ94]_. + :meth:`kazhdan_lusztig_polynomial` EXAMPLES:: - sage: P = posets.AntichainPoset(3) - sage: Pc = P.cuts() - sage: [list(c) for c in Pc] - [[0], [0, 1, 2], [], [1], [2]] - sage: Pc[0] - frozenset({0}) + sage: L = posets.SymmetricGroupWeakOrderPoset(4) + sage: L._kl_poly() + 1 + sage: x = '2314' + sage: y = '3421' + sage: L._kl_poly(x, y) + -q + 1 - .. SEEALSO:: + AUTHORS: - :meth:`completion_by_cuts` + - Travis Scrimshaw (27-12-2014) + """ + R = PolynomialRing(ZZ, 'q') + q = R.gen(0) - REFERENCES: + # Handle some special cases + if self.cardinality() == 0: + return q.parent().zero() + if not self.rank(): + return q.parent().one() - .. [JRJ94] Jourdan, Guy-Vincent; Rampon, Jean-Xavier; Jard, Claude - (1994), "Computing on-line the lattice of maximal antichains - of posets", Order 11 (3) p. 197-210, :doi:`10.1007/BF02115811` - """ - from sage.graphs.graph import Graph - from sage.graphs.independent_sets import IndependentSets - auxg = Graph({(u, 0): [(v, 1) for v in self if not self.ge(u, v)] - for u in self}) - auxg.add_vertices([(v, 1) for v in self]) - return [frozenset([xa for xa, xb in c if xb == 0]) - for c in IndependentSets(auxg, maximal=True)] + if canonical_labels is None: + canonical_labels = x is None and y is None + + if x is not None or y is not None: + if x == y: + return q.parent().one() + if x is None: + x = self.minimal_elements()[0] + if y is None: + y = self.maximal_elements()[0] + if not self.le(x, y): + return q.parent().zero() + P = self.subposet(self.interval(x, y)) + return P.kazhdan_lusztig_polynomial(q=q, canonical_labels=canonical_labels) + + min_elt = self.minimal_elements()[0] + if canonical_labels: + sublat = lambda P: self.subposet(P).canonical_label() + else: + sublat = lambda P: self.subposet(P) + poly = -sum(sublat(self.order_ideal([x])).characteristic_polynomial() + * sublat(self.order_filter([x])).kazhdan_lusztig_polynomial() + for x in self if x != min_elt) + tr = floor(self.rank()/2) + 1 + ret = poly.truncate(tr) + return ret(q=q) + + def kazhdan_lusztig_polynomial(self, x=None, y=None, q=None, canonical_labels=None): + r""" + Return the Kazhdan-Lusztig polynomial `P_{x,y}(q)` of ``self``. - def completion_by_cuts(self): - """ - Return the completion by cuts of ``self``. + We follow the definition given in [EPW14]_. Let `G` denote a + graded poset with unique minimal and maximal elements and `\chi_G` + denote the characteristic polynomial of `G`. Let `I_x` and `F^x` + denote the order ideal and filter of `x` respectively. Define the + *Kazhdan-Lusztig polynomial* of `G` as the unique polynomial + `P_G(q)` satisfying the following: - This is a lattice, also called the Dedekind-MacNeille completion. + 1. If `\operatorname{rank} G = 0`, then `P_G(q) = 1`. + 2. If `\operatorname{rank} G > 0`, then `\deg P_G(q) < + \frac{1}{2} \operatorname{rank} G`. + 3. We have - See the :wikipedia:`Dedekind-MacNeille completion`. + .. MATH:: - OUTPUT: + q^{\operatorname{rank} G} P_G(q^{-1}) + = \sum_{x \in G} \chi_{I_x}(q) P_{F^x}(q). - - a finite lattice + We then extend this to `P_{x,y}(q)` by considering the subposet + corresponding to the (closed) interval `[x, y]`. We also + define `P_{\emptyset}(q) = 0` (so if `x \not\leq y`, + then `P_{x,y}(q) = 0`). - EXAMPLES:: + INPUT: - sage: P = posets.PentagonPoset() - sage: P.completion_by_cuts().is_isomorphic(P) - True + - ``q`` -- (default: `q \in \ZZ[q]`) the indeterminate `q` + - ``x`` -- (default: the minimal element) the element `x` + - ``y`` -- (default: the maximal element) the element `y` + - ``canonical_labels`` -- (optional) for subposets, use the + canonical labeling (this can limit recursive calls for posets + with large amounts of symmetry, but producing the labeling + takes time); if not specified, this is ``True`` if ``x`` + and ``y`` are both not specified and ``False`` otherwise - sage: P = posets.AntichainPoset(3) - sage: Q = P.completion_by_cuts() - sage: Q.is_isomorphic(posets.DiamondPoset(5)) - True + EXAMPLES:: - sage: P = posets.SymmetricGroupBruhatOrderPoset(3) - sage: Q = P.completion_by_cuts(); Q - Finite lattice containing 7 elements + sage: L = posets.BooleanLattice(3) + sage: L.kazhdan_lusztig_polynomial() + 1 - .. SEEALSO:: + :: - :meth:`cuts` - """ - from sage.combinat.posets.lattices import LatticePoset - from sage.misc.misc import attrcall - return LatticePoset((self.cuts(), attrcall("issubset"))) + sage: L = posets.SymmetricGroupWeakOrderPoset(4) + sage: L.kazhdan_lusztig_polynomial() + 1 + sage: x = '2314' + sage: y = '3421' + sage: L.kazhdan_lusztig_polynomial(x, y) + -q + 1 + sage: L.kazhdan_lusztig_polynomial(x, y, var('t')) + -t + 1 - def incidence_algebra(self, R, prefix='I'): - r""" - Return the incidence algebra of ``self`` over ``R``. + REFERENCES: - EXAMPLES:: + .. [EPW14] Ben Elias, Nicholas Proudfoot, and Max Wakefield. + *The Kazhdan-Lusztig polynomial of a matroid*. 2014. + :arxiv:`1412.7408`. - sage: P = posets.BooleanLattice(4) - sage: P.incidence_algebra(QQ) - Incidence algebra of Finite lattice containing 16 elements - over Rational Field + AUTHORS: + + - Travis Scrimshaw (27-12-2014) """ - from sage.combinat.posets.incidence_algebras import IncidenceAlgebra - return IncidenceAlgebra(R, self, prefix) + if not self.is_ranked(): + raise ValueError("poset is not ranked") + if q is None: + q = PolynomialRing(ZZ, 'q').gen(0) + poly = self._kl_poly(x, y, canonical_labels) + return poly(q=q) FinitePoset._dual_class = FinitePoset From 4e51ab0a00e0784de44d7da40f92dc078c48f440 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 14 Oct 2015 22:46:08 -0500 Subject: [PATCH 3/3] Adding an e and following Kevin's suggestions. --- src/sage/combinat/posets/lattices.py | 20 +-- .../{mobius_algebra.py => moebius_algebra.py} | 161 +++++++++--------- src/sage/combinat/posets/posets.py | 6 +- 3 files changed, 95 insertions(+), 92 deletions(-) rename src/sage/combinat/posets/{mobius_algebra.py => moebius_algebra.py} (80%) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 48e36294c76..0b985eeb448 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -1148,20 +1148,20 @@ def frattini_sublattice(self): return LatticePoset(self.subposet([self[x] for x in self._hasse_diagram.frattini_sublattice()])) - def mobius_algebra(self, R): + def moebius_algebra(self, R): """ Return the Mobius algebra of ``self`` over ``R``. EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: L.mobius_algebra(QQ) - Mobius algebra of Finite lattice containing 16 elements over Rational Field + sage: L.moebius_algebra(QQ) + Moebius algebra of Finite lattice containing 16 elements over Rational Field """ - from sage.combinat.posets.mobius_algebra import MobiusAlgebra - return MobiusAlgebra(R, self) + from sage.combinat.posets.moebius_algebra import MoebiusAlgebra + return MoebiusAlgebra(R, self) - def quantum_mobius_algebra(self, q=None): + def quantum_moebius_algebra(self, q=None): """ Return the quantum Mobius algebra of ``self`` with parameter ``q``. @@ -1172,12 +1172,12 @@ def quantum_mobius_algebra(self, q=None): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: L.quantum_mobius_algebra() - Quantum Mobius algebra of Finite lattice containing 16 elements + sage: L.quantum_moebius_algebra() + Quantum Moebius algebra of Finite lattice containing 16 elements with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring """ - from sage.combinat.posets.mobius_algebra import QuantumMobiusAlgebra - return QuantumMobiusAlgebra(self, q) + from sage.combinat.posets.moebius_algebra import QuantumMoebiusAlgebra + return QuantumMoebiusAlgebra(self, q) ############################################################################ diff --git a/src/sage/combinat/posets/mobius_algebra.py b/src/sage/combinat/posets/moebius_algebra.py similarity index 80% rename from src/sage/combinat/posets/mobius_algebra.py rename to src/sage/combinat/posets/moebius_algebra.py index 7d49dd2e4c7..1d57ca89062 100644 --- a/src/sage/combinat/posets/mobius_algebra.py +++ b/src/sage/combinat/posets/moebius_algebra.py @@ -1,5 +1,6 @@ +# -*- coding: utf-8 -*- r""" -Mobius Algebras +Möbius Algebras """ #***************************************************************************** # Copyright (C) 2014 Travis Scrimshaw , @@ -44,21 +45,21 @@ def __getitem__(self, x): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: E = L.mobius_algebra(QQ).E() + sage: E = L.moebius_algebra(QQ).E() sage: E[5] E[5] - sage: C = L.quantum_mobius_algebra().C() + sage: C = L.quantum_moebius_algebra().C() sage: C[5] C[5] """ L = self.realization_of()._lattice return self.monomial(L(x)) -class MobiusAlgebra(Parent, UniqueRepresentation): +class MoebiusAlgebra(Parent, UniqueRepresentation): r""" - The Mobius algebra of a lattice. + The möbius algebra of a lattice. - Let `L` be a lattice. The *Mobius algebra* `M_L` was originally + Let `L` be a lattice. The *Möbius algebra* `M_L` was originally constructed by Solomon and has a natural basis `\{ E_x \mid x \in L \}` with multiplication given by `E_x \cdot E_y = E_{x \vee y}`. Moreover this has a basis given by @@ -70,17 +71,17 @@ class MobiusAlgebra(Parent, UniqueRepresentation): I_x = \sum_{y \leq x} \mu_L(y, x) E_x, - where `\mu_L` is the Mobius function of `L`. + where `\mu_L` is the Möbius function of `L`. REFERENCES: .. [Greene73] Curtis Greene. - *On the Mobius algebra of a partially ordered set*. + *On the Möbius algebra of a partially ordered set*. Advances in Mathematics, **10**, 1973. :doi:`10.1016/0001-8708(73)90106-0`. .. [Etienne98] Gwihen Etienne. - *On the Mobius algebra of geometric lattices*. + *On the Möbius algebra of geometric lattices*. European Journal of Combinatorics, **19**, 1998. :doi:`10.1006/eujc.1998.0227`. """ @@ -91,7 +92,7 @@ def __init__(self, R, L): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.mobius_algebra(QQ) + sage: M = L.moebius_algebra(QQ) sage: TestSuite(M).run() """ if not L.is_lattice(): @@ -110,10 +111,10 @@ def _repr_(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: L.mobius_algebra(QQ) - Mobius algebra of Finite lattice containing 16 elements over Rational Field + sage: L.moebius_algebra(QQ) + Moebius algebra of Finite lattice containing 16 elements over Rational Field """ - return "Mobius algebra of {} over {}".format(self._lattice, self.base_ring()) + return "Moebius algebra of {} over {}".format(self._lattice, self.base_ring()) def a_realization(self): r""" @@ -122,9 +123,9 @@ def a_realization(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: M = L.mobius_algebra(QQ) + sage: M = L.moebius_algebra(QQ) sage: M.a_realization() - Mobius algebra of Finite lattice containing 16 elements + Moebius algebra of Finite lattice containing 16 elements over Rational Field in the natural basis """ return self.E() @@ -136,7 +137,7 @@ def lattice(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: M = L.mobius_algebra(QQ) + sage: M = L.moebius_algebra(QQ) sage: M.lattice() Finite lattice containing 16 elements sage: M.lattice() == L @@ -146,7 +147,7 @@ def lattice(self): class E(BasisAbstract): r""" - The natural basis of a Mobius algebra. + The natural basis of a Möbius algebra. Let `E_x` and `E_y` be basis elements of `M_L` for some lattice `L`. Multiplication is given by `E_x E_y = E_{x \vee y}`. @@ -158,14 +159,14 @@ def __init__(self, M, prefix='E'): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.mobius_algebra(QQ) + sage: M = L.moebius_algebra(QQ) sage: TestSuite(M.E()).run() """ self._basis_name = "natural" CombinatorialFreeModule.__init__(self, M.base_ring(), tuple(M._lattice), prefix=prefix, - category=MobiusAlgebraBases(M)) + category=MoebiusAlgebraBases(M)) @cached_method def _to_idempotent_basis(self, x): @@ -174,7 +175,7 @@ def _to_idempotent_basis(self, x): EXAMPLES:: - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) sage: E = M.E() sage: all(E(E._to_idempotent_basis(x)) == E.monomial(x) ....: for x in E.basis().keys()) @@ -191,7 +192,7 @@ def product_on_basis(self, x, y): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: E = L.mobius_algebra(QQ).E() + sage: E = L.moebius_algebra(QQ).E() sage: E.product_on_basis(5, 14) E[15] sage: E.product_on_basis(2, 8) @@ -207,7 +208,7 @@ def one(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: E = L.mobius_algebra(QQ).E() + sage: E = L.moebius_algebra(QQ).E() sage: E.one() E[0] """ @@ -218,7 +219,7 @@ def one(self): class I(BasisAbstract): """ - The (orthogonal) idempotent basis of a Mobius algebra. + The (orthogonal) idempotent basis of a Möbius algebra. Let `I_x` and `I_y` be basis elements of `M_L` for some lattice `L`. Multiplication is given by `I_x I_y = \delta_{xy} I_x` where @@ -231,14 +232,14 @@ def __init__(self, M, prefix='I'): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.mobius_algebra(QQ) + sage: M = L.moebius_algebra(QQ) sage: TestSuite(M.I()).run() """ self._basis_name = "idempotent" CombinatorialFreeModule.__init__(self, M.base_ring(), tuple(M._lattice), prefix=prefix, - category=MobiusAlgebraBases(M)) + category=MoebiusAlgebraBases(M)) ## Change of basis: E = M.E() @@ -260,7 +261,7 @@ def _to_natural_basis(self, x): EXAMPLES:: - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) sage: I = M.I() sage: all(I(I._to_natural_basis(x)) == I.monomial(x) ....: for x in I.basis().keys()) @@ -278,7 +279,7 @@ def product_on_basis(self, x, y): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: I = L.mobius_algebra(QQ).I() + sage: I = L.moebius_algebra(QQ).I() sage: I.product_on_basis(5, 14) 0 sage: I.product_on_basis(2, 2) @@ -296,7 +297,7 @@ def one(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: I = L.mobius_algebra(QQ).I() + sage: I = L.moebius_algebra(QQ).I() sage: I.one() I[0] + I[1] + I[2] + I[3] + I[4] + I[5] + I[6] + I[7] + I[8] + I[9] + I[10] + I[11] + I[12] + I[13] + I[14] + I[15] @@ -314,7 +315,7 @@ def __getitem__(self, x): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: I = L.mobius_algebra(QQ).I() + sage: I = L.moebius_algebra(QQ).I() sage: I[5] I[5] """ @@ -323,11 +324,11 @@ def __getitem__(self, x): idempotent = I -class QuantumMobiusAlgebra(Parent, UniqueRepresentation): +class QuantumMoebiusAlgebra(Parent, UniqueRepresentation): r""" - The quantum Mobius algebra of a lattice. + The quantum Möbius algebra of a lattice. - Let `L` be a lattice, and we define the *quantum Mobius algebra* `M_L(q)` + Let `L` be a lattice, and we define the *quantum Möbius algebra* `M_L(q)` as the algebra with basis `\{ E_x \mid x \in L \}` with multiplication given by @@ -336,7 +337,7 @@ class QuantumMobiusAlgebra(Parent, UniqueRepresentation): E_x E_y = \sum_{z \geq a \geq x \vee y} \mu_L(a, z) q^{\operatorname{crk} a} E_z, - where `\mu_L` is the Mobius function of `L` and `\operatorname{crk}` + where `\mu_L` is the Möbius function of `L` and `\operatorname{crk}` is the corank function (i.e., `\operatorname{crk} a = \operatorname{rank} L - \operatorname{rank}` a). At `q = 1`, this reduces to the multiplication formula originally given by Solomon. @@ -348,7 +349,7 @@ def __init__(self, L, q=None): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: TestSuite(M).run() # long time """ if not L.is_lattice(): @@ -371,11 +372,11 @@ def _repr_(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: L.quantum_mobius_algebra() - Quantum Mobius algebra of Finite lattice containing 16 elements + sage: L.quantum_moebius_algebra() + Quantum Moebius algebra of Finite lattice containing 16 elements with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring """ - return "Quantum Mobius algebra of {} with q={} over {}".format( + return "Quantum Moebius algebra of {} with q={} over {}".format( self._lattice, self._q, self.base_ring()) def a_realization(self): @@ -385,9 +386,9 @@ def a_realization(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: M.a_realization() - Quantum Mobius algebra of Finite lattice containing 16 elements + Quantum Moebius algebra of Finite lattice containing 16 elements with q=q over Univariate Laurent Polynomial Ring in q over Integer Ring in the natural basis """ @@ -400,7 +401,7 @@ def lattice(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: M.lattice() Finite lattice containing 16 elements sage: M.lattice() == L @@ -410,7 +411,7 @@ def lattice(self): class E(BasisAbstract): r""" - The natural basis of a Mobius algebra. + The natural basis of a quantum Möbius algebra. Let `E_x` and `E_y` be basis elements of `M_L` for some lattice `L`. Multiplication is given by @@ -420,7 +421,7 @@ class E(BasisAbstract): E_x E_y = \sum_{z \geq a \geq x \vee y} \mu_L(a, z) q^{\operatorname{crk} a} E_z, - where `\mu_L` is the Mobius function of `L` and `\operatorname{crk}` + where `\mu_L` is the Möbius function of `L` and `\operatorname{crk}` is the corank function (i.e., `\operatorname{crk} a = \operatorname{rank} L - \operatorname{rank}` a). """ @@ -431,14 +432,14 @@ def __init__(self, M, prefix='E'): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: TestSuite(M.E()).run() # long time """ self._basis_name = "natural" CombinatorialFreeModule.__init__(self, M.base_ring(), tuple(M._lattice), prefix=prefix, - category=MobiusAlgebraBases(M)) + category=MoebiusAlgebraBases(M)) def product_on_basis(self, x, y): """ @@ -447,7 +448,7 @@ def product_on_basis(self, x, y): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: E = L.quantum_mobius_algebra().E() + sage: E = L.quantum_moebius_algebra().E() sage: E.product_on_basis(5, 14) E[15] sage: E.product_on_basis(2, 8) @@ -471,7 +472,7 @@ def one(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: E = L.quantum_mobius_algebra().E() + sage: E = L.quantum_moebius_algebra().E() sage: all(E.one() * b == b for b in E.basis()) True """ @@ -487,17 +488,18 @@ def one(self): class C(BasisAbstract): r""" - The characteristic basis of a Mobius algebra. + The characteristic basis of a quantum Möbius algebra. The characteristic basis `\{ C_x \mid x \in L \}` of `M_L` for some lattice `L` is defined by .. MATH:: - C_x = \sum_{a \geq x} P(I^x; q) E_a, + C_x = \sum_{a \geq x} P(F^x; q) E_a, - where `I^x = \{ y \in L \mid y \geq x \}` is the order filter and - `P(I^x; q)` is the characteristic polynomial of the (sub)poset `I^x`. + where `F^x = \{ y \in L \mid y \geq x \}` is the principal order + filter of `x` and `P(F^x; q)` is the characteristic polynomial + of the (sub)poset `F^x`. """ def __init__(self, M, prefix='C'): """ @@ -506,14 +508,14 @@ def __init__(self, M, prefix='C'): TESTS:: sage: L = posets.BooleanLattice(3) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: TestSuite(M.C()).run() # long time """ self._basis_name = "characteristic" CombinatorialFreeModule.__init__(self, M.base_ring(), tuple(M._lattice), prefix=prefix, - category=MobiusAlgebraBases(M)) + category=MoebiusAlgebraBases(M)) ## Change of basis: E = M.E() @@ -531,7 +533,7 @@ def _to_natural_basis(self, x): EXAMPLES:: - sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: M = posets.BooleanLattice(4).quantum_moebius_algebra() sage: C = M.C() sage: all(C(C._to_natural_basis(x)) == C.monomial(x) ....: for x in C.basis().keys()) @@ -553,7 +555,7 @@ def _to_natural_basis(self, x): class KL(BasisAbstract): """ - The Kazhdan-Lusztig basis of a quantum Mobius algebra. + The Kazhdan-Lusztig basis of a quantum Möbius algebra. The Kazhdan-Lusztig basis `\{ B_x \mid x \in L \}` of `M_L` for some lattice `L` is defined by @@ -569,10 +571,11 @@ class KL(BasisAbstract): We construct some examples of Proposition 4.5 of [EPW14]_:: - sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: M = posets.BooleanLattice(4).quantum_moebius_algebra() sage: KL = M.KL() sage: KL[4] * KL[5] - (q^2+q^3)*KL[5] + (q+2*q^2+q^3)*KL[7] + (q+2*q^2+q^3)*KL[13] + (1+3*q+3*q^2+q^3)*KL[15] + (q^2+q^3)*KL[5] + (q+2*q^2+q^3)*KL[7] + (q+2*q^2+q^3)*KL[13] + + (1+3*q+3*q^2+q^3)*KL[15] sage: KL[4] * KL[15] (1+3*q+3*q^2+q^3)*KL[15] sage: KL[4] * KL[10] @@ -585,14 +588,14 @@ def __init__(self, M, prefix='KL'): TESTS:: sage: L = posets.BooleanLattice(4) - sage: M = L.quantum_mobius_algebra() + sage: M = L.quantum_moebius_algebra() sage: TestSuite(M.KL()).run() # long time """ self._basis_name = "Kazhdan-Lusztig" CombinatorialFreeModule.__init__(self, M.base_ring(), tuple(M._lattice), prefix=prefix, - category=MobiusAlgebraBases(M)) + category=MoebiusAlgebraBases(M)) ## Change of basis: E = M.E() @@ -610,7 +613,7 @@ def _to_natural_basis(self, x): EXAMPLES:: - sage: M = posets.BooleanLattice(4).quantum_mobius_algebra() + sage: M = posets.BooleanLattice(4).quantum_moebius_algebra() sage: KL = M.KL() sage: all(KL(KL._to_natural_basis(x)) == KL.monomial(x) # long time ....: for x in KL.basis().keys()) @@ -630,19 +633,19 @@ def _to_natural_basis(self, x): kazhdan_lusztig = KL -class MobiusAlgebraBases(Category_realization_of_parent): +class MoebiusAlgebraBases(Category_realization_of_parent): r""" - The category of bases of a Mobius algebra. + The category of bases of a Möbius algebra. INPUT: - - ``base`` -- a Mobius algebra + - ``base`` -- a Möbius algebra TESTS:: - sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) - sage: bases = MobiusAlgebraBases(M) + sage: from sage.combinat.posets.moebius_algebra import MoebiusAlgebraBases + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) + sage: bases = MoebiusAlgebraBases(M) sage: M.E() in bases True """ @@ -652,10 +655,10 @@ def _repr_(self): EXAMPLES:: - sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) - sage: MobiusAlgebraBases(M) - Category of bases of Mobius algebra of Finite lattice + sage: from sage.combinat.posets.moebius_algebra import MoebiusAlgebraBases + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) + sage: MoebiusAlgebraBases(M) + Category of bases of Moebius algebra of Finite lattice containing 16 elements over Rational Field """ return "Category of bases of {}".format(self.base()) @@ -666,12 +669,12 @@ def super_categories(self): EXAMPLES:: - sage: from sage.combinat.posets.mobius_algebra import MobiusAlgebraBases - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) - sage: bases = MobiusAlgebraBases(M) + sage: from sage.combinat.posets.moebius_algebra import MoebiusAlgebraBases + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) + sage: bases = MoebiusAlgebraBases(M) sage: bases.super_categories() [Category of finite dimensional commutative algebras with basis over Rational Field, - Category of realizations of Mobius algebra of Finite lattice + Category of realizations of Moebius algebra of Finite lattice containing 16 elements over Rational Field] """ return [self.base()._category, Realizations(self.base())] @@ -679,16 +682,16 @@ def super_categories(self): class ParentMethods: def _repr_(self): """ - Text representation of this basis of a Mobius algebra. + Text representation of this basis of a Möbius algebra. EXAMPLES:: - sage: M = posets.BooleanLattice(4).mobius_algebra(QQ) + sage: M = posets.BooleanLattice(4).moebius_algebra(QQ) sage: M.E() - Mobius algebra of Finite lattice containing 16 elements + Moebius algebra of Finite lattice containing 16 elements over Rational Field in the natural basis sage: M.I() - Mobius algebra of Finite lattice containing 16 elements + Moebius algebra of Finite lattice containing 16 elements over Rational Field in the idempotent basis """ return "{} in the {} basis".format(self.realization_of(), self._basis_name) @@ -700,7 +703,7 @@ def product_on_basis(self, x, y): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: C = L.quantum_mobius_algebra().C() + sage: C = L.quantum_moebius_algebra().C() sage: C.product_on_basis(5, 14) q^3*C[15] sage: C.product_on_basis(2, 8) @@ -717,7 +720,7 @@ def one(self): EXAMPLES:: sage: L = posets.BooleanLattice(4) - sage: C = L.quantum_mobius_algebra().C() + sage: C = L.quantum_moebius_algebra().C() sage: all(C.one() * b == b for b in C.basis()) True """ diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 5bf70f58b65..b29cc3563be 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -5721,9 +5721,9 @@ def kazhdan_lusztig_polynomial(self, x=None, y=None, q=None, canonical_labels=No We follow the definition given in [EPW14]_. Let `G` denote a graded poset with unique minimal and maximal elements and `\chi_G` denote the characteristic polynomial of `G`. Let `I_x` and `F^x` - denote the order ideal and filter of `x` respectively. Define the - *Kazhdan-Lusztig polynomial* of `G` as the unique polynomial - `P_G(q)` satisfying the following: + denote the principal order ideal and filter of `x` respectively. + Define the *Kazhdan-Lusztig polynomial* of `G` as the unique + polynomial `P_G(q)` satisfying the following: 1. If `\operatorname{rank} G = 0`, then `P_G(q) = 1`. 2. If `\operatorname{rank} G > 0`, then `\deg P_G(q) <