Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/calculus/calculus.py
8815 views
1
r"""
2
Symbolic Computation
3
4
AUTHORS:
5
6
- Bobby Moretti and William Stein (2006-2007)
7
8
- Robert Bradshaw (2007-10): minpoly(), numerical algorithm
9
10
- Robert Bradshaw (2008-10): minpoly(), algebraic algorithm
11
12
- Golam Mortuza Hossain (2009-06-15): _limit_latex()
13
14
- Golam Mortuza Hossain (2009-06-22): _laplace_latex(), _inverse_laplace_latex()
15
16
- Tom Coates (2010-06-11): fixed Trac #9217
17
18
The Sage calculus module is loosely based on the Sage Enhancement
19
Proposal found at: http://www.sagemath.org:9001/CalculusSEP.
20
21
EXAMPLES:
22
23
The basic units of the calculus package are symbolic expressions which
24
are elements of the symbolic expression ring (SR). To create a
25
symbolic variable object in Sage, use the :func:`var` function, whose
26
argument is the text of that variable. Note that Sage is intelligent
27
about LaTeXing variable names.
28
29
::
30
31
sage: x1 = var('x1'); x1
32
x1
33
sage: latex(x1)
34
x_{1}
35
sage: theta = var('theta'); theta
36
theta
37
sage: latex(theta)
38
\theta
39
40
Sage predefines ``x`` to be a global indeterminate.
41
Thus the following works::
42
43
sage: x^2
44
x^2
45
sage: type(x)
46
<type 'sage.symbolic.expression.Expression'>
47
48
More complicated expressions in Sage can be built up using ordinary
49
arithmetic. The following are valid, and follow the rules of Python
50
arithmetic: (The '=' operator represents assignment, and not
51
equality)
52
53
::
54
55
sage: var('x,y,z')
56
(x, y, z)
57
sage: f = x + y + z/(2*sin(y*z/55))
58
sage: g = f^f; g
59
(x + y + 1/2*z/sin(1/55*y*z))^(x + y + 1/2*z/sin(1/55*y*z))
60
61
Differentiation and integration are available, but behind the
62
scenes through Maxima::
63
64
sage: f = sin(x)/cos(2*y)
65
sage: f.derivative(y)
66
2*sin(x)*sin(2*y)/cos(2*y)^2
67
sage: g = f.integral(x); g
68
-cos(x)/cos(2*y)
69
70
Note that these methods usually require an explicit variable name. If none
71
is given, Sage will try to find one for you.
72
73
::
74
75
sage: f = sin(x); f.derivative()
76
cos(x)
77
78
If the expression is a callable symbolic expression (i.e., the
79
variable order is specified), then Sage can calculate the matrix
80
derivative (i.e., the gradient, Jacobian matrix, etc.) if no variables
81
are specified. In the example below, we use the second derivative
82
test to determine that there is a saddle point at (0,-1/2).
83
84
::
85
86
sage: f(x,y)=x^2*y+y^2+y
87
sage: f.diff() # gradient
88
(x, y) |--> (2*x*y, x^2 + 2*y + 1)
89
sage: solve(list(f.diff()),[x,y])
90
[[x == -I, y == 0], [x == I, y == 0], [x == 0, y == (-1/2)]]
91
sage: H=f.diff(2); H # Hessian matrix
92
[(x, y) |--> 2*y (x, y) |--> 2*x]
93
[(x, y) |--> 2*x (x, y) |--> 2]
94
sage: H(x=0,y=-1/2)
95
[-1 0]
96
[ 0 2]
97
sage: H(x=0,y=-1/2).eigenvalues()
98
[-1, 2]
99
100
Here we calculate the Jacobian for the polar coordinate transformation::
101
102
sage: T(r,theta)=[r*cos(theta),r*sin(theta)]
103
sage: T
104
(r, theta) |--> (r*cos(theta), r*sin(theta))
105
sage: T.diff() # Jacobian matrix
106
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
107
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
108
sage: diff(T) # Jacobian matrix
109
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
110
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
111
sage: T.diff().det() # Jacobian
112
(r, theta) |--> r*cos(theta)^2 + r*sin(theta)^2
113
114
When the order of variables is ambiguous, Sage will raise an
115
exception when differentiating::
116
117
sage: f = sin(x+y); f.derivative()
118
Traceback (most recent call last):
119
...
120
ValueError: No differentiation variable specified.
121
122
Simplifying symbolic sums is also possible, using the
123
sum command, which also uses Maxima in the background::
124
125
sage: k, m = var('k, m')
126
sage: sum(1/k^4, k, 1, oo)
127
1/90*pi^4
128
sage: sum(binomial(m,k), k, 0, m)
129
2^m
130
131
Symbolic matrices can be used as well in various ways,
132
including exponentiation::
133
134
sage: M = matrix([[x,x^2],[1/x,x]])
135
sage: M^2
136
[x^2 + x 2*x^3]
137
[ 2 x^2 + x]
138
sage: e^M
139
[ 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x)) 1/2*(x*e^(2*sqrt(x)) - x)*sqrt(x)*e^(x - sqrt(x))]
140
[ 1/2*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))/x^(3/2) 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x))]
141
142
And complex exponentiation works now::
143
144
sage: M = i*matrix([[pi]])
145
sage: e^M
146
[-1]
147
sage: M = i*matrix([[pi,0],[0,2*pi]])
148
sage: e^M
149
[-1 0]
150
[ 0 1]
151
sage: M = matrix([[0,pi],[-pi,0]])
152
sage: e^M
153
[-1 0]
154
[ 0 -1]
155
156
Substitution works similarly. We can substitute with a python
157
dict::
158
159
sage: f = sin(x*y - z)
160
sage: f({x: var('t'), y: z})
161
sin(t*z - z)
162
163
Also we can substitute with keywords::
164
165
sage: f = sin(x*y - z)
166
sage: f(x = t, y = z)
167
sin(t*z - z)
168
169
It was formerly the case that if there was no ambiguity of variable
170
names, we didn't have to specify them; that still works for the moment,
171
but the behavior is deprecated::
172
173
sage: f = sin(x)
174
sage: f(y)
175
doctest:...: DeprecationWarning: Substitution using function-call
176
syntax and unnamed arguments is deprecated and will be removed
177
from a future release of Sage; you can use named arguments instead,
178
like EXPR(x=..., y=...)
179
See http://trac.sagemath.org/5930 for details.
180
sin(y)
181
sage: f(pi)
182
0
183
184
However if there is ambiguity, we should explicitly state what
185
variables we're substituting for::
186
187
sage: f = sin(2*pi*x/y)
188
sage: f(x=4)
189
sin(8*pi/y)
190
191
We can also make a ``CallableSymbolicExpression``,
192
which is a ``SymbolicExpression`` that is a function of
193
specified variables in a fixed order. Each
194
``SymbolicExpression`` has a
195
``function(...)`` method that is used to create a
196
``CallableSymbolicExpression``, as illustrated below::
197
198
sage: u = log((2-x)/(y+5))
199
sage: f = u.function(x, y); f
200
(x, y) |--> log(-(x - 2)/(y + 5))
201
202
There is an easier way of creating a
203
``CallableSymbolicExpression``, which relies on the
204
Sage preparser.
205
206
::
207
208
sage: f(x,y) = log(x)*cos(y); f
209
(x, y) |--> cos(y)*log(x)
210
211
Then we have fixed an order of variables and there is no ambiguity
212
substituting or evaluating::
213
214
sage: f(x,y) = log((2-x)/(y+5))
215
sage: f(7,t)
216
log(-5/(t + 5))
217
218
Some further examples::
219
220
sage: f = 5*sin(x)
221
sage: f
222
5*sin(x)
223
sage: f(x=2)
224
5*sin(2)
225
sage: f(x=pi)
226
0
227
sage: float(f(x=pi))
228
0.0
229
230
Another example::
231
232
sage: f = integrate(1/sqrt(9+x^2), x); f
233
arcsinh(1/3*x)
234
sage: f(x=3)
235
arcsinh(1)
236
sage: f.derivative(x)
237
1/3/sqrt(1/9*x^2 + 1)
238
239
We compute the length of the parabola from 0 to 2::
240
241
sage: x = var('x')
242
sage: y = x^2
243
sage: dy = derivative(y,x)
244
sage: z = integral(sqrt(1 + dy^2), x, 0, 2)
245
sage: z
246
sqrt(17) + 1/4*arcsinh(4)
247
sage: n(z,200)
248
4.6467837624329358733826155674904591885104869874232887508703
249
sage: float(z)
250
4.646783762432936
251
252
We test pickling::
253
254
sage: x, y = var('x,y')
255
sage: f = -sqrt(pi)*(x^3 + sin(x/cos(y)))
256
sage: bool(loads(dumps(f)) == f)
257
True
258
259
Coercion examples:
260
261
We coerce various symbolic expressions into the complex numbers::
262
263
sage: CC(I)
264
1.00000000000000*I
265
sage: CC(2*I)
266
2.00000000000000*I
267
sage: ComplexField(200)(2*I)
268
2.0000000000000000000000000000000000000000000000000000000000*I
269
sage: ComplexField(200)(sin(I))
270
1.1752011936438014568823818505956008151557179813340958702296*I
271
sage: f = sin(I) + cos(I/2); f
272
cos(1/2*I) + sin(I)
273
sage: CC(f)
274
1.12762596520638 + 1.17520119364380*I
275
sage: ComplexField(200)(f)
276
1.1276259652063807852262251614026720125478471180986674836290 + 1.1752011936438014568823818505956008151557179813340958702296*I
277
sage: ComplexField(100)(f)
278
1.1276259652063807852262251614 + 1.1752011936438014568823818506*I
279
280
We illustrate construction of an inverse sum where each denominator
281
has a new variable name::
282
283
sage: f = sum(1/var('n%s'%i)^i for i in range(10))
284
sage: f
285
1/n1 + 1/n2^2 + 1/n3^3 + 1/n4^4 + 1/n5^5 + 1/n6^6 + 1/n7^7 + 1/n8^8 + 1/n9^9 + 1
286
287
Note that after calling var, the variables are immediately
288
available for use::
289
290
sage: (n1 + n2)^5
291
(n1 + n2)^5
292
293
We can, of course, substitute::
294
295
sage: f(n9=9,n7=n6)
296
1/n1 + 1/n2^2 + 1/n3^3 + 1/n4^4 + 1/n5^5 + 1/n6^6 + 1/n6^7 + 1/n8^8 + 387420490/387420489
297
298
TESTS:
299
300
Substitution::
301
302
sage: f = x
303
sage: f(x=5)
304
5
305
306
Simplifying expressions involving scientific notation::
307
308
sage: k = var('k')
309
sage: a0 = 2e-06; a1 = 12
310
sage: c = a1 + a0*k; c
311
(2.00000000000000e-6)*k + 12
312
sage: sqrt(c)
313
sqrt((2.00000000000000e-6)*k + 12)
314
sage: sqrt(c^3)
315
sqrt(((2.00000000000000e-6)*k + 12)^3)
316
317
The symbolic calculus package uses its own copy of Maxima for
318
simplification, etc., which is separate from the default
319
system-wide version::
320
321
sage: maxima.eval('[x,y]: [1,2]')
322
'[1,2]'
323
sage: maxima.eval('expand((x+y)^3)')
324
'27'
325
326
If the copy of maxima used by the symbolic calculus package were
327
the same as the default one, then the following would return 27,
328
which would be very confusing indeed!
329
330
::
331
332
sage: x, y = var('x,y')
333
sage: expand((x+y)^3)
334
x^3 + 3*x^2*y + 3*x*y^2 + y^3
335
336
Set x to be 5 in maxima::
337
338
sage: maxima('x: 5')
339
5
340
sage: maxima('x + x + %pi')
341
%pi+10
342
343
Simplifications like these are now done using Pynac::
344
345
sage: x + x + pi
346
pi + 2*x
347
348
But this still uses Maxima::
349
350
sage: (x + x + pi).simplify()
351
pi + 2*x
352
353
Note that ``x`` is still ``x``, since the
354
maxima used by the calculus package is different than the one in
355
the interactive interpreter.
356
357
Check to see that the problem with the variables method mentioned
358
in Trac ticket #3779 is actually fixed::
359
360
sage: f = function('F',x)
361
sage: diff(f*SR(1),x)
362
D[0](F)(x)
363
364
Doubly ensure that Trac #7479 is working::
365
366
sage: f(x)=x
367
sage: integrate(f,x,0,1)
368
1/2
369
370
Check that the problem with Taylor expansions of the gamma function
371
(Trac #9217) is fixed::
372
373
sage: taylor(gamma(1/3+x),x,0,3)
374
-1/432*((72*euler_gamma^3 + 36*euler_gamma^2*(sqrt(3)*pi + 9*log(3)) +
375
27*pi^2*log(3) + 243*log(3)^3 + 18*euler_gamma*(6*sqrt(3)*pi*log(3) + pi^2
376
+ 27*log(3)^2 + 12*psi(1, 1/3)) + 324*log(3)*psi(1, 1/3) + sqrt(3)*(pi^3 +
377
9*pi*(9*log(3)^2 + 4*psi(1, 1/3))))*gamma(1/3) - 72*psi(2,
378
1/3)*gamma(1/3))*x^3 + 1/24*(6*sqrt(3)*pi*log(3) + 12*euler_gamma^2 + pi^2
379
+ 4*euler_gamma*(sqrt(3)*pi + 9*log(3)) + 27*log(3)^2 + 12*psi(1,
380
1/3))*x^2*gamma(1/3) - 1/6*(6*euler_gamma + sqrt(3)*pi +
381
9*log(3))*x*gamma(1/3) + gamma(1/3)
382
sage: map(lambda f:f[0].n(), _.coeffs()) # numerical coefficients to make comparison easier; Maple 12 gives same answer
383
[2.6789385347..., -8.3905259853..., 26.662447494..., -80.683148377...]
384
385
Ensure that ticket #8582 is fixed::
386
387
sage: k = var("k")
388
sage: sum(1/(1+k^2), k, -oo, oo)
389
-1/2*I*psi(I + 1) + 1/2*I*psi(-I + 1) - 1/2*I*psi(I) + 1/2*I*psi(-I)
390
391
Ensure that ticket #8624 is fixed::
392
393
sage: integrate(abs(cos(x)) * sin(x), x, pi/2, pi)
394
1/2
395
sage: integrate(sqrt(cos(x)^2 + sin(x)^2), x, 0, 2*pi)
396
2*pi
397
"""
398
399
import re
400
from sage.rings.all import RR, Integer, CC, QQ, RealDoubleElement, algdep
401
from sage.rings.real_mpfr import create_RealNumber
402
403
from sage.misc.latex import latex
404
from sage.misc.parser import Parser
405
406
from sage.symbolic.ring import var, SR, is_SymbolicVariable
407
from sage.symbolic.expression import Expression
408
from sage.symbolic.function import Function
409
from sage.symbolic.function_factory import function_factory
410
from sage.symbolic.integration.integral import indefinite_integral, \
411
definite_integral
412
import sage.symbolic.pynac
413
414
"""
415
Check if maxima has redundant variables defined after initialization #9538::
416
417
sage: maxima = sage.interfaces.maxima.maxima
418
sage: maxima('f1')
419
f1
420
sage: sage.calculus.calculus.maxima('f1')
421
f1
422
"""
423
from sage.misc.lazy_import import lazy_import
424
lazy_import('sage.interfaces.maxima_lib','maxima')
425
# This is not the same instance of Maxima as the general purpose one
426
#from sage.interfaces.maxima import Maxima
427
#maxima = Maxima(init_code = ['display2d : false', 'domain : complex',
428
# 'keepfloat : true', 'load(to_poly_solver)',
429
# 'load(simplify_sum)'],
430
# script_subdirectory=None)
431
432
########################################################
433
def symbolic_sum(expression, v, a, b, algorithm='maxima'):
434
r"""
435
Returns the symbolic sum `\sum_{v = a}^b expression` with respect
436
to the variable `v` with endpoints `a` and `b`.
437
438
INPUT:
439
440
- ``expression`` - a symbolic expression
441
442
- ``v`` - a variable or variable name
443
444
- ``a`` - lower endpoint of the sum
445
446
- ``b`` - upper endpoint of the sum
447
448
- ``algorithm`` - (default: 'maxima') one of
449
- 'maxima' - use Maxima (the default)
450
- 'maple' - (optional) use Maple
451
- 'mathematica' - (optional) use Mathematica
452
- 'giac' - (optional) use Giac
453
454
EXAMPLES::
455
456
sage: k, n = var('k,n')
457
sage: from sage.calculus.calculus import symbolic_sum
458
sage: symbolic_sum(k, k, 1, n).factor()
459
1/2*(n + 1)*n
460
461
::
462
463
sage: symbolic_sum(1/k^4, k, 1, oo)
464
1/90*pi^4
465
466
::
467
468
sage: symbolic_sum(1/k^5, k, 1, oo)
469
zeta(5)
470
471
A well known binomial identity::
472
473
sage: symbolic_sum(binomial(n,k), k, 0, n)
474
2^n
475
476
And some truncations thereof::
477
478
sage: assume(n>1)
479
sage: symbolic_sum(binomial(n,k),k,1,n)
480
2^n - 1
481
sage: symbolic_sum(binomial(n,k),k,2,n)
482
2^n - n - 1
483
sage: symbolic_sum(binomial(n,k),k,0,n-1)
484
2^n - 1
485
sage: symbolic_sum(binomial(n,k),k,1,n-1)
486
2^n - 2
487
488
The binomial theorem::
489
490
sage: x, y = var('x, y')
491
sage: symbolic_sum(binomial(n,k) * x^k * y^(n-k), k, 0, n)
492
(x + y)^n
493
494
::
495
496
sage: symbolic_sum(k * binomial(n, k), k, 1, n)
497
2^(n - 1)*n
498
499
::
500
501
sage: symbolic_sum((-1)^k*binomial(n,k), k, 0, n)
502
0
503
504
::
505
506
sage: symbolic_sum(2^(-k)/(k*(k+1)), k, 1, oo)
507
-log(2) + 1
508
509
Summing a hypergeometric term::
510
511
sage: symbolic_sum(binomial(n, k) * factorial(k) / factorial(n+1+k), k, 0, n)
512
1/2*sqrt(pi)/factorial(n + 1/2)
513
514
We check a well known identity::
515
516
sage: bool(symbolic_sum(k^3, k, 1, n) == symbolic_sum(k, k, 1, n)^2)
517
True
518
519
A geometric sum::
520
521
sage: a, q = var('a, q')
522
sage: symbolic_sum(a*q^k, k, 0, n)
523
(a*q^(n + 1) - a)/(q - 1)
524
525
For the geometric series, we will have to assume
526
the right values for the sum to converge::
527
528
sage: assume(abs(q) < 1)
529
sage: symbolic_sum(a*q^k, k, 0, oo)
530
-a/(q - 1)
531
532
A divergent geometric series. Don't forget
533
to forget your assumptions::
534
535
sage: forget()
536
sage: assume(q > 1)
537
sage: symbolic_sum(a*q^k, k, 0, oo)
538
Traceback (most recent call last):
539
...
540
ValueError: Sum is divergent.
541
sage: forget()
542
sage: assumptions() # check the assumptions were really forgotten
543
[]
544
545
This summation only Mathematica can perform::
546
547
sage: symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm = 'mathematica') # optional - mathematica
548
pi*coth(pi)
549
550
An example of this summation with Giac::
551
552
sage: symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm = 'giac') # optional - giac
553
-(pi*e^(-2*pi) - pi*e^(2*pi))/(e^(-2*pi) + e^(2*pi) - 2)
554
555
Use Maple as a backend for summation::
556
557
sage: symbolic_sum(binomial(n,k)*x^k, k, 0, n, algorithm = 'maple') # optional - maple
558
(x + 1)^n
559
560
TESTS:
561
562
Trac #10564 is fixed::
563
564
sage: sum (n^3 * x^n, n, 0, infinity)
565
(x^3 + 4*x^2 + x)/(x^4 - 4*x^3 + 6*x^2 - 4*x + 1)
566
567
.. note::
568
569
Sage can currently only understand a subset of the output of Maxima,
570
Maple and Mathematica, so even if the chosen backend can perform
571
the summation the result might not be convertable into a Sage
572
expression.
573
"""
574
if not is_SymbolicVariable(v):
575
if isinstance(v, str):
576
v = var(v)
577
else:
578
raise TypeError("need a summation variable")
579
580
if v in SR(a).variables() or v in SR(b).variables():
581
raise ValueError("summation limits must not depend on the summation variable")
582
583
if algorithm == 'maxima':
584
return maxima.sr_sum(expression,v,a,b)
585
586
elif algorithm == 'mathematica':
587
try:
588
sum = "Sum[%s, {%s, %s, %s}]" % tuple([repr(expr._mathematica_()) for expr in (expression, v, a, b)])
589
except TypeError:
590
raise ValueError("Mathematica cannot make sense of input")
591
from sage.interfaces.mathematica import mathematica
592
try:
593
result = mathematica(sum)
594
except TypeError:
595
raise ValueError("Mathematica cannot make sense of: %s" % sum)
596
return result.sage()
597
598
elif algorithm == 'maple':
599
sum = "sum(%s, %s=%s..%s)" % tuple([repr(expr._maple_()) for expr in (expression, v, a, b)])
600
from sage.interfaces.maple import maple
601
try:
602
result = maple(sum).simplify()
603
except TypeError:
604
raise ValueError("Maple cannot make sense of: %s" % sum)
605
return result.sage()
606
607
elif algorithm == 'giac':
608
sum = "sum(%s, %s, %s, %s)" % tuple([repr(expr._giac_()) for expr in (expression, v, a, b)])
609
from sage.interfaces.giac import giac
610
try:
611
result = giac(sum)
612
except TypeError:
613
raise ValueError("Giac cannot make sense of: %s" % sum)
614
return result.sage()
615
616
else:
617
raise ValueError("unknown algorithm: %s" % algorithm)
618
619
def nintegral(ex, x, a, b,
620
desired_relative_error='1e-8',
621
maximum_num_subintervals=200):
622
r"""
623
Return a floating point machine precision numerical approximation
624
to the integral of ``self`` from `a` to
625
`b`, computed using floating point arithmetic via maxima.
626
627
INPUT:
628
629
- ``x`` - variable to integrate with respect to
630
631
- ``a`` - lower endpoint of integration
632
633
- ``b`` - upper endpoint of integration
634
635
- ``desired_relative_error`` - (default: '1e-8') the
636
desired relative error
637
638
- ``maximum_num_subintervals`` - (default: 200)
639
maxima number of subintervals
640
641
OUTPUT:
642
643
- float: approximation to the integral
644
645
- float: estimated absolute error of the
646
approximation
647
648
- the number of integrand evaluations
649
650
- an error code:
651
652
- ``0`` - no problems were encountered
653
654
- ``1`` - too many subintervals were done
655
656
- ``2`` - excessive roundoff error
657
658
- ``3`` - extremely bad integrand behavior
659
660
- ``4`` - failed to converge
661
662
- ``5`` - integral is probably divergent or slowly
663
convergent
664
665
- ``6`` - the input is invalid; this includes the case of
666
desired_relative_error being too small to be achieved
667
668
ALIAS: nintegrate is the same as nintegral
669
670
REMARK: There is also a function
671
``numerical_integral`` that implements numerical
672
integration using the GSL C library. It is potentially much faster
673
and applies to arbitrary user defined functions.
674
675
Also, there are limits to the precision to which Maxima can compute
676
the integral due to limitations in quadpack.
677
In the following example, remark that the last value of the returned
678
tuple is ``6``, indicating that the input was invalid, in this case
679
because of a too high desired precision.
680
681
::
682
683
sage: f = x
684
sage: f.nintegral(x,0,1,1e-14)
685
(0.0, 0.0, 0, 6)
686
687
EXAMPLES::
688
689
sage: f(x) = exp(-sqrt(x))
690
sage: f.nintegral(x, 0, 1)
691
(0.5284822353142306, 4.163...e-11, 231, 0)
692
693
We can also use the ``numerical_integral`` function,
694
which calls the GSL C library.
695
696
::
697
698
sage: numerical_integral(f, 0, 1)
699
(0.528482232253147, 6.83928460...e-07)
700
701
Note that in exotic cases where floating point evaluation of the
702
expression leads to the wrong value, then the output can be
703
completely wrong::
704
705
sage: f = exp(pi*sqrt(163)) - 262537412640768744
706
707
Despite appearance, `f` is really very close to 0, but one
708
gets a nonzero value since the definition of
709
``float(f)`` is that it makes all constants inside the
710
expression floats, then evaluates each function and each arithmetic
711
operation using float arithmetic::
712
713
sage: float(f)
714
-480.0
715
716
Computing to higher precision we see the truth::
717
718
sage: f.n(200)
719
-7.4992740280181431112064614366622348652078895136533593355718e-13
720
sage: f.n(300)
721
-7.49927402801814311120646143662663009137292462589621789352095066181709095575681963967103004e-13
722
723
Now numerically integrating, we see why the answer is wrong::
724
725
sage: f.nintegrate(x,0,1)
726
(-480.00000000000006, 5.329070518200754e-12, 21, 0)
727
728
It is just because every floating point evaluation of return -480.0
729
in floating point.
730
731
Important note: using PARI/GP one can compute numerical integrals
732
to high precision::
733
734
sage: gp.eval('intnum(x=17,42,exp(-x^2)*log(x))')
735
'2.565728500561051482917356396 E-127' # 32-bit
736
'2.5657285005610514829173563961304785900 E-127' # 64-bit
737
sage: old_prec = gp.set_real_precision(50)
738
sage: gp.eval('intnum(x=17,42,exp(-x^2)*log(x))')
739
'2.5657285005610514829173563961304785900147709554020 E-127'
740
sage: gp.set_real_precision(old_prec)
741
50
742
743
Note that the input function above is a string in PARI syntax.
744
"""
745
try:
746
v = ex._maxima_().quad_qags(x, a, b,
747
epsrel=desired_relative_error,
748
limit=maximum_num_subintervals)
749
except TypeError as err:
750
if "ERROR" in str(err):
751
raise ValueError("Maxima (via quadpack) cannot compute the integral")
752
else:
753
raise TypeError(err)
754
755
# Maxima returns unevaluated expressions when the underlying library fails
756
# to perfom numerical integration. See:
757
# http://www.math.utexas.edu/pipermail/maxima/2008/012975.html
758
if 'quad_qags' in str(v):
759
raise ValueError("Maxima (via quadpack) cannot compute the integral")
760
761
return float(v[0]), float(v[1]), Integer(v[2]), Integer(v[3])
762
763
nintegrate = nintegral
764
765
def minpoly(ex, var='x', algorithm=None, bits=None, degree=None, epsilon=0):
766
r"""
767
Return the minimal polynomial of self, if possible.
768
769
INPUT:
770
771
- ``var`` - polynomial variable name (default 'x')
772
773
- ``algorithm`` - 'algebraic' or 'numerical' (default
774
both, but with numerical first)
775
776
- ``bits`` - the number of bits to use in numerical
777
approx
778
779
- ``degree`` - the expected algebraic degree
780
781
- ``epsilon`` - return without error as long as
782
f(self) epsilon, in the case that the result cannot be proven.
783
784
All of the above parameters are optional, with epsilon=0, bits and
785
degree tested up to 1000 and 24 by default respectively. The
786
numerical algorithm will be faster if bits and/or degree are given
787
explicitly. The algebraic algorithm ignores the last three
788
parameters.
789
790
791
OUTPUT: The minimal polynomial of self. If the numerical algorithm
792
is used then it is proved symbolically when epsilon=0 (default).
793
794
If the minimal polynomial could not be found, two distinct kinds of
795
errors are raised. If no reasonable candidate was found with the
796
given bit/degree parameters, a ``ValueError`` will be
797
raised. If a reasonable candidate was found but (perhaps due to
798
limits in the underlying symbolic package) was unable to be proved
799
correct, a ``NotImplementedError`` will be raised.
800
801
ALGORITHM: Two distinct algorithms are used, depending on the
802
algorithm parameter. By default, the numerical algorithm is
803
attempted first, then the algebraic one.
804
805
Algebraic: Attempt to evaluate this expression in QQbar, using
806
cyclotomic fields to resolve exponential and trig functions at
807
rational multiples of pi, field extensions to handle roots and
808
rational exponents, and computing compositums to represent the full
809
expression as an element of a number field where the minimal
810
polynomial can be computed exactly. The bits, degree, and epsilon
811
parameters are ignored.
812
813
Numerical: Computes a numerical approximation of
814
``self`` and use PARI's algdep to get a candidate
815
minpoly `f`. If `f(\mathtt{self})`,
816
evaluated to a higher precision, is close enough to 0 then evaluate
817
`f(\mathtt{self})` symbolically, attempting to prove
818
vanishing. If this fails, and ``epsilon`` is non-zero,
819
return `f` if and only if
820
`f(\mathtt{self}) < \mathtt{epsilon}`.
821
Otherwise raise a ``ValueError`` (if no suitable
822
candidate was found) or a ``NotImplementedError`` (if a
823
likely candidate was found but could not be proved correct).
824
825
EXAMPLES: First some simple examples::
826
827
sage: sqrt(2).minpoly()
828
x^2 - 2
829
sage: minpoly(2^(1/3))
830
x^3 - 2
831
sage: minpoly(sqrt(2) + sqrt(-1))
832
x^4 - 2*x^2 + 9
833
sage: minpoly(sqrt(2)-3^(1/3))
834
x^6 - 6*x^4 + 6*x^3 + 12*x^2 + 36*x + 1
835
836
837
Works with trig and exponential functions too.
838
839
::
840
841
sage: sin(pi/3).minpoly()
842
x^2 - 3/4
843
sage: sin(pi/7).minpoly()
844
x^6 - 7/4*x^4 + 7/8*x^2 - 7/64
845
sage: minpoly(exp(I*pi/17))
846
x^16 - x^15 + x^14 - x^13 + x^12 - x^11 + x^10 - x^9 + x^8 - x^7 + x^6 - x^5 + x^4 - x^3 + x^2 - x + 1
847
848
Here we verify it gives the same result as the abstract number
849
field.
850
851
::
852
853
sage: (sqrt(2) + sqrt(3) + sqrt(6)).minpoly()
854
x^4 - 22*x^2 - 48*x - 23
855
sage: K.<a,b> = NumberField([x^2-2, x^2-3])
856
sage: (a+b+a*b).absolute_minpoly()
857
x^4 - 22*x^2 - 48*x - 23
858
859
The minpoly function is used implicitly when creating
860
number fields::
861
862
sage: x = var('x')
863
sage: eqn = x^3 + sqrt(2)*x + 5 == 0
864
sage: a = solve(eqn, x)[0].rhs()
865
sage: QQ[a]
866
Number Field in a with defining polynomial x^6 + 10*x^3 - 2*x^2 + 25
867
868
Here we solve a cubic and then recover it from its complicated
869
radical expansion.
870
871
::
872
873
sage: f = x^3 - x + 1
874
sage: a = f.solve(x)[0].rhs(); a
875
-1/2*(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)*(I*sqrt(3) + 1) - 1/6*(-I*sqrt(3) + 1)/(1/18*sqrt(23)*sqrt(3) - 1/2)^(1/3)
876
sage: a.minpoly()
877
x^3 - x + 1
878
879
Note that simplification may be necessary to see that the minimal
880
polynomial is correct.
881
882
::
883
884
sage: a = sqrt(2)+sqrt(3)+sqrt(5)
885
sage: f = a.minpoly(); f
886
x^8 - 40*x^6 + 352*x^4 - 960*x^2 + 576
887
sage: f(a)
888
((((sqrt(5) + sqrt(3) + sqrt(2))^2 - 40)*(sqrt(5) + sqrt(3) + sqrt(2))^2 + 352)*(sqrt(5) + sqrt(3) + sqrt(2))^2 - 960)*(sqrt(5) + sqrt(3) + sqrt(2))^2 + 576
889
sage: f(a).expand()
890
0
891
892
Here we show use of the ``epsilon`` parameter. That
893
this result is actually exact can be shown using the addition
894
formula for sin, but maxima is unable to see that.
895
896
::
897
898
sage: a = sin(pi/5)
899
sage: a.minpoly(algorithm='numerical')
900
Traceback (most recent call last):
901
...
902
NotImplementedError: Could not prove minimal polynomial x^4 - 5/4*x^2 + 5/16 (epsilon 0.00000000000000e-1)
903
sage: f = a.minpoly(algorithm='numerical', epsilon=1e-100); f
904
x^4 - 5/4*x^2 + 5/16
905
sage: f(a).numerical_approx(100)
906
0.00000000000000000000000000000
907
908
The degree must be high enough (default tops out at 24).
909
910
::
911
912
sage: a = sqrt(3) + sqrt(2)
913
sage: a.minpoly(algorithm='numerical', bits=100, degree=3)
914
Traceback (most recent call last):
915
...
916
ValueError: Could not find minimal polynomial (100 bits, degree 3).
917
sage: a.minpoly(algorithm='numerical', bits=100, degree=10)
918
x^4 - 10*x^2 + 1
919
920
There is a difference between algorithm='algebraic' and
921
algorithm='numerical'::
922
923
sage: cos(pi/33).minpoly(algorithm='algebraic')
924
x^10 + 1/2*x^9 - 5/2*x^8 - 5/4*x^7 + 17/8*x^6 + 17/16*x^5 - 43/64*x^4 - 43/128*x^3 + 3/64*x^2 + 3/128*x + 1/1024
925
sage: cos(pi/33).minpoly(algorithm='numerical')
926
Traceback (most recent call last):
927
...
928
NotImplementedError: Could not prove minimal polynomial x^10 + 1/2*x^9 - 5/2*x^8 - 5/4*x^7 + 17/8*x^6 + 17/16*x^5 - 43/64*x^4 - 43/128*x^3 + 3/64*x^2 + 3/128*x + 1/1024 (epsilon ...)
929
930
Sometimes it fails, as it must given that some numbers aren't algebraic::
931
932
sage: sin(1).minpoly(algorithm='numerical')
933
Traceback (most recent call last):
934
...
935
ValueError: Could not find minimal polynomial (1000 bits, degree 24).
936
937
.. note::
938
939
Of course, failure to produce a minimal polynomial does not
940
necessarily indicate that this number is transcendental.
941
"""
942
if algorithm is None or algorithm.startswith('numeric'):
943
bits_list = [bits] if bits else [100,200,500,1000]
944
degree_list = [degree] if degree else [2,4,8,12,24]
945
946
for bits in bits_list:
947
a = ex.numerical_approx(bits)
948
check_bits = int(1.25 * bits + 80)
949
aa = ex.numerical_approx(check_bits)
950
951
for degree in degree_list:
952
953
f = QQ[var](algdep(a, degree)) # TODO: use the known_bits parameter?
954
# If indeed we have found a minimal polynomial,
955
# it should be accurate to a much higher precision.
956
error = abs(f(aa))
957
dx = ~RR(Integer(1) << (check_bits - degree - 2))
958
expected_error = abs(f.derivative()(CC(aa))) * dx
959
960
if error < expected_error:
961
# Degree might have been an over-estimate,
962
# factor because we want (irreducible) minpoly.
963
ff = f.factor()
964
for g, e in ff:
965
lead = g.leading_coefficient()
966
if lead != 1:
967
g = g / lead
968
expected_error = abs(g.derivative()(CC(aa))) * dx
969
error = abs(g(aa))
970
if error < expected_error:
971
# See if we can prove equality exactly
972
if g(ex).simplify_trig().simplify_radical() == 0:
973
return g
974
# Otherwise fall back to numerical guess
975
elif epsilon and error < epsilon:
976
return g
977
elif algorithm is not None:
978
raise NotImplementedError("Could not prove minimal polynomial %s (epsilon %s)" % (g, RR(error).str(no_sci=False)))
979
980
if algorithm is not None:
981
raise ValueError("Could not find minimal polynomial (%s bits, degree %s)." % (bits, degree))
982
983
if algorithm is None or algorithm == 'algebraic':
984
from sage.rings.all import QQbar
985
return QQ[var](QQbar(ex).minpoly())
986
987
raise ValueError("Unknown algorithm: %s" % algorithm)
988
989
990
###################################################################
991
# limits
992
###################################################################
993
def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv):
994
r"""
995
Return the limit as the variable `v` approaches `a`
996
from the given direction.
997
998
::
999
1000
expr.limit(x = a)
1001
expr.limit(x = a, dir='above')
1002
1003
INPUT:
1004
1005
- ``dir`` - (default: None); dir may have the value
1006
'plus' (or '+' or 'right') for a limit from above,
1007
'minus' (or '-' or 'left') for a limit from below, or may be omitted
1008
(implying a two-sided limit is to be computed).
1009
1010
- ``taylor`` - (default: False); if True, use Taylor
1011
series, which allows more limits to be computed (but may also
1012
crash in some obscure cases due to bugs in Maxima).
1013
1014
- ``**argv`` - 1 named parameter
1015
1016
.. note::
1017
1018
The output may also use 'und' (undefined), 'ind'
1019
(indefinite but bounded), and 'infinity' (complex
1020
infinity).
1021
1022
EXAMPLES::
1023
1024
sage: x = var('x')
1025
sage: f = (1+1/x)^x
1026
sage: f.limit(x = oo)
1027
e
1028
sage: f.limit(x = 5)
1029
7776/3125
1030
sage: f.limit(x = 1.2)
1031
2.06961575467...
1032
sage: f.limit(x = I, taylor=True)
1033
(-I + 1)^I
1034
sage: f(x=1.2)
1035
2.0696157546720...
1036
sage: f(x=I)
1037
(-I + 1)^I
1038
sage: CDF(f(x=I))
1039
2.06287223508 + 0.74500706218*I
1040
sage: CDF(f.limit(x = I))
1041
2.06287223508 + 0.74500706218*I
1042
1043
Notice that Maxima may ask for more information::
1044
1045
sage: var('a')
1046
a
1047
sage: limit(x^a,x=0)
1048
Traceback (most recent call last):
1049
...
1050
ValueError: Computation failed since Maxima requested additional
1051
constraints; using the 'assume' command before limit evaluation
1052
*may* help (see `assume?` for more details)
1053
Is a positive, negative, or zero?
1054
1055
With this example, Maxima is looking for a LOT of information::
1056
1057
sage: assume(a>0)
1058
sage: limit(x^a,x=0)
1059
Traceback (most recent call last):
1060
...
1061
ValueError: Computation failed since Maxima requested additional
1062
constraints; using the 'assume' command before limit evaluation
1063
*may* help (see `assume?` for more details)
1064
Is a an integer?
1065
sage: assume(a,'integer')
1066
sage: limit(x^a,x=0)
1067
Traceback (most recent call last):
1068
...
1069
ValueError: Computation failed since Maxima requested additional
1070
constraints; using the 'assume' command before limit evaluation
1071
*may* help (see `assume?` for more details)
1072
Is a an even number?
1073
sage: assume(a,'even')
1074
sage: limit(x^a,x=0)
1075
0
1076
sage: forget()
1077
1078
More examples::
1079
1080
sage: limit(x*log(x), x = 0, dir='+')
1081
0
1082
sage: lim((x+1)^(1/x), x = 0)
1083
e
1084
sage: lim(e^x/x, x = oo)
1085
+Infinity
1086
sage: lim(e^x/x, x = -oo)
1087
0
1088
sage: lim(-e^x/x, x = oo)
1089
-Infinity
1090
sage: lim((cos(x))/(x^2), x = 0)
1091
+Infinity
1092
sage: lim(sqrt(x^2+1) - x, x = oo)
1093
0
1094
sage: lim(x^2/(sec(x)-1), x=0)
1095
2
1096
sage: lim(cos(x)/(cos(x)-1), x=0)
1097
-Infinity
1098
sage: lim(x*sin(1/x), x=0)
1099
0
1100
sage: limit(e^(-1/x), x=0, dir='right')
1101
0
1102
sage: limit(e^(-1/x), x=0, dir='left')
1103
+Infinity
1104
1105
::
1106
1107
sage: f = log(log(x))/log(x)
1108
sage: forget(); assume(x<-2); lim(f, x=0, taylor=True)
1109
0
1110
sage: forget()
1111
1112
Here ind means "indefinite but bounded"::
1113
1114
sage: lim(sin(1/x), x = 0)
1115
ind
1116
1117
TESTS::
1118
1119
sage: lim(x^2, x=2, dir='nugget')
1120
Traceback (most recent call last):
1121
...
1122
ValueError: dir must be one of None, 'plus', '+', 'right',
1123
'minus', '-', 'left'
1124
1125
We check that Trac ticket 3718 is fixed, so that
1126
Maxima gives correct limits for the floor function::
1127
1128
sage: limit(floor(x), x=0, dir='-')
1129
-1
1130
sage: limit(floor(x), x=0, dir='+')
1131
0
1132
sage: limit(floor(x), x=0)
1133
und
1134
1135
Maxima gives the right answer here, too, showing
1136
that Trac 4142 is fixed::
1137
1138
sage: f = sqrt(1-x^2)
1139
sage: g = diff(f, x); g
1140
-x/sqrt(-x^2 + 1)
1141
sage: limit(g, x=1, dir='-')
1142
-Infinity
1143
1144
::
1145
1146
sage: limit(1/x, x=0)
1147
Infinity
1148
sage: limit(1/x, x=0, dir='+')
1149
+Infinity
1150
sage: limit(1/x, x=0, dir='-')
1151
-Infinity
1152
1153
Check that Trac 8942 is fixed::
1154
1155
sage: f(x) = (cos(pi/4-x) - tan(x)) / (1 - sin(pi/4+x))
1156
sage: limit(f(x), x = pi/4, dir='minus')
1157
+Infinity
1158
sage: limit(f(x), x = pi/4, dir='plus')
1159
-Infinity
1160
sage: limit(f(x), x = pi/4)
1161
Infinity
1162
1163
Check that we give deprecation warnings for 'above' and 'below' #9200::
1164
1165
sage: limit(1/x, x=0, dir='above')
1166
doctest:...: DeprecationWarning: the keyword
1167
'above' is deprecated. Please use 'right' or '+' instead.
1168
See http://trac.sagemath.org/9200 for details.
1169
+Infinity
1170
sage: limit(1/x, x=0, dir='below')
1171
doctest:...: DeprecationWarning: the keyword
1172
'below' is deprecated. Please use 'left' or '-' instead.
1173
See http://trac.sagemath.org/9200 for details.
1174
-Infinity
1175
1176
Check that :trac:`12708` is fixed::
1177
1178
sage: limit(tanh(x),x=0)
1179
0
1180
"""
1181
if not isinstance(ex, Expression):
1182
ex = SR(ex)
1183
1184
if len(argv) != 1:
1185
raise ValueError("call the limit function like this, e.g. limit(expr, x=2).")
1186
else:
1187
k = argv.keys()[0]
1188
v = var(k)
1189
a = argv[k]
1190
1191
if taylor and algorithm == 'maxima':
1192
algorithm = 'maxima_taylor'
1193
1194
if dir not in [None, 'plus', '+', 'right', 'minus', '-', 'left',
1195
'above', 'below']:
1196
raise ValueError("dir must be one of None, 'plus', '+', 'right', 'minus', '-', 'left'")
1197
1198
if algorithm == 'maxima':
1199
if dir is None:
1200
l = maxima.sr_limit(ex, v, a)
1201
elif dir in ['plus', '+', 'right', 'above']:
1202
if dir == 'above':
1203
from sage.misc.superseded import deprecation
1204
deprecation(9200, "the keyword 'above' is deprecated. Please use 'right' or '+' instead.")
1205
l = maxima.sr_limit(ex, v, a, 'plus')
1206
elif dir in ['minus', '-', 'left', 'below']:
1207
if dir == 'below':
1208
from sage.misc.superseded import deprecation
1209
deprecation(9200, "the keyword 'below' is deprecated. Please use 'left' or '-' instead.")
1210
l = maxima.sr_limit(ex, v, a, 'minus')
1211
elif algorithm == 'maxima_taylor':
1212
if dir is None:
1213
l = maxima.sr_tlimit(ex, v, a)
1214
elif dir == 'plus' or dir == 'above' or dir == 'from_right':
1215
l = maxima.sr_tlimit(ex, v, a, 'plus')
1216
elif dir == 'minus' or dir == 'below' or dir == 'from_left':
1217
l = maxima.sr_tlimit(ex, v, a, 'minus')
1218
elif algorithm == 'sympy':
1219
if dir is None:
1220
import sympy
1221
l = sympy.limit(ex._sympy_(), v._sympy_(), a._sympy_())
1222
else:
1223
raise NotImplementedError("sympy does not support one-sided limits")
1224
1225
#return l.sage()
1226
return ex.parent()(l)
1227
1228
# lim is alias for limit
1229
lim = limit
1230
1231
###################################################################
1232
# Laplace transform
1233
###################################################################
1234
def laplace(ex, t, s):
1235
r"""
1236
Attempts to compute and return the Laplace transform of
1237
``self`` with respect to the variable `t` and
1238
transform parameter `s`. If this function cannot find a
1239
solution, a formal function is returned.
1240
1241
The function that is returned may be be viewed as a function of
1242
`s`.
1243
1244
DEFINITION:
1245
1246
The Laplace transform of a function `f(t)`,
1247
defined for all real numbers `t \geq 0`, is the function
1248
`F(s)` defined by
1249
1250
.. math::
1251
1252
F(s) = \int_{0}^{\infty} e^{-st} f(t) dt.
1253
1254
EXAMPLES:
1255
1256
We compute a few Laplace transforms::
1257
1258
sage: var('x, s, z, t, t0')
1259
(x, s, z, t, t0)
1260
sage: sin(x).laplace(x, s)
1261
1/(s^2 + 1)
1262
sage: (z + exp(x)).laplace(x, s)
1263
z/s + 1/(s - 1)
1264
sage: log(t/t0).laplace(t, s)
1265
-(euler_gamma + log(s) + log(t0))/s
1266
1267
We do a formal calculation::
1268
1269
sage: f = function('f', x)
1270
sage: g = f.diff(x); g
1271
D[0](f)(x)
1272
sage: g.laplace(x, s)
1273
s*laplace(f(x), x, s) - f(0)
1274
1275
EXAMPLES:
1276
1277
A BATTLE BETWEEN the X-women and the Y-men (by David
1278
Joyner): Solve
1279
1280
.. math::
1281
1282
x' = -16y, x(0)=270, y' = -x + 1, y(0) = 90.
1283
1284
This models a fight between two sides, the "X-women" and the
1285
"Y-men", where the X-women have 270 initially and the Y-men have
1286
90, but the Y-men are better at fighting, because of the higher
1287
factor of "-16" vs "-1", and also get an occasional reinforcement,
1288
because of the "+1" term.
1289
1290
::
1291
1292
sage: var('t')
1293
t
1294
sage: t = var('t')
1295
sage: x = function('x', t)
1296
sage: y = function('y', t)
1297
sage: de1 = x.diff(t) + 16*y
1298
sage: de2 = y.diff(t) + x - 1
1299
sage: de1.laplace(t, s)
1300
s*laplace(x(t), t, s) + 16*laplace(y(t), t, s) - x(0)
1301
sage: de2.laplace(t, s)
1302
s*laplace(y(t), t, s) - 1/s + laplace(x(t), t, s) - y(0)
1303
1304
Next we form the augmented matrix of the above system::
1305
1306
sage: A = matrix([[s, 16, 270],[1, s, 90+1/s]])
1307
sage: E = A.echelon_form()
1308
sage: xt = E[0,2].inverse_laplace(s,t)
1309
sage: yt = E[1,2].inverse_laplace(s,t)
1310
sage: xt
1311
-91/2*e^(4*t) + 629/2*e^(-4*t) + 1
1312
sage: yt
1313
91/8*e^(4*t) + 629/8*e^(-4*t)
1314
sage: p1 = plot(xt,0,1/2,rgbcolor=(1,0,0))
1315
sage: p2 = plot(yt,0,1/2,rgbcolor=(0,1,0))
1316
sage: (p1+p2).save(os.path.join(SAGE_TMP, "de_plot.png"))
1317
1318
Another example::
1319
1320
sage: var('a,s,t')
1321
(a, s, t)
1322
sage: f = exp (2*t + a) * sin(t) * t; f
1323
t*e^(a + 2*t)*sin(t)
1324
sage: L = laplace(f, t, s); L
1325
2*(s - 2)*e^a/(s^2 - 4*s + 5)^2
1326
sage: inverse_laplace(L, s, t)
1327
t*e^(a + 2*t)*sin(t)
1328
1329
Unable to compute solution::
1330
1331
sage: laplace(1/s, s, t)
1332
laplace(1/s, s, t)
1333
"""
1334
if not isinstance(ex, (Expression, Function)):
1335
ex = SR(ex)
1336
return ex.parent()(ex._maxima_().laplace(var(t), var(s)))
1337
1338
def inverse_laplace(ex, t, s):
1339
r"""
1340
Attempts to compute the inverse Laplace transform of
1341
``self`` with respect to the variable `t` and
1342
transform parameter `s`. If this function cannot find a
1343
solution, a formal function is returned.
1344
1345
The function that is returned may be be viewed as a function of
1346
`s`.
1347
1348
DEFINITION: The inverse Laplace transform of a function
1349
`F(s)`, is the function `f(t)` defined by
1350
1351
.. math::
1352
1353
F(s) = \frac{1}{2\pi i} \int_{\gamma-i\infty}^{\gamma + i\infty} e^{st} F(s) dt,
1354
1355
where `\gamma` is chosen so that the contour path of
1356
integration is in the region of convergence of `F(s)`.
1357
1358
EXAMPLES::
1359
1360
sage: var('w, m')
1361
(w, m)
1362
sage: f = (1/(w^2+10)).inverse_laplace(w, m); f
1363
1/10*sqrt(10)*sin(sqrt(10)*m)
1364
sage: laplace(f, m, w)
1365
1/(w^2 + 10)
1366
1367
sage: f(t) = t*cos(t)
1368
sage: s = var('s')
1369
sage: L = laplace(f, t, s); L
1370
t |--> 2*s^2/(s^2 + 1)^2 - 1/(s^2 + 1)
1371
sage: inverse_laplace(L, s, t)
1372
t |--> t*cos(t)
1373
sage: inverse_laplace(1/(s^3+1), s, t)
1374
1/3*(sqrt(3)*sin(1/2*sqrt(3)*t) - cos(1/2*sqrt(3)*t))*e^(1/2*t) + 1/3*e^(-t)
1375
1376
No explicit inverse Laplace transform, so one is returned formally
1377
as a function ``ilt``::
1378
1379
sage: inverse_laplace(cos(s), s, t)
1380
ilt(cos(s), s, t)
1381
"""
1382
if not isinstance(ex, Expression):
1383
ex = SR(ex)
1384
return ex.parent()(ex._maxima_().ilt(var(t), var(s)))
1385
1386
###################################################################
1387
# symbolic evaluation "at" a point
1388
###################################################################
1389
def at(ex, *args, **kwds):
1390
"""
1391
Parses ``at`` formulations from other systems, such as Maxima.
1392
Replaces evaluation 'at' a point with substitution method of
1393
a symbolic expression.
1394
1395
EXAMPLES:
1396
1397
We do not import ``at`` at the top level, but we can use it
1398
as a synonym for substitution if we import it::
1399
1400
sage: g = x^3-3
1401
sage: from sage.calculus.calculus import at
1402
sage: at(g, x=1)
1403
-2
1404
sage: g.subs(x=1)
1405
-2
1406
1407
We find a formal Taylor expansion::
1408
1409
sage: h,x = var('h,x')
1410
sage: u = function('u')
1411
sage: u(x + h)
1412
u(h + x)
1413
sage: diff(u(x+h), x)
1414
D[0](u)(h + x)
1415
sage: taylor(u(x+h),h,0,4)
1416
1/24*h^4*D[0, 0, 0, 0](u)(x) + 1/6*h^3*D[0, 0, 0](u)(x) + 1/2*h^2*D[0, 0](u)(x) + h*D[0](u)(x) + u(x)
1417
1418
We compute a Laplace transform::
1419
1420
sage: var('s,t')
1421
(s, t)
1422
sage: f=function('f', t)
1423
sage: f.diff(t,2)
1424
D[0, 0](f)(t)
1425
sage: f.diff(t,2).laplace(t,s)
1426
s^2*laplace(f(t), t, s) - s*f(0) - D[0](f)(0)
1427
1428
We can also accept a non-keyword list of expression substitutions,
1429
like Maxima does, :trac:`12796`::
1430
1431
sage: from sage.calculus.calculus import at
1432
sage: f = function('f')
1433
sage: at(f(x), [x == 1])
1434
f(1)
1435
1436
TESTS:
1437
1438
Our one non-keyword argument must be a list::
1439
1440
sage: from sage.calculus.calculus import at
1441
sage: f = function('f')
1442
sage: at(f(x), x == 1)
1443
Traceback (most recent call last):
1444
...
1445
TypeError: at can take at most one argument, which must be a list
1446
1447
We should convert our first argument to a symbolic expression::
1448
1449
sage: from sage.calculus.calculus import at
1450
sage: at(int(1), x=1)
1451
1
1452
1453
"""
1454
if not isinstance(ex, (Expression, Function)):
1455
ex = SR(ex)
1456
if len(args) == 1 and isinstance(args[0],list):
1457
for c in args[0]:
1458
kwds[str(c.lhs())]=c.rhs()
1459
else:
1460
if len(args) !=0:
1461
raise TypeError("at can take at most one argument, which must be a list")
1462
1463
return ex.subs(**kwds)
1464
1465
1466
#############################################3333
1467
def var_cmp(x,y):
1468
"""
1469
Return comparison of the two variables x and y, which is just the
1470
comparison of the underlying string representations of the
1471
variables. This is used internally by the Calculus package.
1472
1473
INPUT:
1474
1475
- ``x, y`` - symbolic variables
1476
1477
OUTPUT: Python integer; either -1, 0, or 1.
1478
1479
EXAMPLES::
1480
1481
sage: sage.calculus.calculus.var_cmp(x,x)
1482
0
1483
sage: sage.calculus.calculus.var_cmp(x,var('z'))
1484
-1
1485
sage: sage.calculus.calculus.var_cmp(x,var('a'))
1486
1
1487
"""
1488
return cmp(repr(x), repr(y))
1489
1490
def dummy_limit(*args):
1491
"""
1492
This function is called to create formal wrappers of limits that
1493
Maxima can't compute:
1494
1495
EXAMPLES::
1496
1497
sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a
1498
-limit((erf(x) - 1)*e^(x^2), x, +Infinity)
1499
sage: a = sage.calculus.calculus.dummy_limit(sin(x)/x, x, 0);a
1500
limit(sin(x)/x, x, 0)
1501
"""
1502
return _limit(args[0], var(repr(args[1])), SR(args[2]))
1503
1504
def dummy_diff(*args):
1505
"""
1506
This function is called when 'diff' appears in a Maxima string.
1507
1508
EXAMPLES::
1509
1510
sage: from sage.calculus.calculus import dummy_diff
1511
sage: x,y = var('x,y')
1512
sage: dummy_diff(sin(x*y), x, SR(2), y, SR(1))
1513
-x*y^2*cos(x*y) - 2*y*sin(x*y)
1514
1515
Here the function is used implicitly::
1516
1517
sage: a = var('a')
1518
sage: f = function('cr', a)
1519
sage: g = f.diff(a); g
1520
D[0](cr)(a)
1521
"""
1522
f = args[0]
1523
args = list(args[1:])
1524
for i in range(1, len(args), 2):
1525
args[i] = Integer(args[i])
1526
return f.diff(*args)
1527
1528
def dummy_integrate(*args):
1529
"""
1530
This function is called to create formal wrappers of integrals that
1531
Maxima can't compute:
1532
1533
EXAMPLES::
1534
1535
sage: from sage.calculus.calculus import dummy_integrate
1536
sage: f(x) = function('f',x)
1537
sage: dummy_integrate(f(x), x)
1538
integrate(f(x), x)
1539
sage: a,b = var('a,b')
1540
sage: dummy_integrate(f(x), x, a, b)
1541
integrate(f(x), x, a, b)
1542
"""
1543
if len(args) == 4:
1544
return definite_integral(*args, hold=True)
1545
else:
1546
return indefinite_integral(*args, hold=True)
1547
1548
def dummy_laplace(*args):
1549
"""
1550
This function is called to create formal wrappers of laplace transforms
1551
that Maxima can't compute:
1552
1553
EXAMPLES::
1554
1555
sage: from sage.calculus.calculus import dummy_laplace
1556
sage: s,t = var('s,t')
1557
sage: f(t) = function('f',t)
1558
sage: dummy_laplace(f(t),t,s)
1559
laplace(f(t), t, s)
1560
"""
1561
return _laplace(args[0], var(repr(args[1])), var(repr(args[2])))
1562
1563
def dummy_inverse_laplace(*args):
1564
"""
1565
This function is called to create formal wrappers of inverse laplace
1566
transforms that Maxima can't compute:
1567
1568
EXAMPLES::
1569
1570
sage: from sage.calculus.calculus import dummy_inverse_laplace
1571
sage: s,t = var('s,t')
1572
sage: F(s) = function('F',s)
1573
sage: dummy_inverse_laplace(F(s),s,t)
1574
ilt(F(s), s, t)
1575
"""
1576
return _inverse_laplace(args[0], var(repr(args[1])), var(repr(args[2])))
1577
1578
#######################################################
1579
#
1580
# Helper functions for printing latex expression
1581
#
1582
#######################################################
1583
1584
def _limit_latex_(self, f, x, a, direction=None):
1585
r"""
1586
Return latex expression for limit of a symbolic function.
1587
1588
EXAMPLES::
1589
1590
sage: from sage.calculus.calculus import _limit_latex_
1591
sage: var('x,a')
1592
(x, a)
1593
sage: f = function('f')
1594
sage: _limit_latex_(0, f(x), x, a)
1595
'\\lim_{x \\to a}\\, f\\left(x\\right)'
1596
sage: latex(limit(f(x), x=oo))
1597
\lim_{x \to +\infty}\, f\left(x\right)
1598
1599
TESTS:
1600
1601
When one-sided limits are converted back from maxima, the direction
1602
argument becomes a symbolic variable. We check if typesetting these works::
1603
1604
sage: var('minus,plus')
1605
(minus, plus)
1606
sage: _limit_latex_(0, f(x), x, a, minus)
1607
'\\lim_{x \\to a^-}\\, f\\left(x\\right)'
1608
sage: _limit_latex_(0, f(x), x, a, plus)
1609
'\\lim_{x \\to a^+}\\, f\\left(x\\right)'
1610
sage: latex(limit(f(x),x=a,dir='+'))
1611
\lim_{x \to a^+}\, f\left(x\right)
1612
sage: latex(limit(f(x),x=a,dir='right'))
1613
\lim_{x \to a^+}\, f\left(x\right)
1614
sage: latex(limit(f(x),x=a,dir='-'))
1615
\lim_{x \to a^-}\, f\left(x\right)
1616
sage: latex(limit(f(x),x=a,dir='left'))
1617
\lim_{x \to a^-}\, f\left(x\right)
1618
1619
Check if :trac:`13181` is fixed::
1620
1621
sage: t = var('t')
1622
sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='-'))
1623
\lim_{t \to x^-}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right)
1624
sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='+'))
1625
\lim_{t \to x^+}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right)
1626
sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x))
1627
\lim_{t \to x}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right)
1628
"""
1629
if repr(direction) == 'minus':
1630
dir_str = '^-'
1631
elif repr(direction) == 'plus':
1632
dir_str = '^+'
1633
else:
1634
dir_str = ''
1635
return "\\lim_{%s \\to %s%s}\\, %s"%(latex(x), latex(a), dir_str, latex(f))
1636
1637
def _laplace_latex_(self, *args):
1638
r"""
1639
Return LaTeX expression for Laplace transform of a symbolic function.
1640
1641
EXAMPLES::
1642
1643
sage: from sage.calculus.calculus import _laplace_latex_
1644
sage: var('s,t')
1645
(s, t)
1646
sage: f = function('f',t)
1647
sage: _laplace_latex_(0,f,t,s)
1648
'\\mathcal{L}\\left(f\\left(t\\right), t, s\\right)'
1649
sage: latex(laplace(f, t, s))
1650
\mathcal{L}\left(f\left(t\right), t, s\right)
1651
1652
"""
1653
return "\\mathcal{L}\\left(%s\\right)"%(', '.join([latex(x) for x in args]))
1654
1655
def _inverse_laplace_latex_(self, *args):
1656
r"""
1657
Return LaTeX expression for inverse Laplace transform
1658
of a symbolic function.
1659
1660
EXAMPLES::
1661
1662
sage: from sage.calculus.calculus import _inverse_laplace_latex_
1663
sage: var('s,t')
1664
(s, t)
1665
sage: F = function('F',s)
1666
sage: _inverse_laplace_latex_(0,F,s,t)
1667
'\\mathcal{L}^{-1}\\left(F\\left(s\\right), s, t\\right)'
1668
sage: latex(inverse_laplace(F,s,t))
1669
\mathcal{L}^{-1}\left(F\left(s\right), s, t\right)
1670
"""
1671
return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in args]))
1672
1673
# Return un-evaluated expression as instances of SFunction class
1674
_limit = function_factory('limit', print_latex_func=_limit_latex_)
1675
_laplace = function_factory('laplace', print_latex_func=_laplace_latex_)
1676
_inverse_laplace = function_factory('ilt',
1677
print_latex_func=_inverse_laplace_latex_)
1678
1679
######################################i################
1680
1681
1682
1683
1684
#######################################################
1685
1686
symtable = {'%pi':'pi', '%e': 'e', '%i':'I', '%gamma':'euler_gamma'}
1687
1688
from sage.misc.multireplace import multiple_replace
1689
import re
1690
1691
maxima_tick = re.compile("'[a-z|A-Z|0-9|_]*")
1692
1693
maxima_qp = re.compile("\?\%[a-z|A-Z|0-9|_]*") # e.g., ?%jacobi_cd
1694
1695
maxima_var = re.compile("\%[a-z|A-Z|0-9|_]*") # e.g., ?%jacobi_cd
1696
1697
sci_not = re.compile("(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]\d+)")
1698
1699
polylog_ex = re.compile('li\[([0-9]+?)\]\(')
1700
1701
maxima_polygamma = re.compile("psi\[(\d*)\]\(") # matches psi[n]( where n is a number
1702
1703
def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima):
1704
"""
1705
Given a string representation of a Maxima expression, parse it and
1706
return the corresponding Sage symbolic expression.
1707
1708
INPUT:
1709
1710
- ``x`` - a string
1711
1712
- ``equals_sub`` - (default: False) if True, replace
1713
'=' by '==' in self
1714
1715
- ``maxima`` - (default: the calculus package's
1716
Maxima) the Maxima interpreter to use.
1717
1718
EXAMPLES::
1719
1720
sage: from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms
1721
sage: sefms('x^%e + %e^%pi + %i + sin(0)')
1722
x^e + e^pi + I
1723
sage: f = function('f',x)
1724
sage: sefms('?%at(f(x),x=2)#1')
1725
f(2) != 1
1726
sage: a = sage.calculus.calculus.maxima("x#0"); a
1727
x#0
1728
sage: a.sage()
1729
x != 0
1730
1731
TESTS:
1732
1733
Trac #8459 fixed::
1734
1735
sage: maxima('3*li[2](u)+8*li[33](exp(u))').sage()
1736
8*polylog(33, e^u) + 3*polylog(2, u)
1737
1738
Check if #8345 is fixed::
1739
1740
sage: assume(x,'complex')
1741
sage: t = x.conjugate()
1742
sage: latex(t)
1743
\overline{x}
1744
sage: latex(t._maxima_()._sage_())
1745
\overline{x}
1746
1747
Check that we can understand maxima's not-equals (:trac:`8969`)::
1748
1749
sage: from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms
1750
sage: sefms("x!=3") == (factorial(x) == 3)
1751
True
1752
sage: sefms("x # 3") == SR(x != 3)
1753
True
1754
sage: solve([x != 5], x)
1755
#0: solve_rat_ineq(ineq=x # 5)
1756
[[x - 5 != 0]]
1757
sage: solve([2*x==3, x != 5], x)
1758
[[x == (3/2), (-7/2) != 0]]
1759
1760
"""
1761
syms = sage.symbolic.pynac.symbol_table.get('maxima', {}).copy()
1762
1763
if len(x) == 0:
1764
raise RuntimeError("invalid symbolic expression -- ''")
1765
maxima.set('_tmp_',x)
1766
1767
# This is inefficient since it so rarely is needed:
1768
#r = maxima._eval_line('listofvars(_tmp_);')[1:-1]
1769
1770
s = maxima._eval_line('_tmp_;')
1771
1772
formal_functions = maxima_tick.findall(s)
1773
if len(formal_functions) > 0:
1774
for X in formal_functions:
1775
syms[X[1:]] = function_factory(X[1:])
1776
# You might think there is a potential very subtle bug if 'foo
1777
# is in a string literal -- but string literals should *never*
1778
# ever be part of a symbolic expression.
1779
s = s.replace("'","")
1780
1781
delayed_functions = maxima_qp.findall(s)
1782
if len(delayed_functions) > 0:
1783
for X in delayed_functions:
1784
if X == '?%at': # we will replace Maxima's "at" with symbolic evaluation, not an SFunction
1785
pass
1786
else:
1787
syms[X[2:]] = function_factory(X[2:])
1788
s = s.replace("?%","")
1789
1790
s = polylog_ex.sub('polylog(\\1,',s)
1791
s = multiple_replace(symtable, s)
1792
s = s.replace("%","")
1793
1794
s = s.replace("#","!=") # a lot of this code should be refactored somewhere...
1795
1796
s = maxima_polygamma.sub('psi(\g<1>,',s) # this replaces psi[n](foo) with psi(n,foo), ensuring that derivatives of the digamma function are parsed properly below
1797
1798
if equals_sub:
1799
s = s.replace('=','==')
1800
# unfortunately, this will turn != into !==, which we correct
1801
s = s.replace("!==", "!=")
1802
1803
#replace %union from to_poly_solve with a list
1804
if s[0:5]=='union':
1805
s = s[5:]
1806
s = s[s.find("(")+1:s.rfind(")")]
1807
s = "[" + s + "]" # turn it into a string that looks like a list
1808
1809
#replace %solve from to_poly_solve with the expressions
1810
if s[0:5]=='solve':
1811
s = s[5:]
1812
s = s[s.find("(")+1:s.find("]")+1]
1813
1814
#replace all instances of Maxima's scientific notation
1815
#with regular notation
1816
search = sci_not.search(s)
1817
while not search is None:
1818
(start, end) = search.span()
1819
r = create_RealNumber(s[start:end]).str(no_sci=2, truncate=True)
1820
s = s.replace(s[start:end], r)
1821
search = sci_not.search(s)
1822
1823
# have to do this here, otherwise maxima_tick catches it
1824
syms['limit'] = dummy_limit
1825
syms['diff'] = dummy_diff
1826
syms['integrate'] = dummy_integrate
1827
syms['laplace'] = dummy_laplace
1828
syms['ilt'] = dummy_inverse_laplace
1829
1830
syms['at'] = at
1831
1832
global is_simplified
1833
try:
1834
# use a global flag so all expressions obtained via
1835
# evaluation of maxima code are assumed pre-simplified
1836
is_simplified = True
1837
return symbolic_expression_from_string(s, syms, accept_sequence=True)
1838
except SyntaxError:
1839
raise TypeError("unable to make sense of Maxima expression '%s' in Sage"%s)
1840
finally:
1841
is_simplified = False
1842
1843
1844
# Comma format options for Maxima
1845
def mapped_opts(v):
1846
"""
1847
Used internally when creating a string of options to pass to
1848
Maxima.
1849
1850
INPUT:
1851
1852
- ``v`` - an object
1853
1854
OUTPUT: a string.
1855
1856
The main use of this is to turn Python bools into lower case
1857
strings.
1858
1859
EXAMPLES::
1860
1861
sage: sage.calculus.calculus.mapped_opts(True)
1862
'true'
1863
sage: sage.calculus.calculus.mapped_opts(False)
1864
'false'
1865
sage: sage.calculus.calculus.mapped_opts('bar')
1866
'bar'
1867
"""
1868
if isinstance(v, bool):
1869
return str(v).lower()
1870
return str(v)
1871
1872
def maxima_options(**kwds):
1873
"""
1874
Used internally to create a string of options to pass to Maxima.
1875
1876
EXAMPLES::
1877
1878
sage: sage.calculus.calculus.maxima_options(an_option=True, another=False, foo='bar')
1879
'an_option=true,foo=bar,another=false'
1880
"""
1881
return ','.join(['%s=%s'%(key,mapped_opts(val)) for key, val in kwds.iteritems()])
1882
1883
1884
# Parser for symbolic ring elements
1885
1886
# We keep two dictionaries syms_cur and syms_default to keep the current symbol
1887
# table and the state of the table at startup respectively. These are used by
1888
# the restore() function (see sage.misc.reset).
1889
#
1890
# The dictionary _syms is used as a lookup table for the system function
1891
# registry by _find_func() below. It gets updated by
1892
# symbolic_expression_from_string() before calling the parser.
1893
from sage.symbolic.pynac import symbol_table
1894
_syms = syms_cur = symbol_table.get('functions', {})
1895
syms_default = dict(syms_cur)
1896
1897
# This dictionary is used to pass a lookup table other than the system registry
1898
# to the parser. A global variable is necessary since the parser calls the
1899
# _find_var() and _find_func() functions below without extra arguments.
1900
_augmented_syms = {}
1901
1902
from sage.symbolic.ring import pynac_symbol_registry
1903
1904
def _find_var(name):
1905
"""
1906
Function to pass to Parser for constructing
1907
variables from strings. For internal use.
1908
1909
EXAMPLES::
1910
1911
sage: y = var('y')
1912
sage: sage.calculus.calculus._find_var('y')
1913
y
1914
sage: sage.calculus.calculus._find_var('I')
1915
I
1916
"""
1917
try:
1918
res = _augmented_syms.get(name)
1919
if res is None:
1920
return pynac_symbol_registry[name]
1921
# _augmented_syms might contain entries pointing to functions if
1922
# previous computations polluted the maxima workspace
1923
if not isinstance(res, Function):
1924
return res
1925
except KeyError:
1926
pass
1927
1928
# try to find the name in the global namespace
1929
# needed for identifiers like 'e', etc.
1930
try:
1931
return SR(sage.all.__dict__[name])
1932
except (KeyError, TypeError):
1933
return var(name)
1934
1935
def _find_func(name, create_when_missing = True):
1936
"""
1937
Function to pass to Parser for constructing
1938
functions from strings. For internal use.
1939
1940
EXAMPLES::
1941
1942
sage: sage.calculus.calculus._find_func('limit')
1943
limit
1944
sage: sage.calculus.calculus._find_func('zeta_zeros')
1945
zeta_zeros
1946
sage: f(x)=sin(x)
1947
sage: sage.calculus.calculus._find_func('f')
1948
f
1949
sage: sage.calculus.calculus._find_func('g', create_when_missing=False)
1950
sage: s = sage.calculus.calculus._find_func('sin')
1951
sage: s(0)
1952
0
1953
"""
1954
try:
1955
func = _augmented_syms.get(name)
1956
if func is None:
1957
func = _syms[name]
1958
if not isinstance(func, Expression):
1959
return func
1960
except KeyError:
1961
pass
1962
try:
1963
func = SR(sage.all.__dict__[name])
1964
if not isinstance(func, Expression):
1965
return func
1966
except (KeyError, TypeError):
1967
if create_when_missing:
1968
return function_factory(name)
1969
else:
1970
return None
1971
1972
SR_parser = Parser(make_int = lambda x: SR(Integer(x)),
1973
make_float = lambda x: SR(RealDoubleElement(x)),
1974
make_var = _find_var,
1975
make_function = _find_func)
1976
1977
def symbolic_expression_from_string(s, syms=None, accept_sequence=False):
1978
"""
1979
Given a string, (attempt to) parse it and return the
1980
corresponding Sage symbolic expression. Normally used
1981
to return Maxima output to the user.
1982
1983
INPUT:
1984
1985
- ``s`` - a string
1986
1987
- ``syms`` - (default: None) dictionary of
1988
strings to be regarded as symbols or functions
1989
1990
- ``accept_sequence`` - (default: False) controls whether
1991
to allow a (possibly nested) set of lists and tuples
1992
as input
1993
1994
EXAMPLES::
1995
1996
sage: y = var('y')
1997
sage: sage.calculus.calculus.symbolic_expression_from_string('[sin(0)*x^2,3*spam+e^pi]',syms={'spam':y},accept_sequence=True)
1998
[0, 3*y + e^pi]
1999
"""
2000
global _syms
2001
_syms = sage.symbolic.pynac.symbol_table['functions'].copy()
2002
parse_func = SR_parser.parse_sequence if accept_sequence else SR_parser.parse_expression
2003
if syms is None:
2004
return parse_func(s)
2005
else:
2006
try:
2007
global _augmented_syms
2008
_augmented_syms = syms
2009
return parse_func(s)
2010
finally:
2011
_augmented_syms = {}
2012
2013