passagemath-symbolics 10.6.37__cp314-cp314t-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.6.37.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.37.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.37.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.37.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-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-314t-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -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 +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -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 +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -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 +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -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 +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -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 +1520 -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 +910 -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 +1728 -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 +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -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 +1342 -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-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -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 +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -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 +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,1029 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
"""
|
|
3
|
+
Symbolic sparse matrices
|
|
4
|
+
|
|
5
|
+
EXAMPLES::
|
|
6
|
+
|
|
7
|
+
sage: matrix(SR, 2, 2, range(4), sparse=True)
|
|
8
|
+
[0 1]
|
|
9
|
+
[2 3]
|
|
10
|
+
sage: matrix(SR, 2, 2, var('t'), sparse=True)
|
|
11
|
+
[t 0]
|
|
12
|
+
[0 t]
|
|
13
|
+
|
|
14
|
+
Arithmetic::
|
|
15
|
+
|
|
16
|
+
sage: -matrix(SR, 2, range(4), sparse=True)
|
|
17
|
+
[ 0 -1]
|
|
18
|
+
[-2 -3]
|
|
19
|
+
sage: m = matrix(SR, 2, [1..4], sparse=True); sqrt(2)*m
|
|
20
|
+
[ sqrt(2) 2*sqrt(2)]
|
|
21
|
+
[3*sqrt(2) 4*sqrt(2)]
|
|
22
|
+
sage: m = matrix(SR, 4, [1..4^2], sparse=True)
|
|
23
|
+
sage: m * m
|
|
24
|
+
[ 90 100 110 120]
|
|
25
|
+
[202 228 254 280]
|
|
26
|
+
[314 356 398 440]
|
|
27
|
+
[426 484 542 600]
|
|
28
|
+
|
|
29
|
+
sage: m = matrix(SR, 3, [1, 2, 3], sparse=True); m
|
|
30
|
+
[1]
|
|
31
|
+
[2]
|
|
32
|
+
[3]
|
|
33
|
+
sage: m.transpose() * m
|
|
34
|
+
[14]
|
|
35
|
+
|
|
36
|
+
Computing inverses::
|
|
37
|
+
|
|
38
|
+
sage: M = matrix(SR, 2, var('a,b,c,d'), sparse=True)
|
|
39
|
+
sage: ~M
|
|
40
|
+
[1/a - b*c/(a^2*(b*c/a - d)) b/(a*(b*c/a - d))]
|
|
41
|
+
[ c/(a*(b*c/a - d)) -1/(b*c/a - d)]
|
|
42
|
+
sage: (~M*M).simplify_rational()
|
|
43
|
+
[1 0]
|
|
44
|
+
[0 1]
|
|
45
|
+
sage: M = matrix(SR, 3, 3, range(9), sparse=True) - var('t')
|
|
46
|
+
sage: (~M * M).simplify_rational()
|
|
47
|
+
[1 0 0]
|
|
48
|
+
[0 1 0]
|
|
49
|
+
[0 0 1]
|
|
50
|
+
|
|
51
|
+
sage: matrix(SR, 1, 1, 1, sparse=True).inverse()
|
|
52
|
+
[1]
|
|
53
|
+
sage: matrix(SR, 0, 0, sparse=True).inverse()
|
|
54
|
+
[]
|
|
55
|
+
sage: matrix(SR, 3, 0, sparse=True).inverse()
|
|
56
|
+
Traceback (most recent call last):
|
|
57
|
+
...
|
|
58
|
+
ArithmeticError: self must be a square matrix
|
|
59
|
+
|
|
60
|
+
Transposition::
|
|
61
|
+
|
|
62
|
+
sage: m = matrix(SR, 2, [sqrt(2), -1, pi, e^2], sparse=True)
|
|
63
|
+
sage: m.transpose()
|
|
64
|
+
[sqrt(2) pi]
|
|
65
|
+
[ -1 e^2]
|
|
66
|
+
|
|
67
|
+
``.T`` is a convenient shortcut for the transpose::
|
|
68
|
+
|
|
69
|
+
sage: m.T
|
|
70
|
+
[sqrt(2) pi]
|
|
71
|
+
[ -1 e^2]
|
|
72
|
+
|
|
73
|
+
Test pickling::
|
|
74
|
+
|
|
75
|
+
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True); m
|
|
76
|
+
[sqrt(2) 3]
|
|
77
|
+
[ pi e]
|
|
78
|
+
sage: TestSuite(m).run()
|
|
79
|
+
|
|
80
|
+
Comparison::
|
|
81
|
+
|
|
82
|
+
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
|
|
83
|
+
sage: m == m
|
|
84
|
+
True
|
|
85
|
+
sage: m != 3
|
|
86
|
+
True
|
|
87
|
+
sage: m = matrix(SR,2,[1..4], sparse=True); n = m^2
|
|
88
|
+
sage: (exp(m+n) - exp(m)*exp(n)).simplify_rational() == 0 # indirect test
|
|
89
|
+
True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
Determinant::
|
|
93
|
+
|
|
94
|
+
sage: M = matrix(SR, 2, 2, [x,2,3,4], sparse=True)
|
|
95
|
+
sage: M.determinant()
|
|
96
|
+
4*x - 6
|
|
97
|
+
sage: M = matrix(SR, 3,3,range(9), sparse=True)
|
|
98
|
+
sage: M.det()
|
|
99
|
+
0
|
|
100
|
+
sage: t = var('t')
|
|
101
|
+
sage: M = matrix(SR, 2, 2, [cos(t), sin(t), -sin(t), cos(t)], sparse=True)
|
|
102
|
+
sage: M.det()
|
|
103
|
+
cos(t)^2 + sin(t)^2
|
|
104
|
+
sage: M = matrix([[sqrt(x),0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]], sparse=True)
|
|
105
|
+
sage: det(M)
|
|
106
|
+
sqrt(x)
|
|
107
|
+
|
|
108
|
+
Permanents::
|
|
109
|
+
|
|
110
|
+
sage: M = matrix(SR, 2, 2, [x,2,3,4], sparse=True)
|
|
111
|
+
sage: M.permanent()
|
|
112
|
+
4*x + 6
|
|
113
|
+
|
|
114
|
+
Rank::
|
|
115
|
+
|
|
116
|
+
sage: M = matrix(SR, 5, 5, range(25), sparse=True)
|
|
117
|
+
sage: M.rank()
|
|
118
|
+
2
|
|
119
|
+
sage: M = matrix(SR, 5, 5, range(25), sparse=True) - var('t')
|
|
120
|
+
sage: M.rank()
|
|
121
|
+
5
|
|
122
|
+
|
|
123
|
+
.. warning::
|
|
124
|
+
|
|
125
|
+
:meth:`rank` may return the wrong answer if it cannot determine that a
|
|
126
|
+
matrix element that is equivalent to zero is indeed so.
|
|
127
|
+
|
|
128
|
+
Copying symbolic matrices::
|
|
129
|
+
|
|
130
|
+
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
|
|
131
|
+
sage: n = copy(m)
|
|
132
|
+
sage: n[0,0] = sin(1)
|
|
133
|
+
sage: m
|
|
134
|
+
[sqrt(2) 3]
|
|
135
|
+
[ pi e]
|
|
136
|
+
sage: n
|
|
137
|
+
[sin(1) 3]
|
|
138
|
+
[ pi e]
|
|
139
|
+
|
|
140
|
+
Conversion to Maxima::
|
|
141
|
+
|
|
142
|
+
sage: m = matrix(SR, 2, [sqrt(2), 3, pi, e], sparse=True)
|
|
143
|
+
sage: m._maxima_()
|
|
144
|
+
matrix([sqrt(2),3],[%pi,%e])
|
|
145
|
+
|
|
146
|
+
TESTS:
|
|
147
|
+
|
|
148
|
+
Check that :issue:`12778` is fixed::
|
|
149
|
+
|
|
150
|
+
sage: M = Matrix([[1, 0.9, 1/5, x^2], [2, 1.9, 2/5, x^3], [3, 2.9, 3/5, x^4]], sparse=True); M
|
|
151
|
+
[ 1 0.900000000000000 1/5 x^2]
|
|
152
|
+
[ 2 1.90000000000000 2/5 x^3]
|
|
153
|
+
[ 3 2.90000000000000 3/5 x^4]
|
|
154
|
+
sage: parent(M)
|
|
155
|
+
Full MatrixSpace of 3 by 4 sparse matrices over Symbolic Ring
|
|
156
|
+
|
|
157
|
+
Check that :issue:`35653` is fixed::
|
|
158
|
+
|
|
159
|
+
sage: diagonal_matrix([x]).inverse()
|
|
160
|
+
[1/x]
|
|
161
|
+
sage: M = MatrixSpace(SR,2,2,sparse=True)
|
|
162
|
+
sage: M([[x,0],[0,x]]).inverse()
|
|
163
|
+
[1/x 0]
|
|
164
|
+
[ 0 1/x]
|
|
165
|
+
"""
|
|
166
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
167
|
+
from sage.structure.factorization import Factorization
|
|
168
|
+
|
|
169
|
+
from sage.matrix.matrix_generic_sparse cimport Matrix_generic_sparse
|
|
170
|
+
from sage.matrix.constructor import matrix
|
|
171
|
+
|
|
172
|
+
cdef maxima
|
|
173
|
+
|
|
174
|
+
from sage.calculus.calculus import maxima
|
|
175
|
+
|
|
176
|
+
cdef class Matrix_symbolic_sparse(Matrix_generic_sparse):
|
|
177
|
+
def echelonize(self, **kwds):
|
|
178
|
+
"""
|
|
179
|
+
Echelonize using the classical algorithm.
|
|
180
|
+
|
|
181
|
+
TESTS::
|
|
182
|
+
|
|
183
|
+
sage: m = matrix([[cos(pi/5), sin(pi/5)], [-sin(pi/5), cos(pi/5)]], sparse=True)
|
|
184
|
+
sage: m.echelonize(); m
|
|
185
|
+
[1 0]
|
|
186
|
+
[0 1]
|
|
187
|
+
"""
|
|
188
|
+
return super().echelonize(algorithm='classical', **kwds)
|
|
189
|
+
|
|
190
|
+
def eigenvalues(self, extend=True):
|
|
191
|
+
"""
|
|
192
|
+
Compute the eigenvalues by solving the characteristic
|
|
193
|
+
polynomial in maxima.
|
|
194
|
+
|
|
195
|
+
The argument ``extend`` is ignored but kept for compatibility with
|
|
196
|
+
other matrix classes.
|
|
197
|
+
|
|
198
|
+
EXAMPLES::
|
|
199
|
+
|
|
200
|
+
sage: a=matrix(SR,[[1,2],[3,4]], sparse=True)
|
|
201
|
+
sage: a.eigenvalues()
|
|
202
|
+
[-1/2*sqrt(33) + 5/2, 1/2*sqrt(33) + 5/2]
|
|
203
|
+
|
|
204
|
+
TESTS:
|
|
205
|
+
|
|
206
|
+
Check for :issue:`31700`::
|
|
207
|
+
|
|
208
|
+
sage: m = matrix([[cos(pi/5), sin(pi/5)], [-sin(pi/5), cos(pi/5)]], sparse=True)
|
|
209
|
+
sage: t = linear_transformation(m)
|
|
210
|
+
sage: t.eigenvalues()
|
|
211
|
+
[1/4*sqrt(5) - 1/4*sqrt(2*sqrt(5) - 10) + 1/4,
|
|
212
|
+
1/4*sqrt(5) + 1/4*sqrt(2*sqrt(5) - 10) + 1/4]
|
|
213
|
+
"""
|
|
214
|
+
maxima_evals = self._maxima_(maxima).eigenvalues()._sage_()
|
|
215
|
+
if not len(maxima_evals):
|
|
216
|
+
raise ArithmeticError("could not determine eigenvalues exactly using symbolic matrices; try using a different type of matrix via self.change_ring(), if possible")
|
|
217
|
+
return sum([[ev] * int(mult) for ev, mult in zip(*maxima_evals)], [])
|
|
218
|
+
|
|
219
|
+
def eigenvectors_left(self, other=None):
|
|
220
|
+
r"""
|
|
221
|
+
Compute the left eigenvectors of a matrix.
|
|
222
|
+
|
|
223
|
+
INPUT:
|
|
224
|
+
|
|
225
|
+
- ``other`` -- a square matrix `B` (default: ``None``) in a generalized
|
|
226
|
+
eigenvalue problem; if ``None``, an ordinary eigenvalue problem is
|
|
227
|
+
solved (currently supported only if the base ring of ``self`` is
|
|
228
|
+
``RDF`` or ``CDF``)
|
|
229
|
+
|
|
230
|
+
OUTPUT:
|
|
231
|
+
|
|
232
|
+
For each distinct eigenvalue, returns a list of the form (e,V,n)
|
|
233
|
+
where e is the eigenvalue, V is a list of eigenvectors forming a
|
|
234
|
+
basis for the corresponding left eigenspace, and n is the
|
|
235
|
+
algebraic multiplicity of the eigenvalue.
|
|
236
|
+
|
|
237
|
+
EXAMPLES::
|
|
238
|
+
|
|
239
|
+
sage: A = matrix(SR,3,3,range(9), sparse=True); A
|
|
240
|
+
[0 1 2]
|
|
241
|
+
[3 4 5]
|
|
242
|
+
[6 7 8]
|
|
243
|
+
sage: es = A.eigenvectors_left(); es
|
|
244
|
+
[(-3*sqrt(6) + 6, [(1, -1/5*sqrt(6) + 4/5, -2/5*sqrt(6) + 3/5)], 1),
|
|
245
|
+
(3*sqrt(6) + 6, [(1, 1/5*sqrt(6) + 4/5, 2/5*sqrt(6) + 3/5)], 1),
|
|
246
|
+
(0, [(1, -2, 1)], 1)]
|
|
247
|
+
sage: eval, [evec], mult = es[0]
|
|
248
|
+
sage: delta = eval*evec - evec*A
|
|
249
|
+
sage: abs(abs(delta)) < 1e-10
|
|
250
|
+
3/5*sqrt(((2*sqrt(6) - 3)*(sqrt(6) - 2) + 7*sqrt(6) - 18)^2 + ((sqrt(6) - 2)*(sqrt(6) - 4) + 6*sqrt(6) - 14)^2) < (1.00000000000000e-10)
|
|
251
|
+
sage: abs(abs(delta)).n() < 1e-10
|
|
252
|
+
True
|
|
253
|
+
|
|
254
|
+
::
|
|
255
|
+
|
|
256
|
+
sage: A = matrix(SR, 2, 2, var('a,b,c,d'), sparse=True)
|
|
257
|
+
sage: A.eigenvectors_left()
|
|
258
|
+
[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d + sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1)]
|
|
259
|
+
sage: es = A.eigenvectors_left(); es
|
|
260
|
+
[(1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d + sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1), (1/2*a + 1/2*d + 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2), [(1, -1/2*(a - d - sqrt(a^2 + 4*b*c - 2*a*d + d^2))/c)], 1)]
|
|
261
|
+
sage: eval, [evec], mult = es[0]
|
|
262
|
+
sage: delta = eval*evec - evec*A
|
|
263
|
+
sage: delta.apply_map(lambda x: x.full_simplify())
|
|
264
|
+
(0, 0)
|
|
265
|
+
|
|
266
|
+
This routine calls Maxima and can struggle with even small matrices
|
|
267
|
+
with a few variables, such as a `3\times 3` matrix with three variables.
|
|
268
|
+
However, if the entries are integers or rationals it can produce exact
|
|
269
|
+
values in a reasonable time. These examples create 0-1 matrices from
|
|
270
|
+
the adjacency matrices of graphs and illustrate how the format and type
|
|
271
|
+
of the results differ when the base ring changes. First for matrices
|
|
272
|
+
over the rational numbers, then the same matrix but viewed as a symbolic
|
|
273
|
+
matrix. ::
|
|
274
|
+
|
|
275
|
+
sage: # needs sage.graphs
|
|
276
|
+
sage: G = graphs.CycleGraph(5)
|
|
277
|
+
sage: am = G.adjacency_matrix(sparse=True)
|
|
278
|
+
sage: spectrum = am.eigenvectors_left()
|
|
279
|
+
sage: qqbar_evalue = spectrum[2][0]
|
|
280
|
+
sage: type(qqbar_evalue)
|
|
281
|
+
<class 'sage.rings.qqbar.AlgebraicNumber'>
|
|
282
|
+
sage: qqbar_evalue
|
|
283
|
+
0.618033988749895?
|
|
284
|
+
sage: am = G.adjacency_matrix(sparse=True).change_ring(SR)
|
|
285
|
+
sage: spectrum = am.eigenvectors_left()
|
|
286
|
+
sage: symbolic_evalue = spectrum[2][0]
|
|
287
|
+
sage: type(symbolic_evalue)
|
|
288
|
+
<class 'sage.symbolic.expression.Expression'>
|
|
289
|
+
sage: symbolic_evalue
|
|
290
|
+
1/2*sqrt(5) - 1/2
|
|
291
|
+
sage: bool(qqbar_evalue == symbolic_evalue)
|
|
292
|
+
True
|
|
293
|
+
|
|
294
|
+
A slightly larger matrix with a "nice" spectrum. ::
|
|
295
|
+
|
|
296
|
+
sage: # needs sage.graphs
|
|
297
|
+
sage: G = graphs.CycleGraph(6)
|
|
298
|
+
sage: am = G.adjacency_matrix(sparse=True).change_ring(SR)
|
|
299
|
+
sage: am.eigenvectors_left()
|
|
300
|
+
[(-1, [(1, 0, -1, 1, 0, -1), (0, 1, -1, 0, 1, -1)], 2), (1, [(1, 0, -1, -1, 0, 1), (0, 1, 1, 0, -1, -1)], 2), (-2, [(1, -1, 1, -1, 1, -1)], 1), (2, [(1, 1, 1, 1, 1, 1)], 1)]
|
|
301
|
+
|
|
302
|
+
TESTS::
|
|
303
|
+
|
|
304
|
+
sage: A = matrix(SR, [[1, 2], [3, 4]], sparse=True)
|
|
305
|
+
sage: B = matrix(SR, [[1, 1], [0, 1]], sparse=True)
|
|
306
|
+
sage: A.eigenvectors_left(B)
|
|
307
|
+
Traceback (most recent call last):
|
|
308
|
+
...
|
|
309
|
+
NotImplementedError: generalized eigenvector decomposition is
|
|
310
|
+
implemented for RDF and CDF, but not for Symbolic Ring
|
|
311
|
+
|
|
312
|
+
Check that :issue:`23332` is fixed::
|
|
313
|
+
|
|
314
|
+
sage: matrix([[x, x^2], [1, 0]], sparse=True).eigenvectors_left()
|
|
315
|
+
[(-1/2*x*(sqrt(5) - 1), [(1, -1/2*x*(sqrt(5) + 1))], 1),
|
|
316
|
+
(1/2*x*(sqrt(5) + 1), [(1, 1/2*x*(sqrt(5) - 1))], 1)]
|
|
317
|
+
"""
|
|
318
|
+
if other is not None:
|
|
319
|
+
raise NotImplementedError('generalized eigenvector decomposition '
|
|
320
|
+
'is implemented for RDF and CDF, but '
|
|
321
|
+
'not for %s' % self.base_ring())
|
|
322
|
+
|
|
323
|
+
from sage.modules.free_module_element import vector
|
|
324
|
+
from sage.rings.integer_ring import ZZ
|
|
325
|
+
|
|
326
|
+
[evals, mults], evecs = self.transpose()._maxima_(maxima).eigenvectors()._sage_()
|
|
327
|
+
result = []
|
|
328
|
+
for e, evec, m in zip(evals, evecs, mults):
|
|
329
|
+
result.append((e, [vector(v) for v in evec], ZZ(m)))
|
|
330
|
+
|
|
331
|
+
return result
|
|
332
|
+
|
|
333
|
+
def eigenvectors_right(self, other=None):
|
|
334
|
+
r"""
|
|
335
|
+
Compute the right eigenvectors of a matrix.
|
|
336
|
+
|
|
337
|
+
INPUT:
|
|
338
|
+
|
|
339
|
+
- ``other`` -- a square matrix `B` (default: ``None``) in a generalized
|
|
340
|
+
eigenvalue problem; if ``None``, an ordinary eigenvalue problem is
|
|
341
|
+
solved (currently supported only if the base ring of ``self`` is
|
|
342
|
+
``RDF`` or ``CDF``)
|
|
343
|
+
|
|
344
|
+
OUTPUT:
|
|
345
|
+
|
|
346
|
+
For each distinct eigenvalue, returns a list of the form (e,V,n)
|
|
347
|
+
where e is the eigenvalue, V is a list of eigenvectors forming a
|
|
348
|
+
basis for the corresponding right eigenspace, and n is the
|
|
349
|
+
algebraic multiplicity of the eigenvalue.
|
|
350
|
+
|
|
351
|
+
EXAMPLES::
|
|
352
|
+
|
|
353
|
+
sage: A = matrix(SR,2,2,range(4), sparse=True); A
|
|
354
|
+
[0 1]
|
|
355
|
+
[2 3]
|
|
356
|
+
sage: right = A.eigenvectors_right(); right
|
|
357
|
+
[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2, [(1, 1/2*sqrt(17) + 3/2)], 1)]
|
|
358
|
+
|
|
359
|
+
The right eigenvectors are nothing but the left eigenvectors of the
|
|
360
|
+
transpose matrix::
|
|
361
|
+
|
|
362
|
+
sage: left = A.transpose().eigenvectors_left(); left
|
|
363
|
+
[(-1/2*sqrt(17) + 3/2, [(1, -1/2*sqrt(17) + 3/2)], 1), (1/2*sqrt(17) + 3/2, [(1, 1/2*sqrt(17) + 3/2)], 1)]
|
|
364
|
+
sage: right[0][1] == left[0][1]
|
|
365
|
+
True
|
|
366
|
+
|
|
367
|
+
TESTS::
|
|
368
|
+
|
|
369
|
+
sage: A = matrix(SR, [[1, 2], [3, 4]], sparse=True)
|
|
370
|
+
sage: B = matrix(SR, [[1, 1], [0, 1]], sparse=True)
|
|
371
|
+
sage: A.eigenvectors_right(B)
|
|
372
|
+
Traceback (most recent call last):
|
|
373
|
+
...
|
|
374
|
+
NotImplementedError: generalized eigenvector decomposition is
|
|
375
|
+
implemented for RDF and CDF, but not for Symbolic Ring
|
|
376
|
+
|
|
377
|
+
Check that :issue:`23332` is fixed::
|
|
378
|
+
|
|
379
|
+
sage: matrix([[x, x^2], [1, 0]], sparse=True).eigenvectors_right()
|
|
380
|
+
[(-1/2*x*(sqrt(5) - 1), [(1, -1/2*(sqrt(5) + 1)/x)], 1),
|
|
381
|
+
(1/2*x*(sqrt(5) + 1), [(1, 1/2*(sqrt(5) - 1)/x)], 1)]
|
|
382
|
+
"""
|
|
383
|
+
return self.transpose().eigenvectors_left(other=other)
|
|
384
|
+
|
|
385
|
+
def exp(self):
|
|
386
|
+
r"""
|
|
387
|
+
Return the matrix exponential of this matrix `X`, which is the matrix
|
|
388
|
+
|
|
389
|
+
.. MATH::
|
|
390
|
+
|
|
391
|
+
e^X = \sum_{k=0}^{\infty} \frac{X^k}{k!}.
|
|
392
|
+
|
|
393
|
+
This function depends on maxima's matrix exponentiation
|
|
394
|
+
function, which does not deal well with floating point
|
|
395
|
+
numbers. If the matrix has floating point numbers, they will
|
|
396
|
+
be rounded automatically to rational numbers during the
|
|
397
|
+
computation.
|
|
398
|
+
|
|
399
|
+
EXAMPLES::
|
|
400
|
+
|
|
401
|
+
sage: m = matrix(SR,2, [0,x,x,0], sparse=True); m
|
|
402
|
+
[0 x]
|
|
403
|
+
[x 0]
|
|
404
|
+
sage: m.exp()
|
|
405
|
+
[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)]
|
|
406
|
+
[1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]
|
|
407
|
+
sage: exp(m)
|
|
408
|
+
[1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x)]
|
|
409
|
+
[1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x)]
|
|
410
|
+
|
|
411
|
+
Exponentiation works on 0x0 and 1x1 matrices, but the 1x1 example
|
|
412
|
+
requires a patched version of maxima (:issue:`32898`) for now::
|
|
413
|
+
|
|
414
|
+
sage: m = matrix(SR,0,[], sparse=True); m
|
|
415
|
+
[]
|
|
416
|
+
sage: m.exp()
|
|
417
|
+
[]
|
|
418
|
+
sage: m = matrix(SR,1,[2], sparse=True); m
|
|
419
|
+
[2]
|
|
420
|
+
sage: m.exp() # not tested, requires patched maxima
|
|
421
|
+
[e^2]
|
|
422
|
+
|
|
423
|
+
Commuting matrices `m, n` have the property that
|
|
424
|
+
`e^{m+n} = e^m e^n` (but non-commuting matrices need not)::
|
|
425
|
+
|
|
426
|
+
sage: m = matrix(SR,2,[1..4], sparse=True); n = m^2
|
|
427
|
+
sage: m*n
|
|
428
|
+
[ 37 54]
|
|
429
|
+
[ 81 118]
|
|
430
|
+
sage: n*m
|
|
431
|
+
[ 37 54]
|
|
432
|
+
[ 81 118]
|
|
433
|
+
|
|
434
|
+
sage: a = exp(m+n) - exp(m)*exp(n)
|
|
435
|
+
sage: a.simplify_rational() == 0
|
|
436
|
+
True
|
|
437
|
+
|
|
438
|
+
The input matrix must be square::
|
|
439
|
+
|
|
440
|
+
sage: m = matrix(SR,2,3,[1..6], sparse=True); exp(m)
|
|
441
|
+
Traceback (most recent call last):
|
|
442
|
+
...
|
|
443
|
+
ValueError: exp only defined on square matrices
|
|
444
|
+
|
|
445
|
+
In this example we take the symbolic answer and make it
|
|
446
|
+
numerical at the end::
|
|
447
|
+
|
|
448
|
+
sage: exp(matrix(SR, [[1.2, 5.6], [3,4]], sparse=True)).change_ring(RDF) # rel tol 1e-15
|
|
449
|
+
[ 346.5574872980695 661.7345909344504]
|
|
450
|
+
[354.50067371488416 677.4247827652946]
|
|
451
|
+
|
|
452
|
+
Another example involving the reversed identity matrix, which
|
|
453
|
+
we clumsily create::
|
|
454
|
+
|
|
455
|
+
sage: m = identity_matrix(SR,4, sparse=True)
|
|
456
|
+
sage: m = matrix(list(reversed(m.rows())), sparse=True) * x
|
|
457
|
+
sage: exp(m)
|
|
458
|
+
[1/2*(e^(2*x) + 1)*e^(-x) 0 0 1/2*(e^(2*x) - 1)*e^(-x)]
|
|
459
|
+
[ 0 1/2*(e^(2*x) + 1)*e^(-x) 1/2*(e^(2*x) - 1)*e^(-x) 0]
|
|
460
|
+
[ 0 1/2*(e^(2*x) - 1)*e^(-x) 1/2*(e^(2*x) + 1)*e^(-x) 0]
|
|
461
|
+
[1/2*(e^(2*x) - 1)*e^(-x) 0 0 1/2*(e^(2*x) + 1)*e^(-x)]
|
|
462
|
+
"""
|
|
463
|
+
if not self.is_square():
|
|
464
|
+
raise ValueError("exp only defined on square matrices")
|
|
465
|
+
if self.nrows() == 0:
|
|
466
|
+
return self
|
|
467
|
+
# Maxima's matrixexp function chokes on floating point numbers
|
|
468
|
+
# so we automatically convert floats to rationals by passing
|
|
469
|
+
# keepfloat: false
|
|
470
|
+
m = self._maxima_(maxima)
|
|
471
|
+
z = maxima('matrixexp(%s), keepfloat: false' % m.name())
|
|
472
|
+
if self.nrows() == 1:
|
|
473
|
+
# We do the following, because Maxima stupidly exp's 1x1
|
|
474
|
+
# matrices into non-matrices!
|
|
475
|
+
z = maxima('matrix([%s])' % z.name())
|
|
476
|
+
|
|
477
|
+
return z._sage_()
|
|
478
|
+
|
|
479
|
+
def charpoly(self, var='x', algorithm=None):
|
|
480
|
+
r"""
|
|
481
|
+
Compute the characteristic polynomial of ``self``, using maxima.
|
|
482
|
+
|
|
483
|
+
.. NOTE::
|
|
484
|
+
|
|
485
|
+
The characteristic polynomial is defined as `\det(xI-A)`.
|
|
486
|
+
|
|
487
|
+
INPUT:
|
|
488
|
+
|
|
489
|
+
- ``var`` -- (default: ``'x'``) name of variable of charpoly
|
|
490
|
+
|
|
491
|
+
EXAMPLES::
|
|
492
|
+
|
|
493
|
+
sage: M = matrix(SR, 2, 2, var('a,b,c,d'), sparse=True)
|
|
494
|
+
sage: M.charpoly('t')
|
|
495
|
+
t^2 + (-a - d)*t - b*c + a*d
|
|
496
|
+
sage: matrix(SR, 5, [1..5^2], sparse=True).charpoly()
|
|
497
|
+
x^5 - 65*x^4 - 250*x^3
|
|
498
|
+
|
|
499
|
+
TESTS:
|
|
500
|
+
|
|
501
|
+
The cached polynomial should be independent of the ``var``
|
|
502
|
+
argument (:issue:`12292`). We check (indirectly) that the
|
|
503
|
+
second call uses the cached value by noting that its result is
|
|
504
|
+
not cached::
|
|
505
|
+
|
|
506
|
+
sage: M = MatrixSpace(SR, 2, sparse=True)
|
|
507
|
+
sage: A = M(range(0, 2^2))
|
|
508
|
+
sage: type(A)
|
|
509
|
+
<class 'sage.matrix.matrix_symbolic_sparse.Matrix_symbolic_sparse'>
|
|
510
|
+
sage: A.charpoly('x')
|
|
511
|
+
x^2 - 3*x - 2
|
|
512
|
+
sage: A.charpoly('y')
|
|
513
|
+
y^2 - 3*y - 2
|
|
514
|
+
sage: A._cache['charpoly']
|
|
515
|
+
x^2 - 3*x - 2
|
|
516
|
+
|
|
517
|
+
Ensure the variable name of the polynomial does not conflict
|
|
518
|
+
with variables used within the matrix (:issue:`14403`)::
|
|
519
|
+
|
|
520
|
+
sage: Matrix(SR, [[sqrt(x), x],[1,x]], sparse=True).charpoly().list()
|
|
521
|
+
[x^(3/2) - x, -x - sqrt(x), 1]
|
|
522
|
+
|
|
523
|
+
Test that :issue:`13711` is fixed::
|
|
524
|
+
|
|
525
|
+
sage: matrix([[sqrt(2), -1], [pi, e^2]], sparse=True).charpoly()
|
|
526
|
+
x^2 + (-sqrt(2) - e^2)*x + pi + sqrt(2)*e^2
|
|
527
|
+
|
|
528
|
+
Test that :issue:`26427` is fixed::
|
|
529
|
+
|
|
530
|
+
sage: M = matrix(SR, 7, 7, SR.var('a', 49), sparse=True)
|
|
531
|
+
sage: M.charpoly().degree() # long time
|
|
532
|
+
7
|
|
533
|
+
"""
|
|
534
|
+
cache_key = 'charpoly'
|
|
535
|
+
cp = self.fetch(cache_key)
|
|
536
|
+
if cp is not None:
|
|
537
|
+
return cp.change_variable_name(var)
|
|
538
|
+
from sage.symbolic.ring import SR
|
|
539
|
+
|
|
540
|
+
# We must not use a variable name already present in the matrix
|
|
541
|
+
vname = 'do_not_use_this_name_in_a_matrix_youll_compute_a_charpoly_of'
|
|
542
|
+
vsym = SR(vname)
|
|
543
|
+
|
|
544
|
+
cp = self._maxima_(maxima).charpoly(vname)._sage_().expand()
|
|
545
|
+
cp = [cp.coefficient(vsym, i) for i in range(self.nrows() + 1)]
|
|
546
|
+
cp = SR[var](cp)
|
|
547
|
+
|
|
548
|
+
# Maxima has the definition det(matrix-xI) instead of
|
|
549
|
+
# det(xI-matrix), which is what Sage uses elsewhere. We
|
|
550
|
+
# correct for the discrepancy.
|
|
551
|
+
if self.nrows() % 2 == 1:
|
|
552
|
+
cp = -cp
|
|
553
|
+
|
|
554
|
+
self.cache(cache_key, cp)
|
|
555
|
+
return cp
|
|
556
|
+
|
|
557
|
+
def minpoly(self, var='x'):
|
|
558
|
+
"""
|
|
559
|
+
Return the minimal polynomial of ``self``.
|
|
560
|
+
|
|
561
|
+
EXAMPLES::
|
|
562
|
+
|
|
563
|
+
sage: M = Matrix.identity(SR, 2, sparse=True)
|
|
564
|
+
sage: M.minpoly()
|
|
565
|
+
x - 1
|
|
566
|
+
|
|
567
|
+
sage: t = var('t')
|
|
568
|
+
sage: m = matrix(2, [1, 2, 4, t], sparse=True)
|
|
569
|
+
sage: m.minimal_polynomial()
|
|
570
|
+
x^2 + (-t - 1)*x + t - 8
|
|
571
|
+
|
|
572
|
+
TESTS:
|
|
573
|
+
|
|
574
|
+
Check that the variable `x` can occur in the matrix::
|
|
575
|
+
|
|
576
|
+
sage: m = matrix([[x]], sparse=True)
|
|
577
|
+
sage: m.minimal_polynomial('y')
|
|
578
|
+
y - x
|
|
579
|
+
"""
|
|
580
|
+
mp = self.fetch('minpoly')
|
|
581
|
+
if mp is None:
|
|
582
|
+
mp = self._maxima_lib_().jordan().minimalPoly().expand()
|
|
583
|
+
d = mp.hipow('x')
|
|
584
|
+
mp = [mp.coeff('x', i) for i in range(int(d) + 1)]
|
|
585
|
+
mp = PolynomialRing(self.base_ring(), 'x')(mp)
|
|
586
|
+
self.cache('minpoly', mp)
|
|
587
|
+
return mp.change_variable_name(var)
|
|
588
|
+
|
|
589
|
+
def fcp(self, var='x'):
|
|
590
|
+
"""
|
|
591
|
+
Return the factorization of the characteristic polynomial of ``self``.
|
|
592
|
+
|
|
593
|
+
INPUT:
|
|
594
|
+
|
|
595
|
+
- ``var`` -- (default: ``'x'``) name of variable of charpoly
|
|
596
|
+
|
|
597
|
+
EXAMPLES::
|
|
598
|
+
|
|
599
|
+
sage: a = matrix(SR,[[1,2],[3,4]], sparse=True)
|
|
600
|
+
sage: a.fcp()
|
|
601
|
+
x^2 - 5*x - 2
|
|
602
|
+
sage: [i for i in a.fcp()]
|
|
603
|
+
[(x^2 - 5*x - 2, 1)]
|
|
604
|
+
sage: a = matrix(SR,[[1,0],[0,2]], sparse=True)
|
|
605
|
+
sage: a.fcp()
|
|
606
|
+
(x - 2) * (x - 1)
|
|
607
|
+
sage: [i for i in a.fcp()]
|
|
608
|
+
[(x - 2, 1), (x - 1, 1)]
|
|
609
|
+
sage: a = matrix(SR, 5, [1..5^2], sparse=True)
|
|
610
|
+
sage: a.fcp()
|
|
611
|
+
(x^2 - 65*x - 250) * x^3
|
|
612
|
+
sage: list(a.fcp())
|
|
613
|
+
[(x^2 - 65*x - 250, 1), (x, 3)]
|
|
614
|
+
"""
|
|
615
|
+
from sage.symbolic.ring import SR
|
|
616
|
+
sub_dict = {var: SR.var(var)}
|
|
617
|
+
return Factorization(self.charpoly(var).subs(**sub_dict).factor_list())
|
|
618
|
+
|
|
619
|
+
def jordan_form(self, subdivide=True, transformation=False):
|
|
620
|
+
"""
|
|
621
|
+
Return a Jordan normal form of ``self``.
|
|
622
|
+
|
|
623
|
+
INPUT:
|
|
624
|
+
|
|
625
|
+
- ``self`` -- a square matrix
|
|
626
|
+
|
|
627
|
+
- ``subdivide`` -- boolean (default: ``True``)
|
|
628
|
+
|
|
629
|
+
- ``transformation`` -- boolean (default: ``False``)
|
|
630
|
+
|
|
631
|
+
OUTPUT:
|
|
632
|
+
|
|
633
|
+
If ``transformation`` is ``False``, only a Jordan normal form
|
|
634
|
+
(unique up to the ordering of the Jordan blocks) is returned.
|
|
635
|
+
Otherwise, a pair ``(J, P)`` is returned, where ``J`` is a
|
|
636
|
+
Jordan normal form and ``P`` is an invertible matrix such that
|
|
637
|
+
``self`` equals ``P * J * P^(-1)``.
|
|
638
|
+
|
|
639
|
+
If ``subdivide`` is ``True``, the Jordan blocks in the
|
|
640
|
+
returned matrix ``J`` are indicated by a subdivision in
|
|
641
|
+
the sense of :meth:`~sage.matrix.matrix2.subdivide`.
|
|
642
|
+
|
|
643
|
+
EXAMPLES:
|
|
644
|
+
|
|
645
|
+
We start with some examples of diagonalisable matrices::
|
|
646
|
+
|
|
647
|
+
sage: a,b,c,d = var('a,b,c,d')
|
|
648
|
+
sage: matrix([a], sparse=True).jordan_form()
|
|
649
|
+
[a]
|
|
650
|
+
sage: matrix([[a, 0], [1, d]], sparse=True).jordan_form(subdivide=True)
|
|
651
|
+
[d|0]
|
|
652
|
+
[-+-]
|
|
653
|
+
[0|a]
|
|
654
|
+
sage: matrix([[a, 0], [1, d]], sparse=True).jordan_form(subdivide=False)
|
|
655
|
+
[d 0]
|
|
656
|
+
[0 a]
|
|
657
|
+
sage: matrix([[a, x, x], [0, b, x], [0, 0, c]], sparse=True).jordan_form()
|
|
658
|
+
[c|0|0]
|
|
659
|
+
[-+-+-]
|
|
660
|
+
[0|b|0]
|
|
661
|
+
[-+-+-]
|
|
662
|
+
[0|0|a]
|
|
663
|
+
|
|
664
|
+
In the following examples, we compute Jordan forms of some
|
|
665
|
+
non-diagonalisable matrices::
|
|
666
|
+
|
|
667
|
+
sage: matrix([[a, a], [0, a]], sparse=True).jordan_form()
|
|
668
|
+
[a 1]
|
|
669
|
+
[0 a]
|
|
670
|
+
sage: matrix([[a, 0, b], [0, c, 0], [0, 0, a]], sparse=True).jordan_form()
|
|
671
|
+
[c|0 0]
|
|
672
|
+
[-+---]
|
|
673
|
+
[0|a 1]
|
|
674
|
+
[0|0 a]
|
|
675
|
+
|
|
676
|
+
The following examples illustrate the ``transformation`` flag.
|
|
677
|
+
Note that symbolic expressions may need to be simplified to
|
|
678
|
+
make consistency checks succeed::
|
|
679
|
+
|
|
680
|
+
sage: A = matrix([[x - a*c, a^2], [-c^2, x + a*c]], sparse=True)
|
|
681
|
+
sage: J, P = A.jordan_form(transformation=True)
|
|
682
|
+
sage: J, P
|
|
683
|
+
(
|
|
684
|
+
[x 1] [-a*c 1]
|
|
685
|
+
[0 x], [-c^2 0]
|
|
686
|
+
)
|
|
687
|
+
sage: A1 = P * J * ~P; A1
|
|
688
|
+
[ -a*c + x (a*c - x)*a/c + a*x/c]
|
|
689
|
+
[ -c^2 a*c + x]
|
|
690
|
+
sage: A1.simplify_rational() == A
|
|
691
|
+
True
|
|
692
|
+
|
|
693
|
+
sage: B = matrix([[a, b, c], [0, a, d], [0, 0, a]], sparse=True)
|
|
694
|
+
sage: J, T = B.jordan_form(transformation=True)
|
|
695
|
+
sage: J, T
|
|
696
|
+
(
|
|
697
|
+
[a 1 0] [b*d c 0]
|
|
698
|
+
[0 a 1] [ 0 d 0]
|
|
699
|
+
[0 0 a], [ 0 0 1]
|
|
700
|
+
)
|
|
701
|
+
sage: (B * T).simplify_rational() == T * J
|
|
702
|
+
True
|
|
703
|
+
|
|
704
|
+
Finally, some examples involving square roots::
|
|
705
|
+
|
|
706
|
+
sage: matrix([[a, -b], [b, a]], sparse=True).jordan_form()
|
|
707
|
+
[a - I*b| 0]
|
|
708
|
+
[-------+-------]
|
|
709
|
+
[ 0|a + I*b]
|
|
710
|
+
sage: matrix([[a, b], [c, d]], sparse=True).jordan_form(subdivide=False)
|
|
711
|
+
[1/2*a + 1/2*d - 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2) 0]
|
|
712
|
+
[ 0 1/2*a + 1/2*d + 1/2*sqrt(a^2 + 4*b*c - 2*a*d + d^2)]
|
|
713
|
+
"""
|
|
714
|
+
A = self._maxima_lib_()
|
|
715
|
+
jordan_info = A.jordan()
|
|
716
|
+
J = matrix(jordan_info.dispJordan()._sage_(), sparse=True)
|
|
717
|
+
if subdivide:
|
|
718
|
+
v = [x[1] for x in jordan_info]
|
|
719
|
+
w = [sum(v[0:i]) for i in range(1, len(v))]
|
|
720
|
+
J.subdivide(w, w)
|
|
721
|
+
if transformation:
|
|
722
|
+
P = A.diag_mode_matrix(jordan_info)._sage_()
|
|
723
|
+
return J, matrix(P, sparse=True)
|
|
724
|
+
else:
|
|
725
|
+
return J
|
|
726
|
+
|
|
727
|
+
def simplify(self):
|
|
728
|
+
"""
|
|
729
|
+
Simplify ``self``.
|
|
730
|
+
|
|
731
|
+
EXAMPLES::
|
|
732
|
+
|
|
733
|
+
sage: var('x,y,z')
|
|
734
|
+
(x, y, z)
|
|
735
|
+
sage: m = matrix([[z, (x+y)/(x+y)], [x^2, y^2+2]], sparse=True); m
|
|
736
|
+
[ z 1]
|
|
737
|
+
[ x^2 y^2 + 2]
|
|
738
|
+
sage: m.simplify()
|
|
739
|
+
[ z 1]
|
|
740
|
+
[ x^2 y^2 + 2]
|
|
741
|
+
"""
|
|
742
|
+
return self.parent()([x.simplify() for x in self.list()])
|
|
743
|
+
|
|
744
|
+
def simplify_trig(self):
|
|
745
|
+
"""
|
|
746
|
+
EXAMPLES::
|
|
747
|
+
|
|
748
|
+
sage: theta = var('theta')
|
|
749
|
+
sage: M = matrix(SR, 2, 2, [cos(theta), sin(theta), -sin(theta), cos(theta)], sparse=True)
|
|
750
|
+
sage: ~M
|
|
751
|
+
[1/cos(theta) - sin(theta)^2/((sin(theta)^2/cos(theta) + cos(theta))*cos(theta)^2) -sin(theta)/((sin(theta)^2/cos(theta) + cos(theta))*cos(theta))]
|
|
752
|
+
[ sin(theta)/((sin(theta)^2/cos(theta) + cos(theta))*cos(theta)) 1/(sin(theta)^2/cos(theta) + cos(theta))]
|
|
753
|
+
sage: (~M).simplify_trig()
|
|
754
|
+
[ cos(theta) -sin(theta)]
|
|
755
|
+
[ sin(theta) cos(theta)]
|
|
756
|
+
"""
|
|
757
|
+
return self._maxima_(maxima).trigexpand().trigsimp()._sage_()
|
|
758
|
+
|
|
759
|
+
def simplify_rational(self):
|
|
760
|
+
"""
|
|
761
|
+
EXAMPLES::
|
|
762
|
+
|
|
763
|
+
sage: M = matrix(SR, 3, 3, range(9), sparse=True) - var('t')
|
|
764
|
+
sage: (~M*M)[0,0]
|
|
765
|
+
t*(3*(2/t + (6/t + 7)/((t - 3/t - 4)*t))*(2/t + (6/t + 5)/((t - 3/t
|
|
766
|
+
- 4)*t))/(t - (6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) + 1/t +
|
|
767
|
+
3/((t - 3/t - 4)*t^2)) - 6*(2/t + (6/t + 5)/((t - 3/t - 4)*t))/(t -
|
|
768
|
+
(6/t + 7)*(6/t + 5)/(t - 3/t - 4) - 12/t - 8) - 3*(6/t + 7)*(2/t +
|
|
769
|
+
(6/t + 5)/((t - 3/t - 4)*t))/((t - (6/t + 7)*(6/t + 5)/(t - 3/t -
|
|
770
|
+
4) - 12/t - 8)*(t - 3/t - 4)) - 3/((t - 3/t - 4)*t)
|
|
771
|
+
sage: expand((~M*M)[0,0])
|
|
772
|
+
1
|
|
773
|
+
sage: (~M * M).simplify_rational()
|
|
774
|
+
[1 0 0]
|
|
775
|
+
[0 1 0]
|
|
776
|
+
[0 0 1]
|
|
777
|
+
"""
|
|
778
|
+
return self._maxima_(maxima).fullratsimp()._sage_()
|
|
779
|
+
|
|
780
|
+
def simplify_full(self):
|
|
781
|
+
"""
|
|
782
|
+
Simplify a symbolic matrix by calling
|
|
783
|
+
:meth:`Expression.simplify_full()` componentwise.
|
|
784
|
+
|
|
785
|
+
INPUT:
|
|
786
|
+
|
|
787
|
+
- ``self`` -- the matrix whose entries we should simplify
|
|
788
|
+
|
|
789
|
+
OUTPUT: a copy of ``self`` with all of its entries simplified
|
|
790
|
+
|
|
791
|
+
EXAMPLES:
|
|
792
|
+
|
|
793
|
+
Symbolic matrices will have their entries simplified::
|
|
794
|
+
|
|
795
|
+
sage: a,n,k = SR.var('a,n,k')
|
|
796
|
+
sage: f1 = sin(x)^2 + cos(x)^2
|
|
797
|
+
sage: f2 = sin(x/(x^2 + x))
|
|
798
|
+
sage: f3 = binomial(n,k)*factorial(k)*factorial(n-k)
|
|
799
|
+
sage: f4 = x*sin(2)/(x^a)
|
|
800
|
+
sage: A = matrix(SR, [[f1,f2],[f3,f4]], sparse=True)
|
|
801
|
+
sage: A.simplify_full()
|
|
802
|
+
[ 1 sin(1/(x + 1))]
|
|
803
|
+
[ factorial(n) x^(-a + 1)*sin(2)]
|
|
804
|
+
"""
|
|
805
|
+
M = self.parent()
|
|
806
|
+
return M([expr.simplify_full() for expr in self])
|
|
807
|
+
|
|
808
|
+
def canonicalize_radical(self):
|
|
809
|
+
r"""
|
|
810
|
+
Choose a canonical branch of each entry of ``self`` by calling
|
|
811
|
+
:meth:`Expression.canonicalize_radical()` componentwise.
|
|
812
|
+
|
|
813
|
+
EXAMPLES::
|
|
814
|
+
|
|
815
|
+
sage: var('x','y')
|
|
816
|
+
(x, y)
|
|
817
|
+
sage: l1 = [sqrt(2)*sqrt(3)*sqrt(6) , log(x*y)]
|
|
818
|
+
sage: l2 = [sin(x/(x^2 + x)) , 1]
|
|
819
|
+
sage: m = matrix([l1, l2], sparse=True)
|
|
820
|
+
sage: m
|
|
821
|
+
[sqrt(6)*sqrt(3)*sqrt(2) log(x*y)]
|
|
822
|
+
[ sin(x/(x^2 + x)) 1]
|
|
823
|
+
sage: m.canonicalize_radical()
|
|
824
|
+
[ 6 log(x) + log(y)]
|
|
825
|
+
[ sin(1/(x + 1)) 1]
|
|
826
|
+
"""
|
|
827
|
+
M = self.parent()
|
|
828
|
+
return M([expr.canonicalize_radical() for expr in self])
|
|
829
|
+
|
|
830
|
+
def factor(self):
|
|
831
|
+
"""
|
|
832
|
+
Operate point-wise on each element.
|
|
833
|
+
|
|
834
|
+
EXAMPLES::
|
|
835
|
+
|
|
836
|
+
sage: M = matrix(SR, 2, 2, x^2 - 2*x + 1, sparse=True); M
|
|
837
|
+
[x^2 - 2*x + 1 0]
|
|
838
|
+
[ 0 x^2 - 2*x + 1]
|
|
839
|
+
sage: M.factor()
|
|
840
|
+
[(x - 1)^2 0]
|
|
841
|
+
[ 0 (x - 1)^2]
|
|
842
|
+
"""
|
|
843
|
+
return matrix(self._maxima_(maxima).factor()._sage_(), sparse=True)
|
|
844
|
+
|
|
845
|
+
def expand(self):
|
|
846
|
+
"""
|
|
847
|
+
Operate point-wise on each element.
|
|
848
|
+
|
|
849
|
+
EXAMPLES::
|
|
850
|
+
|
|
851
|
+
sage: M = matrix(2, 2, range(4)) - var('x')
|
|
852
|
+
sage: M*M
|
|
853
|
+
[ x^2 + 2 -2*x + 3]
|
|
854
|
+
[ -4*x + 6 (x - 3)^2 + 2]
|
|
855
|
+
sage: (M*M).expand()
|
|
856
|
+
[ x^2 + 2 -2*x + 3]
|
|
857
|
+
[ -4*x + 6 x^2 - 6*x + 11]
|
|
858
|
+
"""
|
|
859
|
+
from sage.misc.call import attrcall
|
|
860
|
+
return self.apply_map(attrcall('expand'))
|
|
861
|
+
|
|
862
|
+
def variables(self):
|
|
863
|
+
"""
|
|
864
|
+
Return the variables of ``self``.
|
|
865
|
+
|
|
866
|
+
EXAMPLES::
|
|
867
|
+
|
|
868
|
+
sage: var('a,b,c,x,y')
|
|
869
|
+
(a, b, c, x, y)
|
|
870
|
+
sage: m = matrix([[x, x+2], [x^2, x^2+2]], sparse=True); m
|
|
871
|
+
[ x x + 2]
|
|
872
|
+
[ x^2 x^2 + 2]
|
|
873
|
+
sage: m.variables()
|
|
874
|
+
(x,)
|
|
875
|
+
sage: m = matrix([[a, b+c], [x^2, y^2+2]], sparse=True); m
|
|
876
|
+
[ a b + c]
|
|
877
|
+
[ x^2 y^2 + 2]
|
|
878
|
+
sage: m.variables()
|
|
879
|
+
(a, b, c, x, y)
|
|
880
|
+
"""
|
|
881
|
+
vars = set(sum([op.variables() for op in self.list()], ()))
|
|
882
|
+
return tuple(sorted(vars, key=repr))
|
|
883
|
+
|
|
884
|
+
def arguments(self):
|
|
885
|
+
"""
|
|
886
|
+
Return a tuple of the arguments that ``self`` can take.
|
|
887
|
+
|
|
888
|
+
EXAMPLES::
|
|
889
|
+
|
|
890
|
+
sage: var('x,y,z')
|
|
891
|
+
(x, y, z)
|
|
892
|
+
sage: M = MatrixSpace(SR,2,2, sparse=True)
|
|
893
|
+
sage: M(x).arguments()
|
|
894
|
+
(x,)
|
|
895
|
+
sage: M(x+sin(x)).arguments()
|
|
896
|
+
(x,)
|
|
897
|
+
"""
|
|
898
|
+
return self.variables()
|
|
899
|
+
|
|
900
|
+
def number_of_arguments(self):
|
|
901
|
+
"""
|
|
902
|
+
Return the number of arguments that ``self`` can take.
|
|
903
|
+
|
|
904
|
+
EXAMPLES::
|
|
905
|
+
|
|
906
|
+
sage: var('a,b,c,x,y')
|
|
907
|
+
(a, b, c, x, y)
|
|
908
|
+
sage: m = matrix([[a, (x+y)/(x+y)], [x^2, y^2+2]], sparse=True); m
|
|
909
|
+
[ a 1]
|
|
910
|
+
[ x^2 y^2 + 2]
|
|
911
|
+
sage: m.number_of_arguments()
|
|
912
|
+
3
|
|
913
|
+
"""
|
|
914
|
+
return len(self.variables())
|
|
915
|
+
|
|
916
|
+
def __call__(self, *args, **kwargs):
|
|
917
|
+
"""
|
|
918
|
+
EXAMPLES::
|
|
919
|
+
|
|
920
|
+
sage: var('x,y,z')
|
|
921
|
+
(x, y, z)
|
|
922
|
+
sage: M = MatrixSpace(SR,2,2, sparse=True)
|
|
923
|
+
sage: h = M(sin(x)+cos(x))
|
|
924
|
+
sage: h
|
|
925
|
+
[cos(x) + sin(x) 0]
|
|
926
|
+
[ 0 cos(x) + sin(x)]
|
|
927
|
+
sage: h(x=1)
|
|
928
|
+
[cos(1) + sin(1) 0]
|
|
929
|
+
[ 0 cos(1) + sin(1)]
|
|
930
|
+
sage: h(x=x)
|
|
931
|
+
[cos(x) + sin(x) 0]
|
|
932
|
+
[ 0 cos(x) + sin(x)]
|
|
933
|
+
|
|
934
|
+
sage: h = M((sin(x)+cos(x)).function(x))
|
|
935
|
+
sage: h
|
|
936
|
+
[cos(x) + sin(x) 0]
|
|
937
|
+
[ 0 cos(x) + sin(x)]
|
|
938
|
+
|
|
939
|
+
sage: f = M([0,x,y,z]); f
|
|
940
|
+
[0 x]
|
|
941
|
+
[y z]
|
|
942
|
+
sage: f.arguments()
|
|
943
|
+
(x, y, z)
|
|
944
|
+
sage: f()
|
|
945
|
+
[0 x]
|
|
946
|
+
[y z]
|
|
947
|
+
sage: f(x=1)
|
|
948
|
+
[0 1]
|
|
949
|
+
[y z]
|
|
950
|
+
sage: f(x=1,y=2)
|
|
951
|
+
[0 1]
|
|
952
|
+
[2 z]
|
|
953
|
+
sage: f(x=1,y=2,z=3)
|
|
954
|
+
[0 1]
|
|
955
|
+
[2 3]
|
|
956
|
+
sage: f({x:1,y:2,z:3})
|
|
957
|
+
[0 1]
|
|
958
|
+
[2 3]
|
|
959
|
+
|
|
960
|
+
TESTS::
|
|
961
|
+
|
|
962
|
+
sage: f(1, x=2)
|
|
963
|
+
Traceback (most recent call last):
|
|
964
|
+
...
|
|
965
|
+
ValueError: args and kwargs cannot both be specified
|
|
966
|
+
sage: f(x=1,y=2,z=3,t=4)
|
|
967
|
+
[0 1]
|
|
968
|
+
[2 3]
|
|
969
|
+
|
|
970
|
+
sage: h(1)
|
|
971
|
+
Traceback (most recent call last):
|
|
972
|
+
...
|
|
973
|
+
ValueError: use named arguments, like EXPR(x=..., y=...)
|
|
974
|
+
"""
|
|
975
|
+
if kwargs and args:
|
|
976
|
+
raise ValueError("args and kwargs cannot both be specified")
|
|
977
|
+
|
|
978
|
+
if args:
|
|
979
|
+
if len(args) == 1 and isinstance(args[0], dict):
|
|
980
|
+
kwargs = {repr(x): vx for x, vx in args[0].iteritems()}
|
|
981
|
+
else:
|
|
982
|
+
raise ValueError('use named arguments, like EXPR(x=..., y=...)')
|
|
983
|
+
|
|
984
|
+
new_entries = []
|
|
985
|
+
for entry in self.list():
|
|
986
|
+
try:
|
|
987
|
+
new_entries.append(entry(**kwargs))
|
|
988
|
+
except ValueError:
|
|
989
|
+
new_entries.append(entry)
|
|
990
|
+
|
|
991
|
+
return self.parent(new_entries)
|
|
992
|
+
|
|
993
|
+
cdef bint get_is_zero_unsafe(self, Py_ssize_t i, Py_ssize_t j) except -1:
|
|
994
|
+
r"""
|
|
995
|
+
Return 1 if the entry ``(i, j)`` is zero, otherwise 0.
|
|
996
|
+
|
|
997
|
+
EXAMPLES::
|
|
998
|
+
|
|
999
|
+
sage: M = matrix(SR, [[0,1,0],[0,0,0]], sparse=True)
|
|
1000
|
+
sage: M.zero_pattern_matrix() # indirect doctest
|
|
1001
|
+
[1 0 1]
|
|
1002
|
+
[1 1 1]
|
|
1003
|
+
"""
|
|
1004
|
+
entry = self.get_unsafe(i, j)
|
|
1005
|
+
# See if we can avoid the full proof machinery that the entry is 0
|
|
1006
|
+
if entry.is_trivial_zero():
|
|
1007
|
+
return 1
|
|
1008
|
+
if entry:
|
|
1009
|
+
return 0
|
|
1010
|
+
else:
|
|
1011
|
+
return 1
|
|
1012
|
+
|
|
1013
|
+
def function(self, *args):
|
|
1014
|
+
"""
|
|
1015
|
+
Return a matrix over a callable symbolic expression ring.
|
|
1016
|
+
|
|
1017
|
+
EXAMPLES::
|
|
1018
|
+
|
|
1019
|
+
sage: x, y = var('x,y')
|
|
1020
|
+
sage: v = matrix([[x,y],[x*sin(y), 0]], sparse=True)
|
|
1021
|
+
sage: w = v.function([x,y]); w
|
|
1022
|
+
[ (x, y) |--> x (x, y) |--> y]
|
|
1023
|
+
[(x, y) |--> x*sin(y) (x, y) |--> 0]
|
|
1024
|
+
sage: w.parent()
|
|
1025
|
+
Full MatrixSpace of 2 by 2 sparse matrices over Callable function ring with arguments (x, y)
|
|
1026
|
+
"""
|
|
1027
|
+
from sage.symbolic.callable import CallableSymbolicExpressionRing
|
|
1028
|
+
return matrix(CallableSymbolicExpressionRing(args),
|
|
1029
|
+
self.nrows(), self.ncols(), self.list(), sparse=True)
|