passagemath-symbolics 10.8.1a1__cp311-cp311-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +182 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-311-darwin.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-311-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-311-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-311-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-311-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
|
@@ -0,0 +1,1840 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
# sage.doctest: needs sage.combinat
|
|
3
|
+
r"""
|
|
4
|
+
Characteristic cohomology classes
|
|
5
|
+
|
|
6
|
+
A *characteristic class* `\kappa` is a natural transformation that
|
|
7
|
+
associates with each vector bundle `E \to M` a cohomology class
|
|
8
|
+
`\kappa(E) \in H^*(M;R)` such that for any continuous map `f\colon N \to M`
|
|
9
|
+
from another topological manifold `N`, the *naturality condition* is
|
|
10
|
+
satisfied:
|
|
11
|
+
|
|
12
|
+
.. MATH::
|
|
13
|
+
|
|
14
|
+
f^*\kappa(E) = \kappa(f^* E) \in H^*(N;R)
|
|
15
|
+
|
|
16
|
+
The cohomology class `\kappa(E)` is called *characteristic cohomology class*.
|
|
17
|
+
Roughly speaking, characteristic cohomology classes measure the non-triviality
|
|
18
|
+
of vector bundles.
|
|
19
|
+
|
|
20
|
+
One way to obtain and compute characteristic classes in the de Rham cohomology
|
|
21
|
+
with coefficients in the ring `\CC` is via the so-called *Chern-Weil theory*
|
|
22
|
+
using the curvature of a differentiable vector bundle.
|
|
23
|
+
|
|
24
|
+
For that let `\nabla` be a connection on `E`, `e` a local frame on
|
|
25
|
+
`E` and `\Omega` be the corresponding curvature matrix
|
|
26
|
+
(see: :meth:`~sage.manifolds.differentiable.bundle_connection.BundleConnection.curvature_form`).
|
|
27
|
+
|
|
28
|
+
Namely, if `P: \mathrm{Mat}_{n \times n}(\CC) \to \CC` is an invariant
|
|
29
|
+
polynomial, the object
|
|
30
|
+
|
|
31
|
+
.. MATH::
|
|
32
|
+
|
|
33
|
+
\left[ P \left( \Omega \right) \right] \in H^{2*}_{\mathrm{dR}}(M, \CC)
|
|
34
|
+
|
|
35
|
+
is well-defined, independent of the choice of `\nabla` (the proof can be
|
|
36
|
+
found in [Roe1988]_ pp. 31) and fulfills the naturality condition.
|
|
37
|
+
This is the foundation of the Chern-Weil theory and the following definitions.
|
|
38
|
+
|
|
39
|
+
.. NOTE::
|
|
40
|
+
|
|
41
|
+
This documentation is rich of examples, but sparse in explanations. Please
|
|
42
|
+
consult the references for more details.
|
|
43
|
+
|
|
44
|
+
AUTHORS:
|
|
45
|
+
|
|
46
|
+
- Michael Jung (2019) : initial version
|
|
47
|
+
- Michael Jung (2021) : new algorithm; complete refactoring
|
|
48
|
+
|
|
49
|
+
REFERENCES:
|
|
50
|
+
|
|
51
|
+
- [Mil1974]_
|
|
52
|
+
- [Roe1988]_
|
|
53
|
+
|
|
54
|
+
Contents
|
|
55
|
+
--------
|
|
56
|
+
|
|
57
|
+
We consider the following three types of classes:
|
|
58
|
+
|
|
59
|
+
- :ref:`additive`
|
|
60
|
+
- :ref:`multiplicative`
|
|
61
|
+
- :ref:`Pfaffian`
|
|
62
|
+
|
|
63
|
+
.. _additive:
|
|
64
|
+
|
|
65
|
+
Additive Classes
|
|
66
|
+
----------------
|
|
67
|
+
|
|
68
|
+
In the **complex** case, let `f` be a holomorphic function around zero. Then
|
|
69
|
+
we call
|
|
70
|
+
|
|
71
|
+
.. MATH::
|
|
72
|
+
|
|
73
|
+
\left[\mathrm{tr}\left( f\left( \frac{\Omega}{2 \pi i} \right)
|
|
74
|
+
\right)\right] \in H^{2*}_{\mathrm{dR}}(M, \CC)
|
|
75
|
+
|
|
76
|
+
the *additive characteristic class associated to* `f` of the complex vector
|
|
77
|
+
bundle `E`.
|
|
78
|
+
|
|
79
|
+
Important and predefined additive classes are:
|
|
80
|
+
|
|
81
|
+
- *Chern Character* with `f(x) = \exp(x)`
|
|
82
|
+
|
|
83
|
+
In the **real** case, let `g` be a holomorphic function around zero with
|
|
84
|
+
`g(0)=0`. Then we call
|
|
85
|
+
|
|
86
|
+
.. MATH::
|
|
87
|
+
|
|
88
|
+
\left[\mathrm{tr}\left( \frac{1}{2} g\left( -\frac{\Omega^2}{4 \pi^2}
|
|
89
|
+
\right) \right)\right] \in H^{4*}_{\mathrm{dR}}(M, \CC)
|
|
90
|
+
|
|
91
|
+
the *additive characteristic class associated to* `g` of the **real** vector
|
|
92
|
+
bundle `E`.
|
|
93
|
+
|
|
94
|
+
EXAMPLES:
|
|
95
|
+
|
|
96
|
+
Consider the **Chern character** on some 2-dimensional spacetime::
|
|
97
|
+
|
|
98
|
+
sage: M = Manifold(2, 'M', structure='Lorentzian')
|
|
99
|
+
sage: X.<t,x> = M.chart()
|
|
100
|
+
sage: E = M.vector_bundle(1, 'E', field='complex'); E
|
|
101
|
+
Differentiable complex vector bundle E -> M of rank 1 over the base space
|
|
102
|
+
2-dimensional Lorentzian manifold M
|
|
103
|
+
sage: e = E.local_frame('e')
|
|
104
|
+
|
|
105
|
+
Let us define the connection `\nabla^E` in terms of an electro-magnetic
|
|
106
|
+
potential `A(t)`::
|
|
107
|
+
|
|
108
|
+
sage: nab = E.bundle_connection('nabla^E', latex_name=r'\nabla^E')
|
|
109
|
+
sage: omega = M.one_form(name='omega')
|
|
110
|
+
sage: A = function('A')
|
|
111
|
+
sage: nab.set_connection_form(0, 0)[1] = I*A(t)
|
|
112
|
+
sage: nab[0, 0].display()
|
|
113
|
+
connection (0,0) of bundle connection nabla^E w.r.t. Local frame
|
|
114
|
+
(E|_M, (e_0)) = I*A(t) dx
|
|
115
|
+
sage: nab.set_immutable()
|
|
116
|
+
|
|
117
|
+
The Chern character is then given by::
|
|
118
|
+
|
|
119
|
+
sage: ch = E.characteristic_cohomology_class('ChernChar'); ch
|
|
120
|
+
Characteristic cohomology class ch(E) of the Differentiable complex vector
|
|
121
|
+
bundle E -> M of rank 1 over the base space 2-dimensional Lorentzian
|
|
122
|
+
manifold M
|
|
123
|
+
|
|
124
|
+
The corresponding characteristic form w.r.t. the bundle connection can be
|
|
125
|
+
obtained via :meth:`get_form`::
|
|
126
|
+
|
|
127
|
+
sage: ch_form = ch.get_form(nab); ch_form.display_expansion()
|
|
128
|
+
ch(E, nabla^E) = 1 + 1/2*d(A)/dt/pi dt∧dx
|
|
129
|
+
|
|
130
|
+
.. _multiplicative:
|
|
131
|
+
|
|
132
|
+
Multiplicative Classes
|
|
133
|
+
----------------------
|
|
134
|
+
|
|
135
|
+
In the **complex** case, let `f` be a holomorphic function around zero.
|
|
136
|
+
Then we call
|
|
137
|
+
|
|
138
|
+
.. MATH::
|
|
139
|
+
|
|
140
|
+
\left[\det\left( f\left( \frac{\Omega}{2 \pi i} \right)
|
|
141
|
+
\right)\right] \in H^{2*}_{\mathrm{dR}}(M, \CC)
|
|
142
|
+
|
|
143
|
+
the *multiplicative characteristic class associated to* `f` of the complex
|
|
144
|
+
vector bundle `E`.
|
|
145
|
+
|
|
146
|
+
Important and predefined multiplicative classes on complex vector bundles are:
|
|
147
|
+
|
|
148
|
+
- *Chern class* with `f(x) = 1+x`
|
|
149
|
+
- *Todd class* with `f(x) = \frac{x}{1-\exp(-x)}`
|
|
150
|
+
|
|
151
|
+
In the **real** case, let `g` be a holomorphic function around zero with
|
|
152
|
+
`g(0)=1`. Then we call
|
|
153
|
+
|
|
154
|
+
.. MATH::
|
|
155
|
+
|
|
156
|
+
\left[\det\left( \sqrt{ g \left( -\frac{\Omega^2}{4 \pi^2} \right) } \right)
|
|
157
|
+
\right] \in H^{4*}_{\mathrm{dR}}(M, \CC)
|
|
158
|
+
|
|
159
|
+
the *multiplicative characteristic class associated to* `g` on the **real**
|
|
160
|
+
vector bundle `E`.
|
|
161
|
+
|
|
162
|
+
Important and predefined multiplicative classes on real vector bundles are:
|
|
163
|
+
|
|
164
|
+
- *Pontryagin class* with `g(x) = 1+x`
|
|
165
|
+
- `\hat{A}` *class* with `g(x) = \frac{\sqrt{x}/2}{\sinh(\sqrt{x}/2)}`
|
|
166
|
+
- *Hirzebruch class* with `g(x) = \frac{\sqrt{x}}{\tanh(\sqrt{x})}`
|
|
167
|
+
|
|
168
|
+
EXAMPLES:
|
|
169
|
+
|
|
170
|
+
We consider the **Chern class** of the tautological line bundle `\gamma^1` over
|
|
171
|
+
`\CC\mathbf{P}^1`::
|
|
172
|
+
|
|
173
|
+
sage: M = Manifold(2, 'CP^1', start_index=1)
|
|
174
|
+
sage: U = M.open_subset('U')
|
|
175
|
+
sage: c_cart.<x,y> = U.chart() # homogeneous coordinates in real terms
|
|
176
|
+
sage: c_comp.<z, zbar> = U.chart(r'z:z zbar:\bar{z}') # complexification
|
|
177
|
+
sage: cart_to_comp = c_cart.transition_map(c_comp, (x+I*y, x-I*y))
|
|
178
|
+
sage: comp_to_cart = cart_to_comp.inverse()
|
|
179
|
+
sage: E = M.vector_bundle(1, 'gamma^1', field='complex')
|
|
180
|
+
sage: e = E.local_frame('e', domain=U)
|
|
181
|
+
|
|
182
|
+
To apply the Chern-Weil approach, we need a bundle connection in terms of a
|
|
183
|
+
connection one form. To achieve this, we take the connection induced from the
|
|
184
|
+
hermitian metric on the trivial bundle
|
|
185
|
+
`\CC^2 \times \CC\mathbf{P}^1 \supset \gamma^1`. In this the frame `e`
|
|
186
|
+
corresponds to the section `[z:1] \mapsto (z,1)` and its magnitude-squared
|
|
187
|
+
is given by `1+|z|^2`::
|
|
188
|
+
|
|
189
|
+
sage: nab = E.bundle_connection('nabla')
|
|
190
|
+
sage: omega = U.one_form(name='omega')
|
|
191
|
+
sage: omega[c_comp.frame(),1,c_comp] = zbar/(1+z*zbar)
|
|
192
|
+
sage: nab[e, 1, 1] = omega
|
|
193
|
+
sage: nab.set_immutable()
|
|
194
|
+
|
|
195
|
+
Now, the Chern class can be constructed::
|
|
196
|
+
|
|
197
|
+
sage: c = E.characteristic_cohomology_class('Chern'); c
|
|
198
|
+
Characteristic cohomology class c(gamma^1) of the Differentiable complex
|
|
199
|
+
vector bundle gamma^1 -> CP^1 of rank 1 over the base space 2-dimensional
|
|
200
|
+
differentiable manifold CP^1
|
|
201
|
+
sage: c_form = c.get_form(nab)
|
|
202
|
+
sage: c_form.display_expansion(c_comp.frame(), chart=c_comp)
|
|
203
|
+
c(gamma^1, nabla) = 1 + 1/2*I/(pi + pi*z^2*zbar^2 + 2*pi*z*zbar) dz∧dzbar
|
|
204
|
+
|
|
205
|
+
Since `U` and `\CC\mathbf{P}^1` differ only by a point and therefore a null
|
|
206
|
+
set, it is enough to integrate the top form over the domain `U`::
|
|
207
|
+
|
|
208
|
+
sage: integrate(integrate(c_form[2][[1,2]].expr(c_cart), x, -infinity, infinity).full_simplify(),
|
|
209
|
+
....: y, -infinity, infinity)
|
|
210
|
+
1
|
|
211
|
+
|
|
212
|
+
The result shows that `c_1(\gamma^1)` generates the second integer
|
|
213
|
+
cohomology of `\CC\mathbf{P}^1`.
|
|
214
|
+
|
|
215
|
+
.. _Pfaffian:
|
|
216
|
+
|
|
217
|
+
Pfaffian Classes
|
|
218
|
+
----------------
|
|
219
|
+
|
|
220
|
+
Usually, there is no such thing as "Pfaffian classes" in literature. However,
|
|
221
|
+
using the matrix' Pfaffian and inspired by the aforementioned definitions,
|
|
222
|
+
such classes can be defined as follows.
|
|
223
|
+
|
|
224
|
+
Let `E` be a real vector bundle of rank `2n` and `f` an odd real function
|
|
225
|
+
being analytic at zero. Furthermore, let `\Omega` be skew-symmetric, which
|
|
226
|
+
certainly will be true if `\nabla` is metric and `e` is orthonormal. Then
|
|
227
|
+
we call
|
|
228
|
+
|
|
229
|
+
.. MATH::
|
|
230
|
+
|
|
231
|
+
\left[\mathrm{Pf}\left( f\left( \frac{\Omega}{2 \pi} \right) \right)\right]
|
|
232
|
+
\in H^{2n*}(M,\RR)
|
|
233
|
+
|
|
234
|
+
the *Pfaffian class associated to f*.
|
|
235
|
+
|
|
236
|
+
The most important Pfaffian class is the *Euler class* which is simply given by
|
|
237
|
+
`f(x)=x`.
|
|
238
|
+
|
|
239
|
+
EXAMPLES:
|
|
240
|
+
|
|
241
|
+
We consider the **Euler class** of `S^2`::
|
|
242
|
+
|
|
243
|
+
sage: M.<x,y> = manifolds.Sphere(2, coordinates='stereographic')
|
|
244
|
+
sage: TM = M.tangent_bundle()
|
|
245
|
+
sage: e_class = TM.characteristic_cohomology_class('Euler'); e_class
|
|
246
|
+
Characteristic cohomology class e(TS^2) of the Tangent bundle TS^2 over the
|
|
247
|
+
2-sphere S^2 of radius 1 smoothly embedded in the Euclidean space E^3
|
|
248
|
+
|
|
249
|
+
To compute a particular representative of the Euler class, we need to determine
|
|
250
|
+
a connection, which is in this case given by the standard metric::
|
|
251
|
+
|
|
252
|
+
sage: g = M.metric('g') # standard metric on S2, long time
|
|
253
|
+
sage: nab = g.connection() # long time
|
|
254
|
+
sage: nab.set_immutable() # long time
|
|
255
|
+
|
|
256
|
+
Now the representative of the Euler class with respect to the connection
|
|
257
|
+
`\nabla_g` induced by the standard metric can be computed::
|
|
258
|
+
|
|
259
|
+
sage: e_class_form = e_class.get_form(nab) # long time
|
|
260
|
+
sage: e_class_form.display_expansion() # long time
|
|
261
|
+
e(TS^2, nabla_g) = 2/(pi + pi*x^4 + pi*y^4 + 2*pi*x^2 + 2*(pi + pi*x^2)*y^2) dx∧dy
|
|
262
|
+
|
|
263
|
+
Let us check whether this form represents the Euler class correctly::
|
|
264
|
+
|
|
265
|
+
sage: # long time
|
|
266
|
+
sage: expr = e_class_form[2][[1,2]].expr()
|
|
267
|
+
sage: expr = integrate(expr, x, -infinity, infinity)
|
|
268
|
+
sage: expr = expr.simplify_full()
|
|
269
|
+
sage: integrate(expr, y, -infinity, infinity)
|
|
270
|
+
2
|
|
271
|
+
|
|
272
|
+
As we can see, the integral coincides with the Euler characteristic of `S^2` so
|
|
273
|
+
that our form actually represents the Euler class appropriately.
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
# *****************************************************************************
|
|
277
|
+
# Copyright (C) 2021 Michael Jung <m.jung at vu.nl>
|
|
278
|
+
#
|
|
279
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
280
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
281
|
+
# the License, or (at your option) any later version.
|
|
282
|
+
# https://www.gnu.org/licenses/
|
|
283
|
+
# *****************************************************************************
|
|
284
|
+
|
|
285
|
+
from sage.algebras.finite_gca import FiniteGCAlgebra
|
|
286
|
+
from sage.manifolds.differentiable.affine_connection import AffineConnection
|
|
287
|
+
from sage.manifolds.differentiable.bundle_connection import BundleConnection
|
|
288
|
+
from sage.manifolds.differentiable.levi_civita_connection import LeviCivitaConnection
|
|
289
|
+
from sage.misc.abstract_method import abstract_method
|
|
290
|
+
from sage.misc.cachefunc import cached_method
|
|
291
|
+
from sage.misc.fast_methods import Singleton
|
|
292
|
+
from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
|
|
293
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
294
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
295
|
+
from sage.structure.sage_object import SageObject
|
|
296
|
+
from sage.symbolic.expression import Expression
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class CharacteristicCohomologyClassRingElement(IndexedFreeModuleElement):
|
|
300
|
+
r"""
|
|
301
|
+
Characteristic cohomology class.
|
|
302
|
+
|
|
303
|
+
Let `E \to M` be a real/complex vector bundle of rank `k`. A characteristic
|
|
304
|
+
cohomology class of `E` is generated by either
|
|
305
|
+
|
|
306
|
+
- Chern classes if `E` is complex,
|
|
307
|
+
- Pontryagin classes if `E` is real,
|
|
308
|
+
- Pontryagin classes and the Euler class if `E` is real and orientable,
|
|
309
|
+
|
|
310
|
+
via the Chern-Weil homomorphism.
|
|
311
|
+
|
|
312
|
+
For details about the ring structure, see
|
|
313
|
+
:class:`CharacteristicCohomologyClassRing`.
|
|
314
|
+
|
|
315
|
+
To construct a characteristic cohomology class, please use
|
|
316
|
+
:func:`CharacteristicCohomologyClass`.
|
|
317
|
+
|
|
318
|
+
EXAMPLES::
|
|
319
|
+
|
|
320
|
+
sage: M = Manifold(12, 'M')
|
|
321
|
+
sage: TM = M.tangent_bundle()
|
|
322
|
+
sage: CR = TM.characteristic_cohomology_class_ring()
|
|
323
|
+
sage: p1, p2, p3 = CR.gens()
|
|
324
|
+
sage: p1*p2+p3
|
|
325
|
+
Characteristic cohomology class (p_1⌣p_2 + p_3)(TM) of the Tangent
|
|
326
|
+
bundle TM over the 12-dimensional differentiable manifold M
|
|
327
|
+
sage: A = TM.characteristic_cohomology_class('AHat'); A
|
|
328
|
+
Characteristic cohomology class A^(TM) of the Tangent bundle TM over
|
|
329
|
+
the 12-dimensional differentiable manifold M
|
|
330
|
+
sage: A == 1 - p1/24 + (7*p1^2-4*p2)/5760 + (44*p1*p2-31*p1^3-16*p3)/967680
|
|
331
|
+
True
|
|
332
|
+
"""
|
|
333
|
+
def __init__(self, parent, x, name=None, latex_name=None):
|
|
334
|
+
r"""
|
|
335
|
+
Construct a characteristic cohomology class.
|
|
336
|
+
|
|
337
|
+
TESTS::
|
|
338
|
+
|
|
339
|
+
sage: M = Manifold(8, 'M')
|
|
340
|
+
sage: TM = M.tangent_bundle()
|
|
341
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin')
|
|
342
|
+
sage: TestSuite(p).run()
|
|
343
|
+
"""
|
|
344
|
+
self._name = name
|
|
345
|
+
if latex_name is None:
|
|
346
|
+
self._latex_name = self._name
|
|
347
|
+
else:
|
|
348
|
+
self._latex_name = latex_name
|
|
349
|
+
self._mixed_forms = {} # dict. of characteristic forms of self
|
|
350
|
+
# (key: bundle connection)
|
|
351
|
+
super().__init__(parent, x)
|
|
352
|
+
|
|
353
|
+
def _repr_(self):
|
|
354
|
+
r"""
|
|
355
|
+
String representation of the object.
|
|
356
|
+
|
|
357
|
+
TESTS::
|
|
358
|
+
|
|
359
|
+
sage: M = Manifold(8, 'M')
|
|
360
|
+
sage: TM = M.tangent_bundle()
|
|
361
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin')
|
|
362
|
+
sage: p._repr_()
|
|
363
|
+
'Characteristic cohomology class p(TM) of the Tangent bundle TM
|
|
364
|
+
over the 8-dimensional differentiable manifold M'
|
|
365
|
+
sage: p # indirect doctest
|
|
366
|
+
Characteristic cohomology class p(TM) of the Tangent bundle TM over
|
|
367
|
+
the 8-dimensional differentiable manifold M
|
|
368
|
+
|
|
369
|
+
::
|
|
370
|
+
|
|
371
|
+
sage: x = var('x')
|
|
372
|
+
sage: k = TM.characteristic_cohomology_class(1+x^2, class_type='multiplicative')
|
|
373
|
+
sage: k._repr_()
|
|
374
|
+
'Characteristic cohomology class (1 + p_1^2 - 2*p_2)(TM) of the
|
|
375
|
+
Tangent bundle TM over the 8-dimensional differentiable manifold M'
|
|
376
|
+
sage: k # indirect doctest
|
|
377
|
+
Characteristic cohomology class (1 + p_1^2 - 2*p_2)(TM) of the
|
|
378
|
+
Tangent bundle TM over the 8-dimensional differentiable manifold M
|
|
379
|
+
"""
|
|
380
|
+
if self._name is None:
|
|
381
|
+
name = f'({super()._repr_()})'
|
|
382
|
+
else:
|
|
383
|
+
name = self._name
|
|
384
|
+
vbundle = self.parent()._vbundle
|
|
385
|
+
name = f'{name}({vbundle._name})'
|
|
386
|
+
return f'Characteristic cohomology class {name} of the {vbundle}'
|
|
387
|
+
|
|
388
|
+
def _latex_(self):
|
|
389
|
+
r"""
|
|
390
|
+
LaTeX representation of the object.
|
|
391
|
+
|
|
392
|
+
TESTS::
|
|
393
|
+
|
|
394
|
+
sage: M = Manifold(8, 'M')
|
|
395
|
+
sage: TM = M.tangent_bundle()
|
|
396
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin')
|
|
397
|
+
sage: p._latex_()
|
|
398
|
+
'p\\left(TM\\right)'
|
|
399
|
+
sage: latex(p) # indirect doctest
|
|
400
|
+
p\left(TM\right)
|
|
401
|
+
|
|
402
|
+
::
|
|
403
|
+
|
|
404
|
+
sage: x = var('x')
|
|
405
|
+
sage: k = TM.characteristic_cohomology_class(1+x^2, class_type='multiplicative')
|
|
406
|
+
sage: k._latex_()
|
|
407
|
+
'\\left(1 + p_1^{2} - 2 p_2\\right)\\left(TM\\right)'
|
|
408
|
+
sage: latex(k)
|
|
409
|
+
\left(1 + p_1^{2} - 2 p_2\right)\left(TM\right)
|
|
410
|
+
"""
|
|
411
|
+
if self._latex_name is None:
|
|
412
|
+
latex = r'\left(' + super()._latex_() + r'\right)'
|
|
413
|
+
else:
|
|
414
|
+
latex = self._latex_name
|
|
415
|
+
vbundle = self.parent()._vbundle
|
|
416
|
+
latex += r'\left(' + vbundle._latex_name + r'\right)'
|
|
417
|
+
return latex
|
|
418
|
+
|
|
419
|
+
def get_form(self, nab):
|
|
420
|
+
r"""
|
|
421
|
+
Return the characteristic form of ``self``.
|
|
422
|
+
|
|
423
|
+
INPUT:
|
|
424
|
+
|
|
425
|
+
- ``nab`` -- get the characteristic form w.r.t. to the
|
|
426
|
+
connection ``nab``
|
|
427
|
+
|
|
428
|
+
OUTPUT:
|
|
429
|
+
|
|
430
|
+
- an instance of
|
|
431
|
+
:class:`sage.manifolds.differentiable.mixed_form.MixedForm`
|
|
432
|
+
|
|
433
|
+
EXAMPLES:
|
|
434
|
+
|
|
435
|
+
Trivial characteristic form on Euclidean space::
|
|
436
|
+
|
|
437
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
438
|
+
sage: TM = M.tangent_bundle()
|
|
439
|
+
sage: one = TM.characteristic_cohomology_class_ring().one()
|
|
440
|
+
sage: g = M.metric()
|
|
441
|
+
sage: nab = g.connection()
|
|
442
|
+
sage: nab.set_immutable()
|
|
443
|
+
sage: one.get_form(nab)
|
|
444
|
+
Mixed differential form one on the 4-dimensional Euclidean space E^4
|
|
445
|
+
|
|
446
|
+
Pontryagin form on the 4-sphere::
|
|
447
|
+
|
|
448
|
+
sage: M = manifolds.Sphere(4)
|
|
449
|
+
sage: TM = M.tangent_bundle()
|
|
450
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin'); p
|
|
451
|
+
Characteristic cohomology class p(TS^4) of the Tangent bundle TS^4
|
|
452
|
+
over the 4-sphere S^4 of radius 1 smoothly embedded in the
|
|
453
|
+
5-dimensional Euclidean space E^5
|
|
454
|
+
sage: g = M.metric() # long time
|
|
455
|
+
sage: nab = g.connection() # long time
|
|
456
|
+
sage: nab.set_immutable() # long time
|
|
457
|
+
sage: p_form = p.get_form(nab); p_form # long time
|
|
458
|
+
Mixed differential form p(TS^4, nabla_g) on the 4-sphere S^4 of
|
|
459
|
+
radius 1 smoothly embedded in the 5-dimensional Euclidean space E^5
|
|
460
|
+
sage: p_form.display_expansion() # long time
|
|
461
|
+
p(TS^4, nabla_g) = 1
|
|
462
|
+
"""
|
|
463
|
+
if nab not in self._mixed_forms:
|
|
464
|
+
dom = nab._domain
|
|
465
|
+
A = dom.mixed_form_algebra()
|
|
466
|
+
|
|
467
|
+
# trivial cases
|
|
468
|
+
if self == 1:
|
|
469
|
+
self._mixed_forms[nab] = A(dom._one_scalar_field)
|
|
470
|
+
elif self == 0:
|
|
471
|
+
self._mixed_forms[nab] = A(dom._zero_scalar_field)
|
|
472
|
+
else: # non-trivial case
|
|
473
|
+
from functools import reduce
|
|
474
|
+
|
|
475
|
+
parent = self.parent()
|
|
476
|
+
algorithm = parent._algorithm
|
|
477
|
+
|
|
478
|
+
grading = parent.print_options()['sorting_key']
|
|
479
|
+
res = [dom.diff_form_module(i).zero()
|
|
480
|
+
for i in range(dom._dim + 1)]
|
|
481
|
+
for ind, c in self:
|
|
482
|
+
deg = grading(ind)
|
|
483
|
+
gen_pow = [algorithm.get_gen_pow(nab, i, ind[i])
|
|
484
|
+
for i in range(len(ind))]
|
|
485
|
+
res[deg] += c * reduce(lambda x, y: x.wedge(y), gen_pow)
|
|
486
|
+
|
|
487
|
+
res = A(res) # convert result into mixed form
|
|
488
|
+
|
|
489
|
+
# preparse names
|
|
490
|
+
vbundle = parent._vbundle
|
|
491
|
+
if self._name is None:
|
|
492
|
+
name = f'({super()._repr_()})'
|
|
493
|
+
else:
|
|
494
|
+
name = self._name
|
|
495
|
+
if self._latex_name is None:
|
|
496
|
+
latex_name = r'\left(' + super()._latex_() + r'\right)'
|
|
497
|
+
else:
|
|
498
|
+
latex_name = self._latex_name
|
|
499
|
+
# appendix
|
|
500
|
+
append_name = f'({vbundle._name}, {nab._name})'
|
|
501
|
+
append_latex_name = r'\left(' + vbundle._latex_name
|
|
502
|
+
append_latex_name += ', ' + nab._latex_name + r'\right)'
|
|
503
|
+
|
|
504
|
+
# set names of components
|
|
505
|
+
from sage.arith.misc import gcd
|
|
506
|
+
|
|
507
|
+
step = gcd(parent._degrees) # step size of (possibly) nonzero
|
|
508
|
+
for i in range(dom._dim // step + 1):
|
|
509
|
+
# enumerate (possibly) nonzero components
|
|
510
|
+
comp_name = name + f'_{i}' + append_name
|
|
511
|
+
comp_latex_name = latex_name + r'_{' + str(i) + '}'
|
|
512
|
+
comp_latex_name += append_latex_name
|
|
513
|
+
res[step * i].set_name(name=comp_name,
|
|
514
|
+
latex_name=comp_latex_name)
|
|
515
|
+
|
|
516
|
+
# set global names
|
|
517
|
+
res._name = name + append_name
|
|
518
|
+
res._latex_name = latex_name + append_latex_name
|
|
519
|
+
|
|
520
|
+
res.set_immutable()
|
|
521
|
+
|
|
522
|
+
self._mixed_forms[nab] = res # cache result in dict
|
|
523
|
+
|
|
524
|
+
return self._mixed_forms[nab]
|
|
525
|
+
|
|
526
|
+
def representative(self, nab=None):
|
|
527
|
+
r"""
|
|
528
|
+
Return any representative of ``self``.
|
|
529
|
+
|
|
530
|
+
INPUT:
|
|
531
|
+
|
|
532
|
+
- ``nab`` -- (default: ``None``) if stated, return the representative
|
|
533
|
+
w.r.t. to the connection ``nab``; otherwise an arbitrary already
|
|
534
|
+
computed representative will be chosen.
|
|
535
|
+
|
|
536
|
+
OUTPUT:
|
|
537
|
+
|
|
538
|
+
- an instance of
|
|
539
|
+
:class:`sage.manifolds.differentiable.mixed_form.MixedForm`
|
|
540
|
+
|
|
541
|
+
EXAMPLES:
|
|
542
|
+
|
|
543
|
+
Define the 4-dimensional Euclidean space::
|
|
544
|
+
|
|
545
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
546
|
+
sage: TM = M.tangent_bundle()
|
|
547
|
+
sage: one = TM.characteristic_cohomology_class_ring().one()
|
|
548
|
+
|
|
549
|
+
No characteristic form has been computed so far, thus we get an error::
|
|
550
|
+
|
|
551
|
+
sage: one.representative()
|
|
552
|
+
Traceback (most recent call last):
|
|
553
|
+
...
|
|
554
|
+
AttributeError: cannot pick a representative
|
|
555
|
+
|
|
556
|
+
Get a characteristic form::
|
|
557
|
+
|
|
558
|
+
sage: g = M.metric()
|
|
559
|
+
sage: nab = g.connection()
|
|
560
|
+
sage: nab.set_immutable()
|
|
561
|
+
sage: one.get_form(nab)
|
|
562
|
+
Mixed differential form one on the 4-dimensional Euclidean space E^4
|
|
563
|
+
|
|
564
|
+
Now, the result is cached and `representative` returns a form::
|
|
565
|
+
|
|
566
|
+
sage: one.representative()
|
|
567
|
+
Mixed differential form one on the 4-dimensional Euclidean space E^4
|
|
568
|
+
|
|
569
|
+
Alternatively, the option ``nab`` can be used to return the
|
|
570
|
+
characteristic form w.r.t. a fixed connection::
|
|
571
|
+
|
|
572
|
+
sage: one.representative(nab)
|
|
573
|
+
Mixed differential form one on the 4-dimensional Euclidean space E^4
|
|
574
|
+
|
|
575
|
+
.. SEEALSO::
|
|
576
|
+
|
|
577
|
+
:meth:`CharacteristicCohomologyClassRingElement.get_form`
|
|
578
|
+
"""
|
|
579
|
+
if nab is None:
|
|
580
|
+
if not self._mixed_forms:
|
|
581
|
+
raise AttributeError('cannot pick a representative')
|
|
582
|
+
return next(iter(self._mixed_forms.values()))
|
|
583
|
+
return self.get_form(nab)
|
|
584
|
+
|
|
585
|
+
def set_name(self, name=None, latex_name=None):
|
|
586
|
+
r"""
|
|
587
|
+
Set (or change) the text name and LaTeX name of the characteristic
|
|
588
|
+
class.
|
|
589
|
+
|
|
590
|
+
INPUT:
|
|
591
|
+
|
|
592
|
+
- ``name`` -- (string; default: ``None``) name given to the
|
|
593
|
+
characteristic cohomology class
|
|
594
|
+
- ``latex_name`` -- (string; default: ``None``) LaTeX symbol to denote
|
|
595
|
+
the characteristic cohomology class; if ``None`` while ``name`` is
|
|
596
|
+
provided, the LaTeX symbol is set to ``name``
|
|
597
|
+
|
|
598
|
+
EXAMPLES::
|
|
599
|
+
|
|
600
|
+
sage: M = Manifold(8, 'M')
|
|
601
|
+
sage: TM = M.tangent_bundle()
|
|
602
|
+
sage: x = var('x')
|
|
603
|
+
sage: k = TM.characteristic_cohomology_class(1+x^2,
|
|
604
|
+
....: class_type='multiplicative'); k
|
|
605
|
+
Characteristic cohomology class (1 + p_1^2 - 2*p_2)(TM) of the
|
|
606
|
+
Tangent bundle TM over the 8-dimensional differentiable manifold M
|
|
607
|
+
sage: k.set_name(name='k', latex_name=r'\kappa')
|
|
608
|
+
sage: k
|
|
609
|
+
Characteristic cohomology class k(TM) of the Tangent bundle TM over
|
|
610
|
+
the 8-dimensional differentiable manifold M
|
|
611
|
+
sage: latex(k)
|
|
612
|
+
\kappa\left(TM\right)
|
|
613
|
+
"""
|
|
614
|
+
if name is not None:
|
|
615
|
+
self._name = name
|
|
616
|
+
if latex_name is None:
|
|
617
|
+
self._latex_name = self._name
|
|
618
|
+
if latex_name is not None:
|
|
619
|
+
self._latex_name = latex_name
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
class CharacteristicCohomologyClassRing(FiniteGCAlgebra):
|
|
623
|
+
r"""
|
|
624
|
+
Characteristic cohomology class ring.
|
|
625
|
+
|
|
626
|
+
Let `E \to M` be a real or complex vector bundle of rank `k` and `R` be a
|
|
627
|
+
torsion-free subring of `\CC`.
|
|
628
|
+
|
|
629
|
+
Let `BG` be the classifying space of the group `G`. As for vector bundles,
|
|
630
|
+
we consider
|
|
631
|
+
|
|
632
|
+
- `G = O(k)` if `E` is real,
|
|
633
|
+
- `G = SO(k)` if `E` is real and oriented,
|
|
634
|
+
- `G = U(k)` if `E` is complex.
|
|
635
|
+
|
|
636
|
+
The cohomology ring `H^*(BG; R)` can be explicitly expressed for the
|
|
637
|
+
aforementioned cases:
|
|
638
|
+
|
|
639
|
+
.. MATH::
|
|
640
|
+
|
|
641
|
+
H^*(BG; R) \cong \begin{cases}
|
|
642
|
+
R[c_1, \ldots c_k] & \text{if } G = U(k), \\
|
|
643
|
+
R[p_1, \ldots p_{\lfloor \frac{k}{2}\rfloor}] & \text{if } G = O(k), \\
|
|
644
|
+
R[p_1, \ldots p_k, e] \big/ (p_k-e^2) & \text{if } G = SO(2k), \\
|
|
645
|
+
R[p_1, \ldots p_k, e] & \text{if } G = SO(2k+1). \\
|
|
646
|
+
\end{cases}
|
|
647
|
+
|
|
648
|
+
The Chern-Weil homomorphism relates the generators in the de Rham
|
|
649
|
+
cohomology as follows. If `\Omega` is a curvature form matrix on `E`, for
|
|
650
|
+
the Chern classes we get
|
|
651
|
+
|
|
652
|
+
.. MATH::
|
|
653
|
+
|
|
654
|
+
\left[ \det\left( 1 + \frac{t \Omega}{2 \pi i} \right) \right] = 1 +
|
|
655
|
+
\sum^k_{n=1} c_n(E) t^n,
|
|
656
|
+
|
|
657
|
+
for the Pontryagin classes we have
|
|
658
|
+
|
|
659
|
+
.. MATH::
|
|
660
|
+
|
|
661
|
+
\left[ \det\left( 1 - \frac{t \Omega}{2 \pi} \right) \right] = 1 +
|
|
662
|
+
\sum^{\lfloor\frac{k}{2} \rfloor}_{n=1} p_n(E) t^n,
|
|
663
|
+
|
|
664
|
+
and for the Euler class we obtain
|
|
665
|
+
|
|
666
|
+
.. MATH::
|
|
667
|
+
|
|
668
|
+
\left[ \mathrm{Pf}\left(\frac{\Omega}{2 \pi} \right) \right] = e(E).
|
|
669
|
+
|
|
670
|
+
Consequently, the cohomology ring `H^*(BG; R)` is mapped (not
|
|
671
|
+
necessarily injectively) to a subring of `H^*_\mathrm{dR}(M, \CC)` via
|
|
672
|
+
the Chern-Weil homomorphism. This implementation attempts to represent this
|
|
673
|
+
subring.
|
|
674
|
+
|
|
675
|
+
.. NOTE::
|
|
676
|
+
|
|
677
|
+
Some generators might have torsion in `H^*(BG; R)` giving a zero
|
|
678
|
+
element in the de Rham cohomology. Those generators are still
|
|
679
|
+
considered in the implementation. Generators whose degree exceed the
|
|
680
|
+
dimension of the base space, however, are ignored.
|
|
681
|
+
|
|
682
|
+
INPUT:
|
|
683
|
+
|
|
684
|
+
- ``base`` -- base ring
|
|
685
|
+
- ``vbundle`` -- vector bundle
|
|
686
|
+
|
|
687
|
+
EXAMPLES:
|
|
688
|
+
|
|
689
|
+
Characteristic cohomology class ring over the tangent bundle of an
|
|
690
|
+
8-dimensional manifold::
|
|
691
|
+
|
|
692
|
+
sage: M = Manifold(8, 'M')
|
|
693
|
+
sage: TM = M.tangent_bundle()
|
|
694
|
+
sage: CR = TM.characteristic_cohomology_class_ring(); CR
|
|
695
|
+
Algebra of characteristic cohomology classes of the Tangent bundle TM
|
|
696
|
+
over the 8-dimensional differentiable manifold M
|
|
697
|
+
sage: CR.gens()
|
|
698
|
+
(Characteristic cohomology class (p_1)(TM) of the Tangent bundle TM over
|
|
699
|
+
the 8-dimensional differentiable manifold M,
|
|
700
|
+
Characteristic cohomology class (p_2)(TM) of the Tangent bundle TM
|
|
701
|
+
over the 8-dimensional differentiable manifold M)
|
|
702
|
+
|
|
703
|
+
The default base ring is `\QQ`::
|
|
704
|
+
|
|
705
|
+
sage: CR.base_ring()
|
|
706
|
+
Rational Field
|
|
707
|
+
|
|
708
|
+
Characteristic cohomology class ring over a complex vector bundle::
|
|
709
|
+
|
|
710
|
+
sage: M = Manifold(4, 'M')
|
|
711
|
+
sage: E = M.vector_bundle(2, 'E', field='complex')
|
|
712
|
+
sage: CR_E = E.characteristic_cohomology_class_ring(); CR_E
|
|
713
|
+
Algebra of characteristic cohomology classes of the Differentiable
|
|
714
|
+
complex vector bundle E -> M of rank 2 over the base space
|
|
715
|
+
4-dimensional differentiable manifold M
|
|
716
|
+
sage: CR_E.gens()
|
|
717
|
+
(Characteristic cohomology class (c_1)(E) of the Differentiable complex
|
|
718
|
+
vector bundle E -> M of rank 2 over the base space 4-dimensional
|
|
719
|
+
differentiable manifold M,
|
|
720
|
+
Characteristic cohomology class (c_2)(E) of the Differentiable
|
|
721
|
+
complex vector bundle E -> M of rank 2 over the base space
|
|
722
|
+
4-dimensional differentiable manifold M)
|
|
723
|
+
|
|
724
|
+
Characteristic cohomology class ring over an oriented manifold::
|
|
725
|
+
|
|
726
|
+
sage: S2 = manifolds.Sphere(2, coordinates='stereographic')
|
|
727
|
+
sage: TS2 = S2.tangent_bundle()
|
|
728
|
+
sage: S2.has_orientation()
|
|
729
|
+
True
|
|
730
|
+
sage: CR = TS2.characteristic_cohomology_class_ring()
|
|
731
|
+
sage: CR.gens()
|
|
732
|
+
(Characteristic cohomology class (e)(TS^2) of the Tangent bundle TS^2
|
|
733
|
+
over the 2-sphere S^2 of radius 1 smoothly embedded in the Euclidean
|
|
734
|
+
space E^3,)
|
|
735
|
+
"""
|
|
736
|
+
Element = CharacteristicCohomologyClassRingElement
|
|
737
|
+
|
|
738
|
+
def __init__(self, base, vbundle):
|
|
739
|
+
r"""
|
|
740
|
+
Construct a characteristic cohomology ring.
|
|
741
|
+
|
|
742
|
+
TESTS::
|
|
743
|
+
|
|
744
|
+
sage: M = Manifold(8, 'M')
|
|
745
|
+
sage: TM = M.tangent_bundle()
|
|
746
|
+
sage: CR = TM.characteristic_cohomology_class_ring()
|
|
747
|
+
sage: TestSuite(CR).run()
|
|
748
|
+
"""
|
|
749
|
+
self._vbundle = vbundle
|
|
750
|
+
self._domain = vbundle._base_space
|
|
751
|
+
dim = self._domain._dim
|
|
752
|
+
rk = vbundle._rank
|
|
753
|
+
if vbundle._field_type == 'complex':
|
|
754
|
+
ran = min(rk, dim // 2)
|
|
755
|
+
names = [f'c_{i}' for i in range(1, ran + 1)]
|
|
756
|
+
degrees = [2 * i for i in range(1, ran + 1)]
|
|
757
|
+
self._algorithm = ChernAlgorithm()
|
|
758
|
+
elif vbundle._field_type == 'real':
|
|
759
|
+
ran = min(rk // 2, dim // 4)
|
|
760
|
+
names = [f'p_{i}' for i in range(1, ran + 1)]
|
|
761
|
+
degrees = [4 * i for i in range(1, ran + 1)]
|
|
762
|
+
self._algorithm = PontryaginAlgorithm()
|
|
763
|
+
if vbundle.has_orientation():
|
|
764
|
+
# add Euler class generator
|
|
765
|
+
# Euler should be first entry; see `PontryaginEulerAlgorithm`
|
|
766
|
+
names = ['e'] + names
|
|
767
|
+
degrees = [rk] + degrees
|
|
768
|
+
self._algorithm = PontryaginEulerAlgorithm()
|
|
769
|
+
# TODO: add relation e^2=p_k for dim=2*k
|
|
770
|
+
else:
|
|
771
|
+
raise TypeError(f'Characteristic cohomology classes not supported '
|
|
772
|
+
f'for vector bundles with '
|
|
773
|
+
f'field type {vbundle._field_type}')
|
|
774
|
+
|
|
775
|
+
if not names or not degrees:
|
|
776
|
+
raise ValueError('cannot find any generators')
|
|
777
|
+
|
|
778
|
+
names = tuple(names) # hashable
|
|
779
|
+
degrees = tuple(degrees) # hashable
|
|
780
|
+
super().__init__(base=base, names=names, degrees=degrees,
|
|
781
|
+
max_degree=dim, mul_symbol='⌣',
|
|
782
|
+
mul_latex_symbol=r'\smile')
|
|
783
|
+
|
|
784
|
+
def _element_constructor_(self, x, **kwargs):
|
|
785
|
+
r"""
|
|
786
|
+
Convert ``x`` into ``self``.
|
|
787
|
+
|
|
788
|
+
TESTS::
|
|
789
|
+
|
|
790
|
+
sage: M = Manifold(8, 'M')
|
|
791
|
+
sage: TM = M.tangent_bundle()
|
|
792
|
+
sage: CR = TM.characteristic_cohomology_class_ring()
|
|
793
|
+
sage: p = CR('Pontryagin'); p
|
|
794
|
+
Characteristic cohomology class p(TM) of the Tangent bundle TM over
|
|
795
|
+
the 8-dimensional differentiable manifold M
|
|
796
|
+
sage: CR(p, name='pontr')
|
|
797
|
+
Characteristic cohomology class pontr(TM) of the Tangent bundle
|
|
798
|
+
TM over the 8-dimensional differentiable manifold M
|
|
799
|
+
"""
|
|
800
|
+
if isinstance(x, (str, Expression, Polynomial)):
|
|
801
|
+
return self._build_element(x, **kwargs)
|
|
802
|
+
|
|
803
|
+
R = self.base_ring()
|
|
804
|
+
|
|
805
|
+
if x in R:
|
|
806
|
+
one_basis = self.one_basis()
|
|
807
|
+
d = {one_basis: R(x)}
|
|
808
|
+
elif isinstance(x, CharacteristicCohomologyClassRingElement):
|
|
809
|
+
d = x._monomial_coefficients
|
|
810
|
+
# x is an element of the basis enumerated set;
|
|
811
|
+
# This is a very ugly way of testing this
|
|
812
|
+
elif ((hasattr(self._indices, 'element_class') and
|
|
813
|
+
isinstance(self._indices.element_class, type) and
|
|
814
|
+
isinstance(x, self._indices.element_class)) or
|
|
815
|
+
self.parent()(x) == self._indices):
|
|
816
|
+
d = {x: R.one()}
|
|
817
|
+
elif x in self._indices:
|
|
818
|
+
d = {self._indices(x): R.one()}
|
|
819
|
+
else:
|
|
820
|
+
raise TypeError(f"do not know how to make x (= {x}) "
|
|
821
|
+
f"an element of self (={self})")
|
|
822
|
+
name, latex_name = kwargs.get('name'), kwargs.get('latex_name')
|
|
823
|
+
return self.element_class(self, d, name=name, latex_name=latex_name)
|
|
824
|
+
|
|
825
|
+
@cached_method
|
|
826
|
+
def _build_element(self, *args, **kwargs):
|
|
827
|
+
r"""
|
|
828
|
+
Construct a characteristic cohomology class.
|
|
829
|
+
|
|
830
|
+
The result is cached.
|
|
831
|
+
|
|
832
|
+
INPUT:
|
|
833
|
+
|
|
834
|
+
- ``val`` -- the input data corresponding to the characteristic class
|
|
835
|
+
using the Chern-Weil homomorphism; this argument can be either a
|
|
836
|
+
symbolic expression, a polynomial or one of the following predefined
|
|
837
|
+
classes:
|
|
838
|
+
|
|
839
|
+
- ``'Chern'`` -- total Chern class,
|
|
840
|
+
- ``'ChernChar'`` -- Chern character,
|
|
841
|
+
- ``'Todd'`` -- Todd class,
|
|
842
|
+
- ``'Pontryagin'`` -- total Pontryagin class,
|
|
843
|
+
- ``'Hirzebruch'`` -- Hirzebruch class,
|
|
844
|
+
- ``'AHat'`` -- `\hat{A}` class,
|
|
845
|
+
- ``'Euler'`` -- Euler class.
|
|
846
|
+
|
|
847
|
+
- ``name`` -- (default: ``None``) string representation given to the
|
|
848
|
+
characteristic class; if ``None`` the default algebra representation or
|
|
849
|
+
predefined name is used
|
|
850
|
+
- ``latex_name`` -- (default: ``None``) LaTeX name given to the
|
|
851
|
+
characteristic class; if ``None`` the value of ``name`` is used
|
|
852
|
+
- ``class_type`` -- (default: ``None``) class type of the characteristic
|
|
853
|
+
cohomology class; the following options are possible:
|
|
854
|
+
|
|
855
|
+
- ``'multiplicative'`` -- returns a class of multiplicative type
|
|
856
|
+
- ``'additive'`` -- returns a class of additive type
|
|
857
|
+
- ``'Pfaffian'`` -- returns a class of Pfaffian type
|
|
858
|
+
|
|
859
|
+
This argument must be stated if ``val`` is a polynomial or symbolic
|
|
860
|
+
expression.
|
|
861
|
+
|
|
862
|
+
EXAMPLES:
|
|
863
|
+
|
|
864
|
+
Total Pontryagin class of an 8-dimensional manifold::
|
|
865
|
+
|
|
866
|
+
sage: M = Manifold(8, 'M')
|
|
867
|
+
sage: TM = M.tangent_bundle()
|
|
868
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin'); p
|
|
869
|
+
Characteristic cohomology class p(TM) of the Tangent bundle TM over the
|
|
870
|
+
8-dimensional differentiable manifold M
|
|
871
|
+
|
|
872
|
+
Define a multiplicative class (see :func:`multiplicative_sequence`)::
|
|
873
|
+
|
|
874
|
+
sage: P.<x> = PolynomialRing(QQ)
|
|
875
|
+
sage: f = 1 + x - x^2
|
|
876
|
+
sage: f_class = TM.characteristic_cohomology_class(f, class_type='multiplicative'); f_class
|
|
877
|
+
Characteristic cohomology class (1 + p_1 - p_1^2 + 3*p_2)(TM) of the
|
|
878
|
+
Tangent bundle TM over the 8-dimensional differentiable manifold M
|
|
879
|
+
|
|
880
|
+
Pass a symbolic expression, whose Taylor expansion at zero will be used::
|
|
881
|
+
|
|
882
|
+
sage: M = Manifold(8, 'M')
|
|
883
|
+
sage: TM = M.tangent_bundle()
|
|
884
|
+
sage: x = var('x')
|
|
885
|
+
sage: f = cos(x)
|
|
886
|
+
sage: f_class = TM.characteristic_cohomology_class(f, class_type='multiplicative'); f_class
|
|
887
|
+
Characteristic cohomology class (1 - 1/2*p_1^2 + p_2)(TM) of the Tangent
|
|
888
|
+
bundle TM over the 8-dimensional differentiable manifold M
|
|
889
|
+
"""
|
|
890
|
+
name, latex_name = kwargs.get('name'), kwargs.get('latex_name')
|
|
891
|
+
base_ring = self.base_ring()
|
|
892
|
+
class_type = kwargs.get('class_type')
|
|
893
|
+
vbundle = self._vbundle
|
|
894
|
+
val = args[0]
|
|
895
|
+
dim = vbundle._base_space._dim
|
|
896
|
+
|
|
897
|
+
# predefined classes accessible via class names
|
|
898
|
+
if isinstance(val, str):
|
|
899
|
+
from sage.arith.misc import bernoulli, factorial
|
|
900
|
+
|
|
901
|
+
P = PolynomialRing(base_ring, 'x')
|
|
902
|
+
x = P.gen()
|
|
903
|
+
if val == 'Chern':
|
|
904
|
+
if vbundle._field_type != 'complex':
|
|
905
|
+
raise ValueError(f'total Chern class not defined on {vbundle}')
|
|
906
|
+
if name is None:
|
|
907
|
+
name = 'c'
|
|
908
|
+
class_type = 'multiplicative'
|
|
909
|
+
val = 1 + x
|
|
910
|
+
elif val == 'Pontryagin':
|
|
911
|
+
if vbundle._field_type != 'real':
|
|
912
|
+
raise ValueError(f'total Pontryagin class not defined on {vbundle}')
|
|
913
|
+
if name is None:
|
|
914
|
+
name = 'p'
|
|
915
|
+
class_type = 'multiplicative'
|
|
916
|
+
val = 1 + x
|
|
917
|
+
elif val == 'ChernChar':
|
|
918
|
+
if vbundle._field_type != 'complex':
|
|
919
|
+
raise ValueError(f'Chern character not defined on {vbundle}')
|
|
920
|
+
if name is None:
|
|
921
|
+
name = 'ch'
|
|
922
|
+
if latex_name is None:
|
|
923
|
+
latex_name = r'\mathrm{ch}'
|
|
924
|
+
class_type = 'additive'
|
|
925
|
+
coeff = [1 / factorial(k) for k in
|
|
926
|
+
range(dim // 2 + 1)] # exp(x)
|
|
927
|
+
val = P(coeff)
|
|
928
|
+
elif val == 'Todd':
|
|
929
|
+
if vbundle._field_type != 'complex':
|
|
930
|
+
raise ValueError(f'Todd class not defined on {vbundle}')
|
|
931
|
+
if name is None:
|
|
932
|
+
name = 'Td'
|
|
933
|
+
if latex_name is None:
|
|
934
|
+
latex_name = r'\mathrm{Td}'
|
|
935
|
+
class_type = 'multiplicative'
|
|
936
|
+
val = 1 + x / 2
|
|
937
|
+
for k in range(1, dim // 2 + 1):
|
|
938
|
+
val += (-1) ** (k + 1) / factorial(2 * k) * bernoulli(
|
|
939
|
+
2 * k) * x ** (2 * k)
|
|
940
|
+
elif val == 'Hirzebruch':
|
|
941
|
+
if vbundle._field_type != 'real':
|
|
942
|
+
raise ValueError(f'Hirzebruch class not defined on {vbundle}')
|
|
943
|
+
if name is None:
|
|
944
|
+
name = 'L'
|
|
945
|
+
if latex_name is None:
|
|
946
|
+
latex_name = 'L'
|
|
947
|
+
class_type = 'multiplicative'
|
|
948
|
+
coeff = [2 ** (2 * k) * bernoulli(2 * k) / factorial(2 * k)
|
|
949
|
+
for k in range(dim // 4 + 1)]
|
|
950
|
+
val = P(coeff)
|
|
951
|
+
elif val == 'AHat':
|
|
952
|
+
if vbundle._field_type != 'real':
|
|
953
|
+
raise ValueError(f'AHat class not defined on {vbundle}')
|
|
954
|
+
if name is None:
|
|
955
|
+
name = 'A^'
|
|
956
|
+
if latex_name is None:
|
|
957
|
+
latex_name = r'\hat{A}'
|
|
958
|
+
class_type = 'multiplicative'
|
|
959
|
+
coeff = [- (2 ** (2 * k) - 2) / 2 ** (2 * k) * bernoulli(
|
|
960
|
+
2 * k) / factorial(2 * k)
|
|
961
|
+
for k in range(dim // 4 + 1)]
|
|
962
|
+
val = P(coeff)
|
|
963
|
+
elif val == 'Euler':
|
|
964
|
+
if vbundle._field_type != 'real' or not vbundle.has_orientation():
|
|
965
|
+
raise ValueError(f'Euler class not defined on {vbundle}')
|
|
966
|
+
if name is None:
|
|
967
|
+
name = 'e'
|
|
968
|
+
class_type = 'Pfaffian'
|
|
969
|
+
val = x
|
|
970
|
+
else:
|
|
971
|
+
raise ValueError(f'predefined class "{val}" unknown')
|
|
972
|
+
|
|
973
|
+
# turn symbolic expression into a polynomial via Taylor expansion
|
|
974
|
+
if isinstance(val, Expression):
|
|
975
|
+
x = val.default_variable()
|
|
976
|
+
P = PolynomialRing(base_ring, x)
|
|
977
|
+
|
|
978
|
+
if vbundle._field_type == 'real':
|
|
979
|
+
pow_range = dim // 4
|
|
980
|
+
elif vbundle._field_type == 'complex':
|
|
981
|
+
pow_range = dim // 2
|
|
982
|
+
else:
|
|
983
|
+
raise ValueError(f'field type of {vbundle} must be real or complex')
|
|
984
|
+
|
|
985
|
+
val = P(val.taylor(x, 0, pow_range))
|
|
986
|
+
|
|
987
|
+
# turn polynomial into a characteristic cohomology class via sequences
|
|
988
|
+
if isinstance(val, Polynomial):
|
|
989
|
+
if class_type is None:
|
|
990
|
+
raise TypeError(f'class_type must be stated if {val} '
|
|
991
|
+
f'is a polynomial')
|
|
992
|
+
n = self.ngens()
|
|
993
|
+
s = 0 # shift; important in case of Euler class generator
|
|
994
|
+
if self._algorithm is PontryaginEulerAlgorithm():
|
|
995
|
+
s = 1 # skip Euler class
|
|
996
|
+
n -= 1 # ignore Euler class
|
|
997
|
+
|
|
998
|
+
if class_type == 'additive':
|
|
999
|
+
sym = additive_sequence(val, vbundle._rank, n)
|
|
1000
|
+
elif class_type == 'multiplicative':
|
|
1001
|
+
sym = multiplicative_sequence(val, n)
|
|
1002
|
+
elif class_type == 'Pfaffian':
|
|
1003
|
+
P = val.parent()
|
|
1004
|
+
x = P.gen()
|
|
1005
|
+
val = (val(x) - val(-x)) / 2 # project to odd functions
|
|
1006
|
+
val = P([(-1) ** k * val[2 * k + 1] for k in range(n + 1)])
|
|
1007
|
+
sym = multiplicative_sequence(val, n)
|
|
1008
|
+
else:
|
|
1009
|
+
raise AttributeError('unknown class type')
|
|
1010
|
+
|
|
1011
|
+
d = {}
|
|
1012
|
+
w_vec = self._weighted_vectors
|
|
1013
|
+
for p, c in sym:
|
|
1014
|
+
vec = [0] * self.ngens()
|
|
1015
|
+
if class_type == 'Pfaffian':
|
|
1016
|
+
vec[0] = 1 # always multiply with e
|
|
1017
|
+
for i in p:
|
|
1018
|
+
vec[i - 1 + s] += 1
|
|
1019
|
+
key = w_vec(vec)
|
|
1020
|
+
d[key] = c
|
|
1021
|
+
res = self._from_dict(d)
|
|
1022
|
+
res.set_name(name=name, latex_name=latex_name)
|
|
1023
|
+
return res
|
|
1024
|
+
|
|
1025
|
+
# Nothing worked? Then something went wrong!
|
|
1026
|
+
raise ValueError(f'cannot convert {val} into an element of {self}')
|
|
1027
|
+
|
|
1028
|
+
def _repr_(self):
|
|
1029
|
+
r"""
|
|
1030
|
+
String representation of the object.
|
|
1031
|
+
|
|
1032
|
+
TESTS::
|
|
1033
|
+
|
|
1034
|
+
sage: M = Manifold(8, 'M')
|
|
1035
|
+
sage: TM = M.tangent_bundle()
|
|
1036
|
+
sage: CR = TM.characteristic_cohomology_class_ring()
|
|
1037
|
+
sage: CR._repr_()
|
|
1038
|
+
'Algebra of characteristic cohomology classes of the Tangent bundle
|
|
1039
|
+
TM over the 8-dimensional differentiable manifold M'
|
|
1040
|
+
sage: CR # indirect doctest
|
|
1041
|
+
Algebra of characteristic cohomology classes of the Tangent bundle
|
|
1042
|
+
TM over the 8-dimensional differentiable manifold M
|
|
1043
|
+
"""
|
|
1044
|
+
vbundle = self._vbundle
|
|
1045
|
+
repr = f'Algebra of characteristic cohomology classes of the {vbundle}'
|
|
1046
|
+
return repr
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
# *****************************************************************************
|
|
1050
|
+
# ALGORITHMS
|
|
1051
|
+
# *****************************************************************************
|
|
1052
|
+
|
|
1053
|
+
def multiplicative_sequence(q, n=None):
|
|
1054
|
+
r"""
|
|
1055
|
+
Turn the polynomial ``q`` into its multiplicative sequence.
|
|
1056
|
+
|
|
1057
|
+
Let `q` be a polynomial and `x_1, \ldots x_n` indeterminates. The
|
|
1058
|
+
*multiplicative sequence of* `q` is then given by the polynomials `K_j`
|
|
1059
|
+
|
|
1060
|
+
.. MATH::
|
|
1061
|
+
|
|
1062
|
+
\sum_{j=0}^n K_j(\sigma_1, \ldots, \sigma_j) z^j =
|
|
1063
|
+
\prod_{i=1}^{n} q(z \,x_i),
|
|
1064
|
+
|
|
1065
|
+
where `\sigma_i` is the `i`-th elementary symmetric polynomial in the
|
|
1066
|
+
indeterminates `x_i`.
|
|
1067
|
+
|
|
1068
|
+
INPUT:
|
|
1069
|
+
|
|
1070
|
+
- ``q`` -- polynomial to turn into its multiplicative sequence
|
|
1071
|
+
- ``n`` -- (default: ``None``) the highest order `n` of the sequence;
|
|
1072
|
+
if ``None``, the order of ``q`` is assumed
|
|
1073
|
+
|
|
1074
|
+
OUTPUT: a symmetric polynomial representing the multiplicative sequence
|
|
1075
|
+
|
|
1076
|
+
EXAMPLES::
|
|
1077
|
+
|
|
1078
|
+
sage: P.<x> = PolynomialRing(QQ)
|
|
1079
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import multiplicative_sequence
|
|
1080
|
+
sage: f = 1 + x - x^2
|
|
1081
|
+
sage: sym = multiplicative_sequence(f); sym
|
|
1082
|
+
e[] + e[1] - e[1, 1] + 3*e[2]
|
|
1083
|
+
|
|
1084
|
+
The maximal order of the result can be stated with ``n``::
|
|
1085
|
+
|
|
1086
|
+
sage: sym_5 = multiplicative_sequence(f, n=5); sym_5
|
|
1087
|
+
e[] + e[1] - e[1, 1] + 3*e[2] - e[2, 1] + e[2, 2] + 4*e[3] - 3*e[3, 1]
|
|
1088
|
+
+ e[3, 2] + 7*e[4] - 4*e[4, 1] + 11*e[5]
|
|
1089
|
+
"""
|
|
1090
|
+
from sage.combinat.partition import Partitions
|
|
1091
|
+
from sage.combinat.sf.sf import SymmetricFunctions
|
|
1092
|
+
from sage.misc.misc_c import prod
|
|
1093
|
+
|
|
1094
|
+
if n is None:
|
|
1095
|
+
n = q.degree()
|
|
1096
|
+
|
|
1097
|
+
R = q.parent().base_ring()
|
|
1098
|
+
Sym = SymmetricFunctions(R)
|
|
1099
|
+
m = Sym.m()
|
|
1100
|
+
|
|
1101
|
+
# Get the multiplicative sequence in the monomial basis:
|
|
1102
|
+
mon_pol = m._from_dict({p: prod(q[i] for i in p)
|
|
1103
|
+
for k in range(n + 1)
|
|
1104
|
+
for p in Partitions(k)})
|
|
1105
|
+
return Sym.e()(mon_pol)
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
def additive_sequence(q, k, n=None):
|
|
1109
|
+
r"""
|
|
1110
|
+
Turn the polynomial ``q`` into its additive sequence.
|
|
1111
|
+
|
|
1112
|
+
Let `q` be a polynomial and `x_1, \ldots x_n` indeterminates. The
|
|
1113
|
+
*additive sequence of* `q` is then given by the polynomials `Q_j`
|
|
1114
|
+
|
|
1115
|
+
.. MATH::
|
|
1116
|
+
|
|
1117
|
+
\sum_{j=0}^n Q_j(\sigma_1, \ldots, \sigma_j) z^j =
|
|
1118
|
+
\sum_{i=1}^{k} q(z \,x_i),
|
|
1119
|
+
|
|
1120
|
+
where `\sigma_i` is the `i`-th elementary symmetric polynomial in the
|
|
1121
|
+
indeterminates `x_i`.
|
|
1122
|
+
|
|
1123
|
+
INPUT:
|
|
1124
|
+
|
|
1125
|
+
- ``q`` -- polynomial to turn into its additive sequence
|
|
1126
|
+
- ``k`` -- maximal index `k` of the sum
|
|
1127
|
+
- ``n`` -- (default: ``None``) the highest order of the sequence `n`;
|
|
1128
|
+
if ``None``, the order of ``q`` is assumed
|
|
1129
|
+
|
|
1130
|
+
OUTPUT: a symmetric polynomial representing the additive sequence
|
|
1131
|
+
|
|
1132
|
+
EXAMPLES::
|
|
1133
|
+
|
|
1134
|
+
sage: P.<x> = PolynomialRing(QQ)
|
|
1135
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import additive_sequence
|
|
1136
|
+
sage: f = 1 + x - x^2
|
|
1137
|
+
sage: sym = additive_sequence(f, 2); sym
|
|
1138
|
+
2*e[] + e[1] - e[1, 1] + 2*e[2]
|
|
1139
|
+
|
|
1140
|
+
The maximal order of the result can be stated with ``n``::
|
|
1141
|
+
|
|
1142
|
+
sage: sym_1 = additive_sequence(f, 2, 1); sym_1
|
|
1143
|
+
2*e[] + e[1]
|
|
1144
|
+
"""
|
|
1145
|
+
from sage.combinat.partition import Partitions
|
|
1146
|
+
from sage.combinat.sf.sf import SymmetricFunctions
|
|
1147
|
+
|
|
1148
|
+
if n is None:
|
|
1149
|
+
n = q.degree()
|
|
1150
|
+
|
|
1151
|
+
R = q.parent().base_ring()
|
|
1152
|
+
Sym = SymmetricFunctions(R)
|
|
1153
|
+
m = Sym.m()
|
|
1154
|
+
|
|
1155
|
+
# Express the additive sequence in the monomial basis, the 0-th
|
|
1156
|
+
# order term must be treated separately; here comes ``rk`` into play:
|
|
1157
|
+
m_dict = {Partitions(0)([]): k * q[0]}
|
|
1158
|
+
m_dict.update({Partitions(k)([k]): q[k] for k in range(1, n + 1)})
|
|
1159
|
+
mon_pol = m._from_dict(m_dict)
|
|
1160
|
+
return Sym.e()(mon_pol)
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
def fast_wedge_power(form, n):
|
|
1164
|
+
r"""
|
|
1165
|
+
Return the wedge product power of `form` using a square-and-wedge
|
|
1166
|
+
algorithm.
|
|
1167
|
+
|
|
1168
|
+
INPUT:
|
|
1169
|
+
|
|
1170
|
+
- ``form`` -- a differential form
|
|
1171
|
+
- ``n`` -- nonnegative integer
|
|
1172
|
+
|
|
1173
|
+
EXAMPLES::
|
|
1174
|
+
|
|
1175
|
+
sage: M = Manifold(4, 'M')
|
|
1176
|
+
sage: X.<x,y,z,t> = M.chart()
|
|
1177
|
+
sage: omega = M.diff_form(2, name='omega')
|
|
1178
|
+
sage: omega[0,1] = t*y^2 + 2*x
|
|
1179
|
+
sage: omega[0,3] = z - 2*y
|
|
1180
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import fast_wedge_power
|
|
1181
|
+
sage: fast_wedge_power(omega, 0)
|
|
1182
|
+
Scalar field 1 on the 4-dimensional differentiable manifold M
|
|
1183
|
+
sage: fast_wedge_power(omega, 1)
|
|
1184
|
+
2-form omega on the 4-dimensional differentiable manifold M
|
|
1185
|
+
sage: fast_wedge_power(omega, 2)
|
|
1186
|
+
4-form omega∧omega on the 4-dimensional differentiable manifold M
|
|
1187
|
+
"""
|
|
1188
|
+
if n == 0:
|
|
1189
|
+
return form._domain._one_scalar_field
|
|
1190
|
+
elif n < 0:
|
|
1191
|
+
raise ValueError("'n' must be nonnegative")
|
|
1192
|
+
val = form
|
|
1193
|
+
while not (n & 1):
|
|
1194
|
+
val = val.wedge(val)
|
|
1195
|
+
n >>= 1
|
|
1196
|
+
|
|
1197
|
+
# Now multiply together the correct factors form^(2^i)
|
|
1198
|
+
res = val
|
|
1199
|
+
n >>= 1
|
|
1200
|
+
while n:
|
|
1201
|
+
val = val.wedge(val)
|
|
1202
|
+
if n & 1:
|
|
1203
|
+
res = val.wedge(res)
|
|
1204
|
+
n >>= 1
|
|
1205
|
+
|
|
1206
|
+
return res
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
class Algorithm_generic(SageObject):
|
|
1210
|
+
r"""
|
|
1211
|
+
Abstract algorithm class to compute the characteristic forms of the
|
|
1212
|
+
generators.
|
|
1213
|
+
|
|
1214
|
+
EXAMPLES::
|
|
1215
|
+
|
|
1216
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import Algorithm_generic
|
|
1217
|
+
sage: algorithm = Algorithm_generic()
|
|
1218
|
+
sage: algorithm.get
|
|
1219
|
+
Cached version of <function Algorithm_generic.get at 0x...>
|
|
1220
|
+
sage: algorithm.get_local
|
|
1221
|
+
Traceback (most recent call last):
|
|
1222
|
+
...
|
|
1223
|
+
NotImplementedError: <abstract method get_local at 0x...>
|
|
1224
|
+
sage: algorithm.get_gen_pow
|
|
1225
|
+
Cached version of <function Algorithm_generic.get_gen_pow at 0x...>
|
|
1226
|
+
"""
|
|
1227
|
+
@cached_method
|
|
1228
|
+
def get(self, nab):
|
|
1229
|
+
r"""
|
|
1230
|
+
Return the global characteristic forms of the generators w.r.t. a given
|
|
1231
|
+
connection.
|
|
1232
|
+
|
|
1233
|
+
The result is cached.
|
|
1234
|
+
|
|
1235
|
+
OUTPUT:
|
|
1236
|
+
|
|
1237
|
+
- a list containing the generator's global characteristic forms as
|
|
1238
|
+
instances of
|
|
1239
|
+
:class:`sage.manifolds.differentiable.diff_form.DiffForm`
|
|
1240
|
+
|
|
1241
|
+
EXAMPLES::
|
|
1242
|
+
|
|
1243
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
1244
|
+
sage: TM = M.tangent_bundle()
|
|
1245
|
+
sage: g = M.metric()
|
|
1246
|
+
sage: nab = g.connection()
|
|
1247
|
+
sage: nab.set_immutable()
|
|
1248
|
+
|
|
1249
|
+
::
|
|
1250
|
+
|
|
1251
|
+
sage: p = TM.characteristic_cohomology_class('Pontryagin')
|
|
1252
|
+
sage: p_form = p.get_form(nab); p_form # long time
|
|
1253
|
+
Mixed differential form p(TE^4, nabla_g) on the 4-dimensional
|
|
1254
|
+
Euclidean space E^4
|
|
1255
|
+
sage: p_form.display_expansion() # long time
|
|
1256
|
+
p(TE^4, nabla_g) = 1
|
|
1257
|
+
"""
|
|
1258
|
+
if isinstance(nab, AffineConnection):
|
|
1259
|
+
vbundle = nab._domain.tangent_bundle()
|
|
1260
|
+
elif isinstance(nab, BundleConnection):
|
|
1261
|
+
vbundle = nab._vbundle
|
|
1262
|
+
else:
|
|
1263
|
+
raise TypeError(f'{nab} must be a connection')
|
|
1264
|
+
dom = nab._domain
|
|
1265
|
+
res = [] # will be specified within first iteration
|
|
1266
|
+
for frame in dom._get_min_covering(nab._coefficients):
|
|
1267
|
+
cmat = [[nab.curvature_form(i, j, frame) for j in vbundle.irange()]
|
|
1268
|
+
for i in vbundle.irange()]
|
|
1269
|
+
res_loc = self.get_local(cmat)
|
|
1270
|
+
if not res:
|
|
1271
|
+
# until now, degrees of generators were unknown
|
|
1272
|
+
res = [dom.diff_form(loc_form.degree())
|
|
1273
|
+
for loc_form in res_loc]
|
|
1274
|
+
for form, loc_form in zip(res, res_loc):
|
|
1275
|
+
form.set_restriction(loc_form)
|
|
1276
|
+
# TODO: make `res` immutable?
|
|
1277
|
+
return res
|
|
1278
|
+
|
|
1279
|
+
@abstract_method
|
|
1280
|
+
def get_local(self, cmat):
|
|
1281
|
+
r"""
|
|
1282
|
+
Abstract method to get the local forms of the generators w.r.t. a given
|
|
1283
|
+
curvature form matrix ``cmat``.
|
|
1284
|
+
|
|
1285
|
+
OUTPUT: list containing the generator's local characteristic forms
|
|
1286
|
+
|
|
1287
|
+
ALGORITHM:
|
|
1288
|
+
|
|
1289
|
+
The inherited class determines the algorithm.
|
|
1290
|
+
|
|
1291
|
+
EXAMPLES:
|
|
1292
|
+
|
|
1293
|
+
4-dimensional Euclidean space::
|
|
1294
|
+
|
|
1295
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
1296
|
+
sage: TM = M.tangent_bundle()
|
|
1297
|
+
sage: g = M.metric()
|
|
1298
|
+
sage: nab = g.connection()
|
|
1299
|
+
sage: e = M.frames()[0] # select standard frame
|
|
1300
|
+
sage: cmat = [ [nab.curvature_form(i, j, e) # long time
|
|
1301
|
+
....: for j in TM.irange()]
|
|
1302
|
+
....: for i in TM.irange()]
|
|
1303
|
+
|
|
1304
|
+
Import the algorithm::
|
|
1305
|
+
|
|
1306
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginAlgorithm
|
|
1307
|
+
sage: algorithm = PontryaginAlgorithm()
|
|
1308
|
+
sage: [p1] = algorithm.get_local(cmat) # long time
|
|
1309
|
+
sage: p1.display() # long time
|
|
1310
|
+
0
|
|
1311
|
+
|
|
1312
|
+
A concrete implementation is given by a
|
|
1313
|
+
:class:`sage.misc.fast_methods.Singleton`::
|
|
1314
|
+
|
|
1315
|
+
sage: algorithm is PontryaginAlgorithm()
|
|
1316
|
+
True
|
|
1317
|
+
"""
|
|
1318
|
+
pass
|
|
1319
|
+
|
|
1320
|
+
@cached_method
|
|
1321
|
+
def get_gen_pow(self, nab, i, n):
|
|
1322
|
+
r"""
|
|
1323
|
+
Return the `n`-th power of the `i`-th generator's characteristic form
|
|
1324
|
+
w.r.t ``nab``.
|
|
1325
|
+
|
|
1326
|
+
The result is cached.
|
|
1327
|
+
|
|
1328
|
+
EXAMPLES::
|
|
1329
|
+
|
|
1330
|
+
sage: M = manifolds.EuclideanSpace(8)
|
|
1331
|
+
sage: TM = M.tangent_bundle()
|
|
1332
|
+
sage: g = M.metric()
|
|
1333
|
+
sage: nab = g.connection()
|
|
1334
|
+
sage: nab.set_immutable()
|
|
1335
|
+
|
|
1336
|
+
::
|
|
1337
|
+
|
|
1338
|
+
sage: A = TM.characteristic_cohomology_class('AHat')
|
|
1339
|
+
sage: A_form = A.get_form(nab); A_form # long time
|
|
1340
|
+
Mixed differential form A^(TE^8, nabla_g) on the 8-dimensional
|
|
1341
|
+
Euclidean space E^8
|
|
1342
|
+
sage: A_form.display_expansion() # long time
|
|
1343
|
+
A^(TE^8, nabla_g) = 1
|
|
1344
|
+
"""
|
|
1345
|
+
if n == 0:
|
|
1346
|
+
return nab._domain._one_scalar_field # no computation necessary
|
|
1347
|
+
return fast_wedge_power(self.get(nab)[i], n)
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
class ChernAlgorithm(Singleton, Algorithm_generic):
|
|
1351
|
+
r"""
|
|
1352
|
+
Algorithm class to generate Chern forms.
|
|
1353
|
+
|
|
1354
|
+
EXAMPLES:
|
|
1355
|
+
|
|
1356
|
+
Define a complex line bundle over a 2-dimensional manifold::
|
|
1357
|
+
|
|
1358
|
+
sage: M = Manifold(2, 'M', structure='Lorentzian')
|
|
1359
|
+
sage: X.<t,x> = M.chart()
|
|
1360
|
+
sage: E = M.vector_bundle(1, 'E', field='complex'); E
|
|
1361
|
+
Differentiable complex vector bundle E -> M of rank 1 over the base space
|
|
1362
|
+
2-dimensional Lorentzian manifold M
|
|
1363
|
+
sage: e = E.local_frame('e')
|
|
1364
|
+
sage: nab = E.bundle_connection('nabla^E', latex_name=r'\nabla^E')
|
|
1365
|
+
sage: omega = M.one_form(name='omega')
|
|
1366
|
+
sage: A = function('A')
|
|
1367
|
+
sage: nab.set_connection_form(0, 0)[1] = I*A(t)
|
|
1368
|
+
sage: nab[0, 0].display()
|
|
1369
|
+
connection (0,0) of bundle connection nabla^E w.r.t. Local frame
|
|
1370
|
+
(E|_M, (e_0)) = I*A(t) dx
|
|
1371
|
+
sage: nab.set_immutable()
|
|
1372
|
+
|
|
1373
|
+
Import the algorithm and apply ``nab`` to it::
|
|
1374
|
+
|
|
1375
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import ChernAlgorithm
|
|
1376
|
+
sage: algorithm = ChernAlgorithm()
|
|
1377
|
+
sage: algorithm.get(nab)
|
|
1378
|
+
[2-form on the 2-dimensional Lorentzian manifold M]
|
|
1379
|
+
sage: algorithm.get(nab)[0].display()
|
|
1380
|
+
1/2*d(A)/dt/pi dt∧dx
|
|
1381
|
+
|
|
1382
|
+
Check some equalities::
|
|
1383
|
+
|
|
1384
|
+
sage: cmat = [[nab.curvature_form(0, 0, e)]]
|
|
1385
|
+
sage: algorithm.get(nab)[0] == algorithm.get_local(cmat)[0] # bundle trivial
|
|
1386
|
+
True
|
|
1387
|
+
sage: algorithm.get_gen_pow(nab, 0, 1) == algorithm.get(nab)[0]
|
|
1388
|
+
True
|
|
1389
|
+
"""
|
|
1390
|
+
def get_local(self, cmat):
|
|
1391
|
+
r"""
|
|
1392
|
+
Return the local Chern forms w.r.t. a given curvature form matrix.
|
|
1393
|
+
|
|
1394
|
+
OUTPUT:
|
|
1395
|
+
|
|
1396
|
+
- a list containing the local characteristic Chern forms as
|
|
1397
|
+
instances of
|
|
1398
|
+
:class:`sage.manifolds.differentiable.diff_form.DiffForm`
|
|
1399
|
+
|
|
1400
|
+
ALGORITHM::
|
|
1401
|
+
|
|
1402
|
+
The algorithm is based on the Faddeev-LeVerrier algorithm for the
|
|
1403
|
+
characteristic polynomial.
|
|
1404
|
+
|
|
1405
|
+
EXAMPLES:
|
|
1406
|
+
|
|
1407
|
+
Define a complex line bundle over a 2-dimensional manifold::
|
|
1408
|
+
|
|
1409
|
+
sage: M = Manifold(2, 'M', structure='Lorentzian')
|
|
1410
|
+
sage: X.<t,x> = M.chart()
|
|
1411
|
+
sage: E = M.vector_bundle(1, 'E', field='complex'); E
|
|
1412
|
+
Differentiable complex vector bundle E -> M of rank 1 over the base
|
|
1413
|
+
space 2-dimensional Lorentzian manifold M
|
|
1414
|
+
sage: e = E.local_frame('e')
|
|
1415
|
+
sage: nab = E.bundle_connection('nabla^E', latex_name=r'\nabla^E')
|
|
1416
|
+
sage: omega = M.one_form(name='omega')
|
|
1417
|
+
sage: A = function('A')
|
|
1418
|
+
sage: nab.set_connection_form(0, 0)[1] = I*A(t)
|
|
1419
|
+
sage: nab[0, 0].display()
|
|
1420
|
+
connection (0,0) of bundle connection nabla^E w.r.t. Local frame
|
|
1421
|
+
(E|_M, (e_0)) = I*A(t) dx
|
|
1422
|
+
sage: cmat = [[nab.curvature_form(i, j, e) for j in E.irange()]
|
|
1423
|
+
....: for i in E.irange()]
|
|
1424
|
+
|
|
1425
|
+
Import the algorithm and apply ``cmat`` to it::
|
|
1426
|
+
|
|
1427
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import ChernAlgorithm
|
|
1428
|
+
sage: algorithm = ChernAlgorithm()
|
|
1429
|
+
sage: algorithm.get_local(cmat)
|
|
1430
|
+
[2-form on the 2-dimensional Lorentzian manifold M]
|
|
1431
|
+
"""
|
|
1432
|
+
from sage.symbolic.constants import I, pi
|
|
1433
|
+
|
|
1434
|
+
dom = cmat[0][0]._domain
|
|
1435
|
+
rk = len(cmat)
|
|
1436
|
+
dim = dom._dim
|
|
1437
|
+
ran = min(rk, dim // 2)
|
|
1438
|
+
if ran < 1:
|
|
1439
|
+
return [] # nothing to compute
|
|
1440
|
+
fac = I / (2 * pi)
|
|
1441
|
+
res = []
|
|
1442
|
+
m = cmat
|
|
1443
|
+
for k in range(1, ran):
|
|
1444
|
+
c = -sum(m[i][i] for i in range(rk)) / k
|
|
1445
|
+
res.append(fac * c)
|
|
1446
|
+
for i in range(rk):
|
|
1447
|
+
m[i][i] += c
|
|
1448
|
+
fac *= I / (2 * pi)
|
|
1449
|
+
m = [[sum(cmat[i][l].wedge(m[l][j]) for l in range(rk))
|
|
1450
|
+
for j in range(rk)] for i in range(rk)]
|
|
1451
|
+
res.append(-fac * sum(m[i][i] for i in range(rk)) / ran)
|
|
1452
|
+
return res
|
|
1453
|
+
|
|
1454
|
+
|
|
1455
|
+
class PontryaginAlgorithm(Singleton, Algorithm_generic):
|
|
1456
|
+
r"""
|
|
1457
|
+
Algorithm class to generate Pontryagin forms.
|
|
1458
|
+
|
|
1459
|
+
EXAMPLES:
|
|
1460
|
+
|
|
1461
|
+
5-dimensional Euclidean space::
|
|
1462
|
+
|
|
1463
|
+
sage: M = manifolds.EuclideanSpace(5)
|
|
1464
|
+
sage: g = M.metric()
|
|
1465
|
+
sage: nab = g.connection()
|
|
1466
|
+
sage: nab.set_immutable()
|
|
1467
|
+
|
|
1468
|
+
Import the algorithm::
|
|
1469
|
+
|
|
1470
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginAlgorithm
|
|
1471
|
+
sage: algorithm = PontryaginAlgorithm()
|
|
1472
|
+
sage: [p1] = algorithm.get(nab) # long time
|
|
1473
|
+
sage: p1.display() # long time
|
|
1474
|
+
0
|
|
1475
|
+
"""
|
|
1476
|
+
def get_local(self, cmat):
|
|
1477
|
+
r"""
|
|
1478
|
+
Return the local Pontryagin forms w.r.t. a given curvature form matrix.
|
|
1479
|
+
|
|
1480
|
+
OUTPUT: list containing the local characteristic Pontryagin forms
|
|
1481
|
+
|
|
1482
|
+
ALGORITHM::
|
|
1483
|
+
|
|
1484
|
+
The algorithm is based on the Faddeev-LeVerrier algorithm for the
|
|
1485
|
+
characteristic polynomial.
|
|
1486
|
+
|
|
1487
|
+
EXAMPLES:
|
|
1488
|
+
|
|
1489
|
+
5-dimensional Euclidean space::
|
|
1490
|
+
|
|
1491
|
+
sage: M = manifolds.EuclideanSpace(5)
|
|
1492
|
+
sage: TM = M.tangent_bundle()
|
|
1493
|
+
sage: g = M.metric()
|
|
1494
|
+
sage: nab = g.connection()
|
|
1495
|
+
sage: e = M.frames()[0] # select standard frame
|
|
1496
|
+
sage: cmat = [ [nab.curvature_form(i, j, e) # long time
|
|
1497
|
+
....: for j in TM.irange()]
|
|
1498
|
+
....: for i in TM.irange()]
|
|
1499
|
+
|
|
1500
|
+
Import the algorithm::
|
|
1501
|
+
|
|
1502
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginAlgorithm
|
|
1503
|
+
sage: algorithm = PontryaginAlgorithm()
|
|
1504
|
+
sage: [p1] = algorithm.get_local(cmat) # long time
|
|
1505
|
+
sage: p1.display() # long time
|
|
1506
|
+
0
|
|
1507
|
+
"""
|
|
1508
|
+
from sage.symbolic.constants import pi
|
|
1509
|
+
|
|
1510
|
+
dom = cmat[0][0]._domain
|
|
1511
|
+
rk = len(cmat)
|
|
1512
|
+
dim = dom._dim
|
|
1513
|
+
ran = min(rk // 2, dim // 4)
|
|
1514
|
+
if ran < 1:
|
|
1515
|
+
return [] # nothing to compute
|
|
1516
|
+
fac = 1 / (2 * pi) ** 2
|
|
1517
|
+
res = []
|
|
1518
|
+
m = cmat2 = [[sum(cmat[i][l].wedge(cmat[l][j])
|
|
1519
|
+
for l in range(rk))
|
|
1520
|
+
for j in range(rk)] for i in range(rk)]
|
|
1521
|
+
for k in range(1, ran):
|
|
1522
|
+
c = -sum(m[i][i] for i in range(rk)) / (2 * k)
|
|
1523
|
+
res.append(fac * c)
|
|
1524
|
+
for i in range(rk):
|
|
1525
|
+
m[i][i] += c
|
|
1526
|
+
fac *= 1 / (2 * pi) ** 2
|
|
1527
|
+
m = [[sum(cmat2[i][l].wedge(m[l][j]) for l in range(rk))
|
|
1528
|
+
for j in range(rk)] for i in range(rk)]
|
|
1529
|
+
res.append(-fac * sum(m[i][i] for i in range(rk)) / (2 * ran))
|
|
1530
|
+
return res
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
class EulerAlgorithm(Singleton, Algorithm_generic):
|
|
1534
|
+
r"""
|
|
1535
|
+
Algorithm class to generate Euler forms.
|
|
1536
|
+
|
|
1537
|
+
EXAMPLES:
|
|
1538
|
+
|
|
1539
|
+
Consider the 2-dimensional Euclidean space::
|
|
1540
|
+
|
|
1541
|
+
sage: M = manifolds.EuclideanSpace(2)
|
|
1542
|
+
sage: g = M.metric()
|
|
1543
|
+
sage: nab = g.connection()
|
|
1544
|
+
sage: nab.set_immutable()
|
|
1545
|
+
|
|
1546
|
+
Import the algorithm and apply ``nab`` to it::
|
|
1547
|
+
|
|
1548
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import EulerAlgorithm
|
|
1549
|
+
sage: algorithm = EulerAlgorithm()
|
|
1550
|
+
sage: algorithm.get(nab)
|
|
1551
|
+
[2-form on the Euclidean plane E^2]
|
|
1552
|
+
sage: algorithm.get(nab)[0].display()
|
|
1553
|
+
0
|
|
1554
|
+
"""
|
|
1555
|
+
@cached_method
|
|
1556
|
+
def get(self, nab):
|
|
1557
|
+
r"""
|
|
1558
|
+
Return the global characteristic forms of the generators w.r.t. a given
|
|
1559
|
+
connection.
|
|
1560
|
+
|
|
1561
|
+
INPUT:
|
|
1562
|
+
|
|
1563
|
+
- ``nab`` -- a metric connection `\nabla`
|
|
1564
|
+
|
|
1565
|
+
OUTPUT: list containing the global characteristic Euler form
|
|
1566
|
+
|
|
1567
|
+
ALGORITHM:
|
|
1568
|
+
|
|
1569
|
+
Assume that `\nabla` is compatible with the metric `g`, and let
|
|
1570
|
+
`(s_1, \ldots, s_n)` be any oriented frame. Denote by
|
|
1571
|
+
`G_s = (g(s_i, s_j))_{ij}` the metric tensor and let
|
|
1572
|
+
`\Omega_s` be the curvature form matrix of `\nabla` w.r.t. `s`.
|
|
1573
|
+
Then, we get:
|
|
1574
|
+
|
|
1575
|
+
.. MATH::
|
|
1576
|
+
|
|
1577
|
+
\left(G_s \cdot \Omega_s \right)_{ij} = g\!\left(R(.,.)s_i, s_j\right),
|
|
1578
|
+
|
|
1579
|
+
where `R` is the Riemannian curvature tensor w.r.t. `\nabla`.
|
|
1580
|
+
|
|
1581
|
+
The characteristic Euler form is now obtained by the expression
|
|
1582
|
+
|
|
1583
|
+
.. MATH::
|
|
1584
|
+
|
|
1585
|
+
\frac{1}{\sqrt{\left|\det(G_s)\right|}} \
|
|
1586
|
+
\mathrm{Pf}\!\left(G_s \cdot \frac{\Omega_s}{2 \pi}\right).
|
|
1587
|
+
|
|
1588
|
+
EXAMPLES:
|
|
1589
|
+
|
|
1590
|
+
Consider the 2-sphere::
|
|
1591
|
+
|
|
1592
|
+
sage: M.<x,y> = manifolds.Sphere(2, coordinates='stereographic')
|
|
1593
|
+
sage: g = M.metric() # long time
|
|
1594
|
+
sage: nab = g.connection() # long time
|
|
1595
|
+
sage: nab.set_immutable() # long time
|
|
1596
|
+
|
|
1597
|
+
Import the algorithm and apply ``nab`` to it::
|
|
1598
|
+
|
|
1599
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import EulerAlgorithm
|
|
1600
|
+
sage: algorithm = EulerAlgorithm()
|
|
1601
|
+
sage: algorithm.get(nab) # long time
|
|
1602
|
+
[2-form on the 2-sphere S^2 of radius 1 smoothly embedded in the
|
|
1603
|
+
Euclidean space E^3]
|
|
1604
|
+
sage: algorithm.get(nab)[0].display() # long time
|
|
1605
|
+
2/(pi + pi*x^4 + pi*y^4 + 2*pi*x^2 + 2*(pi + pi*x^2)*y^2) dx∧dy
|
|
1606
|
+
|
|
1607
|
+
REFERENCES:
|
|
1608
|
+
|
|
1609
|
+
- [Che1944]_
|
|
1610
|
+
- [Baer2020]_
|
|
1611
|
+
"""
|
|
1612
|
+
if not isinstance(nab, LeviCivitaConnection):
|
|
1613
|
+
raise TypeError('Euler forms are currently only supported for '
|
|
1614
|
+
'Levi-Civita connections')
|
|
1615
|
+
dom = nab._domain
|
|
1616
|
+
vbundle = dom.tangent_bundle()
|
|
1617
|
+
rk = vbundle._rank
|
|
1618
|
+
if not vbundle.has_orientation():
|
|
1619
|
+
raise ValueError('Euler forms can only be defined for orientable '
|
|
1620
|
+
'vector bundles')
|
|
1621
|
+
if rk % 2 != 0:
|
|
1622
|
+
raise ValueError('Euler forms are currently only supported for '
|
|
1623
|
+
'vector bundles with even rank')
|
|
1624
|
+
res = dom.diff_form(rk)
|
|
1625
|
+
g = nab._metric
|
|
1626
|
+
for frame in dom._get_min_covering(vbundle.orientation()):
|
|
1627
|
+
# (G_s * Ω_s)_ij = g(R(.,.)s_i, s_j)
|
|
1628
|
+
gcmat = [[sum(g[[frame, i, j]] * nab.curvature_form(j, k, frame)
|
|
1629
|
+
for j in vbundle.irange())
|
|
1630
|
+
for k in vbundle.irange()] for i in vbundle.irange()]
|
|
1631
|
+
[res_loc] = self.get_local(gcmat) # Pf(G_s * Ω_s) mod const.
|
|
1632
|
+
# e = 1 / sqrt(|det(G_s)|) * Pf(G_s * Ω_s) mod const.
|
|
1633
|
+
det = g.det(frame)
|
|
1634
|
+
if det.is_trivial_zero():
|
|
1635
|
+
raise ValueError(f'metric {g} must be non-degenerate')
|
|
1636
|
+
sqrt_det = det.abs().sqrt()
|
|
1637
|
+
res.set_restriction(res_loc / sqrt_det) # local Euler form
|
|
1638
|
+
# TODO: make `res` immutable?
|
|
1639
|
+
return [res]
|
|
1640
|
+
|
|
1641
|
+
def get_local(self, cmat):
|
|
1642
|
+
r"""
|
|
1643
|
+
Return the normalized Pfaffian w.r.t. a given curvature form matrix.
|
|
1644
|
+
|
|
1645
|
+
The normalization is given by the factor
|
|
1646
|
+
`\left(\frac{1}{2 \pi}\right)^{\frac{k}{2}}`, where `k` is the
|
|
1647
|
+
dimension of the curvature matrix.
|
|
1648
|
+
|
|
1649
|
+
OUTPUT: list containing the normalized Pfaffian of a given curvature form
|
|
1650
|
+
|
|
1651
|
+
.. NOTE::
|
|
1652
|
+
|
|
1653
|
+
In general, the output does *not* represent the local
|
|
1654
|
+
characteristic Euler form. The result is only guaranteed to be the
|
|
1655
|
+
local Euler form if ``cmat`` is given w.r.t. an orthonormal
|
|
1656
|
+
oriented frame. See :meth:`get` for details.
|
|
1657
|
+
|
|
1658
|
+
ALGORITHM::
|
|
1659
|
+
|
|
1660
|
+
The algorithm is based on the Bär-Faddeev-LeVerrier algorithm for
|
|
1661
|
+
the Pfaffian.
|
|
1662
|
+
|
|
1663
|
+
EXAMPLES:
|
|
1664
|
+
|
|
1665
|
+
Consider the 2-sphere::
|
|
1666
|
+
|
|
1667
|
+
sage: M.<th,phi> = manifolds.Sphere(2) # use spherical coordinates
|
|
1668
|
+
sage: TM = M.tangent_bundle()
|
|
1669
|
+
sage: g = M.metric()
|
|
1670
|
+
sage: nab = g.connection()
|
|
1671
|
+
sage: e = M.frames()[0] # select frame (opposite orientation!)
|
|
1672
|
+
sage: cmat = [[nab.curvature_form(i, j, e) for j in TM.irange()]
|
|
1673
|
+
....: for i in TM.irange()]
|
|
1674
|
+
|
|
1675
|
+
We need some preprocessing because the frame is not orthonormal::
|
|
1676
|
+
|
|
1677
|
+
sage: gcmat = [[sum(g[[e, i, j]] * nab.curvature_form(j, k, e)
|
|
1678
|
+
....: for j in TM.irange())
|
|
1679
|
+
....: for k in TM.irange()] for i in TM.irange()]
|
|
1680
|
+
|
|
1681
|
+
Now, ``gcmat`` is guaranteed to be skew-symmetric and can be applied
|
|
1682
|
+
to :meth:`get_local`. Then, the result must be normalized::
|
|
1683
|
+
|
|
1684
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import EulerAlgorithm
|
|
1685
|
+
sage: algorithm = EulerAlgorithm()
|
|
1686
|
+
sage: euler = -algorithm.get_local(gcmat)[0] / sqrt(g.det(frame=e))
|
|
1687
|
+
sage: euler.display()
|
|
1688
|
+
1/2*sin(th)/pi dth∧dphi
|
|
1689
|
+
"""
|
|
1690
|
+
from sage.symbolic.constants import pi
|
|
1691
|
+
|
|
1692
|
+
rk = len(cmat)
|
|
1693
|
+
ran = rk // 2
|
|
1694
|
+
m = a = [cmat[i].copy() for i in range(rk)]
|
|
1695
|
+
for i in range(0, rk, 2):
|
|
1696
|
+
m[i], m[i + 1] = m[i + 1], m[i] # swap entries
|
|
1697
|
+
for k in range(rk):
|
|
1698
|
+
m[k][i + 1] = -m[k][i + 1]
|
|
1699
|
+
for k in range(1, ran):
|
|
1700
|
+
e = -sum(m[i][i] for i in range(rk)) / (2 * k)
|
|
1701
|
+
for i in range(rk):
|
|
1702
|
+
m[i][i] += e
|
|
1703
|
+
m = [[sum(a[i][l].wedge(m[l][j]) for l in range(rk))
|
|
1704
|
+
for j in range(rk)] for i in range(rk)]
|
|
1705
|
+
e = -sum(m[i][i] for i in range(rk)) / (2 * ran) # Pfaffian mod sign
|
|
1706
|
+
e *= (-1 / (2 * pi)) ** ran # normalize
|
|
1707
|
+
return [e]
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
class PontryaginEulerAlgorithm(Singleton, Algorithm_generic):
|
|
1711
|
+
r"""
|
|
1712
|
+
Algorithm class to generate Euler and Pontryagin forms.
|
|
1713
|
+
|
|
1714
|
+
EXAMPLES:
|
|
1715
|
+
|
|
1716
|
+
6-dimensional Euclidean space::
|
|
1717
|
+
|
|
1718
|
+
sage: M = manifolds.EuclideanSpace(6)
|
|
1719
|
+
sage: g = M.metric()
|
|
1720
|
+
sage: nab = g.connection()
|
|
1721
|
+
sage: nab.set_immutable()
|
|
1722
|
+
|
|
1723
|
+
Import the algorithm::
|
|
1724
|
+
|
|
1725
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginEulerAlgorithm
|
|
1726
|
+
sage: algorithm = PontryaginEulerAlgorithm()
|
|
1727
|
+
sage: e_form, p1_form = algorithm.get(nab) # long time
|
|
1728
|
+
sage: e_form.display() # long time
|
|
1729
|
+
0
|
|
1730
|
+
sage: p1_form.display() # long time
|
|
1731
|
+
0
|
|
1732
|
+
"""
|
|
1733
|
+
|
|
1734
|
+
@cached_method
|
|
1735
|
+
def get(self, nab):
|
|
1736
|
+
r"""
|
|
1737
|
+
Return the global characteristic forms of the generators w.r.t. a given
|
|
1738
|
+
connection.
|
|
1739
|
+
|
|
1740
|
+
OUTPUT:
|
|
1741
|
+
|
|
1742
|
+
- a list containing the global Euler form in the first entry, and the
|
|
1743
|
+
global Pontryagin forms in the remaining entries.
|
|
1744
|
+
|
|
1745
|
+
EXAMPLES:
|
|
1746
|
+
|
|
1747
|
+
4-dimensional Euclidean space::
|
|
1748
|
+
|
|
1749
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
1750
|
+
sage: g = M.metric()
|
|
1751
|
+
sage: nab = g.connection()
|
|
1752
|
+
sage: nab.set_immutable()
|
|
1753
|
+
|
|
1754
|
+
Import the algorithm::
|
|
1755
|
+
|
|
1756
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginEulerAlgorithm
|
|
1757
|
+
sage: algorithm = PontryaginEulerAlgorithm()
|
|
1758
|
+
sage: algorithm.get(nab) # long time
|
|
1759
|
+
[4-form on the 4-dimensional Euclidean space E^4,
|
|
1760
|
+
4-form on the 4-dimensional Euclidean space E^4]
|
|
1761
|
+
"""
|
|
1762
|
+
return EulerAlgorithm().get(nab) + PontryaginAlgorithm().get(nab)
|
|
1763
|
+
|
|
1764
|
+
def get_local(self, cmat):
|
|
1765
|
+
r"""
|
|
1766
|
+
Return the local Euler and Pontryagin forms w.r.t. a given curvature
|
|
1767
|
+
form matrix.
|
|
1768
|
+
|
|
1769
|
+
.. NOTE::
|
|
1770
|
+
|
|
1771
|
+
Similar as for :class:`EulerAlgorithm`, the first entry only
|
|
1772
|
+
represents the Euler form if the curvature form matrix is chosen
|
|
1773
|
+
w.r.t. an orthonormal oriented frame. See
|
|
1774
|
+
:meth:`EulerAlgorithm.get_local` for details.
|
|
1775
|
+
|
|
1776
|
+
OUTPUT:
|
|
1777
|
+
|
|
1778
|
+
- a list containing the local Euler form in the first entry, and the
|
|
1779
|
+
local Pontryagin forms in the remaining entries.
|
|
1780
|
+
|
|
1781
|
+
EXAMPLES:
|
|
1782
|
+
|
|
1783
|
+
6-dimensional Euclidean space::
|
|
1784
|
+
|
|
1785
|
+
sage: M = manifolds.EuclideanSpace(6)
|
|
1786
|
+
sage: TM = M.tangent_bundle()
|
|
1787
|
+
sage: g = M.metric()
|
|
1788
|
+
sage: nab = g.connection()
|
|
1789
|
+
sage: e = M.frames()[0] # select the standard frame
|
|
1790
|
+
sage: cmat = [ [nab.curvature_form(i, j, e) # long time
|
|
1791
|
+
....: for j in TM.irange()]
|
|
1792
|
+
....: for i in TM.irange() ]
|
|
1793
|
+
|
|
1794
|
+
Import the algorithm::
|
|
1795
|
+
|
|
1796
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginEulerAlgorithm
|
|
1797
|
+
sage: algorithm = PontryaginEulerAlgorithm()
|
|
1798
|
+
sage: e, p1 = algorithm.get_local(cmat) # long time
|
|
1799
|
+
sage: e.display() # long time
|
|
1800
|
+
0
|
|
1801
|
+
sage: p1.display() # long time
|
|
1802
|
+
0
|
|
1803
|
+
"""
|
|
1804
|
+
res = EulerAlgorithm().get_local(cmat) # first entry is Euler class
|
|
1805
|
+
res += PontryaginAlgorithm().get_local(cmat) # rest Pontryagin
|
|
1806
|
+
return res
|
|
1807
|
+
|
|
1808
|
+
@cached_method
|
|
1809
|
+
def get_gen_pow(self, nab, i, n):
|
|
1810
|
+
r"""
|
|
1811
|
+
Return the `n`-th power of the `i`-th generator w.r.t ``nab``.
|
|
1812
|
+
|
|
1813
|
+
The result is cached.
|
|
1814
|
+
|
|
1815
|
+
EXAMPLES:
|
|
1816
|
+
|
|
1817
|
+
4-dimensional Euclidean space::
|
|
1818
|
+
|
|
1819
|
+
sage: M = manifolds.EuclideanSpace(4)
|
|
1820
|
+
sage: TM = M.tangent_bundle()
|
|
1821
|
+
sage: g = M.metric()
|
|
1822
|
+
sage: nab = g.connection()
|
|
1823
|
+
sage: nab.set_immutable()
|
|
1824
|
+
|
|
1825
|
+
Import the algorithm::
|
|
1826
|
+
|
|
1827
|
+
sage: from sage.manifolds.differentiable.characteristic_cohomology_class import PontryaginEulerAlgorithm
|
|
1828
|
+
sage: algorithm = PontryaginEulerAlgorithm()
|
|
1829
|
+
sage: e = algorithm.get_gen_pow(nab, 0, 1) # Euler, long time
|
|
1830
|
+
sage: e.display() # long time
|
|
1831
|
+
0
|
|
1832
|
+
sage: p1_pow2 = algorithm.get_gen_pow(nab, 1, 2) # 1st Pontryagin squared, long time
|
|
1833
|
+
sage: p1_pow2 # long time
|
|
1834
|
+
8-form zero on the 4-dimensional Euclidean space E^4
|
|
1835
|
+
"""
|
|
1836
|
+
if n == 0:
|
|
1837
|
+
return nab._domain._one_scalar_field # no computation necessary
|
|
1838
|
+
if i == 0:
|
|
1839
|
+
return fast_wedge_power(EulerAlgorithm().get(nab)[0], n)
|
|
1840
|
+
return fast_wedge_power(PontryaginAlgorithm().get(nab)[i - 1], n)
|