Symbolic Expressions
RELATIONAL EXPRESSIONS:
We create a relational expression:
sage: x = var('x')
sage: eqn = (x-1)^2 <= x^2 - 2*x + 3
sage: eqn.subs(x == 5)
16 <= 18
Notice that squaring the relation squares both sides.
sage: eqn^2
(x - 1)^4 <= (x^2 - 2*x + 3)^2
sage: eqn.expand()
x^2 - 2*x + 1 <= x^2 - 2*x + 3
The can transform a true relational into a false one:
sage: eqn = SR(-5) < SR(-3); eqn
-5 < -3
sage: bool(eqn)
True
sage: eqn^2
25 < 9
sage: bool(eqn^2)
False
We can do arithmetic with relationals:
sage: e = x+1 <= x-2
sage: e + 2
x + 3 <= x
sage: e - 1
x <= x - 3
sage: e*(-1)
-x - 1 <= -x + 2
sage: (-2)*e
-2*x - 2 <= -2*x + 4
sage: e*5
5*x + 5 <= 5*x - 10
sage: e/5
1/5*x + 1/5 <= 1/5*x - 2/5
sage: 5/e
5/(x + 1) <= 5/(x - 2)
sage: e/(-2)
-1/2*x - 1/2 <= -1/2*x + 1
sage: -2/e
-2/(x + 1) <= -2/(x - 2)
We can even add together two relations, so long as the operators are the same:
sage: (x^3 + x <= x - 17) + (-x <= x - 10)
x^3 <= 2*x - 27
Here they are not:
sage: (x^3 + x <= x - 17) + (-x >= x - 10)
Traceback (most recent call last):
...
TypeError: incompatible relations
ARBITRARY SAGE ELEMENTS:
You can work symbolically with any Sage data type. This can lead to nonsense if the data type is strange, e.g., an element of a finite field (at present).
We mix Singular variables with symbolic variables:
sage: R.<u,v> = QQ[]
sage: var('a,b,c')
(a, b, c)
sage: expand((u + v + a + b + c)^2)
a^2 + 2*a*b + b^2 + 2*a*c + 2*b*c + c^2 + 2*a*u + 2*b*u + 2*c*u + u^2 + 2*a*v + 2*b*v + 2*c*v + 2*u*v + v^2
TESTS:
Test Jacobian on Pynac expressions. (trac ticket #5546)
sage: var('x,y')
(x, y)
sage: f = x + y
sage: jacobian(f, [x,y])
[1 1]
Test if matrices work (trac ticket #5546)
sage: var('x,y,z')
(x, y, z)
sage: M = matrix(2,2,[x,y,z,x])
sage: v = vector([x,y])
sage: M * v
(x^2 + y^2, x*y + x*z)
sage: v*M
(x^2 + y*z, 2*x*y)
Test if comparison bugs from trac ticket #6256 are fixed:
sage: t = exp(sqrt(x)); u = 1/t
sage: t*u
1
sage: t + u
e^(-sqrt(x)) + e^sqrt(x)
sage: t
e^sqrt(x)
Test if trac ticket #9947 is fixed:
sage: real_part(1+2*(sqrt(2)+1)*(sqrt(2)-1))
3
sage: a=(sqrt(4*(sqrt(3) - 5)*(sqrt(3) + 5) + 48) + 4*sqrt(3))/ (sqrt(3) + 5)
sage: a.real_part()
4*sqrt(3)/(sqrt(3) + 5)
sage: a.imag_part()
sqrt(abs(4*(sqrt(3) + 5)*(sqrt(3) - 5) + 48))/(sqrt(3) + 5)
Bases: sage.structure.element.CommutativeRingElement
Nearly all expressions are created by calling new_Expression_from_*, but we need to make sure this at least does not leave self._gobj uninitialized and segfault.
TESTS:
sage: sage.symbolic.expression.Expression(SR)
0
sage: sage.symbolic.expression.Expression(SR, 5)
5
We test subclassing Expression:
sage: from sage.symbolic.expression import Expression
sage: class exp_sub(Expression): pass
sage: f = function('f')
sage: t = f(x)
sage: u = exp_sub(SR, t)
sage: u.operator()
f
Return a numerical approximation this symbolic expression as either a real or complex number with at least the requested number of bits or digits of precision.
EXAMPLES:
sage: sin(x).subs(x=5).n()
-0.958924274663138
sage: sin(x).subs(x=5).n(100)
-0.95892427466313846889315440616
sage: sin(x).subs(x=5).n(digits=50)
-0.95892427466313846889315440615599397335246154396460
sage: zeta(x).subs(x=2).numerical_approx(digits=50)
1.6449340668482264364724151666460251892189499012068
sage: cos(3).numerical_approx(200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3),200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3), digits=10)
-0.9899924966
sage: (i + 1).numerical_approx(32)
1.00000000 + 1.00000000*I
sage: (pi + e + sqrt(2)).numerical_approx(100)
7.2740880444219335226246195788
TESTS:
We test the evaluation of different infinities available in Pynac:
sage: t = x - oo; t
-Infinity
sage: t.n()
-infinity
sage: t = x + oo; t
+Infinity
sage: t.n()
+infinity
sage: t = x - unsigned_infinity; t
Infinity
sage: t.n()
Traceback (most recent call last):
...
ValueError: can only convert signed infinity to RR
Some expressions cannot be evaluated numerically:
sage: n(sin(x))
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
sage: a = var('a')
sage: (x^2 + 2*x + 2).subs(x=a).n()
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
Make sure we’ve rounded up log(10,2) enough to guarantee sufficient precision (trac ticket #10164):
sage: ks = 4*10**5, 10**6
sage: all(len(str(e.n(digits=k)))-1 >= k for k in ks)
True
Return the order of the expression, as in big oh notation.
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: n = var('n')
sage: t = (17*n^3).Order(); t
Order(n^3)
sage: t.derivative(n)
Order(n^2)
To prevent automatic evaluation use the hold argument:
sage: (17*n^3).Order(hold=True)
Order(17*n^3)
Return the absolute value of this expression.
EXAMPLES:
sage: var('x, y')
(x, y)
sage: (x+y).abs()
abs(x + y)
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(-5).abs(hold=True)
abs(-5)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(-5).abs(hold=True); a.simplify()
5
TESTS:
From trac ticket #7557:
sage: var('y', domain='real')
y
sage: abs(exp(1.1*y*I)).simplify()
1
sage: var('y', domain='complex') # reset the domain for other tests
y
Return the sum of the current expression and the given arguments.
To prevent automatic evaluation use the hold argument.
EXAMPLES:
sage: x.add(x)
2*x
sage: x.add(x, hold=True)
x + x
sage: x.add(x, (2+x), hold=True)
(x + 2) + x + x
sage: x.add(x, (2+x), x, hold=True)
(x + 2) + x + x + x
sage: x.add(x, (2+x), x, 2*x, hold=True)
(x + 2) + 2*x + x + x + x
To then evaluate again, we currently must use Maxima via simplify():
sage: a = x.add(x, hold=True); a.simplify()
2*x
Return a relation obtained by adding x to both sides of this relation.
EXAMPLES:
sage: var('x y z')
(x, y, z)
sage: eqn = x^2 + y^2 + z^2 <= 1
sage: eqn.add_to_both_sides(-z^2)
x^2 + y^2 <= -z^2 + 1
sage: eqn.add_to_both_sides(I)
x^2 + y^2 + z^2 + I <= (I + 1)
Return the arc cosine of self.
EXAMPLES:
sage: x.arccos()
arccos(x)
sage: SR(1).arccos()
0
sage: SR(1/2).arccos()
1/3*pi
sage: SR(0.4).arccos()
1.15927948072741
sage: plot(lambda x: SR(x).arccos(), -1,1)
Graphics object consisting of 1 graphics primitive
To prevent automatic evaluation use the hold argument:
sage: SR(1).arccos(hold=True)
arccos(1)
This also works using functional notation:
sage: arccos(1,hold=True)
arccos(1)
sage: arccos(1)
0
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(1).arccos(hold=True); a.simplify()
0
TESTS:
sage: SR(oo).arccos()
Traceback (most recent call last):
...
RuntimeError: arccos_eval(): arccos(infinity) encountered
sage: SR(-oo).arccos()
Traceback (most recent call last):
...
RuntimeError: arccos_eval(): arccos(infinity) encountered
sage: SR(unsigned_infinity).arccos()
Infinity
Return the inverse hyperbolic cosine of self.
EXAMPLES:
sage: x.arccosh()
arccosh(x)
sage: SR(0).arccosh()
1/2*I*pi
sage: SR(1/2).arccosh()
arccosh(1/2)
sage: SR(CDF(1/2)).arccosh() # rel tol 1e-15
1.0471975511965976*I
sage: maxima('acosh(0.5)')
1.04719755119659...*%i
To prevent automatic evaluation use the hold argument:
sage: SR(-1).arccosh()
I*pi
sage: SR(-1).arccosh(hold=True)
arccosh(-1)
This also works using functional notation:
sage: arccosh(-1,hold=True)
arccosh(-1)
sage: arccosh(-1)
I*pi
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(-1).arccosh(hold=True); a.simplify()
I*pi
TESTS:
sage: SR(oo).arccosh()
+Infinity
sage: SR(-oo).arccosh()
+Infinity
sage: SR(unsigned_infinity).arccosh()
+Infinity
Return the arcsin of x, i.e., the number y between -pi and pi such that sin(y) == x.
EXAMPLES:
sage: x.arcsin()
arcsin(x)
sage: SR(0.5).arcsin()
0.523598775598299
sage: SR(0.999).arcsin()
1.52607123962616
sage: SR(1/3).arcsin()
arcsin(1/3)
sage: SR(-1/3).arcsin()
-arcsin(1/3)
To prevent automatic evaluation use the hold argument:
sage: SR(0).arcsin()
0
sage: SR(0).arcsin(hold=True)
arcsin(0)
This also works using functional notation:
sage: arcsin(0,hold=True)
arcsin(0)
sage: arcsin(0)
0
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(0).arcsin(hold=True); a.simplify()
0
TESTS:
sage: SR(oo).arcsin()
Traceback (most recent call last):
...
RuntimeError: arcsin_eval(): arcsin(infinity) encountered
sage: SR(-oo).arcsin()
Traceback (most recent call last):
...
RuntimeError: arcsin_eval(): arcsin(infinity) encountered
sage: SR(unsigned_infinity).arcsin()
Infinity
Return the inverse hyperbolic sine of self.
EXAMPLES:
sage: x.arcsinh()
arcsinh(x)
sage: SR(0).arcsinh()
0
sage: SR(1).arcsinh()
arcsinh(1)
sage: SR(1.0).arcsinh()
0.881373587019543
sage: maxima('asinh(2.0)')
1.4436354751788...
Sage automatically applies certain identities:
sage: SR(3/2).arcsinh().cosh()
1/2*sqrt(13)
To prevent automatic evaluation use the hold argument:
sage: SR(-2).arcsinh()
-arcsinh(2)
sage: SR(-2).arcsinh(hold=True)
arcsinh(-2)
This also works using functional notation:
sage: arcsinh(-2,hold=True)
arcsinh(-2)
sage: arcsinh(-2)
-arcsinh(2)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(-2).arcsinh(hold=True); a.simplify()
-arcsinh(2)
TESTS:
sage: SR(oo).arcsinh()
+Infinity
sage: SR(-oo).arcsinh()
-Infinity
sage: SR(unsigned_infinity).arcsinh()
Infinity
Return the arc tangent of self.
EXAMPLES:
sage: x = var('x')
sage: x.arctan()
arctan(x)
sage: SR(1).arctan()
1/4*pi
sage: SR(1/2).arctan()
arctan(1/2)
sage: SR(0.5).arctan()
0.463647609000806
sage: plot(lambda x: SR(x).arctan(), -20,20)
Graphics object consisting of 1 graphics primitive
To prevent automatic evaluation use the hold argument:
sage: SR(1).arctan(hold=True)
arctan(1)
This also works using functional notation:
sage: arctan(1,hold=True)
arctan(1)
sage: arctan(1)
1/4*pi
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(1).arctan(hold=True); a.simplify()
1/4*pi
TESTS:
sage: SR(oo).arctan()
1/2*pi
sage: SR(-oo).arctan()
-1/2*pi
sage: SR(unsigned_infinity).arctan()
Traceback (most recent call last):
...
RuntimeError: arctan_eval(): arctan(unsigned_infinity) encountered
Return the inverse of the 2-variable tan function on self and x.
EXAMPLES:
sage: var('x,y')
(x, y)
sage: x.arctan2(y)
arctan2(x, y)
sage: SR(1/2).arctan2(1/2)
1/4*pi
sage: maxima.eval('atan2(1/2,1/2)')
'%pi/4'
sage: SR(-0.7).arctan2(SR(-0.6))
-2.27942259892257
To prevent automatic evaluation use the hold argument:
sage: SR(1/2).arctan2(1/2, hold=True)
arctan2(1/2, 1/2)
This also works using functional notation:
sage: arctan2(1,2,hold=True)
arctan2(1, 2)
sage: arctan2(1,2)
arctan(1/2)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(1/2).arctan2(1/2, hold=True); a.simplify()
1/4*pi
TESTS:
We compare a bunch of different evaluation points between Sage and Maxima:
sage: float(SR(0.7).arctan2(0.6))
0.8621700546672264
sage: maxima('atan2(0.7,0.6)')
0.8621700546672264
sage: float(SR(0.7).arctan2(-0.6))
2.279422598922567
sage: maxima('atan2(0.7,-0.6)')
2.279422598922567
sage: float(SR(-0.7).arctan2(0.6))
-0.8621700546672264
sage: maxima('atan2(-0.7,0.6)')
-0.8621700546672264
sage: float(SR(-0.7).arctan2(-0.6))
-2.279422598922567
sage: maxima('atan2(-0.7,-0.6)')
-2.279422598922567
sage: float(SR(0).arctan2(-0.6))
3.141592653589793
sage: maxima('atan2(0,-0.6)')
3.141592653589793
sage: float(SR(0).arctan2(0.6))
0.0
sage: maxima('atan2(0,0.6)')
0.0
sage: SR(0).arctan2(0) # see trac ticket #11423
Traceback (most recent call last):
...
RuntimeError: arctan2_eval(): arctan2(0,0) encountered
sage: SR(I).arctan2(1)
arctan2(I, 1)
sage: SR(CDF(0,1)).arctan2(1)
arctan2(1.0*I, 1)
sage: SR(1).arctan2(CDF(0,1))
arctan2(1, 1.0*I)
sage: arctan2(0,oo)
0
sage: SR(oo).arctan2(oo)
1/4*pi
sage: SR(oo).arctan2(0)
1/2*pi
sage: SR(-oo).arctan2(0)
-1/2*pi
sage: SR(-oo).arctan2(-2)
pi
sage: SR(unsigned_infinity).arctan2(2)
Traceback (most recent call last):
...
RuntimeError: arctan2_eval(): arctan2(x, unsigned_infinity) encountered
sage: SR(2).arctan2(oo)
1/2*pi
sage: SR(2).arctan2(-oo)
-1/2*pi
sage: SR(2).arctan2(SR(unsigned_infinity))
Traceback (most recent call last):
...
RuntimeError: arctan2_eval(): arctan2(unsigned_infinity, x) encountered
Return the inverse hyperbolic tangent of self.
EXAMPLES:
sage: x.arctanh()
arctanh(x)
sage: SR(0).arctanh()
0
sage: SR(1/2).arctanh()
arctanh(1/2)
sage: SR(0.5).arctanh()
0.549306144334055
sage: SR(0.5).arctanh().tanh()
0.500000000000000
sage: maxima('atanh(0.5)') # abs tol 2e-16
0.5493061443340548
To prevent automatic evaluation use the hold argument:
sage: SR(-1/2).arctanh()
-arctanh(1/2)
sage: SR(-1/2).arctanh(hold=True)
arctanh(-1/2)
This also works using functional notation:
sage: arctanh(-1/2,hold=True)
arctanh(-1/2)
sage: arctanh(-1/2)
-arctanh(1/2)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(-1/2).arctanh(hold=True); a.simplify()
-arctanh(1/2)
TESTS:
sage: SR(1).arctanh()
+Infinity
sage: SR(-1).arctanh()
-Infinity
sage: SR(oo).arctanh()
-1/2*I*pi
sage: SR(-oo).arctanh()
1/2*I*pi
sage: SR(unsigned_infinity).arctanh()
Traceback (most recent call last):
...
RuntimeError: arctanh_eval(): arctanh(unsigned_infinity) encountered
EXAMPLES:
sage: x,y = var('x,y')
sage: f = x + y
sage: f.arguments()
(x, y)
sage: g = f.function(x)
sage: g.arguments()
(x,)
EXAMPLES:
sage: x,y = var('x,y')
sage: f = x + y
sage: f.arguments()
(x, y)
sage: g = f.function(x)
sage: g.arguments()
(x,)
Assume that this equation holds. This is relevant for symbolic integration, among other things.
EXAMPLES: We call the assume method to assume that :
sage: (x > 2).assume()
Bool returns True below if the inequality is definitely known to be True.
sage: bool(x > 0)
True
sage: bool(x < 0)
False
This may or may not be True, so bool returns False:
sage: bool(x > 3)
False
If you make inconsistent or meaningless assumptions, Sage will let you know:
sage: forget()
sage: assume(x<0)
sage: assume(x>0)
Traceback (most recent call last):
...
ValueError: Assumption is inconsistent
sage: assumptions()
[x < 0]
sage: forget()
TESTS:
sage: v,c = var('v,c')
sage: assume(c != 0)
sage: integral((1+v^2/c^2)^3/(1-v^2/c^2)^(3/2),v)
83/8*v/sqrt(-v^2/c^2 + 1) - 17/8*v^3/(c^2*sqrt(-v^2/c^2 + 1)) - 1/4*v^5/(c^4*sqrt(-v^2/c^2 + 1)) - 75/8*arcsin(v/(c^2*sqrt(c^(-2))))/sqrt(c^(-2))
sage: forget()
Return binomial coefficient “self choose k”.
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: var('x, y')
(x, y)
sage: SR(5).binomial(SR(3))
10
sage: x.binomial(SR(3))
1/6*(x - 1)*(x - 2)*x
sage: x.binomial(y)
binomial(x, y)
To prevent automatic evaluation use the hold argument:
sage: x.binomial(3, hold=True)
binomial(x, 3)
sage: SR(5).binomial(3, hold=True)
binomial(5, 3)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(5).binomial(3, hold=True); a.simplify()
10
The hold parameter is also supported in functional notation:
sage: binomial(5,3, hold=True)
binomial(5, 3)
TESTS:
Check if we handle zero correctly (trac ticket #8561):
sage: x.binomial(0)
1
sage: SR(0).binomial(0)
1
Return the coefficient of in this symbolic expression.
INPUT:
OUTPUT:
A symbolic expression. The coefficient of .
Sometimes it may be necessary to expand or factor first, since this is not done automatically.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.collect(x)
x^3*sin(x*y) + (a + y + 1/y)*x + 2*sin(x*y)/x + 100
sage: f.coefficient(x,0)
100
sage: f.coefficient(x,-1)
2*sin(x*y)
sage: f.coefficient(x,1)
a + y + 1/y
sage: f.coefficient(x,2)
0
sage: f.coefficient(x,3)
sin(x*y)
sage: f.coefficient(x^3)
sin(x*y)
sage: f.coefficient(sin(x*y))
x^3 + 2/x
sage: f.collect(sin(x*y))
a*x + x*y + (x^3 + 2/x)*sin(x*y) + x/y + 100
sage: var('a, x, y, z')
(a, x, y, z)
sage: f = (a*sqrt(2))*x^2 + sin(y)*x^(1/2) + z^z
sage: f.coefficient(sin(y))
sqrt(x)
sage: f.coefficient(x^2)
sqrt(2)*a
sage: f.coefficient(x^(1/2))
sin(y)
sage: f.coefficient(1)
0
sage: f.coefficient(x, 0)
sqrt(x)*sin(y) + z^z
TESTS:
Check if trac ticket #9505 is fixed:
sage: var('x,y,z')
(x, y, z)
sage: f = x*y*z^2
sage: f.coeff(x*y)
z^2
sage: f.coeff(x*y, 2)
Traceback (most recent call last):
...
TypeError: n != 1 only allowed for s being a variable
Return the coefficient of in this symbolic expression.
INPUT:
OUTPUT:
A symbolic expression. The coefficient of .
Sometimes it may be necessary to expand or factor first, since this is not done automatically.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.collect(x)
x^3*sin(x*y) + (a + y + 1/y)*x + 2*sin(x*y)/x + 100
sage: f.coefficient(x,0)
100
sage: f.coefficient(x,-1)
2*sin(x*y)
sage: f.coefficient(x,1)
a + y + 1/y
sage: f.coefficient(x,2)
0
sage: f.coefficient(x,3)
sin(x*y)
sage: f.coefficient(x^3)
sin(x*y)
sage: f.coefficient(sin(x*y))
x^3 + 2/x
sage: f.collect(sin(x*y))
a*x + x*y + (x^3 + 2/x)*sin(x*y) + x/y + 100
sage: var('a, x, y, z')
(a, x, y, z)
sage: f = (a*sqrt(2))*x^2 + sin(y)*x^(1/2) + z^z
sage: f.coefficient(sin(y))
sqrt(x)
sage: f.coefficient(x^2)
sqrt(2)*a
sage: f.coefficient(x^(1/2))
sin(y)
sage: f.coefficient(1)
0
sage: f.coefficient(x, 0)
sqrt(x)*sin(y) + z^z
TESTS:
Check if trac ticket #9505 is fixed:
sage: var('x,y,z')
(x, y, z)
sage: f = x*y*z^2
sage: f.coeff(x*y)
z^2
sage: f.coeff(x*y, 2)
Traceback (most recent call last):
...
TypeError: n != 1 only allowed for s being a variable
Return the coefficients of this symbolic expression as a polynomial in x.
INPUT:
OUTPUT:
A list of pairs (expr, n), where expr is a symbolic expression and n is a power.
EXAMPLES:
sage: var('x, y, a')
(x, y, a)
sage: p = x^3 - (x-3)*(x^2+x) + 1
sage: p.coefficients()
[[1, 0], [3, 1], [2, 2]]
sage: p = expand((x-a*sqrt(2))^2 + x + 1); p
-2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1
sage: p.coefficients(a)
[[x^2 + x + 1, 0], [-2*sqrt(2)*x, 1], [2, 2]]
sage: p.coefficients(x)
[[2*a^2 + 1, 0], [-2*sqrt(2)*a + 1, 1], [1, 2]]
A polynomial with wacky exponents:
sage: p = (17/3*a)*x^(3/2) + x*y + 1/x + x^x
sage: p.coefficients(x)
[[1, -1], [x^x, 0], [y, 1], [17/3*a, 3/2]]
Return the coefficients of this symbolic expression as a polynomial in x.
INPUT:
OUTPUT:
A list of pairs (expr, n), where expr is a symbolic expression and n is a power.
EXAMPLES:
sage: var('x, y, a')
(x, y, a)
sage: p = x^3 - (x-3)*(x^2+x) + 1
sage: p.coefficients()
[[1, 0], [3, 1], [2, 2]]
sage: p = expand((x-a*sqrt(2))^2 + x + 1); p
-2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1
sage: p.coefficients(a)
[[x^2 + x + 1, 0], [-2*sqrt(2)*x, 1], [2, 2]]
sage: p.coefficients(x)
[[2*a^2 + 1, 0], [-2*sqrt(2)*a + 1, 1], [1, 2]]
A polynomial with wacky exponents:
sage: p = (17/3*a)*x^(3/2) + x*y + 1/x + x^x
sage: p.coefficients(x)
[[1, -1], [x^x, 0], [y, 1], [17/3*a, 3/2]]
Collect the coefficients of s into a group.
INPUT:
OUTPUT:
A new expression, equivalent to the original one, with the coefficients of s grouped.
Note
The expression is not expanded or factored before the grouping takes place. For best results, call expand() on the expression before collect().
EXAMPLES:
In the first term of ,
has a coefficient of
. In
the second term,
has a coefficient of
. Therefore, if
we collect those coefficients,
will have a coefficient of
:
sage: x,y,z = var('x,y,z')
sage: f = 4*x*y + x*z + 20*y^2 + 21*y*z + 4*z^2 + x^2*y^2*z^2
sage: f.collect(x)
x^2*y^2*z^2 + x*(4*y + z) + 20*y^2 + 21*y*z + 4*z^2
Here we do the same thing for and
; however, note that
we do not factor the
and
terms before
collecting coefficients:
sage: f.collect(y)
(x^2*z^2 + 20)*y^2 + (4*x + 21*z)*y + x*z + 4*z^2
sage: f.collect(z)
(x^2*y^2 + 4)*z^2 + 4*x*y + 20*y^2 + (x + 21*y)*z
Sometimes, we do have to call expand() on the expression first to achieve the desired result:
sage: f = (x + y)*(x - z)
sage: f.collect(x)
x^2 + x*y - x*z - y*z
sage: f.expand().collect(x)
x^2 + x*(y - z) - y*z
TESTS:
The output should be equivalent to the input:
sage: polynomials = QQ['x']
sage: f = SR(polynomials.random_element())
sage: g = f.collect(x)
sage: bool(f == g)
True
If s is not present in the given expression, the
expression should not be modified. The variable will not
be present in
below since
is a random polynomial of
maximum degree 10 in
and
:
sage: z = var('z')
sage: polynomials = QQ['x,y']
sage: f = SR(polynomials.random_element(10))
sage: g = f.collect(z)
sage: bool(str(f) == str(g))
True
Check if trac ticket #9046 is fixed:
sage: var('a b x y z')
(a, b, x, y, z)
sage: p = -a*x^3 - a*x*y^2 + 2*b*x^2*y + 2*y^3 + x^2*z + y^2*z + x^2 + y^2 + a*x
sage: p.collect(x)
-a*x^3 + (2*b*y + z + 1)*x^2 + 2*y^3 + y^2*z - (a*y^2 - a)*x + y^2
This function does not perform a full factorization but only looks for factors which are already explicitly present.
Polynomials can often be brought into a more compact form by collecting common factors from the terms of sums. This is accomplished by this function.
EXAMPLES:
sage: var('x')
x
sage: (x/(x^2 + x)).collect_common_factors()
1/(x + 1)
sage: var('a,b,c,x,y')
(a, b, c, x, y)
sage: (a*x+a*y).collect_common_factors()
a*(x + y)
sage: (a*x^2+2*a*x*y+a*y^2).collect_common_factors()
(x^2 + 2*x*y + y^2)*a
sage: (a*(b*(a+c)*x+b*((a+c)*x+(a+c)*y)*y)).collect_common_factors()
((x + y)*y + x)*(a + c)*a*b
Return a simplified version of this symbolic expression by combining all terms with the same denominator into a single term.
EXAMPLES:
sage: var('x, y, a, b, c')
(x, y, a, b, c)
sage: f = x*(x-1)/(x^2 - 7) + y^2/(x^2-7) + 1/(x+1) + b/a + c/a; f
(x - 1)*x/(x^2 - 7) + y^2/(x^2 - 7) + b/a + c/a + 1/(x + 1)
sage: f.combine()
((x - 1)*x + y^2)/(x^2 - 7) + (b + c)/a + 1/(x + 1)
Return the complex conjugate of this symbolic expression.
EXAMPLES:
sage: a = 1 + 2*I
sage: a.conjugate()
-2*I + 1
sage: a = sqrt(2) + 3^(1/3)*I; a
sqrt(2) + I*3^(1/3)
sage: a.conjugate()
sqrt(2) - I*3^(1/3)
sage: SR(CDF.0).conjugate()
-1.0*I
sage: x.conjugate()
conjugate(x)
sage: SR(RDF(1.5)).conjugate()
1.5
sage: SR(float(1.5)).conjugate()
1.5
sage: SR(I).conjugate()
-I
sage: ( 1+I + (2-3*I)*x).conjugate()
(3*I + 2)*conjugate(x) - I + 1
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(I).conjugate(hold=True)
conjugate(I)
This also works in functional notation:
sage: conjugate(I)
-I
sage: conjugate(I,hold=True)
conjugate(I)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(I).conjugate(hold=True); a.simplify()
-I
Return the content of this expression when considered as a polynomial in s.
See also unit(), primitive_part(), and unit_content_primitive().
INPUT:
OUTPUT:
The content part of a polynomial as a symbolic expression. It is defined as the gcd of the coefficients.
Warning
The expression is considered to be a univariate polynomial in s. The output is different from the content() method provided by multivariate polynomial rings in Sage.
EXAMPLES:
sage: (2*x+4).content(x)
2
sage: (2*x+1).content(x)
1
sage: (2*x+1/2).content(x)
1/2
sage: var('y')
y
sage: (2*x + 4*sin(y)).content(sin(y))
2
Return True if this relation is violated by the given variable assignment(s).
EXAMPLES:
sage: (x<3).contradicts(x==0)
False
sage: (x<3).contradicts(x==3)
True
sage: (x<=3).contradicts(x==3)
False
sage: y = var('y')
sage: (x<y).contradicts(x==30)
False
sage: (x<y).contradicts({x: 30, y: 20})
True
Call the convert function in the units package. For symbolic variables that are not units, this function just returns the variable.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: units.length.foot.convert()
381/1250*meter
sage: units.mass.kilogram.convert(units.mass.pound)
100000000/45359237*pound
We do not get anything new by converting an ordinary symbolic variable:
sage: a = var('a')
sage: a - a.convert()
0
Raises ValueError if self and target are not convertible:
sage: units.mass.kilogram.convert(units.length.foot)
Traceback (most recent call last):
...
ValueError: Incompatible units
sage: (units.length.meter^2).convert(units.length.foot)
Traceback (most recent call last):
...
ValueError: Incompatible units
Recognizes derived unit relationships to base units and other derived units:
sage: (units.length.foot/units.time.second^2).convert(units.acceleration.galileo)
762/25*galileo
sage: (units.mass.kilogram*units.length.meter/units.time.second^2).convert(units.force.newton)
newton
sage: (units.length.foot^3).convert(units.area.acre*units.length.inch)
1/3630*(acre*inch)
sage: (units.charge.coulomb).convert(units.current.ampere*units.time.second)
(ampere*second)
sage: (units.pressure.pascal*units.si_prefixes.kilo).convert(units.pressure.pounds_per_square_inch)
1290320000000/8896443230521*pounds_per_square_inch
For decimal answers multiply by 1.0:
sage: (units.pressure.pascal*units.si_prefixes.kilo).convert(units.pressure.pounds_per_square_inch)*1.0
0.145037737730209*pounds_per_square_inch
Converting temperatures works as well:
sage: s = 68*units.temperature.fahrenheit
sage: s.convert(units.temperature.celsius)
20*celsius
sage: s.convert()
293.150000000000*kelvin
Trying to multiply temperatures by another unit then converting raises a ValueError:
sage: wrong = 50*units.temperature.celsius*units.length.foot
sage: wrong.convert()
Traceback (most recent call last):
...
ValueError: Cannot convert
Return the cosine of self.
EXAMPLES:
sage: var('x, y')
(x, y)
sage: cos(x^2 + y^2)
cos(x^2 + y^2)
sage: cos(sage.symbolic.constants.pi)
-1
sage: cos(SR(1))
cos(1)
sage: cos(SR(RealField(150)(1)))
0.54030230586813971740093660744297660373231042
In order to get a numeric approximation use .n():
sage: SR(RR(1)).cos().n()
0.540302305868140
sage: SR(float(1)).cos().n()
0.540302305868140
To prevent automatic evaluation use the hold argument:
sage: pi.cos()
-1
sage: pi.cos(hold=True)
cos(pi)
This also works using functional notation:
sage: cos(pi,hold=True)
cos(pi)
sage: cos(pi)
-1
To then evaluate again, we currently must use Maxima via simplify():
sage: a = pi.cos(hold=True); a.simplify()
-1
TESTS:
sage: SR(oo).cos()
Traceback (most recent call last):
...
RuntimeError: cos_eval(): cos(infinity) encountered
sage: SR(-oo).cos()
Traceback (most recent call last):
...
RuntimeError: cos_eval(): cos(infinity) encountered
sage: SR(unsigned_infinity).cos()
Traceback (most recent call last):
...
RuntimeError: cos_eval(): cos(infinity) encountered
Return cosh of self.
We have .
EXAMPLES:
sage: x.cosh()
cosh(x)
sage: SR(1).cosh()
cosh(1)
sage: SR(0).cosh()
1
sage: SR(1.0).cosh()
1.54308063481524
sage: maxima('cosh(1.0)')
1.54308063481524...
sage: SR(1.00000000000000000000000000).cosh()
1.5430806348152437784779056
sage: SR(RIF(1)).cosh()
1.543080634815244?
To prevent automatic evaluation use the hold argument:
sage: arcsinh(x).cosh()
sqrt(x^2 + 1)
sage: arcsinh(x).cosh(hold=True)
cosh(arcsinh(x))
This also works using functional notation:
sage: cosh(arcsinh(x),hold=True)
cosh(arcsinh(x))
sage: cosh(arcsinh(x))
sqrt(x^2 + 1)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = arcsinh(x).cosh(hold=True); a.simplify()
sqrt(x^2 + 1)
TESTS:
sage: SR(oo).cosh()
+Infinity
sage: SR(-oo).cosh()
+Infinity
sage: SR(unsigned_infinity).cosh()
Traceback (most recent call last):
...
RuntimeError: cosh_eval(): cosh(unsigned_infinity) encountered
Return the sign of self, which is -1 if self < 0, 0 if self == 0, and 1 if self > 0, or unevaluated when self is a nonconstant symbolic expression.
If self is not real, return the complex half-plane (left or right) in which the number lies. If self is pure imaginary, return the sign of the imaginary part of self.
EXAMPLES:
sage: x = var('x')
sage: SR(-2).csgn()
-1
sage: SR(0.0).csgn()
0
sage: SR(10).csgn()
1
sage: x.csgn()
csgn(x)
sage: SR(CDF.0).csgn()
1
sage: SR(I).csgn()
1
sage: SR(-I).csgn()
-1
sage: SR(1+I).csgn()
1
sage: SR(1-I).csgn()
1
sage: SR(-1+I).csgn()
-1
sage: SR(-1-I).csgn()
-1
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(I).csgn(hold=True)
csgn(I)
Return the default variable, which is by definition the first
variable in self, or is there are no variables in self.
The result is cached.
EXAMPLES:
sage: sqrt(2).default_variable()
x
sage: x, theta, a = var('x, theta, a')
sage: f = x^2 + theta^3 - a^x
sage: f.default_variable()
a
Note that this is the first variable, not the first argument:
sage: f(theta, a, x) = a + theta^3
sage: f.default_variable()
a
sage: f.variables()
(a, theta)
sage: f.arguments()
(theta, a, x)
Return the exponent of the highest nonnegative power of s in self.
OUTPUT:
An integer >= 0.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y^10 + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + 2*sin(x*y)/x + x/y^10 + 100
sage: f.degree(x)
3
sage: f.degree(y)
1
sage: f.degree(sin(x*y))
1
sage: (x^-3+y).degree(x)
0
Return the denominator of this symbolic expression
INPUT:
If normalize is True, the expression is first normalized to have it as a fraction before getting the denominator.
If normalize is False, the expression is kept and if it is not a quotient, then this will just return 1.
See also
normalize(), numerator(), numerator_denominator(), combine()
EXAMPLES:
sage: x, y, z, theta = var('x, y, z, theta')
sage: f = (sqrt(x) + sqrt(y) + sqrt(z))/(x^10 - y^10 - sqrt(theta))
sage: f.numerator()
sqrt(x) + sqrt(y) + sqrt(z)
sage: f.denominator()
x^10 - y^10 - sqrt(theta)
sage: f.numerator(normalize=False)
(sqrt(x) + sqrt(y) + sqrt(z))
sage: f.denominator(normalize=False)
x^10 - y^10 - sqrt(theta)
sage: y = var('y')
sage: g = x + y/(x + 2); g
x + y/(x + 2)
sage: g.numerator(normalize=False)
x + y/(x + 2)
sage: g.denominator(normalize=False)
1
TESTS:
sage: ((x+y)^2/(x-y)^3*x^3).denominator(normalize=False)
(x - y)^3
sage: ((x+y)^2*x^3).denominator(normalize=False)
1
sage: (y/x^3).denominator(normalize=False)
x^3
sage: t = y/x^3/(x+y)^(1/2); t
y/(sqrt(x + y)*x^3)
sage: t.denominator(normalize=False)
sqrt(x + y)*x^3
sage: (1/x^3).denominator(normalize=False)
x^3
sage: (x^3).denominator(normalize=False)
1
sage: (y*x^sin(x)).denominator(normalize=False)
Traceback (most recent call last):
...
TypeError: self is not a rational expression
Return the derivative of this expressions with respect to the variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function for more details.
See also
This is implemented in the method (see the
source code).
EXAMPLES:
sage: var("x y")
(x, y)
sage: t = (x^2+y)^2
sage: t.derivative(x)
4*(x^2 + y)*x
sage: t.derivative(x, 2)
12*x^2 + 4*y
sage: t.derivative(x, 2, y)
4
sage: t.derivative(y)
2*x^2 + 2*y
If the function depends on only one variable, you may omit the variable. Giving just a number (for the order of the derivative) also works:
sage: f(x) = x^3 + sin(x)
sage: f.derivative()
x |--> 3*x^2 + cos(x)
sage: f.derivative(2)
x |--> 6*x - sin(x)
sage: t = sin(x+y^2)*tan(x*y)
sage: t.derivative(x)
(tan(x*y)^2 + 1)*y*sin(y^2 + x) + cos(y^2 + x)*tan(x*y)
sage: t.derivative(y)
(tan(x*y)^2 + 1)*x*sin(y^2 + x) + 2*y*cos(y^2 + x)*tan(x*y)
sage: h = sin(x)/cos(x)
sage: derivative(h,x,x,x)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: derivative(h,x,3)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: var('x, y')
(x, y)
sage: u = (sin(x) + cos(y))*(cos(x) - sin(y))
sage: derivative(u,x,y)
-cos(x)*cos(y) + sin(x)*sin(y)
sage: f = ((x^2+1)/(x^2-1))^(1/4)
sage: g = derivative(f, x); g # this is a complex expression
-1/2*((x^2 + 1)*x/(x^2 - 1)^2 - x/(x^2 - 1))/((x^2 + 1)/(x^2 - 1))^(3/4)
sage: g.factor()
-x/((x + 1)^2*(x - 1)^2*((x^2 + 1)/(x^2 - 1))^(3/4))
sage: y = var('y')
sage: f = y^(sin(x))
sage: derivative(f, x)
y^sin(x)*cos(x)*log(y)
sage: g(x) = sqrt(5-2*x)
sage: g_3 = derivative(g, x, 3); g_3(2)
-3
sage: f = x*e^(-x)
sage: derivative(f, 100)
x*e^(-x) - 100*e^(-x)
sage: g = 1/(sqrt((x^2-1)*(x+5)^6))
sage: derivative(g, x)
-((x + 5)^6*x + 3*(x^2 - 1)*(x + 5)^5)/((x^2 - 1)*(x + 5)^6)^(3/2)
TESTS:
sage: t.derivative()
Traceback (most recent call last):
...
ValueError: No differentiation variable specified.
Return the derivative of this expressions with respect to the variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function for more details.
See also
This is implemented in the method (see the
source code).
EXAMPLES:
sage: var("x y")
(x, y)
sage: t = (x^2+y)^2
sage: t.derivative(x)
4*(x^2 + y)*x
sage: t.derivative(x, 2)
12*x^2 + 4*y
sage: t.derivative(x, 2, y)
4
sage: t.derivative(y)
2*x^2 + 2*y
If the function depends on only one variable, you may omit the variable. Giving just a number (for the order of the derivative) also works:
sage: f(x) = x^3 + sin(x)
sage: f.derivative()
x |--> 3*x^2 + cos(x)
sage: f.derivative(2)
x |--> 6*x - sin(x)
sage: t = sin(x+y^2)*tan(x*y)
sage: t.derivative(x)
(tan(x*y)^2 + 1)*y*sin(y^2 + x) + cos(y^2 + x)*tan(x*y)
sage: t.derivative(y)
(tan(x*y)^2 + 1)*x*sin(y^2 + x) + 2*y*cos(y^2 + x)*tan(x*y)
sage: h = sin(x)/cos(x)
sage: derivative(h,x,x,x)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: derivative(h,x,3)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: var('x, y')
(x, y)
sage: u = (sin(x) + cos(y))*(cos(x) - sin(y))
sage: derivative(u,x,y)
-cos(x)*cos(y) + sin(x)*sin(y)
sage: f = ((x^2+1)/(x^2-1))^(1/4)
sage: g = derivative(f, x); g # this is a complex expression
-1/2*((x^2 + 1)*x/(x^2 - 1)^2 - x/(x^2 - 1))/((x^2 + 1)/(x^2 - 1))^(3/4)
sage: g.factor()
-x/((x + 1)^2*(x - 1)^2*((x^2 + 1)/(x^2 - 1))^(3/4))
sage: y = var('y')
sage: f = y^(sin(x))
sage: derivative(f, x)
y^sin(x)*cos(x)*log(y)
sage: g(x) = sqrt(5-2*x)
sage: g_3 = derivative(g, x, 3); g_3(2)
-3
sage: f = x*e^(-x)
sage: derivative(f, 100)
x*e^(-x) - 100*e^(-x)
sage: g = 1/(sqrt((x^2-1)*(x+5)^6))
sage: derivative(g, x)
-((x + 5)^6*x + 3*(x^2 - 1)*(x + 5)^5)/((x^2 - 1)*(x + 5)^6)^(3/2)
TESTS:
sage: t.derivative()
Traceback (most recent call last):
...
ValueError: No differentiation variable specified.
Return the derivative of this expressions with respect to the variables supplied in args.
Multiple variables and iteration counts may be supplied; see documentation for the global derivative() function for more details.
See also
This is implemented in the method (see the
source code).
EXAMPLES:
sage: var("x y")
(x, y)
sage: t = (x^2+y)^2
sage: t.derivative(x)
4*(x^2 + y)*x
sage: t.derivative(x, 2)
12*x^2 + 4*y
sage: t.derivative(x, 2, y)
4
sage: t.derivative(y)
2*x^2 + 2*y
If the function depends on only one variable, you may omit the variable. Giving just a number (for the order of the derivative) also works:
sage: f(x) = x^3 + sin(x)
sage: f.derivative()
x |--> 3*x^2 + cos(x)
sage: f.derivative(2)
x |--> 6*x - sin(x)
sage: t = sin(x+y^2)*tan(x*y)
sage: t.derivative(x)
(tan(x*y)^2 + 1)*y*sin(y^2 + x) + cos(y^2 + x)*tan(x*y)
sage: t.derivative(y)
(tan(x*y)^2 + 1)*x*sin(y^2 + x) + 2*y*cos(y^2 + x)*tan(x*y)
sage: h = sin(x)/cos(x)
sage: derivative(h,x,x,x)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: derivative(h,x,3)
8*sin(x)^2/cos(x)^2 + 6*sin(x)^4/cos(x)^4 + 2
sage: var('x, y')
(x, y)
sage: u = (sin(x) + cos(y))*(cos(x) - sin(y))
sage: derivative(u,x,y)
-cos(x)*cos(y) + sin(x)*sin(y)
sage: f = ((x^2+1)/(x^2-1))^(1/4)
sage: g = derivative(f, x); g # this is a complex expression
-1/2*((x^2 + 1)*x/(x^2 - 1)^2 - x/(x^2 - 1))/((x^2 + 1)/(x^2 - 1))^(3/4)
sage: g.factor()
-x/((x + 1)^2*(x - 1)^2*((x^2 + 1)/(x^2 - 1))^(3/4))
sage: y = var('y')
sage: f = y^(sin(x))
sage: derivative(f, x)
y^sin(x)*cos(x)*log(y)
sage: g(x) = sqrt(5-2*x)
sage: g_3 = derivative(g, x, 3); g_3(2)
-3
sage: f = x*e^(-x)
sage: derivative(f, 100)
x*e^(-x) - 100*e^(-x)
sage: g = 1/(sqrt((x^2-1)*(x+5)^6))
sage: derivative(g, x)
-((x + 5)^6*x + 3*(x^2 - 1)*(x + 5)^5)/((x^2 - 1)*(x + 5)^6)^(3/2)
TESTS:
sage: t.derivative()
Traceback (most recent call last):
...
ValueError: No differentiation variable specified.
Return a relation obtained by dividing both sides of this relation by x.
Note
The checksign keyword argument is currently ignored and is included for backward compatibility reasons only.
EXAMPLES:
sage: theta = var('theta')
sage: eqn = (x^3 + theta < sin(x*theta))
sage: eqn.divide_both_sides(theta, checksign=False)
(x^3 + theta)/theta < sin(theta*x)/theta
sage: eqn.divide_both_sides(theta)
(x^3 + theta)/theta < sin(theta*x)/theta
sage: eqn/theta
(x^3 + theta)/theta < sin(theta*x)/theta
Return exponential function of self, i.e., e to the power of self.
EXAMPLES:
sage: x.exp()
e^x
sage: SR(0).exp()
1
sage: SR(1/2).exp()
e^(1/2)
sage: SR(0.5).exp()
1.64872127070013
sage: math.exp(0.5)
1.6487212707001282
sage: SR(0.5).exp().log()
0.500000000000000
sage: (pi*I).exp()
-1
To prevent automatic evaluation use the hold argument:
sage: (pi*I).exp(hold=True)
e^(I*pi)
This also works using functional notation:
sage: exp(I*pi,hold=True)
e^(I*pi)
sage: exp(I*pi)
-1
To then evaluate again, we currently must use Maxima via simplify():
sage: a = (pi*I).exp(hold=True); a.simplify()
-1
TESTS:
Test if trac ticket #6377 is fixed:
sage: SR(oo).exp()
+Infinity
sage: SR(-oo).exp()
0
sage: SR(unsigned_infinity).exp()
Traceback (most recent call last):
...
RuntimeError: exp_eval(): exp^(unsigned_infinity) encountered
Simplify this symbolic expression, which can contain logs, exponentials, and radicals, by trying to convert it into a canonical form over a large class of expressions and a given ordering of variables.
Warning
As shown in the examples below, a canonical form is not always returned, i.e., two mathematically identical expressions might be simplified to different expressions.
ALGORITHM:
This uses the Maxima radcan() command. From the Maxima documentation: “All functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, produces a regular form. Two equivalent expressions in this class do not necessarily have the same appearance, but their difference can be simplified by radcan to zero. For some expressions radcan is quite time consuming. This is the cost of exploring certain relationships among the components of the expression for simplifications based on factoring and partial fraction expansions of exponents.”
Note
radical_simplify(), simplify_radical(), exp_simplify(), simplify_exp() are all the same.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = log(x*y)
sage: f.simplify_radical()
log(x) + log(y)
sage: f = log(8)/log(2)
sage: f.simplify_radical()
3
sage: f = (log(x+x^2)-log(x))^a/log(1+x)^(a/2)
sage: f.simplify_radical()
log(x + 1)^(1/2*a)
sage: f = (e^x-1)/(1+e^(x/2))
sage: f.simplify_exp()
e^(1/2*x) - 1
The example below shows two expressions e1 and e2 which are “simplified” to different expressions, while their difference is “simplified” to zero, thus simplify_radical does not return a canonical form, except maybe for 0.
sage: e1 = 1/(sqrt(5)+sqrt(2))
sage: e2 = (sqrt(5)-sqrt(2))/3
sage: e1.simplify_radical()
1/(sqrt(5) + sqrt(2))
sage: e2.simplify_radical()
1/3*sqrt(5) - 1/3*sqrt(2)
sage: (e1-e2).simplify_radical()
0
TESTS:
This tests that trac ticket #11668 has been fixed (by trac ticket #12780):
sage: a,b = var('a b')
sage: A = abs((a+I*b))^2
sage: A.simplify_radical()
abs(a + I*b)^2
sage: imag(A)
0
sage: imag(A.simplify_radical())
0
Expand this symbolic expression. Products of sums and exponentiated sums are multiplied out, numerators of rational expressions which are sums are split into their respective terms, and multiplications are distributed over addition at all levels.
EXAMPLES:
We expand the expression using both
method and functional notation.
sage: x,y = var('x,y')
sage: a = (x-y)^5
sage: a.expand()
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
sage: expand(a)
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
We expand some other expressions:
sage: expand((x-1)^3/(y-1))
x^3/(y - 1) - 3*x^2/(y - 1) + 3*x/(y - 1) - 1/(y - 1)
sage: expand((x+sin((x+y)^2))^2)
x^2 + 2*x*sin((x + y)^2) + sin((x + y)^2)^2
We can expand individual sides of a relation:
sage: a = (16*x-13)^2 == (3*x+5)^2/2
sage: a.expand()
256*x^2 - 416*x + 169 == 9/2*x^2 + 15*x + 25/2
sage: a.expand('left')
256*x^2 - 416*x + 169 == 1/2*(3*x + 5)^2
sage: a.expand('right')
(16*x - 13)^2 == 9/2*x^2 + 15*x + 25/2
TESTS:
sage: var('x,y')
(x, y)
sage: ((x + (2/3)*y)^3).expand()
x^3 + 2*x^2*y + 4/3*x*y^2 + 8/27*y^3
sage: expand( (x*sin(x) - cos(y)/x)^2 )
x^2*sin(x)^2 - 2*cos(y)*sin(x) + cos(y)^2/x^2
sage: f = (x-y)*(x+y); f
(x + y)*(x - y)
sage: f.expand()
x^2 - y^2
Simplify symbolic expression, which can contain logs.
Expands logarithms of powers, logarithms of products and logarithms of quotients. The option algorithm specifies which expression types should be expanded.
INPUT:
self - expression to be simplified
algorithm - (default: ‘products’) optional, governs which expression is expanded. Possible values are
See also examples below.
DETAILS: This uses the Maxima simplifier and sets logexpand option for this simplifier. From the Maxima documentation: “Logexpand:true causes log(a^b) to become b*log(a). If it is set to all, log(a*b) will also simplify to log(a)+log(b). If it is set to super, then log(a/b) will also simplify to log(a)-log(b) for rational numbers a/b, a#1. (log(1/b), for integer b, always simplifies.) If it is set to false, all of these simplifications will be turned off. “
ALIAS: log_expand() and expand_log() are the same
EXAMPLES:
By default powers and products (and quotients) are expanded, but not quotients of integers:
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
To expand also log(3/4) use algorithm='all':
sage: (log(3/4*x^pi)).log_expand('all')
pi*log(x) - log(4) + log(3)
To expand only the power use algorithm='powers'.:
sage: (log(x^6)).log_expand('powers')
6*log(x)
The expression log((3*x)^6) is not expanded with algorithm='powers', since it is converted into product first:
sage: (log((3*x)^6)).log_expand('powers')
log(729*x^6)
This shows that the option algorithm from the previous call has no influence to future calls (we changed some default Maxima flag, and have to ensure that this flag has been restored):
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
sage: (log(3/4*x^pi)).log_expand('all')
pi*log(x) - log(4) + log(3)
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
TESTS:
Most of these log expansions only make sense over the reals. So, we should set the Maxima domain variable to ‘real’ before we call out to Maxima. When we return, however, we should set the domain back to what it was, rather than assuming that it was ‘complex’. See trac ticket #12780:
sage: from sage.calculus.calculus import maxima
sage: maxima('domain: real;')
real
sage: x.expand_log()
x
sage: maxima('domain;')
real
sage: maxima('domain: complex;')
complex
AUTHORS:
Expand this symbolic expression. Products of sums and exponentiated sums are multiplied out, numerators of rational expressions which are sums are split into their respective terms, and multiplications are distributed over addition at all levels.
EXAMPLES:
We expand the expression using both
method and functional notation.
sage: x,y = var('x,y')
sage: a = (x-y)^5
sage: a.expand()
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
sage: expand(a)
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
We expand some other expressions:
sage: expand((x-1)^3/(y-1))
x^3/(y - 1) - 3*x^2/(y - 1) + 3*x/(y - 1) - 1/(y - 1)
sage: expand((x+sin((x+y)^2))^2)
x^2 + 2*x*sin((x + y)^2) + sin((x + y)^2)^2
We can expand individual sides of a relation:
sage: a = (16*x-13)^2 == (3*x+5)^2/2
sage: a.expand()
256*x^2 - 416*x + 169 == 9/2*x^2 + 15*x + 25/2
sage: a.expand('left')
256*x^2 - 416*x + 169 == 1/2*(3*x + 5)^2
sage: a.expand('right')
(16*x - 13)^2 == 9/2*x^2 + 15*x + 25/2
TESTS:
sage: var('x,y')
(x, y)
sage: ((x + (2/3)*y)^3).expand()
x^3 + 2*x^2*y + 4/3*x*y^2 + 8/27*y^3
sage: expand( (x*sin(x) - cos(y)/x)^2 )
x^2*sin(x)^2 - 2*cos(y)*sin(x) + cos(y)^2/x^2
sage: f = (x-y)*(x+y); f
(x + y)*(x - y)
sage: f.expand()
x^2 - y^2
Expand trigonometric and hyperbolic functions of sums of angles and of multiple angles occurring in self. For best results, self should already be expanded.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: sin(5*x).expand_trig()
5*cos(x)^4*sin(x) - 10*cos(x)^2*sin(x)^3 + sin(x)^5
sage: cos(2*x + var('y')).expand_trig()
cos(2*x)*cos(y) - sin(2*x)*sin(y)
We illustrate various options to this function:
sage: f = sin(sin(3*cos(2*x))*x)
sage: f.expand_trig()
sin((3*cos(cos(2*x))^2*sin(cos(2*x)) - sin(cos(2*x))^3)*x)
sage: f.expand_trig(full=True)
sin((3*(cos(cos(x)^2)*cos(sin(x)^2) + sin(cos(x)^2)*sin(sin(x)^2))^2*(cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2)) - (cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2))^3)*x)
sage: sin(2*x).expand_trig(times=False)
sin(2*x)
sage: sin(2*x).expand_trig(times=True)
2*cos(x)*sin(x)
sage: sin(2 + x).expand_trig(plus=False)
sin(x + 2)
sage: sin(2 + x).expand_trig(plus=True)
cos(x)*sin(2) + cos(2)*sin(x)
sage: sin(x/2).expand_trig(half_angles=False)
sin(1/2*x)
sage: sin(x/2).expand_trig(half_angles=True)
(-1)^floor(1/2*x/pi)*sqrt(-1/2*cos(x) + 1/2)
ALIASES:
trig_expand() and expand_trig() are the same
Factor the expression, containing any number of variables or functions, into factors irreducible over the integers.
INPUT:
EXAMPLES:
sage: x,y,z = var('x, y, z')
sage: (x^3-y^3).factor()
(x^2 + x*y + y^2)*(x - y)
sage: factor(-8*y - 4*x + z^2*(2*y + x))
(x + 2*y)*(z + 2)*(z - 2)
sage: f = -1 - 2*x - x^2 + y^2 + 2*x*y^2 + x^2*y^2
sage: F = factor(f/(36*(1 + 2*y + y^2)), dontfactor=[x]); F
1/36*(x^2 + 2*x + 1)*(y - 1)/(y + 1)
If you are factoring a polynomial with rational coefficients (and dontfactor is empty) the factorization is done using Singular instead of Maxima, so the following is very fast instead of dreadfully slow:
sage: var('x,y')
(x, y)
sage: (x^99 + y^99).factor()
(x^60 + x^57*y^3 - x^51*y^9 - x^48*y^12 + x^42*y^18 + x^39*y^21 -
x^33*y^27 - x^30*y^30 - x^27*y^33 + x^21*y^39 + x^18*y^42 -
x^12*y^48 - x^9*y^51 + x^3*y^57 + y^60)*(x^20 + x^19*y -
x^17*y^3 - x^16*y^4 + x^14*y^6 + x^13*y^7 - x^11*y^9 -
x^10*y^10 - x^9*y^11 + x^7*y^13 + x^6*y^14 - x^4*y^16 -
x^3*y^17 + x*y^19 + y^20)*(x^10 - x^9*y + x^8*y^2 - x^7*y^3 +
x^6*y^4 - x^5*y^5 + x^4*y^6 - x^3*y^7 + x^2*y^8 - x*y^9 +
y^10)*(x^6 - x^3*y^3 + y^6)*(x^2 - x*y + y^2)*(x + y)
Return a list of the factors of self, as computed by the factor command.
INPUT:
Note
If you already have a factored expression and just want to
get at the individual factors, use the method
instead.
EXAMPLES:
sage: var('x, y, z')
(x, y, z)
sage: f = x^3-y^3
sage: f.factor()
(x^2 + x*y + y^2)*(x - y)
Notice that the -1 factor is separated out:
sage: f.factor_list()
[(x^2 + x*y + y^2, 1), (x - y, 1)]
We factor a fairly straightforward expression:
sage: factor(-8*y - 4*x + z^2*(2*y + x)).factor_list()
[(x + 2*y, 1), (z + 2, 1), (z - 2, 1)]
A more complicated example:
sage: var('x, u, v')
(x, u, v)
sage: f = expand((2*u*v^2-v^2-4*u^3)^2 * (-u)^3 * (x-sin(x))^3)
sage: f.factor()
-(4*u^3 - 2*u*v^2 + v^2)^2*u^3*(x - sin(x))^3
sage: g = f.factor_list(); g
[(4*u^3 - 2*u*v^2 + v^2, 2), (u, 3), (x - sin(x), 3), (-1, 1)]
This function also works for quotients:
sage: f = -1 - 2*x - x^2 + y^2 + 2*x*y^2 + x^2*y^2
sage: g = f/(36*(1 + 2*y + y^2)); g
1/36*(x^2*y^2 + 2*x*y^2 - x^2 + y^2 - 2*x - 1)/(y^2 + 2*y + 1)
sage: g.factor(dontfactor=[x])
1/36*(x^2 + 2*x + 1)*(y - 1)/(y + 1)
sage: g.factor_list(dontfactor=[x])
[(x^2 + 2*x + 1, 1), (y + 1, -1), (y - 1, 1), (1/36, 1)]
This example also illustrates that the exponents do not have to be integers:
sage: f = x^(2*sin(x)) * (x-1)^(sqrt(2)*x); f
(x - 1)^(sqrt(2)*x)*x^(2*sin(x))
sage: f.factor_list()
[(x - 1, sqrt(2)*x), (x, 2*sin(x))]
Return the factorial of self.
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: var('x, y')
(x, y)
sage: SR(5).factorial()
120
sage: x.factorial()
factorial(x)
sage: (x^2+y^3).factorial()
factorial(y^3 + x^2)
To prevent automatic evaluation use the hold argument:
sage: SR(5).factorial(hold=True)
factorial(5)
This also works using functional notation:
sage: factorial(5,hold=True)
factorial(5)
sage: factorial(5)
120
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(5).factorial(hold=True); a.simplify()
120
Simplify by combining expressions with factorials, and by expanding binomials into factorials.
ALIAS: factorial_simplify and simplify_factorial are the same
EXAMPLES:
Some examples are relatively clear:
sage: var('n,k')
(n, k)
sage: f = factorial(n+1)/factorial(n); f
factorial(n + 1)/factorial(n)
sage: f.simplify_factorial()
n + 1
sage: f = factorial(n)*(n+1); f
(n + 1)*factorial(n)
sage: simplify(f)
(n + 1)*factorial(n)
sage: f.simplify_factorial()
factorial(n + 1)
sage: f = binomial(n, k)*factorial(k)*factorial(n-k); f
binomial(n, k)*factorial(k)*factorial(-k + n)
sage: f.simplify_factorial()
factorial(n)
A more complicated example, which needs further processing:
sage: f = factorial(x)/factorial(x-2)/2 + factorial(x+1)/factorial(x)/2; f
1/2*factorial(x + 1)/factorial(x) + 1/2*factorial(x)/factorial(x - 2)
sage: g = f.simplify_factorial(); g
1/2*(x - 1)*x + 1/2*x + 1/2
sage: g.simplify_rational()
1/2*x^2 + 1/2
TESTS:
Check that the problem with applying to gamma
functions (trac ticket #9240) has been fixed:
sage: gamma(1/3)
gamma(1/3)
sage: gamma(1/3).full_simplify()
gamma(1/3)
sage: gamma(4/3)
gamma(4/3)
sage: gamma(4/3).full_simplify()
1/3*gamma(1/3)
Find all occurrences of the given pattern in this expression.
Note that once a subexpression matches the pattern, the search does not extend to subexpressions of it.
EXAMPLES:
sage: var('x,y,z,a,b')
(x, y, z, a, b)
sage: w0 = SR.wild(0); w1 = SR.wild(1)
sage: (sin(x)*sin(y)).find(sin(w0))
[sin(y), sin(x)]
sage: ((sin(x)+sin(y))*(a+b)).expand().find(sin(w0))
[sin(y), sin(x)]
sage: (1+x+x^2+x^3).find(x)
[x]
sage: (1+x+x^2+x^3).find(x^w0)
[x^2, x^3]
sage: (1+x+x^2+x^3).find(y)
[]
# subexpressions of a match are not listed
sage: ((x^y)^z).find(w0^w1)
[(x^y)^z]
Numerically find a local maximum of the expression self on the interval [a,b] (or [b,a]) along with the point at which the maximum is attained.
See the documentation for find_local_minimum() for more details.
EXAMPLES:
sage: f = x*cos(x)
sage: f.find_local_maximum(0,5)
(0.5610963381910451, 0.8603335890...)
sage: f.find_local_maximum(0,5, tol=0.1, maxfun=10)
(0.561090323458081..., 0.857926501456...)
Numerically find a local minimum of the expression self on the interval [a,b] (or [b,a]) and the point at which it attains that minimum. Note that self must be a function of (at most) one variable.
INPUT:
OUTPUT:
A tuple (minval, x), where
EXAMPLES:
sage: f = x*cos(x)
sage: f.find_local_minimum(1, 5)
(-3.288371395590..., 3.4256184695...)
sage: f.find_local_minimum(1, 5, tol=1e-3)
(-3.288371361890..., 3.4257507903...)
sage: f.find_local_minimum(1, 5, tol=1e-2, maxfun=10)
(-3.288370845983..., 3.4250840220...)
sage: show(f.plot(0, 20))
sage: f.find_local_minimum(1, 15)
(-9.477294259479..., 9.5293344109...)
ALGORITHM:
Uses sage.numerical.optimize.find_local_minimum().
AUTHORS:
Numerically find a root of self on the closed interval [a,b] (or [b,a]) if possible, where self is a function in the one variable. Note: this function only works in fixed (machine) precision, it is not possible to get arbitrary precision approximations with it.
INPUT:
EXAMPLES:
Note that in this example both f(-2) and f(3) are positive, yet we still find a root in that interval:
sage: f = x^2 - 1
sage: f.find_root(-2, 3)
1.0
sage: f.find_root(-2, 3, x)
1.0
sage: z, result = f.find_root(-2, 3, full_output=True)
sage: result.converged
True
sage: result.flag
'converged'
sage: result.function_calls
11
sage: result.iterations
10
sage: result.root
1.0
More examples:
sage: (sin(x) + exp(x)).find_root(-10, 10)
-0.588532743981862...
sage: sin(x).find_root(-1,1)
0.0
sage: (1/tan(x)).find_root(3,3.5)
3.1415926535...
An example with a square root:
sage: f = 1 + x + sqrt(x+2); f.find_root(-2,10)
-1.618033988749895
Some examples that Ted Kosan came up with:
sage: t = var('t')
sage: v = 0.004*(9600*e^(-(1200*t)) - 2400*e^(-(300*t)))
sage: v.find_root(0, 0.002)
0.001540327067911417...
With this expression, we can see there is a zero very close to the origin:
sage: a = .004*(8*e^(-(300*t)) - 8*e^(-(1200*t)))*(720000*e^(-(300*t)) - 11520000*e^(-(1200*t))) +.004*(9600*e^(-(1200*t)) - 2400*e^(-(300*t)))^2
sage: show(plot(a, 0, .002), xmin=0, xmax=.002)
It is easy to approximate with find_root:
sage: a.find_root(0,0.002)
0.0004110514049349...
Using solve takes more effort, and even then gives only a solution with free (integer) variables:
sage: a.solve(t)
[]
sage: b = a.simplify_radical(); b
-23040*(-2.0*e^(1800*t) + 25.0*e^(900*t) - 32.0)*e^(-2400*t)
sage: b.solve(t)
[]
sage: b.solve(t, to_poly_solve=True)
[t == 1/450*I*pi*z... + 1/900*log(-3/4*sqrt(41) + 25/4),
t == 1/450*I*pi*z... + 1/900*log(3/4*sqrt(41) + 25/4)]
sage: n(1/900*log(-3/4*sqrt(41) + 25/4))
0.000411051404934985
We illustrate that root finding is only implemented in one dimension:
sage: x, y = var('x,y')
sage: (x-y).find_root(-2,2)
Traceback (most recent call last):
...
NotImplementedError: root finding currently only implemented in 1 dimension.
TESTS:
Test the special case that failed for the first attempt to fix trac ticket #3980:
sage: t = var('t')
sage: find_root(1/t - x,0,2)
Traceback (most recent call last):
...
NotImplementedError: root finding currently only implemented in 1 dimension.
Forget the given constraint.
EXAMPLES:
sage: var('x,y')
(x, y)
sage: forget()
sage: assume(x>0, y < 2)
sage: assumptions()
[x > 0, y < 2]
sage: forget(y < 2)
sage: assumptions()
[x > 0]
TESTS:
Check if trac ticket #7507 is fixed:
sage: forget()
sage: n = var('n')
sage: foo=sin((-1)*n*pi)
sage: foo.simplify()
-sin(pi*n)
sage: assume(n, 'odd')
sage: assumptions()
[n is odd]
sage: foo.simplify()
0
sage: forget(n, 'odd')
sage: assumptions()
[]
sage: foo.simplify()
-sin(pi*n)
Apply simplify_factorial, simplify_trig, simplify_rational, simplify_log, and again simplify_rational to self (in that order).
ALIAS: simplify_full and full_simplify are the same.
EXAMPLES:
sage: f = sin(x)^2 + cos(x)^2
sage: f.simplify_full()
1
sage: f = sin(x/(x^2 + x))
sage: f.simplify_full()
sin(1/(x + 1))
sage: var('n,k')
(n, k)
sage: f = binomial(n,k)*factorial(k)*factorial(n-k)
sage: f.simplify_full()
factorial(n)
TESTS:
There are two square roots of , so this should
not be simplified to
, trac ticket #12737:
sage: f = sqrt((x + 1)^2)
sage: f.simplify_full()
sqrt(x^2 + 2*x + 1)
The imaginary part of an expression should not change under simplification; trac ticket #11934:
sage: f = sqrt(-8*(4*sqrt(2) - 7)*x^4 + 16*(3*sqrt(2) - 5)*x^3)
sage: original = f.imag_part()
sage: simplified = f.full_simplify().imag_part()
sage: original - simplified
0
The invalid simplification from trac ticket #12322 should not occur after trac ticket #12737:
sage: t = var('t')
sage: assume(t, 'complex')
sage: assumptions()
[t is complex]
sage: f = (1/2)*log(2*t) + (1/2)*log(1/t)
sage: f.simplify_full()
1/2*log(2*t) - 1/2*log(t)
Return a callable symbolic expression with the given variables.
EXAMPLES:
We will use several symbolic variables in the examples below:
sage: var('x, y, z, t, a, w, n')
(x, y, z, t, a, w, n)
sage: u = sin(x) + x*cos(y)
sage: g = u.function(x,y)
sage: g(x,y)
x*cos(y) + sin(x)
sage: g(t,z)
t*cos(z) + sin(t)
sage: g(x^2, x^y)
x^2*cos(x^y) + sin(x^2)
sage: f = (x^2 + sin(a*w)).function(a,x,w); f
(a, x, w) |--> x^2 + sin(a*w)
sage: f(1,2,3)
sin(3) + 4
Using the function() method we can obtain the above function
, but viewed as a function of different variables:
sage: h = f.function(w,a); h
(w, a) |--> x^2 + sin(a*w)
This notation also works:
sage: h(w,a) = f
sage: h
(w, a) |--> x^2 + sin(a*w)
You can even make a symbolic expression into a function
by writing f(x,y) = f:
sage: f = x^n + y^n; f
x^n + y^n
sage: f(x,y) = f
sage: f
(x, y) |--> x^n + y^n
sage: f(2,3)
3^n + 2^n
Return the Gamma function evaluated at self.
EXAMPLES:
sage: x = var('x')
sage: x.gamma()
gamma(x)
sage: SR(2).gamma()
1
sage: SR(10).gamma()
362880
sage: SR(10.0r).gamma() # For ARM: rel tol 2e-15
362880.0
sage: SR(CDF(1,1)).gamma()
0.49801566811835607 - 0.15494982830181067*I
sage: gp('gamma(1+I)')
0.4980156681183560427136911175 - 0.1549498283018106851249551305*I # 32-bit
0.49801566811835604271369111746219809195 - 0.15494982830181068512495513048388660520*I # 64-bit
We plot the familiar plot of this log-convex function:
sage: plot(gamma(x), -6,4).show(ymin=-3,ymax=3)
To prevent automatic evaluation use the hold argument:
sage: SR(1/2).gamma()
sqrt(pi)
sage: SR(1/2).gamma(hold=True)
gamma(1/2)
This also works using functional notation:
sage: gamma(1/2,hold=True)
gamma(1/2)
sage: gamma(1/2)
sqrt(pi)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(1/2).gamma(hold=True); a.simplify()
sqrt(pi)
Return the gcd of self and b, which must be integers or polynomials over the rational numbers.
TODO: I tried the massive gcd from http://trac.sagemath.org/sage_trac/ticket/694 on Ginac dies after about 10 seconds. Singular easily does that GCD now. Since Ginac only handles poly gcd over QQ, we should change ginac itself to use Singular.
EXAMPLES:
sage: var('x,y')
(x, y)
sage: SR(10).gcd(SR(15))
5
sage: (x^3 - 1).gcd(x-1)
x - 1
sage: (x^3 - 1).gcd(x^2+x+1)
x^2 + x + 1
sage: (x^3 - sage.symbolic.constants.pi).gcd(x-sage.symbolic.constants.pi)
Traceback (most recent call last):
...
ValueError: gcd: arguments must be polynomials over the rationals
sage: gcd(x^3 - y^3, x-y)
-x + y
sage: gcd(x^100-y^100, x^10-y^10)
-x^10 + y^10
sage: gcd(expand( (x^2+17*x+3/7*y)*(x^5 - 17*y + 2/3) ), expand((x^13+17*x+3/7*y)*(x^5 - 17*y + 2/3)) )
1/7*x^5 - 17/7*y + 2/21
Compute the gradient of a symbolic function.
This function returns a vector whose components are the derivatives of the original function with respect to the arguments of the original function. Alternatively, you can specify the variables as a list.
EXAMPLES:
sage: x,y = var('x y')
sage: f = x^2+y^2
sage: f.gradient()
(2*x, 2*y)
sage: g(x,y) = x^2+y^2
sage: g.gradient()
(x, y) |--> (2*x, 2*y)
sage: n = var('n')
sage: f(x,y) = x^n+y^n
sage: f.gradient()
(x, y) |--> (n*x^(n - 1), n*y^(n - 1))
sage: f.gradient([y,x])
(x, y) |--> (n*y^(n - 1), n*x^(n - 1))
EXAMPLES:
sage: var('x,y,a'); w0 = SR.wild(); w1 = SR.wild()
(x, y, a)
sage: (x*sin(x + y + 2*a)).has(y)
True
Here “x+y” is not a subexpression of “x+y+2*a” (which has the subexpressions “x”, “y” and “2*a”):
sage: (x*sin(x + y + 2*a)).has(x+y)
False
sage: (x*sin(x + y + 2*a)).has(x + y + w0)
True
The following fails because “2*(x+y)” automatically gets converted to “2*x+2*y” of which “x+y” is not a subexpression:
sage: (x*sin(2*(x+y) + 2*a)).has(x+y)
False
Although x^1==x and x^0==1, neither “x” nor “1” are actually of the form “x^something”:
sage: (x+1).has(x^w0)
False
Here is another possible pitfall, where the first expression matches because the term “-x” has the form “(-1)*x” in GiNaC. To check whether a polynomial contains a linear term you should use the coeff() function instead.
sage: (4*x^2 - x + 3).has(w0*x)
True
sage: (4*x^2 + x + 3).has(w0*x)
False
sage: (4*x^2 + x + 3).has(x)
True
sage: (4*x^2 - x + 3).coeff(x,1)
-1
sage: (4*x^2 + x + 3).coeff(x,1)
1
Compute the hessian of a function. This returns a matrix components are the 2nd partial derivatives of the original function.
EXAMPLES:
sage: x,y = var('x y')
sage: f = x^2+y^2
sage: f.hessian()
[2 0]
[0 2]
sage: g(x,y) = x^2+y^2
sage: g.hessian()
[(x, y) |--> 2 (x, y) |--> 0]
[(x, y) |--> 0 (x, y) |--> 2]
Simplify an expression containing hypergeometric functions.
INPUT:
ALIAS: hypergeometric_simplify() and simplify_hypergeometric() are the same
EXAMPLES:
sage: hypergeometric((5, 4), (4, 1, 2, 3),
....: x).simplify_hypergeometric()
1/144*x^2*hypergeometric((), (3, 4), x) +...
1/3*x*hypergeometric((), (2, 3), x) + hypergeometric((), (1, 2), x)
sage: (2*hypergeometric((), (), x)).simplify_hypergeometric()
2*e^x
sage: (nest(lambda y: hypergeometric([y], [1], x), 3, 1)
....: .simplify_hypergeometric())
laguerre(-laguerre(-e^x, x), x)
sage: (nest(lambda y: hypergeometric([y], [1], x), 3, 1)
....: .simplify_hypergeometric(algorithm='sage'))
hypergeometric((hypergeometric((e^x,), (1,), x),), (1,), x)
Return the imaginary part of this symbolic expression.
EXAMPLES:
sage: sqrt(-2).imag_part()
sqrt(2)
We simplify to
. This should only
be for
, but Maxima does not
have a symbolic imaginary part function, so we cannot
use assume to assume that first:
sage: z = var('z')
sage: f = log(exp(z))
sage: f
log(e^z)
sage: f.simplify()
z
sage: forget()
A more symbolic example:
sage: var('a, b')
(a, b)
sage: f = log(a + b*I)
sage: f.imag_part()
arctan2(imag_part(a) + real_part(b), -imag_part(b) + real_part(a))
Using the hold parameter it is possible to prevent automatic evaluation:
sage: I.imag_part()
1
sage: I.imag_part(hold=True)
imag_part(I)
This also works using functional notation:
sage: imag_part(I,hold=True)
imag_part(I)
sage: imag_part(I)
1
To then evaluate again, we currently must use Maxima via simplify():
sage: a = I.imag_part(hold=True); a.simplify()
1
TESTS:
sage: x = var('x')
sage: x.imag_part()
imag_part(x)
sage: SR(2+3*I).imag_part()
3
sage: SR(CC(2,3)).imag_part()
3.00000000000000
sage: SR(CDF(2,3)).imag_part()
3.0
Return the imaginary part of this symbolic expression.
EXAMPLES:
sage: sqrt(-2).imag_part()
sqrt(2)
We simplify to
. This should only
be for
, but Maxima does not
have a symbolic imaginary part function, so we cannot
use assume to assume that first:
sage: z = var('z')
sage: f = log(exp(z))
sage: f
log(e^z)
sage: f.simplify()
z
sage: forget()
A more symbolic example:
sage: var('a, b')
(a, b)
sage: f = log(a + b*I)
sage: f.imag_part()
arctan2(imag_part(a) + real_part(b), -imag_part(b) + real_part(a))
Using the hold parameter it is possible to prevent automatic evaluation:
sage: I.imag_part()
1
sage: I.imag_part(hold=True)
imag_part(I)
This also works using functional notation:
sage: imag_part(I,hold=True)
imag_part(I)
sage: imag_part(I)
1
To then evaluate again, we currently must use Maxima via simplify():
sage: a = I.imag_part(hold=True); a.simplify()
1
TESTS:
sage: x = var('x')
sage: x.imag_part()
imag_part(x)
sage: SR(2+3*I).imag_part()
3
sage: SR(CC(2,3)).imag_part()
3.00000000000000
sage: SR(CDF(2,3)).imag_part()
3.0
Compute the integral of self. Please see sage.symbolic.integration.integral.integrate() for more details.
EXAMPLES:
sage: sin(x).integral(x,0,3)
-cos(3) + 1
sage: sin(x).integral(x)
-cos(x)
TESTS:
We check that trac ticket #12438 is resolved:
sage: f(x) = x; f
x |--> x
sage: integral(f, x)
x |--> 1/2*x^2
sage: integral(f, x, 0, 1)
1/2
sage: f(x, y) = x + y
sage: f
(x, y) |--> x + y
sage: integral(f, y, 0, 1)
x |--> x + 1/2
sage: integral(f, x, 0, 1)
y |--> y + 1/2
sage: _(3)
7/2
sage: var("z")
z
sage: integral(f, z, 0, 2)
(x, y) |--> 2*x + 2*y
sage: integral(f, z)
(x, y) |--> (x + y)*z
Compute the integral of self. Please see sage.symbolic.integration.integral.integrate() for more details.
EXAMPLES:
sage: sin(x).integral(x,0,3)
-cos(3) + 1
sage: sin(x).integral(x)
-cos(x)
TESTS:
We check that trac ticket #12438 is resolved:
sage: f(x) = x; f
x |--> x
sage: integral(f, x)
x |--> 1/2*x^2
sage: integral(f, x, 0, 1)
1/2
sage: f(x, y) = x + y
sage: f
(x, y) |--> x + y
sage: integral(f, y, 0, 1)
x |--> x + 1/2
sage: integral(f, x, 0, 1)
y |--> y + 1/2
sage: _(3)
7/2
sage: var("z")
z
sage: integral(f, z, 0, 2)
(x, y) |--> 2*x + 2*y
sage: integral(f, z)
(x, y) |--> (x + y)*z
Return inverse Laplace transform of self. See sage.calculus.calculus.inverse_laplace
EXAMPLES:
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)
Return True if this symbolic expression is a constant.
This function is intended to provide an interface to query the internal representation of the expression. In this sense, the word constant does not reflect the mathematical properties of the expression. Expressions which have no variables may return False.
EXAMPLES:
sage: pi.is_constant()
True
sage: x.is_constant()
False
sage: SR(1).is_constant()
False
Note that the complex I is not a constant:
sage: I.is_constant()
False
sage: I.is_numeric()
True
Return True if self is an infinite expression.
EXAMPLES:
sage: SR(oo).is_infinity()
True
sage: x.is_infinity()
False
Return True if this expression is known to be an integer.
EXAMPLES:
sage: SR(5).is_integer()
True
Return True if this expression is known to be negative.
EXAMPLES:
sage: SR(-5).is_negative()
True
Check if we can correctly deduce negativity of mul objects:
sage: t0 = SR.symbol("t0", domain='positive')
sage: t0.is_negative()
False
sage: (-t0).is_negative()
True
sage: (-pi).is_negative()
True
Return True if self is a negative infinite expression.
EXAMPLES:
sage: SR(oo).is_negative_infinity()
False
sage: SR(-oo).is_negative_infinity()
True
sage: x.is_negative_infinity()
False
Return True if this expression only consists of a numeric object.
EXAMPLES:
sage: SR(1).is_numeric()
True
sage: x.is_numeric()
False
sage: pi.is_numeric()
False
Return True if self is a polynomial in the given variable.
EXAMPLES:
sage: var('x,y,z')
(x, y, z)
sage: t = x^2 + y; t
x^2 + y
sage: t.is_polynomial(x)
True
sage: t.is_polynomial(y)
True
sage: t.is_polynomial(z)
True
sage: t = sin(x) + y; t
y + sin(x)
sage: t.is_polynomial(x)
False
sage: t.is_polynomial(y)
True
sage: t.is_polynomial(sin(x))
True
TESTS:
Check if we can handle derivatives. trac ticket #6523:
sage: f(x) = function('f',x)
sage: f(x).diff(x).is_zero()
False
Check if trac ticket #11352 is fixed:
sage: el = -1/2*(2*x^2 - sqrt(2*x - 1)*sqrt(2*x + 1) - 1)
sage: el.is_polynomial(x)
False
Return True if this expression is known to be positive.
EXAMPLES:
sage: t0 = SR.symbol("t0", domain='positive')
sage: t0.is_positive()
True
sage: t0.is_negative()
False
sage: t0.is_real()
True
sage: t1 = SR.symbol("t1", domain='positive')
sage: (t0*t1).is_positive()
True
sage: (t0 + t1).is_positive()
True
sage: (t0*x).is_positive()
False
Return True if self is a positive infinite expression.
EXAMPLES:
sage: SR(oo).is_positive_infinity()
True
sage: SR(-oo).is_positive_infinity()
False
sage: x.is_infinity()
False
Return True if this expression is known to be a real number.
EXAMPLES:
sage: t0 = SR.symbol("t0", domain='real')
sage: t0.is_real()
True
sage: t0.is_positive()
False
sage: t1 = SR.symbol("t1", domain='positive')
sage: (t0+t1).is_real()
True
sage: (t0+x).is_real()
False
sage: (t0*t1).is_real()
True
sage: (t0*x).is_real()
False
The following is real, but we cannot deduce that.:
sage: (x*x.conjugate()).is_real()
False
Return True if self is a relational expression.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 == x^2 - 2*x + 3
sage: eqn.is_relational()
True
sage: sin(x).is_relational()
False
Return True if self is a series.
Series are special kinds of symbolic expressions that are constructed via the series() method. They usually have an Order() term unless the series representation is exact, see is_terminating_series().
OUTPUT:
Boolean. Whether self is a series symbolic expression. Usually, this means that it was constructed by the series() method.
Returns False if only a subexpression of the symbolic expression is a series.
EXAMPLES:
sage: SR(5).is_series()
False
sage: var('x')
x
sage: x.is_series()
False
sage: exp(x).is_series()
False
sage: exp(x).series(x,10).is_series()
True
Laurent series are series, too:
sage: laurent_series = (cos(x)/x).series(x, 5)
sage: laurent_series
1*x^(-1) + (-1/2)*x + 1/24*x^3 + Order(x^5)
sage: laurent_series.is_series()
True
Something only containing a series as a subexpression is not a series:
sage: sum_expr = 1 + exp(x).series(x,5); sum_expr
(1 + 1*x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + Order(x^5)) + 1
sage: sum_expr.is_series()
False
Return True if this symbolic expression consists of only a symbol, i.e., a symbolic variable.
EXAMPLES:
sage: x.is_symbol()
True
sage: var('y')
y
sage: y.is_symbol()
True
sage: (x*y).is_symbol()
False
sage: pi.is_symbol()
False
sage: ((x*y)/y).is_symbol()
True
sage: (x^y).is_symbol()
False
Return True if self is a series without order term.
A series is terminating if it can be represented exactly, without requiring an order term. See also is_series() for general series.
OUTPUT:
Boolean. Whether self was constructed by series() and has no order term.
EXAMPLES:
sage: (x^5+x^2+1).series(x,10)
1 + 1*x^2 + 1*x^5
sage: (x^5+x^2+1).series(x,10).is_series()
True
sage: (x^5+x^2+1).series(x,10).is_terminating_series()
True
sage: SR(5).is_terminating_series()
False
sage: var('x')
x
sage: x.is_terminating_series()
False
sage: exp(x).series(x,10).is_terminating_series()
False
Check if this expression is trivially equal to zero without any simplification.
This method is intended to be used in library code where trying to obtain a mathematically correct result by applying potentially expensive rewrite rules is not desirable.
EXAMPLES:
sage: SR(0).is_trivial_zero()
True
sage: SR(0.0).is_trivial_zero()
True
sage: SR(float(0.0)).is_trivial_zero()
True
sage: (SR(1)/2^1000).is_trivial_zero()
False
sage: SR(1./2^10000).is_trivial_zero()
False
The is_zero() method is more capable:
sage: t = pi + (pi - 1)*pi - pi^2
sage: t.is_trivial_zero()
False
sage: t.is_zero()
True
sage: u = sin(x)^2 + cos(x)^2 - 1
sage: u.is_trivial_zero()
False
sage: u.is_zero()
True
Return True if this expression is a unit of the symbolic ring.
EXAMPLES:
sage: SR(1).is_unit()
True
sage: SR(-1).is_unit()
True
sage: SR(0).is_unit()
False
Return an iterator over the operands of this expression.
EXAMPLES:
sage: x,y,z = var('x,y,z')
sage: list((x+y+z).iterator())
[x, y, z]
sage: list((x*y*z).iterator())
[x, y, z]
sage: list((x^y*z*(x+y)).iterator())
[x + y, x^y, z]
Note that symbols, constants and numeric objects do not have operands, so the iterator function raises an error in these cases:
sage: x.iterator()
Traceback (most recent call last):
...
ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands
sage: pi.iterator()
Traceback (most recent call last):
...
ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands
sage: SR(5).iterator()
Traceback (most recent call last):
...
ValueError: expressions containing only a numeric coefficient, constant or symbol have no operands
Return Laplace transform of self. See sage.calculus.calculus.laplace
EXAMPLES:
sage: var('x,s,z')
(x, s, z)
sage: (z + exp(x)).laplace(x, s)
z/s + 1/(s - 1)
Return the lcm of self and b, which must be integers or polynomials over the rational numbers. This is computed from the gcd of self and b implicitly from the relation self * b = gcd(self, b) * lcm(self, b).
Note
In agreement with the convention in use for integers, if self * b == 0, then gcd(self, b) == max(self, b) and lcm(self, b) == 0.
EXAMPLES:
sage: var('x,y')
(x, y)
sage: SR(10).lcm(SR(15))
30
sage: (x^3 - 1).lcm(x-1)
x^3 - 1
sage: (x^3 - 1).lcm(x^2+x+1)
x^3 - 1
sage: (x^3 - sage.symbolic.constants.pi).lcm(x-sage.symbolic.constants.pi)
Traceback (most recent call last):
...
ValueError: lcm: arguments must be polynomials over the rationals
sage: lcm(x^3 - y^3, x-y)
-x^3 + y^3
sage: lcm(x^100-y^100, x^10-y^10)
-x^100 + y^100
sage: lcm(expand( (x^2+17*x+3/7*y)*(x^5 - 17*y + 2/3) ), expand((x^13+17*x+3/7*y)*(x^5 - 17*y + 2/3)) )
1/21*(21*x^18 - 357*x^13*y + 14*x^13 + 357*x^6 + 9*x^5*y -
6069*x*y - 153*y^2 + 238*x + 6*y)*(21*x^7 + 357*x^6 +
9*x^5*y - 357*x^2*y + 14*x^2 - 6069*x*y -
153*y^2 + 238*x + 6*y)/(3*x^5 - 51*y + 2)
TESTS:
Verify that x * y = gcd(x,y) * lcm(x,y):
sage: x, y = var('x,y')
sage: LRs = [(SR(10), SR(15)), (x^3-1, x-1), (x^3-y^3, x-y), (x^3-1, x^2+x+1), (SR(0), x-y)]
sage: all((L.gcd(R) * L.lcm(R)) == L*R for L, R in LRs)
True
Make sure that the convention for what to do with the 0 is being respected:
sage: gcd(x, SR(0)), lcm(x, SR(0))
(x, 0)
sage: gcd(SR(0), SR(0)), lcm(SR(0), SR(0))
(0, 0)
Return the leading coefficient of s in self.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.leading_coefficient(x)
sin(x*y)
sage: f.leading_coefficient(y)
x
sage: f.leading_coefficient(sin(x*y))
x^3 + 2/x
Return the leading coefficient of s in self.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.leading_coefficient(x)
sin(x*y)
sage: f.leading_coefficient(y)
x
sage: f.leading_coefficient(sin(x*y))
x^3 + 2/x
If self is a relational expression, return the left hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 == x^2 - 2*x + 3
sage: eqn.left_hand_side()
(x - 1)^2
sage: eqn.lhs()
(x - 1)^2
sage: eqn.left()
(x - 1)^2
If self is a relational expression, return the left hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 == x^2 - 2*x + 3
sage: eqn.left_hand_side()
(x - 1)^2
sage: eqn.lhs()
(x - 1)^2
sage: eqn.left()
(x - 1)^2
This method is deprecated, please use the .log_gamma() function instead.
Log gamma function evaluated at self.
EXAMPLES:
sage: x.lgamma()
doctest:...: DeprecationWarning: The lgamma() function is deprecated. Use log_gamma() instead.
See http://trac.sagemath.org/6992 for details.
log_gamma(x)
If self is a relational expression, return the left hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 == x^2 - 2*x + 3
sage: eqn.left_hand_side()
(x - 1)^2
sage: eqn.lhs()
(x - 1)^2
sage: eqn.left()
(x - 1)^2
Return a symbolic limit. See sage.calculus.calculus.limit
EXAMPLES:
sage: (sin(x)/x).limit(x=0)
1
Return the logarithm of self.
EXAMPLES:
sage: x, y = var('x, y')
sage: x.log()
log(x)
sage: (x^y + y^x).log()
log(x^y + y^x)
sage: SR(0).log()
-Infinity
sage: SR(-1).log()
I*pi
sage: SR(1).log()
0
sage: SR(1/2).log()
log(1/2)
sage: SR(0.5).log()
-0.693147180559945
sage: SR(0.5).log().exp()
0.500000000000000
sage: math.log(0.5)
-0.6931471805599453
sage: plot(lambda x: SR(x).log(), 0.1,10)
Graphics object consisting of 1 graphics primitive
To prevent automatic evaluation use the hold argument:
sage: I.log()
1/2*I*pi
sage: I.log(hold=True)
log(I)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = I.log(hold=True); a.simplify()
1/2*I*pi
The hold parameter also works in functional notation:
sage: log(-1,hold=True)
log(-1)
sage: log(-1)
I*pi
TESTS:
sage: SR(oo).log()
+Infinity
sage: SR(-oo).log()
+Infinity
sage: SR(unsigned_infinity).log()
+Infinity
Simplify symbolic expression, which can contain logs.
Expands logarithms of powers, logarithms of products and logarithms of quotients. The option algorithm specifies which expression types should be expanded.
INPUT:
self - expression to be simplified
algorithm - (default: ‘products’) optional, governs which expression is expanded. Possible values are
See also examples below.
DETAILS: This uses the Maxima simplifier and sets logexpand option for this simplifier. From the Maxima documentation: “Logexpand:true causes log(a^b) to become b*log(a). If it is set to all, log(a*b) will also simplify to log(a)+log(b). If it is set to super, then log(a/b) will also simplify to log(a)-log(b) for rational numbers a/b, a#1. (log(1/b), for integer b, always simplifies.) If it is set to false, all of these simplifications will be turned off. “
ALIAS: log_expand() and expand_log() are the same
EXAMPLES:
By default powers and products (and quotients) are expanded, but not quotients of integers:
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
To expand also log(3/4) use algorithm='all':
sage: (log(3/4*x^pi)).log_expand('all')
pi*log(x) - log(4) + log(3)
To expand only the power use algorithm='powers'.:
sage: (log(x^6)).log_expand('powers')
6*log(x)
The expression log((3*x)^6) is not expanded with algorithm='powers', since it is converted into product first:
sage: (log((3*x)^6)).log_expand('powers')
log(729*x^6)
This shows that the option algorithm from the previous call has no influence to future calls (we changed some default Maxima flag, and have to ensure that this flag has been restored):
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
sage: (log(3/4*x^pi)).log_expand('all')
pi*log(x) - log(4) + log(3)
sage: (log(3/4*x^pi)).log_expand()
pi*log(x) + log(3/4)
TESTS:
Most of these log expansions only make sense over the reals. So, we should set the Maxima domain variable to ‘real’ before we call out to Maxima. When we return, however, we should set the domain back to what it was, rather than assuming that it was ‘complex’. See trac ticket #12780:
sage: from sage.calculus.calculus import maxima
sage: maxima('domain: real;')
real
sage: x.expand_log()
x
sage: maxima('domain;')
real
sage: maxima('domain: complex;')
complex
AUTHORS:
Return the log gamma function evaluated at self.
This is the logarithm of gamma of self, where
gamma is a complex function such that
equals
.
EXAMPLES:
sage: x = var('x')
sage: x.log_gamma()
log_gamma(x)
sage: SR(2).log_gamma()
0
sage: SR(5).log_gamma()
log(24)
sage: a = SR(5).log_gamma(); a.n()
3.17805383034795
sage: SR(5-1).factorial().log()
log(24)
sage: set_verbose(-1); plot(lambda x: SR(x).log_gamma(), -7,8, plot_points=1000).show()
sage: math.exp(0.5)
1.6487212707001282
sage: plot(lambda x: (SR(x).exp() - SR(-x).exp())/2 - SR(x).sinh(), -1, 1)
Graphics object consisting of 1 graphics primitive
To prevent automatic evaluation use the hold argument:
sage: SR(5).log_gamma(hold=True)
log_gamma(5)
To evaluate again, currently we must use numerical evaluation via n():
sage: a = SR(5).log_gamma(hold=True); a.n()
3.17805383034795
Simplify symbolic expression, which can contain logs.
Recursively scans the expression self, transforming
subexpressions of the form into
and simplifies inside logarithm. User
can specify, which conditions must satisfy
and
to use
this transformation in optional parameter algorithm.
INPUT:
self - expression to be simplified
algorithm - (default: None) optional, governs the condition
on and
which must be satisfied to contract expression
. Values are
See also examples below.
DETAILS: This uses the Maxima logcontract() command. From the Maxima documentation: “Recursively scans the expression expr, transforming subexpressions of the form a1*log(b1) + a2*log(b2) + c into log(ratsimp(b1^a1 * b2^a2)) + c. The user can control which coefficients are contracted by setting the option logconcoeffp to the name of a predicate function of one argument. E.g. if you like to generate SQRTs, you can do logconcoeffp:’logconfun` logconfun(m):=featurep(m,integer) or ratnump(m)` . Then logcontract(1/2*log(x)); will give log(sqrt(x)).”
ALIAS: log_simplify() and simplify_log() are the same
EXAMPLES:
sage: x,y,t=var('x y t')
Only two first terms are contracted in the following example , the logarithm with coefficient 1/2 is not contracted:
sage: f = log(x)+2*log(y)+1/2*log(t)
sage: f.simplify_log()
log(x*y^2) + 1/2*log(t)
To contract all terms in previous example use option algorithm:
sage: f.simplify_log(algorithm='ratios')
log(sqrt(t)*x*y^2)
This shows that the option algorithm from the previous call has no influence to future calls (we changed some default Maxima flag, and have to ensure that this flag has been restored):
sage: f.simplify_log('one')
1/2*log(t) + log(x) + 2*log(y)
sage: f.simplify_log('ratios')
log(sqrt(t)*x*y^2)
sage: f.simplify_log()
log(x*y^2) + 1/2*log(t)
To contract terms with no coefficient (more precisely, with coefficients 1 and -1) use option algorithm:
sage: f = log(x)+2*log(y)-log(t)
sage: f.simplify_log('one')
2*log(y) + log(x/t)
sage: f = log(x)+log(y)-1/3*log((x+1))
sage: f.simplify_log()
log(x*y) - 1/3*log(x + 1)
sage: f.simplify_log('ratios')
log(x*y/(x + 1)^(1/3))
is irrational number, to contract logarithms in the following example
we have to put algorithm to constants or all:
sage: f = log(x)+log(y)-pi*log((x+1))
sage: f.simplify_log('constants')
log(x*y/(x + 1)^pi)
x*log(9) is contracted only if algorithm is all:
sage: (x*log(9)).simplify_log()
x*log(9)
sage: (x*log(9)).simplify_log('all')
log(9^x)
TESTS:
This shows that the issue at trac ticket #7334 is fixed. Maxima intentionally keeps the expression inside the log factored:
sage: log_expr = (log(sqrt(2)-1)+log(sqrt(2)+1))
sage: log_expr.simplify_log('all')
log((sqrt(2) + 1)*(sqrt(2) - 1))
sage: _.simplify_rational()
0
sage: log_expr.simplify_full() # applies both simplify_log and simplify_rational
0
We should use the current simplification domain rather than set it to ‘real’ explicitly (trac ticket #12780):
sage: f = sqrt(x^2)
sage: f.simplify_log()
sqrt(x^2)
sage: from sage.calculus.calculus import maxima
sage: maxima('domain: real;')
real
sage: f.simplify_log()
abs(x)
sage: maxima('domain: complex;')
complex
AUTHORS:
Return the exponent of the lowest nonpositive power of s in self.
OUTPUT:
An integer <= 0.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y^10 + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + 2*sin(x*y)/x + x/y^10 + 100
sage: f.low_degree(x)
-1
sage: f.low_degree(y)
-10
sage: f.low_degree(sin(x*y))
0
sage: (x^3+y).low_degree(x)
0
Check if self matches the given pattern.
INPUT:
OUTPUT:
One of
None if there is no match, or a dictionary mapping the wildcards to the matching values if a match was found. Note that the dictionary is empty if there were no wildcards in the given pattern.
See also http://www.ginac.de/tutorial/Pattern-matching-and-advanced-substitutions.html
EXAMPLES:
sage: var('x,y,z,a,b,c,d,f,g')
(x, y, z, a, b, c, d, f, g)
sage: w0 = SR.wild(0); w1 = SR.wild(1); w2 = SR.wild(2)
sage: ((x+y)^a).match((x+y)^a) # no wildcards, so empty dict
{}
sage: print ((x+y)^a).match((x+y)^b)
None
sage: t = ((x+y)^a).match(w0^w1)
sage: t[w0], t[w1]
(x + y, a)
sage: print ((x+y)^a).match(w0^w0)
None
sage: ((x+y)^(x+y)).match(w0^w0)
{$0: x + y}
sage: t = ((a+b)*(a+c)).match((a+w0)*(a+w1))
sage: t[w0], t[w1]
(c, b)
sage: ((a+b)*(a+c)).match((w0+b)*(w0+c))
{$0: a}
sage: t = ((a+b)*(a+c)).match((w0+w1)*(w0+w2))
sage: t[w0], t[w1], t[w2]
(a, c, b)
sage: print ((a+b)*(a+c)).match((w0+w1)*(w1+w2))
None
sage: t = (a*(x+y)+a*z+b).match(a*w0+w1)
sage: t[w0], t[w1]
(x + y, a*z + b)
sage: print (a+b+c+d+f+g).match(c)
None
sage: (a+b+c+d+f+g).has(c)
True
sage: (a+b+c+d+f+g).match(c+w0)
{$0: a + b + d + f + g}
sage: (a+b+c+d+f+g).match(c+g+w0)
{$0: a + b + d + f}
sage: (a+b).match(a+b+w0)
{$0: 0}
sage: print (a*b^2).match(a^w0*b^w1)
None
sage: (a*b^2).match(a*b^w1)
{$1: 2}
sage: (x*x.arctan2(x^2)).match(w0*w0.arctan2(w0^2))
{$0: x}
Beware that behind-the-scenes simplification can lead to surprising results in matching:
sage: print (x+x).match(w0+w1)
None
sage: t = x+x; t
2*x
sage: t.operator()
<built-in function mul>
Since asking to match w0+w1 looks for an addition operator, there is no match.
Provide easy access to maxima methods, converting the result to a Sage expression automatically.
EXAMPLES:
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
log(sqrt(2) + 1) + log(sqrt(2) - 1)
sage: res = t.maxima_methods().logcontract(); res
log((sqrt(2) + 1)*(sqrt(2) - 1))
sage: type(res)
<type 'sage.symbolic.expression.Expression'>
Return the minimal polynomial of this symbolic expression.
EXAMPLES:
sage: golden_ratio.minpoly()
x^2 - x - 1
Return the product of the current expression and the given arguments.
To prevent automatic evaluation use the hold argument.
EXAMPLES:
sage: x.mul(x)
x^2
sage: x.mul(x, hold=True)
x*x
sage: x.mul(x, (2+x), hold=True)
(x + 2)*x*x
sage: x.mul(x, (2+x), x, hold=True)
(x + 2)*x*x*x
sage: x.mul(x, (2+x), x, 2*x, hold=True)
(2*x)*(x + 2)*x*x*x
To then evaluate again, we currently must use Maxima via simplify():
sage: a = x.mul(x, hold=True); a.simplify()
x^2
Return a relation obtained by multiplying both sides of this relation by x.
Note
The checksign keyword argument is currently ignored and is included for backward compatibility reasons only.
EXAMPLES:
sage: var('x,y'); f = x + 3 < y - 2
(x, y)
sage: f.multiply_both_sides(7)
7*x + 21 < 7*y - 14
sage: f.multiply_both_sides(-1/2)
-1/2*x - 3/2 < -1/2*y + 1
sage: f*(-2/3)
-2/3*x - 2 < -2/3*y + 4/3
sage: f*(-pi)
-pi*(x + 3) < -pi*(y - 2)
Since the direction of the inequality never changes when doing arithmetic with equations, you can multiply or divide the equation by a quantity with unknown sign:
sage: f*(1+I)
(I + 1)*x + 3*I + 3 < (I + 1)*y - 2*I - 2
sage: f = sqrt(2) + x == y^3
sage: f.multiply_both_sides(I)
I*x + I*sqrt(2) == I*y^3
sage: f.multiply_both_sides(-1)
-x - sqrt(2) == -y^3
Note that the direction of the following inequalities is not reversed:
sage: (x^3 + 1 > 2*sqrt(3)) * (-1)
-x^3 - 1 > -2*sqrt(3)
sage: (x^3 + 1 >= 2*sqrt(3)) * (-1)
-x^3 - 1 >= -2*sqrt(3)
sage: (x^3 + 1 <= 2*sqrt(3)) * (-1)
-x^3 - 1 <= -2*sqrt(3)
Return a numerical approximation this symbolic expression as either a real or complex number with at least the requested number of bits or digits of precision.
EXAMPLES:
sage: sin(x).subs(x=5).n()
-0.958924274663138
sage: sin(x).subs(x=5).n(100)
-0.95892427466313846889315440616
sage: sin(x).subs(x=5).n(digits=50)
-0.95892427466313846889315440615599397335246154396460
sage: zeta(x).subs(x=2).numerical_approx(digits=50)
1.6449340668482264364724151666460251892189499012068
sage: cos(3).numerical_approx(200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3),200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3), digits=10)
-0.9899924966
sage: (i + 1).numerical_approx(32)
1.00000000 + 1.00000000*I
sage: (pi + e + sqrt(2)).numerical_approx(100)
7.2740880444219335226246195788
TESTS:
We test the evaluation of different infinities available in Pynac:
sage: t = x - oo; t
-Infinity
sage: t.n()
-infinity
sage: t = x + oo; t
+Infinity
sage: t.n()
+infinity
sage: t = x - unsigned_infinity; t
Infinity
sage: t.n()
Traceback (most recent call last):
...
ValueError: can only convert signed infinity to RR
Some expressions cannot be evaluated numerically:
sage: n(sin(x))
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
sage: a = var('a')
sage: (x^2 + 2*x + 2).subs(x=a).n()
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
Make sure we’ve rounded up log(10,2) enough to guarantee sufficient precision (trac ticket #10164):
sage: ks = 4*10**5, 10**6
sage: all(len(str(e.n(digits=k)))-1 >= k for k in ks)
True
Return the negated version of self, that is the relation that is False iff self is True.
EXAMPLES:
sage: (x < 5).negation()
x >= 5
sage: (x == sin(3)).negation()
x != sin(3)
sage: (2*x >= sqrt(2)).negation()
2*x < sqrt(2)
Compute the numerical integral of self. Please see sage.calculus.calculus.nintegral for more details.
EXAMPLES:
sage: sin(x).nintegral(x,0,3)
(1.989992496600..., 2.209335488557...e-14, 21, 0)
Compute the numerical integral of self. Please see sage.calculus.calculus.nintegral for more details.
EXAMPLES:
sage: sin(x).nintegral(x,0,3)
(1.989992496600..., 2.209335488557...e-14, 21, 0)
Return the number of arguments of this expression.
EXAMPLES:
sage: var('a,b,c,x,y')
(a, b, c, x, y)
sage: a.number_of_operands()
0
sage: (a^2 + b^2 + (x+y)^2).number_of_operands()
3
sage: (a^2).number_of_operands()
2
sage: (a*b^2*c).number_of_operands()
3
Return the complex norm of this symbolic expression, i.e.,
the expression times its complex conjugate. If is a
complex number, then the norm of
is defined as the product of
and its complex conjugate
The norm of a complex number is different from its absolute value.
The absolute value of a complex number is defined to be the square
root of its norm. A typical use of the complex norm is in the
integral domain of Gaussian integers, where the norm of
each Gaussian integer
is defined as its complex norm.
See also
EXAMPLES:
sage: a = 1 + 2*I
sage: a.norm()
5
sage: a = sqrt(2) + 3^(1/3)*I; a
sqrt(2) + I*3^(1/3)
sage: a.norm()
3^(2/3) + 2
sage: CDF(a).norm()
4.080083823051...
sage: CDF(a.norm())
4.080083823051904
Return this expression normalized as a fraction
EXAMPLES:
sage: var('x, y, a, b, c')
(x, y, a, b, c)
sage: g = x + y/(x + 2)
sage: g.normalize()
(x^2 + 2*x + y)/(x + 2)
sage: f = x*(x-1)/(x^2 - 7) + y^2/(x^2-7) + 1/(x+1) + b/a + c/a
sage: f.normalize()
(a*x^3 + b*x^3 + c*x^3 + a*x*y^2 + a*x^2 + b*x^2 + c*x^2 +
a*y^2 - a*x - 7*b*x - 7*c*x - 7*a - 7*b - 7*c)/((x^2 -
7)*a*(x + 1))
ALGORITHM: Uses GiNaC.
EXAMPLES:
sage: x,y = var('x,y')
sage: f = x + y
sage: f.number_of_arguments()
2
sage: g = f.function(x)
sage: g.number_of_arguments()
1
sage: x,y,z = var('x,y,z')
sage: (x+y).number_of_arguments()
2
sage: (x+1).number_of_arguments()
1
sage: (sin(x)+1).number_of_arguments()
1
sage: (sin(z)+x+y).number_of_arguments()
3
sage: (sin(x+y)).number_of_arguments()
2
sage: ( 2^(8/9) - 2^(1/9) )(x-1)
Traceback (most recent call last):
...
ValueError: the number of arguments must be less than or equal to 0
Return the number of arguments of this expression.
EXAMPLES:
sage: var('a,b,c,x,y')
(a, b, c, x, y)
sage: a.number_of_operands()
0
sage: (a^2 + b^2 + (x+y)^2).number_of_operands()
3
sage: (a^2).number_of_operands()
2
sage: (a*b^2*c).number_of_operands()
3
Return the numerator of this symbolic expression
INPUT:
If normalize is True, the expression is first normalized to have it as a fraction before getting the numerator.
If normalize is False, the expression is kept and if it is not a quotient, then this will return the expression itself.
See also
normalize(), denominator(), numerator_denominator(), combine()
EXAMPLES:
sage: a, x, y = var('a,x,y')
sage: f = x*(x-a)/((x^2 - y)*(x-a)); f
x/(x^2 - y)
sage: f.numerator()
x
sage: f.denominator()
x^2 - y
sage: f.numerator(normalize=False)
x
sage: f.denominator(normalize=False)
x^2 - y
sage: y = var('y')
sage: g = x + y/(x + 2); g
x + y/(x + 2)
sage: g.numerator()
x^2 + 2*x + y
sage: g.denominator()
x + 2
sage: g.numerator(normalize=False)
x + y/(x + 2)
sage: g.denominator(normalize=False)
1
TESTS:
sage: ((x+y)^2/(x-y)^3*x^3).numerator(normalize=False)
(x + y)^2*x^3
sage: ((x+y)^2*x^3).numerator(normalize=False)
(x + y)^2*x^3
sage: (y/x^3).numerator(normalize=False)
y
sage: t = y/x^3/(x+y)^(1/2); t
y/(sqrt(x + y)*x^3)
sage: t.numerator(normalize=False)
y
sage: (1/x^3).numerator(normalize=False)
1
sage: (x^3).numerator(normalize=False)
x^3
sage: (y*x^sin(x)).numerator(normalize=False)
Traceback (most recent call last):
...
TypeError: self is not a rational expression
Return the numerator and the denominator of this symbolic expression
INPUT:
If normalize is True, the expression is first normalized to have it as a fraction before getting the numerator and denominator.
If normalize is False, the expression is kept and if it is not a quotient, then this will return the expression itself together with 1.
See also
EXAMPLE:
sage: x, y, a = var("x y a")
sage: ((x+y)^2/(x-y)^3*x^3).numerator_denominator()
((x + y)^2*x^3, (x - y)^3)
sage: ((x+y)^2/(x-y)^3*x^3).numerator_denominator(False)
((x + y)^2*x^3, (x - y)^3)
sage: g = x + y/(x + 2)
sage: g.numerator_denominator()
(x^2 + 2*x + y, x + 2)
sage: g.numerator_denominator(normalize=False)
(x + y/(x + 2), 1)
sage: g = x^2*(x + 2)
sage: g.numerator_denominator()
((x + 2)*x^2, 1)
sage: g.numerator_denominator(normalize=False)
((x + 2)*x^2, 1)
TESTS:
sage: ((x+y)^2/(x-y)^3*x^3).numerator_denominator(normalize=False)
((x + y)^2*x^3, (x - y)^3)
sage: ((x+y)^2*x^3).numerator_denominator(normalize=False)
((x + y)^2*x^3, 1)
sage: (y/x^3).numerator_denominator(normalize=False)
(y, x^3)
sage: t = y/x^3/(x+y)^(1/2); t
y/(sqrt(x + y)*x^3)
sage: t.numerator_denominator(normalize=False)
(y, sqrt(x + y)*x^3)
sage: (1/x^3).numerator_denominator(normalize=False)
(1, x^3)
sage: (x^3).numerator_denominator(normalize=False)
(x^3, 1)
sage: (y*x^sin(x)).numerator_denominator(normalize=False)
Traceback (most recent call last):
...
TypeError: self is not a rational expression
Return a numerical approximation this symbolic expression as either a real or complex number with at least the requested number of bits or digits of precision.
EXAMPLES:
sage: sin(x).subs(x=5).n()
-0.958924274663138
sage: sin(x).subs(x=5).n(100)
-0.95892427466313846889315440616
sage: sin(x).subs(x=5).n(digits=50)
-0.95892427466313846889315440615599397335246154396460
sage: zeta(x).subs(x=2).numerical_approx(digits=50)
1.6449340668482264364724151666460251892189499012068
sage: cos(3).numerical_approx(200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3),200)
-0.98999249660044545727157279473126130239367909661558832881409
sage: numerical_approx(cos(3), digits=10)
-0.9899924966
sage: (i + 1).numerical_approx(32)
1.00000000 + 1.00000000*I
sage: (pi + e + sqrt(2)).numerical_approx(100)
7.2740880444219335226246195788
TESTS:
We test the evaluation of different infinities available in Pynac:
sage: t = x - oo; t
-Infinity
sage: t.n()
-infinity
sage: t = x + oo; t
+Infinity
sage: t.n()
+infinity
sage: t = x - unsigned_infinity; t
Infinity
sage: t.n()
Traceback (most recent call last):
...
ValueError: can only convert signed infinity to RR
Some expressions cannot be evaluated numerically:
sage: n(sin(x))
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
sage: a = var('a')
sage: (x^2 + 2*x + 2).subs(x=a).n()
Traceback (most recent call last):
...
TypeError: cannot evaluate symbolic expression numerically
Make sure we’ve rounded up log(10,2) enough to guarantee sufficient precision (trac ticket #10164):
sage: ks = 4*10**5, 10**6
sage: all(len(str(e.n(digits=k)))-1 >= k for k in ks)
True
Return a list containing the operands of this expression.
EXAMPLES:
sage: var('a,b,c,x,y')
(a, b, c, x, y)
sage: (a^2 + b^2 + (x+y)^2).operands()
[a^2, b^2, (x + y)^2]
sage: (a^2).operands()
[a, 2]
sage: (a*b^2*c).operands()
[a, b^2, c]
Return the topmost operator in this expression.
EXAMPLES:
sage: x,y,z = var('x,y,z')
sage: (x+y).operator()
<built-in function add>
sage: (x^y).operator()
<built-in function pow>
sage: (x^y * z).operator()
<built-in function mul>
sage: (x < y).operator()
<built-in function lt>
sage: abs(x).operator()
abs
sage: r = gamma(x).operator(); type(r)
<class 'sage.functions.other.Function_gamma'>
sage: psi = function('psi', nargs=1)
sage: psi(x).operator()
psi
sage: r = psi(x).operator()
sage: r == psi
True
sage: f = function('f', nargs=1, conjugate_func=lambda self, x: 2*x)
sage: nf = f(x).operator()
sage: nf(x).conjugate()
2*x
sage: f = function('f')
sage: a = f(x).diff(x); a
D[0](f)(x)
sage: a.operator()
D[0](f)
TESTS:
sage: (x <= y).operator()
<built-in function le>
sage: (x == y).operator()
<built-in function eq>
sage: (x != y).operator()
<built-in function ne>
sage: (x > y).operator()
<built-in function gt>
sage: (x >= y).operator()
<built-in function ge>
sage: SR._force_pyobject( (x, x + 1, x + 2) ).operator()
<type 'tuple'>
Return the partial fraction expansion of self with respect to the given variable.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: f = x^2/(x+1)^3
sage: f.partial_fraction()
1/(x + 1) - 2/(x + 1)^2 + 1/(x + 1)^3
sage: f.partial_fraction()
1/(x + 1) - 2/(x + 1)^2 + 1/(x + 1)^3
Notice that the first variable in the expression is used by default:
sage: y = var('y')
sage: f = y^2/(y+1)^3
sage: f.partial_fraction()
1/(y + 1) - 2/(y + 1)^2 + 1/(y + 1)^3
sage: f = y^2/(y+1)^3 + x/(x-1)^3
sage: f.partial_fraction()
y^2/(y^3 + 3*y^2 + 3*y + 1) + 1/(x - 1)^2 + 1/(x - 1)^3
You can explicitly specify which variable is used:
sage: f.partial_fraction(y)
x/(x^3 - 3*x^2 + 3*x - 1) + 1/(y + 1) - 2/(y + 1)^2 + 1/(y + 1)^3
Plot a symbolic expression. All arguments are passed onto the standard plot command.
EXAMPLES:
This displays a straight line:
sage: sin(2).plot((x,0,3))
Graphics object consisting of 1 graphics primitive
This draws a red oscillatory curve:
sage: sin(x^2).plot((x,0,2*pi), rgbcolor=(1,0,0))
Graphics object consisting of 1 graphics primitive
Another plot using the variable theta:
sage: var('theta')
theta
sage: (cos(theta) - erf(theta)).plot((theta,-2*pi,2*pi))
Graphics object consisting of 1 graphics primitive
A very thick green plot with a frame:
sage: sin(x).plot((x,-4*pi, 4*pi), thickness=20, rgbcolor=(0,0.7,0)).show(frame=True)
You can embed 2d plots in 3d space as follows:
sage: plot(sin(x^2), (x,-pi, pi), thickness=2).plot3d(z = 1)
Graphics3d Object
A more complicated family:
sage: G = sum([plot(sin(n*x), (x,-2*pi, 2*pi)).plot3d(z=n) for n in [0,0.1,..1]])
sage: G.show(frame_aspect_ratio=[1,1,1/2]) # long time (5s on sage.math, 2012)
A plot involving the floor function:
sage: plot(1.0 - x * floor(1/x), (x,0.00001,1.0))
Graphics object consisting of 1 graphics primitive
Sage used to allow symbolic functions with “no arguments”; this no longer works:
sage: plot(2*sin, -4, 4)
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for '*': 'Integer Ring' and '<class 'sage.functions.trig.Function_sin'>'
You should evaluate the function first:
sage: plot(2*sin(x), -4, 4)
Graphics object consisting of 1 graphics primitive
TESTS:
sage: f(x) = x*(1 - x)
sage: plot(f,0,1)
Graphics object consisting of 1 graphics primitive
Express this symbolic expression as a polynomial in x. If this is not a polynomial in x, then some coefficients may be functions of x.
Warning
This is different from polynomial() which returns a Sage polynomial over a given base ring.
EXAMPLES:
sage: var('a, x')
(a, x)
sage: p = expand((x-a*sqrt(2))^2 + x + 1); p
-2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1
sage: p.poly(a)
-2*sqrt(2)*a*x + 2*a^2 + x^2 + x + 1
sage: bool(p.poly(a) == (x-a*sqrt(2))^2 + x + 1)
True
sage: p.poly(x)
2*a^2 - (2*sqrt(2)*a - 1)*x + x^2 + 1
Return this symbolic expression as an algebraic polynomial over the given base ring, if possible.
The point of this function is that it converts purely symbolic polynomials into optimised algebraic polynomials over a given base ring.
You can specify either the base ring (base_ring) you want the output polynomial to be over, or you can specify the full polynomial ring (ring) you want the output polynomial to be an element of.
INPUT:
Warning
This is different from poly() which is used to rewrite self as a polynomial in terms of one of the variables.
EXAMPLES:
sage: f = x^2 -2/3*x + 1
sage: f.polynomial(QQ)
x^2 - 2/3*x + 1
sage: f.polynomial(GF(19))
x^2 + 12*x + 1
Polynomials can be useful for getting the coefficients of an expression:
sage: g = 6*x^2 - 5
sage: g.coefficients()
[[-5, 0], [6, 2]]
sage: g.polynomial(QQ).list()
[-5, 0, 6]
sage: g.polynomial(QQ).dict()
{0: -5, 2: 6}
sage: f = x^2*e + x + pi/e
sage: f.polynomial(RDF)
2.718281828459045*x^2 + x + 1.1557273497909217
sage: g = f.polynomial(RR); g
2.71828182845905*x^2 + x + 1.15572734979092
sage: g.parent()
Univariate Polynomial Ring in x over Real Field with 53 bits of precision
sage: f.polynomial(RealField(100))
2.7182818284590452353602874714*x^2 + x + 1.1557273497909217179100931833
sage: f.polynomial(CDF)
2.718281828459045*x^2 + x + 1.1557273497909217
sage: f.polynomial(CC)
2.71828182845905*x^2 + x + 1.15572734979092
We coerce a multivariate polynomial with complex symbolic coefficients:
sage: x, y, n = var('x, y, n')
sage: f = pi^3*x - y^2*e - I; f
pi^3*x - y^2*e - I
sage: f.polynomial(CDF)
(-2.71828182846)*y^2 + 31.0062766803*x - 1.0*I
sage: f.polynomial(CC)
(-2.71828182845905)*y^2 + 31.0062766802998*x - 1.00000000000000*I
sage: f.polynomial(ComplexField(70))
(-2.7182818284590452354)*y^2 + 31.006276680299820175*x - 1.0000000000000000000*I
Another polynomial:
sage: f = sum((e*I)^n*x^n for n in range(5)); f
x^4*e^4 - I*x^3*e^3 - x^2*e^2 + I*x*e + 1
sage: f.polynomial(CDF)
54.598150033144236*x^4 - 20.085536923187668*I*x^3 - 7.38905609893065*x^2 + 2.718281828459045*I*x + 1.0
sage: f.polynomial(CC)
54.5981500331442*x^4 - 20.0855369231877*I*x^3 - 7.38905609893065*x^2 + 2.71828182845905*I*x + 1.00000000000000
A multivariate polynomial over a finite field:
sage: f = (3*x^5 - 5*y^5)^7; f
(3*x^5 - 5*y^5)^7
sage: g = f.polynomial(GF(7)); g
3*x^35 + 2*y^35
sage: parent(g)
Multivariate Polynomial Ring in x, y over Finite Field of size 7
We check to make sure constants are converted appropriately:
sage: (pi*x).polynomial(SR)
pi*x
Using the ring parameter, you can also create polynomials rings over the symbolic ring where only certain variables are considered generators of the polynomial ring and the others are considered “constants”:
sage: a, x, y = var('a,x,y')
sage: f = a*x^10*y+3*x
sage: B = f.polynomial(ring=SR['x,y'])
sage: B.coefficients()
[a, 3]
Return the current expression to the power exp.
To prevent automatic evaluation use the hold argument.
EXAMPLES:
sage: (x^2).power(2)
x^4
sage: (x^2).power(2, hold=True)
(x^2)^2
To then evaluate again, we currently must use Maxima via simplify():
sage: a = (x^2).power(2, hold=True); a.simplify()
x^4
Return algebraic power series associated to this symbolic expression, which must be a polynomial in one variable, with coefficients coercible to the base ring.
The power series is truncated one more than the degree.
EXAMPLES:
sage: theta = var('theta')
sage: f = theta^3 + (1/3)*theta - 17/3
sage: g = f.power_series(QQ); g
-17/3 + 1/3*theta + theta^3 + O(theta^4)
sage: g^3
-4913/27 + 289/9*theta - 17/9*theta^2 + 2602/27*theta^3 + O(theta^4)
sage: g.parent()
Power Series Ring in theta over Rational Field
Return the primitive polynomial of this expression when considered as a polynomial in s.
See also unit(), content(), and unit_content_primitive().
INPUT:
OUTPUT:
The primitive polynomial as a symbolic expression. It is defined as the quotient by the unit() and content() parts (with respect to the variable s).
EXAMPLES:
sage: (2*x+4).primitive_part(x)
x + 2
sage: (2*x+1).primitive_part(x)
2*x + 1
sage: (2*x+1/2).primitive_part(x)
4*x + 1
sage: var('y')
y
sage: (2*x + 4*sin(y)).primitive_part(sin(y))
x + 2*sin(y)
Get the underlying Python object.
OUTPUT:
The Python object corresponding to this expression, assuming this expression is a single numerical value or an infinity representable in Python. Otherwise, a TypeError is raised.
EXAMPLES:
sage: var('x')
x
sage: b = -17/3
sage: a = SR(b)
sage: a.pyobject()
-17/3
sage: a.pyobject() is b
True
TESTS:
sage: SR(oo).pyobject()
+Infinity
sage: SR(-oo).pyobject()
-Infinity
sage: SR(unsigned_infinity).pyobject()
Infinity
sage: SR(I*oo).pyobject()
Traceback (most recent call last):
...
TypeError: Python infinity cannot have complex phase.
Simplify this symbolic expression, which can contain logs, exponentials, and radicals, by trying to convert it into a canonical form over a large class of expressions and a given ordering of variables.
Warning
As shown in the examples below, a canonical form is not always returned, i.e., two mathematically identical expressions might be simplified to different expressions.
ALGORITHM:
This uses the Maxima radcan() command. From the Maxima documentation: “All functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, produces a regular form. Two equivalent expressions in this class do not necessarily have the same appearance, but their difference can be simplified by radcan to zero. For some expressions radcan is quite time consuming. This is the cost of exploring certain relationships among the components of the expression for simplifications based on factoring and partial fraction expansions of exponents.”
Note
radical_simplify(), simplify_radical(), exp_simplify(), simplify_exp() are all the same.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = log(x*y)
sage: f.simplify_radical()
log(x) + log(y)
sage: f = log(8)/log(2)
sage: f.simplify_radical()
3
sage: f = (log(x+x^2)-log(x))^a/log(1+x)^(a/2)
sage: f.simplify_radical()
log(x + 1)^(1/2*a)
sage: f = (e^x-1)/(1+e^(x/2))
sage: f.simplify_exp()
e^(1/2*x) - 1
The example below shows two expressions e1 and e2 which are “simplified” to different expressions, while their difference is “simplified” to zero, thus simplify_radical does not return a canonical form, except maybe for 0.
sage: e1 = 1/(sqrt(5)+sqrt(2))
sage: e2 = (sqrt(5)-sqrt(2))/3
sage: e1.simplify_radical()
1/(sqrt(5) + sqrt(2))
sage: e2.simplify_radical()
1/3*sqrt(5) - 1/3*sqrt(2)
sage: (e1-e2).simplify_radical()
0
TESTS:
This tests that trac ticket #11668 has been fixed (by trac ticket #12780):
sage: a,b = var('a b')
sage: A = abs((a+I*b))^2
sage: A.simplify_radical()
abs(a + I*b)^2
sage: imag(A)
0
sage: imag(A.simplify_radical())
0
Expand this symbolic expression. Products of sums and exponentiated sums are multiplied out, numerators of rational expressions which are sums are split into their respective terms, and multiplications are distributed over addition at all levels.
EXAMPLES:
We expand the expression using both
method and functional notation.
sage: x,y = var('x,y')
sage: a = (x-y)^5
sage: a.expand()
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
sage: expand(a)
x^5 - 5*x^4*y + 10*x^3*y^2 - 10*x^2*y^3 + 5*x*y^4 - y^5
We expand some other expressions:
sage: expand((x-1)^3/(y-1))
x^3/(y - 1) - 3*x^2/(y - 1) + 3*x/(y - 1) - 1/(y - 1)
sage: expand((x+sin((x+y)^2))^2)
x^2 + 2*x*sin((x + y)^2) + sin((x + y)^2)^2
We can expand individual sides of a relation:
sage: a = (16*x-13)^2 == (3*x+5)^2/2
sage: a.expand()
256*x^2 - 416*x + 169 == 9/2*x^2 + 15*x + 25/2
sage: a.expand('left')
256*x^2 - 416*x + 169 == 1/2*(3*x + 5)^2
sage: a.expand('right')
(16*x - 13)^2 == 9/2*x^2 + 15*x + 25/2
TESTS:
sage: var('x,y')
(x, y)
sage: ((x + (2/3)*y)^3).expand()
x^3 + 2*x^2*y + 4/3*x*y^2 + 8/27*y^3
sage: expand( (x*sin(x) - cos(y)/x)^2 )
x^2*sin(x)^2 - 2*cos(y)*sin(x) + cos(y)^2/x^2
sage: f = (x-y)*(x+y); f
(x + y)*(x - y)
sage: f.expand()
x^2 - y^2
Simplify rational expressions.
INPUT:
ALIAS: rational_simplify() and simplify_rational() are the same
DETAILS: We call Maxima functions ratsimp, fullratsimp and xthru. If each part of the expression has to be simplified separately, we use Maxima function map.
EXAMPLES:
sage: f = sin(x/(x^2 + x))
sage: f
sin(x/(x^2 + x))
sage: f.simplify_rational()
sin(1/(x + 1))
sage: f = ((x - 1)^(3/2) - (x + 1)*sqrt(x - 1))/sqrt((x - 1)*(x + 1)); f
-((x + 1)*sqrt(x - 1) - (x - 1)^(3/2))/sqrt((x + 1)*(x - 1))
sage: f.simplify_rational()
-2*sqrt(x - 1)/sqrt(x^2 - 1)
With map=True each term in a sum is simplified separately and thus the resuls are shorter for functions which are combination of rational and nonrational funtions. In the following example, we use this option if we want not to combine logarithm and the rational function into one fraction:
sage: f=(x^2-1)/(x+1)-ln(x)/(x+2)
sage: f.simplify_rational()
(x^2 + x - log(x) - 2)/(x + 2)
sage: f.simplify_rational(map=True)
x - log(x)/(x + 2) - 1
Here is an example from the Maxima documentation of where algorithm='simple' produces an (possibly useful) intermediate step:
sage: y = var('y')
sage: g = (x^(y/2) + 1)^2*(x^(y/2) - 1)^2/(x^y - 1)
sage: g.simplify_rational(algorithm='simple')
(x^(2*y) - 2*x^y + 1)/(x^y - 1)
sage: g.simplify_rational()
x^y - 1
With option algorithm='noexpand' we only convert to common denominators and add. No expansion of products is performed:
sage: f=1/(x+1)+x/(x+2)^2
sage: f.simplify_rational()
(2*x^2 + 5*x + 4)/(x^3 + 5*x^2 + 8*x + 4)
sage: f.simplify_rational(algorithm='noexpand')
((x + 2)^2 + (x + 1)*x)/((x + 2)^2*(x + 1))
Return the real part of this symbolic expression.
EXAMPLES:
sage: x = var('x')
sage: x.real_part()
real_part(x)
sage: SR(2+3*I).real_part()
2
sage: SR(CDF(2,3)).real_part()
2.0
sage: SR(CC(2,3)).real_part()
2.00000000000000
sage: f = log(x)
sage: f.real_part()
log(abs(x))
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(2).real_part()
2
sage: SR(2).real_part(hold=True)
real_part(2)
This also works using functional notation:
sage: real_part(I,hold=True)
real_part(I)
sage: real_part(I)
0
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(2).real_part(hold=True); a.simplify()
2
Return the real part of this symbolic expression.
EXAMPLES:
sage: x = var('x')
sage: x.real_part()
real_part(x)
sage: SR(2+3*I).real_part()
2
sage: SR(CDF(2,3)).real_part()
2.0
sage: SR(CC(2,3)).real_part()
2.00000000000000
sage: f = log(x)
sage: f.real_part()
log(abs(x))
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(2).real_part()
2
sage: SR(2).real_part(hold=True)
real_part(2)
This also works using functional notation:
sage: real_part(I,hold=True)
real_part(I)
sage: real_part(I)
0
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(2).real_part(hold=True); a.simplify()
2
Convert this symbolic expression to rectangular form; that
is, the form where
and
are real numbers and
is the imaginary unit.
Note
The name “rectangular” comes from the fact that, in the
complex plane, and
are perpendicular.
INPUT:
OUTPUT:
A new expression, equivalent to the original, but expressed in
the form .
ALGORITHM:
We call Maxima’s rectform() and return the result unmodified.
EXAMPLES:
The exponential form of :
sage: f = (e^(I*x) - e^(-I*x)) / (2*I)
sage: f.rectform()
sin(x)
And :
sage: f = (e^(I*x) + e^(-I*x)) / 2
sage: f.rectform()
cos(x)
In some cases, this will simplify the given expression. For
example, here, ,
should cancel
leaving only
which can then be simplified:
sage: k = var('k')
sage: assume(k, 'integer')
sage: f = e^(I*pi*k)
sage: f.rectform()
(-1)^k
However, in general, the resulting expression may be more complicated than the original:
sage: f = e^(I*x)
sage: f.rectform()
cos(x) + I*sin(x)
TESTS:
If the expression is already in rectangular form, it should be left alone:
sage: a,b = var('a,b')
sage: assume((a, 'real'), (b, 'real'))
sage: f = a + b*I
sage: f.rectform()
a + I*b
sage: forget()
We can check with specific real numbers:
sage: a = RR.random_element()
sage: b = RR.random_element()
sage: f = a + b*I
sage: bool(f.rectform() == a + b*I)
True
If we decompose a complex number into its real and imaginary parts, they should correspond to the real and imaginary terms of the rectangular form:
sage: z = CC.random_element()
sage: a = z.real_part()
sage: b = z.imag_part()
sage: bool(SR(z).rectform() == a + b*I)
True
Combine products and powers of trigonometric and hyperbolic sin’s and cos’s of x into those of multiples of x. It also tries to eliminate these functions when they occur in denominators.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: y=var('y')
sage: f=sin(x)*cos(x)^3+sin(y)^2
sage: f.reduce_trig()
-1/2*cos(2*y) + 1/8*sin(4*x) + 1/4*sin(2*x) + 1/2
To reduce only the expressions involving x we use optional parameter:
sage: f.reduce_trig(x)
sin(y)^2 + 1/8*sin(4*x) + 1/4*sin(2*x)
ALIASES: trig_reduce() and reduce_trig() are the same
Calculate the residue of self with respect to symbol.
INPUT:
OUTPUT:
The residue of self.
Say, symbol is x == a, then this function calculates
the residue of self at , i.e., the coefficient of
of the series expansion of self around
.
EXAMPLES:
sage: (1/x).residue(x == 0)
1
sage: (1/x).residue(x == oo)
-1
sage: (1/x^2).residue(x == 0)
0
sage: (1/sin(x)).residue(x == 0)
1
sage: var('q, n, z')
(q, n, z)
sage: (-z^(-n-1)/(1-z/q)^2).residue(z == q).simplify_full()
(n + 1)/q^n
sage: var('s')
s
sage: zeta(s).residue(s == 1) # not tested - #15846
1
TESTS:
sage: (exp(x)/sin(x)^4).residue(x == 0)
5/6
If self is a relational expression, return the right hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 <= x^2 - 2*x + 3
sage: eqn.right_hand_side()
x^2 - 2*x + 3
sage: eqn.rhs()
x^2 - 2*x + 3
sage: eqn.right()
x^2 - 2*x + 3
If self is a relational expression, return the right hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 <= x^2 - 2*x + 3
sage: eqn.right_hand_side()
x^2 - 2*x + 3
sage: eqn.rhs()
x^2 - 2*x + 3
sage: eqn.right()
x^2 - 2*x + 3
If self is a relational expression, return the right hand side of the relation. Otherwise, raise a ValueError.
EXAMPLES:
sage: x = var('x')
sage: eqn = (x-1)^2 <= x^2 - 2*x + 3
sage: eqn.right_hand_side()
x^2 - 2*x + 3
sage: eqn.rhs()
x^2 - 2*x + 3
sage: eqn.right()
x^2 - 2*x + 3
Return roots of self that can be found exactly, possibly with multiplicities. Not all roots are guaranteed to be found.
Warning
This is not a numerical solver - use find_root to solve for self == 0 numerically on an interval.
INPUT:
OUTPUT:
A list of pairs (root, multiplicity) or list of roots.
If there are infinitely many roots, e.g., a function like
, only one is returned.
EXAMPLES:
sage: var('x, a')
(x, a)
A simple example:
sage: ((x^2-1)^2).roots()
[(-1, 2), (1, 2)]
sage: ((x^2-1)^2).roots(multiplicities=False)
[-1, 1]
A complicated example:
sage: f = expand((x^2 - 1)^3*(x^2 + 1)*(x-a)); f
-a*x^8 + x^9 + 2*a*x^6 - 2*x^7 - 2*a*x^2 + 2*x^3 + a - x
The default variable is , since it is the first in
alphabetical order:
sage: f.roots()
[(x, 1)]
As a polynomial in ,
is indeed a root:
sage: f.poly(a)
x^9 - 2*x^7 + 2*x^3 - (x^8 - 2*x^6 + 2*x^2 - 1)*a - x
sage: f(a=x)
0
The roots in terms of are what we expect:
sage: f.roots(x)
[(a, 1), (-I, 1), (I, 1), (1, 3), (-1, 3)]
Only one root of is given:
sage: f = sin(x)
sage: f.roots(x)
[(0, 1)]
Note
It is possible to solve a greater variety of equations using solve() and the keyword to_poly_solve, but only at the price of possibly encountering approximate solutions. See documentation for f.solve for more details.
We derive the roots of a general quadratic polynomial:
sage: var('a,b,c,x')
(a, b, c, x)
sage: (a*x^2 + b*x + c).roots(x)
[(-1/2*(b + sqrt(b^2 - 4*a*c))/a, 1), (-1/2*(b - sqrt(b^2 - 4*a*c))/a, 1)]
By default, all the roots are required to be explicit rather than implicit. To get implicit roots, pass explicit_solutions=False to .roots()
sage: var('x')
x
sage: f = x^(1/9) + (2^(8/9) - 2^(1/9))*(x - 1) - x^(8/9)
sage: f.roots()
Traceback (most recent call last):
...
RuntimeError: no explicit roots found
sage: f.roots(explicit_solutions=False)
[((2^(8/9) + x^(8/9) - 2^(1/9) - x^(1/9))/(2^(8/9) - 2^(1/9)), 1)]
Another example, but involving a degree 5 poly whose roots do not get computed explicitly:
sage: f = x^5 + x^3 + 17*x + 1
sage: f.roots()
Traceback (most recent call last):
...
RuntimeError: no explicit roots found
sage: f.roots(explicit_solutions=False)
[(x^5 + x^3 + 17*x + 1, 1)]
sage: f.roots(explicit_solutions=False, multiplicities=False)
[x^5 + x^3 + 17*x + 1]
Now let us find some roots over different rings:
sage: f.roots(ring=CC)
[(-0.0588115223184..., 1), (-1.331099917875... - 1.52241655183732*I, 1), (-1.331099917875... + 1.52241655183732*I, 1), (1.36050567903502 - 1.51880872209965*I, 1), (1.36050567903502 + 1.51880872209965*I, 1)]
sage: (2.5*f).roots(ring=RR)
[(-0.058811522318449..., 1)]
sage: f.roots(ring=CC, multiplicities=False)
[-0.05881152231844..., -1.331099917875... - 1.52241655183732*I, -1.331099917875... + 1.52241655183732*I, 1.36050567903502 - 1.51880872209965*I, 1.36050567903502 + 1.51880872209965*I]
sage: f.roots(ring=QQ)
[]
sage: f.roots(ring=QQbar, multiplicities=False)
[-0.05881152231844944?, -1.331099917875796? - 1.522416551837318?*I, -1.331099917875796? + 1.522416551837318?*I, 1.360505679035020? - 1.518808722099650?*I, 1.360505679035020? + 1.518808722099650?*I]
Root finding over finite fields:
sage: f.roots(ring=GF(7^2, 'a'))
[(3, 1), (4*a + 6, 2), (3*a + 3, 2)]
TESTS:
sage: (sqrt(3) * f).roots(ring=QQ)
Traceback (most recent call last):
...
TypeError: unable to convert sqrt(3) to a rational
Check if trac ticket #9538 is fixed:
sage: var('f6,f5,f4,x')
(f6, f5, f4, x)
sage: e=15*f6*x^2 + 5*f5*x + f4
sage: res = e.roots(x); res
[(-1/30*(5*f5 + sqrt(25*f5^2 - 60*f4*f6))/f6, 1), (-1/30*(5*f5 - sqrt(25*f5^2 - 60*f4*f6))/f6, 1)]
sage: e.subs(x=res[0][0]).is_zero()
True
Round this expression to the nearest integer.
EXAMPLES:
sage: u = sqrt(43203735824841025516773866131535024)
sage: u.round()
207855083711803945
sage: t = sqrt(Integer('1'*1000)).round(); print str(t)[-10:]
3333333333
sage: (-sqrt(110)).round()
-10
sage: (-sqrt(115)).round()
-11
sage: (sqrt(-3)).round()
Traceback (most recent call last):
...
ValueError: could not convert sqrt(-3) to a real number
Return the power series expansion of self in terms of the given variable to the given order.
INPUT:
OUTPUT:
A power series.
To truncate the power series and obtain a normal expression, use the truncate() command.
EXAMPLES:
We expand a polynomial in about 0, about
, and also truncate
it back to a polynomial:
sage: var('x,y')
(x, y)
sage: f = (x^3 - sin(y)*x^2 - 5*x + 3); f
x^3 - x^2*sin(y) - 5*x + 3
sage: g = f.series(x, 4); g
3 + (-5)*x + (-sin(y))*x^2 + 1*x^3
sage: g.truncate()
x^3 - x^2*sin(y) - 5*x + 3
sage: g = f.series(x==1, 4); g
(-sin(y) - 1) + (-2*sin(y) - 2)*(x - 1) + (-sin(y) + 3)*(x - 1)^2 + 1*(x - 1)^3
sage: h = g.truncate(); h
(x - 1)^3 - (x - 1)^2*(sin(y) - 3) - 2*(x - 1)*(sin(y) + 1) - sin(y) - 1
sage: h.expand()
x^3 - x^2*sin(y) - 5*x + 3
We computer another series expansion of an analytic function:
sage: f = sin(x)/x^2
sage: f.series(x,7)
1*x^(-1) + (-1/6)*x + 1/120*x^3 + (-1/5040)*x^5 + Order(x^7)
sage: f.series(x==1,3)
(sin(1)) + (cos(1) - 2*sin(1))*(x - 1) + (-2*cos(1) + 5/2*sin(1))*(x - 1)^2 + Order((x - 1)^3)
sage: f.series(x==1,3).truncate().expand()
-2*x^2*cos(1) + 5/2*x^2*sin(1) + 5*x*cos(1) - 7*x*sin(1) - 3*cos(1) + 11/2*sin(1)
Following the GiNaC tutorial, we use John Machin’s amazing
formula to compute
digits of
. We expand the arc tangent around 0 and insert
the fractions 1/5 and 1/239.
sage: x = var('x')
sage: f = atan(x).series(x, 10); f
1*x + (-1/3)*x^3 + 1/5*x^5 + (-1/7)*x^7 + 1/9*x^9 + Order(x^10)
sage: float(16*f.subs(x==1/5) - 4*f.subs(x==1/239))
3.1415926824043994
TESTS:
Check if trac ticket #8943 is fixed:
sage: ((1+arctan(x))**(1/x)).series(x==0, 3)
(e) + (-1/2*e)*x + (1/8*e)*x^2 + Order(x^3)
Show this symbolic expression, i.e., typeset it nicely.
EXAMPLES:
sage: (x^2 + 1).show()
x^{2} + 1
Return a simplified version of this symbolic expression.
Note
Currently, this just sends the expression to Maxima and converts it back to Sage.
See also
simplify_full(), simplify_trig(), simplify_rational(), simplify_radical(), simplify_factorial(), simplify_log()
EXAMPLES:
sage: a = var('a'); f = x*sin(2)/(x^a); f
x*sin(2)/x^a
sage: f.simplify()
x^(-a + 1)*sin(2)
TESTS:
Check that trac ticket #14637 is fixed:
sage: assume(x > 0, x < pi/2)
sage: acos(cos(x)).simplify()
x
sage: forget()
Simplify this symbolic expression, which can contain logs, exponentials, and radicals, by trying to convert it into a canonical form over a large class of expressions and a given ordering of variables.
Warning
As shown in the examples below, a canonical form is not always returned, i.e., two mathematically identical expressions might be simplified to different expressions.
ALGORITHM:
This uses the Maxima radcan() command. From the Maxima documentation: “All functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, produces a regular form. Two equivalent expressions in this class do not necessarily have the same appearance, but their difference can be simplified by radcan to zero. For some expressions radcan is quite time consuming. This is the cost of exploring certain relationships among the components of the expression for simplifications based on factoring and partial fraction expansions of exponents.”
Note
radical_simplify(), simplify_radical(), exp_simplify(), simplify_exp() are all the same.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = log(x*y)
sage: f.simplify_radical()
log(x) + log(y)
sage: f = log(8)/log(2)
sage: f.simplify_radical()
3
sage: f = (log(x+x^2)-log(x))^a/log(1+x)^(a/2)
sage: f.simplify_radical()
log(x + 1)^(1/2*a)
sage: f = (e^x-1)/(1+e^(x/2))
sage: f.simplify_exp()
e^(1/2*x) - 1
The example below shows two expressions e1 and e2 which are “simplified” to different expressions, while their difference is “simplified” to zero, thus simplify_radical does not return a canonical form, except maybe for 0.
sage: e1 = 1/(sqrt(5)+sqrt(2))
sage: e2 = (sqrt(5)-sqrt(2))/3
sage: e1.simplify_radical()
1/(sqrt(5) + sqrt(2))
sage: e2.simplify_radical()
1/3*sqrt(5) - 1/3*sqrt(2)
sage: (e1-e2).simplify_radical()
0
TESTS:
This tests that trac ticket #11668 has been fixed (by trac ticket #12780):
sage: a,b = var('a b')
sage: A = abs((a+I*b))^2
sage: A.simplify_radical()
abs(a + I*b)^2
sage: imag(A)
0
sage: imag(A.simplify_radical())
0
Simplify by combining expressions with factorials, and by expanding binomials into factorials.
ALIAS: factorial_simplify and simplify_factorial are the same
EXAMPLES:
Some examples are relatively clear:
sage: var('n,k')
(n, k)
sage: f = factorial(n+1)/factorial(n); f
factorial(n + 1)/factorial(n)
sage: f.simplify_factorial()
n + 1
sage: f = factorial(n)*(n+1); f
(n + 1)*factorial(n)
sage: simplify(f)
(n + 1)*factorial(n)
sage: f.simplify_factorial()
factorial(n + 1)
sage: f = binomial(n, k)*factorial(k)*factorial(n-k); f
binomial(n, k)*factorial(k)*factorial(-k + n)
sage: f.simplify_factorial()
factorial(n)
A more complicated example, which needs further processing:
sage: f = factorial(x)/factorial(x-2)/2 + factorial(x+1)/factorial(x)/2; f
1/2*factorial(x + 1)/factorial(x) + 1/2*factorial(x)/factorial(x - 2)
sage: g = f.simplify_factorial(); g
1/2*(x - 1)*x + 1/2*x + 1/2
sage: g.simplify_rational()
1/2*x^2 + 1/2
TESTS:
Check that the problem with applying to gamma
functions (trac ticket #9240) has been fixed:
sage: gamma(1/3)
gamma(1/3)
sage: gamma(1/3).full_simplify()
gamma(1/3)
sage: gamma(4/3)
gamma(4/3)
sage: gamma(4/3).full_simplify()
1/3*gamma(1/3)
Apply simplify_factorial, simplify_trig, simplify_rational, simplify_log, and again simplify_rational to self (in that order).
ALIAS: simplify_full and full_simplify are the same.
EXAMPLES:
sage: f = sin(x)^2 + cos(x)^2
sage: f.simplify_full()
1
sage: f = sin(x/(x^2 + x))
sage: f.simplify_full()
sin(1/(x + 1))
sage: var('n,k')
(n, k)
sage: f = binomial(n,k)*factorial(k)*factorial(n-k)
sage: f.simplify_full()
factorial(n)
TESTS:
There are two square roots of , so this should
not be simplified to
, trac ticket #12737:
sage: f = sqrt((x + 1)^2)
sage: f.simplify_full()
sqrt(x^2 + 2*x + 1)
The imaginary part of an expression should not change under simplification; trac ticket #11934:
sage: f = sqrt(-8*(4*sqrt(2) - 7)*x^4 + 16*(3*sqrt(2) - 5)*x^3)
sage: original = f.imag_part()
sage: simplified = f.full_simplify().imag_part()
sage: original - simplified
0
The invalid simplification from trac ticket #12322 should not occur after trac ticket #12737:
sage: t = var('t')
sage: assume(t, 'complex')
sage: assumptions()
[t is complex]
sage: f = (1/2)*log(2*t) + (1/2)*log(1/t)
sage: f.simplify_full()
1/2*log(2*t) - 1/2*log(t)
Simplify an expression containing hypergeometric functions.
INPUT:
ALIAS: hypergeometric_simplify() and simplify_hypergeometric() are the same
EXAMPLES:
sage: hypergeometric((5, 4), (4, 1, 2, 3),
....: x).simplify_hypergeometric()
1/144*x^2*hypergeometric((), (3, 4), x) +...
1/3*x*hypergeometric((), (2, 3), x) + hypergeometric((), (1, 2), x)
sage: (2*hypergeometric((), (), x)).simplify_hypergeometric()
2*e^x
sage: (nest(lambda y: hypergeometric([y], [1], x), 3, 1)
....: .simplify_hypergeometric())
laguerre(-laguerre(-e^x, x), x)
sage: (nest(lambda y: hypergeometric([y], [1], x), 3, 1)
....: .simplify_hypergeometric(algorithm='sage'))
hypergeometric((hypergeometric((e^x,), (1,), x),), (1,), x)
Simplify symbolic expression, which can contain logs.
Recursively scans the expression self, transforming
subexpressions of the form into
and simplifies inside logarithm. User
can specify, which conditions must satisfy
and
to use
this transformation in optional parameter algorithm.
INPUT:
self - expression to be simplified
algorithm - (default: None) optional, governs the condition
on and
which must be satisfied to contract expression
. Values are
See also examples below.
DETAILS: This uses the Maxima logcontract() command. From the Maxima documentation: “Recursively scans the expression expr, transforming subexpressions of the form a1*log(b1) + a2*log(b2) + c into log(ratsimp(b1^a1 * b2^a2)) + c. The user can control which coefficients are contracted by setting the option logconcoeffp to the name of a predicate function of one argument. E.g. if you like to generate SQRTs, you can do logconcoeffp:’logconfun` logconfun(m):=featurep(m,integer) or ratnump(m)` . Then logcontract(1/2*log(x)); will give log(sqrt(x)).”
ALIAS: log_simplify() and simplify_log() are the same
EXAMPLES:
sage: x,y,t=var('x y t')
Only two first terms are contracted in the following example , the logarithm with coefficient 1/2 is not contracted:
sage: f = log(x)+2*log(y)+1/2*log(t)
sage: f.simplify_log()
log(x*y^2) + 1/2*log(t)
To contract all terms in previous example use option algorithm:
sage: f.simplify_log(algorithm='ratios')
log(sqrt(t)*x*y^2)
This shows that the option algorithm from the previous call has no influence to future calls (we changed some default Maxima flag, and have to ensure that this flag has been restored):
sage: f.simplify_log('one')
1/2*log(t) + log(x) + 2*log(y)
sage: f.simplify_log('ratios')
log(sqrt(t)*x*y^2)
sage: f.simplify_log()
log(x*y^2) + 1/2*log(t)
To contract terms with no coefficient (more precisely, with coefficients 1 and -1) use option algorithm:
sage: f = log(x)+2*log(y)-log(t)
sage: f.simplify_log('one')
2*log(y) + log(x/t)
sage: f = log(x)+log(y)-1/3*log((x+1))
sage: f.simplify_log()
log(x*y) - 1/3*log(x + 1)
sage: f.simplify_log('ratios')
log(x*y/(x + 1)^(1/3))
is irrational number, to contract logarithms in the following example
we have to put algorithm to constants or all:
sage: f = log(x)+log(y)-pi*log((x+1))
sage: f.simplify_log('constants')
log(x*y/(x + 1)^pi)
x*log(9) is contracted only if algorithm is all:
sage: (x*log(9)).simplify_log()
x*log(9)
sage: (x*log(9)).simplify_log('all')
log(9^x)
TESTS:
This shows that the issue at trac ticket #7334 is fixed. Maxima intentionally keeps the expression inside the log factored:
sage: log_expr = (log(sqrt(2)-1)+log(sqrt(2)+1))
sage: log_expr.simplify_log('all')
log((sqrt(2) + 1)*(sqrt(2) - 1))
sage: _.simplify_rational()
0
sage: log_expr.simplify_full() # applies both simplify_log and simplify_rational
0
We should use the current simplification domain rather than set it to ‘real’ explicitly (trac ticket #12780):
sage: f = sqrt(x^2)
sage: f.simplify_log()
sqrt(x^2)
sage: from sage.calculus.calculus import maxima
sage: maxima('domain: real;')
real
sage: f.simplify_log()
abs(x)
sage: maxima('domain: complex;')
complex
AUTHORS:
Simplify this symbolic expression, which can contain logs, exponentials, and radicals, by trying to convert it into a canonical form over a large class of expressions and a given ordering of variables.
Warning
As shown in the examples below, a canonical form is not always returned, i.e., two mathematically identical expressions might be simplified to different expressions.
ALGORITHM:
This uses the Maxima radcan() command. From the Maxima documentation: “All functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, produces a regular form. Two equivalent expressions in this class do not necessarily have the same appearance, but their difference can be simplified by radcan to zero. For some expressions radcan is quite time consuming. This is the cost of exploring certain relationships among the components of the expression for simplifications based on factoring and partial fraction expansions of exponents.”
Note
radical_simplify(), simplify_radical(), exp_simplify(), simplify_exp() are all the same.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = log(x*y)
sage: f.simplify_radical()
log(x) + log(y)
sage: f = log(8)/log(2)
sage: f.simplify_radical()
3
sage: f = (log(x+x^2)-log(x))^a/log(1+x)^(a/2)
sage: f.simplify_radical()
log(x + 1)^(1/2*a)
sage: f = (e^x-1)/(1+e^(x/2))
sage: f.simplify_exp()
e^(1/2*x) - 1
The example below shows two expressions e1 and e2 which are “simplified” to different expressions, while their difference is “simplified” to zero, thus simplify_radical does not return a canonical form, except maybe for 0.
sage: e1 = 1/(sqrt(5)+sqrt(2))
sage: e2 = (sqrt(5)-sqrt(2))/3
sage: e1.simplify_radical()
1/(sqrt(5) + sqrt(2))
sage: e2.simplify_radical()
1/3*sqrt(5) - 1/3*sqrt(2)
sage: (e1-e2).simplify_radical()
0
TESTS:
This tests that trac ticket #11668 has been fixed (by trac ticket #12780):
sage: a,b = var('a b')
sage: A = abs((a+I*b))^2
sage: A.simplify_radical()
abs(a + I*b)^2
sage: imag(A)
0
sage: imag(A.simplify_radical())
0
Simplify rational expressions.
INPUT:
ALIAS: rational_simplify() and simplify_rational() are the same
DETAILS: We call Maxima functions ratsimp, fullratsimp and xthru. If each part of the expression has to be simplified separately, we use Maxima function map.
EXAMPLES:
sage: f = sin(x/(x^2 + x))
sage: f
sin(x/(x^2 + x))
sage: f.simplify_rational()
sin(1/(x + 1))
sage: f = ((x - 1)^(3/2) - (x + 1)*sqrt(x - 1))/sqrt((x - 1)*(x + 1)); f
-((x + 1)*sqrt(x - 1) - (x - 1)^(3/2))/sqrt((x + 1)*(x - 1))
sage: f.simplify_rational()
-2*sqrt(x - 1)/sqrt(x^2 - 1)
With map=True each term in a sum is simplified separately and thus the resuls are shorter for functions which are combination of rational and nonrational funtions. In the following example, we use this option if we want not to combine logarithm and the rational function into one fraction:
sage: f=(x^2-1)/(x+1)-ln(x)/(x+2)
sage: f.simplify_rational()
(x^2 + x - log(x) - 2)/(x + 2)
sage: f.simplify_rational(map=True)
x - log(x)/(x + 2) - 1
Here is an example from the Maxima documentation of where algorithm='simple' produces an (possibly useful) intermediate step:
sage: y = var('y')
sage: g = (x^(y/2) + 1)^2*(x^(y/2) - 1)^2/(x^y - 1)
sage: g.simplify_rational(algorithm='simple')
(x^(2*y) - 2*x^y + 1)/(x^y - 1)
sage: g.simplify_rational()
x^y - 1
With option algorithm='noexpand' we only convert to common denominators and add. No expansion of products is performed:
sage: f=1/(x+1)+x/(x+2)^2
sage: f.simplify_rational()
(2*x^2 + 5*x + 4)/(x^3 + 5*x^2 + 8*x + 4)
sage: f.simplify_rational(algorithm='noexpand')
((x + 2)^2 + (x + 1)*x)/((x + 2)^2*(x + 1))
Attempt to simplify this expression by expressing it in the
form where both
and
are real. This
transformation is generally not a simplification, so we use
the given complexity_measure to discard
non-simplifications.
INPUT:
OUTPUT:
If the transformation produces a simpler expression (according to complexity_measure) then that simpler expression is returned. Otherwise, the original expression is returned.
ALGORITHM:
We first call rectform() on the given expression. Then, the supplied complexity measure is used to determine whether or not the result is simpler than the original expression.
EXAMPLES:
The exponential form of :
sage: f = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) )
sage: f.simplify_rectform()
sin(x)/cos(x)
This should not be expanded with Euler’s formula since the resulting expression is longer when considered as a string, and the default complexity_measure uses string length to determine which expression is simpler:
sage: f = e^(I*x)
sage: f.simplify_rectform()
e^(I*x)
However, if we pass None as our complexity measure, it is:
sage: f = e^(I*x)
sage: f.simplify_rectform(complexity_measure = None)
cos(x) + I*sin(x)
TESTS:
When given None, we should always call rectform() and return the result:
sage: polynomials = QQ['x']
sage: f = SR(polynomials.random_element())
sage: g = f.simplify_rectform(complexity_measure = None)
sage: bool(g == f.rectform())
True
Optionally expand and then employ identities such as
,
,
, or
to simplify expressions containing tan, sec, etc., to sin,
cos, sinh, cosh.
INPUT:
ALIAS: trig_simplify() and simplify_trig() are the same
EXAMPLES:
sage: f = sin(x)^2 + cos(x)^2; f
cos(x)^2 + sin(x)^2
sage: f.simplify()
cos(x)^2 + sin(x)^2
sage: f.simplify_trig()
1
sage: h = sin(x)*csc(x)
sage: h.simplify_trig()
1
sage: k = tanh(x)*cosh(2*x)
sage: k.simplify_trig()
(2*sinh(x)^3 + sinh(x))/cosh(x)
In some cases we do not want to expand:
sage: f=tan(3*x)
sage: f.simplify_trig()
(4*cos(x)^2 - 1)*sin(x)/(4*cos(x)^3 - 3*cos(x))
sage: f.simplify_trig(False)
sin(3*x)/cos(3*x)
EXAMPLES:
sage: var('x, y')
(x, y)
sage: sin(x^2 + y^2)
sin(x^2 + y^2)
sage: sin(sage.symbolic.constants.pi)
0
sage: sin(SR(1))
sin(1)
sage: sin(SR(RealField(150)(1)))
0.84147098480789650665250232163029899962256306
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(0).sin()
0
sage: SR(0).sin(hold=True)
sin(0)
This also works using functional notation:
sage: sin(0,hold=True)
sin(0)
sage: sin(0)
0
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(0).sin(hold=True); a.simplify()
0
TESTS:
sage: SR(oo).sin()
Traceback (most recent call last):
...
RuntimeError: sin_eval(): sin(infinity) encountered
sage: SR(-oo).sin()
Traceback (most recent call last):
...
RuntimeError: sin_eval(): sin(infinity) encountered
sage: SR(unsigned_infinity).sin()
Traceback (most recent call last):
...
RuntimeError: sin_eval(): sin(infinity) encountered
Return sinh of self.
We have .
EXAMPLES:
sage: x.sinh()
sinh(x)
sage: SR(1).sinh()
sinh(1)
sage: SR(0).sinh()
0
sage: SR(1.0).sinh()
1.17520119364380
sage: maxima('sinh(1.0)')
1.17520119364380...
sinh(1.0000000000000000000000000)
sage: SR(1).sinh().n(90)
1.1752011936438014568823819
sage: SR(RIF(1)).sinh()
1.175201193643802?
To prevent automatic evaluation use the hold argument:
sage: arccosh(x).sinh()
sqrt(x + 1)*sqrt(x - 1)
sage: arccosh(x).sinh(hold=True)
sinh(arccosh(x))
This also works using functional notation:
sage: sinh(arccosh(x),hold=True)
sinh(arccosh(x))
sage: sinh(arccosh(x))
sqrt(x + 1)*sqrt(x - 1)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = arccosh(x).sinh(hold=True); a.simplify()
sqrt(x + 1)*sqrt(x - 1)
TESTS:
sage: SR(oo).sinh()
+Infinity
sage: SR(-oo).sinh()
-Infinity
sage: SR(unsigned_infinity).sinh()
Traceback (most recent call last):
...
RuntimeError: sinh_eval(): sinh(unsigned_infinity) encountered
Analytically solve the equation self == 0 or a univariate
inequality for the variable .
Warning
This is not a numerical solver - use find_root to solve for self == 0 numerically on an interval.
INPUT:
EXAMPLES:
sage: z = var('z')
sage: (z^5 - 1).solve(z)
[z == e^(2/5*I*pi), z == e^(4/5*I*pi), z == e^(-4/5*I*pi), z == e^(-2/5*I*pi), z == 1]
sage: solve((z^3-1)^3, z, multiplicities=True)
([z == 1/2*I*sqrt(3) - 1/2, z == -1/2*I*sqrt(3) - 1/2, z == 1], [3, 3, 3])
A simple example to show the use of the keyword multiplicities:
sage: ((x^2-1)^2).solve(x)
[x == -1, x == 1]
sage: ((x^2-1)^2).solve(x,multiplicities=True)
([x == -1, x == 1], [2, 2])
sage: ((x^2-1)^2).solve(x,multiplicities=True,to_poly_solve=True)
Traceback (most recent call last):
...
NotImplementedError: to_poly_solve does not return multiplicities
Here is how the explicit_solutions keyword functions:
sage: solve(sin(x)==x,x)
[x == sin(x)]
sage: solve(sin(x)==x,x,explicit_solutions=True)
[]
sage: solve(x*sin(x)==x^2,x)
[x == 0, x == sin(x)]
sage: solve(x*sin(x)==x^2,x,explicit_solutions=True)
[x == 0]
The following examples show the use of the keyword to_poly_solve:
sage: solve(abs(1-abs(1-x)) == 10, x)
[abs(abs(x - 1) - 1) == 10]
sage: solve(abs(1-abs(1-x)) == 10, x, to_poly_solve=True)
[x == -10, x == 12]
sage: var('Q')
Q
sage: solve(Q*sqrt(Q^2 + 2) - 1, Q)
[Q == 1/sqrt(Q^2 + 2)]
sage: solve(Q*sqrt(Q^2 + 2) - 1, Q, to_poly_solve=True)
[Q == 1/sqrt(-sqrt(2) + 1), Q == 1/sqrt(sqrt(2) + 1)]
In some cases there may be infinitely many solutions indexed by a dummy variable. If it begins with z, it is implicitly assumed to be an integer, a real if with r, and so on:
sage: solve( sin(x)==cos(x), x, to_poly_solve=True)
[x == 1/4*pi + pi*z...]
An effort is made to only return solutions that satisfy the current assumptions:
sage: solve(x^2==4, x)
[x == -2, x == 2]
sage: assume(x<0)
sage: solve(x^2==4, x)
[x == -2]
sage: solve((x^2-4)^2 == 0, x, multiplicities=True)
([x == -2], [2])
sage: solve(x^2==2, x)
[x == -sqrt(2)]
sage: assume(x, 'rational')
sage: solve(x^2 == 2, x)
[]
sage: solve(x^2==2-z, x)
[x == -sqrt(-z + 2)]
sage: solve((x-z)^2==2, x)
[x == z - sqrt(2), x == z + sqrt(2)]
There is still room for improvement:
sage: assume(x, 'integer')
sage: assume(z, 'integer')
sage: solve((x-z)^2==2, x)
[x == z - sqrt(2), x == z + sqrt(2)]
sage: forget()
In some cases it may be worthwhile to directly use to_poly_solve if one suspects some answers are being missed:
sage: solve(cos(x)==0, x)
[x == 1/2*pi]
sage: solve(cos(x)==0, x, to_poly_solve=True)
[x == 1/2*pi]
sage: solve(cos(x)==0, x, to_poly_solve='force')
[x == 1/2*pi + pi*z77]
The same may also apply if a returned unsolved expression has a denominator, but the original one did not:
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True)
[sin(x) == 1/2/cos(x)]
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve=True, explicit_solutions=True)
[x == 1/4*pi + pi*z...]
sage: solve(cos(x) * sin(x) == 1/2, x, to_poly_solve='force')
[x == 1/4*pi + pi*z...]
We can also solve for several variables:
sage: var('b, c')
(b, c)
sage: solve((b-1)*(c-1), [b,c])
[[b == 1, c == r4], [b == r5, c == 1]]
Some basic inequalities can be also solved:
sage: x,y=var('x,y'); (ln(x)-ln(y)>0).solve(x)
[[log(x) - log(y) > 0]]
sage: x,y=var('x,y'); (ln(x)>ln(y)).solve(x) # not tested - output depends on system
[[0 < y, y < x, 0 < x]]
[[y < x, 0 < y]]
TESTS:
trac ticket #7325 (solving inequalities):
sage: (x^2>1).solve(x)
[[x < -1], [x > 1]]
Catch error message from Maxima:
sage: solve(acot(x),x)
[]
sage: solve(acot(x),x,to_poly_solve=True)
[]
trac ticket #7491 fixed:
sage: y=var('y')
sage: solve(y==y,y)
[y == r1]
sage: solve(y==y,y,multiplicities=True)
([y == r1], [])
sage: from sage.symbolic.assumptions import GenericDeclaration
sage: GenericDeclaration(x, 'rational').assume()
sage: solve(x^2 == 2, x)
[]
sage: forget()
trac ticket #8390 fixed:
sage: solve(sin(x)==1/2,x)
[x == 1/6*pi]
sage: solve(sin(x)==1/2,x,to_poly_solve=True)
[x == 1/6*pi]
sage: solve(sin(x)==1/2, x, to_poly_solve='force')
[x == 1/6*pi + 2*pi*z..., x == 5/6*pi + 2*pi*z...]
trac ticket #11618 fixed:
sage: g(x)=0
sage: solve(g(x)==0,x,solution_dict=True)
[{x: r1}]
trac ticket #13286 fixed:
sage: solve([x-4], [x])
[x == 4]
trac ticket #13645: fixed:
sage: x.solve((1,2))
Traceback (most recent call last):
...
TypeError: (1, 2) are not valid variables.
trac ticket #17128: fixed:
sage: var('x,y')
(x, y)
sage: f = x+y
sage: sol = f.solve([x, y], solution_dict=True)
sage: sol[0].get(x) + sol[0].get(y)
0
trac ticket #16651 fixed:
sage: (x^7-x-1).solve(x, to_poly_solve=True) # abs tol 1e-6
[x == 1.11277569705,
x == (-0.363623519329 - 0.952561195261*I),
x == (0.617093477784 - 0.900864951949*I),
x == (-0.809857800594 - 0.262869645851*I),
x == (-0.809857800594 + 0.262869645851*I),
x == (0.617093477784 + 0.900864951949*I),
x == (-0.363623519329 + 0.952561195261*I)]
Return the square root of this expression
EXAMPLES:
sage: var('x, y')
(x, y)
sage: SR(2).sqrt()
sqrt(2)
sage: (x^2+y^2).sqrt()
sqrt(x^2 + y^2)
sage: (x^2).sqrt()
sqrt(x^2)
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(4).sqrt()
2
sage: SR(4).sqrt(hold=True)
sqrt(4)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(4).sqrt(hold=True); a.simplify()
2
To use this parameter in functional notation, you must coerce to the symbolic ring:
sage: sqrt(SR(4),hold=True)
sqrt(4)
sage: sqrt(4,hold=True)
Traceback (most recent call last):
...
TypeError: _do_sqrt() got an unexpected keyword argument 'hold'
Return the value of the Heaviside step function, which is 0 for negative x, 1/2 for 0, and 1 for positive x.
EXAMPLES:
sage: x = var('x')
sage: SR(1.5).step()
1
sage: SR(0).step()
1/2
sage: SR(-1/2).step()
0
sage: SR(float(-1)).step()
0
Using the hold parameter it is possible to prevent automatic evaluation:
sage: SR(2).step()
1
sage: SR(2).step(hold=True)
step(2)
EXAMPLES:
sage: var('x,y,z,a,b,c,d,f,g')
(x, y, z, a, b, c, d, f, g)
sage: w0 = SR.wild(0); w1 = SR.wild(1)
sage: t = a^2 + b^2 + (x+y)^3
# substitute with keyword arguments (works only with symbols)
sage: t.subs(a=c)
(x + y)^3 + b^2 + c^2
# substitute with a dictionary argument
sage: t.subs({a^2: c})
(x + y)^3 + b^2 + c
sage: t.subs({w0^2: w0^3})
a^3 + b^3 + (x + y)^3
# substitute with a relational expression
sage: t.subs(w0^2 == w0^3)
a^3 + b^3 + (x + y)^3
sage: t.subs(w0==w0^2)
(x^2 + y^2)^18 + a^16 + b^16
# more than one keyword argument is accepted
sage: t.subs(a=b, b=c)
(x + y)^3 + b^2 + c^2
# using keyword arguments with a dictionary is allowed
sage: t.subs({a:b}, b=c)
(x + y)^3 + b^2 + c^2
# in this case keyword arguments override the dictionary
sage: t.subs({a:b}, a=c)
(x + y)^3 + b^2 + c^2
sage: t.subs({a:b, b:c})
(x + y)^3 + b^2 + c^2
TESTS:
sage: # no arguments return the same expression
sage: t.subs()
(x + y)^3 + a^2 + b^2
# similarly for an empty dictionary argument
sage: t.subs({})
(x + y)^3 + a^2 + b^2
# non keyword or dictionary argument returns error
sage: t.subs(5)
Traceback (most recent call last):
...
TypeError: subs takes either a set of keyword arguments, a dictionary, or a symbolic relational expression
# substitutions with infinity
sage: (x/y).subs(y=oo)
0
sage: (x/y).subs(x=oo)
Traceback (most recent call last):
...
RuntimeError: indeterminate expression: infinity * f(x) encountered.
sage: (x*y).subs(x=oo)
Traceback (most recent call last):
...
RuntimeError: indeterminate expression: infinity * f(x) encountered.
sage: (x^y).subs(x=oo)
Traceback (most recent call last):
...
ValueError: power::eval(): pow(Infinity, f(x)) is not defined.
sage: (x^y).subs(y=oo)
Traceback (most recent call last):
...
ValueError: power::eval(): pow(f(x), infinity) is not defined.
sage: (x+y).subs(x=oo)
+Infinity
sage: (x-y).subs(y=oo)
-Infinity
sage: gamma(x).subs(x=-1)
Infinity
sage: 1/gamma(x).subs(x=-1)
0
Verify that this operation does not modify the passed dictionary (trac ticket #6622):
sage: var('v t')
(v, t)
sage: f = v*t
sage: D = {v: 2}
sage: f(D, t=3)
6
sage: D
{v: 2}
Check if trac ticket #9891 is fixed:
sage: exp(x).subs(x=log(x))
x
Check if trac ticket #13587 is fixed:
sage: t = tan(x)^2 - tan(x)
sage: t.subs(x=pi/2)
Infinity
sage: u = gamma(x) - gamma(x-1)
sage: u.subs(x=-1)
Infinity
Given a dictionary of key:value pairs, substitute all occurrences of key for value in self. The substitutions can also be given as a number of symbolic equalities key == value; see the examples.
Warning
This is a formal pattern substitution, which may or may not have any mathematical meaning. The exact rules used at present in Sage are determined by Maxima’s subst command. Sometimes patterns are not replaced even though one would think they should be - see examples below.
EXAMPLES:
sage: f = x^2 + 1
sage: f.subs_expr(x^2 == x)
x + 1
sage: var('x,y,z'); f = x^3 + y^2 + z
(x, y, z)
sage: f.subs_expr(x^3 == y^2, z == 1)
2*y^2 + 1
Or the same thing giving the substitutions as a dictionary:
sage: f.subs_expr({x^3:y^2, z:1})
2*y^2 + 1
sage: f = x^2 + x^4
sage: f.subs_expr(x^2 == x)
x^4 + x
sage: f = cos(x^2) + sin(x^2)
sage: f.subs_expr(x^2 == x)
cos(x) + sin(x)
sage: f(x,y,t) = cos(x) + sin(y) + x^2 + y^2 + t
sage: f.subs_expr(y^2 == t)
(x, y, t) |--> x^2 + 2*t + cos(x) + sin(y)
The following seems really weird, but it is what Maple does:
sage: f.subs_expr(x^2 + y^2 == t)
(x, y, t) |--> x^2 + y^2 + t + cos(x) + sin(y)
sage: maple.eval('subs(x^2 + y^2 = t, cos(x) + sin(y) + x^2 + y^2 + t)') # optional - maple
'cos(x)+sin(y)+x^2+y^2+t'
sage: maxima.quit()
sage: maxima.eval('cos(x) + sin(y) + x^2 + y^2 + t, x^2 + y^2 = t')
'sin(y)+y^2+cos(x)+x^2+t'
Actually Mathematica does something that makes more sense:
sage: mathematica.eval('Cos[x] + Sin[y] + x^2 + y^2 + t /. x^2 + y^2 -> t') # optional - mathematica
2 t + Cos[x] + Sin[y]
EXAMPLES:
sage: var('x,y,z,a,b,c,d,f,g')
(x, y, z, a, b, c, d, f, g)
sage: w0 = SR.wild(0); w1 = SR.wild(1)
sage: t = a^2 + b^2 + (x+y)^3
# substitute with keyword arguments (works only with symbols)
sage: t.subs(a=c)
(x + y)^3 + b^2 + c^2
# substitute with a dictionary argument
sage: t.subs({a^2: c})
(x + y)^3 + b^2 + c
sage: t.subs({w0^2: w0^3})
a^3 + b^3 + (x + y)^3
# substitute with a relational expression
sage: t.subs(w0^2 == w0^3)
a^3 + b^3 + (x + y)^3
sage: t.subs(w0==w0^2)
(x^2 + y^2)^18 + a^16 + b^16
# more than one keyword argument is accepted
sage: t.subs(a=b, b=c)
(x + y)^3 + b^2 + c^2
# using keyword arguments with a dictionary is allowed
sage: t.subs({a:b}, b=c)
(x + y)^3 + b^2 + c^2
# in this case keyword arguments override the dictionary
sage: t.subs({a:b}, a=c)
(x + y)^3 + b^2 + c^2
sage: t.subs({a:b, b:c})
(x + y)^3 + b^2 + c^2
TESTS:
sage: # no arguments return the same expression
sage: t.subs()
(x + y)^3 + a^2 + b^2
# similarly for an empty dictionary argument
sage: t.subs({})
(x + y)^3 + a^2 + b^2
# non keyword or dictionary argument returns error
sage: t.subs(5)
Traceback (most recent call last):
...
TypeError: subs takes either a set of keyword arguments, a dictionary, or a symbolic relational expression
# substitutions with infinity
sage: (x/y).subs(y=oo)
0
sage: (x/y).subs(x=oo)
Traceback (most recent call last):
...
RuntimeError: indeterminate expression: infinity * f(x) encountered.
sage: (x*y).subs(x=oo)
Traceback (most recent call last):
...
RuntimeError: indeterminate expression: infinity * f(x) encountered.
sage: (x^y).subs(x=oo)
Traceback (most recent call last):
...
ValueError: power::eval(): pow(Infinity, f(x)) is not defined.
sage: (x^y).subs(y=oo)
Traceback (most recent call last):
...
ValueError: power::eval(): pow(f(x), infinity) is not defined.
sage: (x+y).subs(x=oo)
+Infinity
sage: (x-y).subs(y=oo)
-Infinity
sage: gamma(x).subs(x=-1)
Infinity
sage: 1/gamma(x).subs(x=-1)
0
Verify that this operation does not modify the passed dictionary (trac ticket #6622):
sage: var('v t')
(v, t)
sage: f = v*t
sage: D = {v: 2}
sage: f(D, t=3)
6
sage: D
{v: 2}
Check if trac ticket #9891 is fixed:
sage: exp(x).subs(x=log(x))
x
Check if trac ticket #13587 is fixed:
sage: t = tan(x)^2 - tan(x)
sage: t.subs(x=pi/2)
Infinity
sage: u = gamma(x) - gamma(x-1)
sage: u.subs(x=-1)
Infinity
Given a dictionary of key:value pairs, substitute all occurrences of key for value in self. The substitutions can also be given as a number of symbolic equalities key == value; see the examples.
Warning
This is a formal pattern substitution, which may or may not have any mathematical meaning. The exact rules used at present in Sage are determined by Maxima’s subst command. Sometimes patterns are not replaced even though one would think they should be - see examples below.
EXAMPLES:
sage: f = x^2 + 1
sage: f.subs_expr(x^2 == x)
x + 1
sage: var('x,y,z'); f = x^3 + y^2 + z
(x, y, z)
sage: f.subs_expr(x^3 == y^2, z == 1)
2*y^2 + 1
Or the same thing giving the substitutions as a dictionary:
sage: f.subs_expr({x^3:y^2, z:1})
2*y^2 + 1
sage: f = x^2 + x^4
sage: f.subs_expr(x^2 == x)
x^4 + x
sage: f = cos(x^2) + sin(x^2)
sage: f.subs_expr(x^2 == x)
cos(x) + sin(x)
sage: f(x,y,t) = cos(x) + sin(y) + x^2 + y^2 + t
sage: f.subs_expr(y^2 == t)
(x, y, t) |--> x^2 + 2*t + cos(x) + sin(y)
The following seems really weird, but it is what Maple does:
sage: f.subs_expr(x^2 + y^2 == t)
(x, y, t) |--> x^2 + y^2 + t + cos(x) + sin(y)
sage: maple.eval('subs(x^2 + y^2 = t, cos(x) + sin(y) + x^2 + y^2 + t)') # optional - maple
'cos(x)+sin(y)+x^2+y^2+t'
sage: maxima.quit()
sage: maxima.eval('cos(x) + sin(y) + x^2 + y^2 + t, x^2 + y^2 = t')
'sin(y)+y^2+cos(x)+x^2+t'
Actually Mathematica does something that makes more sense:
sage: mathematica.eval('Cos[x] + Sin[y] + x^2 + y^2 + t /. x^2 + y^2 -> t') # optional - mathematica
2 t + Cos[x] + Sin[y]
Return this symbolic expressions all occurrences of the function original replaced with the function new.
EXAMPLES:
sage: x,y = var('x,y')
sage: foo = function('foo'); bar = function('bar')
sage: f = foo(x) + 1/foo(pi*y)
sage: f.substitute_function(foo, bar)
1/bar(pi*y) + bar(x)
Return a relation obtained by subtracting x from both sides of this relation.
EXAMPLES:
sage: eqn = x*sin(x)*sqrt(3) + sqrt(2) > cos(sin(x))
sage: eqn.subtract_from_both_sides(sqrt(2))
sqrt(3)*x*sin(x) > -sqrt(2) + cos(sin(x))
sage: eqn.subtract_from_both_sides(cos(sin(x)))
sqrt(3)*x*sin(x) + sqrt(2) - cos(sin(x)) > 0
Return the symbolic sum
with respect to the variable with endpoints
and
.
INPUT:
v - a variable or variable name
a - lower endpoint of the sum
b - upper endpoint of the sum
algorithm - (default: 'maxima') one of
- 'maxima' - use Maxima (the default)
- 'maple' - (optional) use Maple
- 'mathematica' - (optional) use Mathematica
- 'giac' - (optional) use Giac
EXAMPLES:
sage: k, n = var('k,n')
sage: k.sum(k, 1, n).factor()
1/2*(n + 1)*n
sage: (1/k^4).sum(k, 1, oo)
1/90*pi^4
sage: (1/k^5).sum(k, 1, oo)
zeta(5)
Warning
This function only works with symbolic expressions. To sum any other objects like list elements or function return values, please use python summation, see http://docs.python.org/library/functions.html#sum
In particular, this does not work:
sage: n = var('n')
sage: list=[1,2,3,4,5]
sage: sum(list[n],n,0,3)
Traceback (most recent call last):
...
TypeError: unable to convert x (=n) to an integer
Use python sum() instead:
sage: sum(list[n] for n in range(4))
10
Also, only a limited number of functions are recognized in symbolic sums:
sage: sum(valuation(n,2),n,1,5)
Traceback (most recent call last):
...
AttributeError: 'sage.symbolic.expression.Expression' object has no attribute 'valuation'
Again, use python sum():
sage: sum(valuation(n+1,2) for n in range(5))
3
(now back to the Sage sum examples)
A well known binomial identity:
sage: assume(n>=0)
sage: binomial(n,k).sum(k, 0, n)
2^n
And some truncations thereof:
sage: binomial(n,k).sum(k,1,n)
2^n - 1
sage: binomial(n,k).sum(k,2,n)
2^n - n - 1
sage: binomial(n,k).sum(k,0,n-1)
2^n - 1
sage: binomial(n,k).sum(k,1,n-1)
2^n - 2
The binomial theorem:
sage: x, y = var('x, y')
sage: (binomial(n,k) * x^k * y^(n-k)).sum(k, 0, n)
(x + y)^n
sage: (k * binomial(n, k)).sum(k, 1, n)
2^(n - 1)*n
sage: ((-1)^k*binomial(n,k)).sum(k, 0, n)
0
sage: (2^(-k)/(k*(k+1))).sum(k, 1, oo)
-log(2) + 1
Summing a hypergeometric term:
sage: (binomial(n, k) * factorial(k) / factorial(n+1+k)).sum(k, 0, n)
1/2*sqrt(pi)/factorial(n + 1/2)
We check a well known identity:
sage: bool((k^3).sum(k, 1, n) == k.sum(k, 1, n)^2)
True
A geometric sum:
sage: a, q = var('a, q')
sage: (a*q^k).sum(k, 0, n)
(a*q^(n + 1) - a)/(q - 1)
The geometric series:
sage: assume(abs(q) < 1)
sage: (a*q^k).sum(k, 0, oo)
-a/(q - 1)
A divergent geometric series. Do not forget to forget your assumptions:
sage: forget()
sage: assume(q > 1)
sage: (a*q^k).sum(k, 0, oo)
Traceback (most recent call last):
...
ValueError: Sum is divergent.
This summation only Mathematica can perform:
sage: (1/(1+k^2)).sum(k, -oo, oo, algorithm = 'mathematica') # optional - mathematica
pi*coth(pi)
Use Giac to perform this summation:
sage: (sum(1/(1+k^2), k, -oo, oo, algorithm = 'giac')).factor() # optional - giac
(e^(2*pi) + 1)*pi/((e^pi - 1)*(e^pi + 1))
Use Maple as a backend for summation:
sage: (binomial(n,k)*x^k).sum(k, 0, n, algorithm = 'maple') # optional - maple
(x + 1)^n
Check that the sum in trac ticket #10682 is done right:
sage: sum(binomial(n,k)*k^2, k, 2, n)
1/4*(n^2 + n)*2^n - n
Note
EXAMPLES:
sage: var('x, y')
(x, y)
sage: tan(x^2 + y^2)
tan(x^2 + y^2)
sage: tan(sage.symbolic.constants.pi/2)
Infinity
sage: tan(SR(1))
tan(1)
sage: tan(SR(RealField(150)(1)))
1.5574077246549022305069748074583601730872508
To prevent automatic evaluation use the hold argument:
sage: (pi/12).tan()
-sqrt(3) + 2
sage: (pi/12).tan(hold=True)
tan(1/12*pi)
This also works using functional notation:
sage: tan(pi/12,hold=True)
tan(1/12*pi)
sage: tan(pi/12)
-sqrt(3) + 2
To then evaluate again, we currently must use Maxima via simplify():
sage: a = (pi/12).tan(hold=True); a.simplify()
-sqrt(3) + 2
TESTS:
sage: SR(oo).tan()
Traceback (most recent call last):
...
RuntimeError: tan_eval(): tan(infinity) encountered
sage: SR(-oo).tan()
Traceback (most recent call last):
...
RuntimeError: tan_eval(): tan(infinity) encountered
sage: SR(unsigned_infinity).tan()
Traceback (most recent call last):
...
RuntimeError: tan_eval(): tan(infinity) encountered
Return tanh of self.
We have .
EXAMPLES:
sage: x.tanh()
tanh(x)
sage: SR(1).tanh()
tanh(1)
sage: SR(0).tanh()
0
sage: SR(1.0).tanh()
0.761594155955765
sage: maxima('tanh(1.0)')
0.7615941559557649
sage: plot(lambda x: SR(x).tanh(), -1, 1)
Graphics object consisting of 1 graphics primitive
To prevent automatic evaluation use the hold argument:
sage: arcsinh(x).tanh()
x/sqrt(x^2 + 1)
sage: arcsinh(x).tanh(hold=True)
tanh(arcsinh(x))
This also works using functional notation:
sage: tanh(arcsinh(x),hold=True)
tanh(arcsinh(x))
sage: tanh(arcsinh(x))
x/sqrt(x^2 + 1)
To then evaluate again, we currently must use Maxima via simplify():
sage: a = arcsinh(x).tanh(hold=True); a.simplify()
x/sqrt(x^2 + 1)
TESTS:
sage: SR(oo).tanh()
1
sage: SR(-oo).tanh()
-1
sage: SR(unsigned_infinity).tanh()
Traceback (most recent call last):
...
RuntimeError: tanh_eval(): tanh(unsigned_infinity) encountered
Expand this symbolic expression in a truncated Taylor or
Laurent series in the variable around the point
,
containing terms through
. Functions in more
variables is also supported.
INPUT:
EXAMPLES:
sage: var('a, x, z')
(a, x, z)
sage: taylor(a*log(z), z, 2, 3)
1/24*a*(z - 2)^3 - 1/8*a*(z - 2)^2 + 1/2*a*(z - 2) + a*log(2)
sage: taylor(sqrt (sin(x) + a*x + 1), x, 0, 3)
1/48*(3*a^3 + 9*a^2 + 9*a - 1)*x^3 - 1/8*(a^2 + 2*a + 1)*x^2 + 1/2*(a + 1)*x + 1
sage: taylor (sqrt (x + 1), x, 0, 5)
7/256*x^5 - 5/128*x^4 + 1/16*x^3 - 1/8*x^2 + 1/2*x + 1
sage: taylor (1/log (x + 1), x, 0, 3)
-19/720*x^3 + 1/24*x^2 - 1/12*x + 1/x + 1/2
sage: taylor (cos(x) - sec(x), x, 0, 5)
-1/6*x^4 - x^2
sage: taylor ((cos(x) - sec(x))^3, x, 0, 9)
-1/2*x^8 - x^6
sage: taylor (1/(cos(x) - sec(x))^3, x, 0, 5)
-15377/7983360*x^4 - 6767/604800*x^2 + 11/120/x^2 + 1/2/x^4 - 1/x^6 - 347/15120
TESTS:
Check that ticket trac ticket #7472 is fixed (Taylor polynomial in more variables):
sage: x,y=var('x y'); taylor(x*y^3,(x,1),(y,1),4)
(x - 1)*(y - 1)^3 + 3*(x - 1)*(y - 1)^2 + (y - 1)^3 + 3*(x - 1)*(y - 1) + 3*(y - 1)^2 + x + 3*y - 3
sage: expand(_)
x*y^3
Test this relation at several random values, attempting to find a contradiction. If this relation has no variables, it will also test this relation after casting into the domain.
Because the interval fields never return false positives, we can be assured that if True or False is returned (and proof is False) then the answer is correct.
INPUT:
OUTPUT:
Boolean or NotImplemented, meaning
EXAMPLES:
sage: (3 < pi).test_relation()
True
sage: (0 >= pi).test_relation()
False
sage: (exp(pi) - pi).n()
19.9990999791895
sage: (exp(pi) - pi == 20).test_relation()
False
sage: (sin(x)^2 + cos(x)^2 == 1).test_relation()
NotImplemented
sage: (sin(x)^2 + cos(x)^2 == 1).test_relation(proof=False)
True
sage: (x == 1).test_relation()
False
sage: var('x,y')
(x, y)
sage: (x < y).test_relation()
False
TESTS:
sage: all_relations = [op for name, op in sorted(operator.__dict__.items()) if len(name) == 2]
sage: all_relations
[<built-in function eq>, <built-in function ge>, <built-in function gt>, <built-in function le>, <built-in function lt>, <built-in function ne>]
sage: [op(3, pi).test_relation() for op in all_relations]
[False, False, False, True, True, True]
sage: [op(pi, pi).test_relation() for op in all_relations]
[True, True, False, True, False, False]
sage: s = 'some_very_long_variable_name_which_will_definitely_collide_if_we_use_a_reasonable_length_bound_for_a_hash_that_respects_lexicographic_order'
sage: t1, t2 = var(','.join([s+'1',s+'2']))
sage: (t1 == t2).test_relation()
False
sage: (cot(pi + x) == 0).test_relation()
NotImplemented
Return the trailing coefficient of s in self, i.e., the coefficient of the smallest power of s in self.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.trailing_coefficient(x)
2*sin(x*y)
sage: f.trailing_coefficient(y)
x
sage: f.trailing_coefficient(sin(x*y))
a*x + x*y + x/y + 100
Return the trailing coefficient of s in self, i.e., the coefficient of the smallest power of s in self.
EXAMPLES:
sage: var('x,y,a')
(x, y, a)
sage: f = 100 + a*x + x^3*sin(x*y) + x*y + x/y + 2*sin(x*y)/x; f
x^3*sin(x*y) + a*x + x*y + x/y + 2*sin(x*y)/x + 100
sage: f.trailing_coefficient(x)
2*sin(x*y)
sage: f.trailing_coefficient(y)
x
sage: f.trailing_coefficient(sin(x*y))
a*x + x*y + x/y + 100
Expand trigonometric and hyperbolic functions of sums of angles and of multiple angles occurring in self. For best results, self should already be expanded.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: sin(5*x).expand_trig()
5*cos(x)^4*sin(x) - 10*cos(x)^2*sin(x)^3 + sin(x)^5
sage: cos(2*x + var('y')).expand_trig()
cos(2*x)*cos(y) - sin(2*x)*sin(y)
We illustrate various options to this function:
sage: f = sin(sin(3*cos(2*x))*x)
sage: f.expand_trig()
sin((3*cos(cos(2*x))^2*sin(cos(2*x)) - sin(cos(2*x))^3)*x)
sage: f.expand_trig(full=True)
sin((3*(cos(cos(x)^2)*cos(sin(x)^2) + sin(cos(x)^2)*sin(sin(x)^2))^2*(cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2)) - (cos(sin(x)^2)*sin(cos(x)^2) - cos(cos(x)^2)*sin(sin(x)^2))^3)*x)
sage: sin(2*x).expand_trig(times=False)
sin(2*x)
sage: sin(2*x).expand_trig(times=True)
2*cos(x)*sin(x)
sage: sin(2 + x).expand_trig(plus=False)
sin(x + 2)
sage: sin(2 + x).expand_trig(plus=True)
cos(x)*sin(2) + cos(2)*sin(x)
sage: sin(x/2).expand_trig(half_angles=False)
sin(1/2*x)
sage: sin(x/2).expand_trig(half_angles=True)
(-1)^floor(1/2*x/pi)*sqrt(-1/2*cos(x) + 1/2)
ALIASES:
trig_expand() and expand_trig() are the same
Combine products and powers of trigonometric and hyperbolic sin’s and cos’s of x into those of multiples of x. It also tries to eliminate these functions when they occur in denominators.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: y=var('y')
sage: f=sin(x)*cos(x)^3+sin(y)^2
sage: f.reduce_trig()
-1/2*cos(2*y) + 1/8*sin(4*x) + 1/4*sin(2*x) + 1/2
To reduce only the expressions involving x we use optional parameter:
sage: f.reduce_trig(x)
sin(y)^2 + 1/8*sin(4*x) + 1/4*sin(2*x)
ALIASES: trig_reduce() and reduce_trig() are the same
Optionally expand and then employ identities such as
,
,
, or
to simplify expressions containing tan, sec, etc., to sin,
cos, sinh, cosh.
INPUT:
ALIAS: trig_simplify() and simplify_trig() are the same
EXAMPLES:
sage: f = sin(x)^2 + cos(x)^2; f
cos(x)^2 + sin(x)^2
sage: f.simplify()
cos(x)^2 + sin(x)^2
sage: f.simplify_trig()
1
sage: h = sin(x)*csc(x)
sage: h.simplify_trig()
1
sage: k = tanh(x)*cosh(2*x)
sage: k.simplify_trig()
(2*sinh(x)^3 + sinh(x))/cosh(x)
In some cases we do not want to expand:
sage: f=tan(3*x)
sage: f.simplify_trig()
(4*cos(x)^2 - 1)*sin(x)/(4*cos(x)^3 - 3*cos(x))
sage: f.simplify_trig(False)
sin(3*x)/cos(3*x)
Given a power series or expression, return the corresponding expression without the big oh.
INPUT:
OUTPUT:
A symbolic expression.
EXAMPLES:
sage: f = sin(x)/x^2
sage: f.truncate()
sin(x)/x^2
sage: f.series(x,7)
1*x^(-1) + (-1/6)*x + 1/120*x^3 + (-1/5040)*x^5 + Order(x^7)
sage: f.series(x,7).truncate()
-1/5040*x^5 + 1/120*x^3 - 1/6*x + 1/x
sage: f.series(x==1,3).truncate().expand()
-2*x^2*cos(1) + 5/2*x^2*sin(1) + 5*x*cos(1) - 7*x*sin(1) - 3*cos(1) + 11/2*sin(1)
Return the unit of this expression when considered as a polynomial in s.
See also content(), primitive_part(), and unit_content_primitive().
INPUT:
OUTPUT:
The unit part of a polynomial as a symbolic expression. It is defined as the sign of the leading coefficient.
EXAMPLES:
sage: (2*x+4).unit(x)
1
sage: (-2*x+1).unit(x)
-1
sage: (2*x+1/2).unit(x)
1
sage: var('y')
y
sage: (2*x - 4*sin(y)).unit(sin(y))
-1
Return the factorization into unit, content, and primitive part.
INPUT:
OUTPUT:
A triple (unit, content, primitive polynomial)` containing the unit, content, and primitive polynomial. Their product equals self.
EXAMPLES:
sage: var('x,y')
(x, y)
sage: ex = 9*x^3*y+3*y
sage: ex.unit_content_primitive(x)
(1, 3*y, 3*x^3 + 1)
sage: ex.unit_content_primitive(y)
(1, 9*x^3 + 3, y)
Return sorted tuple of variables that occur in this expression.
EXAMPLES:
sage: (x,y,z) = var('x,y,z')
sage: (x+y).variables()
(x, y)
sage: (2*x).variables()
(x,)
sage: (x^y).variables()
(x, y)
sage: sin(x+y^z).variables()
(x, y, z)
EXAMPLES:
sage: x, y = var('x, y')
sage: (x/y).zeta()
zeta(x/y)
sage: SR(2).zeta()
1/6*pi^2
sage: SR(3).zeta()
zeta(3)
sage: SR(CDF(0,1)).zeta() # abs tol 1e-16
0.003300223685324103 - 0.4181554491413217*I
sage: CDF(0,1).zeta() # abs tol 1e-16
0.003300223685324103 - 0.4181554491413217*I
sage: plot(lambda x: SR(x).zeta(), -10,10).show(ymin=-3,ymax=3)
To prevent automatic evaluation use the hold argument:
sage: SR(2).zeta(hold=True)
zeta(2)
This also works using functional notation:
sage: zeta(2,hold=True)
zeta(2)
sage: zeta(2)
1/6*pi^2
To then evaluate again, we currently must use Maxima via simplify():
sage: a = SR(2).zeta(hold=True); a.simplify()
1/6*pi^2
TESTS:
sage: t = SR(1).zeta(); t
Infinity
Bases: object
x.__init__(...) initializes x; see help(type(x)) for signature
x.next() -> the next value, or raise StopIteration
Return True if x is a symbolic Expression.
EXAMPLES:
sage: from sage.symbolic.expression import is_Expression
sage: is_Expression(x)
True
sage: is_Expression(2)
False
sage: is_Expression(SR(2))
True
Return True if x is a symbolic equation.
EXAMPLES:
The following two examples are symbolic equations:
sage: from sage.symbolic.expression import is_SymbolicEquation
sage: is_SymbolicEquation(sin(x) == x)
True
sage: is_SymbolicEquation(sin(x) < x)
True
sage: is_SymbolicEquation(x)
False
This is not, since 2==3 evaluates to the boolean False:
sage: is_SymbolicEquation(2 == 3)
False
However here since both 2 and 3 are coerced to be symbolic, we obtain a symbolic equation:
sage: is_SymbolicEquation(SR(2) == SR(3))
True