passagemath-symbolics 10.6.43__cp314-cp314t-musllinux_1_2_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.

Files changed (171) hide show
  1. passagemath_symbolics/__init__.py +3 -0
  2. passagemath_symbolics-10.6.43.dist-info/METADATA +187 -0
  3. passagemath_symbolics-10.6.43.dist-info/RECORD +171 -0
  4. passagemath_symbolics-10.6.43.dist-info/WHEEL +5 -0
  5. passagemath_symbolics-10.6.43.dist-info/top_level.txt +3 -0
  6. sage/all__sagemath_symbolics.py +17 -0
  7. sage/calculus/all.py +14 -0
  8. sage/calculus/calculus.py +2826 -0
  9. sage/calculus/desolvers.py +1866 -0
  10. sage/calculus/predefined.py +51 -0
  11. sage/calculus/tests.py +225 -0
  12. sage/calculus/var.cpython-314t-x86_64-linux-musl.so +0 -0
  13. sage/calculus/var.pyx +401 -0
  14. sage/dynamics/all__sagemath_symbolics.py +6 -0
  15. sage/dynamics/complex_dynamics/all.py +5 -0
  16. sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
  17. sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-x86_64-linux-musl.so +0 -0
  18. sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -0
  19. sage/ext/all__sagemath_symbolics.py +1 -0
  20. sage/ext_data/kenzo/CP2.txt +45 -0
  21. sage/ext_data/kenzo/CP3.txt +349 -0
  22. sage/ext_data/kenzo/CP4.txt +4774 -0
  23. sage/ext_data/kenzo/README.txt +49 -0
  24. sage/ext_data/kenzo/S4.txt +20 -0
  25. sage/ext_data/magma/latex/latex.m +1021 -0
  26. sage/ext_data/magma/latex/latex.spec +1 -0
  27. sage/ext_data/magma/sage/basic.m +356 -0
  28. sage/ext_data/magma/sage/sage.spec +1 -0
  29. sage/ext_data/magma/spec +9 -0
  30. sage/geometry/all__sagemath_symbolics.py +8 -0
  31. sage/geometry/hyperbolic_space/all.py +5 -0
  32. sage/geometry/hyperbolic_space/hyperbolic_coercion.py +743 -0
  33. sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
  34. sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
  35. sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
  36. sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -0
  37. sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
  38. sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
  39. sage/geometry/riemannian_manifolds/all.py +7 -0
  40. sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
  41. sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
  42. sage/interfaces/all__sagemath_symbolics.py +1 -0
  43. sage/interfaces/magma.py +3017 -0
  44. sage/interfaces/magma_free.py +92 -0
  45. sage/interfaces/maple.py +1397 -0
  46. sage/interfaces/mathematica.py +1345 -0
  47. sage/interfaces/mathics.py +1312 -0
  48. sage/interfaces/sympy.py +1398 -0
  49. sage/interfaces/sympy_wrapper.py +197 -0
  50. sage/interfaces/tides.py +938 -0
  51. sage/libs/all__sagemath_symbolics.py +6 -0
  52. sage/manifolds/all.py +7 -0
  53. sage/manifolds/calculus_method.py +555 -0
  54. sage/manifolds/catalog.py +437 -0
  55. sage/manifolds/chart.py +4019 -0
  56. sage/manifolds/chart_func.py +3419 -0
  57. sage/manifolds/continuous_map.py +2183 -0
  58. sage/manifolds/continuous_map_image.py +155 -0
  59. sage/manifolds/differentiable/affine_connection.py +2475 -0
  60. sage/manifolds/differentiable/all.py +1 -0
  61. sage/manifolds/differentiable/automorphismfield.py +1383 -0
  62. sage/manifolds/differentiable/automorphismfield_group.py +604 -0
  63. sage/manifolds/differentiable/bundle_connection.py +1445 -0
  64. sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
  65. sage/manifolds/differentiable/chart.py +1241 -0
  66. sage/manifolds/differentiable/curve.py +1028 -0
  67. sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
  68. sage/manifolds/differentiable/degenerate.py +559 -0
  69. sage/manifolds/differentiable/degenerate_submanifold.py +1671 -0
  70. sage/manifolds/differentiable/diff_form.py +1658 -0
  71. sage/manifolds/differentiable/diff_form_module.py +1062 -0
  72. sage/manifolds/differentiable/diff_map.py +1315 -0
  73. sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
  74. sage/manifolds/differentiable/examples/all.py +1 -0
  75. sage/manifolds/differentiable/examples/euclidean.py +2517 -0
  76. sage/manifolds/differentiable/examples/real_line.py +897 -0
  77. sage/manifolds/differentiable/examples/sphere.py +1186 -0
  78. sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
  79. sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
  80. sage/manifolds/differentiable/integrated_curve.py +4035 -0
  81. sage/manifolds/differentiable/levi_civita_connection.py +841 -0
  82. sage/manifolds/differentiable/manifold.py +4254 -0
  83. sage/manifolds/differentiable/manifold_homset.py +1826 -0
  84. sage/manifolds/differentiable/metric.py +3032 -0
  85. sage/manifolds/differentiable/mixed_form.py +1507 -0
  86. sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
  87. sage/manifolds/differentiable/multivector_module.py +800 -0
  88. sage/manifolds/differentiable/multivectorfield.py +1520 -0
  89. sage/manifolds/differentiable/poisson_tensor.py +268 -0
  90. sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
  91. sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
  92. sage/manifolds/differentiable/scalarfield.py +1343 -0
  93. sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
  94. sage/manifolds/differentiable/symplectic_form.py +910 -0
  95. sage/manifolds/differentiable/symplectic_form_test.py +220 -0
  96. sage/manifolds/differentiable/tangent_space.py +412 -0
  97. sage/manifolds/differentiable/tangent_vector.py +616 -0
  98. sage/manifolds/differentiable/tensorfield.py +4665 -0
  99. sage/manifolds/differentiable/tensorfield_module.py +963 -0
  100. sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
  101. sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
  102. sage/manifolds/differentiable/vector_bundle.py +1728 -0
  103. sage/manifolds/differentiable/vectorfield.py +1717 -0
  104. sage/manifolds/differentiable/vectorfield_module.py +2445 -0
  105. sage/manifolds/differentiable/vectorframe.py +1832 -0
  106. sage/manifolds/family.py +270 -0
  107. sage/manifolds/local_frame.py +1490 -0
  108. sage/manifolds/manifold.py +3090 -0
  109. sage/manifolds/manifold_homset.py +452 -0
  110. sage/manifolds/operators.py +359 -0
  111. sage/manifolds/point.py +994 -0
  112. sage/manifolds/scalarfield.py +3718 -0
  113. sage/manifolds/scalarfield_algebra.py +629 -0
  114. sage/manifolds/section.py +3111 -0
  115. sage/manifolds/section_module.py +831 -0
  116. sage/manifolds/structure.py +229 -0
  117. sage/manifolds/subset.py +2764 -0
  118. sage/manifolds/subsets/all.py +1 -0
  119. sage/manifolds/subsets/closure.py +131 -0
  120. sage/manifolds/subsets/pullback.py +885 -0
  121. sage/manifolds/topological_submanifold.py +891 -0
  122. sage/manifolds/trivialization.py +733 -0
  123. sage/manifolds/utilities.py +1348 -0
  124. sage/manifolds/vector_bundle.py +1342 -0
  125. sage/manifolds/vector_bundle_fiber.py +332 -0
  126. sage/manifolds/vector_bundle_fiber_element.py +111 -0
  127. sage/matrix/all__sagemath_symbolics.py +1 -0
  128. sage/matrix/matrix_symbolic_dense.cpython-314t-x86_64-linux-musl.so +0 -0
  129. sage/matrix/matrix_symbolic_dense.pxd +6 -0
  130. sage/matrix/matrix_symbolic_dense.pyx +1022 -0
  131. sage/matrix/matrix_symbolic_sparse.cpython-314t-x86_64-linux-musl.so +0 -0
  132. sage/matrix/matrix_symbolic_sparse.pxd +6 -0
  133. sage/matrix/matrix_symbolic_sparse.pyx +1029 -0
  134. sage/modules/all__sagemath_symbolics.py +1 -0
  135. sage/modules/vector_callable_symbolic_dense.py +105 -0
  136. sage/modules/vector_symbolic_dense.py +116 -0
  137. sage/modules/vector_symbolic_sparse.py +118 -0
  138. sage/rings/all__sagemath_symbolics.py +4 -0
  139. sage/rings/asymptotic/all.py +6 -0
  140. sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
  141. sage/rings/asymptotic/asymptotic_ring.py +4858 -0
  142. sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4153 -0
  143. sage/rings/asymptotic/growth_group.py +5373 -0
  144. sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
  145. sage/rings/asymptotic/term_monoid.py +5237 -0
  146. sage/rings/function_field/all__sagemath_symbolics.py +2 -0
  147. sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
  148. sage/symbolic/all.py +15 -0
  149. sage/symbolic/assumptions.py +985 -0
  150. sage/symbolic/benchmark.py +93 -0
  151. sage/symbolic/callable.py +459 -0
  152. sage/symbolic/complexity_measures.py +35 -0
  153. sage/symbolic/constants.py +1287 -0
  154. sage/symbolic/expression_conversion_algebraic.py +310 -0
  155. sage/symbolic/expression_conversion_sympy.py +317 -0
  156. sage/symbolic/expression_conversions.py +1713 -0
  157. sage/symbolic/function_factory.py +355 -0
  158. sage/symbolic/integration/all.py +1 -0
  159. sage/symbolic/integration/external.py +270 -0
  160. sage/symbolic/integration/integral.py +1115 -0
  161. sage/symbolic/maxima_wrapper.py +162 -0
  162. sage/symbolic/operators.py +267 -0
  163. sage/symbolic/random_tests.py +462 -0
  164. sage/symbolic/relation.py +1907 -0
  165. sage/symbolic/ring.cpython-314t-x86_64-linux-musl.so +0 -0
  166. sage/symbolic/ring.pxd +5 -0
  167. sage/symbolic/ring.pyx +1396 -0
  168. sage/symbolic/subring.py +1025 -0
  169. sage/symbolic/symengine.py +19 -0
  170. sage/symbolic/tests.py +40 -0
  171. sage/symbolic/units.py +1470 -0
@@ -0,0 +1,1345 @@
1
+ # sage_setup: distribution = sagemath-symbolics
2
+ r"""
3
+ Interface to Mathematica
4
+
5
+ The Mathematica interface will only work if Mathematica is installed on your
6
+ computer with a command line interface that runs when you give the ``math``
7
+ command. The interface lets you send certain Sage objects to Mathematica,
8
+ run Mathematica functions, import certain Mathematica expressions to Sage,
9
+ or any combination of the above.
10
+ The Sage command::
11
+
12
+ sage: print(mathematica._install_hints())
13
+ ...
14
+
15
+ prints more information on Mathematica installation.
16
+
17
+ To send a Sage object ``sobj`` to Mathematica, call ``mathematica(sobj)``.
18
+ This exports the Sage object to Mathematica and returns a new Sage object
19
+ wrapping the Mathematica expression/variable, so that you can use the
20
+ Mathematica variable from within Sage. You can then call Mathematica
21
+ functions on the new object; for example::
22
+
23
+ sage: mobj = mathematica(x^2-1) # optional - mathematica
24
+ sage: mobj.Factor() # optional - mathematica
25
+ (-1 + x)*(1 + x)
26
+
27
+ In the above example the factorization is done using Mathematica's
28
+ ``Factor[]`` function.
29
+
30
+ To see Mathematica's output you can simply print the Mathematica wrapper
31
+ object. However if you want to import Mathematica's output back to Sage,
32
+ call the Mathematica wrapper object's ``sage()`` method. This method returns
33
+ a native Sage object::
34
+
35
+ sage: # optional - mathematica
36
+ sage: mobj = mathematica(x^2-1)
37
+ sage: mobj2 = mobj.Factor(); mobj2
38
+ (-1 + x)*(1 + x)
39
+ sage: mobj2.parent()
40
+ Mathematica
41
+ sage: sobj = mobj2.sage(); sobj
42
+ (x + 1)*(x - 1)
43
+ sage: sobj.parent()
44
+ Symbolic Ring
45
+
46
+
47
+ If you want to run a Mathematica function and don't already have the input
48
+ in the form of a Sage object, then it might be simpler to input a string to
49
+ ``mathematica(expr)``. This string will be evaluated as if you had typed it
50
+ into Mathematica::
51
+
52
+ sage: mathematica('Factor[x^2-1]') # optional - mathematica
53
+ (-1 + x)*(1 + x)
54
+ sage: mathematica('Range[3]') # optional - mathematica
55
+ {1, 2, 3}
56
+
57
+ If you don't want Sage to go to the trouble of creating a wrapper for the
58
+ Mathematica expression, then you can call ``mathematica.eval(expr)``, which
59
+ returns the result as a Mathematica AsciiArtString formatted string. If you
60
+ want the result to be a string formatted like Mathematica's InputForm, call
61
+ ``repr(mobj)`` on the wrapper object ``mobj``. If you want a string
62
+ formatted in Sage style, call ``mobj._sage_repr()``::
63
+
64
+ sage: mathematica.eval('x^2 - 1') # optional - mathematica
65
+ 2
66
+ -1 + x
67
+ sage: repr(mathematica('Range[3]')) # optional - mathematica
68
+ '{1, 2, 3}'
69
+ sage: mathematica('Range[3]')._sage_repr() # optional - mathematica
70
+ '[1, 2, 3]'
71
+
72
+ Finally, if you just want to use a Mathematica command line from within
73
+ Sage, the function ``mathematica_console()`` dumps you into an interactive
74
+ command-line Mathematica session. This is an enhanced version of the usual
75
+ Mathematica command-line, in that it provides readline editing and history
76
+ (the usual one doesn't!)
77
+
78
+ Tutorial
79
+ --------
80
+
81
+ We follow some of the tutorial from
82
+ http://library.wolfram.com/conferences/devconf99/withoff/Basic1.html/.
83
+
84
+ For any of this to work you must buy and install the Mathematica
85
+ program, and it must be available as the command
86
+ ``math`` in your PATH.
87
+
88
+ Syntax
89
+ ~~~~~~
90
+
91
+ Now make 1 and add it to itself. The result is a Mathematica
92
+ object.
93
+
94
+ ::
95
+
96
+ sage: m = mathematica
97
+ sage: a = m(1) + m(1); a # optional - mathematica
98
+ 2
99
+ sage: a.parent() # optional - mathematica
100
+ Mathematica
101
+ sage: m('1+1') # optional - mathematica
102
+ 2
103
+ sage: m(3)**m(50) # optional - mathematica
104
+ 717897987691852588770249
105
+
106
+ The following is equivalent to ``Plus[2, 3]`` in
107
+ Mathematica::
108
+
109
+ sage: m = mathematica
110
+ sage: m(2).Plus(m(3)) # optional - mathematica
111
+ 5
112
+
113
+ We can also compute `7(2+3)`.
114
+
115
+ ::
116
+
117
+ sage: m(7).Times(m(2).Plus(m(3))) # optional - mathematica
118
+ 35
119
+ sage: m('7(2+3)') # optional - mathematica
120
+ 35
121
+
122
+ Some typical input
123
+ ~~~~~~~~~~~~~~~~~~
124
+
125
+ We solve an equation and a system of two equations::
126
+
127
+ sage: # optional - mathematica
128
+ sage: eqn = mathematica('3x + 5 == 14')
129
+ sage: eqn
130
+ 5 + 3*x == 14
131
+ sage: eqn.Solve('x')
132
+ {{x -> 3}}
133
+ sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}')
134
+ sage: print(sys)
135
+ 2
136
+ {x - 3 y == 3, 2 x - y == 1}
137
+ sage: sys.Solve('{x, y}')
138
+ {{x -> 0, y -> -1}, {x -> 6, y -> 11}}
139
+
140
+ Assignments and definitions
141
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
142
+
143
+ If you assign the mathematica `5` to a variable `c`
144
+ in Sage, this does not affect the `c` in Mathematica.
145
+
146
+ ::
147
+
148
+ sage: c = m(5) # optional - mathematica
149
+ sage: print(m('b + c x')) # optional - mathematica
150
+ b + c x
151
+ sage: print(m('b') + c*m('x')) # optional - mathematica
152
+ b + 5 x
153
+
154
+ The Sage interfaces changes Sage lists into Mathematica lists::
155
+
156
+ sage: m = mathematica
157
+ sage: eq1 = m('x^2 - 3y == 3') # optional - mathematica
158
+ sage: eq2 = m('2x - y == 1') # optional - mathematica
159
+ sage: v = m([eq1, eq2]); v # optional - mathematica
160
+ {x^2 - 3*y == 3, 2*x - y == 1}
161
+ sage: v.Solve(['x', 'y']) # optional - mathematica
162
+ {{x -> 0, y -> -1}, {x -> 6, y -> 11}}
163
+
164
+ Function definitions
165
+ ~~~~~~~~~~~~~~~~~~~~
166
+
167
+ Define mathematica functions by simply sending the definition to
168
+ the interpreter.
169
+
170
+ ::
171
+
172
+ sage: m = mathematica
173
+ sage: _ = mathematica('f[p_] = p^2'); # optional - mathematica
174
+ sage: m('f[9]') # optional - mathematica
175
+ 81
176
+
177
+ Numerical Calculations
178
+ ~~~~~~~~~~~~~~~~~~~~~~
179
+
180
+ We find the `x` such that `e^x - 3x = 0`.
181
+
182
+ ::
183
+
184
+ sage: eqn = mathematica('Exp[x] - 3x == 0') # optional - mathematica
185
+ sage: eqn.FindRoot(['x', 2]) # optional - mathematica
186
+ {x -> 1.512134551657842}
187
+
188
+ Note that this agrees with what the PARI interpreter gp produces::
189
+
190
+ sage: gp('solve(x=1,2,exp(x)-3*x)') # needs sage.libs.pari
191
+ 1.5121345516578424738967396780720387046
192
+
193
+ Next we find the minimum of a polynomial using the two different
194
+ ways of accessing Mathematica::
195
+
196
+ sage: mathematica('FindMinimum[x^3 - 6x^2 + 11x - 5, {x,3}]') # optional - mathematica
197
+ {0.6150998205402516, {x -> 2.5773502699629733}}
198
+ sage: f = mathematica('x^3 - 6x^2 + 11x - 5') # optional - mathematica
199
+ sage: f.FindMinimum(['x', 3]) # optional - mathematica
200
+ {0.6150998205402516, {x -> 2.5773502699629733}}
201
+
202
+ Polynomial and Integer Factorization
203
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204
+
205
+ We factor a polynomial of degree 200 over the integers.
206
+
207
+ ::
208
+
209
+ sage: R.<x> = PolynomialRing(ZZ)
210
+ sage: f = (x**100+17*x+5)*(x**100-5*x+20)
211
+ sage: f
212
+ x^200 + 12*x^101 + 25*x^100 - 85*x^2 + 315*x + 100
213
+ sage: g = mathematica(str(f)) # optional - mathematica
214
+ sage: print(g) # optional - mathematica
215
+ 2 100 101 200
216
+ 100 + 315 x - 85 x + 25 x + 12 x + x
217
+ sage: g # optional - mathematica
218
+ 100 + 315*x - 85*x^2 + 25*x^100 + 12*x^101 + x^200
219
+ sage: print(g.Factor()) # optional - mathematica
220
+ 100 100
221
+ (20 - 5 x + x ) (5 + 17 x + x )
222
+
223
+ We can also factor a multivariate polynomial::
224
+
225
+ sage: f = mathematica('x^6 + (-y - 2)*x^5 + (y^3 + 2*y)*x^4 - y^4*x^3') # optional - mathematica
226
+ sage: print(f.Factor()) # optional - mathematica
227
+ 3 2 3
228
+ x (x - y) (-2 x + x + y )
229
+
230
+ We factor an integer::
231
+
232
+ sage: # optional - mathematica
233
+ sage: n = mathematica(2434500)
234
+ sage: n.FactorInteger()
235
+ {{2, 2}, {3, 2}, {5, 3}, {541, 1}}
236
+ sage: n = mathematica(2434500)
237
+ sage: F = n.FactorInteger(); F
238
+ {{2, 2}, {3, 2}, {5, 3}, {541, 1}}
239
+ sage: F[1]
240
+ {2, 2}
241
+ sage: F[4]
242
+ {541, 1}
243
+
244
+ Mathematica's ECM package is no longer available.
245
+
246
+ Long Input
247
+ ----------
248
+
249
+ The Mathematica interface reads in even very long input (using
250
+ files) in a robust manner.
251
+
252
+ ::
253
+
254
+ sage: t = '"%s"'%10^10000 # ten thousand character string.
255
+ sage: a = mathematica(t) # optional - mathematica
256
+ sage: a = mathematica.eval(t) # optional - mathematica
257
+
258
+ Loading and saving
259
+ ------------------
260
+
261
+ Mathematica has an excellent ``InputForm`` function,
262
+ which makes saving and loading Mathematica objects possible. The
263
+ first examples test saving and loading to strings.
264
+
265
+ ::
266
+
267
+ sage: # optional - mathematica
268
+ sage: x = mathematica(pi/2)
269
+ sage: print(x)
270
+ Pi
271
+ --
272
+ 2
273
+ sage: loads(dumps(x)) == x
274
+ True
275
+ sage: n = x.N(50)
276
+ sage: print(n)
277
+ 1.5707963267948966192313216916397514420985846996876
278
+ sage: loads(dumps(n)) == n
279
+ True
280
+
281
+ Complicated translations
282
+ ------------------------
283
+
284
+ The ``mobj.sage()`` method tries to convert a Mathematica object to a Sage
285
+ object. In many cases, it will just work. In particular, it should be able to
286
+ convert expressions entirely consisting of:
287
+
288
+ - numbers, i.e. integers, floats, complex numbers;
289
+ - functions and named constants also present in Sage, where:
290
+
291
+ - Sage knows how to translate the function or constant's name from
292
+ Mathematica's, or
293
+ - the Sage name for the function or constant is trivially related to
294
+ Mathematica's;
295
+
296
+ - symbolic variables whose names don't pathologically overlap with
297
+ objects already defined in Sage.
298
+
299
+ This method will not work when Mathematica's output includes:
300
+
301
+ - strings;
302
+ - functions unknown to Sage;
303
+ - Mathematica functions with different parameters/parameter order to
304
+ the Sage equivalent.
305
+
306
+ If you want to convert more complicated Mathematica expressions, you can
307
+ instead call ``mobj._sage_()`` and supply a translation dictionary::
308
+
309
+ sage: m = mathematica('NewFn[x]') # optional - mathematica
310
+ sage: m._sage_(locals={('NewFn', 1): sin}) # optional - mathematica
311
+ sin(x)
312
+
313
+ For more details, see the documentation for ``._sage_()``.
314
+
315
+
316
+ OTHER Examples::
317
+
318
+ sage: def math_bessel_K(nu, x):
319
+ ....: return mathematica(nu).BesselK(x).N(20)
320
+ sage: math_bessel_K(2,I) # optional - mathematica
321
+ -2.59288617549119697817 + 0.18048997206696202663*I
322
+
323
+ ::
324
+
325
+ sage: slist = [[1, 2], 3., 4 + I]
326
+ sage: mlist = mathematica(slist); mlist # optional - mathematica
327
+ {{1, 2}, 3., 4 + I}
328
+ sage: slist2 = list(mlist); slist2 # optional - mathematica
329
+ [{1, 2}, 3., 4 + I]
330
+ sage: slist2[0] # optional - mathematica
331
+ {1, 2}
332
+ sage: slist2[0].parent() # optional - mathematica
333
+ Mathematica
334
+ sage: slist3 = mlist.sage(); slist3 # optional - mathematica
335
+ [[1, 2], 3.00000000000000, I + 4]
336
+
337
+ ::
338
+
339
+ sage: mathematica('10.^80') # optional - mathematica
340
+ 1.*^80
341
+ sage: mathematica('10.^80').sage() # optional - mathematica
342
+ 1.00000000000000e80
343
+
344
+ AUTHORS:
345
+
346
+ - William Stein (2005): first version
347
+
348
+ - Doug Cutrell (2006-03-01): Instructions for use under Cygwin/Windows.
349
+
350
+ - Felix Lawrence (2009-08-21): Added support for importing Mathematica lists
351
+ and floats with exponents.
352
+
353
+ TESTS:
354
+
355
+ Check that numerical approximations via Mathematica's `N[]` function work
356
+ correctly (:issue:`18888`, :issue:`28907`)::
357
+
358
+ sage: # optional - mathematica
359
+ sage: mathematica('Pi/2').N(10)
360
+ 1.5707963268
361
+ sage: mathematica('Pi').N(10)
362
+ 3.1415926536
363
+ sage: mathematica('Pi').N(50)
364
+ 3.14159265358979323846264338327950288419716939937511
365
+ sage: str(mathematica('Pi*x^2-1/2').N())
366
+ 2
367
+ -0.5 + 3.14159 x
368
+
369
+ Check that Mathematica's `E` exponential symbol is correctly backtranslated
370
+ as Sage's `e` (:issue:`29833`)::
371
+
372
+ sage: x = var('x')
373
+ sage: (e^x)._mathematica_().sage() # optional -- mathematica
374
+ e^x
375
+ sage: exp(x)._mathematica_().sage() # optional -- mathematica
376
+ e^x
377
+
378
+ Check that all trig/hyperbolic functions and their reciprocals are correctly
379
+ translated to Mathematica (:issue:`34087`)::
380
+
381
+ sage: # optional - mathematica
382
+ sage: x=var('x')
383
+ sage: FL=[sin, cos, tan, csc, sec, cot,
384
+ ....: sinh, cosh, tanh, csch, sech, coth]
385
+ sage: IFL=[arcsin, arccos, arctan, arccsc,
386
+ ....: arcsec, arccot, arcsinh, arccosh,
387
+ ....: arctanh, arccsch, arcsech, arccoth]
388
+ sage: [mathematica.TrigToExp(u(x)).sage()
389
+ ....: for u in FL]
390
+ [-1/2*I*e^(I*x) + 1/2*I*e^(-I*x),
391
+ 1/2*e^(I*x) + 1/2*e^(-I*x),
392
+ (-I*e^(I*x) + I*e^(-I*x))/(e^(I*x) + e^(-I*x)),
393
+ 2*I/(e^(I*x) - e^(-I*x)),
394
+ 2/(e^(I*x) + e^(-I*x)),
395
+ -(-I*e^(I*x) - I*e^(-I*x))/(e^(I*x) - e^(-I*x)),
396
+ -1/2*e^(-x) + 1/2*e^x,
397
+ 1/2*e^(-x) + 1/2*e^x,
398
+ -e^(-x)/(e^(-x) + e^x) + e^x/(e^(-x) + e^x),
399
+ -2/(e^(-x) - e^x),
400
+ 2/(e^(-x) + e^x),
401
+ -(e^(-x) + e^x)/(e^(-x) - e^x)]
402
+ sage: [mathematica.TrigToExp(u(x)).sage()
403
+ ....: for u in IFL]
404
+ [-I*log(I*x + sqrt(-x^2 + 1)),
405
+ 1/2*pi + I*log(I*x + sqrt(-x^2 + 1)),
406
+ -1/2*I*log(I*x + 1) + 1/2*I*log(-I*x + 1),
407
+ -I*log(sqrt(-1/x^2 + 1) + I/x),
408
+ 1/2*pi + I*log(sqrt(-1/x^2 + 1) + I/x),
409
+ -1/2*I*log(I/x + 1) + 1/2*I*log(-I/x + 1),
410
+ log(x + sqrt(x^2 + 1)),
411
+ log(sqrt(x + 1)*sqrt(x - 1) + x),
412
+ 1/2*log(x + 1) - 1/2*log(-x + 1),
413
+ log(sqrt(1/x^2 + 1) + 1/x),
414
+ log(sqrt(1/x + 1)*sqrt(1/x - 1) + 1/x),
415
+ 1/2*log(1/x + 1) - 1/2*log(-1/x + 1)]
416
+ """
417
+
418
+ # ****************************************************************************
419
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
420
+ #
421
+ # Distributed under the terms of the GNU General Public License (GPL)
422
+ #
423
+ # This code is distributed in the hope that it will be useful,
424
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
425
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
426
+ # General Public License for more details.
427
+ #
428
+ # The full text of the GPL is available at:
429
+ #
430
+ # https://www.gnu.org/licenses/
431
+ # ****************************************************************************
432
+
433
+ import os
434
+ import re
435
+
436
+ from sage.misc.cachefunc import cached_method
437
+ from sage.interfaces.expect import (Expect, ExpectElement, ExpectFunction,
438
+ FunctionElement)
439
+ from sage.interfaces.interface import AsciiArtString
440
+ from sage.interfaces.tab_completion import ExtraTabCompletion
441
+ from sage.misc.instancedoc import instancedoc
442
+ from sage.structure.richcmp import rich_to_bool
443
+
444
+
445
+ def clean_output(s):
446
+ if s is None:
447
+ return ''
448
+ i = s.find('Out[')
449
+ j = i + s[i:].find('=')
450
+ s = s[:i] + ' ' * (j + 1 - i) + s[j + 1:]
451
+ s = s.replace('\\\n', '')
452
+ return s.strip('\n')
453
+
454
+
455
+ def _un_camel(name):
456
+ """
457
+ Convert ``CamelCase`` to ``camel_case``.
458
+
459
+ EXAMPLES::
460
+
461
+ sage: sage.interfaces.mathematica._un_camel('CamelCase')
462
+ 'camel_case'
463
+ sage: sage.interfaces.mathematica._un_camel('EllipticE')
464
+ 'elliptic_e'
465
+ sage: sage.interfaces.mathematica._un_camel('FindRoot')
466
+ 'find_root'
467
+ sage: sage.interfaces.mathematica._un_camel('GCD')
468
+ 'gcd'
469
+ """
470
+ s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
471
+ return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
472
+
473
+
474
+ class Mathematica(ExtraTabCompletion, Expect):
475
+ """
476
+ Interface to the Mathematica interpreter.
477
+ """
478
+ def __init__(self, maxread=None, script_subdirectory=None, logfile=None, server=None,
479
+ server_tmpdir=None, command=None, verbose_start=False):
480
+ r"""
481
+ TESTS:
482
+
483
+ Test that :issue:`28075` is fixed::
484
+
485
+ sage: repr(mathematica.eval("Print[1]; Print[2]; Print[3]")) # optional - mathematica
486
+ '1\n2\n3'
487
+ """
488
+ # We use -rawterm to get a raw text interface in Mathematica 9 or later.
489
+ # This works around the following issues of Mathematica 9 or later
490
+ # (tested with Mathematica 11.0.1 for Mac OS X x86 (64-bit))
491
+ #
492
+ # 1) If TERM is unset and input is a pseudoterminal, Mathematica shows no
493
+ # prompts, so pexpect will not work.
494
+ #
495
+ # 2) If TERM is set (to dumb, lpr, vt100, or xterm), there will be
496
+ # prompts; but there is bizarre echoing behavior by Mathematica (not
497
+ # the terminal driver). For example, with TERM=dumb, many spaces and
498
+ # \r's are echoed. With TERM=vt100 or better, in addition, many escape
499
+ # sequences are printed.
500
+ #
501
+ if command is None:
502
+ command = os.getenv('SAGE_MATHEMATICA_COMMAND') or 'math -rawterm'
503
+ eval_using_file_cutoff = 1024
504
+ # Removing terminal echo using "stty -echo" is not essential but it slightly
505
+ # improves performance (system time) and eliminates races of the terminal echo
506
+ # as a possible source of error.
507
+ if server:
508
+ command = 'stty -echo; {}'.format(command)
509
+ else:
510
+ command = 'sh -c "stty -echo; {}"'.format(command)
511
+ Expect.__init__(self,
512
+ name='mathematica',
513
+ terminal_echo=False,
514
+ command=command,
515
+ prompt=r'In\[[0-9]+\]:= ',
516
+ server=server,
517
+ server_tmpdir=server_tmpdir,
518
+ script_subdirectory=script_subdirectory,
519
+ verbose_start=verbose_start,
520
+ logfile=logfile,
521
+ eval_using_file_cutoff=eval_using_file_cutoff)
522
+
523
+ def _read_in_file_command(self, filename):
524
+ return '<<"%s"' % filename
525
+
526
+ def _keyboard_interrupt(self):
527
+ print("Interrupting %s..." % self)
528
+ e = self._expect
529
+ e.sendline(chr(3)) # send ctrl-c
530
+ e.expect('Interrupt> ')
531
+ e.sendline("a") # a -- abort
532
+ e.expect(self._prompt)
533
+ return e.before
534
+
535
+ def _install_hints(self):
536
+ """
537
+ Hints for installing mathematica on your computer.
538
+
539
+ AUTHORS:
540
+
541
+ - William Stein and Justin Walker (2006-02-12)
542
+ """
543
+ return """
544
+ In order to use the Mathematica interface you need to have Mathematica
545
+ installed and have a script in your PATH called "math" that runs the
546
+ command-line version of Mathematica. Alternatively, you could use a
547
+ remote connection to a server running Mathematica -- for hints, type
548
+ print(mathematica._install_hints_ssh())
549
+
550
+
551
+ (1) You might have to buy Mathematica (https://www.wolfram.com/), or
552
+ install a currently (Feb 2022) free for personal use Wolfram Engine
553
+ (https://www.wolfram.com/engine/).
554
+
555
+ (2) * LINUX: The math script usually comes standard with your Mathematica install.
556
+ However, on some systems it may be called wolfram,
557
+ or, in case of Wolfram Engine, wolframengine, while math is absent.
558
+ In this case, assuming wolfram, respectively, wolframengine,
559
+ is in your PATH,
560
+ (a) create a file called math (in your PATH):
561
+ #!/bin/sh
562
+ /usr/bin/env wolfram $@
563
+
564
+ respectively,
565
+ (a') create a file called math (in your PATH):
566
+ #!/bin/sh
567
+ /usr/bin/env wolframengine $@
568
+
569
+ (b) Make the file executable.
570
+ chmod +x math
571
+
572
+ * Apple macOS: for Mathematica,
573
+ (a) create a file called math (in your PATH):
574
+ #!/bin/sh
575
+ /Applications/Mathematica.app/Contents/MacOS/MathKernel $@
576
+
577
+ (a') for Wolfram Engine, follow the Linux step (a') above.
578
+
579
+ The path in the above script must be modified if you installed
580
+ Mathematica elsewhere or installed an old version of
581
+ Mathematica that has the version in the .app name.
582
+
583
+ (b) Make the file executable.
584
+ chmod +x math
585
+
586
+ * WINDOWS:
587
+
588
+ Install Mathematica for Linux into the VMware virtual machine, or in
589
+ a WSL/WSL2 Linux installation with Sage installed there (sorry,
590
+ that's the only ways at present).
591
+ """
592
+
593
+ def eval(self, code, strip=True, **kwds):
594
+ s = Expect.eval(self, code, **kwds)
595
+ if strip:
596
+ return AsciiArtString(clean_output(s))
597
+ else:
598
+ return AsciiArtString(s)
599
+
600
+ def set(self, var, value):
601
+ """
602
+ Set the variable var to the given value.
603
+ """
604
+ cmd = '%s=%s;' % (var, value)
605
+ out = self._eval_line(cmd, allow_use_file=True)
606
+ if len(out) > 8:
607
+ raise TypeError("Error executing code in Mathematica\nCODE:\n\t%s\nMathematica ERROR:\n\t%s" % (cmd, out))
608
+
609
+ def get(self, var, ascii_art=False):
610
+ """
611
+ Get the value of the variable var.
612
+
613
+ AUTHORS:
614
+
615
+ - William Stein
616
+
617
+ - Kiran Kedlaya (2006-02-04): suggested using InputForm
618
+ """
619
+ if ascii_art:
620
+ return self.eval(var, strip=True)
621
+ return self.eval('InputForm[%s, NumberMarks->False]' % var, strip=True)
622
+
623
+ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if_needed=False):
624
+ s = Expect._eval_line(self, line,
625
+ allow_use_file=allow_use_file, wait_for_prompt=wait_for_prompt)
626
+ return str(s).strip('\n')
627
+
628
+ def _function_call_string(self, function, args, kwds):
629
+ """
630
+ Return the string used to make function calls.
631
+
632
+ EXAMPLES::
633
+
634
+ sage: mathematica._function_call_string('Sin', ['x'], [])
635
+ 'Sin[x]'
636
+ """
637
+ return "%s[%s]" % (function, ",".join(args))
638
+
639
+ def _left_list_delim(self):
640
+ return "{"
641
+
642
+ def _right_list_delim(self):
643
+ return "}"
644
+
645
+ def _left_func_delim(self):
646
+ return "["
647
+
648
+ def _right_func_delim(self):
649
+ return "]"
650
+
651
+ ###########################################
652
+ # System -- change directory, etc.
653
+ ###########################################
654
+ def chdir(self, dir):
655
+ """
656
+ Change Mathematica's current working directory.
657
+
658
+ EXAMPLES::
659
+
660
+ sage: mathematica.chdir('/') # optional - mathematica
661
+ sage: mathematica('Directory[]') # optional - mathematica
662
+ "/"
663
+ """
664
+ self.eval('SetDirectory["%s"]' % dir)
665
+
666
+ def _true_symbol(self):
667
+ return 'True'
668
+
669
+ def _false_symbol(self):
670
+ return 'False'
671
+
672
+ def _equality_symbol(self):
673
+ return '=='
674
+
675
+ def _assign_symbol(self):
676
+ return ":="
677
+
678
+ def _exponent_symbol(self):
679
+ """
680
+ Return the symbol used to denote the exponent of a number in
681
+ Mathematica.
682
+
683
+ EXAMPLES::
684
+
685
+ sage: mathematica._exponent_symbol() # optional - mathematica
686
+ '*^'
687
+
688
+ ::
689
+
690
+ sage: bignum = mathematica('10.^80') # optional - mathematica
691
+ sage: repr(bignum) # optional - mathematica
692
+ '1.*^80'
693
+ sage: repr(bignum).replace(mathematica._exponent_symbol(), 'e').strip() # optional - mathematica
694
+ '1.e80'
695
+ """
696
+ return "*^"
697
+
698
+ def _object_class(self):
699
+ return MathematicaElement
700
+
701
+ def console(self, readline=True):
702
+ mathematica_console(readline=readline)
703
+
704
+ def _tab_completion(self):
705
+ a = self.eval('Names["*"]')
706
+ return a.replace('$', '').replace('\n \n>', '').replace(',', '').replace('}', '').replace('{', '').split()
707
+
708
+ def help(self, cmd):
709
+ return self.eval('? %s' % cmd)
710
+
711
+ def __getattr__(self, attrname):
712
+ if attrname[:1] == "_":
713
+ raise AttributeError
714
+ return MathematicaFunction(self, attrname)
715
+
716
+
717
+ @instancedoc
718
+ class MathematicaElement(ExpectElement):
719
+ def __getitem__(self, n):
720
+ return self.parent().new('%s[[%s]]' % (self._name, n))
721
+
722
+ def __getattr__(self, attrname):
723
+ self._check_valid()
724
+ if attrname[:1] == "_":
725
+ raise AttributeError
726
+ return MathematicaFunctionElement(self, attrname)
727
+
728
+ def __float__(self, precision=16):
729
+ P = self.parent()
730
+ return float(P.eval('N[%s,%s]' % (self.name(), precision)))
731
+
732
+ def _reduce(self):
733
+ return self.parent().eval('InputForm[%s]' % self.name()).strip()
734
+
735
+ def __reduce__(self):
736
+ return reduce_load, (self._reduce(), )
737
+
738
+ def _latex_(self):
739
+ z = self.parent().eval('TeXForm[%s]' % self.name())
740
+ i = z.find('=')
741
+ return z[i + 1:].strip()
742
+
743
+ def _repr_(self):
744
+ P = self.parent()
745
+ return P.get(self._name, ascii_art=False).strip()
746
+
747
+ def _sage_(self, locals={}):
748
+ r"""
749
+ Attempt to return a Sage version of this object.
750
+
751
+ This method works successfully when Mathematica returns a result
752
+ or list of results that consist only of:
753
+
754
+ - numbers, i.e. integers, floats, complex numbers;
755
+ - functions and named constants also present in Sage, where:
756
+ - Sage knows how to translate the function or constant's name
757
+ from Mathematica's naming scheme, or
758
+ - you provide a translation dictionary `locals`, or
759
+ - the Sage name for the function or constant is simply the
760
+ Mathematica name in lower case;
761
+
762
+ - symbolic variables whose names do not pathologically overlap with
763
+ objects already defined in Sage.
764
+
765
+ This method will not work when Mathematica's output includes:
766
+
767
+ - strings;
768
+ - functions unknown to Sage that are not specified in `locals`;
769
+ - Mathematica functions with different parameters/parameter order to
770
+ the Sage equivalent. In this case, define a function to do the
771
+ parameter conversion, and pass it in via the locals dictionary.
772
+
773
+ EXAMPLES:
774
+
775
+ Mathematica lists of numbers/constants become Sage lists of
776
+ numbers/constants::
777
+
778
+ sage: # optional - mathematica
779
+ sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}')
780
+ sage: s = m.sage(); s
781
+ [[1.00000000000000, 4], pi, 3.20000000000000*e100, I]
782
+ sage: s[1].n()
783
+ 3.14159265358979
784
+ sage: s[3]^2
785
+ -1
786
+
787
+ ::
788
+
789
+ sage: m = mathematica('x^2 + 5*y') # optional - mathematica
790
+ sage: m.sage() # optional - mathematica
791
+ x^2 + 5*y
792
+
793
+ ::
794
+
795
+ sage: m = mathematica('Sin[Sqrt[1-x^2]] * (1 - Cos[1/x])^2') # optional - mathematica
796
+ sage: m.sage() # optional - mathematica
797
+ (cos(1/x) - 1)^2*sin(sqrt(-x^2 + 1))
798
+
799
+ ::
800
+
801
+ sage: m = mathematica('NewFn[x]') # optional - mathematica
802
+ sage: m._sage_(locals={('NewFn', 1): sin}) # optional - mathematica
803
+ sin(x)
804
+
805
+ ::
806
+
807
+ sage: var('bla') # optional - mathematica
808
+ bla
809
+ sage: m = mathematica('bla^2') # optional - mathematica
810
+ sage: bla^2 - m.sage() # optional - mathematica
811
+ 0
812
+
813
+ ::
814
+
815
+ sage: # optional - mathematica
816
+ sage: m = mathematica('bla^2')
817
+ sage: mb = m.sage()
818
+ sage: var('bla')
819
+ bla
820
+ sage: bla^2 - mb
821
+ 0
822
+
823
+
824
+ AUTHORS:
825
+
826
+ - Felix Lawrence (2010-11-03): Major rewrite to use ._sage_repr() and
827
+ sage.calculus.calculus.symbolic_expression_from_string() for greater
828
+ compatibility, while still supporting conversion of symbolic
829
+ expressions.
830
+
831
+ TESTS:
832
+
833
+ Check that :issue:`28814` is fixed::
834
+
835
+ sage: mathematica('Exp[1000.0]').sage() # optional - mathematica
836
+ 1.97007111401700e434
837
+ sage: mathematica('1/Exp[1000.0]').sage() # optional - mathematica
838
+ 5.07595889754950e-435
839
+ sage: mathematica(RealField(100)(1/3)).sage() # optional - mathematica
840
+ 0.3333333333333333333333333333335
841
+ """
842
+ from sage.symbolic.expression import symbol_table
843
+ from sage.symbolic.constants import constants_name_table as constants
844
+ from sage.calculus.calculus import symbolic_expression_from_string
845
+ from sage.calculus.calculus import _find_func as find_func
846
+
847
+ # Get Mathematica's output and perform preliminary formatting
848
+ res = self._sage_repr()
849
+ if '"' in res:
850
+ raise NotImplementedError("String conversion from Mathematica \
851
+ does not work. Mathematica's output was: %s" % res)
852
+
853
+ # Find all the mathematica functions, constants and symbolic variables
854
+ # present in `res`. Convert MMA functions and constants to their
855
+ # Sage equivalents (if possible), using `locals` and
856
+ # `sage.symbolic.pynac.symbol_table['mathematica']` as translation
857
+ # dictionaries. If a MMA function or constant is not in either
858
+ # dictionary, then we use a variety of tactics listed in `autotrans`.
859
+ # If a MMA variable is not in any dictionary, then create an
860
+ # identically named Sage equivalent.
861
+
862
+ # Merge the user-specified locals dictionary and the symbol_table
863
+ # (locals takes priority)
864
+ lsymbols = symbol_table['mathematica'].copy()
865
+ lsymbols.update(locals)
866
+
867
+ # Strategies for translating unknown functions/constants:
868
+ autotrans = [str.lower, # Try it in lower case
869
+ _un_camel, # Convert `CamelCase` to `camel_case`
870
+ lambda x: x] # Try the original name
871
+
872
+ # Find the MMA funcs/vars/constants - they start with a letter.
873
+ # Exclude exponents (e.g. 'e8' from 4.e8)
874
+ p = re.compile(r'(?<!\.)[a-zA-Z]\w*')
875
+ for m in p.finditer(res):
876
+ # If the function, variable or constant is already in the
877
+ # translation dictionary, then just move on.
878
+ if m.group() in lsymbols:
879
+ pass
880
+ # Now try to translate all other functions -- try each strategy
881
+ # in `autotrans` and check if the function exists in Sage
882
+ elif m.end() < len(res) and res[m.end()] == '(':
883
+ for t in autotrans:
884
+ f = find_func(t(m.group()), create_when_missing=False)
885
+ if f is not None:
886
+ lsymbols[m.group()] = f
887
+ break
888
+ else:
889
+ raise NotImplementedError("Don't know a Sage equivalent \
890
+ for Mathematica function '%s'. Please specify one \
891
+ manually using the 'locals' dictionary" % m.group())
892
+ # Check if Sage has an equivalent constant
893
+ else:
894
+ for t in autotrans:
895
+ if t(m.group()) in constants:
896
+ lsymbols[m.group()] = constants[t(m.group())]
897
+ break
898
+ # If Sage has never heard of the variable, then
899
+ # symbolic_expression_from_string will automatically create it
900
+ try:
901
+ return symbolic_expression_from_string(res, lsymbols,
902
+ accept_sequence=True)
903
+ except Exception:
904
+ raise NotImplementedError("Unable to parse Mathematica \
905
+ output: %s" % res)
906
+
907
+ def __str__(self):
908
+ P = self._check_valid()
909
+ return P.get(self._name, ascii_art=True)
910
+
911
+ def __len__(self):
912
+ """
913
+ Return the object's length, evaluated by mathematica.
914
+
915
+ EXAMPLES::
916
+
917
+ sage: len(mathematica([1,1.,2])) # optional - mathematica
918
+ 3
919
+
920
+ AUTHORS:
921
+ - Felix Lawrence (2009-08-21)
922
+ """
923
+ return int(self.Length())
924
+
925
+ @cached_method
926
+ def _is_graphics(self):
927
+ """
928
+ Test whether the mathematica expression is graphics.
929
+
930
+ OUTPUT: boolean
931
+
932
+ EXAMPLES::
933
+
934
+ sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica
935
+ sage: P._is_graphics() # optional - mathematica
936
+ True
937
+ """
938
+ P = self._check_valid()
939
+ return P.eval('InputForm[%s]' % self.name()).strip().startswith('Graphics[')
940
+
941
+ def save_image(self, filename, ImageSize=600):
942
+ r"""
943
+ Save a mathematica graphics.
944
+
945
+ INPUT:
946
+
947
+ - ``filename`` -- string; the filename to save as. The
948
+ extension determines the image file format
949
+
950
+ - ``ImageSize`` -- integer; the size of the resulting image
951
+
952
+ EXAMPLES::
953
+
954
+ sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica
955
+ sage: filename = tmp_filename() # optional - mathematica
956
+ sage: P.save_image(filename, ImageSize=800) # optional - mathematica
957
+ """
958
+ P = self._check_valid()
959
+ if not self._is_graphics():
960
+ raise ValueError('mathematica expression is not graphics')
961
+ filename = os.path.abspath(filename)
962
+ s = 'Export["%s", %s, ImageSize->%s]' % (filename, self.name(),
963
+ ImageSize)
964
+ P.eval(s)
965
+
966
+ def _rich_repr_(self, display_manager, **kwds):
967
+ """
968
+ Rich Output Magic Method.
969
+
970
+ See :mod:`sage.repl.rich_output` for details.
971
+
972
+ EXAMPLES::
973
+
974
+ sage: from sage.repl.rich_output import get_display_manager
975
+ sage: dm = get_display_manager()
976
+ sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica
977
+
978
+ The following test requires a working X display on Linux so that the
979
+ Mathematica frontend can do the rendering (:issue:`23112`)::
980
+
981
+ sage: P._rich_repr_(dm) # optional - mathematica mathematicafrontend
982
+ OutputImagePng container
983
+ """
984
+ if self._is_graphics():
985
+ OutputImagePng = display_manager.types.OutputImagePng
986
+ if display_manager.preferences.graphics == 'disable':
987
+ return
988
+ if OutputImagePng in display_manager.supported_output():
989
+ return display_manager.graphics_from_save(
990
+ self.save_image, kwds, '.png', OutputImagePng)
991
+ else:
992
+ OutputLatex = display_manager.types.OutputLatex
993
+ dmp = display_manager.preferences.text
994
+ if dmp is None or dmp == 'plain':
995
+ return
996
+ if dmp == 'latex' and OutputLatex in display_manager.supported_output():
997
+ return OutputLatex(self._latex_())
998
+
999
+ def show(self, ImageSize=600):
1000
+ r"""
1001
+ Show a mathematica expression immediately.
1002
+
1003
+ This method attempts to display the graphics immediately,
1004
+ without waiting for the currently running code (if any) to
1005
+ return to the command line. Be careful, calling it from within
1006
+ a loop will potentially launch a large number of external
1007
+ viewer programs.
1008
+
1009
+ INPUT:
1010
+
1011
+ - ``ImageSize`` -- integer; the size of the resulting image
1012
+
1013
+ OUTPUT:
1014
+
1015
+ This method does not return anything. Use :meth:`save` if you
1016
+ want to save the figure as an image.
1017
+
1018
+ EXAMPLES::
1019
+
1020
+ sage: Q = mathematica('Sin[x Cos[y]]/Sqrt[1-x^2]') # optional - mathematica
1021
+ sage: show(Q) # optional - mathematica
1022
+ Sin[x*Cos[y]]/Sqrt[1 - x^2]
1023
+
1024
+ The following example starts a Mathematica frontend to do the rendering
1025
+ (:issue:`28819`)::
1026
+
1027
+ sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]') # optional - mathematica
1028
+ sage: show(P) # optional - mathematica mathematicafrontend
1029
+ sage: P.show(ImageSize=800) # optional - mathematica mathematicafrontend
1030
+ """
1031
+ from sage.repl.rich_output import get_display_manager
1032
+ dm = get_display_manager()
1033
+ dm.display_immediately(self, ImageSize=ImageSize)
1034
+
1035
+ def str(self):
1036
+ return str(self)
1037
+
1038
+ def _richcmp_(self, other, op):
1039
+ P = self.parent()
1040
+ if P.eval("%s < %s" % (self.name(), other.name())).strip() == 'True':
1041
+ return rich_to_bool(op, -1)
1042
+ elif P.eval("%s > %s" % (self.name(), other.name())).strip() == 'True':
1043
+ return rich_to_bool(op, 1)
1044
+ elif P.eval("%s == %s" % (self.name(), other.name())).strip() == 'True':
1045
+ return rich_to_bool(op, 0)
1046
+ return NotImplemented
1047
+
1048
+ def __bool__(self):
1049
+ """
1050
+ Return whether this Mathematica element is not identical to ``False``.
1051
+
1052
+ EXAMPLES::
1053
+
1054
+ sage: bool(mathematica(True)) # optional - mathematica
1055
+ True
1056
+ sage: bool(mathematica(False)) # optional - mathematica
1057
+ False
1058
+
1059
+ In Mathematica, `0` cannot be used to express falsity::
1060
+
1061
+ sage: bool(mathematica(0)) # optional - mathematica
1062
+ True
1063
+ """
1064
+ P = self._check_valid()
1065
+ cmd = '%s===%s' % (self._name, P._false_symbol())
1066
+ return P.eval(cmd).strip() != P._true_symbol()
1067
+
1068
+ def n(self, *args, **kwargs):
1069
+ r"""
1070
+ Numerical approximation by converting to Sage object first.
1071
+
1072
+ Convert the object into a Sage object and return its numerical
1073
+ approximation. See documentation of the function
1074
+ :func:`sage.misc.functional.n` for details.
1075
+
1076
+ EXAMPLES::
1077
+
1078
+ sage: mathematica('Pi').n(10) # optional -- mathematica
1079
+ 3.1
1080
+ sage: mathematica('Pi').n() # optional -- mathematica
1081
+ 3.14159265358979
1082
+ sage: mathematica('Pi').n(digits=10) # optional -- mathematica
1083
+ 3.141592654
1084
+ """
1085
+ return self._sage_().n(*args, **kwargs)
1086
+
1087
+
1088
+ @instancedoc
1089
+ class MathematicaFunction(ExpectFunction):
1090
+ def _instancedoc_(self):
1091
+ M = self._parent
1092
+ return M.help(self._name)
1093
+
1094
+
1095
+ @instancedoc
1096
+ class MathematicaFunctionElement(FunctionElement):
1097
+ def _instancedoc_(self):
1098
+ M = self._obj.parent()
1099
+ return M.help(self._name)
1100
+
1101
+
1102
+ # An instance
1103
+ mathematica = Mathematica()
1104
+
1105
+
1106
+ def reduce_load(X):
1107
+ return mathematica(X)
1108
+
1109
+
1110
+ def mathematica_console(readline=True):
1111
+ from sage.repl.rich_output.display_manager import get_display_manager
1112
+ if not get_display_manager().is_in_terminal():
1113
+ raise RuntimeError('Can use the console only in the terminal. Try %%mathematica magics instead.')
1114
+ if not readline:
1115
+ os.system('math')
1116
+ return
1117
+ else:
1118
+ os.system('math-readline')
1119
+ return
1120
+
1121
+
1122
+ # some tools for online interface
1123
+
1124
+ def request_wolfram_alpha(input, verbose=False):
1125
+ r"""
1126
+ Request Wolfram Alpha website.
1127
+
1128
+ INPUT:
1129
+
1130
+ - ``input`` -- string
1131
+ - ``verbose`` -- boolean (default: ``False``)
1132
+
1133
+ OUTPUT: json
1134
+
1135
+ EXAMPLES::
1136
+
1137
+ sage: from sage.interfaces.mathematica import request_wolfram_alpha
1138
+ sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
1139
+ sage: [str(a) for a in sorted(page_data.keys())] # optional internet
1140
+ ['queryresult']
1141
+ sage: [str(a) for a in sorted(page_data['queryresult'].keys())] # optional internet
1142
+ ['datatypes',
1143
+ 'encryptedEvaluatedExpression',
1144
+ 'encryptedParsedExpression',
1145
+ 'error',
1146
+ 'host',
1147
+ 'id',
1148
+ 'inputstring',
1149
+ 'numpods',
1150
+ 'parsetimedout',
1151
+ 'parsetiming',
1152
+ 'pods',
1153
+ 'recalculate',
1154
+ 'related',
1155
+ 'server',
1156
+ 'sponsorCategories',
1157
+ 'success',
1158
+ 'timedout',
1159
+ 'timedoutpods',
1160
+ 'timing',
1161
+ 'version']
1162
+ """
1163
+ from urllib.parse import urlencode
1164
+ from urllib.request import Request, build_opener, HTTPCookieProcessor, HTTPSHandler
1165
+ import json
1166
+ from http.cookiejar import CookieJar
1167
+ from ssl import create_default_context as default_context
1168
+
1169
+ # we need cookies for this...
1170
+ cj = CookieJar()
1171
+ opener = build_opener(HTTPCookieProcessor(cj),
1172
+ HTTPSHandler(context=default_context()))
1173
+ # build initial query for code
1174
+ req = Request("https://www.wolframalpha.com/input/api/v1/code")
1175
+ resp = opener.open(req)
1176
+ # the website returns JSON containing the code
1177
+ page_data = json.loads(resp.read().decode("utf-8"))
1178
+ if "code" not in page_data:
1179
+ raise ValueError("Wolfram did not return a code")
1180
+ proxy_code = page_data['code']
1181
+ if verbose:
1182
+ print("Code: {}".format(proxy_code))
1183
+ print("Cookies: {}".format(cj))
1184
+ # now we can make a request
1185
+ # some parameters documented here:
1186
+ # https://products.wolframalpha.com/api/documentation/#parameter-reference
1187
+ # the following are the parameters used by the website
1188
+ params = {
1189
+ 'assumptionsversion': '2',
1190
+ 'async': 'true',
1191
+ 'banners': 'raw',
1192
+ 'debuggingdata': 'false',
1193
+ 'format': 'image,plaintext,imagemap,sound,minput,moutput',
1194
+ 'formattimeout': '8',
1195
+ 'input': input,
1196
+ 'output': 'JSON',
1197
+ 'parsetimeout': '5',
1198
+ 'podinfosasync': 'true',
1199
+ 'proxycode': proxy_code,
1200
+ 'recalcscheme': 'parallel',
1201
+ 'sbsdetails': 'true',
1202
+ 'scantimeout': '0.5',
1203
+ 'sponsorcategories': 'true',
1204
+ 'statemethod': 'deploybutton',
1205
+ 'storesubpodexprs': 'true'}
1206
+ # # we can also change some parameters
1207
+ # params = {
1208
+ # 'assumptionsversion': '2',
1209
+ # 'banners': 'raw',
1210
+ # 'format': 'minput,moutput',
1211
+ # 'formattimeout': '8',
1212
+ # 'input': input,
1213
+ # 'output': 'JSON',
1214
+ # 'parsetimeout': '5',
1215
+ # 'proxycode': proxy_code,
1216
+ # 'scantimeout': '0.5',
1217
+ # 'storesubpodexprs': 'true'
1218
+ # }
1219
+ params = urlencode(params)
1220
+ url = "https://www.wolframalpha.com/input/json.jsp?%s" % params
1221
+ req = Request(url)
1222
+ req.add_header('Referer', "https://www.wolframalpha.com/input/") # seems important
1223
+ resp = opener.open(req)
1224
+ # the website returns JSON containing the code
1225
+ return json.loads(resp.read().decode("utf-8"))
1226
+
1227
+
1228
+ def parse_moutput_from_json(page_data, verbose=False):
1229
+ r"""
1230
+ Return the list of outputs found in the json (with key ``'moutput'``).
1231
+
1232
+ INPUT:
1233
+
1234
+ - ``page_data`` -- json obtained from Wolfram Alpha
1235
+ - ``verbose`` -- boolean (default: ``False``)
1236
+
1237
+ OUTPUT: list of unicode strings
1238
+
1239
+ EXAMPLES::
1240
+
1241
+ sage: from sage.interfaces.mathematica import request_wolfram_alpha
1242
+ sage: from sage.interfaces.mathematica import parse_moutput_from_json
1243
+ sage: page_data = request_wolfram_alpha('integrate Sin[x]') # optional internet
1244
+ sage: parse_moutput_from_json(page_data) # optional internet
1245
+ ['-Cos[x]']
1246
+
1247
+ ::
1248
+
1249
+ sage: page_data = request_wolfram_alpha('Sin[x]') # optional internet
1250
+ sage: L = parse_moutput_from_json(page_data) # optional internet
1251
+ sage: sorted(L) # optional internet
1252
+ ['-Cos[x]', '{x == 0}', '{x == Pi C[1], Element[C[1], Integers]}']
1253
+
1254
+ TESTS::
1255
+
1256
+ sage: page_data = request_wolfram_alpha('Integrate(Sin[z], y)') # optional internet
1257
+ sage: parse_moutput_from_json(page_data) # optional internet
1258
+ Traceback (most recent call last):
1259
+ ...
1260
+ ValueError: asking wolframalpha.com was not successful
1261
+ """
1262
+ queryresult = page_data['queryresult']
1263
+ if not queryresult['success']:
1264
+ raise ValueError('asking wolframalpha.com was not successful')
1265
+ if 'pods' not in queryresult:
1266
+ raise ValueError('json object contains no pods')
1267
+ pods = queryresult['pods']
1268
+ if verbose:
1269
+ print(" Query successful: {}".format(queryresult['success']))
1270
+ print(" Number of results: {}".format(len(pods)))
1271
+ L = []
1272
+ for i, result in enumerate(pods):
1273
+ if verbose:
1274
+ print(" Result #{}".format(i))
1275
+ print(" Title: {}".format(result['title']))
1276
+ if 'subpods' not in result:
1277
+ continue
1278
+ subpods = result['subpods']
1279
+ for j, subpod in enumerate(subpods):
1280
+ if verbose:
1281
+ print(" Subpod #{}".format(j))
1282
+ if 'minput' in subpod.keys():
1283
+ print(" MInput: {}".format(subpod['minput']))
1284
+ if 'moutput' in subpod.keys():
1285
+ print(" MOutput: {}".format(subpod['moutput']))
1286
+ if 'moutput' in subpod.keys():
1287
+ L.append(subpod['moutput'])
1288
+ return L
1289
+
1290
+
1291
+ def symbolic_expression_from_mathematica_string(mexpr):
1292
+ r"""
1293
+ Translate a mathematica string into a symbolic expression.
1294
+
1295
+ INPUT:
1296
+
1297
+ - ``mexpr`` -- string
1298
+
1299
+ OUTPUT: symbolic expression
1300
+
1301
+ EXAMPLES::
1302
+
1303
+ sage: from sage.interfaces.mathematica import symbolic_expression_from_mathematica_string
1304
+ sage: symbolic_expression_from_mathematica_string('-Cos[x]')
1305
+ -cos(x)
1306
+ """
1307
+ from sage.symbolic.expression import symbol_table
1308
+ from sage.symbolic.constants import constants_name_table as constants
1309
+ from sage.calculus.calculus import symbolic_expression_from_string
1310
+ from sage.calculus.calculus import _find_func as find_func
1311
+
1312
+ expr = mexpr.replace('\n', ' ').replace('\r', '')
1313
+ expr = expr.replace('[', '(').replace(']', ')')
1314
+ expr = expr.replace('{', '[').replace('}', ']')
1315
+ lsymbols = symbol_table['mathematica'].copy()
1316
+ lsymbols_names_only = [s[0] for s in lsymbols]
1317
+ autotrans = [lambda x:x.lower(), # Try it in lower case
1318
+ _un_camel, # Convert `CamelCase` to `camel_case`
1319
+ lambda x: x] # Try the original name
1320
+ # Find the MMA funcs/vars/constants - they start with a letter.
1321
+ # Exclude exponents (e.g. 'e8' from 4.e8)
1322
+ p = re.compile(r'(?<!\.)[a-zA-Z]\w*')
1323
+
1324
+ for m in p.finditer(expr):
1325
+ # If the function, variable or constant is already in the
1326
+ # translation dictionary, then just move on.
1327
+ if m.group() in lsymbols_names_only:
1328
+ pass
1329
+ # Now try to translate all other functions -- try each strategy
1330
+ # in `autotrans` and check if the function exists in Sage
1331
+ elif m.end() < len(expr) and expr[m.end()] == '(':
1332
+ for t in autotrans:
1333
+ f = find_func(t(m.group()), create_when_missing=False)
1334
+ if f is not None:
1335
+ lsymbols[(m.group(), f.number_of_arguments())] = f
1336
+ break
1337
+ else:
1338
+ raise NotImplementedError("Don't know a Sage equivalent for Mathematica function '%s'." % m.group())
1339
+ # Check if Sage has an equivalent constant
1340
+ else:
1341
+ for t in autotrans:
1342
+ if t(m.group()) in constants:
1343
+ lsymbols[(m.group(), 0)] = constants[t(m.group())]
1344
+ break
1345
+ return symbolic_expression_from_string(expr, lsymbols, accept_sequence=True)