Key and Atom Polynomials - Combinatorics

Skip to content
Back to top
View this page
Edit this page

# Key and Atom Polynomials

Key polynomials (also known as type A Demazure characters) are defined by applying the divided difference operator \(\pi_{\sigma}\), where \(\sigma\) is a permutation, to a monomial corresponding to an integer partition \(\mu \vdash n\).

See also

For Demazure characters in other types, see

- `sage.combinat.root_system.weyl_characters.WeylCharacterRing.demazure_character()`

- `sage.categories.classical_crystals.ClassicalCrystals.ParentMethods.demazure_character()`

Atom polynomials (also known as Demazure atoms) are defined analogously by using a deformed divided difference operator \(\bar{\pi}_i = \pi_i - 1\).

AUTHORS:

- Trevor K. Karn (2022-08-17): initial version

- Travis Scrimshaw (2025-10-10): expanded to atoms

class sage.combinat.key_polynomial.AtomPolynomial

  Bases: `OperatorPolynomial`

  An atom polynomial.

  Atom polynomials are polynomials that form a basis for a polynomial ring and are indexed by weak compositions.

  Elements should be created by first creating the basis `AtomPolynomialBasis` and passing a list representing the indexing composition.

  EXAMPLES:

  Sage

      sage: a = AtomPolynomials(QQ)
      sage: f = a([4,3,2,1]) + a([1,2,3,4]); f
      a[1, 2, 3, 4] + a[4, 3, 2, 1]
      sage: f in a
      True

  Python

      >>> from sage.all import *
      >>> a = AtomPolynomials(QQ)
      >>> f = a([Integer(4),Integer(3),Integer(2),Integer(1)]) + a([Integer(1),Integer(2),Integer(3),Integer(4)]); f
      a[1, 2, 3, 4] + a[4, 3, 2, 1]
      >>> f in a
      True

  isobaric_divided_difference(w)

    alias of `pi()`.

  pi(w)

    Return the action of the isobaric divided difference operator \(\pi_w\) on `self`.

    EXAMPLES:

    Sage

        sage: a = AtomPolynomials(QQ)
        sage: a[2,3,1].pi(2)
        a[2, 1, 3] + a[2, 3, 1]
        sage: a[2,3,1].pi([2,3])
        a[2, 1, 0, 3] + a[2, 1, 3] + a[2, 3, 0, 1] + a[2, 3, 1]
        sage: a[2,3,1].pi([2,2]) == a[2,3,1].pi(2)
        True

    Python

        >>> from sage.all import *
        >>> a = AtomPolynomials(QQ)
        >>> a[Integer(2),Integer(3),Integer(1)].pi(Integer(2))
        a[2, 1, 3] + a[2, 3, 1]
        >>> a[Integer(2),Integer(3),Integer(1)].pi([Integer(2),Integer(3)])
        a[2, 1, 0, 3] + a[2, 1, 3] + a[2, 3, 0, 1] + a[2, 3, 1]
        >>> a[Integer(2),Integer(3),Integer(1)].pi([Integer(2),Integer(2)]) == a[Integer(2),Integer(3),Integer(1)].pi(Integer(2))
        True

  pibar(w)

    Apply the operator \(\bar{\pi}_w\) to `self`.

    `w` may be either a `Permutation` or a list of indices of simple transpositions (1-based).

    The convention is to apply from left to right so if `w = [w1, w2, ..., wm]` then we apply \(\bar{\pi}_{w_2 \cdots w_m} \circ \bar{\pi}_{w_1}\).

    EXAMPLES:

    Sage

        sage: a = AtomPolynomials(QQ)
        sage: a([3,2,1]).pibar(2)
        a[3, 1, 2]
        sage: a([3,2,1]).pibar([2,1])
        a[1, 3, 2]
        sage: a([3,2,1]).pibar(Permutation([3,2,1]))
        a[1, 2, 3]
        sage: f = a([3,2,1]) + a([3,2,1,1])
        sage: f.pibar(2)
        a[3, 1, 2] + a[3, 1, 2, 1]
        sage: a.one().pibar(1)
        0

        sage: a([3,2,1,0]).pibar(2).pibar(2)
        -a[3, 1, 2]
        sage: (-a([3,2,1,0]) + 4*a([3,1,2,0])).pibar(2)
        -5*a[3, 1, 2]

        sage: a = AtomPolynomials(QQ, 4)
        sage: a([3,2,1,0]).pibar(2)
        a[3, 1, 2, 0]
        sage: a([3,2,1,0]).pibar([2,1])
        a[1, 3, 2, 0]
        sage: a([3,2,1,0]).pibar(Permutation([3,2,1,4]))
        a[1, 2, 3, 0]
        sage: f = a([3,2,1,0]) + a([3,2,1,1])
        sage: f.pibar(2)
        a[3, 1, 2, 0] + a[3, 1, 2, 1]
        sage: a.one().pibar(1)
        0

    Python

        >>> from sage.all import *
        >>> a = AtomPolynomials(QQ)
        >>> a([Integer(3),Integer(2),Integer(1)]).pibar(Integer(2))
        a[3, 1, 2]
        >>> a([Integer(3),Integer(2),Integer(1)]).pibar([Integer(2),Integer(1)])
        a[1, 3, 2]
        >>> a([Integer(3),Integer(2),Integer(1)]).pibar(Permutation([Integer(3),Integer(2),Integer(1)]))
        a[1, 2, 3]
        >>> f = a([Integer(3),Integer(2),Integer(1)]) + a([Integer(3),Integer(2),Integer(1),Integer(1)])
        >>> f.pibar(Integer(2))
        a[3, 1, 2] + a[3, 1, 2, 1]
        >>> a.one().pibar(Integer(1))
        0

        >>> a([Integer(3),Integer(2),Integer(1),Integer(0)]).pibar(Integer(2)).pibar(Integer(2))
        -a[3, 1, 2]
        >>> (-a([Integer(3),Integer(2),Integer(1),Integer(0)]) + Integer(4)*a([Integer(3),Integer(1),Integer(2),Integer(0)])).pibar(Integer(2))
        -5*a[3, 1, 2]

        >>> a = AtomPolynomials(QQ, Integer(4))
        >>> a([Integer(3),Integer(2),Integer(1),Integer(0)]).pibar(Integer(2))
        a[3, 1, 2, 0]
        >>> a([Integer(3),Integer(2),Integer(1),Integer(0)]).pibar([Integer(2),Integer(1)])
        a[1, 3, 2, 0]
        >>> a([Integer(3),Integer(2),Integer(1),Integer(0)]).pibar(Permutation([Integer(3),Integer(2),Integer(1),Integer(4)]))
        a[1, 2, 3, 0]
        >>> f = a([Integer(3),Integer(2),Integer(1),Integer(0)]) + a([Integer(3),Integer(2),Integer(1),Integer(1)])
        >>> f.pibar(Integer(2))
        a[3, 1, 2, 0] + a[3, 1, 2, 1]
        >>> a.one().pibar(Integer(1))
        0

class sage.combinat.key_polynomial.AtomPolynomialBasis(R=None, k=None, poly_ring=None)

  Bases: `OperatorPolynomialBasis`

  The atom polynomial basis for a polynomial ring.

  For a full definition, see SymmetricFunctions.com. Atom polynomials are indexed by weak compositions \(\alpha\) with no trailing zeros. A basis element is given by

  \[a_{\alpha} = \bar{\pi}_{\sigma} x^{\mu},\]

  where \(\sigma\) is the permutation of shortest length which sorts the \(\alpha\) into a partition \(\mu\).

  EXAMPLES:

  Atom polynomials are a basis, indexed by (weak) compositions, for polynomial rings:

  Sage

      sage: a = AtomPolynomials(QQ)
      sage: a([3,0,1,2])
      a[3, 0, 1, 2]
      sage: a([3,0,1,2])/2
      1/2*a[3, 0, 1, 2]
      sage: R = a.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field

      sage: A = AtomPolynomials(GF(5)); A
      Atom polynomial basis over Finite Field of size 5
      sage: 2*A([3,0,1,2])
      2*a[3, 0, 1, 2]
      sage: 5*(A([3,0,1,2]) + A([3,1,1]))
      0

  Python

      >>> from sage.all import *
      >>> a = AtomPolynomials(QQ)
      >>> a([Integer(3),Integer(0),Integer(1),Integer(2)])
      a[3, 0, 1, 2]
      >>> a([Integer(3),Integer(0),Integer(1),Integer(2)])/Integer(2)
      1/2*a[3, 0, 1, 2]
      >>> R = a.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field

      >>> A = AtomPolynomials(GF(Integer(5))); A
      Atom polynomial basis over Finite Field of size 5
      >>> Integer(2)*A([Integer(3),Integer(0),Integer(1),Integer(2)])
      2*a[3, 0, 1, 2]
      >>> Integer(5)*(A([Integer(3),Integer(0),Integer(1),Integer(2)]) + A([Integer(3),Integer(1),Integer(1)]))
      0

  We can expand them in the standard monomial basis:

  Sage

      sage: a([2,1,3,2]).expand()
      z_3^2*z_2^3*z_1*z_0^2 + z_3^2*z_2^2*z_1^2*z_0^2

      sage: a[0,2,2].expand()
      z_2^2*z_1^2 + z_2^2*z_1*z_0 + z_2*z_1^2*z_0

  [Python]

      >>> from sage.all import *
      >>> a([Integer(2),Integer(1),Integer(3),Integer(2)]).expand()
      z_3^2*z_2^3*z_1*z_0^2 + z_3^2*z_2^2*z_1^2*z_0^2

      >>> a[Integer(0),Integer(2),Integer(2)].expand()
      z_2^2*z_1^2 + z_2^2*z_1*z_0 + z_2*z_1^2*z_0

  If we have a polynomial, we can express it in the atom basis:

  Sage

      sage: z = R.gen()
      sage: a.from_polynomial(z[2]^2*z[1]*z[0])
      a[1, 1, 2]
      sage: a.from_polynomial(z[2]^3*z[1]^2*z[0])
      a[1, 2, 3]

      sage: f = (z[3]^2*z[2]*z[0]^3 + z[3]^2*z[1]*z[0]^3 + z[3]*z[2]^2*z[0]^3
      ....:      + 2*z[3]*z[2]*z[1]*z[0]^3 + z[3]*z[1]^2*z[0]^3
      ....:      + z[2]^2*z[1]*z[0]^3 + z[2]*z[1]^2*z[0]^3)
      sage: a.from_polynomial(f)
      a[3, 0, 1, 2] + a[3, 0, 2, 1] + a[3, 1, 0, 2] + a[3, 1, 2]
       + a[3, 2, 0, 1] + a[3, 2, 1]

  Python

      >>> from sage.all import *
      >>> z = R.gen()
      >>> a.from_polynomial(z[Integer(2)]**Integer(2)*z[Integer(1)]*z[Integer(0)])
      a[1, 1, 2]
      >>> a.from_polynomial(z[Integer(2)]**Integer(3)*z[Integer(1)]**Integer(2)*z[Integer(0)])
      a[1, 2, 3]

      >>> f = (z[Integer(3)]**Integer(2)*z[Integer(2)]*z[Integer(0)]**Integer(3) + z[Integer(3)]**Integer(2)*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(3)]*z[Integer(2)]**Integer(2)*z[Integer(0)]**Integer(3)
      ...      + Integer(2)*z[Integer(3)]*z[Integer(2)]*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(3)]*z[Integer(1)]**Integer(2)*z[Integer(0)]**Integer(3)
      ...      + z[Integer(2)]**Integer(2)*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(2)]*z[Integer(1)]**Integer(2)*z[Integer(0)]**Integer(3))
      >>> a.from_polynomial(f)
      a[3, 0, 1, 2] + a[3, 0, 2, 1] + a[3, 1, 0, 2] + a[3, 1, 2]
       + a[3, 2, 0, 1] + a[3, 2, 1]

  Since the ring of atom polynomials may be regarded as a different choice of basis for a polynomial ring, it forms an algebra, so we have multiplication:

  Sage

      sage: a[10,5,2] * a[1,1,1]
      a[11, 6, 3]

  [Python]

      >>> from sage.all import *
      >>> a[Integer(10),Integer(5),Integer(2)] * a[Integer(1),Integer(1),Integer(1)]
      a[11, 6, 3]

  We can also multiply by polynomials in the monomial basis:

  Sage

      sage: a([10,9,1]) * z[0]
      a[11, 9, 1]
      sage: z[0] * a([10,9,1])
      a[11, 9, 1]
      sage: a([10,9,1]) * (z[0] + z[3])
      a[10, 9, 1, 1] + a[11, 9, 1]

  Python

      >>> from sage.all import *
      >>> a([Integer(10),Integer(9),Integer(1)]) * z[Integer(0)]
      a[11, 9, 1]
      >>> z[Integer(0)] * a([Integer(10),Integer(9),Integer(1)])
      a[11, 9, 1]
      >>> a([Integer(10),Integer(9),Integer(1)]) * (z[Integer(0)] + z[Integer(3)])
      a[10, 9, 1, 1] + a[11, 9, 1]

  Element

    alias of `AtomPolynomial`

  from_key_polynomial(x)

    Expand a key polynomial in `self`.

    EXAMPLES:

    Sage

        sage: a = AtomPolynomials(ZZ)
        sage: k = KeyPolynomials(ZZ)
        sage: f = k[1,2,3]
        sage: a.from_key_polynomial(f)
        a[1, 2, 3] + a[1, 3, 2] + a[2, 1, 3] + a[2, 3, 1] + a[3, 1, 2] + a[3, 2, 1]
        sage: a.from_key_polynomial(2)
        2*a[]
        sage: a(f)
        a[1, 2, 3] + a[1, 3, 2] + a[2, 1, 3] + a[2, 3, 1] + a[3, 1, 2] + a[3, 2, 1]

        sage: a = AtomPolynomials(GF(7), 4)
        sage: a.from_key_polynomial(f)
        a[1, 2, 3, 0] + a[1, 3, 2, 0] + a[2, 1, 3, 0]
         + a[2, 3, 1, 0] + a[3, 1, 2, 0] + a[3, 2, 1, 0]

    Python

        >>> from sage.all import *
        >>> a = AtomPolynomials(ZZ)
        >>> k = KeyPolynomials(ZZ)
        >>> f = k[Integer(1),Integer(2),Integer(3)]
        >>> a.from_key_polynomial(f)
        a[1, 2, 3] + a[1, 3, 2] + a[2, 1, 3] + a[2, 3, 1] + a[3, 1, 2] + a[3, 2, 1]
        >>> a.from_key_polynomial(Integer(2))
        2*a[]
        >>> a(f)
        a[1, 2, 3] + a[1, 3, 2] + a[2, 1, 3] + a[2, 3, 1] + a[3, 1, 2] + a[3, 2, 1]

        >>> a = AtomPolynomials(GF(Integer(7)), Integer(4))
        >>> a.from_key_polynomial(f)
        a[1, 2, 3, 0] + a[1, 3, 2, 0] + a[2, 1, 3, 0]
         + a[2, 3, 1, 0] + a[3, 1, 2, 0] + a[3, 2, 1, 0]

class sage.combinat.key_polynomial.KeyPolynomial

  Bases: `OperatorPolynomial`

  A key polynomial.

  Key polynomials are polynomials that form a basis for a polynomial ring and are indexed by weak compositions.

  Elements should be created by first creating the basis `KeyPolynomialBasis` and passing a list representing the indexing composition.

  EXAMPLES:

  Sage

      sage: k = KeyPolynomials(QQ)
      sage: f = k([4,3,2,1]) + k([1,2,3,4]); f
      k[1, 2, 3, 4] + k[4, 3, 2, 1]
      sage: f in k
      True

  Python

      >>> from sage.all import *
      >>> k = KeyPolynomials(QQ)
      >>> f = k([Integer(4),Integer(3),Integer(2),Integer(1)]) + k([Integer(1),Integer(2),Integer(3),Integer(4)]); f
      k[1, 2, 3, 4] + k[4, 3, 2, 1]
      >>> f in k
      True

  isobaric_divided_difference(w)

    alias of `pi()`.

  pi(w)

    Apply the operator \(\pi_w\) to `self`.

    `w` may be either a `Permutation` or a list of indices of simple transpositions (1-based).

    The convention is to apply from left to right so if `w = [w1, w2, ..., wm]` then we apply \(\pi_{w_2 \cdots w_m} \circ \pi_{w_1}\)

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k([3,2,1]).pi(2)
        k[3, 1, 2]
        sage: k([3,2,1]).pi([2,1])
        k[1, 3, 2]
        sage: k([3,2,1]).pi(Permutation([3,2,1]))
        k[1, 2, 3]
        sage: f = k([3,2,1]) + k([3,2,1,1])
        sage: f.pi(2)
        k[3, 1, 2] + k[3, 1, 2, 1]
        sage: k.one().pi(1)
        k[]

        sage: k([3,2,1,0]).pi(2).pi(2)
        k[3, 1, 2]
        sage: (-k([3,2,1,0]) + 4*k([3,1,2,0])).pi(2)
        3*k[3, 1, 2]

        sage: k = KeyPolynomials(QQ, 4)
        sage: k([3,2,1,0]).pi(2)
        k[3, 1, 2, 0]
        sage: k([3,2,1,0]).pi([2,1])
        k[1, 3, 2, 0]
        sage: k([3,2,1,0]).pi(Permutation([3,2,1,4]))
        k[1, 2, 3, 0]
        sage: f = k([3,2,1,0]) + k([3,2,1,1])
        sage: f.pi(2)
        k[3, 1, 2, 0] + k[3, 1, 2, 1]
        sage: k.one().pi(1)
        k[0, 0, 0, 0]

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k([Integer(3),Integer(2),Integer(1)]).pi(Integer(2))
        k[3, 1, 2]
        >>> k([Integer(3),Integer(2),Integer(1)]).pi([Integer(2),Integer(1)])
        k[1, 3, 2]
        >>> k([Integer(3),Integer(2),Integer(1)]).pi(Permutation([Integer(3),Integer(2),Integer(1)]))
        k[1, 2, 3]
        >>> f = k([Integer(3),Integer(2),Integer(1)]) + k([Integer(3),Integer(2),Integer(1),Integer(1)])
        >>> f.pi(Integer(2))
        k[3, 1, 2] + k[3, 1, 2, 1]
        >>> k.one().pi(Integer(1))
        k[]

        >>> k([Integer(3),Integer(2),Integer(1),Integer(0)]).pi(Integer(2)).pi(Integer(2))
        k[3, 1, 2]
        >>> (-k([Integer(3),Integer(2),Integer(1),Integer(0)]) + Integer(4)*k([Integer(3),Integer(1),Integer(2),Integer(0)])).pi(Integer(2))
        3*k[3, 1, 2]

        >>> k = KeyPolynomials(QQ, Integer(4))
        >>> k([Integer(3),Integer(2),Integer(1),Integer(0)]).pi(Integer(2))
        k[3, 1, 2, 0]
        >>> k([Integer(3),Integer(2),Integer(1),Integer(0)]).pi([Integer(2),Integer(1)])
        k[1, 3, 2, 0]
        >>> k([Integer(3),Integer(2),Integer(1),Integer(0)]).pi(Permutation([Integer(3),Integer(2),Integer(1),Integer(4)]))
        k[1, 2, 3, 0]
        >>> f = k([Integer(3),Integer(2),Integer(1),Integer(0)]) + k([Integer(3),Integer(2),Integer(1),Integer(1)])
        >>> f.pi(Integer(2))
        k[3, 1, 2, 0] + k[3, 1, 2, 1]
        >>> k.one().pi(Integer(1))
        k[0, 0, 0, 0]

  pibar(w)

    Apply the operator \(\bar{\pi}_w\) to `self`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k[2,3,1].pibar(2)
        k[2, 1, 3] - k[2, 3, 1]
        sage: k[2,3,1].pibar([2,3])
        k[2, 1, 0, 3] - k[2, 1, 3] - k[2, 3, 0, 1] + k[2, 3, 1]
        sage: k[2,3,1].pibar([2,2]) == -k[2,3,1].pibar(2)
        True

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k[Integer(2),Integer(3),Integer(1)].pibar(Integer(2))
        k[2, 1, 3] - k[2, 3, 1]
        >>> k[Integer(2),Integer(3),Integer(1)].pibar([Integer(2),Integer(3)])
        k[2, 1, 0, 3] - k[2, 1, 3] - k[2, 3, 0, 1] + k[2, 3, 1]
        >>> k[Integer(2),Integer(3),Integer(1)].pibar([Integer(2),Integer(2)]) == -k[Integer(2),Integer(3),Integer(1)].pibar(Integer(2))
        True

class sage.combinat.key_polynomial.KeyPolynomialBasis(R=None, k=None, poly_ring=None)

  Bases: `OperatorPolynomialBasis`

  The key polynomial basis for a polynomial ring.

  For a full definition, see SymmetricFunctions.com. Key polynomials are indexed by weak compositions with no trailing zeros, and \(\sigma\) is the permutation of shortest length which sorts the indexing composition into a partition.

  EXAMPLES:

  Key polynomials are a basis, indexed by (weak) compositions, for polynomial rings:

  Sage

      sage: k = KeyPolynomials(QQ)
      sage: k([3,0,1,2])
      k[3, 0, 1, 2]
      sage: k([3,0,1,2])/2
      1/2*k[3, 0, 1, 2]
      sage: R = k.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field

      sage: K = KeyPolynomials(GF(5)); K
      Key polynomial basis over Finite Field of size 5
      sage: 2*K([3,0,1,2])
      2*k[3, 0, 1, 2]
      sage: 5*(K([3,0,1,2]) + K([3,1,1]))
      0

  Python

      >>> from sage.all import *
      >>> k = KeyPolynomials(QQ)
      >>> k([Integer(3),Integer(0),Integer(1),Integer(2)])
      k[3, 0, 1, 2]
      >>> k([Integer(3),Integer(0),Integer(1),Integer(2)])/Integer(2)
      1/2*k[3, 0, 1, 2]
      >>> R = k.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field

      >>> K = KeyPolynomials(GF(Integer(5))); K
      Key polynomial basis over Finite Field of size 5
      >>> Integer(2)*K([Integer(3),Integer(0),Integer(1),Integer(2)])
      2*k[3, 0, 1, 2]
      >>> Integer(5)*(K([Integer(3),Integer(0),Integer(1),Integer(2)]) + K([Integer(3),Integer(1),Integer(1)]))
      0

  We can expand them in the standard monomial basis:

  Sage

      sage: k([3,0,1,2]).expand()
      z_3^2*z_2*z_0^3 + z_3^2*z_1*z_0^3 + z_3*z_2^2*z_0^3
       + 2*z_3*z_2*z_1*z_0^3 + z_3*z_1^2*z_0^3 + z_2^2*z_1*z_0^3
       + z_2*z_1^2*z_0^3

      sage: k([0,0,2]).expand()
      z_2^2 + z_2*z_1 + z_2*z_0 + z_1^2 + z_1*z_0 + z_0^2

  [Python]

      >>> from sage.all import *
      >>> k([Integer(3),Integer(0),Integer(1),Integer(2)]).expand()
      z_3^2*z_2*z_0^3 + z_3^2*z_1*z_0^3 + z_3*z_2^2*z_0^3
       + 2*z_3*z_2*z_1*z_0^3 + z_3*z_1^2*z_0^3 + z_2^2*z_1*z_0^3
       + z_2*z_1^2*z_0^3

      >>> k([Integer(0),Integer(0),Integer(2)]).expand()
      z_2^2 + z_2*z_1 + z_2*z_0 + z_1^2 + z_1*z_0 + z_0^2

  If we have a polynomial, we can express it in the key basis:

  Sage

      sage: z = R.gen()
      sage: k.from_polynomial(z[2]^2*z[1]*z[0])
      k[1, 1, 2] - k[1, 2, 1]

      sage: f = z[3]^2*z[2]*z[0]^3 + z[3]^2*z[1]*z[0]^3 + z[3]*z[2]^2*z[0]^3 + \
      ....: 2*z[3]*z[2]*z[1]*z[0]^3 + z[3]*z[1]^2*z[0]^3 + z[2]^2*z[1]*z[0]^3 + \
      ....: z[2]*z[1]^2*z[0]^3
      sage: k.from_polynomial(f)
      k[3, 0, 1, 2]

  Python

      >>> from sage.all import *
      >>> z = R.gen()
      >>> k.from_polynomial(z[Integer(2)]**Integer(2)*z[Integer(1)]*z[Integer(0)])
      k[1, 1, 2] - k[1, 2, 1]

      >>> f = z[Integer(3)]**Integer(2)*z[Integer(2)]*z[Integer(0)]**Integer(3) + z[Integer(3)]**Integer(2)*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(3)]*z[Integer(2)]**Integer(2)*z[Integer(0)]**Integer(3) + Integer(2)*z[Integer(3)]*z[Integer(2)]*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(3)]*z[Integer(1)]**Integer(2)*z[Integer(0)]**Integer(3) + z[Integer(2)]**Integer(2)*z[Integer(1)]*z[Integer(0)]**Integer(3) + z[Integer(2)]*z[Integer(1)]**Integer(2)*z[Integer(0)]**Integer(3)
      >>> k.from_polynomial(f)
      k[3, 0, 1, 2]

  Since the ring of key polynomials may be regarded as a different choice of basis for a polynomial ring, it forms an algebra, so we have multiplication:

  Sage

      sage: k([10,5,2])*k([1,1,1])
      k[11, 6, 3]

  [Python]

      >>> from sage.all import *
      >>> k([Integer(10),Integer(5),Integer(2)])*k([Integer(1),Integer(1),Integer(1)])
      k[11, 6, 3]

  We can also multiply by polynomials in the monomial basis:

  Sage

      sage: k([10,9,1])*z[0]
      k[11, 9, 1]
      sage: z[0] * k([10,9,1])
      k[11, 9, 1]
      sage: k([10,9,1])*(z[0] + z[3])
      k[10, 9, 1, 1] + k[11, 9, 1]

  Python

      >>> from sage.all import *
      >>> k([Integer(10),Integer(9),Integer(1)])*z[Integer(0)]
      k[11, 9, 1]
      >>> z[Integer(0)] * k([Integer(10),Integer(9),Integer(1)])
      k[11, 9, 1]
      >>> k([Integer(10),Integer(9),Integer(1)])*(z[Integer(0)] + z[Integer(3)])
      k[10, 9, 1, 1] + k[11, 9, 1]

  When the sorting permutation is the longest element, the key polynomial agrees with the Schur polynomial:

  Sage

      sage: s = SymmetricFunctions(QQ).schur()
      sage: k([1,2,3]).expand()
      z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
       + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
       + z_2*z_1^2*z_0^3
      sage: s[3,2,1].expand(3)
      x0^3*x1^2*x2 + x0^2*x1^3*x2 + x0^3*x1*x2^2 + 2*x0^2*x1^2*x2^2
       + x0*x1^3*x2^2 + x0^2*x1*x2^3 + x0*x1^2*x2^3

  [Python]

      >>> from sage.all import *
      >>> s = SymmetricFunctions(QQ).schur()
      >>> k([Integer(1),Integer(2),Integer(3)]).expand()
      z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
       + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
       + z_2*z_1^2*z_0^3
      >>> s[Integer(3),Integer(2),Integer(1)].expand(Integer(3))
      x0^3*x1^2*x2 + x0^2*x1^3*x2 + x0^3*x1*x2^2 + 2*x0^2*x1^2*x2^2
       + x0*x1^3*x2^2 + x0^2*x1*x2^3 + x0*x1^2*x2^3

  The polynomial expansions can be computed using crystals and expressed in terms of the key basis:

  Sage

      sage: T = crystals.Tableaux(['A',3],shape=[2,1])
      sage: f = T.demazure_character([3,2,1])
      sage: k.from_polynomial(f)
      k[1, 0, 0, 2]

  Python

      >>> from sage.all import *
      >>> T = crystals.Tableaux(['A',Integer(3)],shape=[Integer(2),Integer(1)])
      >>> f = T.demazure_character([Integer(3),Integer(2),Integer(1)])
      >>> k.from_polynomial(f)
      k[1, 0, 0, 2]

  The default behavior is to work in a polynomial ring with infinitely many variables. One can work in a specicfied number of variables:

  Sage

      sage: k = KeyPolynomials(QQ, 4)
      sage: k([3,0,1,2]).expand()
      z_0^3*z_1^2*z_2 + z_0^3*z_1*z_2^2 + z_0^3*z_1^2*z_3
       + 2*z_0^3*z_1*z_2*z_3 + z_0^3*z_2^2*z_3 + z_0^3*z_1*z_3^2 + z_0^3*z_2*z_3^2

      sage: k([0,0,2,0]).expand()
      z_0^2 + z_0*z_1 + z_1^2 + z_0*z_2  + z_1*z_2 + z_2^2

      sage: k([0,0,2,0]).expand().parent()
      Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field

  [Python]

      >>> from sage.all import *
      >>> k = KeyPolynomials(QQ, Integer(4))
      >>> k([Integer(3),Integer(0),Integer(1),Integer(2)]).expand()
      z_0^3*z_1^2*z_2 + z_0^3*z_1*z_2^2 + z_0^3*z_1^2*z_3
       + 2*z_0^3*z_1*z_2*z_3 + z_0^3*z_2^2*z_3 + z_0^3*z_1*z_3^2 + z_0^3*z_2*z_3^2

      >>> k([Integer(0),Integer(0),Integer(2),Integer(0)]).expand()
      z_0^2 + z_0*z_1 + z_1^2 + z_0*z_2  + z_1*z_2 + z_2^2

      >>> k([Integer(0),Integer(0),Integer(2),Integer(0)]).expand().parent()
      Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field

  If working in a specified number of variables, the length of the indexing composition must be the same as the number of variables:

  Sage

      sage: k([0,0,2])
      Traceback (most recent call last):
       ...
      TypeError: do not know how to make x (= [0, 0, 2]) an element of self
       (=Key polynomial basis over Rational Field)

  Python

      >>> from sage.all import *
      >>> k([Integer(0),Integer(0),Integer(2)])
      Traceback (most recent call last):
       ...
      TypeError: do not know how to make x (= [0, 0, 2]) an element of self
       (=Key polynomial basis over Rational Field)

  One can also work in a specified polynomial ring:

  Sage

      sage: k = KeyPolynomials(QQ['x0', 'x1', 'x2', 'x3'])
      sage: k([0,2,0,0])
      k[0, 2, 0, 0]
      sage: k([4,0,0,0]).expand()
      x0^4

  [Python]

      >>> from sage.all import *
      >>> k = KeyPolynomials(QQ['x0', 'x1', 'x2', 'x3'])
      >>> k([Integer(0),Integer(2),Integer(0),Integer(0)])
      k[0, 2, 0, 0]
      >>> k([Integer(4),Integer(0),Integer(0),Integer(0)]).expand()
      x0^4

  If one wishes to use a polynomial ring as coefficients for the key polynomials, pass the keyword argument `poly_coeffs=True`:

  Sage

      sage: k = KeyPolynomials(QQ['q'], poly_coeffs=True)
      sage: R = k.base_ring(); R
      Univariate Polynomial Ring in q over Rational Field
      sage: R.inject_variables()
      Defining q
      sage: (q^2 + q + 1)*k([0,2,2,0,3,2])
      (q^2+q+1)*k[0, 2, 2, 0, 3, 2]

  Python

      >>> from sage.all import *
      >>> k = KeyPolynomials(QQ['q'], poly_coeffs=True)
      >>> R = k.base_ring(); R
      Univariate Polynomial Ring in q over Rational Field
      >>> R.inject_variables()
      Defining q
      >>> (q**Integer(2) + q + Integer(1))*k([Integer(0),Integer(2),Integer(2),Integer(0),Integer(3),Integer(2)])
      (q^2+q+1)*k[0, 2, 2, 0, 3, 2]

  Element

    alias of `KeyPolynomial`

  from_schubert_polynomial(x)

    Expand a Schubert polynomial in `self`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(ZZ)
        sage: X = SchubertPolynomialRing(ZZ)
        sage: f = X([2,1,5,4,3])
        sage: k.from_schubert_polynomial(f)
        k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]
        sage: k.from_schubert_polynomial(2)
        2*k[]
        sage: k(f)
        k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]

        sage: k = KeyPolynomials(GF(7), 4)
        sage: k.from_schubert_polynomial(f)
        k[1, 0, 2, 1] + k[2, 0, 2, 0] + k[3, 0, 0, 1]

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(ZZ)
        >>> X = SchubertPolynomialRing(ZZ)
        >>> f = X([Integer(2),Integer(1),Integer(5),Integer(4),Integer(3)])
        >>> k.from_schubert_polynomial(f)
        k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]
        >>> k.from_schubert_polynomial(Integer(2))
        2*k[]
        >>> k(f)
        k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]

        >>> k = KeyPolynomials(GF(Integer(7)), Integer(4))
        >>> k.from_schubert_polynomial(f)
        k[1, 0, 2, 1] + k[2, 0, 2, 0] + k[3, 0, 0, 1]

class sage.combinat.key_polynomial.OperatorPolynomial

  Bases: `IndexedFreeModuleElement`

  Abstract base class for a polynomial defined recursively by divided difference type operators.

  Parents should implement the divided difference operator as a `staticmethod` `_operator`.

  divided_difference(w)

    Apply the divided difference operator \(\partial_w\) to `self`.

    The convention is to apply from left to right so if `w = [w1, w2, ..., wm]` then we apply \(\partial_{w_2 \cdots w_m} \circ \partial_{w_1}\)

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k([3,2,1]).divided_difference(2)
        k[3, 1, 1]
        sage: k([3,2,1]).divided_difference([2,3])
        k[3, 1]

        sage: k = KeyPolynomials(QQ, 4)
        sage: k([3,2,1,0]).divided_difference(2)
        k[3, 1, 1, 0]

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k([Integer(3),Integer(2),Integer(1)]).divided_difference(Integer(2))
        k[3, 1, 1]
        >>> k([Integer(3),Integer(2),Integer(1)]).divided_difference([Integer(2),Integer(3)])
        k[3, 1]

        >>> k = KeyPolynomials(QQ, Integer(4))
        >>> k([Integer(3),Integer(2),Integer(1),Integer(0)]).divided_difference(Integer(2))
        k[3, 1, 1, 0]

  expand()

    Return `self` written in the monomial basis (i.e., as an element in the corresponding polynomial ring).

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: f = k([4,3,2,1])
        sage: f.expand()
        z_3*z_2^2*z_1^3*z_0^4

        sage: f = k([1,2,3])
        sage: f.expand()
        z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
         + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
         + z_2*z_1^2*z_0^3

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> f = k([Integer(4),Integer(3),Integer(2),Integer(1)])
        >>> f.expand()
        z_3*z_2^2*z_1^3*z_0^4

        >>> f = k([Integer(1),Integer(2),Integer(3)])
        >>> f.expand()
        z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
         + 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
         + z_2*z_1^2*z_0^3

  isobaric_divided_difference(w)

    Apply the isobaric divided difference operator \(\pi_w\) to `self`.

    The convention is to apply from left to right so if `w = [w1, w2, ..., wm]` then we apply \(\pi_{w_2 \cdots w_m} \circ \pi_{w_1}\)

    EXAMPLES:

    Sage

        sage: a = AtomPolynomials(QQ)
        sage: a([3,2,1]).isobaric_divided_difference(2)
        a[3, 1, 2] + a[3, 2, 1]
        sage: a([3,2,1]).isobaric_divided_difference([2, 3])
        a[3, 1, 0, 2] + a[3, 1, 2] + a[3, 2, 0, 1] + a[3, 2, 1]

        sage: a = AtomPolynomials(QQ, 4)
        sage: a([3,2,1,0]).divided_difference(2)
        a[3, 1, 1, 0]

    Python

        >>> from sage.all import *
        >>> a = AtomPolynomials(QQ)
        >>> a([Integer(3),Integer(2),Integer(1)]).isobaric_divided_difference(Integer(2))
        a[3, 1, 2] + a[3, 2, 1]
        >>> a([Integer(3),Integer(2),Integer(1)]).isobaric_divided_difference([Integer(2), Integer(3)])
        a[3, 1, 0, 2] + a[3, 1, 2] + a[3, 2, 0, 1] + a[3, 2, 1]

        >>> a = AtomPolynomials(QQ, Integer(4))
        >>> a([Integer(3),Integer(2),Integer(1),Integer(0)]).divided_difference(Integer(2))
        a[3, 1, 1, 0]

  to_polynomial()

    alias of `expand()`.

class sage.combinat.key_polynomial.OperatorPolynomialBasis(R=None, k=None, poly_ring=None)

  Bases: `CombinatorialFreeModule`

  A basis for a polynomial ring defined recursively by divided difference type operators such that the result is a triangular change of basis with the natural monomial basis.

  degree_on_basis(alpha)

    Return the degree of the basis element indexed by `alpha`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k.degree_on_basis([2,1,0,2])
        5

        sage: k = KeyPolynomials(QQ, 5)
        sage: k.degree_on_basis([2,1,0,2,0])
        5

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k.degree_on_basis([Integer(2),Integer(1),Integer(0),Integer(2)])
        5

        >>> k = KeyPolynomials(QQ, Integer(5))
        >>> k.degree_on_basis([Integer(2),Integer(1),Integer(0),Integer(2),Integer(0)])
        5

  from_polynomial(f)

    Expand a polynomial in terms of `self`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: z = k.poly_gens(); z
        z_*
        sage: p = z[0]^4*z[1]^2*z[2]*z[3] + z[0]^4*z[1]*z[2]^2*z[3]
        sage: k.from_polynomial(p)
        k[4, 1, 2, 1]

        sage: all(k(c) == k.from_polynomial(k(c).expand()) for c in IntegerVectors(n=5, k=4))
        True

        sage: T = crystals.Tableaux(['A', 4], shape=[4,2,1,1])
        sage: k.from_polynomial(T.demazure_character([2]))
        k[4, 1, 2, 1]

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> z = k.poly_gens(); z
        z_*
        >>> p = z[Integer(0)]**Integer(4)*z[Integer(1)]**Integer(2)*z[Integer(2)]*z[Integer(3)] + z[Integer(0)]**Integer(4)*z[Integer(1)]*z[Integer(2)]**Integer(2)*z[Integer(3)]
        >>> k.from_polynomial(p)
        k[4, 1, 2, 1]

        >>> all(k(c) == k.from_polynomial(k(c).expand()) for c in IntegerVectors(n=Integer(5), k=Integer(4)))
        True

        >>> T = crystals.Tableaux(['A', Integer(4)], shape=[Integer(4),Integer(2),Integer(1),Integer(1)])
        >>> k.from_polynomial(T.demazure_character([Integer(2)]))
        k[4, 1, 2, 1]

  one_basis()

    Return the basis element indexing the identity.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k.one_basis()
        []

        sage: k = KeyPolynomials(QQ, 4)
        sage: k.one_basis()
        [0, 0, 0, 0]

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k.one_basis()
        []

        >>> k = KeyPolynomials(QQ, Integer(4))
        >>> k.one_basis()
        [0, 0, 0, 0]

  poly_gens()

    Return the polynomial generators for the polynomial ring associated to `self`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k.poly_gens()
        z_*

        sage: k = KeyPolynomials(QQ, 4)
        sage: k.poly_gens()
        (z_0, z_1, z_2, z_3)

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k.poly_gens()
        z_*

        >>> k = KeyPolynomials(QQ, Integer(4))
        >>> k.poly_gens()
        (z_0, z_1, z_2, z_3)

  polynomial_ring()

    Return the polynomial ring associated to `self`.

    EXAMPLES:

    Sage

        sage: k = KeyPolynomials(QQ)
        sage: k.polynomial_ring()
        Infinite polynomial ring in z over Rational Field

        sage: k = KeyPolynomials(QQ, 4)
        sage: k.polynomial_ring()
        Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field

    Python

        >>> from sage.all import *
        >>> k = KeyPolynomials(QQ)
        >>> k.polynomial_ring()
        Infinite polynomial ring in z over Rational Field

        >>> k = KeyPolynomials(QQ, Integer(4))
        >>> k.polynomial_ring()
        Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field

sage.combinat.key_polynomial.divided_difference(f, i)

  Apply the `i`-th divided difference operator to the polynomial `f`.

  EXAMPLES:

  Sage

      sage: from sage.combinat.key_polynomial import divided_difference
      sage: k = KeyPolynomials(QQ)
      sage: z = k.poly_gens()
      sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3]
      sage: divided_difference(f, 3)
      z_3^2*z_1 + z_3*z_2*z_1 + z_2^2*z_1

      sage: k = KeyPolynomials(QQ, 4)
      sage: z = k.poly_gens()
      sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3]
      sage: divided_difference(f, 3)
      z_1*z_2^2 + z_1*z_2*z_3 + z_1*z_3^2

      sage: k = KeyPolynomials(QQ)
      sage: R = k.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field
      sage: z = R.gen()
      sage: divided_difference(z[1]*z[2]^3, 2)
      -z_2^2*z_1 - z_2*z_1^2
      sage: divided_difference(z[1]*z[2]*z[3], 3)
      0
      sage: divided_difference(z[1]*z[2]*z[3], 4)
      z_2*z_1
      sage: divided_difference(z[1]*z[2]*z[4], 4)
      -z_2*z_1

      sage: k = KeyPolynomials(QQ, 5)
      sage: z = k.polynomial_ring().gens()
      sage: divided_difference(z[1]*z[2]^3, 2)
      -z_1^2*z_2 - z_1*z_2^2
      sage: divided_difference(z[1]*z[2]*z[3], 3)
      0
      sage: divided_difference(z[1]*z[2]*z[3], 4)
      z_1*z_2
      sage: divided_difference(z[1]*z[2]*z[4], 4)
      -z_1*z_2

  Python

      >>> from sage.all import *
      >>> from sage.combinat.key_polynomial import divided_difference
      >>> k = KeyPolynomials(QQ)
      >>> z = k.poly_gens()
      >>> f = z[Integer(1)]*z[Integer(2)]**Integer(3) + z[Integer(1)]*z[Integer(2)]*z[Integer(3)]
      >>> divided_difference(f, Integer(3))
      z_3^2*z_1 + z_3*z_2*z_1 + z_2^2*z_1

      >>> k = KeyPolynomials(QQ, Integer(4))
      >>> z = k.poly_gens()
      >>> f = z[Integer(1)]*z[Integer(2)]**Integer(3) + z[Integer(1)]*z[Integer(2)]*z[Integer(3)]
      >>> divided_difference(f, Integer(3))
      z_1*z_2^2 + z_1*z_2*z_3 + z_1*z_3^2

      >>> k = KeyPolynomials(QQ)
      >>> R = k.polynomial_ring(); R
      Infinite polynomial ring in z over Rational Field
      >>> z = R.gen()
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]**Integer(3), Integer(2))
      -z_2^2*z_1 - z_2*z_1^2
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(3)], Integer(3))
      0
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(3)], Integer(4))
      z_2*z_1
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(4)], Integer(4))
      -z_2*z_1

      >>> k = KeyPolynomials(QQ, Integer(5))
      >>> z = k.polynomial_ring().gens()
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]**Integer(3), Integer(2))
      -z_1^2*z_2 - z_1*z_2^2
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(3)], Integer(3))
      0
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(3)], Integer(4))
      z_1*z_2
      >>> divided_difference(z[Integer(1)]*z[Integer(2)]*z[Integer(4)], Integer(4))
      -z_1*z_2

sage.combinat.key_polynomial.isobaric_divided_difference(f, w)

  Apply the isobaric divided difference operator \(\pi_w\) to the polynomial \(f\).

  `w` may be either a single index or a list of indices of simple transpositions.

  Warning

  The simple transpositions should be applied from left to right.

  EXAMPLES:

  Sage

      sage: from sage.combinat.key_polynomial import isobaric_divided_difference as idd
      sage: R.<z> = InfinitePolynomialRing(GF(3))
      sage: idd(z[1]^4*z[2]^2*z[4], 4)
      0

      sage: idd(z[1]^4*z[2]^2*z[3]*z[4], 3)
      z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [3, 4])
      z_4^2*z_3*z_2*z_1^4 + z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [4, 3])
      z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      sage: idd(z[1]^2*z[2], [3, 2])
      z_3*z_2^2 + z_3*z_2*z_1 + z_3*z_1^2 + z_2^2*z_1 + z_2*z_1^2

  Python

      >>> from sage.all import *
      >>> from sage.combinat.key_polynomial import isobaric_divided_difference as idd
      >>> R = InfinitePolynomialRing(GF(Integer(3)), names=('z',)); (z,) = R._first_ngens(1)
      >>> idd(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(4)], Integer(4))
      0

      >>> idd(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], Integer(3))
      z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      >>> idd(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], [Integer(3), Integer(4)])
      z_4^2*z_3*z_2*z_1^4 + z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      >>> idd(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], [Integer(4), Integer(3)])
      z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4

      >>> idd(z[Integer(1)]**Integer(2)*z[Integer(2)], [Integer(3), Integer(2)])
      z_3*z_2^2 + z_3*z_2*z_1 + z_3*z_1^2 + z_2^2*z_1 + z_2*z_1^2

sage.combinat.key_polynomial.isobaric_divided_difference_bar(f, w)

  Apply the isobaric divided difference operator \(\bar{\pi}_w\) to the polynomial \(f\).

  This map is defined by \(\bar{\pi}_i := \pi_i - 1\).

  `w` may be either a single index or a list of indices of simple transpositions.

  Warning

  The simple transpositions should be applied from left to right.

  EXAMPLES:

  Sage

      sage: from sage.combinat.key_polynomial import isobaric_divided_difference_bar as iddb
      sage: R.<z> = InfinitePolynomialRing(GF(3))
      sage: iddb(z[1]^4*z[2]^2*z[4], 4)
      -z_4*z_2^2*z_1^4

      sage: iddb(z[1]^4*z[2]^2*z[3]*z[4], 3)
      z_4*z_3^2*z_2*z_1^4

      sage: iddb(z[1]^4*z[2]^2*z[3]*z[4], [3, 4])
      z_4^2*z_3*z_2*z_1^4

      sage: iddb(z[1]^4*z[2]^2*z[3]*z[4], [4, 3])
      0

      sage: iddb(z[1]^2*z[2], [3, 2])
      z_3*z_2^2 + z_3*z_2*z_1

  Python

      >>> from sage.all import *
      >>> from sage.combinat.key_polynomial import isobaric_divided_difference_bar as iddb
      >>> R = InfinitePolynomialRing(GF(Integer(3)), names=('z',)); (z,) = R._first_ngens(1)
      >>> iddb(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(4)], Integer(4))
      -z_4*z_2^2*z_1^4

      >>> iddb(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], Integer(3))
      z_4*z_3^2*z_2*z_1^4

      >>> iddb(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], [Integer(3), Integer(4)])
      z_4^2*z_3*z_2*z_1^4

      >>> iddb(z[Integer(1)]**Integer(4)*z[Integer(2)]**Integer(2)*z[Integer(3)]*z[Integer(4)], [Integer(4), Integer(3)])
      0

      >>> iddb(z[Integer(1)]**Integer(2)*z[Integer(2)], [Integer(3), Integer(2)])
      z_3*z_2^2 + z_3*z_2*z_1

sage.combinat.key_polynomial.sorting_word(alpha)

  Get a reduced word for the permutation which sorts `alpha` into a partition.

  The result is a list `l = [i0, i1, i2, ...]` where each `ij` is a positive integer such that it applies the simple transposition \((i_j, i_j+1)\). The transpositions are applied starting with `i0`, then `i1` is applied, followed by `i2`, and so on. See `sage.combinat.permutation.Permutation.reduced_words()` for the convention used.

  EXAMPLES:

  Sage

      sage: IV = IntegerVectors()
      sage: from sage.combinat.key_polynomial import sorting_word
      sage: list(sorting_word(IV([2,3,2]))[0])
      [1]
      sage: sorting_word(IV([2,3,2]))[1]
      [3, 2, 2]
      sage: list(sorting_word(IV([5,6,7]))[0])
      [1, 2, 1]
      sage: list(sorting_word(IV([0,3,2]))[0])
      [2, 1]
      sage: list(sorting_word(IV([0,3,0,2]))[0])
      [2, 3, 1]
      sage: list(sorting_word(IV([3,2,1]))[0])
      []
      sage: list(sorting_word(IV([2,3,3]))[0])
      [2, 1]

  Python

      >>> from sage.all import *
      >>> IV = IntegerVectors()
      >>> from sage.combinat.key_polynomial import sorting_word
      >>> list(sorting_word(IV([Integer(2),Integer(3),Integer(2)]))[Integer(0)])
      [1]
      >>> sorting_word(IV([Integer(2),Integer(3),Integer(2)]))[Integer(1)]
      [3, 2, 2]
      >>> list(sorting_word(IV([Integer(5),Integer(6),Integer(7)]))[Integer(0)])
      [1, 2, 1]
      >>> list(sorting_word(IV([Integer(0),Integer(3),Integer(2)]))[Integer(0)])
      [2, 1]
      >>> list(sorting_word(IV([Integer(0),Integer(3),Integer(0),Integer(2)]))[Integer(0)])
      [2, 3, 1]
      >>> list(sorting_word(IV([Integer(3),Integer(2),Integer(1)]))[Integer(0)])
      []
      >>> list(sorting_word(IV([Integer(2),Integer(3),Integer(3)]))[Integer(0)])
      [2, 1]