passagemath-symbolics 10.6.40__cp314-cp314t-macosx_13_0_x86_64.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.
Potentially problematic release.
This version of passagemath-symbolics might be problematic. Click here for more details.
- passagemath_symbolics/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.40.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.40.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.40.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.40.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,310 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
r"""
|
|
3
|
+
Conversion of symbolic expressions to algebraic numbers
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2009-2012 Mike Hansen
|
|
7
|
+
# 2015-2018 Ralf Stephan
|
|
8
|
+
# 2015 Nils Bruin
|
|
9
|
+
# 2017 Jeroen Demeyer
|
|
10
|
+
# 2019-2022 Frédéric Chapoton
|
|
11
|
+
# 2021 Dave Witte Morris
|
|
12
|
+
# 2023 Vincent Delecroix
|
|
13
|
+
#
|
|
14
|
+
# This program is free software: you can redistribute it and/or modify
|
|
15
|
+
# it under the terms of the GNU General Public License as published by
|
|
16
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
17
|
+
# (at your option) any later version.
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# ****************************************************************************
|
|
20
|
+
|
|
21
|
+
from operator import eq, ne, gt, lt, ge, le, mul, pow, neg, add, truediv
|
|
22
|
+
from functools import reduce
|
|
23
|
+
|
|
24
|
+
import sage.rings.abc
|
|
25
|
+
|
|
26
|
+
from sage.functions.all import exp
|
|
27
|
+
from sage.symbolic.expression_conversions import Converter
|
|
28
|
+
from sage.symbolic.operators import add_vararg, mul_vararg
|
|
29
|
+
from sage.symbolic.ring import SR
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
#############
|
|
33
|
+
# Algebraic #
|
|
34
|
+
#############
|
|
35
|
+
class AlgebraicConverter(Converter):
|
|
36
|
+
def __init__(self, field):
|
|
37
|
+
"""
|
|
38
|
+
EXAMPLES::
|
|
39
|
+
|
|
40
|
+
sage: from sage.symbolic.expression_conversions import AlgebraicConverter
|
|
41
|
+
sage: a = AlgebraicConverter(QQbar)
|
|
42
|
+
sage: a.field
|
|
43
|
+
Algebraic Field
|
|
44
|
+
sage: a.reciprocal_trig_functions['cot']
|
|
45
|
+
tan
|
|
46
|
+
"""
|
|
47
|
+
self.field = field
|
|
48
|
+
|
|
49
|
+
from sage.functions.all import reciprocal_trig_functions
|
|
50
|
+
self.reciprocal_trig_functions = reciprocal_trig_functions
|
|
51
|
+
|
|
52
|
+
def pyobject(self, ex, obj):
|
|
53
|
+
"""
|
|
54
|
+
EXAMPLES::
|
|
55
|
+
|
|
56
|
+
sage: from sage.symbolic.expression_conversions import AlgebraicConverter
|
|
57
|
+
sage: a = AlgebraicConverter(QQbar)
|
|
58
|
+
sage: f = SR(2)
|
|
59
|
+
sage: a.pyobject(f, f.pyobject())
|
|
60
|
+
2
|
|
61
|
+
sage: _.parent()
|
|
62
|
+
Algebraic Field
|
|
63
|
+
"""
|
|
64
|
+
return self.field(obj)
|
|
65
|
+
|
|
66
|
+
def arithmetic(self, ex, operator):
|
|
67
|
+
"""
|
|
68
|
+
Convert a symbolic expression to an algebraic number.
|
|
69
|
+
|
|
70
|
+
EXAMPLES::
|
|
71
|
+
|
|
72
|
+
sage: from sage.symbolic.expression_conversions import AlgebraicConverter
|
|
73
|
+
sage: f = 2^(1/2)
|
|
74
|
+
sage: a = AlgebraicConverter(QQbar)
|
|
75
|
+
sage: a.arithmetic(f, f.operator())
|
|
76
|
+
1.414213562373095?
|
|
77
|
+
|
|
78
|
+
TESTS::
|
|
79
|
+
|
|
80
|
+
sage: f = pi^6
|
|
81
|
+
sage: a = AlgebraicConverter(QQbar)
|
|
82
|
+
sage: a.arithmetic(f, f.operator())
|
|
83
|
+
Traceback (most recent call last):
|
|
84
|
+
...
|
|
85
|
+
TypeError: unable to convert pi^6 to Algebraic Field
|
|
86
|
+
|
|
87
|
+
Test that :issue:`14602` is fixed::
|
|
88
|
+
|
|
89
|
+
sage: # needs sage.rings.number_field
|
|
90
|
+
sage: K = QuadraticField(3)
|
|
91
|
+
sage: K(sqrt(3)).parent() is K
|
|
92
|
+
True
|
|
93
|
+
sage: sqrt(K(3)).parent() is K
|
|
94
|
+
True
|
|
95
|
+
sage: (K(3)^(1/2)).parent()
|
|
96
|
+
Symbolic Ring
|
|
97
|
+
sage: bool(K.gen() == K(3)^(1/2) == sqrt(K(3)) == K(sqrt(3)) == sqrt(3))
|
|
98
|
+
True
|
|
99
|
+
sage: L = QuadraticField(3, embedding=-AA(3).sqrt())
|
|
100
|
+
sage: bool(L.gen() == -sqrt(3))
|
|
101
|
+
True
|
|
102
|
+
"""
|
|
103
|
+
# We try to avoid simplifying, because maxima's simplify command
|
|
104
|
+
# can change the value of a radical expression (by changing which
|
|
105
|
+
# root is selected).
|
|
106
|
+
try:
|
|
107
|
+
if operator is pow:
|
|
108
|
+
from sage.rings.rational import Rational
|
|
109
|
+
base, expt = ex.operands()
|
|
110
|
+
base = self.field(base)
|
|
111
|
+
expt = Rational(expt)
|
|
112
|
+
return self.field(base**expt)
|
|
113
|
+
else:
|
|
114
|
+
if operator is add_vararg:
|
|
115
|
+
operator = add
|
|
116
|
+
elif operator is mul_vararg:
|
|
117
|
+
operator = mul
|
|
118
|
+
return reduce(operator, map(self, ex.operands()))
|
|
119
|
+
except TypeError:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
if operator is pow:
|
|
123
|
+
from sage.symbolic.constants import e, pi, I
|
|
124
|
+
from sage.rings.rational_field import QQ
|
|
125
|
+
|
|
126
|
+
base, expt = ex.operands()
|
|
127
|
+
if base == e and expt / (pi * I) in QQ:
|
|
128
|
+
return exp(expt)._algebraic_(self.field)
|
|
129
|
+
|
|
130
|
+
raise TypeError("unable to convert %r to %s" % (ex, self.field))
|
|
131
|
+
|
|
132
|
+
def composition(self, ex, operator):
|
|
133
|
+
"""
|
|
134
|
+
Coerce to an algebraic number.
|
|
135
|
+
|
|
136
|
+
EXAMPLES::
|
|
137
|
+
|
|
138
|
+
sage: # needs sage.libs.pari
|
|
139
|
+
sage: from sage.symbolic.expression_conversions import AlgebraicConverter
|
|
140
|
+
sage: a = AlgebraicConverter(QQbar)
|
|
141
|
+
sage: a.composition(exp(I*pi/3, hold=True), exp)
|
|
142
|
+
0.500000000000000? + 0.866025403784439?*I
|
|
143
|
+
sage: a.composition(sin(pi/7), sin)
|
|
144
|
+
0.4338837391175581? + 0.?e-18*I
|
|
145
|
+
sage: x = SR.var('x')
|
|
146
|
+
sage: a.composition(complex_root_of(x^3 - x^2 - x - 1, 0), complex_root_of)
|
|
147
|
+
1.839286755214161?
|
|
148
|
+
sage: a.composition(complex_root_of(x^5 - 1, 3), complex_root_of)
|
|
149
|
+
0.3090169943749474? - 0.9510565162951536?*I
|
|
150
|
+
sage: a.composition(complex_root_of(x^2 + 1, 0), complex_root_of)
|
|
151
|
+
1.?e-683 - 0.9999999999999999?*I
|
|
152
|
+
sage: a.composition(complex_root_of(x^2 + 1, 1), complex_root_of)
|
|
153
|
+
1.?e-683 + 0.9999999999999999?*I
|
|
154
|
+
|
|
155
|
+
TESTS::
|
|
156
|
+
|
|
157
|
+
sage: QQbar(zeta(7))
|
|
158
|
+
Traceback (most recent call last):
|
|
159
|
+
...
|
|
160
|
+
TypeError: unable to convert zeta(7) to Algebraic Field
|
|
161
|
+
|
|
162
|
+
Test :issue:`22571`::
|
|
163
|
+
|
|
164
|
+
sage: # needs sage.libs.pari
|
|
165
|
+
sage: a.composition(exp(0, hold=True), exp)
|
|
166
|
+
1
|
|
167
|
+
sage: a.composition(exp(1, hold=True), exp)
|
|
168
|
+
Traceback (most recent call last):
|
|
169
|
+
...
|
|
170
|
+
ValueError: unable to represent as an algebraic number
|
|
171
|
+
sage: a.composition(exp(pi*I*RR(1), hold=True), exp)
|
|
172
|
+
Traceback (most recent call last):
|
|
173
|
+
...
|
|
174
|
+
TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field
|
|
175
|
+
sage: a.composition(exp(pi*CC.gen(), hold=True), exp)
|
|
176
|
+
Traceback (most recent call last):
|
|
177
|
+
...
|
|
178
|
+
TypeError: unable to convert e^(1.00000000000000*I*pi) to Algebraic Field
|
|
179
|
+
sage: bool(sin(pi*RR("0.7000000000000002")) > 0)
|
|
180
|
+
True
|
|
181
|
+
|
|
182
|
+
Check that :issue:`24440` is fixed::
|
|
183
|
+
|
|
184
|
+
sage: # needs sage.libs.pari
|
|
185
|
+
sage: QQbar(tanh(pi + 0.1))
|
|
186
|
+
Traceback (most recent call last):
|
|
187
|
+
...
|
|
188
|
+
ValueError: unable to represent as an algebraic number
|
|
189
|
+
sage: QQbar(sin(I*pi/7))
|
|
190
|
+
Traceback (most recent call last):
|
|
191
|
+
...
|
|
192
|
+
ValueError: unable to represent as an algebraic number
|
|
193
|
+
sage: QQbar(sin(I*pi/7, hold=True))
|
|
194
|
+
Traceback (most recent call last):
|
|
195
|
+
...
|
|
196
|
+
ValueError: unable to represent as an algebraic number
|
|
197
|
+
"""
|
|
198
|
+
func = operator
|
|
199
|
+
operands = ex.operands()
|
|
200
|
+
if len(operands) == 1:
|
|
201
|
+
operand = operands[0]
|
|
202
|
+
else:
|
|
203
|
+
operand = None
|
|
204
|
+
|
|
205
|
+
if isinstance(self.field, sage.rings.abc.UniversalCyclotomicField):
|
|
206
|
+
QQbar = self.field
|
|
207
|
+
hold = True
|
|
208
|
+
else:
|
|
209
|
+
QQbar = self.field.algebraic_closure()
|
|
210
|
+
hold = False
|
|
211
|
+
|
|
212
|
+
zeta = QQbar.zeta
|
|
213
|
+
# Note that comparing functions themselves goes via maxima, and is SLOW
|
|
214
|
+
func_name = repr(func)
|
|
215
|
+
if func_name == 'exp':
|
|
216
|
+
if operand.is_trivial_zero():
|
|
217
|
+
return self.field.one()
|
|
218
|
+
if not (SR(-1).sqrt() * operand).is_real():
|
|
219
|
+
raise ValueError("unable to represent as an algebraic number")
|
|
220
|
+
# Coerce (not convert, see #22571) arg to a rational
|
|
221
|
+
from sage.rings.rational_field import QQ
|
|
222
|
+
arg = operand.imag()/(2*ex.parent().pi())
|
|
223
|
+
try:
|
|
224
|
+
rat_arg = QQ.coerce(arg.pyobject())
|
|
225
|
+
except TypeError:
|
|
226
|
+
raise TypeError("unable to convert %r to %s" % (ex, self.field))
|
|
227
|
+
res = zeta(rat_arg.denom())**rat_arg.numer()
|
|
228
|
+
return self.field(res)
|
|
229
|
+
elif func_name in ['sin', 'cos', 'tan']:
|
|
230
|
+
exp_ia = exp(SR(-1).sqrt() * operand, hold=hold)._algebraic_(QQbar)
|
|
231
|
+
if func_name == 'sin':
|
|
232
|
+
res = (exp_ia - ~exp_ia) / (2 * zeta(4))
|
|
233
|
+
elif func_name == 'cos':
|
|
234
|
+
res = (exp_ia + ~exp_ia) / 2
|
|
235
|
+
else:
|
|
236
|
+
res = -zeta(4) * (exp_ia - ~exp_ia) / (exp_ia + ~exp_ia)
|
|
237
|
+
return self.field(res)
|
|
238
|
+
elif func_name in ['sinh', 'cosh', 'tanh']:
|
|
239
|
+
if not (SR(-1).sqrt()*operand).is_real():
|
|
240
|
+
raise ValueError("unable to represent as an algebraic number")
|
|
241
|
+
exp_a = exp(operand, hold=hold)._algebraic_(QQbar)
|
|
242
|
+
if func_name == 'sinh':
|
|
243
|
+
res = (exp_a - ~exp_a) / 2
|
|
244
|
+
elif func_name == 'cosh':
|
|
245
|
+
res = (exp_a + ~exp_a) / 2
|
|
246
|
+
else:
|
|
247
|
+
res = (exp_a - ~exp_a) / (exp_a + ~exp_a)
|
|
248
|
+
return self.field(res)
|
|
249
|
+
elif func_name in self.reciprocal_trig_functions:
|
|
250
|
+
res = ~self.reciprocal_trig_functions[func_name](operand)._algebraic_(QQbar)
|
|
251
|
+
return self.field(res)
|
|
252
|
+
elif func_name == 'complex_root_of':
|
|
253
|
+
cr = ex._sympy_()
|
|
254
|
+
poly = cr.poly._sage_()
|
|
255
|
+
interval = cr._get_interval()._sage_()
|
|
256
|
+
return self.field.polynomial_root(poly, interval)
|
|
257
|
+
elif operand is not None:
|
|
258
|
+
res = func(operand._algebraic_(self.field))
|
|
259
|
+
# We have to handle the case where we get the same symbolic
|
|
260
|
+
# expression back. For example, QQbar(zeta(7)). See
|
|
261
|
+
# issue #12665.
|
|
262
|
+
if (res - ex).is_trivial_zero():
|
|
263
|
+
raise TypeError("unable to convert %r to %s" % (ex, self.field))
|
|
264
|
+
return self.field(res)
|
|
265
|
+
|
|
266
|
+
raise ValueError("unable to represent as an algebraic number")
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def algebraic(ex, field):
|
|
270
|
+
"""
|
|
271
|
+
Return the symbolic expression ``ex`` as a element of the algebraic
|
|
272
|
+
field ``field``.
|
|
273
|
+
|
|
274
|
+
EXAMPLES::
|
|
275
|
+
|
|
276
|
+
sage: a = SR(5/6)
|
|
277
|
+
sage: AA(a)
|
|
278
|
+
5/6
|
|
279
|
+
sage: type(AA(a))
|
|
280
|
+
<class 'sage.rings.qqbar.AlgebraicReal'>
|
|
281
|
+
sage: QQbar(a)
|
|
282
|
+
5/6
|
|
283
|
+
sage: type(QQbar(a))
|
|
284
|
+
<class 'sage.rings.qqbar.AlgebraicNumber'>
|
|
285
|
+
sage: QQbar(i)
|
|
286
|
+
I
|
|
287
|
+
sage: AA(golden_ratio) # needs sage.libs.pari
|
|
288
|
+
1.618033988749895?
|
|
289
|
+
sage: QQbar(golden_ratio) # needs sage.libs.pari
|
|
290
|
+
1.618033988749895?
|
|
291
|
+
sage: QQbar(sin(pi/3)) # needs sage.libs.pari
|
|
292
|
+
0.866025403784439?
|
|
293
|
+
|
|
294
|
+
sage: QQbar(sqrt(2) + sqrt(8))
|
|
295
|
+
4.242640687119285?
|
|
296
|
+
sage: AA(sqrt(2) ^ 4) == 4
|
|
297
|
+
True
|
|
298
|
+
sage: AA(-golden_ratio)
|
|
299
|
+
-1.618033988749895?
|
|
300
|
+
sage: QQbar((2*SR(I))^(1/2))
|
|
301
|
+
1 + 1*I
|
|
302
|
+
sage: QQbar(e^(pi*I/3))
|
|
303
|
+
0.50000000000000000? + 0.866025403784439?*I
|
|
304
|
+
|
|
305
|
+
sage: AA(x*sin(0))
|
|
306
|
+
0
|
|
307
|
+
sage: QQbar(x*sin(0))
|
|
308
|
+
0
|
|
309
|
+
"""
|
|
310
|
+
return AlgebraicConverter(field)(ex)
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
# sage.doctest: needs sympy
|
|
3
|
+
r"""
|
|
4
|
+
Conversion of symbolic expressions to SymPy
|
|
5
|
+
"""
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# Copyright (C) 2009 Mike Hansen
|
|
8
|
+
# 2011 D. S. McNeil
|
|
9
|
+
# 2011 Francois Bissey
|
|
10
|
+
# 2017 Ralf Stephan
|
|
11
|
+
# 2017 Marco Mancini
|
|
12
|
+
# 2017 Travis Scrimshaw
|
|
13
|
+
#
|
|
14
|
+
# This program is free software: you can redistribute it and/or modify
|
|
15
|
+
# it under the terms of the GNU General Public License as published by
|
|
16
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
17
|
+
# (at your option) any later version.
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# ****************************************************************************
|
|
20
|
+
|
|
21
|
+
from operator import eq, ne, gt, lt, ge, le, mul, pow, neg, add, truediv
|
|
22
|
+
|
|
23
|
+
from sage.structure.element import Expression
|
|
24
|
+
from sage.symbolic.expression_conversions import Converter
|
|
25
|
+
from sage.symbolic.operators import arithmetic_operators
|
|
26
|
+
|
|
27
|
+
#########
|
|
28
|
+
# Sympy #
|
|
29
|
+
#########
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SympyConverter(Converter):
|
|
33
|
+
"""
|
|
34
|
+
Convert any expression to SymPy.
|
|
35
|
+
|
|
36
|
+
EXAMPLES::
|
|
37
|
+
|
|
38
|
+
sage: import sympy
|
|
39
|
+
sage: var('x,y')
|
|
40
|
+
(x, y)
|
|
41
|
+
sage: f = exp(x^2) - arcsin(pi+x)/y
|
|
42
|
+
sage: f._sympy_()
|
|
43
|
+
exp(x**2) - asin(x + pi)/y
|
|
44
|
+
sage: _._sage_()
|
|
45
|
+
-arcsin(pi + x)/y + e^(x^2)
|
|
46
|
+
|
|
47
|
+
sage: sympy.sympify(x) # indirect doctest
|
|
48
|
+
x
|
|
49
|
+
|
|
50
|
+
TESTS:
|
|
51
|
+
|
|
52
|
+
Make sure we can convert I (:issue:`6424`)::
|
|
53
|
+
|
|
54
|
+
sage: bool(I._sympy_() == I)
|
|
55
|
+
True
|
|
56
|
+
sage: (x+I)._sympy_()
|
|
57
|
+
x + I
|
|
58
|
+
"""
|
|
59
|
+
def __init__(self):
|
|
60
|
+
"""
|
|
61
|
+
TESTS::
|
|
62
|
+
|
|
63
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
64
|
+
sage: s = SympyConverter() # indirect doctest
|
|
65
|
+
sage: TestSuite(s).run(skip='_test_pickling')
|
|
66
|
+
"""
|
|
67
|
+
from sage.interfaces.sympy import sympy_init
|
|
68
|
+
sympy_init()
|
|
69
|
+
|
|
70
|
+
def __call__(self, ex=None):
|
|
71
|
+
"""
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
75
|
+
sage: s = SympyConverter()
|
|
76
|
+
sage: f(x, y) = x^2 + y^2; f
|
|
77
|
+
(x, y) |--> x^2 + y^2
|
|
78
|
+
sage: s(f)
|
|
79
|
+
Lambda((x, y), x**2 + y**2)
|
|
80
|
+
"""
|
|
81
|
+
if isinstance(ex, Expression) and ex.is_callable():
|
|
82
|
+
from sympy import Symbol, Lambda
|
|
83
|
+
return Lambda(tuple(Symbol(str(arg)) for arg in ex.arguments()),
|
|
84
|
+
super().__call__(ex))
|
|
85
|
+
return super().__call__(ex)
|
|
86
|
+
|
|
87
|
+
def pyobject(self, ex, obj):
|
|
88
|
+
"""
|
|
89
|
+
EXAMPLES::
|
|
90
|
+
|
|
91
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
92
|
+
sage: s = SympyConverter()
|
|
93
|
+
sage: f = SR(2)
|
|
94
|
+
sage: s.pyobject(f, f.pyobject())
|
|
95
|
+
2
|
|
96
|
+
sage: type(_)
|
|
97
|
+
<class 'sympy.core.numbers.Integer'>
|
|
98
|
+
"""
|
|
99
|
+
try:
|
|
100
|
+
return obj._sympy_()
|
|
101
|
+
except AttributeError:
|
|
102
|
+
return obj
|
|
103
|
+
|
|
104
|
+
def arithmetic(self, ex, operator):
|
|
105
|
+
"""
|
|
106
|
+
EXAMPLES::
|
|
107
|
+
|
|
108
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
109
|
+
sage: s = SympyConverter()
|
|
110
|
+
sage: f = x + 2
|
|
111
|
+
sage: s.arithmetic(f, f.operator())
|
|
112
|
+
x + 2
|
|
113
|
+
"""
|
|
114
|
+
import sympy
|
|
115
|
+
operator = arithmetic_operators[operator]
|
|
116
|
+
ops = [sympy.sympify(self(a), evaluate=False) for a in ex.operands()]
|
|
117
|
+
if operator == "+":
|
|
118
|
+
return sympy.Add(*ops)
|
|
119
|
+
elif operator == "*":
|
|
120
|
+
return sympy.Mul(*ops)
|
|
121
|
+
elif operator == "-":
|
|
122
|
+
return sympy.Sub(*ops)
|
|
123
|
+
elif operator == "/":
|
|
124
|
+
return sympy.Div(*ops)
|
|
125
|
+
elif operator == "^":
|
|
126
|
+
return sympy.Pow(*ops)
|
|
127
|
+
else:
|
|
128
|
+
raise NotImplementedError
|
|
129
|
+
|
|
130
|
+
def symbol(self, ex):
|
|
131
|
+
"""
|
|
132
|
+
EXAMPLES::
|
|
133
|
+
|
|
134
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
135
|
+
sage: s = SympyConverter()
|
|
136
|
+
sage: s.symbol(x)
|
|
137
|
+
x
|
|
138
|
+
sage: type(_)
|
|
139
|
+
<class 'sympy.core.symbol.Symbol'>
|
|
140
|
+
"""
|
|
141
|
+
import sympy
|
|
142
|
+
return sympy.symbols(repr(ex))
|
|
143
|
+
|
|
144
|
+
def relation(self, ex, op):
|
|
145
|
+
"""
|
|
146
|
+
EXAMPLES::
|
|
147
|
+
|
|
148
|
+
sage: import operator
|
|
149
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
150
|
+
sage: s = SympyConverter()
|
|
151
|
+
sage: s.relation(x == 3, operator.eq)
|
|
152
|
+
Eq(x, 3)
|
|
153
|
+
sage: s.relation(pi < 3, operator.lt)
|
|
154
|
+
pi < 3
|
|
155
|
+
sage: s.relation(x != pi, operator.ne)
|
|
156
|
+
Ne(x, pi)
|
|
157
|
+
sage: s.relation(x > 0, operator.gt)
|
|
158
|
+
x > 0
|
|
159
|
+
"""
|
|
160
|
+
from sympy import Eq, Ne, Gt, Lt, Ge, Le
|
|
161
|
+
ops = {eq: Eq, ne: Ne, gt: Gt, lt: Lt, ge: Ge, le: Le}
|
|
162
|
+
return ops.get(op)(self(ex.lhs()), self(ex.rhs()), evaluate=False)
|
|
163
|
+
|
|
164
|
+
def composition(self, ex, operator):
|
|
165
|
+
"""
|
|
166
|
+
EXAMPLES::
|
|
167
|
+
|
|
168
|
+
sage: from sage.symbolic.expression_conversions import SympyConverter
|
|
169
|
+
sage: s = SympyConverter()
|
|
170
|
+
sage: f = sin(2)
|
|
171
|
+
sage: s.composition(f, f.operator())
|
|
172
|
+
sin(2)
|
|
173
|
+
sage: type(_)
|
|
174
|
+
sin
|
|
175
|
+
sage: f = arcsin(2)
|
|
176
|
+
sage: s.composition(f, f.operator())
|
|
177
|
+
asin(2)
|
|
178
|
+
"""
|
|
179
|
+
g = ex.operands()
|
|
180
|
+
try:
|
|
181
|
+
return operator._sympy_(*g)
|
|
182
|
+
except (AttributeError, TypeError):
|
|
183
|
+
pass
|
|
184
|
+
f = operator._sympy_init_()
|
|
185
|
+
import sympy
|
|
186
|
+
|
|
187
|
+
f_sympy = getattr(sympy, f, None)
|
|
188
|
+
if f_sympy:
|
|
189
|
+
return f_sympy(*sympy.sympify(g, evaluate=False))
|
|
190
|
+
else:
|
|
191
|
+
return sympy.Function(str(f))(*g, evaluate=False)
|
|
192
|
+
|
|
193
|
+
def tuple(self, ex):
|
|
194
|
+
"""
|
|
195
|
+
Conversion of tuples.
|
|
196
|
+
|
|
197
|
+
EXAMPLES::
|
|
198
|
+
|
|
199
|
+
sage: t = SR._force_pyobject((3, 4, e^x))
|
|
200
|
+
sage: t._sympy_()
|
|
201
|
+
(3, 4, e^x)
|
|
202
|
+
sage: t = SR._force_pyobject((cos(x),))
|
|
203
|
+
sage: t._sympy_()
|
|
204
|
+
(cos(x),)
|
|
205
|
+
|
|
206
|
+
TESTS::
|
|
207
|
+
|
|
208
|
+
sage: from sage.symbolic.expression_conversions import sympy_converter
|
|
209
|
+
sage: F = hypergeometric([1/3,2/3],[1,1],x)
|
|
210
|
+
sage: F._sympy_()
|
|
211
|
+
hyper((1/3, 2/3), (1, 1), x)
|
|
212
|
+
|
|
213
|
+
sage: F = hypergeometric([1/3,2/3],[1],x)
|
|
214
|
+
sage: F._sympy_()
|
|
215
|
+
hyper((1/3, 2/3), (1,), x)
|
|
216
|
+
|
|
217
|
+
sage: var('a,b,c,d')
|
|
218
|
+
(a, b, c, d)
|
|
219
|
+
sage: hypergeometric((a,b,),(c,),d)._sympy_()
|
|
220
|
+
hyper((a, b), (c,), d)
|
|
221
|
+
"""
|
|
222
|
+
return tuple(ex.operands())
|
|
223
|
+
|
|
224
|
+
def derivative(self, ex, operator):
|
|
225
|
+
"""
|
|
226
|
+
Convert the derivative of ``self`` in sympy.
|
|
227
|
+
|
|
228
|
+
INPUT:
|
|
229
|
+
|
|
230
|
+
- ``ex`` -- a symbolic expression
|
|
231
|
+
|
|
232
|
+
- ``operator`` -- operator
|
|
233
|
+
|
|
234
|
+
TESTS::
|
|
235
|
+
|
|
236
|
+
sage: var('x','y')
|
|
237
|
+
(x, y)
|
|
238
|
+
|
|
239
|
+
sage: f_sage = function('f_sage')(x, y)
|
|
240
|
+
sage: f_sympy = f_sage._sympy_()
|
|
241
|
+
|
|
242
|
+
sage: df_sage = f_sage.diff(x, 2, y, 1); df_sage
|
|
243
|
+
diff(f_sage(x, y), x, x, y)
|
|
244
|
+
sage: df_sympy = df_sage._sympy_(); df_sympy
|
|
245
|
+
Derivative(f_sage(x, y), (x, 2), y)
|
|
246
|
+
sage: df_sympy == f_sympy.diff(x, 2, y, 1)
|
|
247
|
+
True
|
|
248
|
+
|
|
249
|
+
Check that :issue:`28964` is fixed::
|
|
250
|
+
|
|
251
|
+
sage: f = function('f')
|
|
252
|
+
sage: _ = var('x,t')
|
|
253
|
+
sage: diff(f(x, t), x)._sympy_(), diff(f(x, t), t)._sympy_()
|
|
254
|
+
(Derivative(f(x, t), x), Derivative(f(x, t), t))
|
|
255
|
+
|
|
256
|
+
Check differentiating by variables with multiple occurrences
|
|
257
|
+
(:issue:`28964`)::
|
|
258
|
+
|
|
259
|
+
sage: f = function('f')
|
|
260
|
+
sage: _ = var('x1,x2,x3,x,t')
|
|
261
|
+
sage: f(x, x, t).diff(x)._sympy_()._sage_()
|
|
262
|
+
D[0](f)(x, x, t) + D[1](f)(x, x, t)
|
|
263
|
+
|
|
264
|
+
sage: g = f(x1, x2, x3, t).diff(x1, 2, x2).subs(x1==x, x2==x, x3==x); g
|
|
265
|
+
D[0, 0, 1](f)(x, x, x, t)
|
|
266
|
+
sage: g._sympy_()
|
|
267
|
+
Subs(Derivative(f(_xi_1, _xi_2, x, t), (_xi_1, 2), _xi_2),
|
|
268
|
+
(_xi_1, _xi_2), (x, x))
|
|
269
|
+
sage: assert g._sympy_()._sage_() == g
|
|
270
|
+
|
|
271
|
+
Check that the use of dummy variables does not cause a collision::
|
|
272
|
+
|
|
273
|
+
sage: f = function('f')
|
|
274
|
+
sage: _ = var('x1,x2,x,xi_1')
|
|
275
|
+
sage: g = f(x1, x2, xi_1).diff(x1).subs(x1==x, x2==x); g
|
|
276
|
+
D[0](f)(x, x, xi_1)
|
|
277
|
+
sage: assert g._sympy_()._sage_() == g
|
|
278
|
+
"""
|
|
279
|
+
import sympy
|
|
280
|
+
|
|
281
|
+
# retrieve derivated function
|
|
282
|
+
f = operator.function()
|
|
283
|
+
|
|
284
|
+
# retrieve order
|
|
285
|
+
order = operator._parameter_set
|
|
286
|
+
# arguments
|
|
287
|
+
_args = [a._sympy_() for a in ex.operands()]
|
|
288
|
+
|
|
289
|
+
# when differentiating by a variable that occurs multiple times,
|
|
290
|
+
# substitute it by a dummy variable
|
|
291
|
+
subs_new = []
|
|
292
|
+
subs_old = []
|
|
293
|
+
sympy_arg = []
|
|
294
|
+
for idx in order:
|
|
295
|
+
a = _args[idx]
|
|
296
|
+
if _args.count(a) > 1:
|
|
297
|
+
D = sympy.Dummy('xi_%i' % (idx + 1))
|
|
298
|
+
# to avoid collisions with ordinary symbols when converting
|
|
299
|
+
# back to Sage, we pick an unused variable name for the dummy
|
|
300
|
+
while D._sage_() in ex.variables():
|
|
301
|
+
D = sympy.Dummy(D.name + '_0')
|
|
302
|
+
subs_old.append(a)
|
|
303
|
+
subs_new.append(D)
|
|
304
|
+
_args[idx] = D
|
|
305
|
+
sympy_arg.append(D)
|
|
306
|
+
else:
|
|
307
|
+
sympy_arg.append(a)
|
|
308
|
+
|
|
309
|
+
f_sympy = f._sympy_()(*_args)
|
|
310
|
+
result = f_sympy.diff(*sympy_arg)
|
|
311
|
+
if subs_new:
|
|
312
|
+
return sympy.Subs(result, subs_new, subs_old)
|
|
313
|
+
else:
|
|
314
|
+
return result
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
sympy_converter = SympyConverter()
|