Commits (7)
......@@ -320,8 +320,10 @@ that our form actually represents the Euler class appropriately.
#******************************************************************************
from sage.structure.unique_representation import UniqueRepresentation
from sage.misc.cachefunc import cached_method
from sage.structure.sage_object import SageObject
from sage.symbolic.ring import SR
from sage.rings.rational_field import QQ
################################################################################
## Separate functions
......@@ -473,7 +475,7 @@ class CharacteristicClass(UniqueRepresentation, SageObject):
self._coeff_list = self._get_coeff_list()
self._init_derived()
def _get_coeff_list(self):
def _get_coeff_list(self, distinct_real=True):
r"""
Return the list of coefficients of the Taylor expansion at zero of the
function.
......@@ -491,7 +493,7 @@ class CharacteristicClass(UniqueRepresentation, SageObject):
def_var = self._func.default_variable()
# Use a complex variable without affecting the old one:
new_var = SR.symbol('x_char_class_', domain='complex')
if self._vbundle._field_type == 'real':
if self._vbundle._field_type == 'real' and distinct_real:
if self._class_type == 'additive':
func = self._func.subs({def_var: new_var ** 2}) / 2
elif self._class_type == 'multiplicative':
......@@ -508,6 +510,9 @@ class CharacteristicClass(UniqueRepresentation, SageObject):
else:
func = self._func.subs({def_var: new_var})
if self._vbundle._field_type == 'real' and not distinct_real:
pow_range = pow_range // 2
return func.taylor(new_var, 0, pow_range).coefficients(sparse=False)
def _init_derived(self):
......@@ -623,6 +628,106 @@ class CharacteristicClass(UniqueRepresentation, SageObject):
"""
return self._func
@cached_method
def sequence(self, ring=QQ):
r"""
Return the multiplicative/additive sequence (depending on the class
type of ``self``) of ``self.function`` in terms of elementary symmetric
functions `e_i`.
If `f(x)` is the function with respect to ``self`` then its
multiplicative sequence is given by
.. MATH::
\Pi_{i = 1}^n f(x_i) = \sum^n_{i=0} c_i \, e_i(x_1, \ldots, x_n)
whereas its additive sequence is given by
.. MATH::
\sum_{i = 1}^n f(x_i) = \sum^n_{i=0} c_i \, e_i(x_1, \ldots, x_n).
Here, `e_i` denotes the `i`-th elementary symmetric function.
INPUT:
- ``ring`` -- (default: ``QQ``) the base ring of the symmetric
function ring; in most cases, one can assume ``QQ`` which is
supposed to work faster, if it doesn't work, try ``SR`` instead.
OUTPUT:
- a symmetric function in the elementary symmetric basis represented
by an instance of
:class:`~sage.combinat.sf.elementary.SymmetricFunctionAlgebra_elementary`
EXAMPLES:
Consider the multiplicative sequence of the `\hat{A}` class::
sage: M = Manifold(8, 'M')
sage: A = M.tangent_bundle().characteristic_class('AHat')
sage: A.sequence()
e[] - 1/24*e[1] + 7/5760*e[1, 1] - 1/1440*e[2]
This is an element of the symmetric functions over the rational field::
sage: A.sequence().parent()
Symmetric Functions over Rational Field in the elementary basis
To get the sequence as an element of usual polynomial ring, we can do
the following::
sage: P = PolynomialRing(QQ, 'e', 3)
sage: poly = P(sum(c * prod(P.gens()[i] for i in p)
....: for p, c in A.sequence()))
sage: poly
7/5760*e1^2 - 1/24*e1 - 1/1440*e2 + 1
Get an additive sequence::
sage: E = M.vector_bundle(2, 'E', field='complex')
sage: ch = E.characteristic_class('ChernChar')
sage: ch.sequence()
2*e[] + e[1] + 1/2*e[1, 1] + 1/6*e[1, 1, 1] + 1/24*e[1, 1, 1, 1]
- e[2] - 1/2*e[2, 1] - 1/6*e[2, 1, 1] + 1/12*e[2, 2] + 1/2*e[3]
+ 1/6*e[3, 1] - 1/6*e[4]
.. SEEALSO::
See :class:`~sage.combinat.sf.elementary.SymmetricFunctionAlgebra_elementary`
for detailed information about elementary symmetric functions.
"""
if self._class_type == 'Pfaffian':
return NotImplementedError('this functionality is not supported '
'for characteristic classes of '
'Pfaffian type')
from sage.combinat.sf.sf import SymmetricFunctions
from sage.misc.misc_c import prod
Sym = SymmetricFunctions(ring)
coeff = self._get_coeff_list(distinct_real=False)
from sage.combinat.partition import Partitions
m = Sym.m()
if self._class_type == 'multiplicative':
# Get the multiplicative sequence in the monomial basis:
mon_pol = m._from_dict({p: prod(ring(coeff[i]) for i in p)
for k in range(len(coeff))
for p in Partitions(k)})
elif self._class_type == 'additive':
# Express the additive sequence in the monomial basis, the 0th
# order term must be treated separately:
m_dict = {Partitions(0)([]): self._vbundle._rank * ring(coeff[0])}
m_dict.update({Partitions(k)([k]): ring(coeff[k]) for k in range(1, len(coeff))})
mon_pol = m._from_dict(m_dict)
# Convert to elementary symmetric polynomials:
return Sym.e()(mon_pol)
def get_form(self, connection, cmatrices=None):
r"""
Return the form representing ``self`` with respect to the given
......