Bases: sage.combinat.sf.multiplicative.SymmetricFunctionAlgebra_multiplicative
The Witt symmetric function basis (or Witt basis, to be short).
The Witt basis of the ring of symmetric functions is
denoted by in [HazWitt1], section 9.63, and by
in [DoranIV1996]. We will denote this basis by
. It is a multiplicative basis (meaning that
and that every partition
satisfies
,
where
means
for every nonnegative integer
).
This basis can be defined in various ways. Probably the most well-known one is using the equation
where is a formal variable and
are the complete
homogeneous symmetric functions, extended to
by
.
This equation allows one to uniquely determine the functions
by recursion; one consequently extends the
definition to all
by requiring multiplicativity.
A way to rewrite the above equation without power series is:
for all nonnegative integers , where
means
that
is a partition of
.
A similar equation (which is easily seen to be equivalent to the former) is
with the sum running only over strict partitions of
this time. This equation can also be used to recursively
define the
. Furthermore, every positive integer
satisfies
and this can be used to define the recursively over any
ring which is torsion-free as a
-module. While these
equations all yield easy formulas for classical bases of the
ring of symmetric functions in terms of the Witt symmetric
functions, it seems difficult to obtain explicit formulas in
the other direction.
The Witt symmetric functions owe their name to the fact that the ring of symmetric functions can be viewed as the coordinate ring of the group scheme of Witt vectors, and the Witt symmetric functions are the functions that send a Witt vector to its components (whereas the powersum symmetric functions send a Witt vector to its ghost components). Details can be found in [HazWitt1] or section 3.2 of [BorWi2004].
INPUT:
REFERENCES:
[HazWitt1] | (1, 2) Michiel Hazewinkel. Witt vectors. Part 1. Arxiv 0804.3888v1 |
[DoranIV1996] | William F. Doran IV. A Proof of Reutenauer’s `-q_{(n)}` Conjecture. Journal of combinatorial theory, Series A 74, pp. 342-344 (1996), article no. 0056. doi:10.1006/jcta.1996.0056 |
[BorWi2004] | James Borger, Ben Wieland. Plethystic algebra. Arxiv math/0407227v1 |
EXAMPLES:
Here are the first few Witt symmetric functions, in various bases:
sage: Sym = SymmetricFunctions(QQ)
sage: w = Sym.w()
sage: e = Sym.e()
sage: h = Sym.h()
sage: p = Sym.p()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p(w([1]))
p[1]
sage: m(w([1]))
m[1]
sage: e(w([1]))
e[1]
sage: h(w([1]))
h[1]
sage: s(w([1]))
s[1]
sage: p(w([2]))
-1/2*p[1, 1] + 1/2*p[2]
sage: m(w([2]))
-m[1, 1]
sage: e(w([2]))
-e[2]
sage: h(w([2]))
-h[1, 1] + h[2]
sage: s(w([2]))
-s[1, 1]
sage: p(w([3]))
-1/3*p[1, 1, 1] + 1/3*p[3]
sage: m(w([3]))
-2*m[1, 1, 1] - m[2, 1]
sage: e(w([3]))
-e[2, 1] + e[3]
sage: h(w([3]))
-h[2, 1] + h[3]
sage: s(w([3]))
-s[2, 1]
sage: Sym = SymmetricFunctions(ZZ)
sage: w = Sym.w()
sage: e = Sym.e()
sage: h = Sym.h()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p = Sym.p()
sage: m(w([4]))
-9*m[1, 1, 1, 1] - 4*m[2, 1, 1] - 2*m[2, 2] - m[3, 1]
sage: e(w([4]))
-e[2, 1, 1] + e[3, 1] - e[4]
sage: h(w([4]))
-h[1, 1, 1, 1] + 2*h[2, 1, 1] - h[2, 2] - h[3, 1] + h[4]
sage: s(w([4]))
-s[1, 1, 1, 1] - s[2, 1, 1] - s[2, 2] - s[3, 1]
Some examples of conversions the other way:
sage: w(h[3])
w[1, 1, 1] + w[2, 1] + w[3]
sage: w(e[3])
-w[2, 1] + w[3]
sage: w(m[2,1])
2*w[2, 1] - 3*w[3]
sage: w(p[3])
w[1, 1, 1] + 3*w[3]
Antipodes:
sage: w([1]).antipode()
-w[1]
sage: w([2]).antipode()
-w[1, 1] - w[2]
This holds for all odd and is easily proven by induction:
sage: all( w([i]).antipode() == -w([i]) for i in range(1, 10, 2) )
True
The Witt basis does not allow for simple expressions for
comultiplication and antipode in general (this is related to the
fact that the sum of two Witt vectors isn’t easily described in
terms of the components). Therefore, most computations with Witt
symmetric functions, as well as conversions and coercions, pass
through the complete homogeneous symmetric functions by default.
However, one can also use the elementary symmetric functions
instead, or (if the base ring is a -algebra) the powersum
symmetric functions. This is what the optional keyword variables
coerce_e, coerce_h and coerce_p are for. These
variables do not affect the results of the (non-underscored)
methods of self, but they affect the speed of the computations
(the more of these variables are set to True, the
faster these are) and on the size of the cache (the more of
these variables are set to True, the bigger the cache). Let us
check that the results are the same no matter to what the
variables are set:
sage: Sym = SymmetricFunctions(QQ)
sage: p = Sym.p()
sage: wh = Sym.w()
sage: we = Sym.w(coerce_h=False, coerce_e=True)
sage: wp = Sym.w(coerce_h=False, coerce_p=True)
sage: all( p(wh(lam)) == p(we(lam)) == p(wp(lam)) for lam in Partitions(4) )
True
sage: all ( wh(p(lam)).monomial_coefficients()
....: == we(p(lam)).monomial_coefficients()
....: == wp(p(lam)).monomial_coefficients() for lam in Partitions(4) )
True
TESTS:
Let us check that all the above computations work with a non-default setting as well:
sage: Sym = SymmetricFunctions(QQ)
sage: w = Sym.w(coerce_h=False, coerce_p=True)
sage: e = Sym.e()
sage: h = Sym.h()
sage: p = Sym.p()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p(w([1]))
p[1]
sage: m(w([1]))
m[1]
sage: e(w([1]))
e[1]
sage: h(w([1]))
h[1]
sage: s(w([1]))
s[1]
sage: p(w([2]))
-1/2*p[1, 1] + 1/2*p[2]
sage: m(w([2]))
-m[1, 1]
sage: e(w([2]))
-e[2]
sage: h(w([2]))
-h[1, 1] + h[2]
sage: s(w([2]))
-s[1, 1]
sage: p(w([3]))
-1/3*p[1, 1, 1] + 1/3*p[3]
sage: m(w([3]))
-2*m[1, 1, 1] - m[2, 1]
sage: e(w([3]))
-e[2, 1] + e[3]
sage: h(w([3]))
-h[2, 1] + h[3]
sage: s(w([3]))
-s[2, 1]
sage: Sym = SymmetricFunctions(ZZ)
sage: w = Sym.w()
sage: e = Sym.e()
sage: h = Sym.h()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p = Sym.p()
sage: m(w([4]))
-9*m[1, 1, 1, 1] - 4*m[2, 1, 1] - 2*m[2, 2] - m[3, 1]
sage: e(w([4]))
-e[2, 1, 1] + e[3, 1] - e[4]
sage: h(w([4]))
-h[1, 1, 1, 1] + 2*h[2, 1, 1] - h[2, 2] - h[3, 1] + h[4]
sage: s(w([4]))
-s[1, 1, 1, 1] - s[2, 1, 1] - s[2, 2] - s[3, 1]
sage: w(h[3])
w[1, 1, 1] + w[2, 1] + w[3]
sage: w(e[3])
-w[2, 1] + w[3]
sage: w(m[2,1])
2*w[2, 1] - 3*w[3]
sage: w(p[3])
w[1, 1, 1] + 3*w[3]
sage: w([1]).antipode()
-w[1]
sage: w([2]).antipode()
-w[1, 1] - w[2]
sage: all( w([i]).antipode() == -w([i]) for i in range(1, 10, 2) )
True
Another non-default setting:
sage: Sym = SymmetricFunctions(QQ)
sage: w = Sym.w(coerce_h=False, coerce_e=True)
sage: e = Sym.e()
sage: h = Sym.h()
sage: p = Sym.p()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p(w([1]))
p[1]
sage: m(w([1]))
m[1]
sage: e(w([1]))
e[1]
sage: h(w([1]))
h[1]
sage: s(w([1]))
s[1]
sage: p(w([2]))
-1/2*p[1, 1] + 1/2*p[2]
sage: m(w([2]))
-m[1, 1]
sage: e(w([2]))
-e[2]
sage: h(w([2]))
-h[1, 1] + h[2]
sage: s(w([2]))
-s[1, 1]
sage: p(w([3]))
-1/3*p[1, 1, 1] + 1/3*p[3]
sage: m(w([3]))
-2*m[1, 1, 1] - m[2, 1]
sage: e(w([3]))
-e[2, 1] + e[3]
sage: h(w([3]))
-h[2, 1] + h[3]
sage: s(w([3]))
-s[2, 1]
sage: Sym = SymmetricFunctions(ZZ)
sage: w = Sym.w()
sage: e = Sym.e()
sage: h = Sym.h()
sage: s = Sym.s()
sage: m = Sym.m()
sage: p = Sym.p()
sage: m(w([4]))
-9*m[1, 1, 1, 1] - 4*m[2, 1, 1] - 2*m[2, 2] - m[3, 1]
sage: e(w([4]))
-e[2, 1, 1] + e[3, 1] - e[4]
sage: h(w([4]))
-h[1, 1, 1, 1] + 2*h[2, 1, 1] - h[2, 2] - h[3, 1] + h[4]
sage: s(w([4]))
-s[1, 1, 1, 1] - s[2, 1, 1] - s[2, 2] - s[3, 1]
sage: w(h[3])
w[1, 1, 1] + w[2, 1] + w[3]
sage: w(e[3])
-w[2, 1] + w[3]
sage: w(m[2,1])
2*w[2, 1] - 3*w[3]
sage: w(p[3])
w[1, 1, 1] + 3*w[3]
sage: w([1]).antipode()
-w[1]
sage: w([2]).antipode()
-w[1, 1] - w[2]
sage: all( w([i]).antipode() == -w([i]) for i in range(1, 10, 2) )
....: #this holds for all odd i and is easily proven by induction
True
Return the coproduct of the element elt.
INPUT:
OUTPUT:
EXAMPLES:
sage: w = SymmetricFunctions(QQ).w()
sage: w[2].coproduct()
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w.coproduct(w[2])
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w[2,1].coproduct()
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
sage: w.coproduct(w[2,1])
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
TESTS:
The same, but with other settings:
sage: w = SymmetricFunctions(QQ).w(coerce_h=False, coerce_e=True)
sage: w[2].coproduct()
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w.coproduct(w[2])
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w[2,1].coproduct()
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
sage: w.coproduct(w[2,1])
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
sage: w = SymmetricFunctions(QQ).w(coerce_h=False, coerce_p=True)
sage: w[2].coproduct()
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w.coproduct(w[2])
w[] # w[2] - w[1] # w[1] + w[2] # w[]
sage: w[2,1].coproduct()
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
sage: w.coproduct(w[2,1])
w[] # w[2, 1] - w[1] # w[1, 1] + w[1] # w[2] - w[1, 1] # w[1] + w[2] # w[1] + w[2, 1] # w[]
Return an element u of another basis of the ring of symmetric functions, expanded in the Witt basis self. The result is the same as self(u), but the from_other_uncached method does not precompute a cache with transition matrices. Thus, from_other_uncached is faster when u is sparse.
INPUT:
OUTPUT:
EXAMPLES:
sage: Sym = SymmetricFunctions(QQ)
sage: p = Sym.p()
sage: w = Sym.w()
sage: a = p([3,2]) - p([4,1]) + 27 * p([3])
sage: w.from_other_uncached(a) == w(a)
True
Here’s a verification of an obvious fact that would take long with regular coercion:
sage: fouc = w.from_other_uncached
sage: fouc(p([15]))
w[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + 3*w[3, 3, 3, 3, 3] + 5*w[5, 5, 5] + 15*w[15]
sage: fouc(p([15])) * fouc(p([14])) == fouc(p([15, 14]))
True
Other bases:
sage: e = Sym.e()
sage: h = Sym.h()
sage: s = Sym.s()
sage: all( fouc(e(lam)) == w(e(lam)) for lam in Partitions(5) )
True
sage: all( fouc(h(lam)) == w(h(lam)) for lam in Partitions(5) )
True
sage: all( fouc(p(lam)) == w(p(lam)) for lam in Partitions(5) )
True
sage: all( fouc(s(lam)) == w(s(lam)) for lam in Partitions(5) )
True
Return the image of the symmetric function self under the
-th Verschiebung operator.
The -th Verschiebung operator
is defined to be
the unique algebra endomorphism
of the ring of symmetric
functions that satisfies
for every positive
integer
divisible by
, and satisfies
for
every positive integer
not divisible by
. This operator
is a Hopf algebra endomorphism. For every
nonnegative integer
with
, it satisfies
(where is the complete homogeneous basis,
is the
powersum basis,
is the elementary basis, and
is the
Witt basis). For every nonnegative integer
with
,
it satisfes
The -th Verschiebung operator is also called the
-th
Verschiebung endomorphism. Its name derives from the Verschiebung
(German for “shift”) endomorphism of the Witt vectors.
The -th Verschiebung operator is adjoint to the
-th
Frobenius operator (see frobenius() for its definition)
with respect to the Hall scalar product (scalar()).
The action of the -th Verschiebung operator on the Schur basis
can also be computed explicitly. The following (probably clumsier
than necessary) description can be obtained by solving exercise
7.61 in Stanley’s [STA].
Let be a partition. Let
be a positive integer. If
the
-core of
is nonempty, then
. Otherwise, the following method
computes
: Write the partition
in the form
for some
nonnegative integer
. (If
does not divide the length of
, then this is achieved by adding trailing zeroes to
.) Set
for every
. Then,
is a strictly decreasing
sequence of nonnegative integers. Stably sort the list
in order of (weakly) increasing remainder of
modulo
. Let
be the sign of the
permutation that is used for this sorting. Let
be the sign
of the permutation that is used to stably sort the list
in order of (weakly) increasing remainder of
modulo
. (Notice that
.)
Then,
, where
is the
-quotient of
.
INPUT:
OUTPUT:
The result of applying the -th Verschiebung operator (on the ring of
symmetric functions) to self.
EXAMPLES:
sage: Sym = SymmetricFunctions(ZZ)
sage: w = Sym.w()
sage: w[3].verschiebung(2)
0
sage: w[4].verschiebung(4)
w[1]
TESTS:
Let us check that this method on the Witt basis gives the same result as the implementation in sfa.py on the complete homogeneous basis:
sage: Sym = SymmetricFunctions(QQ)
sage: w = Sym.w(); h = Sym.h()
sage: all( w(h(lam)).verschiebung(3) == w(h(lam).verschiebung(3))
....: for lam in Partitions(6) )
True
sage: all( h(w(lam)).verschiebung(2) == h(w(lam).verschiebung(2))
....: for lam in Partitions(4) )
True