Symbolic Computation¶
AUTHORS:
Bobby Moretti and William Stein (2006-2007)
Robert Bradshaw (2007-10): minpoly(), numerical algorithm
Robert Bradshaw (2008-10): minpoly(), algebraic algorithm
Golam Mortuza Hossain (2009-06-15): _limit_latex()
Golam Mortuza Hossain (2009-06-22): _laplace_latex(), _inverse_laplace_latex()
Tom Coates (2010-06-11): fixed upstream Issue #9217
EXAMPLES:
The basic units of the calculus package are symbolic expressions which
are elements of the symbolic expression ring (SR). To create a
symbolic variable object in Sage, use the var() function, whose
argument is the text of that variable. Note that Sage is intelligent
about LaTeXing variable names.
sage: x1 = var('x1'); x1
x1
sage: latex(x1)
x_{1}
sage: theta = var('theta'); theta
theta
sage: latex(theta)
\theta
>>> from sage.all import *
>>> x1 = var('x1'); x1
x1
>>> latex(x1)
x_{1}
>>> theta = var('theta'); theta
theta
>>> latex(theta)
\theta
x1 = var('x1'); x1
latex(x1)
theta = var('theta'); theta
latex(theta)
Sage predefines x to be a global indeterminate.
Thus the following works:
sage: x^2
x^2
sage: type(x)
<class 'sage.symbolic.expression.Expression'>
>>> from sage.all import *
>>> x**Integer(2)
x^2
>>> type(x)
<class 'sage.symbolic.expression.Expression'>
x^2 type(x)
More complicated expressions in Sage can be built up using ordinary arithmetic. The following are valid, and follow the rules of Python arithmetic: (The ‘=’ operator represents assignment, and not equality)
sage: var('x,y,z')
(x, y, z)
sage: f = x + y + z/(2*sin(y*z/55))
sage: g = f^f; g
(x + y + 1/2*z/sin(1/55*y*z))^(x + y + 1/2*z/sin(1/55*y*z))
>>> from sage.all import *
>>> var('x,y,z')
(x, y, z)
>>> f = x + y + z/(Integer(2)*sin(y*z/Integer(55)))
>>> g = f**f; g
(x + y + 1/2*z/sin(1/55*y*z))^(x + y + 1/2*z/sin(1/55*y*z))
var('x,y,z')
f = x + y + z/(2*sin(y*z/55))
g = f^f; g
Differentiation and integration are available, but behind the scenes through Maxima:
sage: f = sin(x)/cos(2*y)
sage: f.derivative(y)
2*sin(x)*sin(2*y)/cos(2*y)^2
sage: g = f.integral(x); g # needs sage.libs.maxima
-cos(x)/cos(2*y)
>>> from sage.all import *
>>> f = sin(x)/cos(Integer(2)*y)
>>> f.derivative(y)
2*sin(x)*sin(2*y)/cos(2*y)^2
>>> g = f.integral(x); g # needs sage.libs.maxima
-cos(x)/cos(2*y)
f = sin(x)/cos(2*y) f.derivative(y) g = f.integral(x); g # needs sage.libs.maxima
Note that these methods usually require an explicit variable name. If none is given, Sage will try to find one for you.
sage: f = sin(x); f.derivative()
cos(x)
>>> from sage.all import *
>>> f = sin(x); f.derivative()
cos(x)
f = sin(x); f.derivative()
If the expression is a callable symbolic expression (i.e., the variable order is specified), then Sage can calculate the matrix derivative (i.e., the gradient, Jacobian matrix, etc.) if no variables are specified. In the example below, we use the second derivative test to determine that there is a saddle point at (0,-1/2).
sage: f(x,y) = x^2*y + y^2 + y
sage: f.diff() # gradient
(x, y) |--> (2*x*y, x^2 + 2*y + 1)
sage: solve(list(f.diff()), [x,y]) # needs sage.libs.maxima
[[x == -I, y == 0], [x == I, y == 0], [x == 0, y == (-1/2)]]
sage: H = f.diff(2); H # Hessian matrix
[(x, y) |--> 2*y (x, y) |--> 2*x]
[(x, y) |--> 2*x (x, y) |--> 2]
sage: H(x=0, y=-1/2)
[-1 0]
[ 0 2]
sage: H(x=0, y=-1/2).eigenvalues() # needs sage.libs.maxima
[-1, 2]
>>> from sage.all import *
>>> __tmp__=var("x,y"); f = symbolic_expression(x**Integer(2)*y + y**Integer(2) + y).function(x,y)
>>> f.diff() # gradient
(x, y) |--> (2*x*y, x^2 + 2*y + 1)
>>> solve(list(f.diff()), [x,y]) # needs sage.libs.maxima
[[x == -I, y == 0], [x == I, y == 0], [x == 0, y == (-1/2)]]
>>> H = f.diff(Integer(2)); H # Hessian matrix
[(x, y) |--> 2*y (x, y) |--> 2*x]
[(x, y) |--> 2*x (x, y) |--> 2]
>>> H(x=Integer(0), y=-Integer(1)/Integer(2))
[-1 0]
[ 0 2]
>>> H(x=Integer(0), y=-Integer(1)/Integer(2)).eigenvalues() # needs sage.libs.maxima
[-1, 2]
f(x,y) = x^2*y + y^2 + y f.diff() # gradient solve(list(f.diff()), [x,y]) # needs sage.libs.maxima H = f.diff(2); H # Hessian matrix H(x=0, y=-1/2) H(x=0, y=-1/2).eigenvalues() # needs sage.libs.maxima
Here we calculate the Jacobian for the polar coordinate transformation:
sage: T(r,theta) = [r*cos(theta),r*sin(theta)]
sage: T
(r, theta) |--> (r*cos(theta), r*sin(theta))
sage: T.diff() # Jacobian matrix
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
sage: diff(T) # Jacobian matrix
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
sage: T.diff().det() # Jacobian
(r, theta) |--> r*cos(theta)^2 + r*sin(theta)^2
>>> from sage.all import *
>>> __tmp__=var("r,theta"); T = symbolic_expression([r*cos(theta),r*sin(theta)]).function(r,theta)
>>> T
(r, theta) |--> (r*cos(theta), r*sin(theta))
>>> T.diff() # Jacobian matrix
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
>>> diff(T) # Jacobian matrix
[ (r, theta) |--> cos(theta) (r, theta) |--> -r*sin(theta)]
[ (r, theta) |--> sin(theta) (r, theta) |--> r*cos(theta)]
>>> T.diff().det() # Jacobian
(r, theta) |--> r*cos(theta)^2 + r*sin(theta)^2
T(r,theta) = [r*cos(theta),r*sin(theta)] T T.diff() # Jacobian matrix diff(T) # Jacobian matrix T.diff().det() # Jacobian
When the order of variables is ambiguous, Sage will raise an exception when differentiating:
sage: f = sin(x+y); f.derivative()
Traceback (most recent call last):
...
ValueError: No differentiation variable specified.
>>> from sage.all import *
>>> f = sin(x+y); f.derivative()
Traceback (most recent call last):
...
ValueError: No differentiation variable specified.
f = sin(x+y); f.derivative()
Simplifying symbolic sums is also possible, using the
sum() command, which also uses Maxima in the background:
sage: k, m = var('k, m')
sage: sum(1/k^4, k, 1, oo) # needs sage.libs.maxima
1/90*pi^4
sage: sum(binomial(m,k), k, 0, m) # needs sage.libs.maxima
2^m
>>> from sage.all import *
>>> k, m = var('k, m')
>>> sum(Integer(1)/k**Integer(4), k, Integer(1), oo) # needs sage.libs.maxima
1/90*pi^4
>>> sum(binomial(m,k), k, Integer(0), m) # needs sage.libs.maxima
2^m
k, m = var('k, m')
sum(1/k^4, k, 1, oo) # needs sage.libs.maxima
sum(binomial(m,k), k, 0, m) # needs sage.libs.maxima
Symbolic matrices can be used as well in various ways, including exponentiation:
sage: M = matrix([[x,x^2],[1/x,x]])
sage: M^2
[x^2 + x 2*x^3]
[ 2 x^2 + x]
sage: e^M # needs sage.libs.maxima
[ 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x)) 1/2*x^(3/2)*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))]
[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))]
>>> from sage.all import *
>>> M = matrix([[x,x**Integer(2)],[Integer(1)/x,x]])
>>> M**Integer(2)
[x^2 + x 2*x^3]
[ 2 x^2 + x]
>>> e**M # needs sage.libs.maxima
[ 1/2*(e^(2*sqrt(x)) + 1)*e^(x - sqrt(x)) 1/2*x^(3/2)*(e^(2*sqrt(x)) - 1)*e^(x - sqrt(x))]
[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))]
M = matrix([[x,x^2],[1/x,x]]) M^2 e^M # needs sage.libs.maxima
Complex exponentiation works, but may require a patched version of maxima (upstream Issue #32898) for now:
sage: # needs sage.libs.maxima
sage: M = i*matrix([[pi]])
sage: e^M # not tested, requires patched maxima
[-1]
sage: M = i*matrix([[pi,0],[0,2*pi]])
sage: e^M
[-1 0]
[ 0 1]
sage: M = matrix([[0,pi],[-pi,0]])
sage: e^M
[-1 0]
[ 0 -1]
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> M = i*matrix([[pi]])
>>> e**M # not tested, requires patched maxima
[-1]
>>> M = i*matrix([[pi,Integer(0)],[Integer(0),Integer(2)*pi]])
>>> e**M
[-1 0]
[ 0 1]
>>> M = matrix([[Integer(0),pi],[-pi,Integer(0)]])
>>> e**M
[-1 0]
[ 0 -1]
# needs sage.libs.maxima M = i*matrix([[pi]]) e^M # not tested, requires patched maxima M = i*matrix([[pi,0],[0,2*pi]]) e^M M = matrix([[0,pi],[-pi,0]]) e^M
Substitution works similarly. We can substitute with a python dict:
sage: f = sin(x*y - z)
sage: f({x: var('t'), y: z})
sin(t*z - z)
>>> from sage.all import *
>>> f = sin(x*y - z)
>>> f({x: var('t'), y: z})
sin(t*z - z)
f = sin(x*y - z)
f({x: var('t'), y: z})
Also we can substitute with keywords:
sage: f = sin(x*y - z)
sage: f(x=t, y=z)
sin(t*z - z)
>>> from sage.all import *
>>> f = sin(x*y - z)
>>> f(x=t, y=z)
sin(t*z - z)
f = sin(x*y - z) f(x=t, y=z)
Another example:
sage: f = sin(2*pi*x/y)
sage: f(x=4)
sin(8*pi/y)
>>> from sage.all import *
>>> f = sin(Integer(2)*pi*x/y)
>>> f(x=Integer(4))
sin(8*pi/y)
f = sin(2*pi*x/y) f(x=4)
It is no longer allowed to call expressions with positional arguments:
sage: f = sin(x)
sage: f(y)
Traceback (most recent call last):
...
TypeError: Substitution using function-call syntax and unnamed
arguments has been removed. You can use named arguments instead, like
EXPR(x=..., y=...)
sage: f(x=pi)
0
>>> from sage.all import *
>>> f = sin(x)
>>> f(y)
Traceback (most recent call last):
...
TypeError: Substitution using function-call syntax and unnamed
arguments has been removed. You can use named arguments instead, like
EXPR(x=..., y=...)
>>> f(x=pi)
0
f = sin(x) f(y) f(x=pi)
We can also make a CallableSymbolicExpression,
which is a SymbolicExpression that is a function of
specified variables in a fixed order. Each
SymbolicExpression has a
function(...) method that is used to create a
CallableSymbolicExpression, as illustrated below:
sage: u = log((2-x)/(y+5))
sage: f = u.function(x, y); f
(x, y) |--> log(-(x - 2)/(y + 5))
>>> from sage.all import *
>>> u = log((Integer(2)-x)/(y+Integer(5)))
>>> f = u.function(x, y); f
(x, y) |--> log(-(x - 2)/(y + 5))
u = log((2-x)/(y+5)) f = u.function(x, y); f
There is an easier way of creating a
CallableSymbolicExpression, which relies on the
Sage preparser.
sage: f(x,y) = log(x)*cos(y); f
(x, y) |--> cos(y)*log(x)
>>> from sage.all import *
>>> __tmp__=var("x,y"); f = symbolic_expression(log(x)*cos(y)).function(x,y); f
(x, y) |--> cos(y)*log(x)
f(x,y) = log(x)*cos(y); f
Then we have fixed an order of variables and there is no ambiguity substituting or evaluating:
sage: f(x,y) = log((2-x)/(y+5))
sage: f(7,t)
log(-5/(t + 5))
>>> from sage.all import *
>>> __tmp__=var("x,y"); f = symbolic_expression(log((Integer(2)-x)/(y+Integer(5)))).function(x,y)
>>> f(Integer(7),t)
log(-5/(t + 5))
f(x,y) = log((2-x)/(y+5)) f(7,t)
Some further examples:
sage: f = 5*sin(x)
sage: f
5*sin(x)
sage: f(x=2)
5*sin(2)
sage: f(x=pi)
0
sage: float(f(x=pi))
0.0
>>> from sage.all import *
>>> f = Integer(5)*sin(x)
>>> f
5*sin(x)
>>> f(x=Integer(2))
5*sin(2)
>>> f(x=pi)
0
>>> float(f(x=pi))
0.0
f = 5*sin(x) f f(x=2) f(x=pi) float(f(x=pi))
Another example:
sage: # needs sage.libs.maxima
sage: f = integrate(1/sqrt(9+x^2), x); f
arcsinh(1/3*x)
sage: f(x=3)
arcsinh(1)
sage: f.derivative(x)
1/sqrt(x^2 + 9)
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> f = integrate(Integer(1)/sqrt(Integer(9)+x**Integer(2)), x); f
arcsinh(1/3*x)
>>> f(x=Integer(3))
arcsinh(1)
>>> f.derivative(x)
1/sqrt(x^2 + 9)
# needs sage.libs.maxima f = integrate(1/sqrt(9+x^2), x); f f(x=3) f.derivative(x)
We compute the length of the parabola from 0 to 2:
sage: # needs sage.libs.maxima
sage: x = var('x')
sage: y = x^2
sage: dy = derivative(y,x)
sage: z = integral(sqrt(1 + dy^2), x, 0, 2)
sage: z
sqrt(17) + 1/4*arcsinh(4)
sage: n(z,200)
4.6467837624329358733826155674904591885104869874232887508703
sage: float(z)
4.646783762432936
>>> from sage.all import *
>>> # needs sage.libs.maxima
>>> x = var('x')
>>> y = x**Integer(2)
>>> dy = derivative(y,x)
>>> z = integral(sqrt(Integer(1) + dy**Integer(2)), x, Integer(0), Integer(2))
>>> z
sqrt(17) + 1/4*arcsinh(4)
>>> n(z,Integer(200))
4.6467837624329358733826155674904591885104869874232887508703
>>> float(z)
4.646783762432936
# needs sage.libs.maxima
x = var('x')
y = x^2
dy = derivative(y,x)
z = integral(sqrt(1 + dy^2), x, 0, 2)
z
n(z,200)
float(z)
We test pickling:
sage: x, y = var('x,y')
sage: f = -sqrt(pi)*(x^3 + sin(x/cos(y)))
sage: bool(loads(dumps(f)) == f)
True
>>> from sage.all import *
>>> x, y = var('x,y')
>>> f = -sqrt(pi)*(x**Integer(3) + sin(x/cos(y)))
>>> bool(loads(dumps(f)) == f)
True
x, y = var('x,y')
f = -sqrt(pi)*(x^3 + sin(x/cos(y)))
bool(loads(dumps(f)) == f)
Coercion examples:
We coerce various symbolic expressions into the complex numbers:
sage: CC(I)
1.00000000000000*I
sage: CC(2*I)
2.00000000000000*I
sage: ComplexField(200)(2*I)
2.0000000000000000000000000000000000000000000000000000000000*I
sage: ComplexField(200)(sin(I))
1.1752011936438014568823818505956008151557179813340958702296*I
sage: f = sin(I) + cos(I/2); f
cosh(1/2) + I*sinh(1)
sage: CC(f)
1.12762596520638 + 1.17520119364380*I
sage: ComplexField(200)(f)
1.1276259652063807852262251614026720125478471180986674836290
+ 1.1752011936438014568823818505956008151557179813340958702296*I
sage: ComplexField(100)(f)
1.1276259652063807852262251614 + 1.1752011936438014568823818506*I
>>> from sage.all import *
>>> CC(I)
1.00000000000000*I
>>> CC(Integer(2)*I)
2.00000000000000*I
>>> ComplexField(Integer(200))(Integer(2)*I)
2.0000000000000000000000000000000000000000000000000000000000*I
>>> ComplexField(Integer(200))(sin(I))
1.1752011936438014568823818505956008151557179813340958702296*I
>>> f = sin(I) + cos(I/Integer(2)); f
cosh(1/2) + I*sinh(1)
>>> CC(f)
1.12762596520638 + 1.17520119364380*I
>>> ComplexField(Integer(200))(f)
1.1276259652063807852262251614026720125478471180986674836290
+ 1.1752011936438014568823818505956008151557179813340958702296*I
>>> ComplexField(Integer(100))(f)
1.1276259652063807852262251614 + 1.1752011936438014568823818506*I
CC(I) CC(2*I) ComplexField(200)(2*I) ComplexField(200)(sin(I)) f = sin(I) + cos(I/2); f CC(f) ComplexField(200)(f) ComplexField(100)(f)
We illustrate construction of an inverse sum where each denominator has a new variable name:
sage: f = sum(1/var('n%s'%i)^i for i in range(10))
sage: f
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
>>> from sage.all import *
>>> f = sum(Integer(1)/var('n%s'%i)**i for i in range(Integer(10)))
>>> f
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
f = sum(1/var('n%s'%i)^i for i in range(10))
f
Note that after calling var, the variables are immediately available for use:
sage: (n1 + n2)^5
(n1 + n2)^5
>>> from sage.all import *
>>> (n1 + n2)**Integer(5)
(n1 + n2)^5
(n1 + n2)^5
We can, of course, substitute:
sage: f(n9=9, n7=n6)
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
>>> from sage.all import *
>>> f(n9=Integer(9), n7=n6)
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
f(n9=9, n7=n6)
- sage.calculus.calculus.at(ex, *args, **kwds)[source]¶
Parses
atformulations from other systems, such as Maxima. Replaces evaluation ‘at’ a point with substitution method of a symbolic expression.EXAMPLES:
We do not import
atat the top level, but we can use it as a synonym for substitution if we import it:sage: g = x^3 - 3 sage: from sage.calculus.calculus import at sage: at(g, x=1) -2 sage: g.subs(x=1) -2
>>> from sage.all import * >>> g = x**Integer(3) - Integer(3) >>> from sage.calculus.calculus import at >>> at(g, x=Integer(1)) -2 >>> g.subs(x=Integer(1)) -2
g = x^3 - 3 from sage.calculus.calculus import at at(g, x=1) g.subs(x=1)
We find a formal Taylor expansion:
sage: h,x = var('h,x') sage: u = function('u') sage: u(x + h) u(h + x) sage: diff(u(x+h), x) D[0](u)(h + x) sage: taylor(u(x+h), h, 0, 4) # needs sage.libs.maxima 1/24*h^4*diff(u(x), x, x, x, x) + 1/6*h^3*diff(u(x), x, x, x) + 1/2*h^2*diff(u(x), x, x) + h*diff(u(x), x) + u(x)
>>> from sage.all import * >>> h,x = var('h,x') >>> u = function('u') >>> u(x + h) u(h + x) >>> diff(u(x+h), x) D[0](u)(h + x) >>> taylor(u(x+h), h, Integer(0), Integer(4)) # needs sage.libs.maxima 1/24*h^4*diff(u(x), x, x, x, x) + 1/6*h^3*diff(u(x), x, x, x) + 1/2*h^2*diff(u(x), x, x) + h*diff(u(x), x) + u(x)
h,x = var('h,x') u = function('u') u(x + h) diff(u(x+h), x) taylor(u(x+h), h, 0, 4) # needs sage.libs.maximaWe compute a Laplace transform:
sage: var('s,t') (s, t) sage: f = function('f')(t) sage: f.diff(t, 2) diff(f(t), t, t) sage: f.diff(t,2).laplace(t,s) # needs sage.libs.maxima s^2*laplace(f(t), t, s) - s*f(0) - D[0](f)(0)
>>> from sage.all import * >>> var('s,t') (s, t) >>> f = function('f')(t) >>> f.diff(t, Integer(2)) diff(f(t), t, t) >>> f.diff(t,Integer(2)).laplace(t,s) # needs sage.libs.maxima s^2*laplace(f(t), t, s) - s*f(0) - D[0](f)(0)
var('s,t') f = function('f')(t) f.diff(t, 2) f.diff(t,2).laplace(t,s) # needs sage.libs.maximaWe can also accept a non-keyword list of expression substitutions, like Maxima does (upstream Issue #12796):
sage: from sage.calculus.calculus import at sage: f = function('f') sage: at(f(x), [x == 1]) f(1)
>>> from sage.all import * >>> from sage.calculus.calculus import at >>> f = function('f') >>> at(f(x), [x == Integer(1)]) f(1)
from sage.calculus.calculus import at f = function('f') at(f(x), [x == 1])
- sage.calculus.calculus.dummy_diff(*args)[source]¶
This function is called when ‘diff’ appears in a Maxima string.
EXAMPLES:
sage: from sage.calculus.calculus import dummy_diff sage: x,y = var('x,y') sage: dummy_diff(sin(x*y), x, SR(2), y, SR(1)) -x*y^2*cos(x*y) - 2*y*sin(x*y)
>>> from sage.all import * >>> from sage.calculus.calculus import dummy_diff >>> x,y = var('x,y') >>> dummy_diff(sin(x*y), x, SR(Integer(2)), y, SR(Integer(1))) -x*y^2*cos(x*y) - 2*y*sin(x*y)
from sage.calculus.calculus import dummy_diff x,y = var('x,y') dummy_diff(sin(x*y), x, SR(2), y, SR(1))Here the function is used implicitly:
sage: a = var('a') sage: f = function('cr')(a) sage: g = f.diff(a); g diff(cr(a), a)
>>> from sage.all import * >>> a = var('a') >>> f = function('cr')(a) >>> g = f.diff(a); g diff(cr(a), a)
a = var('a') f = function('cr')(a) g = f.diff(a); g
- sage.calculus.calculus.dummy_integrate(*args)[source]¶
This function is called to create formal wrappers of integrals that Maxima can’t compute:
EXAMPLES:
sage: from sage.calculus.calculus import dummy_integrate sage: f = function('f') sage: dummy_integrate(f(x), x) integrate(f(x), x) sage: a,b = var('a,b') sage: dummy_integrate(f(x), x, a, b) integrate(f(x), x, a, b)
>>> from sage.all import * >>> from sage.calculus.calculus import dummy_integrate >>> f = function('f') >>> dummy_integrate(f(x), x) integrate(f(x), x) >>> a,b = var('a,b') >>> dummy_integrate(f(x), x, a, b) integrate(f(x), x, a, b)
from sage.calculus.calculus import dummy_integrate f = function('f') dummy_integrate(f(x), x) a,b = var('a,b') dummy_integrate(f(x), x, a, b)
- sage.calculus.calculus.dummy_inverse_laplace(*args)[source]¶
This function is called to create formal wrappers of inverse Laplace transforms that Maxima can’t compute:
EXAMPLES:
sage: from sage.calculus.calculus import dummy_inverse_laplace sage: s,t = var('s,t') sage: F = function('F') sage: dummy_inverse_laplace(F(s), s, t) ilt(F(s), s, t)
>>> from sage.all import * >>> from sage.calculus.calculus import dummy_inverse_laplace >>> s,t = var('s,t') >>> F = function('F') >>> dummy_inverse_laplace(F(s), s, t) ilt(F(s), s, t)
from sage.calculus.calculus import dummy_inverse_laplace s,t = var('s,t') F = function('F') dummy_inverse_laplace(F(s), s, t)
- sage.calculus.calculus.dummy_laplace(*args)[source]¶
This function is called to create formal wrappers of Laplace transforms that Maxima cannot compute:
EXAMPLES:
sage: from sage.calculus.calculus import dummy_laplace sage: s,t = var('s,t') sage: f = function('f') sage: dummy_laplace(f(t), t, s) laplace(f(t), t, s)
>>> from sage.all import * >>> from sage.calculus.calculus import dummy_laplace >>> s,t = var('s,t') >>> f = function('f') >>> dummy_laplace(f(t), t, s) laplace(f(t), t, s)
from sage.calculus.calculus import dummy_laplace s,t = var('s,t') f = function('f') dummy_laplace(f(t), t, s)
- sage.calculus.calculus.dummy_pochhammer(*args)[source]¶
This function is called to create formal wrappers of Pochhammer symbols.
EXAMPLES:
sage: from sage.calculus.calculus import dummy_pochhammer sage: s,t = var('s,t') sage: dummy_pochhammer(s, t) gamma(s + t)/gamma(s)
>>> from sage.all import * >>> from sage.calculus.calculus import dummy_pochhammer >>> s,t = var('s,t') >>> dummy_pochhammer(s, t) gamma(s + t)/gamma(s)
from sage.calculus.calculus import dummy_pochhammer s,t = var('s,t') dummy_pochhammer(s, t)
- sage.calculus.calculus.inverse_laplace(ex, s, t, algorithm='maxima')[source]¶
Return the inverse Laplace transform with respect to the variable \(t\) and transform parameter \(s\), if possible.
If this function cannot find a solution, a formal function is returned. The function that is returned may be viewed as a function of \(t\).
DEFINITION:
The inverse Laplace transform of a function \(F(s)\) is the function \(f(t)\), defined by
\[f(t) = \frac{1}{2\pi i} \int_{\gamma-i\infty}^{\gamma + i\infty} e^{st} F(s) ds,\]where \(\gamma\) is chosen so that the contour path of integration is in the region of convergence of \(F(s)\).
INPUT:
ex– a symbolic expressions– transform parametert– independent variablealgorithm– (default:'maxima') one of'maxima'– use Maxima (the default)'sympy'– use SymPy'giac'– use Giac (optional)
See also
EXAMPLES:
sage: # needs sage.libs.maxima sage: var('w, m') (w, m) sage: f = (1/(w^2+10)).inverse_laplace(w, m); f 1/10*sqrt(10)*sin(sqrt(10)*m) sage: laplace(f, m, w) 1/(w^2 + 10) sage: f(t) = t*cos(t) sage: s = var('s') sage: L = laplace(f, t, s); L # needs sage.libs.maxima t |--> 2*s^2/(s^2 + 1)^2 - 1/(s^2 + 1) sage: inverse_laplace(L, s, t) # needs sage.libs.maxima t |--> t*cos(t) sage: inverse_laplace(1/(s^3+1), s, t) # needs sage.libs.maxima 1/3*(sqrt(3)*sin(1/2*sqrt(3)*t) - cos(1/2*sqrt(3)*t))*e^(1/2*t) + 1/3*e^(-t)
>>> from sage.all import * >>> # needs sage.libs.maxima >>> var('w, m') (w, m) >>> f = (Integer(1)/(w**Integer(2)+Integer(10))).inverse_laplace(w, m); f 1/10*sqrt(10)*sin(sqrt(10)*m) >>> laplace(f, m, w) 1/(w^2 + 10) >>> __tmp__=var("t"); f = symbolic_expression(t*cos(t)).function(t) >>> s = var('s') >>> L = laplace(f, t, s); L # needs sage.libs.maxima t |--> 2*s^2/(s^2 + 1)^2 - 1/(s^2 + 1) >>> inverse_laplace(L, s, t) # needs sage.libs.maxima t |--> t*cos(t) >>> inverse_laplace(Integer(1)/(s**Integer(3)+Integer(1)), s, t) # needs sage.libs.maxima 1/3*(sqrt(3)*sin(1/2*sqrt(3)*t) - cos(1/2*sqrt(3)*t))*e^(1/2*t) + 1/3*e^(-t)
# needs sage.libs.maxima var('w, m') f = (1/(w^2+10)).inverse_laplace(w, m); f laplace(f, m, w) f(t) = t*cos(t) s = var('s') L = laplace(f, t, s); L # needs sage.libs.maxima inverse_laplace(L, s, t) # needs sage.libs.maxima inverse_laplace(1/(s^3+1), s, t) # needs sage.libs.maximaNo explicit inverse Laplace transform, so one is returned formally a function
ilt:sage: inverse_laplace(cos(s), s, t) # needs sage.libs.maxima ilt(cos(s), s, t)
>>> from sage.all import * >>> inverse_laplace(cos(s), s, t) # needs sage.libs.maxima ilt(cos(s), s, t)
inverse_laplace(cos(s), s, t) # needs sage.libs.maxima
Transform an expression involving a time-shift, via SymPy:
sage: inverse_laplace(1/s^2*exp(-s), s, t, algorithm='sympy').simplify() # needs sage.libs.maxima (t - 1)*heaviside(t - 1)
>>> from sage.all import * >>> inverse_laplace(Integer(1)/s**Integer(2)*exp(-s), s, t, algorithm='sympy').simplify() # needs sage.libs.maxima (t - 1)*heaviside(t - 1)
inverse_laplace(1/s^2*exp(-s), s, t, algorithm='sympy').simplify() # needs sage.libs.maxima
The same instance with Giac:
sage: # needs giac sage: inverse_laplace(1/s^2*exp(-s), s, t, algorithm='giac') (t - 1)*heaviside(t - 1)
>>> from sage.all import * >>> # needs giac >>> inverse_laplace(Integer(1)/s**Integer(2)*exp(-s), s, t, algorithm='giac') (t - 1)*heaviside(t - 1)
# needs giac inverse_laplace(1/s^2*exp(-s), s, t, algorithm='giac')
Transform a rational expression:
sage: # needs giac sage: inverse_laplace((2*s^2*exp(-2*s) - exp(-s))/(s^3+1), s, t, ....: algorithm='giac') -1/3*(sqrt(3)*e^(1/2*t - 1/2)*sin(1/2*sqrt(3)*(t - 1)) - cos(1/2*sqrt(3)*(t - 1))*e^(1/2*t - 1/2) + e^(-t + 1))*heaviside(t - 1) + 2/3*(2*cos(1/2*sqrt(3)*(t - 2))*e^(1/2*t - 1) + e^(-t + 2))*heaviside(t - 2) sage: inverse_laplace(1/(s - 1), s, x) # needs sage.libs.maxima e^x
>>> from sage.all import * >>> # needs giac >>> inverse_laplace((Integer(2)*s**Integer(2)*exp(-Integer(2)*s) - exp(-s))/(s**Integer(3)+Integer(1)), s, t, ... algorithm='giac') -1/3*(sqrt(3)*e^(1/2*t - 1/2)*sin(1/2*sqrt(3)*(t - 1)) - cos(1/2*sqrt(3)*(t - 1))*e^(1/2*t - 1/2) + e^(-t + 1))*heaviside(t - 1) + 2/3*(2*cos(1/2*sqrt(3)*(t - 2))*e^(1/2*t - 1) + e^(-t + 2))*heaviside(t - 2) >>> inverse_laplace(Integer(1)/(s - Integer(1)), s, x) # needs sage.libs.maxima e^x
# needs giac inverse_laplace((2*s^2*exp(-2*s) - exp(-s))/(s^3+1), s, t, algorithm='giac') inverse_laplace(1/(s - 1), s, x) # needs sage.libs.maximaThe inverse Laplace transform of a constant is a delta distribution:
sage: inverse_laplace(1, s, t) # needs sage.libs.maxima dirac_delta(t) sage: inverse_laplace(1, s, t, algorithm='sympy') dirac_delta(t) sage: inverse_laplace(1, s, t, algorithm='giac') # needs giac dirac_delta(t)
>>> from sage.all import * >>> inverse_laplace(Integer(1), s, t) # needs sage.libs.maxima dirac_delta(t) >>> inverse_laplace(Integer(1), s, t, algorithm='sympy') dirac_delta(t) >>> inverse_laplace(Integer(1), s, t, algorithm='giac') # needs giac dirac_delta(t)
inverse_laplace(1, s, t) # needs sage.libs.maxima inverse_laplace(1, s, t, algorithm='sympy') inverse_laplace(1, s, t, algorithm='giac') # needs giac
- sage.calculus.calculus.laplace(ex, t, s, algorithm='maxima')[source]¶
Return the Laplace transform with respect to the variable \(t\) and transform parameter \(s\), if possible.
If this function cannot find a solution, a formal function is returned. The function that is returned may be viewed as a function of \(s\).
DEFINITION:
The Laplace transform of a function \(f(t)\), defined for all real numbers \(t \geq 0\), is the function \(F(s)\) defined by
\[F(s) = \int_{0}^{\infty} e^{-st} f(t) dt.\]INPUT:
ex– a symbolic expressiont– independent variables– transform parameteralgorithm– (default:'maxima') one of'maxima'– use Maxima (the default)'sympy'– use SymPy'giac'– use Giac (optional)
Note
The
'sympy'algorithm returns the tuple (\(F\), \(a\),cond) where \(F\) is the Laplace transform of \(f(t)\), \(Re(s)>a\) is the half-plane of convergence, andcondare auxiliary convergence conditions.See also
EXAMPLES:
We compute a few Laplace transforms:
sage: # needs sage.libs.maxima sage: var('x, s, z, t, t0') (x, s, z, t, t0) sage: sin(x).laplace(x, s) 1/(s^2 + 1) sage: (z + exp(x)).laplace(x, s) z/s + 1/(s - 1) sage: log(t/t0).laplace(t, s) -(euler_gamma + log(s) + log(t0))/s
>>> from sage.all import * >>> # needs sage.libs.maxima >>> var('x, s, z, t, t0') (x, s, z, t, t0) >>> sin(x).laplace(x, s) 1/(s^2 + 1) >>> (z + exp(x)).laplace(x, s) z/s + 1/(s - 1) >>> log(t/t0).laplace(t, s) -(euler_gamma + log(s) + log(t0))/s
# needs sage.libs.maxima var('x, s, z, t, t0') sin(x).laplace(x, s) (z + exp(x)).laplace(x, s) log(t/t0).laplace(t, s)We do a formal calculation:
sage: x, s = var('x, s') sage: f = function('f')(x) sage: g = f.diff(x); g diff(f(x), x) sage: g.laplace(x, s) # needs sage.libs.maxima s*laplace(f(x), x, s) - f(0)
>>> from sage.all import * >>> x, s = var('x, s') >>> f = function('f')(x) >>> g = f.diff(x); g diff(f(x), x) >>> g.laplace(x, s) # needs sage.libs.maxima s*laplace(f(x), x, s) - f(0)
x, s = var('x, s') f = function('f')(x) g = f.diff(x); g g.laplace(x, s) # needs sage.libs.maximaA BATTLE BETWEEN the X-women and the Y-men (by David Joyner): Solve
\[x' = -16y, x(0)=270, y' = -x + 1, y(0) = 90.\]This models a fight between two sides, the “X-women” and the “Y-men”, where the X-women have 270 initially and the Y-men have 90, but the Y-men are better at fighting, because of the higher factor of “-16” vs “-1”, and also get an occasional reinforcement, because of the “+1” term.
sage: var('t') t sage: t = var('t') sage: x = function('x')(t) sage: y = function('y')(t) sage: de1 = x.diff(t) + 16*y sage: de2 = y.diff(t) + x - 1 sage: de1.laplace(t, s) # needs sage.libs.maxima s*laplace(x(t), t, s) + 16*laplace(y(t), t, s) - x(0) sage: de2.laplace(t, s) # needs sage.libs.maxima s*laplace(y(t), t, s) - 1/s + laplace(x(t), t, s) - y(0)
>>> from sage.all import * >>> var('t') t >>> t = var('t') >>> x = function('x')(t) >>> y = function('y')(t) >>> de1 = x.diff(t) + Integer(16)*y >>> de2 = y.diff(t) + x - Integer(1) >>> de1.laplace(t, s) # needs sage.libs.maxima s*laplace(x(t), t, s) + 16*laplace(y(t), t, s) - x(0) >>> de2.laplace(t, s) # needs sage.libs.maxima s*laplace(y(t), t, s) - 1/s + laplace(x(t), t, s) - y(0)
var('t') t = var('t') x = function('x')(t) y = function('y')(t) de1 = x.diff(t) + 16*y de2 = y.diff(t) + x - 1 de1.laplace(t, s) # needs sage.libs.maxima de2.laplace(t, s) # needs sage.libs.maximaNext we form the augmented matrix of the above system:
sage: # needs sage.libs.maxima sage: A = matrix([[s, 16, 270], [1, s, 90+1/s]]) sage: E = A.echelon_form() sage: xt = E[0,2].inverse_laplace(s, t) sage: yt = E[1,2].inverse_laplace(s, t) sage: xt -91/2*e^(4*t) + 629/2*e^(-4*t) + 1 sage: yt 91/8*e^(4*t) + 629/8*e^(-4*t) sage: p1 = plot(xt, 0, 1/2, rgbcolor=(1,0,0)) # needs sage.plot sage: p2 = plot(yt, 0, 1/2, rgbcolor=(0,1,0)) # needs sage.plot sage: import tempfile sage: with tempfile.NamedTemporaryFile(suffix='.png') as f: # needs sage.plot ....: (p1 + p2).save(f.name)
>>> from sage.all import * >>> # needs sage.libs.maxima >>> A = matrix([[s, Integer(16), Integer(270)], [Integer(1), s, Integer(90)+Integer(1)/s]]) >>> E = A.echelon_form() >>> xt = E[Integer(0),Integer(2)].inverse_laplace(s, t) >>> yt = E[Integer(1),Integer(2)].inverse_laplace(s, t) >>> xt -91/2*e^(4*t) + 629/2*e^(-4*t) + 1 >>> yt 91/8*e^(4*t) + 629/8*e^(-4*t) >>> p1 = plot(xt, Integer(0), Integer(1)/Integer(2), rgbcolor=(Integer(1),Integer(0),Integer(0))) # needs sage.plot >>> p2 = plot(yt, Integer(0), Integer(1)/Integer(2), rgbcolor=(Integer(0),Integer(1),Integer(0))) # needs sage.plot >>> import tempfile >>> with tempfile.NamedTemporaryFile(suffix='.png') as f: # needs sage.plot ... (p1 + p2).save(f.name)
# needs sage.libs.maxima A = matrix([[s, 16, 270], [1, s, 90+1/s]]) E = A.echelon_form() xt = E[0,2].inverse_laplace(s, t) yt = E[1,2].inverse_laplace(s, t) xt yt p1 = plot(xt, 0, 1/2, rgbcolor=(1,0,0)) # needs sage.plot p2 = plot(yt, 0, 1/2, rgbcolor=(0,1,0)) # needs sage.plot import tempfile with tempfile.NamedTemporaryFile(suffix='.png') as f: # needs sage.plot (p1 + p2).save(f.name)Another example:
sage: # needs sage.libs.maxima sage: var('a,s,t') (a, s, t) sage: f = exp(2*t + a) * sin(t) * t; f t*e^(a + 2*t)*sin(t) sage: L = laplace(f, t, s); L 2*(s - 2)*e^a/(s^4 - 8*s^3 + 26*s^2 - 40*s + 25) sage: inverse_laplace(L, s, t) t*e^(a + 2*t)*sin(t)
>>> from sage.all import * >>> # needs sage.libs.maxima >>> var('a,s,t') (a, s, t) >>> f = exp(Integer(2)*t + a) * sin(t) * t; f t*e^(a + 2*t)*sin(t) >>> L = laplace(f, t, s); L 2*(s - 2)*e^a/(s^4 - 8*s^3 + 26*s^2 - 40*s + 25) >>> inverse_laplace(L, s, t) t*e^(a + 2*t)*sin(t)
# needs sage.libs.maxima var('a,s,t') f = exp(2*t + a) * sin(t) * t; f L = laplace(f, t, s); L inverse_laplace(L, s, t)The Laplace transform of the exponential function:
sage: laplace(exp(x), x, s) # needs sage.libs.maxima 1/(s - 1)
>>> from sage.all import * >>> laplace(exp(x), x, s) # needs sage.libs.maxima 1/(s - 1)
laplace(exp(x), x, s) # needs sage.libs.maxima
Dirac’s delta distribution is handled (the output of SymPy is related to a choice that has to be made when defining Laplace transforms of distributions):
sage: laplace(dirac_delta(t), t, s) # needs sage.libs.maxima 1 sage: F, a, cond = laplace(dirac_delta(t), t, s, algorithm='sympy') sage: a, cond # random - sympy <1.10 gives (-oo, True) (0, True) sage: F # random - sympy <1.9 includes undefined heaviside(0) in answer 1 sage: laplace(dirac_delta(t), t, s, algorithm='giac') # needs giac 1
>>> from sage.all import * >>> laplace(dirac_delta(t), t, s) # needs sage.libs.maxima 1 >>> F, a, cond = laplace(dirac_delta(t), t, s, algorithm='sympy') >>> a, cond # random - sympy <1.10 gives (-oo, True) (0, True) >>> F # random - sympy <1.9 includes undefined heaviside(0) in answer 1 >>> laplace(dirac_delta(t), t, s, algorithm='giac') # needs giac 1
laplace(dirac_delta(t), t, s) # needs sage.libs.maxima F, a, cond = laplace(dirac_delta(t), t, s, algorithm='sympy') a, cond # random - sympy <1.10 gives (-oo, True) F # random - sympy <1.9 includes undefined heaviside(0) in answer laplace(dirac_delta(t), t, s, algorithm='giac') # needs giac
Heaviside step function can be handled with different interfaces. Try with Maxima:
sage: laplace(heaviside(t-1), t, s) # needs sage.libs.maxima e^(-s)/s
>>> from sage.all import * >>> laplace(heaviside(t-Integer(1)), t, s) # needs sage.libs.maxima e^(-s)/s
laplace(heaviside(t-1), t, s) # needs sage.libs.maxima
Try with giac, if it is installed:
sage: # needs giac sage: laplace(heaviside(t-1), t, s, algorithm='giac') e^(-s)/s
>>> from sage.all import * >>> # needs giac >>> laplace(heaviside(t-Integer(1)), t, s, algorithm='giac') e^(-s)/s
# needs giac laplace(heaviside(t-1), t, s, algorithm='giac')
Try with SymPy:
sage: laplace(heaviside(t-1), t, s, algorithm='sympy') (e^(-s)/s, 0, True)
>>> from sage.all import * >>> laplace(heaviside(t-Integer(1)), t, s, algorithm='sympy') (e^(-s)/s, 0, True)
laplace(heaviside(t-1), t, s, algorithm='sympy')
- sage.calculus.calculus.limit(ex, dir, taylor, algorithm, *args, **kwargs)[source]¶
Return the limit as the variable \(v\) approaches \(a\) from the given direction.
SYNTAX:
There are two ways of invoking limit. One can write
limit(expr, x=a, <keywords>)orlimit(expr, x, a, <keywords>). In the first option,xmust be a valid Python identifier. Its string representation is used to create the corresponding symbolic variable with respect to which to take the limit. In the second option,xcan simply be a symbolic variable. For symbolic variables that do not have a string representation that is a valid Python identifier (for instance, ifxis an indexed symbolic variable), the second option is required.INPUT:
ex– the expression whose limit is computed. Must be convertible to a symbolic expression.v– The variable for the limit. Required for thelimit(expr, v, a)syntax. Must be convertible to a symbolic variable.a– The value the variable approaches. Required for thelimit(expr, v, a)syntax. Must be convertible to a symbolic expression.dir– (default:None) direction for the limit:'plus'(or'+'or'right'or'above') for a limit from above,'minus'(or'-'or'left'or'below') for a limit from below. Omitted (None) implies a two-sided limit.taylor– (default:False) ifTrue, use Taylor series via Maxima (may handle more cases but potentially less stable). Setting this automatically uses the'maxima_taylor'algorithm.algorithm– (default:'maxima') the backend algorithm to use. Options include'maxima','maxima_taylor','sympy','giac','fricas','mathematica_free'.**kwargs– (optional) single named parameter. Required for thelimit(expr, v=a)syntax to specify variable and limit point.
Note
The output may also use
und(undefined),ind(indefinite but bounded), andinfinity(complex infinity).EXAMPLES:
sage: # needs sage.libs.maxima sage: x = var('x') sage: f = (1 + 1/x)^x sage: limit(f, x=oo) e sage: limit(f, x, oo) e sage: f.limit(x=5) 7776/3125 sage: f.limit(x, 5) 7776/3125
>>> from sage.all import * >>> # needs sage.libs.maxima >>> x = var('x') >>> f = (Integer(1) + Integer(1)/x)**x >>> limit(f, x=oo) e >>> limit(f, x, oo) e >>> f.limit(x=Integer(5)) 7776/3125 >>> f.limit(x, Integer(5)) 7776/3125
# needs sage.libs.maxima x = var('x') f = (1 + 1/x)^x limit(f, x=oo) limit(f, x, oo) f.limit(x=5) f.limit(x, 5)The positional
limit(expr, v, a)syntax is particularly useful when the limit variablevis an indexed variable or another expression that cannot be used as a keyword argument (fixes upstream Issue #38761):sage: # needs sage.libs.maxima sage: y = var('y', n=3) sage: g = sum(y); g y0 + y1 + y2 sage: limit(g, y[1], 1) y0 + y2 + 1 sage: g.limit(y[0], 5) y1 + y2 + 5 sage: limit(y[0]^2 + y[1], y[0], y[2]) # Limit as y0 -> y2 y2^2 + y1
>>> from sage.all import * >>> # needs sage.libs.maxima >>> y = var('y', n=Integer(3)) >>> g = sum(y); g y0 + y1 + y2 >>> limit(g, y[Integer(1)], Integer(1)) y0 + y2 + 1 >>> g.limit(y[Integer(0)], Integer(5)) y1 + y2 + 5 >>> limit(y[Integer(0)]**Integer(2) + y[Integer(1)], y[Integer(0)], y[Integer(2)]) # Limit as y0 -> y2 y2^2 + y1
# needs sage.libs.maxima y = var('y', n=3) g = sum(y); g limit(g, y[1], 1) g.limit(y[0], 5) limit(y[0]^2 + y[1], y[0], y[2]) # Limit as y0 -> y2Directional limits work with both syntaxes:
sage: # needs sage.libs.maxima sage: limit(1/x, x, 0, dir='+') +Infinity sage: limit(1/x, x=0, dir='-') -Infinity sage: limit(exp(-1/x), x, 0, dir='left') +Infinity
>>> from sage.all import * >>> # needs sage.libs.maxima >>> limit(Integer(1)/x, x, Integer(0), dir='+') +Infinity >>> limit(Integer(1)/x, x=Integer(0), dir='-') -Infinity >>> limit(exp(-Integer(1)/x), x, Integer(0), dir='left') +Infinity
# needs sage.libs.maxima limit(1/x, x, 0, dir='+') limit(1/x, x=0, dir='-') limit(exp(-1/x), x, 0, dir='left')
Using different algorithms:
sage: x = var('x') sage: limit(sin(x)/x, x, 0, algorithm='sympy') 1 sage: limit(sin(x)/x, x, 0, algorithm='giac') # needs sage.libs.giac 1 sage: limit(x^x, x, 0, dir='+', algorithm='fricas') # optional - fricas 1
>>> from sage.all import * >>> x = var('x') >>> limit(sin(x)/x, x, Integer(0), algorithm='sympy') 1 >>> limit(sin(x)/x, x, Integer(0), algorithm='giac') # needs sage.libs.giac 1 >>> limit(x**x, x, Integer(0), dir='+', algorithm='fricas') # optional - fricas 1
x = var('x') limit(sin(x)/x, x, 0, algorithm='sympy') limit(sin(x)/x, x, 0, algorithm='giac') # needs sage.libs.giac limit(x^x, x, 0, dir='+', algorithm='fricas') # optional - fricasUsing Taylor series (can sometimes handle more complex limits):
sage: limit((cos(x)-1)/x^2, x, 0, taylor=True) # needs sage.libs.maxima -1/2
>>> from sage.all import * >>> limit((cos(x)-Integer(1))/x**Integer(2), x, Integer(0), taylor=True) # needs sage.libs.maxima -1/2
limit((cos(x)-1)/x^2, x, 0, taylor=True) # needs sage.libs.maxima
Error handling for incorrect syntax:
sage: limit(sin(x)/x, x=0, y=1) # Too many keyword args Traceback (most recent call last): ... ValueError: multiple keyword arguments specified sage: limit(sin(x)/x, x, 0, y=1) # Mixed positional (v,a) and keyword variable Traceback (most recent call last): ... ValueError: cannot mix positional specification of limit variable and point with keyword variable arguments sage: limit(sin(x)/x, x) # Not enough positional args Traceback (most recent call last): ... ValueError: three positional arguments (expr, v, a) or one positional and one keyword argument (expr, v=a) required sage: limit(sin(x)/x) # No variable specified Traceback (most recent call last): ... ValueError: invalid limit specification sage: limit(sin(x)/x, x, 0, x=0) # Mixing both syntaxes Traceback (most recent call last): ... ValueError: cannot mix positional specification of limit variable and point with keyword variable arguments
>>> from sage.all import * >>> limit(sin(x)/x, x=Integer(0), y=Integer(1)) # Too many keyword args Traceback (most recent call last): ... ValueError: multiple keyword arguments specified >>> limit(sin(x)/x, x, Integer(0), y=Integer(1)) # Mixed positional (v,a) and keyword variable Traceback (most recent call last): ... ValueError: cannot mix positional specification of limit variable and point with keyword variable arguments >>> limit(sin(x)/x, x) # Not enough positional args Traceback (most recent call last): ... ValueError: three positional arguments (expr, v, a) or one positional and one keyword argument (expr, v=a) required >>> limit(sin(x)/x) # No variable specified Traceback (most recent call last): ... ValueError: invalid limit specification >>> limit(sin(x)/x, x, Integer(0), x=Integer(0)) # Mixing both syntaxes Traceback (most recent call last): ... ValueError: cannot mix positional specification of limit variable and point with keyword variable arguments
limit(sin(x)/x, x=0, y=1) # Too many keyword args limit(sin(x)/x, x, 0, y=1) # Mixed positional (v,a) and keyword variable limit(sin(x)/x, x) # Not enough positional args limit(sin(x)/x) # No variable specified limit(sin(x)/x, x, 0, x=0) # Mixing both syntaxes
Domain to real, a regression in 5.46.0, see https://sf.net/p/maxima/bugs/4138
sage: # needs sage.libs.maxima sage: maxima_calculus.eval("domain:real") ... sage: f = (1 + 1/x)^x sage: f.limit(x=1.2).n() 2.06961575467... sage: maxima_calculus.eval("domain:complex"); ...
>>> from sage.all import * >>> # needs sage.libs.maxima >>> maxima_calculus.eval("domain:real") ... >>> f = (Integer(1) + Integer(1)/x)**x >>> f.limit(x=RealNumber('1.2')).n() 2.06961575467... >>> maxima_calculus.eval("domain:complex"); ...
# needs sage.libs.maxima maxima_calculus.eval("domain:real") f = (1 + 1/x)^x f.limit(x=1.2).n() maxima_calculus.eval("domain:complex");Otherwise, it works
sage: # needs sage.libs.maxima sage: f.limit(x=I, taylor=True) (-I + 1)^I sage: f(x=1.2) 2.0696157546720... sage: f(x=I) (-I + 1)^I sage: CDF(f(x=I)) 2.0628722350809046 + 0.7450070621797239*I sage: CDF(f.limit(x=I)) 2.0628722350809046 + 0.7450070621797239*I
>>> from sage.all import * >>> # needs sage.libs.maxima >>> f.limit(x=I, taylor=True) (-I + 1)^I >>> f(x=RealNumber('1.2')) 2.0696157546720... >>> f(x=I) (-I + 1)^I >>> CDF(f(x=I)) 2.0628722350809046 + 0.7450070621797239*I >>> CDF(f.limit(x=I)) 2.0628722350809046 + 0.7450070621797239*I
# needs sage.libs.maxima f.limit(x=I, taylor=True) f(x=1.2) f(x=I) CDF(f(x=I)) CDF(f.limit(x=I))
Notice that Maxima may ask for more information:
sage: # needs sage.libs.maxima sage: var('a') a sage: limit(x^a,x=0) Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a positive, negative or zero?
>>> from sage.all import * >>> # needs sage.libs.maxima >>> var('a') a >>> limit(x**a,x=Integer(0)) Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a positive, negative or zero?
# needs sage.libs.maxima var('a') limit(x^a,x=0)With this example, Maxima is looking for a LOT of information:
sage: # needs sage.libs.maxima sage: assume(a>0) sage: limit(x^a,x=0) # random - maxima 5.46.0 does not need extra assumption Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a an integer? sage: assume(a,'integer') sage: limit(x^a, x=0) # random - maxima 5.46.0 does not need extra assumption Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a an even number? sage: assume(a, 'even') sage: limit(x^a, x=0) 0 sage: forget()
>>> from sage.all import * >>> # needs sage.libs.maxima >>> assume(a>Integer(0)) >>> limit(x**a,x=Integer(0)) # random - maxima 5.46.0 does not need extra assumption Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a an integer? >>> assume(a,'integer') >>> limit(x**a, x=Integer(0)) # random - maxima 5.46.0 does not need extra assumption Traceback (most recent call last): ... ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(a>0)', see `assume?` for more details) Is a an even number? >>> assume(a, 'even') >>> limit(x**a, x=Integer(0)) 0 >>> forget()
# needs sage.libs.maxima assume(a>0) limit(x^a,x=0) # random - maxima 5.46.0 does not need extra assumption assume(a,'integer') limit(x^a, x=0) # random - maxima 5.46.0 does not need extra assumption assume(a, 'even') limit(x^a, x=0) forget()
More examples:
sage: # needs sage.libs.maxima sage: limit(x*log(x), x=0, dir='+') 0 sage: lim((x+1)^(1/x), x=0) e sage: lim(e^x/x, x=oo) +Infinity sage: lim(e^x/x, x=-oo) 0 sage: lim(-e^x/x, x=oo) -Infinity sage: lim((cos(x))/(x^2), x=0) +Infinity sage: lim(sqrt(x^2+1) - x, x=oo) 0 sage: lim(x^2/(sec(x)-1), x=0) 2 sage: lim(cos(x)/(cos(x)-1), x=0) -Infinity sage: lim(x*sin(1/x), x=0) 0 sage: limit(e^(-1/x), x=0, dir='right') 0 sage: limit(e^(-1/x), x=0, dir='left') +Infinity
>>> from sage.all import * >>> # needs sage.libs.maxima >>> limit(x*log(x), x=Integer(0), dir='+') 0 >>> lim((x+Integer(1))**(Integer(1)/x), x=Integer(0)) e >>> lim(e**x/x, x=oo) +Infinity >>> lim(e**x/x, x=-oo) 0 >>> lim(-e**x/x, x=oo) -Infinity >>> lim((cos(x))/(x**Integer(2)), x=Integer(0)) +Infinity >>> lim(sqrt(x**Integer(2)+Integer(1)) - x, x=oo) 0 >>> lim(x**Integer(2)/(sec(x)-Integer(1)), x=Integer(0)) 2 >>> lim(cos(x)/(cos(x)-Integer(1)), x=Integer(0)) -Infinity >>> lim(x*sin(Integer(1)/x), x=Integer(0)) 0 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='right') 0 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='left') +Infinity
# needs sage.libs.maxima limit(x*log(x), x=0, dir='+') lim((x+1)^(1/x), x=0) lim(e^x/x, x=oo) lim(e^x/x, x=-oo) lim(-e^x/x, x=oo) lim((cos(x))/(x^2), x=0) lim(sqrt(x^2+1) - x, x=oo) lim(x^2/(sec(x)-1), x=0) lim(cos(x)/(cos(x)-1), x=0) lim(x*sin(1/x), x=0) limit(e^(-1/x), x=0, dir='right') limit(e^(-1/x), x=0, dir='left')
sage: # needs sage.libs.maxima sage: f = log(log(x)) / log(x) sage: forget(); assume(x < -2); lim(f, x=0, taylor=True) 0 sage: forget()
>>> from sage.all import * >>> # needs sage.libs.maxima >>> f = log(log(x)) / log(x) >>> forget(); assume(x < -Integer(2)); lim(f, x=Integer(0), taylor=True) 0 >>> forget()
# needs sage.libs.maxima f = log(log(x)) / log(x) forget(); assume(x < -2); lim(f, x=0, taylor=True) forget()
Here ind means “indefinite but bounded”:
sage: lim(sin(1/x), x = 0) # needs sage.libs.maxima ind
>>> from sage.all import * >>> lim(sin(Integer(1)/x), x = Integer(0)) # needs sage.libs.maxima ind
lim(sin(1/x), x = 0) # needs sage.libs.maxima
We can use other packages than maxima, namely “sympy”, “giac”, “fricas”.
With the standard package Giac:
sage: # needs sage.libs.giac sage: (exp(-x)/(2+sin(x))).limit(x=oo, algorithm='giac') 0 sage: limit(e^(-1/x), x=0, dir='right', algorithm='giac') 0 sage: limit(e^(-1/x), x=0, dir='left', algorithm='giac') +Infinity sage: (x / (x+2^x+cos(x))).limit(x=-infinity, algorithm='giac') 1
>>> from sage.all import * >>> # needs sage.libs.giac >>> (exp(-x)/(Integer(2)+sin(x))).limit(x=oo, algorithm='giac') 0 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='right', algorithm='giac') 0 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='left', algorithm='giac') +Infinity >>> (x / (x+Integer(2)**x+cos(x))).limit(x=-infinity, algorithm='giac') 1
# needs sage.libs.giac (exp(-x)/(2+sin(x))).limit(x=oo, algorithm='giac') limit(e^(-1/x), x=0, dir='right', algorithm='giac') limit(e^(-1/x), x=0, dir='left', algorithm='giac') (x / (x+2^x+cos(x))).limit(x=-infinity, algorithm='giac')
With the optional package FriCAS:
sage: (x / (x+2^x+cos(x))).limit(x=-infinity, algorithm='fricas') # optional - fricas 1 sage: limit(e^(-1/x), x=0, dir='right', algorithm='fricas') # optional - fricas 0 sage: limit(e^(-1/x), x=0, dir='left', algorithm='fricas') # optional - fricas +Infinity
>>> from sage.all import * >>> (x / (x+Integer(2)**x+cos(x))).limit(x=-infinity, algorithm='fricas') # optional - fricas 1 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='right', algorithm='fricas') # optional - fricas 0 >>> limit(e**(-Integer(1)/x), x=Integer(0), dir='left', algorithm='fricas') # optional - fricas +Infinity
(x / (x+2^x+cos(x))).limit(x=-infinity, algorithm='fricas') # optional - fricas limit(e^(-1/x), x=0, dir='right', algorithm='fricas') # optional - fricas limit(e^(-1/x), x=0, dir='left', algorithm='fricas') # optional - fricas
One can also call Mathematica’s online interface:
sage: limit(pi+log(x)/x,x=oo, algorithm='mathematica_free') # optional - internet pi
>>> from sage.all import * >>> limit(pi+log(x)/x,x=oo, algorithm='mathematica_free') # optional - internet pi
limit(pi+log(x)/x,x=oo, algorithm='mathematica_free') # optional - internet
- sage.calculus.calculus.mapped_opts(v)[source]¶
Used internally when creating a string of options to pass to Maxima.
INPUT:
v– an object
OUTPUT: string
The main use of this is to turn Python bools into lower case strings.
EXAMPLES:
sage: sage.calculus.calculus.mapped_opts(True) 'true' sage: sage.calculus.calculus.mapped_opts(False) 'false' sage: sage.calculus.calculus.mapped_opts('bar') 'bar'
>>> from sage.all import * >>> sage.calculus.calculus.mapped_opts(True) 'true' >>> sage.calculus.calculus.mapped_opts(False) 'false' >>> sage.calculus.calculus.mapped_opts('bar') 'bar'
sage.calculus.calculus.mapped_opts(True) sage.calculus.calculus.mapped_opts(False) sage.calculus.calculus.mapped_opts('bar')
- sage.calculus.calculus.maxima_options(**kwds)[source]¶
Used internally to create a string of options to pass to Maxima.
EXAMPLES:
sage: sage.calculus.calculus.maxima_options(an_option=True, another=False, foo='bar') 'an_option=true,another=false,foo=bar'
>>> from sage.all import * >>> sage.calculus.calculus.maxima_options(an_option=True, another=False, foo='bar') 'an_option=true,another=false,foo=bar'
sage.calculus.calculus.maxima_options(an_option=True, another=False, foo='bar')
- sage.calculus.calculus.minpoly(ex, var='x', algorithm=None, bits=None, degree=None, epsilon=0)[source]¶
Return the minimal polynomial of
self, if possible.INPUT:
var– polynomial variable name (default:'x')algorithm–'algebraic'or'numerical'(default both, but with numerical first)bits– the number of bits to use in numerical approxdegree– the expected algebraic degreeepsilon– return without error as long as f(self) epsilon, in the case that the result cannot be provenAll of the above parameters are optional, with epsilon=0,
bitsanddegreetested up to 1000 and 24 by default respectively. The numerical algorithm will be faster if bits and/or degree are given explicitly. The algebraic algorithm ignores the last three parameters.
OUTPUT: the minimal polynomial of
self. If the numerical algorithm is used, then it is proved symbolically whenepsilon=0(default).If the minimal polynomial could not be found, two distinct kinds of errors are raised. If no reasonable candidate was found with the given
bits/degreeparameters, aValueErrorwill be raised. If a reasonable candidate was found but (perhaps due to limits in the underlying symbolic package) was unable to be proved correct, aNotImplementedErrorwill be raised.ALGORITHM: Two distinct algorithms are used, depending on the algorithm parameter. By default, the numerical algorithm is attempted first, then the algebraic one.
Algebraic: Attempt to evaluate this expression in
QQbar, using cyclotomic fields to resolve exponential and trig functions at rational multiples of \(\pi\), field extensions to handle roots and rational exponents, and computing compositums to represent the full expression as an element of a number field where the minimal polynomial can be computed exactly. Thebits,degree, andepsilonparameters are ignored.Numerical: Computes a numerical approximation of
selfand use PARI’s pari:algdep to get a candidate minpoly \(f\). If \(f(\mathtt{self})\), evaluated to a higher precision, is close enough to 0 then evaluate \(f(\mathtt{self})\) symbolically, attempting to prove vanishing. If this fails, andepsilonis nonzero, return \(f\) if and only if \(f(\mathtt{self}) < \mathtt{epsilon}\). Otherwise raise aValueError(if no suitable candidate was found) or aNotImplementedError(if a likely candidate was found but could not be proved correct).EXAMPLES: First some simple examples:
sage: # needs fpylll sage: sqrt(2).minpoly() x^2 - 2 sage: minpoly(2^(1/3)) x^3 - 2 sage: minpoly(sqrt(2) + sqrt(-1)) x^4 - 2*x^2 + 9 sage: minpoly(sqrt(2)-3^(1/3)) x^6 - 6*x^4 + 6*x^3 + 12*x^2 + 36*x + 1
>>> from sage.all import * >>> # needs fpylll >>> sqrt(Integer(2)).minpoly() x^2 - 2 >>> minpoly(Integer(2)**(Integer(1)/Integer(3))) x^3 - 2 >>> minpoly(sqrt(Integer(2)) + sqrt(-Integer(1))) x^4 - 2*x^2 + 9 >>> minpoly(sqrt(Integer(2))-Integer(3)**(Integer(1)/Integer(3))) x^6 - 6*x^4 + 6*x^3 + 12*x^2 + 36*x + 1
# needs fpylll sqrt(2).minpoly() minpoly(2^(1/3)) minpoly(sqrt(2) + sqrt(-1)) minpoly(sqrt(2)-3^(1/3))
Works with trig and exponential functions too.
sage: # needs fpylll sage: sin(pi/3).minpoly() x^2 - 3/4 sage: sin(pi/7).minpoly() x^6 - 7/4*x^4 + 7/8*x^2 - 7/64 sage: minpoly(exp(I*pi/17)) 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
>>> from sage.all import * >>> # needs fpylll >>> sin(pi/Integer(3)).minpoly() x^2 - 3/4 >>> sin(pi/Integer(7)).minpoly() x^6 - 7/4*x^4 + 7/8*x^2 - 7/64 >>> minpoly(exp(I*pi/Integer(17))) 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
# needs fpylll sin(pi/3).minpoly() sin(pi/7).minpoly() minpoly(exp(I*pi/17))
Here we verify it gives the same result as the abstract number field.
sage: # needs fpylll sage: (sqrt(2) + sqrt(3) + sqrt(6)).minpoly() x^4 - 22*x^2 - 48*x - 23 sage: K.<a,b> = NumberField([x^2-2, x^2-3]) sage: (a+b+a*b).absolute_minpoly() x^4 - 22*x^2 - 48*x - 23
>>> from sage.all import * >>> # needs fpylll >>> (sqrt(Integer(2)) + sqrt(Integer(3)) + sqrt(Integer(6))).minpoly() x^4 - 22*x^2 - 48*x - 23 >>> K = NumberField([x**Integer(2)-Integer(2), x**Integer(2)-Integer(3)], names=('a', 'b',)); (a, b,) = K._first_ngens(2) >>> (a+b+a*b).absolute_minpoly() x^4 - 22*x^2 - 48*x - 23
# needs fpylll (sqrt(2) + sqrt(3) + sqrt(6)).minpoly() K.<a,b> = NumberField([x^2-2, x^2-3]) (a+b+a*b).absolute_minpoly()
The
minpoly()function is used implicitly when creating number fields:sage: # needs fpylll sage: x = var('x') sage: eqn = x^3 + sqrt(2)*x + 5 == 0 sage: a = solve(eqn, x)[0].rhs() sage: QQ[a] Number Field in a with defining polynomial x^6 + 10*x^3 - 2*x^2 + 25 with a = 0.7185272465828846? - 1.721353471724806?*I
>>> from sage.all import * >>> # needs fpylll >>> x = var('x') >>> eqn = x**Integer(3) + sqrt(Integer(2))*x + Integer(5) == Integer(0) >>> a = solve(eqn, x)[Integer(0)].rhs() >>> QQ[a] Number Field in a with defining polynomial x^6 + 10*x^3 - 2*x^2 + 25 with a = 0.7185272465828846? - 1.721353471724806?*I
# needs fpylll x = var('x') eqn = x^3 + sqrt(2)*x + 5 == 0 a = solve(eqn, x)[0].rhs() QQ[a]Here we solve a cubic and then recover it from its complicated radical expansion.
sage: # needs fpylll sage: f = x^3 - x + 1 sage: a = f.solve(x)[0].rhs(); a -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) sage: a.minpoly() x^3 - x + 1
>>> from sage.all import * >>> # needs fpylll >>> f = x**Integer(3) - x + Integer(1) >>> a = f.solve(x)[Integer(0)].rhs(); a -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) >>> a.minpoly() x^3 - x + 1
# needs fpylll f = x^3 - x + 1 a = f.solve(x)[0].rhs(); a a.minpoly()
Note that simplification may be necessary to see that the minimal polynomial is correct.
sage: # needs fpylll sage: a = sqrt(2) + sqrt(3) + sqrt(5) sage: f = a.minpoly(); f x^8 - 40*x^6 + 352*x^4 - 960*x^2 + 576 sage: f(a) (sqrt(5) + sqrt(3) + sqrt(2))^8 - 40*(sqrt(5) + sqrt(3) + sqrt(2))^6 + 352*(sqrt(5) + sqrt(3) + sqrt(2))^4 - 960*(sqrt(5) + sqrt(3) + sqrt(2))^2 + 576 sage: f(a).expand() 0
>>> from sage.all import * >>> # needs fpylll >>> a = sqrt(Integer(2)) + sqrt(Integer(3)) + sqrt(Integer(5)) >>> f = a.minpoly(); f x^8 - 40*x^6 + 352*x^4 - 960*x^2 + 576 >>> f(a) (sqrt(5) + sqrt(3) + sqrt(2))^8 - 40*(sqrt(5) + sqrt(3) + sqrt(2))^6 + 352*(sqrt(5) + sqrt(3) + sqrt(2))^4 - 960*(sqrt(5) + sqrt(3) + sqrt(2))^2 + 576 >>> f(a).expand() 0
# needs fpylll a = sqrt(2) + sqrt(3) + sqrt(5) f = a.minpoly(); f f(a) f(a).expand()
sage: # needs fpylll sage: a = sin(pi/7) sage: f = a.minpoly(algorithm='numerical'); f x^6 - 7/4*x^4 + 7/8*x^2 - 7/64 sage: f(a).horner(a).numerical_approx(100) 0.00000000000000000000000000000
>>> from sage.all import * >>> # needs fpylll >>> a = sin(pi/Integer(7)) >>> f = a.minpoly(algorithm='numerical'); f x^6 - 7/4*x^4 + 7/8*x^2 - 7/64 >>> f(a).horner(a).numerical_approx(Integer(100)) 0.00000000000000000000000000000
# needs fpylll a = sin(pi/7) f = a.minpoly(algorithm='numerical'); f f(a).horner(a).numerical_approx(100)
The degree must be high enough (default tops out at 24).
sage: # needs fpylll sage: a = sqrt(3) + sqrt(2) sage: a.minpoly(algorithm='numerical', bits=100, degree=3) Traceback (most recent call last): ... ValueError: Could not find minimal polynomial (100 bits, degree 3). sage: a.minpoly(algorithm='numerical', bits=100, degree=10) x^4 - 10*x^2 + 1
>>> from sage.all import * >>> # needs fpylll >>> a = sqrt(Integer(3)) + sqrt(Integer(2)) >>> a.minpoly(algorithm='numerical', bits=Integer(100), degree=Integer(3)) Traceback (most recent call last): ... ValueError: Could not find minimal polynomial (100 bits, degree 3). >>> a.minpoly(algorithm='numerical', bits=Integer(100), degree=Integer(10)) x^4 - 10*x^2 + 1
# needs fpylll a = sqrt(3) + sqrt(2) a.minpoly(algorithm='numerical', bits=100, degree=3) a.minpoly(algorithm='numerical', bits=100, degree=10)
sage: # needs fpylll sage: cos(pi/33).minpoly(algorithm='algebraic') 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 sage: cos(pi/33).minpoly(algorithm='numerical') 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
>>> from sage.all import * >>> # needs fpylll >>> cos(pi/Integer(33)).minpoly(algorithm='algebraic') 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 >>> cos(pi/Integer(33)).minpoly(algorithm='numerical') 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
# needs fpylll cos(pi/33).minpoly(algorithm='algebraic') cos(pi/33).minpoly(algorithm='numerical')
Sometimes it fails, as it must given that some numbers aren’t algebraic:
sage: sin(1).minpoly(algorithm='numerical') # needs fpylll Traceback (most recent call last): ... ValueError: Could not find minimal polynomial (1000 bits, degree 24).
>>> from sage.all import * >>> sin(Integer(1)).minpoly(algorithm='numerical') # needs fpylll Traceback (most recent call last): ... ValueError: Could not find minimal polynomial (1000 bits, degree 24).
sin(1).minpoly(algorithm='numerical') # needs fpylll
Note
Of course, failure to produce a minimal polynomial does not necessarily indicate that this number is transcendental.
- sage.calculus.calculus.mma_free_limit(expression, v, a, dir=None)[source]¶
Limit using Mathematica’s online interface.
INPUT:
expression– symbolic expressionv– variablea– value where the variable goes todir–'+','-'orNone(default:None)
EXAMPLES:
sage: from sage.calculus.calculus import mma_free_limit sage: mma_free_limit(sin(x)/x, x, a=0) # optional - internet 1
>>> from sage.all import * >>> from sage.calculus.calculus import mma_free_limit >>> mma_free_limit(sin(x)/x, x, a=Integer(0)) # optional - internet 1
from sage.calculus.calculus import mma_free_limit mma_free_limit(sin(x)/x, x, a=0) # optional - internet
Another simple limit:
sage: mma_free_limit(e^(-x), x, a=oo) # optional - internet 0
>>> from sage.all import * >>> mma_free_limit(e**(-x), x, a=oo) # optional - internet 0
mma_free_limit(e^(-x), x, a=oo) # optional - internet
- sage.calculus.calculus.nintegral(ex, x, a, b, desired_relative_error='1e-8', maximum_num_subintervals=200)[source]¶
Return a floating point machine precision numerical approximation to the integral of
selffrom \(a\) to \(b\), computed using floating point arithmetic via maxima.INPUT:
x– variable to integrate with respect toa– lower endpoint of integrationb– upper endpoint of integrationdesired_relative_error– (default:1e-8) the desired relative errormaximum_num_subintervals– (default: 200) maximal number of subintervals
OUTPUT: float; approximation to the integral
float: estimated absolute error of the approximation
the number of integrand evaluations
an error code:
0– no problems were encountered1– too many subintervals were done2– excessive roundoff error3– extremely bad integrand behavior4– failed to converge5– integral is probably divergent or slowly convergent6– the input is invalid; this includes the case ofdesired_relative_errorbeing too small to be achieved
ALIAS:
nintegrate()is the same asnintegral()REMARK: There is also a function
numerical_integral()that implements numerical integration using the GSL C library. It is potentially much faster and applies to arbitrary user defined functions.Also, there are limits to the precision to which Maxima can compute the integral due to limitations in quadpack. In the following example, remark that the last value of the returned tuple is
6, indicating that the input was invalid, in this case because of a too high desired precision.sage: f = x sage: f.nintegral(x, 0, 1, 1e-14) # needs sage.libs.maxima (0.0, 0.0, 0, 6)
>>> from sage.all import * >>> f = x >>> f.nintegral(x, Integer(0), Integer(1), RealNumber('1e-14')) # needs sage.libs.maxima (0.0, 0.0, 0, 6)
f = x f.nintegral(x, 0, 1, 1e-14) # needs sage.libs.maxima
EXAMPLES:
sage: f(x) = exp(-sqrt(x)) sage: f.nintegral(x, 0, 1) # needs sage.libs.maxima (0.5284822353142306, 4.163...e-11, 231, 0)
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(exp(-sqrt(x))).function(x) >>> f.nintegral(x, Integer(0), Integer(1)) # needs sage.libs.maxima (0.5284822353142306, 4.163...e-11, 231, 0)
f(x) = exp(-sqrt(x)) f.nintegral(x, 0, 1) # needs sage.libs.maxima
We can also use the
numerical_integral()function, which calls the GSL C library.sage: numerical_integral(f, 0, 1) (0.528482232253147, 6.83928460...e-07)
>>> from sage.all import * >>> numerical_integral(f, Integer(0), Integer(1)) (0.528482232253147, 6.83928460...e-07)
numerical_integral(f, 0, 1)
Note that in exotic cases where floating point evaluation of the expression leads to the wrong value, then the output can be completely wrong:
sage: f = exp(pi*sqrt(163)) - 262537412640768744
>>> from sage.all import * >>> f = exp(pi*sqrt(Integer(163))) - Integer(262537412640768744)
f = exp(pi*sqrt(163)) - 262537412640768744
Despite appearance, \(f\) is really very close to 0, but one gets a nonzero value since the definition of
float(f)is that it makes all constants inside the expression floats, then evaluates each function and each arithmetic operation using float arithmetic:sage: float(f) -480.0
>>> from sage.all import * >>> float(f) -480.0
float(f)
Computing to higher precision we see the truth:
sage: f.n(200) -7.4992740280181431112064614366622348652078895136533593355718e-13 sage: f.n(300) -7.49927402801814311120646143662663009137292462589621789352095066181709095575681963967103004e-13
>>> from sage.all import * >>> f.n(Integer(200)) -7.4992740280181431112064614366622348652078895136533593355718e-13 >>> f.n(Integer(300)) -7.49927402801814311120646143662663009137292462589621789352095066181709095575681963967103004e-13
f.n(200) f.n(300)
Now numerically integrating, we see why the answer is wrong:
sage: f.nintegrate(x,0,1) # needs sage.libs.maxima (-480.000000000000..., 5.32907051820075...e-12, 21, 0)
>>> from sage.all import * >>> f.nintegrate(x,Integer(0),Integer(1)) # needs sage.libs.maxima (-480.000000000000..., 5.32907051820075...e-12, 21, 0)
f.nintegrate(x,0,1) # needs sage.libs.maxima
It is just because every floating point evaluation of \(f\) returns \(-480.0\) in floating point.
Important note: using PARI/GP one can compute numerical integrals to high precision:
sage: # needs sage.libs.pari sage: gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') '2.5657285005610514829176211363206621657 E-127' sage: old_prec = gp.set_real_precision(50) sage: gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') '2.5657285005610514829173563961304957417746108003917 E-127' sage: gp.set_real_precision(old_prec) 57
>>> from sage.all import * >>> # needs sage.libs.pari >>> gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') '2.5657285005610514829176211363206621657 E-127' >>> old_prec = gp.set_real_precision(Integer(50)) >>> gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') '2.5657285005610514829173563961304957417746108003917 E-127' >>> gp.set_real_precision(old_prec) 57
# needs sage.libs.pari gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') old_prec = gp.set_real_precision(50) gp.eval('intnum(x=17,42,exp(-x^2)*log(x))') gp.set_real_precision(old_prec)Note that the input function above is a string in PARI syntax.
- sage.calculus.calculus.nintegrate(ex, x, a, b, desired_relative_error='1e-8', maximum_num_subintervals=200)[source]¶
alias of
nintegral().
- sage.calculus.calculus.symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=Maxima)[source]¶
Given a string representation of a Maxima expression, parse it and return the corresponding Sage symbolic expression.
INPUT:
x– stringequals_sub– boolean (default:False); ifTrue, replace ‘=’ by ‘==’ in selfmaxima– (default: the calculus package’s copy of Maxima) the Maxima interpreter to use
EXAMPLES:
sage: # needs sage.libs.maxima sage: from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms sage: sefms('x^%e + %e^%pi + %i + sin(0)') x^e + e^pi + I sage: f = function('f')(x) sage: sefms('?%at(f(x),x=2)#1') f(2) != 1 sage: a = sage.calculus.calculus.maxima("x#0"); a x # 0 sage: a.sage() x != 0
>>> from sage.all import * >>> # needs sage.libs.maxima >>> from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms >>> sefms('x^%e + %e^%pi + %i + sin(0)') x^e + e^pi + I >>> f = function('f')(x) >>> sefms('?%at(f(x),x=2)#1') f(2) != 1 >>> a = sage.calculus.calculus.maxima("x#0"); a x # 0 >>> a.sage() x != 0
# needs sage.libs.maxima from sage.calculus.calculus import symbolic_expression_from_maxima_string as sefms sefms('x^%e + %e^%pi + %i + sin(0)') f = function('f')(x) sefms('?%at(f(x),x=2)#1') a = sage.calculus.calculus.maxima("x#0"); a a.sage()
- sage.calculus.calculus.symbolic_expression_from_string(s, syms, accept_sequence=None, parser=False)[source]¶
Given a string, (attempt to) parse it and return the corresponding Sage symbolic expression. Normally used to return Maxima output to the user.
INPUT:
s– stringsyms– (default:{}) dictionary of strings to be regarded as symbols or functions; keys are pairs (string, number of arguments)accept_sequence– boolean (default:False); controls whether to allow a (possibly nested) set of lists and tuples as inputparser– (default:SR_parser) parser for internal use
EXAMPLES:
sage: from sage.calculus.calculus import symbolic_expression_from_string sage: y = var('y') sage: symbolic_expression_from_string('[sin(0)*x^2,3*spam+e^pi]', ....: syms={('spam',0): y}, accept_sequence=True) [0, 3*y + e^pi]
>>> from sage.all import * >>> from sage.calculus.calculus import symbolic_expression_from_string >>> y = var('y') >>> symbolic_expression_from_string('[sin(0)*x^2,3*spam+e^pi]', ... syms={('spam',Integer(0)): y}, accept_sequence=True) [0, 3*y + e^pi]
from sage.calculus.calculus import symbolic_expression_from_string y = var('y') symbolic_expression_from_string('[sin(0)*x^2,3*spam+e^pi]', syms={('spam',0): y}, accept_sequence=True)
- sage.calculus.calculus.symbolic_product(expression, v, a, b, algorithm='maxima', hold=False)[source]¶
Return the symbolic product \(\prod_{v = a}^b expression\) with respect to the variable \(v\) with endpoints \(a\) and \(b\).
INPUT:
expression– a symbolic expressionv– a variable or variable namea– lower endpoint of the productb– upper endpoint of the prductalgorithm– (default:'maxima') one of'maxima'– use Maxima (the default)'giac'– use Giac (optional)'sympy'– use SymPy'mathematica'– (optional) use Mathematica
hold– boolean (default:False); ifTrue, don’t evaluate
EXAMPLES:
sage: # needs sage.libs.maxima sage: i, k, n = var('i,k,n') sage: from sage.calculus.calculus import symbolic_product sage: symbolic_product(k, k, 1, n) factorial(n) sage: symbolic_product(x + i*(i+1)/2, i, 1, 4) x^4 + 20*x^3 + 127*x^2 + 288*x + 180 sage: symbolic_product(i^2, i, 1, 7) 25401600 sage: f = function('f') sage: symbolic_product(f(i), i, 1, 7) f(7)*f(6)*f(5)*f(4)*f(3)*f(2)*f(1) sage: symbolic_product(f(i), i, 1, n) product(f(i), i, 1, n) sage: assume(k>0) sage: symbolic_product(integrate (x^k, x, 0, 1), k, 1, n) 1/factorial(n + 1) sage: symbolic_product(f(i), i, 1, n).log().log_expand() sum(log(f(i)), i, 1, n)
>>> from sage.all import * >>> # needs sage.libs.maxima >>> i, k, n = var('i,k,n') >>> from sage.calculus.calculus import symbolic_product >>> symbolic_product(k, k, Integer(1), n) factorial(n) >>> symbolic_product(x + i*(i+Integer(1))/Integer(2), i, Integer(1), Integer(4)) x^4 + 20*x^3 + 127*x^2 + 288*x + 180 >>> symbolic_product(i**Integer(2), i, Integer(1), Integer(7)) 25401600 >>> f = function('f') >>> symbolic_product(f(i), i, Integer(1), Integer(7)) f(7)*f(6)*f(5)*f(4)*f(3)*f(2)*f(1) >>> symbolic_product(f(i), i, Integer(1), n) product(f(i), i, 1, n) >>> assume(k>Integer(0)) >>> symbolic_product(integrate (x**k, x, Integer(0), Integer(1)), k, Integer(1), n) 1/factorial(n + 1) >>> symbolic_product(f(i), i, Integer(1), n).log().log_expand() sum(log(f(i)), i, 1, n)
# needs sage.libs.maxima i, k, n = var('i,k,n') from sage.calculus.calculus import symbolic_product symbolic_product(k, k, 1, n) symbolic_product(x + i*(i+1)/2, i, 1, 4) symbolic_product(i^2, i, 1, 7) f = function('f') symbolic_product(f(i), i, 1, 7) symbolic_product(f(i), i, 1, n) assume(k>0) symbolic_product(integrate (x^k, x, 0, 1), k, 1, n) symbolic_product(f(i), i, 1, n).log().log_expand()
- sage.calculus.calculus.symbolic_sum(expression, v, a, b, algorithm='maxima', hold=False)[source]¶
Return the symbolic sum \(\sum_{v = a}^b expression\) with respect to the variable \(v\) with endpoints \(a\) and \(b\).
INPUT:
expression– a symbolic expressionv– a variable or variable namea– lower endpoint of the sumb– upper endpoint of the sumalgorithm– (default:'maxima') one of'maxima'– use Maxima (the default)'maple'– (optional) use Maple'mathematica'– (optional) use Mathematica'giac'– (optional) use Giac'sympy'– use SymPy
hold– boolean (default:False); ifTrue, don’t evaluate
EXAMPLES:
sage: k, n = var('k,n') sage: from sage.calculus.calculus import symbolic_sum sage: symbolic_sum(k, k, 1, n).factor() # needs sage.libs.maxima 1/2*(n + 1)*n
>>> from sage.all import * >>> k, n = var('k,n') >>> from sage.calculus.calculus import symbolic_sum >>> symbolic_sum(k, k, Integer(1), n).factor() # needs sage.libs.maxima 1/2*(n + 1)*n
k, n = var('k,n') from sage.calculus.calculus import symbolic_sum symbolic_sum(k, k, 1, n).factor() # needs sage.libs.maximasage: symbolic_sum(1/k^4, k, 1, oo) # needs sage.libs.maxima 1/90*pi^4
>>> from sage.all import * >>> symbolic_sum(Integer(1)/k**Integer(4), k, Integer(1), oo) # needs sage.libs.maxima 1/90*pi^4
symbolic_sum(1/k^4, k, 1, oo) # needs sage.libs.maxima
sage: symbolic_sum(1/k^5, k, 1, oo) # needs sage.libs.maxima zeta(5)
>>> from sage.all import * >>> symbolic_sum(Integer(1)/k**Integer(5), k, Integer(1), oo) # needs sage.libs.maxima zeta(5)
symbolic_sum(1/k^5, k, 1, oo) # needs sage.libs.maxima
A well known binomial identity:
sage: symbolic_sum(binomial(n,k), k, 0, n) # needs sage.libs.maxima 2^n
>>> from sage.all import * >>> symbolic_sum(binomial(n,k), k, Integer(0), n) # needs sage.libs.maxima 2^n
symbolic_sum(binomial(n,k), k, 0, n) # needs sage.libs.maxima
And some truncations thereof:
sage: # needs sage.libs.maxima sage: assume(n>1) sage: symbolic_sum(binomial(n,k), k, 1, n) 2^n - 1 sage: symbolic_sum(binomial(n,k), k, 2, n) 2^n - n - 1 sage: symbolic_sum(binomial(n,k), k, 0, n-1) 2^n - 1 sage: symbolic_sum(binomial(n,k), k, 1, n-1) 2^n - 2
>>> from sage.all import * >>> # needs sage.libs.maxima >>> assume(n>Integer(1)) >>> symbolic_sum(binomial(n,k), k, Integer(1), n) 2^n - 1 >>> symbolic_sum(binomial(n,k), k, Integer(2), n) 2^n - n - 1 >>> symbolic_sum(binomial(n,k), k, Integer(0), n-Integer(1)) 2^n - 1 >>> symbolic_sum(binomial(n,k), k, Integer(1), n-Integer(1)) 2^n - 2
# needs sage.libs.maxima assume(n>1) symbolic_sum(binomial(n,k), k, 1, n) symbolic_sum(binomial(n,k), k, 2, n) symbolic_sum(binomial(n,k), k, 0, n-1) symbolic_sum(binomial(n,k), k, 1, n-1)
The binomial theorem:
sage: x, y = var('x, y') sage: symbolic_sum(binomial(n,k) * x^k * y^(n-k), k, 0, n) # needs sage.libs.maxima (x + y)^n
>>> from sage.all import * >>> x, y = var('x, y') >>> symbolic_sum(binomial(n,k) * x**k * y**(n-k), k, Integer(0), n) # needs sage.libs.maxima (x + y)^n
x, y = var('x, y') symbolic_sum(binomial(n,k) * x^k * y^(n-k), k, 0, n) # needs sage.libs.maximasage: symbolic_sum(k * binomial(n, k), k, 1, n) # needs sage.libs.maxima 2^(n - 1)*n
>>> from sage.all import * >>> symbolic_sum(k * binomial(n, k), k, Integer(1), n) # needs sage.libs.maxima 2^(n - 1)*n
symbolic_sum(k * binomial(n, k), k, 1, n) # needs sage.libs.maxima
sage: symbolic_sum((-1)^k*binomial(n,k), k, 0, n) # needs sage.libs.maxima 0
>>> from sage.all import * >>> symbolic_sum((-Integer(1))**k*binomial(n,k), k, Integer(0), n) # needs sage.libs.maxima 0
symbolic_sum((-1)^k*binomial(n,k), k, 0, n) # needs sage.libs.maxima
sage: symbolic_sum(2^(-k)/(k*(k+1)), k, 1, oo) # needs sage.libs.maxima -log(2) + 1
>>> from sage.all import * >>> symbolic_sum(Integer(2)**(-k)/(k*(k+Integer(1))), k, Integer(1), oo) # needs sage.libs.maxima -log(2) + 1
symbolic_sum(2^(-k)/(k*(k+1)), k, 1, oo) # needs sage.libs.maxima
Summing a hypergeometric term:
sage: symbolic_sum(binomial(n, k) * factorial(k) / factorial(n+1+k), k, 0, n) # needs sage.libs.maxima 1/2*sqrt(pi)/factorial(n + 1/2)
>>> from sage.all import * >>> symbolic_sum(binomial(n, k) * factorial(k) / factorial(n+Integer(1)+k), k, Integer(0), n) # needs sage.libs.maxima 1/2*sqrt(pi)/factorial(n + 1/2)
symbolic_sum(binomial(n, k) * factorial(k) / factorial(n+1+k), k, 0, n) # needs sage.libs.maxima
We check a well known identity:
sage: bool(symbolic_sum(k^3, k, 1, n) == symbolic_sum(k, k, 1, n)^2) # needs sage.libs.maxima True
>>> from sage.all import * >>> bool(symbolic_sum(k**Integer(3), k, Integer(1), n) == symbolic_sum(k, k, Integer(1), n)**Integer(2)) # needs sage.libs.maxima True
bool(symbolic_sum(k^3, k, 1, n) == symbolic_sum(k, k, 1, n)^2) # needs sage.libs.maxima
A geometric sum:
sage: a, q = var('a, q') sage: symbolic_sum(a*q^k, k, 0, n) # needs sage.libs.maxima (a*q^(n + 1) - a)/(q - 1)
>>> from sage.all import * >>> a, q = var('a, q') >>> symbolic_sum(a*q**k, k, Integer(0), n) # needs sage.libs.maxima (a*q^(n + 1) - a)/(q - 1)
a, q = var('a, q') symbolic_sum(a*q^k, k, 0, n) # needs sage.libs.maximaFor the geometric series, we will have to assume the right values for the sum to converge:
sage: assume(abs(q) < 1) sage: symbolic_sum(a*q^k, k, 0, oo) # needs sage.libs.maxima -a/(q - 1)
>>> from sage.all import * >>> assume(abs(q) < Integer(1)) >>> symbolic_sum(a*q**k, k, Integer(0), oo) # needs sage.libs.maxima -a/(q - 1)
assume(abs(q) < 1) symbolic_sum(a*q^k, k, 0, oo) # needs sage.libs.maxima
A divergent geometric series. Don’t forget to forget your assumptions:
sage: forget() sage: assume(q > 1) sage: symbolic_sum(a*q^k, k, 0, oo) # needs sage.libs.maxima Traceback (most recent call last): ... ValueError: Sum is divergent. sage: forget() sage: assumptions() # check the assumptions were really forgotten []
>>> from sage.all import * >>> forget() >>> assume(q > Integer(1)) >>> symbolic_sum(a*q**k, k, Integer(0), oo) # needs sage.libs.maxima Traceback (most recent call last): ... ValueError: Sum is divergent. >>> forget() >>> assumptions() # check the assumptions were really forgotten []
forget() assume(q > 1) symbolic_sum(a*q^k, k, 0, oo) # needs sage.libs.maxima forget() assumptions() # check the assumptions were really forgotten
A summation performed by Mathematica:
sage: symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='mathematica') # optional - mathematica pi*coth(pi)
>>> from sage.all import * >>> symbolic_sum(Integer(1)/(Integer(1)+k**Integer(2)), k, -oo, oo, algorithm='mathematica') # optional - mathematica pi*coth(pi)
symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='mathematica') # optional - mathematica
An example of this summation with Giac:
sage: # needs giac sage: symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='giac').factor() pi*(e^(2*pi) + 1)/((e^pi + 1)*(e^pi - 1))
>>> from sage.all import * >>> # needs giac >>> symbolic_sum(Integer(1)/(Integer(1)+k**Integer(2)), k, -oo, oo, algorithm='giac').factor() pi*(e^(2*pi) + 1)/((e^pi + 1)*(e^pi - 1))
# needs giac symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='giac').factor()
The same summation is solved by SymPy:
sage: symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='sympy') pi/tanh(pi)
>>> from sage.all import * >>> symbolic_sum(Integer(1)/(Integer(1)+k**Integer(2)), k, -oo, oo, algorithm='sympy') pi/tanh(pi)
symbolic_sum(1/(1+k^2), k, -oo, oo, algorithm='sympy')
SymPy and Maxima 5.39.0 can do the following (see upstream Issue #22005):
sage: sum(1/((2*n+1)^2-4)^2, n, 0, Infinity, algorithm='sympy') 1/64*pi^2 sage: sum(1/((2*n+1)^2-4)^2, n, 0, Infinity) # needs sage.libs.maxima 1/64*pi^2
>>> from sage.all import * >>> sum(Integer(1)/((Integer(2)*n+Integer(1))**Integer(2)-Integer(4))**Integer(2), n, Integer(0), Infinity, algorithm='sympy') 1/64*pi^2 >>> sum(Integer(1)/((Integer(2)*n+Integer(1))**Integer(2)-Integer(4))**Integer(2), n, Integer(0), Infinity) # needs sage.libs.maxima 1/64*pi^2
sum(1/((2*n+1)^2-4)^2, n, 0, Infinity, algorithm='sympy') sum(1/((2*n+1)^2-4)^2, n, 0, Infinity) # needs sage.libs.maxima
Use Maple as a backend for summation:
sage: symbolic_sum(binomial(n,k)*x^k, k, 0, n, algorithm='maple') # optional - maple (x + 1)^n
>>> from sage.all import * >>> symbolic_sum(binomial(n,k)*x**k, k, Integer(0), n, algorithm='maple') # optional - maple (x + 1)^n
symbolic_sum(binomial(n,k)*x^k, k, 0, n, algorithm='maple') # optional - maple
If you don’t want to evaluate immediately give the
holdkeyword:sage: s = sum(n, n, 1, k, hold=True); s sum(n, n, 1, k) sage: s.unhold() # needs sage.libs.maxima 1/2*k^2 + 1/2*k sage: s.subs(k == 10) sum(n, n, 1, 10) sage: s.subs(k == 10).unhold() # needs sage.libs.maxima 55 sage: s.subs(k == 10).n() # needs sage.libs.maxima 55.0000000000000
>>> from sage.all import * >>> s = sum(n, n, Integer(1), k, hold=True); s sum(n, n, 1, k) >>> s.unhold() # needs sage.libs.maxima 1/2*k^2 + 1/2*k >>> s.subs(k == Integer(10)) sum(n, n, 1, 10) >>> s.subs(k == Integer(10)).unhold() # needs sage.libs.maxima 55 >>> s.subs(k == Integer(10)).n() # needs sage.libs.maxima 55.0000000000000
s = sum(n, n, 1, k, hold=True); s s.unhold() # needs sage.libs.maxima s.subs(k == 10) s.subs(k == 10).unhold() # needs sage.libs.maxima s.subs(k == 10).n() # needs sage.libs.maxima
Note
Sage can currently only understand a subset of the output of Maxima, Maple and Mathematica, so even if the chosen backend can perform the summation the result might not be convertible into a Sage expression.