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
This can transform a true relation 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 relations:
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, as 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()
2*sqrt(10)/(sqrt(3) + 5)
-
class
sage.symbolic.expression.
Expression
¶ 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
-
Order
(hold=False)¶ 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)
-
abs
(hold=False)¶ 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 use
unhold()
:sage: a = SR(-5).abs(hold=True); a.unhold() 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
-
add
(hold=False, *args)¶ 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 use
unhold()
:sage: a = x.add(x, hold=True); a.unhold() 2*x
-
add_to_both_sides
(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)
-
arccos
(hold=False)¶ 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 use
unhold()
:sage: a = SR(1).arccos(hold=True); a.unhold() 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
-
arccosh
(hold=False)¶ 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 use
unhold()
:sage: a = SR(-1).arccosh(hold=True); a.unhold() I*pi
TESTS:
sage: SR(oo).arccosh() +Infinity sage: SR(-oo).arccosh() +Infinity sage: SR(unsigned_infinity).arccosh() +Infinity
-
arcsin
(hold=False)¶ 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() 1/6*pi 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 use
unhold()
:sage: a = SR(0).arcsin(hold=True); a.unhold() 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
-
arcsinh
(hold=False)¶ 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 use
unhold()
:sage: a = SR(-2).arcsinh(hold=True); a.unhold() -arcsinh(2)
TESTS:
sage: SR(oo).arcsinh() +Infinity sage: SR(-oo).arcsinh() -Infinity sage: SR(unsigned_infinity).arcsinh() Infinity
-
arctan
(hold=False)¶ 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 use
unhold()
:sage: a = SR(1).arctan(hold=True); a.unhold() 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
-
arctan2
(x, hold=False)¶ 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 use
unhold()
:sage: a = SR(1/2).arctan2(1/2, hold=True); a.unhold() 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 NaN 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
-
arctanh
(hold=False)¶ 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 use
unhold()
:sage: a = SR(-1/2).arctanh(hold=True); a.unhold() -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
-
args
()¶ 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,)
-
arguments
()¶ 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
()¶ Assume that this equation holds. This is relevant for symbolic integration, among other things.
EXAMPLES: We call the assume method to assume that \(x>2\):
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()
-
binomial
(k, hold=False)¶ 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 use
unhold()
:sage: a = SR(5).binomial(3, hold=True); a.unhold() 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
-
canonicalize_radical
()¶ Choose a canonical branch of the given expression. The square root, cube root, natural log, etc. functions are multi-valued. The
canonicalize_radical()
method will choose one of these values based on a heuristic.For example,
sqrt(x^2)
has two values:x
, and-x
. Thecanonicalize_radical()
function will choose one of them, consistently, based on the behavior of the expression asx
tends to positive infinity. The solution chosen is the one which exhibits this same behavior. Sincesqrt(x^2)
approaches positive infinity asx
does, the solution chosen isx
(which also tends to positive infinity).Warning
As shown in the examples below, a canonical form is not always returned, i.e., two mathematically identical expressions might be converted to different expressions.
Assumptions are not taken into account during the transformation. This may result in a branch choice inconsistent with your assumptions.
ALGORITHM:
This uses the Maxima
radcan()
command. From the Maxima documentation:Simplifies an expression, which can contain logs, exponentials, and radicals, by converting it into a form which is canonical over a large class of expressions and a given ordering of variables; that is, all functionally equivalent forms are mapped into a unique form. For a somewhat larger class of expressions, radcan 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.
EXAMPLES:
canonicalize_radical()
can perform some of the same manipulations aslog_expand()
:sage: y = SR.symbol('y') sage: f = log(x*y) sage: f.log_expand() log(x) + log(y) sage: f.canonicalize_radical() log(x) + log(y)
And also handles some exponential functions:
sage: f = (e^x-1)/(1+e^(x/2)) sage: f.canonicalize_radical() e^(1/2*x) - 1
It can also be used to change the base of a logarithm when the arguments to
log()
are positive real numbers:sage: f = log(8)/log(2) sage: f.canonicalize_radical() 3
sage: a = SR.symbol('a') sage: f = (log(x+x^2)-log(x))^a/log(1+x)^(a/2) sage: f.canonicalize_radical() log(x + 1)^(1/2*a)
The simplest example of counter-intuitive behavior is what happens when we take the square root of a square:
sage: sqrt(x^2).canonicalize_radical() x
If you don’t want this kind of “simplification,” don’t use
canonicalize_radical()
.This behavior can also be triggered when the expression under the radical is not given explicitly as a square:
sage: sqrt(x^2 - 2*x + 1).canonicalize_radical() x - 1
Another place where this can become confusing is with logarithms of complex numbers. Suppose
x
is complex withx == r*e^(I*t)
(r
real). Thenlog(x)
islog(r) + I*(t + 2*k*pi)
for some integerk
.Calling
canonicalize_radical()
will choose a branch, eliminating the solutions for all choices ofk
but one. Simplified by hand, the expression below is(1/2)*log(2) + I*pi*k
for integerk
. However,canonicalize_radical()
will take each log expression, and choose one particular solution, dropping the other. When the results are subtracted, we’re left with no imaginary part:sage: f = (1/2)*log(2*x) + (1/2)*log(1/x) sage: f.canonicalize_radical() 1/2*log(2)
Naturally the result is wrong for some choices of
x
:sage: f(x = -1) I*pi + 1/2*log(2)
The example below shows two expressions e1 and e2 which are “simplified” to different expressions, while their difference is “simplified” to zero; thus
canonicalize_radical()
does not return a canonical form:sage: e1 = 1/(sqrt(5)+sqrt(2)) sage: e2 = (sqrt(5)-sqrt(2))/3 sage: e1.canonicalize_radical() 1/(sqrt(5) + sqrt(2)) sage: e2.canonicalize_radical() 1/3*sqrt(5) - 1/3*sqrt(2) sage: (e1-e2).canonicalize_radical() 0
The issue reported in trac ticket #3520 is a case where
canonicalize_radical()
causes a numerical integral to be calculated incorrectly:sage: f1 = sqrt(25 - x) * sqrt( 1 + 1/(4*(25-x)) ) sage: f2 = f1.canonicalize_radical() sage: numerical_integral(f1.real(), 0, 1)[0] # abs tol 1e-10 4.974852579915647 sage: numerical_integral(f2.real(), 0, 1)[0] # abs tol 1e-10 -4.974852579915647
TESTS:
This tests that trac ticket #11668 has been fixed (by trac ticket #12780):
sage: a,b = var('a b', domain='real') sage: A = abs((a+I*b))^2 sage: imag(A) 0 sage: A.canonicalize_radical() # not implemented a^2 + b^2 sage: imag(A.canonicalize_radical()) 0
Ensure that deprecation warnings are thrown for the old “simplify” aliases:
sage: x.simplify_radical() doctest...: DeprecationWarning: simplify_radical is deprecated. Please use canonicalize_radical instead. See http://trac.sagemath.org/11912 for details. x sage: x.radical_simplify() doctest...: DeprecationWarning: radical_simplify is deprecated. Please use canonicalize_radical instead. See http://trac.sagemath.org/11912 for details. x sage: x.simplify_exp() doctest...: DeprecationWarning: simplify_exp is deprecated. Please use canonicalize_radical instead. See http://trac.sagemath.org/11912 for details. x sage: x.exp_simplify() doctest...: DeprecationWarning: exp_simplify is deprecated. Please use canonicalize_radical instead. See http://trac.sagemath.org/11912 for details. x
-
coeff
(*args, **kwds)¶ Deprecated: Use
coefficient()
instead. See trac ticket #17438 for details.
-
coefficient
(s, n=1)¶ Return the coefficient of \(s^n\) in this symbolic expression.
INPUT:
s
- expressionn
- integer, default 1
OUTPUT:
A symbolic expression. The coefficient of \(s^n\).
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.coefficient(x*y) z^2 sage: f.coefficient(x*y, 2) Traceback (most recent call last): ... TypeError: n != 1 only allowed for s being a variable
Using
coeff()
is now deprecated (trac ticket #17438):sage: x.coeff(x) doctest:...: DeprecationWarning: coeff is deprecated. Please use coefficient instead. See http://trac.sagemath.org/17438 for details. 1
-
coefficients
(x=None, sparse=True)¶ Return the coefficients of this symbolic expression as a polynomial in x.
INPUT:
x
– optional variable.
OUTPUT:
Depending on the value of
sparse
,- A list of pairs
(expr, n)
, whereexpr
is a symbolic expression andn
is a power (sparse=True
, default) - A list of expressions where the
n
-th element is the coefficient ofx^n
when self is seen as polynomial inx
(sparse=False
).
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.coefficients(sparse=False) [1, 3, 2] sage: p = x - x^3 + 5/7*x^5 sage: p.coefficients() [[1, 1], [-1, 3], [5/7, 5]] sage: p.coefficients(sparse=False) [0, 1, 0, -1, 0, 5/7] 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(a, sparse=False) [x^2 + x + 1, -2*sqrt(2)*x, 2] sage: p.coefficients(x) [[2*a^2 + 1, 0], [-2*sqrt(2)*a + 1, 1], [1, 2]] sage: p.coefficients(x, sparse=False) [2*a^2 + 1, -2*sqrt(2)*a + 1, 1]
TESTS:
The behaviour is undefined with noninteger or negative exponents:
sage: p = (17/3*a)*x^(3/2) + x*y + 1/x + 2*x^x + 5*x^y sage: rset = set([(1, -1), (y, 1), (17/3*a, 3/2), (2, x), (5, y)]) sage: all([(pair[0],pair[1]) in rset for pair in p.coefficients(x)]) True sage: p.coefficients(x, sparse=False) Traceback (most recent call last): ... ValueError: Cannot return dense coefficient list with noninteger exponents.
Using
coeffs()
is now deprecated (trac ticket #17438):sage: x.coeffs() doctest:...: DeprecationWarning: coeffs is deprecated. Please use coefficients instead. See http://trac.sagemath.org/17438 for details. [[1, 1]]
Series coefficients are now handled correctly (trac ticket #17399):
sage: s=(1/(1-x)).series(x,6); s 1 + 1*x + 1*x^2 + 1*x^3 + 1*x^4 + 1*x^5 + Order(x^6) sage: s.coefficients() [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5]] sage: s.coefficients(x, sparse=False) [1, 1, 1, 1, 1, 1] sage: x,y = var("x,y") sage: s=(1/(1-y*x-x)).series(x,3); s 1 + (y + 1)*x + ((y + 1)^2)*x^2 + Order(x^3) sage: s.coefficients(x, sparse=False) [1, y + 1, (y + 1)^2]
We can find coefficients of symbolic functions, trac ticket #12255:
sage: g = function('g')(var('t')) sage: f = 3*g + g**2 + t sage: f.coefficients(g) [[t, 0], [3, 1], [1, 2]]
Handle bound variable strictly as part of a constant:
sage: (sin(1+x)*sin(1+x^2)).coefficients(x) [[sin(x^2 + 1)*sin(x + 1), 0]] sage: (sin(1+x)*sin(1+x^2)*x).coefficients(x) [[sin(x^2 + 1)*sin(x + 1), 1]]
-
coeffs
(*args, **kwds)¶ Deprecated: Use
coefficients()
instead. See trac ticket #17438 for details.
-
collect
(s)¶ Collect the coefficients of
s
into a group.INPUT:
s
– the symbol whose coefficients will be collected.
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 beforecollect()
.EXAMPLES:
In the first term of \(f\), \(x\) has a coefficient of \(4y\). In the second term, \(x\) has a coefficient of \(z\). Therefore, if we collect those coefficients, \(x\) will have a coefficient of \(4y+z\):
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 \(y\) and \(z\); however, note that we do not factor the \(y^{2}\) and \(z^{2}\) 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 \(z\) will not be present in \(f\) below since \(f\) is a random polynomial of maximum degree 10 in \(x\) and \(y\):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
-
collect_common_factors
()¶ 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
-
combine
(deep=False)¶ Return a simplified version of this symbolic expression by combining all toplevel terms with the same denominator into a single term.
Please use the keyword
deep=True
to apply the process recursively.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) sage: (1/x + 1/x^2 + (x+1)/x).combine() (x + 2)/x + 1/x^2 sage: ex = 1/x + ((x + 1)/x - 1/x)/x^2 + (x+1)/x; ex (x + 1)/x + 1/x + ((x + 1)/x - 1/x)/x^2 sage: ex.combine() (x + 2)/x + ((x + 1)/x - 1/x)/x^2 sage: ex.combine(deep=True) (x + 2)/x + 1/x^2 sage: (1+sin((x + 1)/x - 1/x)).combine(deep=True) sin(1) + 1
-
conjugate
(hold=False)¶ 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 use
unhold()
:sage: a = SR(I).conjugate(hold=True); a.unhold() -I
-
content
(s)¶ Return the content of this expression when considered as a polynomial in
s
.See also
unit()
,primitive_part()
, andunit_content_primitive()
.INPUT:
s
– a symbolic expression.
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 thecontent()
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
-
contradicts
(soln)¶ 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
-
convert
(target=None)¶ Call the convert function in the units package. For symbolic variables that are not units, this function just returns the variable.
INPUT:
self
– the symbolic expression converting fromtarget
– (default None) the symbolic expression converting to
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
-
cos
(hold=False)¶ 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 use
unhold()
:sage: a = pi.cos(hold=True); a.unhold() -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
-
cosh
(hold=False)¶ Return cosh of self.
We have \(\cosh(x) = (e^{x} + e^{-x})/2\).
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 use
unhold()
:sage: a = arcsinh(x).cosh(hold=True); a.unhold() 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
-
csgn
(hold=False)¶ 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)
-
decl_assume
(decl)¶ TESTS:
sage: from sage.symbolic.assumptions import GenericDeclaration sage: decl = GenericDeclaration(x, 'real') sage: x.is_real() False sage: x.decl_assume(decl._assumption) sage: x.is_real() True
-
decl_forget
(decl)¶ TESTS:
sage: from sage.symbolic.assumptions import GenericDeclaration sage: decl = GenericDeclaration(x, 'integer') sage: x.is_integer() False sage: x.decl_assume(decl._assumption) sage: x.is_integer() True sage: x.decl_forget(decl._assumption) sage: x.is_integer() False
-
default_variable
()¶ Return the default variable, which is by definition the first variable in self, or \(x\) 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)
-
degree
(s)¶ 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
-
denominator
(normalize=True)¶ Return the denominator of this symbolic expression
INPUT:
normalize
– (default:True
) a boolean.
If
normalize
isTrue
, the expression is first normalized to have it as a fraction before getting the denominator.If
normalize
isFalse
, 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
-
derivative
(*args)¶ 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
_derivative
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.
-
diff
(*args)¶ 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
_derivative
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.
-
differentiate
(*args)¶ 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
_derivative
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.
-
divide_both_sides
(x, checksign=None)¶ 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
-
exp
(hold=False)¶ 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 use
unhold()
:sage: a = (pi*I).exp(hold=True); a.unhold() -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
-
exp_simplify
(*args, **kwds)¶ Deprecated: Use
canonicalize_radical()
instead. See trac ticket #11912 for details.
-
expand
(side=None)¶ 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 \((x-y)^5\) 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^2 + 2*x*y + y^2) + sin(x^2 + 2*x*y + y^2)^2
Observe that
expand()
also expands function arguments:sage: f(x) = function('f')(x) sage: fx = f(x*(x+1)); fx f((x + 1)*x) sage: fx.expand() f(x^2 + x)
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 sage: a,b,c = var('a,b,c') sage: x,y = var('x,y', domain='real') sage: p,q = var('p,q', domain='positive') sage: (c/2*(5*(3*a*b*x*y*p*q)^2)^(7/2*c)).expand() 1/2*45^(7/2*c)*(a^2*b^2)^(7/2*c)*c*p^(7*c)*q^(7*c)*(x^2)^(7/2*c)*(y^2)^(7/2*c) sage: ((-(-a*x*p)^3*(b*y*p)^3)^(c/2)).expand() (a^3*b^3*x^3*y^3)^(1/2*c)*p^(3*c) sage: x,y,p,q = var('x,y,p,q', domain='complex')
Check that trac ticket #18568 is fixed:
sage: ((x+sqrt(2)*x)^2).expand() 2*sqrt(2)*x^2 + 3*x^2
Check that trac ticket #21360 is fixed:
sage: ((x^(x/2) + 1)^2).expand() 2*x^(1/2*x) + x^x + 1 sage: ((x^(1/2*x))^2).expand() x^x sage: ((x^(2*x))^2).expand() x^(4*x)
Check that exactness is preserved:
sage: ((x+1.001)^2).expand() x^2 + 2.00200000000000*x + 1.00200100000000 sage: ((x+1.001)^3).expand() x^3 + 3.00300000000000*x^2 + 3.00600300000000*x + 1.00300300100000
Check that trac ticket #21302 is fixed:
sage: ((x+1)^-2).expand() 1/(x^2 + 2*x + 1) sage: (((x-1)/(x+1))^2).expand() x^2/(x^2 + 2*x + 1) - 2*x/(x^2 + 2*x + 1) + 1/(x^2 + 2*x + 1)
-
expand_log
(algorithm='products')¶ 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 simplifiedalgorithm
- (default: ‘products’) optional, governs which expression is expanded. Possible values are- ‘nothing’ (no expansion),
- ‘powers’ (log(a^r) is expanded),
- ‘products’ (like ‘powers’ and also log(a*b) are expanded),
- ‘all’ (all possible expansion).
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()
andexpand_log()
are the sameEXAMPLES:
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 withalgorithm='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 thedomain
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:
- Robert Marik (11-2009)
-
expand_rational
(side=None)¶ 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 \((x-y)^5\) 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^2 + 2*x*y + y^2) + sin(x^2 + 2*x*y + y^2)^2
Observe that
expand()
also expands function arguments:sage: f(x) = function('f')(x) sage: fx = f(x*(x+1)); fx f((x + 1)*x) sage: fx.expand() f(x^2 + x)
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 sage: a,b,c = var('a,b,c') sage: x,y = var('x,y', domain='real') sage: p,q = var('p,q', domain='positive') sage: (c/2*(5*(3*a*b*x*y*p*q)^2)^(7/2*c)).expand() 1/2*45^(7/2*c)*(a^2*b^2)^(7/2*c)*c*p^(7*c)*q^(7*c)*(x^2)^(7/2*c)*(y^2)^(7/2*c) sage: ((-(-a*x*p)^3*(b*y*p)^3)^(c/2)).expand() (a^3*b^3*x^3*y^3)^(1/2*c)*p^(3*c) sage: x,y,p,q = var('x,y,p,q', domain='complex')
Check that trac ticket #18568 is fixed:
sage: ((x+sqrt(2)*x)^2).expand() 2*sqrt(2)*x^2 + 3*x^2
Check that trac ticket #21360 is fixed:
sage: ((x^(x/2) + 1)^2).expand() 2*x^(1/2*x) + x^x + 1 sage: ((x^(1/2*x))^2).expand() x^x sage: ((x^(2*x))^2).expand() x^(4*x)
Check that exactness is preserved:
sage: ((x+1.001)^2).expand() x^2 + 2.00200000000000*x + 1.00200100000000 sage: ((x+1.001)^3).expand() x^3 + 3.00300000000000*x^2 + 3.00600300000000*x + 1.00300300100000
Check that trac ticket #21302 is fixed:
sage: ((x+1)^-2).expand() 1/(x^2 + 2*x + 1) sage: (((x-1)/(x+1))^2).expand() x^2/(x^2 + 2*x + 1) - 2*x/(x^2 + 2*x + 1) + 1/(x^2 + 2*x + 1)
-
expand_sum
()¶ For every symbolic sum in the given expression, try to expand it, symbolically or numerically.
While symbolic sum expressions with constant limits are evaluated immediately on the command line, unevaluated sums of this kind can result from, e.g., substitution of limit variables.
INPUT:
self
- symbolic expression
EXAMPLES:
sage: (k,n) = var('k,n') sage: ex = sum(abs(-k*k+n),k,1,n)(n=8); ex sum(abs(-k^2 + 8), k, 1, 8) sage: ex.expand_sum() 162 sage: f(x,k) = sum((2/n)*(sin(n*x)*(-1)^(n+1)), n, 1, k) sage: f(x,2) -2*sum((-1)^n*sin(n*x)/n, n, 1, 2) sage: f(x,2).expand_sum() -sin(2*x) + 2*sin(x)
We can use this to do floating-point approximation as well:
sage: (k,n) = var('k,n') sage: f(n)=sum(sqrt(abs(-k*k+n)),k,1,n) sage: f(n=8) sum(sqrt(abs(-k^2 + 8)), k, 1, 8) sage: f(8).expand_sum() sqrt(41) + sqrt(17) + 2*sqrt(14) + 3*sqrt(7) + 2*sqrt(2) + 3 sage: f(8).expand_sum().n() 31.7752256945384
See trac ticket #9424 for making the following no longer raise an error:
sage: f(8).n() 31.7752256945384
-
expand_trig
(full=False, half_angles=False, plus=True, times=True)¶ 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:
full
- (default: False) To enhance user control of simplification, this function expands only one level at a time by default, expanding sums of angles or multiple angles. To obtain full expansion into sines and cosines immediately, set the optional parameter full to True.half_angles
- (default: False) If True, causes half-angles to be simplified away.plus
- (default: True) Controls the sum rule; expansion of sums (e.g. ‘sin(x + y)’) will take place only if plus is True.times
- (default: True) Controls the product rule, expansion of products (e.g. sin(2*x)) will take place only if times is True.
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()
andexpand_trig()
are the same
-
factor
(dontfactor=[])¶ Factor the expression, containing any number of variables or functions, into factors irreducible over the integers.
INPUT:
self
- a symbolic expressiondontfactor
- list (default: []), a list of variables with respect to which factoring is not to occur. Factoring also will not take place with respect to any variables which are less important (using the variable ordering assumed for CRE form) than those on the ‘dontfactor’ list.
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)
TESTS:
Check that trac ticket #21529 is fixed:
sage: f(x) = function('f')(x) sage: (f(x).diff(x)^2-1).factor() (diff(f(x), x) + 1)*(diff(f(x), x) - 1)
-
factor_list
(dontfactor=[])¶ Return a list of the factors of self, as computed by the factor command.
INPUT:
self
- a symbolic expressiondontfactor
- see docs forfactor()
Note
If you already have a factored expression and just want to get at the individual factors, use the
_factor_list
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))]
-
factorial
(hold=False)¶ 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 use
unhold()
:sage: a = SR(5).factorial(hold=True); a.unhold() 120
-
factorial_simplify
()¶ 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 \(full_simplify()\) 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
(pattern)¶ 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]
-
find_local_maximum
(a, b, var=None, tol=1.48e-08, maxfun=500)¶ 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...)
-
find_local_minimum
(a, b, var=None, tol=1.48e-08, maxfun=500)¶ 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 thatself
must be a function of (at most) one variable.INPUT:
var
- variable (default: first variable in self)a,b
- endpoints of interval on which to minimize self.tol
- the convergence tolerancemaxfun
- maximum function evaluations
OUTPUT:
A tuple
(minval, x)
, whereminval
– float. The minimum value that self takes on in the interval[a,b]
.x
– float. The point at which self takes on the minimum value.
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:
- William Stein (2007-12-07)
-
find_root
(a, b, var=None, xtol=1e-12, rtol=0, maxiter=100, full_output=False)¶ 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:
a, b
- endpoints of the intervalvar
- optional variablextol, rtol
- the routine converges when a root is known to lie within xtol of the value return. Should be >= 0. The routine modifies this to take into account the relative precision of doubles.maxiter
- integer; if convergence is not achieved in maxiter iterations, an error is raised. Must be >= 0.full_output
- bool (default: False), if True, also return object that contains information about convergence.
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.canonicalize_radical(); b -23040.0*(-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
()¶ 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)
-
fraction
(base_ring)¶ Return this expression as element of the algebraic fraction field over the base ring given.
EXAMPLES:
sage: fr = (1/x).fraction(ZZ); fr 1/x sage: parent(fr) Fraction Field of Univariate Polynomial Ring in x over Integer Ring sage: parent(((pi+sqrt(2)/x).fraction(SR))) Fraction Field of Univariate Polynomial Ring in x over Symbolic Ring sage: parent(((pi+sqrt(2))/x).fraction(SR)) Fraction Field of Univariate Polynomial Ring in x over Symbolic Ring sage: y=var('y') sage: fr=((3*x^5 - 5*y^5)^7/(x*y)).fraction(GF(7)); fr (3*x^35 + 2*y^35)/(x*y) sage: parent(fr) Fraction Field of Multivariate Polynomial Ring in x, y over Finite Field of size 7
TESTS:
Check that trac ticket #17736 is fixed:
sage: a,b,c = var('a,b,c') sage: fr = (1/a).fraction(QQ); fr 1/a sage: parent(fr) Fraction Field of Univariate Polynomial Ring in a over Rational Field sage: parent((b/(a+sin(c))).fraction(SR)) Fraction Field of Multivariate Polynomial Ring in a, b over Symbolic Ring
-
full_simplify
()¶ Apply
simplify_factorial()
,simplify_rectform()
,simplify_trig()
,simplify_rational()
, and thenexpand_sum()
to self (in that order).ALIAS:
simplify_full
andfull_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 \((x + 1)^2\), so this should not be simplified to \(x + 1\), see 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) sage: forget()
Complex logs are not contracted, trac ticket #17556:
sage: x,y = SR.var('x,y') sage: assume(y, 'complex') sage: f = log(x*y) - (log(x) + log(y)) sage: f.simplify_full() log(x*y) - log(x) - log(y) sage: forget()
The simplifications from
simplify_rectform()
are performed, trac ticket #17556:sage: f = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) ) sage: f.simplify_full() sin(x)/cos(x)
-
function
(*args)¶ 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 \(f\), 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 \(f\) 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
-
gamma
(hold=False)¶ 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 use
unhold()
:sage: a = SR(1/2).gamma(hold=True); a.unhold() sqrt(pi)
-
gcd
(b)¶ Return the gcd of self and b.
Note that the polynomial GCD is unique up to the multiplication by an invertible constant. The following examples make sure all results are caught.
EXAMPLES:
sage: var('x,y') (x, y) sage: SR(10).gcd(SR(15)) 5 sage: (x^3 - 1).gcd(x-1) / (x-1) in QQ True sage: (x^3 - 1).gcd(x^2+x+1) / (x^2+x+1) in QQ True sage: (x^3 - x^2*pi + x^2 - pi^2).gcd(x-pi) / (x-pi) in QQ True sage: gcd(sin(x)^2 + sin(x), sin(x)^2 - 1) / (sin(x) + 1) in QQ True sage: gcd(x^3 - y^3, x-y) / (x-y) in QQ True sage: gcd(x^100-y^100, x^10-y^10) / (x^10-y^10) in QQ True sage: r = 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)) ) sage: r / (x^5 - 17*y + 2/3) in QQ True
TESTS:
Check if trac ticket #10284 is fixed:
sage: u = var('u') sage: v = var('v') sage: w = var('w') sage: x = var('x') sage: y = var('y') sage: z = var('z') sage: e = 792*z^8*w^4*x^3*y^4*u^7 + 24*z^4*w^4*x^2*y^3*u^4 + \ 264*z^8*w^3*x^2*y^7*u^5 + 198*z^4*w^5*x^5*y*u^6 + 110*z^2*w^3*x^5*y^4*u^6 \ - 120*z^8*w*x^4*u^6 - 480*z^5*w*x^4*y^6*u^8 - 720*z^7*x^3*y^3*u^7 + \ 165*z^4*w^2*x^4*y*u^5 + 450*z^8*w^6*x^2*y*u^8 + 40*z^2*w^3*x^3*y^3*u^6 - \ 288*z^7*w^2*x^3*y^6*u^6 + 250*z^6*w^4*x^2*y^4*u^8 + \ 576*z^7*w^7*x^2*y^4*u^8 - 80*z^6*w^2*x^5*y^3*u^7 - 144*z^8*w^4*x^5*u^7 + \ 120*z^4*w*x^2*y^6*u^6 + 320*z^5*w^5*x^2*y^7*u^8 + 192*z^7*w^6*x*y^7*u^6 - \ 12*z^4*w^3*x^3*y^5*u^6 - 36*z^4*w^4*x^4*y^2*u^8 + 72*z^4*w^5*x^3*u^6 - \ 20*z^2*w^2*x^4*y^5*u^8 + 660*z^8*w*x^2*y^4*u^6 + 66*z^4*w^4*x^4*y^4*u^4 + \ 440*z^6*w^2*x^3*y^7*u^7 - 30*z^4*w*x^3*y^2*u^7 - 48*z^8*w^3*x^4*y^3*u^5 + \ 72*z^6*w^2*x*y^6*u^4 - 864*z^7*w^3*x^4*y^3*u^8 + 480*z^7*w^4*x*y^4*u^7 + \ 60*z^4*w^2*x^2*u^5 + 375*z^8*w^3*x*y*u^7 + 150*z^8*w^5*x*y^4*u^6 + \ 180*z^6*x*y^3*u^5 + 216*z^6*w^3*x^2*y^3*u^6; sage: d = e.diff(x) sage: gcd(d,e) / (u^4*z^2) in QQ # known bug True
-
gradient
(variables=None)¶ 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))
-
has
(pattern)¶ 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).coefficient(x,1) -1 sage: (4*x^2 + x + 3).coefficient(x,1) 1
-
has_wild
()¶ Return
True
if this expression contains a wildcard.EXAMPLES:
sage: (1 + x^2).has_wild() False sage: (SR.wild(0) + x^2).has_wild() True sage: SR.wild(0).has_wild() True
-
hessian
()¶ 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]
-
horner
(x)¶ Rewrite this expression as a polynomial in Horner form in
x
.EXAMPLES:
sage: add((i+1)*x^i for i in range(5)).horner(x) (((5*x + 4)*x + 3)*x + 2)*x + 1 sage: x, y, z = SR.var('x,y,z') sage: (x^5 + y*cos(x) + z^3 + (x + y)^2 + y^x).horner(x) z^3 + ((x^3 + 1)*x + 2*y)*x + y^2 + y*cos(x) + y^x sage: expr = sin(5*x).expand_trig(); expr 5*cos(x)^4*sin(x) - 10*cos(x)^2*sin(x)^3 + sin(x)^5 sage: expr.horner(sin(x)) (5*cos(x)^4 - (10*cos(x)^2 - sin(x)^2)*sin(x)^2)*sin(x) sage: expr.horner(cos(x)) sin(x)^5 + 5*(cos(x)^2*sin(x) - 2*sin(x)^3)*cos(x)^2
TESTS:
sage: SR(0).horner(x), SR(1).horner(x), x.horner(x) (0, 1, x) sage: (x^(1/3)).horner(x) Traceback (most recent call last): ... ValueError: Cannot return dense coefficient list with noninteger exponents.
-
hypergeometric_simplify
(algorithm='maxima')¶ Simplify an expression containing hypergeometric or confluent hypergeometric functions.
INPUT:
algorithm
– (default:'maxima'
) the algorithm to use for for simplification. Implemented are'maxima'
, which uses Maxima’shgfred
function, and'sage'
, which uses an algorithm implemented in the hypergeometric module
ALIAS:
hypergeometric_simplify()
andsimplify_hypergeometric()
are the sameEXAMPLES:
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) sage: hypergeometric_M(1, 3, x).simplify_hypergeometric() -2*(x - e^x + 1)/x^2 sage: (2 * hypergeometric_U(1, 3, x)).simplify_hypergeometric() 2*(x + 1)/x^2
-
imag
(hold=False)¶ Return the imaginary part of this symbolic expression.
EXAMPLES:
sage: sqrt(-2).imag_part() sqrt(2)
We simplify \(\ln(\exp(z))\) to \(z\). This should only be for \(-\pi<{\rm Im}(z)<=\pi\), 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 use
unhold()
:sage: a = I.imag_part(hold=True); a.unhold() 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
-
imag_part
(hold=False)¶ Return the imaginary part of this symbolic expression.
EXAMPLES:
sage: sqrt(-2).imag_part() sqrt(2)
We simplify \(\ln(\exp(z))\) to \(z\). This should only be for \(-\pi<{\rm Im}(z)<=\pi\), 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 use
unhold()
:sage: a = I.imag_part(hold=True); a.unhold() 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
-
implicit_derivative
(Y, X, n=1)¶ Return the n’th derivative of Y with respect to X given implicitly by this expression.
INPUT:
Y
- The dependent variable of the implicit expression.X
- The independent variable with respect to which the derivative is taken.n
- (default : 1) the order of the derivative.
EXAMPLES:
sage: var('x, y') (x, y) sage: f = cos(x)*sin(y) sage: f.implicit_derivative(y, x) sin(x)*sin(y)/(cos(x)*cos(y)) sage: g = x*y^2 sage: g.implicit_derivative(y, x, 3) -1/4*(y + 2*y/x)/x^2 + 1/4*(2*y^2/x - y^2/x^2)/(x*y) - 3/4*y/x^3
It is an error to not include an independent variable term in the expression:
sage: (cos(x)*sin(x)).implicit_derivative(y, x) Traceback (most recent call last): ... ValueError: Expression cos(x)*sin(x) contains no y terms
TESTS:
Check that the symbols registry is not polluted:
sage: var('x,y') (x, y) sage: psr = copy(SR.symbols) sage: (x^6*y^5).implicit_derivative(y, x, 3) -792/125*y/x^3 + 12/25*(15*x^4*y^5 + 28*x^3*y^5)/(x^6*y^4) - 36/125*(20*x^5*y^4 + 43*x^4*y^4)/(x^7*y^3) sage: psr == SR.symbols True
-
integral
(*args, **kwds)¶ 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
-
integrate
(*args, **kwds)¶ 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
-
inverse_laplace
(t, s)¶ 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)
-
is_algebraic
()¶ Return True if this expression is known to be algebraic.
EXAMPLES:
sage: sqrt(2).is_algebraic() True sage: (5*sqrt(2)).is_algebraic() True sage: (sqrt(2) + 2^(1/3) - 1).is_algebraic() True sage: (I*golden_ratio + sqrt(2)).is_algebraic() True sage: (sqrt(2) + pi).is_algebraic() False sage: SR(QQ(2/3)).is_algebraic() True sage: SR(1.2).is_algebraic() False
-
is_constant
()¶ Return whether this symbolic expression is a constant.
A symbolic expression is constant if it does not contain any variables.
EXAMPLES:
sage: pi.is_constant() True sage: SR(1).is_constant() True sage: SR(2).is_constant() True sage: log(2).is_constant() True sage: I.is_constant() True sage: x.is_constant() False
TESTS:
sage: P.<p> = ZZ[] sage: SR(42).is_constant() == P(2).is_constant() True
-
is_infinity
()¶ Return True if self is an infinite expression.
EXAMPLES:
sage: SR(oo).is_infinity() True sage: x.is_infinity() False
-
is_integer
()¶ Return True if this expression is known to be an integer.
EXAMPLES:
sage: SR(5).is_integer() True
TESTS:
Check that integer variables are recognized (trac ticket #18921):
sage: _ = var('n', domain='integer') sage: n.is_integer() True
Assumption of integer has the same effect as setting the domain:
sage: forget() sage: assume(x, 'integer') sage: x.is_integer() True sage: forget()
-
is_negative
()¶ 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
-
is_negative_infinity
()¶ 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
-
is_numeric
()¶ A Pynac numeric is an object you can do arithmetic with that is not a symbolic variable, function, or constant. 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 sage: sin(x).is_numeric() False
-
is_polynomial
(var)¶ 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
Check that negative exponents are handled (trac ticket #15304):
sage: y = var('y') sage: (y/x).is_polynomial(x) False
-
is_positive
()¶ 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
sage: forget() sage: assume(x>0) sage: x.is_positive() True sage: f = function('f')(x) sage: assume(f>0) sage: f.is_positive() True sage: forget()
-
is_positive_infinity
()¶ 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
-
is_real
()¶ 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
Assumption of real has the same effect as setting the domain:
sage: forget() sage: assume(x, 'real') sage: x.is_real() True sage: forget()
-
is_relational
()¶ 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
-
is_series
()¶ TESTS:
sage: x.is_series() doctest:...: DeprecationWarning: ex.is_series() is deprecated. Use isinstance(ex, sage.symbolic.series.SymbolicSeries) instead See http://trac.sagemath.org/17659 for details. False
-
is_symbol
()¶ 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
-
is_terminating_series
()¶ 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.
OUTPUT:
Boolean. Whether
self
was constructed byseries()
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_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
-
is_trivial_zero
()¶ 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
-
is_unit
()¶ 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
-
iterator
()¶ 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
-
laplace
(t, s)¶ 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)
-
lcm
(b)¶ Return the lcm of self and b.
The lcm 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.
Note
Since the polynomial lcm is computed from the gcd, and the polynomial gcd is unique up to a constant factor (which can be negative), the polynomial lcm is unique up to a factor of -1.
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) (pi - x^3)*(pi - x) sage: lcm(x^3 - y^3, x-y) / (x^3 - y^3) in [1,-1] True sage: lcm(x^100-y^100, x^10-y^10) / (x^100 - y^100) in [1,-1] True sage: l = 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)) ) sage: r = 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) sage: l / r in [1,-1] True
The result is not automatically simplified:
sage: ex = lcm(sin(x)^2 - 1, sin(x)^2 + sin(x)); ex (sin(x)^2 + sin(x))*(sin(x)^2 - 1)/(sin(x) + 1) sage: ex.simplify_full() -cos(x)^2*sin(x)
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)
-
leading_coeff
(s)¶ 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
-
leading_coefficient
(s)¶ 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
-
left
()¶ 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
-
left_hand_side
()¶ 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
-
lhs
()¶ 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
-
limit
(*args, **kwds)¶ Return a symbolic limit. See
sage.calculus.calculus.limit
EXAMPLES:
sage: (sin(x)/x).limit(x=0) 1
-
list
(x=None)¶ Return the coefficients of this symbolic expression as a polynomial in x.
INPUT:
x
– optional variable.
OUTPUT:
A list of expressions where the
n
-th element is the coefficient ofx^n
when self is seen as polynomial inx
.EXAMPLES:
sage: var('x, y, a') (x, y, a) sage: (x^5).list() [0, 0, 0, 0, 0, 1] sage: p = x - x^3 + 5/7*x^5 sage: p.list() [0, 1, 0, -1, 0, 5/7] 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.list(a) [x^2 + x + 1, -2*sqrt(2)*x, 2] sage: s=(1/(1-x)).series(x,6); s 1 + 1*x + 1*x^2 + 1*x^3 + 1*x^4 + 1*x^5 + Order(x^6) sage: s.list() [1, 1, 1, 1, 1, 1]
-
log
(b=None, hold=False)¶ 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 use
unhold()
:sage: a = I.log(hold=True); a.unhold() 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
-
log_expand
(algorithm='products')¶ 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 simplifiedalgorithm
- (default: ‘products’) optional, governs which expression is expanded. Possible values are- ‘nothing’ (no expansion),
- ‘powers’ (log(a^r) is expanded),
- ‘products’ (like ‘powers’ and also log(a*b) are expanded),
- ‘all’ (all possible expansion).
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()
andexpand_log()
are the sameEXAMPLES:
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 withalgorithm='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 thedomain
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:
- Robert Marik (11-2009)
-
log_gamma
(hold=False)¶ Return the log gamma function evaluated at self. This is the logarithm of gamma of self, where gamma is a complex function such that \(gamma(n)\) equals \(factorial(n-1)\).
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
-
log_simplify
(algorithm=None)¶ Simplify a (real) symbolic expression that contains logarithms.
The given expression is scanned recursively, transforming subexpressions of the form \(a \log(b) + c \log(d)\) into \(\log(b^{a} d^{c})\) before simplifying within the
log()
.The user can specify conditions that \(a\) and \(c\) must satisfy before this transformation will be performed using the optional parameter
algorithm
.Warning
This is only safe to call if every variable in the given expression is assumed to be real. The simplification it performs is in general not valid over the complex numbers. For example:
sage: x,y = SR.var('x,y') sage: f = log(x*y) - (log(x) + log(y)) sage: f(x=-1, y=i) -2*I*pi sage: f.simplify_log() 0
INPUT:
self
- expression to be simplifiedalgorithm
- (default: None) optional, governs the condition on \(a\) and \(c\) which must be satisfied to contract expression \(a \log(b) + c \log(d)\). Values areNone
(use Maxima default, integers),'one'
(1 and -1),'ratios'
(rational numbers),'constants'
(constants),'all'
(all expressions).
ALGORITHM:
This uses the Maxima
logcontract()
command.ALIAS:
log_simplify()
andsimplify_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 \(\frac{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 the previous example, we use the
'ratios'
algorithm
:sage: f.simplify_log(algorithm='ratios') log(sqrt(t)*x*y^2)
To contract terms with no coefficient (more precisely, with coefficients \(1\) and \(-1\)), we use the
'one'
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))
\(\pi\) is an irrational number; to contract logarithms in the following example we have to set
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 ifalgorithm
is'all'
:sage: (x*log(9)).simplify_log() x*log(9) sage: (x*log(9)).simplify_log('all') log(9^x)
TESTS:
Ensure that the option
algorithm
from one call has no influence upon future calls (a Maxima flag was set, and we have to ensure that its value has been restored):sage: f = log(x)+2*log(y)+1/2*log(t) 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)
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
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:
- Robert Marik (11-2009)
-
low_degree
(s)¶ 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
-
match
(pattern)¶ Check if self matches the given pattern.
INPUT:
pattern
– a symbolic expression, possibly containing wildcards to match for
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() <function mul_vararg ...>
Since asking to match w0+w1 looks for an addition operator, there is no match.
-
maxima_methods
()¶ 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'>
-
minpoly
(*args, **kwds)¶ Return the minimal polynomial of this symbolic expression.
EXAMPLES:
sage: golden_ratio.minpoly() x^2 - x - 1
-
mul
(hold=False, *args)¶ 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 use
unhold()
:sage: a = x.mul(x, hold=True); a.unhold() x^2
-
multiply_both_sides
(x, checksign=None)¶ 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)
-
negation
()¶ 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)
-
nintegral
(*args, **kwds)¶ 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)
-
nintegrate
(*args, **kwds)¶ 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)
-
nops
()¶ 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
-
norm
()¶ Return the complex norm of this symbolic expression, i.e., the expression times its complex conjugate. If \(c = a + bi\) is a complex number, then the norm of \(c\) is defined as the product of \(c\) and its complex conjugate
\[\text{norm}(c) = \text{norm}(a + bi) = c \cdot \overline{c} = a^2 + b^2.\]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 \(\ZZ[i]\) of Gaussian integers, where the norm of each Gaussian integer \(c = a + bi\) 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
-
normalize
()¶ Return this expression normalized as a fraction
See also
numerator()
,denominator()
,numerator_denominator()
,combine()
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))
TESTS:
Check that trac ticket #19775 is fixed:
sage: a,b,c,d,e,y = var('a,b,c,d,e,y') sage: ((x - 2*y)^4/(x^2 - 4*y^2)^2).normalize() (x - 2*y)^2/(x + 2*y)^2 sage: f = ((x - 2*y)^4/(x^2 - 4*y^2)^2 + 1)*(y + a)*(2*y + x) / (4*y^2 + x^2) sage: f.normalize() 2*(a + y)/(x + 2*y) sage: (c/a - b*c^2/(a^2*(b*c/a-d)) + c*d/(a*(b*c/a-d))).normalize() 0 sage: (e + c/a - b*c^2/(a^2*(b*c/a-d)) + c*d/(a*(b*c/a-d))).normalize() e
ALGORITHM: Uses GiNaC.
-
number_of_arguments
()¶ 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
-
number_of_operands
()¶ 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
-
numerator
(normalize=True)¶ Return the numerator of this symbolic expression
INPUT:
normalize
– (default:True
) a boolean.
If
normalize
isTrue
, the expression is first normalized to have it as a fraction before getting the numerator.If
normalize
isFalse
, 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
-
numerator_denominator
(normalize=True)¶ Return the numerator and the denominator of this symbolic expression
INPUT:
normalize
– (default:True
) a boolean.
If
normalize
isTrue
, the expression is first normalized to have it as a fraction before getting the numerator and denominator.If
normalize
isFalse
, 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
-
numerical_approx
(prec=None, digits=None, algorithm=None)¶ Return a numerical approximation of
self
withprec
bits (or decimaldigits
) of precision.No guarantee is made about the accuracy of the result.
INPUT:
prec
– precision in bitsdigits
– precision in decimal digits (only used ifprec
is not given)algorithm
– which algorithm to use to compute this approximation
If neither
prec
nordigits
is given, the default precision is 53 bits (roughly 16 digits).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
Symbolic sums with definite endpoints are expanded (trac ticket #9424):
sage: (k,n) = var('k,n') sage: f(n) = sum(abs(-k*k+n),k,1,n) sage: ex = f(n=8); ex sum(abs(-k^2 + 8), k, 1, 8) sage: ex.n() 162.000000000000 sage: (ex+1).n() 163.000000000000
-
op
¶ Provide access to the operands of an expression through a property.
EXAMPLES:
sage: t = 1+x+x^2 sage: t.op Operands of x^2 + x + 1 sage: x.op Traceback (most recent call last): ... TypeError: expressions containing only a numeric coefficient, constant or symbol have no operands sage: t.op[0] x^2
Indexing directly with
t[1]
causes problems with numpy types.sage: t[1] Traceback (most recent call last): ... TypeError: ‘sage.symbolic.expression.Expression’ object does not support indexing
-
operands
()¶ 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]
-
operator
()¶ Return the topmost operator in this expression.
EXAMPLES:
sage: x,y,z = var('x,y,z') sage: (x+y).operator() <function add_vararg ...> sage: (x^y).operator() <built-in function pow> sage: (x^y * z).operator() <function mul_vararg ...> 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 diff(f(x), 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'>
-
partial_fraction
(var=None)¶ Return the partial fraction expansion of
self
with respect to the given variable.INPUT:
var
- variable name or string (default: first variable)
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
(*args, **kwds)¶ 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) # long time 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
-
poly
(x=None)¶ 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
-
polynomial
(base_ring=None, ring=None)¶ 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:
base_ring
- (optional) the base ring for the polynomialring
- (optional) the parent for the polynomial
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) # abs tol 5e-16 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) # abs tol 5e-16 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) # abs tol 5e-16 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]
-
power
(exp, hold=False)¶ 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 use
unhold()
:sage: a = (x^2).power(2, hold=True); a.unhold() x^4
-
power_series
(base_ring)¶ 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
-
primitive_part
(s)¶ Return the primitive polynomial of this expression when considered as a polynomial in
s
.See also
unit()
,content()
, andunit_content_primitive()
.INPUT:
s
– a symbolic expression.
OUTPUT:
The primitive polynomial as a symbolic expression. It is defined as the quotient by the
unit()
andcontent()
parts (with respect to the variables
).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)
-
pyobject
()¶ 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.3000000000000 sage: a.pyobject() is b True
Integers and Rationals are converted internally though, so you won’t get back the same object:
sage: b = -17/3 sage: a = SR(b) sage: a.pyobject() -17/3 sage: a.pyobject() is b False
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.
-
radical_simplify
(*args, **kwds)¶ Deprecated: Use
canonicalize_radical()
instead. See trac ticket #11912 for details.
-
rational_expand
(side=None)¶ 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 \((x-y)^5\) 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^2 + 2*x*y + y^2) + sin(x^2 + 2*x*y + y^2)^2
Observe that
expand()
also expands function arguments:sage: f(x) = function('f')(x) sage: fx = f(x*(x+1)); fx f((x + 1)*x) sage: fx.expand() f(x^2 + x)
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 sage: a,b,c = var('a,b,c') sage: x,y = var('x,y', domain='real') sage: p,q = var('p,q', domain='positive') sage: (c/2*(5*(3*a*b*x*y*p*q)^2)^(7/2*c)).expand() 1/2*45^(7/2*c)*(a^2*b^2)^(7/2*c)*c*p^(7*c)*q^(7*c)*(x^2)^(7/2*c)*(y^2)^(7/2*c) sage: ((-(-a*x*p)^3*(b*y*p)^3)^(c/2)).expand() (a^3*b^3*x^3*y^3)^(1/2*c)*p^(3*c) sage: x,y,p,q = var('x,y,p,q', domain='complex')
Check that trac ticket #18568 is fixed:
sage: ((x+sqrt(2)*x)^2).expand() 2*sqrt(2)*x^2 + 3*x^2
Check that trac ticket #21360 is fixed:
sage: ((x^(x/2) + 1)^2).expand() 2*x^(1/2*x) + x^x + 1 sage: ((x^(1/2*x))^2).expand() x^x sage: ((x^(2*x))^2).expand() x^(4*x)
Check that exactness is preserved:
sage: ((x+1.001)^2).expand() x^2 + 2.00200000000000*x + 1.00200100000000 sage: ((x+1.001)^3).expand() x^3 + 3.00300000000000*x^2 + 3.00600300000000*x + 1.00300300100000
Check that trac ticket #21302 is fixed:
sage: ((x+1)^-2).expand() 1/(x^2 + 2*x + 1) sage: (((x-1)/(x+1))^2).expand() x^2/(x^2 + 2*x + 1) - 2*x/(x^2 + 2*x + 1) + 1/(x^2 + 2*x + 1)
-
rational_simplify
(algorithm='full', map=False)¶ Simplify rational expressions.
INPUT:
self
- symbolic expressionalgorithm
- (default: ‘full’) string which switches the algorithm for simplifications. Possible values are- ‘simple’ (simplify rational functions into quotient of two polynomials),
- ‘full’ (apply repeatedly, if necessary)
- ‘noexpand’ (convert to commmon denominator and add)
map
- (default: False) if True, the result is an expression whose leading operator is the same as that of the expressionself
but whose subparts are the results of applying simplification rules to the corresponding subparts of the expressions.
ALIAS:
rational_simplify()
andsimplify_rational()
are the sameDETAILS: 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 functions. 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))
-
real
(hold=False)¶ 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 use
unhold()
:sage: a = SR(2).real_part(hold=True); a.unhold() 2
TESTS:
Check that trac ticket #12807 is fixed:
sage: (6*exp(i*pi/3)-6*exp(i*2*pi/3)).real_part() 6
-
real_part
(hold=False)¶ 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 use
unhold()
:sage: a = SR(2).real_part(hold=True); a.unhold() 2
TESTS:
Check that trac ticket #12807 is fixed:
sage: (6*exp(i*pi/3)-6*exp(i*2*pi/3)).real_part() 6
-
rectform
()¶ Convert this symbolic expression to rectangular form; that is, the form \(a + bi\) where \(a\) and \(b\) are real numbers and \(i\) is the imaginary unit.
Note
The name “rectangular” comes from the fact that, in the complex plane, \(a\) and \(bi\) are perpendicular.
INPUT:
self
– the expression to convert.
OUTPUT:
A new expression, equivalent to the original, but expressed in the form \(a + bi\).
ALGORITHM:
We call Maxima’s
rectform()
and return the result unmodified.EXAMPLES:
The exponential form of \(\sin(x)\):
sage: f = (e^(I*x) - e^(-I*x)) / (2*I) sage: f.rectform() sin(x)
And \(\cos(x)\):
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, \(e^{ik\pi}\), \(\sin(k\pi)=0\) should cancel leaving only \(\cos(k\pi)\) 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
-
reduce_trig
(var=None)¶ 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:
self
- a symbolic expressionvar
- (default: None) the variable which is used for these transformations. If not specified, all variables are used.
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()
andreduce_trig()
are the same
-
residue
(symbol)¶ Calculate the residue of
self
with respect tosymbol
.INPUT:
symbol
- a symbolic variable or symbolic equality such asx == 5
. If an equality is given, the expansion is around the value on the right hand side of the equality, otherwise at0
.
OUTPUT:
The residue of
self
.Say,
symbol
isx == a
, then this function calculates the residue ofself
at \(x=a\), i.e., the coefficient of \(1/(x-a)\) of the series expansion ofself
around \(a\).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) 1
TESTS:
sage: (exp(x)/sin(x)^4).residue(x == 0) 5/6
Check that trac ticket #18372 is resolved:
sage: (1/(x^2 - x - 1)).residue(x == 1/2*sqrt(5) + 1/2) 1/5*sqrt(5)
-
rhs
()¶ 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
-
right
()¶ 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
-
right_hand_side
()¶ 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
-
roots
(x=None, explicit_solutions=True, multiplicities=True, ring=None)¶ 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:
x
- variable to view the function in terms of (use default variable if not given)explicit_solutions
- bool (default True); require that roots be explicit rather than implicitmultiplicities
- bool (default True); when True, return multiplicitiesring
- a ring (default None): if not None, convert self to a polynomial over ring and find roots over ring
OUTPUT:
A list of pairs
(root, multiplicity)
or list of roots.If there are infinitely many roots, e.g., a function like \(\sin(x)\), 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 \(a\), since it is the first in alphabetical order:
sage: f.roots() [(x, 1)]
As a polynomial in \(a\), \(x\) 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 \(x\) are what we expect:
sage: f.roots(x) [(a, 1), (-I, 1), (I, 1), (1, 3), (-1, 3)]
Only one root of \(\sin(x) = 0\) 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 keywordto_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
()¶ 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
-
series
(symbol, order=None)¶ Return the power series expansion of self in terms of the given variable to the given order.
INPUT:
symbol
- a symbolic variable or symbolic equality such asx == 5
; if an equality is given, the expansion is around the value on the right hand side of the equalityorder
- an integer; if nothing given, it is set to the global default (20
), which can be changed usingset_series_precision()
OUTPUT:
A power series.
To truncate the power series and obtain a normal expression, use the
truncate()
command.EXAMPLES:
We expand a polynomial in \(x\) about 0, about \(1\), 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*x^(-1) + (-1/6)*x + ... + Order(x^20) 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)
Expressions formed by combining series can be expanded by applying series again:
sage: (1/(1-x)).series(x, 3)+(1/(1+x)).series(x,3) (1 + 1*x + 1*x^2 + Order(x^3)) + (1 + (-1)*x + 1*x^2 + Order(x^3)) sage: _.series(x,3) 2 + 2*x^2 + Order(x^3) sage: (1/(1-x)).series(x, 3)*(1/(1+x)).series(x,3) (1 + 1*x + 1*x^2 + Order(x^3))*(1 + (-1)*x + 1*x^2 + Order(x^3)) sage: _.series(x,3) 1 + 1*x^2 + Order(x^3)
Following the GiNaC tutorial, we use John Machin’s amazing formula \(\pi = 16 \tan^{-1}(1/5) - 4 \tan^{-1}(1/239)\) to compute digits of \(\pi\). 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)
Order may be negative:
sage: f = sin(x)^(-2); f.series(x, -1) 1*x^(-2) + Order(1/x)
Check if changing global series precision does it right:
sage: set_series_precision(3) sage: (1/(1-2*x)).series(x) 1 + 2*x + 4*x^2 + Order(x^3) sage: set_series_precision(20)
-
show
()¶ Pretty-Print this symbolic expression
This typeset it nicely and prints it immediately.
OUTPUT:
This method does not return anything. Like
print
, output is sent directly to the screen.EXAMPLES:
sage: (x^2 + 1).show() <html><script type="math/tex">\newcommand{\Bold}[1]{\mathbf{#1}}x^{2} + 1</script></html>
-
simplify
()¶ 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_rectform()
simplify_factorial()
,simplify_log()
,simplify_real()
,simplify_hypergeometric()
,canonicalize_radical()
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_exp
(*args, **kwds)¶ Deprecated: Use
canonicalize_radical()
instead. See trac ticket #11912 for details.
-
simplify_factorial
()¶ 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 \(full_simplify()\) 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)
-
simplify_full
()¶ Apply
simplify_factorial()
,simplify_rectform()
,simplify_trig()
,simplify_rational()
, and thenexpand_sum()
to self (in that order).ALIAS:
simplify_full
andfull_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 \((x + 1)^2\), so this should not be simplified to \(x + 1\), see 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) sage: forget()
Complex logs are not contracted, trac ticket #17556:
sage: x,y = SR.var('x,y') sage: assume(y, 'complex') sage: f = log(x*y) - (log(x) + log(y)) sage: f.simplify_full() log(x*y) - log(x) - log(y) sage: forget()
The simplifications from
simplify_rectform()
are performed, trac ticket #17556:sage: f = ( e^(I*x) - e^(-I*x) ) / ( I*e^(I*x) + I*e^(-I*x) ) sage: f.simplify_full() sin(x)/cos(x)
-
simplify_hypergeometric
(algorithm='maxima')¶ Simplify an expression containing hypergeometric or confluent hypergeometric functions.
INPUT:
algorithm
– (default:'maxima'
) the algorithm to use for for simplification. Implemented are'maxima'
, which uses Maxima’shgfred
function, and'sage'
, which uses an algorithm implemented in the hypergeometric module
ALIAS:
hypergeometric_simplify()
andsimplify_hypergeometric()
are the sameEXAMPLES:
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) sage: hypergeometric_M(1, 3, x).simplify_hypergeometric() -2*(x - e^x + 1)/x^2 sage: (2 * hypergeometric_U(1, 3, x)).simplify_hypergeometric() 2*(x + 1)/x^2
-
simplify_log
(algorithm=None)¶ Simplify a (real) symbolic expression that contains logarithms.
The given expression is scanned recursively, transforming subexpressions of the form \(a \log(b) + c \log(d)\) into \(\log(b^{a} d^{c})\) before simplifying within the
log()
.The user can specify conditions that \(a\) and \(c\) must satisfy before this transformation will be performed using the optional parameter
algorithm
.Warning
This is only safe to call if every variable in the given expression is assumed to be real. The simplification it performs is in general not valid over the complex numbers. For example:
sage: x,y = SR.var('x,y') sage: f = log(x*y) - (log(x) + log(y)) sage: f(x=-1, y=i) -2*I*pi sage: f.simplify_log() 0
INPUT:
self
- expression to be simplifiedalgorithm
- (default: None) optional, governs the condition on \(a\) and \(c\) which must be satisfied to contract expression \(a \log(b) + c \log(d)\). Values areNone
(use Maxima default, integers),'one'
(1 and -1),'ratios'
(rational numbers),'constants'
(constants),'all'
(all expressions).
ALGORITHM:
This uses the Maxima
logcontract()
command.ALIAS:
log_simplify()
andsimplify_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 \(\frac{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 the previous example, we use the
'ratios'
algorithm
:sage: f.simplify_log(algorithm='ratios') log(sqrt(t)*x*y^2)
To contract terms with no coefficient (more precisely, with coefficients \(1\) and \(-1\)), we use the
'one'
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))
\(\pi\) is an irrational number; to contract logarithms in the following example we have to set
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 ifalgorithm
is'all'
:sage: (x*log(9)).simplify_log() x*log(9) sage: (x*log(9)).simplify_log('all') log(9^x)
TESTS:
Ensure that the option
algorithm
from one call has no influence upon future calls (a Maxima flag was set, and we have to ensure that its value has been restored):sage: f = log(x)+2*log(y)+1/2*log(t) 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)
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
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:
- Robert Marik (11-2009)
-
simplify_radical
(*args, **kwds)¶ Deprecated: Use
canonicalize_radical()
instead. See trac ticket #11912 for details.
-
simplify_rational
(algorithm='full', map=False)¶ Simplify rational expressions.
INPUT:
self
- symbolic expressionalgorithm
- (default: ‘full’) string which switches the algorithm for simplifications. Possible values are- ‘simple’ (simplify rational functions into quotient of two polynomials),
- ‘full’ (apply repeatedly, if necessary)
- ‘noexpand’ (convert to commmon denominator and add)
map
- (default: False) if True, the result is an expression whose leading operator is the same as that of the expressionself
but whose subparts are the results of applying simplification rules to the corresponding subparts of the expressions.
ALIAS:
rational_simplify()
andsimplify_rational()
are the sameDETAILS: 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 functions. 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))
-
simplify_real
()¶ Simplify the given expression over the real numbers. This allows the simplification of \(\sqrt{x^{2}}\) into \(\left|x\right|\) and the contraction of \(\log(x) + \log(y)\) into \(\log(xy)\).
INPUT:
self
– the expression to convert.
OUTPUT:
A new expression, equivalent to the original one under the assumption that the variables involved are real.
EXAMPLES:
sage: f = sqrt(x^2) sage: f.simplify_real() abs(x)
sage: y = SR.var('y') sage: f = log(x) + 2*log(y) sage: f.simplify_real() log(x*y^2)
TESTS:
We set the Maxima
domain
variable to ‘real’ before we call out to Maxima. When we return, however, we should set thedomain
back to what it was, rather than assuming that it was ‘complex’:sage: from sage.calculus.calculus import maxima sage: maxima('domain: real;') real sage: x.simplify_real() x sage: maxima('domain;') real sage: maxima('domain: complex;') complex
We forget the assumptions that our variables are real after simplification; make sure we don’t forget an assumption that existed before we were called:
sage: assume(x, 'real') sage: x.simplify_real() x sage: assumptions() [x is real] sage: forget()
We also want to be sure that we don’t forget assumptions on other variables:
sage: x,y,z = SR.var('x,y,z') sage: assume(y, 'integer') sage: assume(z, 'antisymmetric') sage: x.simplify_real() x sage: assumptions() [y is integer, z is antisymmetric] sage: forget()
No new assumptions should exist after the call:
sage: assumptions() [] sage: x.simplify_real() x sage: assumptions() []
-
simplify_rectform
(complexity_measure='string_length')¶ Attempt to simplify this expression by expressing it in the form \(a + bi\) where both \(a\) and \(b\) are real. This transformation is generally not a simplification, so we use the given
complexity_measure
to discard non-simplifications.INPUT:
self
– the expression to simplify.complexity_measure
– (default:sage.symbolic.complexity_measures.string_length
) a function taking a symbolic expression as an argument and returning a measure of that expressions complexity. IfNone
is supplied, the simplification will be performed regardless of the result.
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 \(\tan(x)\):
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 callrectform()
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
-
simplify_trig
(expand=True)¶ Optionally expand and then employ identities such as \(\sin(x)^2 + \cos(x)^2 = 1\), \(\cosh(x)^2 - \sinh(x)^2 = 1\), \(\sin(x)\csc(x) = 1\), or \(\tanh(x)=\sinh(x)/\cosh(x)\) to simplify expressions containing tan, sec, etc., to sin, cos, sinh, cosh.
INPUT:
self
- symbolic expressionexpand
- (default:True) if True, expands trigonometric and hyperbolic functions of sums of angles and of multiple angles occurring inself
first. For best results,self
should be expanded. See alsoexpand_trig()
to get more controls on this expansion.
ALIAS:
trig_simplify()
andsimplify_trig()
are the sameEXAMPLES:
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)
-
sin
(hold=False)¶ 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 use
unhold()
:sage: a = SR(0).sin(hold=True); a.unhold() 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
-
sinh
(hold=False)¶ Return sinh of self.
We have \(\sinh(x) = (e^{x} - e^{-x})/2\).
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 use
unhold()
: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
-
solve
(x, multiplicities=False, solution_dict=False, explicit_solutions=False, to_poly_solve=False)¶ Analytically solve the equation
self == 0
or a univariate inequality for the variable \(x\).Warning
This is not a numerical solver - use
find_root
to solve for self == 0 numerically on an interval.INPUT:
x
- variable(s) to solve formultiplicities
- bool (default: False); if True, return corresponding multiplicities. This keyword is incompatible withto_poly_solve=True
and does not make any sense when solving an inequality.solution_dict
- bool (default: False); if True or non-zero, return a list of dictionaries containing solutions. Not used when solving an inequality.explicit_solutions
- bool (default: False); require that all roots be explicit rather than implicit. Not used when solving an inequality.to_poly_solve
- bool (default: False) or string; use Maxima’sto_poly_solver
package to search for more possible solutions, but possibly encounter approximate solutions. This keyword is incompatible withmultiplicities=True
and is not used when solving an inequality. Settingto_poly_solve
to'force'
omits Maxima’s solve command (useful when some solutions of trigonometric equations are lost).
EXAMPLES:
sage: z = var('z') sage: (z^5 - 1).solve(z) [z == 1/4*sqrt(5) + 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, z == -1/4*sqrt(5) + 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, z == -1/4*sqrt(5) - 1/4*I*sqrt(-2*sqrt(5) + 10) - 1/4, z == 1/4*sqrt(5) - 1/4*I*sqrt(2*sqrt(5) + 10) - 1/4, 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 withr
, 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)]
In some cases it may be worthwhile to directly use
to_poly_solve
if one suspects some answers are being missed:sage: forget() 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*z...]
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]]
We use sympy for Diophantine equations, see
solve_diophantine()
sage: assume(x, 'integer') sage: assume(z, 'integer') sage: solve((x-z)^2==2, x) [] sage: forget()
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) # random [[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)]
-
solve_diophantine
(x=None, solution_dict=False)¶ Solve a polynomial equation in the integers (a so called Diophantine).
If the argument is just a polynomial expression, equate to zero. If
solution_dict=True
return a list of dictionaries instead of a list of tuples.EXAMPLES:
sage: x,y = var('x,y') sage: solve_diophantine(3*x == 4) [] sage: solve_diophantine(x^2 - 9) [-3, 3] sage: sorted(solve_diophantine(x^2 + y^2 == 25)) [(-4, -3), (-4, 3), (0, -5), (0, 5), (4, -3), (4, 3)]
The function is used when
solve()
is called with all variables assumed integer:sage: assume(x, 'integer') sage: assume(y, 'integer') sage: sorted(solve(x*y == 1, (x,y))) [(-1, -1), (1, 1)]
You can also pick specific variables, and get the solution as a dictionary:
sage: solve_diophantine(x*y == 10, x) [-10, -5, -2, -1, 1, 2, 5, 10] sage: sorted(solve_diophantine(x*y - y == 10, (x,y))) [(-9, -1), (-4, -2), (-1, -5), (0, -10), (2, 10), (3, 5), (6, 2), (11, 1)] sage: res = solve_diophantine(x*y - y == 10, solution_dict=True) sage: sol = [{y: -5, x: -1}, {y: -10, x: 0}, {y: -1, x: -9}, {y: -2, x: -4}, {y: 10, x: 2}, {y: 1, x: 11}, {y: 2, x: 6}, {y: 5, x: 3}] sage: all(solution in res for solution in sol) and bool(len(res) == len(sol)) True
If the solution is parametrized the parameter(s) are not defined, but you can substitute them with specific integer values:
sage: x,y,z = var('x,y,z') sage: sol=solve_diophantine(x^2-y==0); sol (t, t^2) sage: [(sol[0].subs(t=t),sol[1].subs(t=t)) for t in range(-3,4)] [(-3, 9), (-2, 4), (-1, 1), (0, 0), (1, 1), (2, 4), (3, 9)] sage: sol = solve_diophantine(x^2 + y^2 == z^2); sol (2*p*q, p^2 - q^2, p^2 + q^2) sage: [(sol[0].subs(p=p,q=q),sol[1].subs(p=p,q=q),sol[2].subs(p=p,q=q)) for p in range(1,4) for q in range(1,4)] [(2, 0, 2), (4, -3, 5), (6, -8, 10), (4, 3, 5), (8, 0, 8), (12, -5, 13), (6, 8, 10), (12, 5, 13), (18, 0, 18)]
Solve Brahmagupta-Pell equations:
sage: sol = solve_diophantine(x^2 - 2*y^2 == 1); sol [(-sqrt(2)*(2*sqrt(2) + 3)^t + sqrt(2)*(-2*sqrt(2) + 3)^t - 3/2*(2*sqrt(2) + 3)^t - 3/2*(-2*sqrt(2) + 3)^t,... sage: [(sol[1][0].subs(t=t).simplify_full(),sol[1][1].subs(t=t).simplify_full()) for t in range(-1,5)] [(1, 0), (3, 2), (17, 12), (99, 70), (577, 408), (3363, 2378)]
TESTS:
sage: solve_diophantine(x^2 - y, x, y) Traceback (most recent call last): ... AttributeError: please use a tuple or list for several variables.
-
sqrt
(hold=False)¶ 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 use
unhold()
:sage: a = SR(4).sqrt(hold=True); a.unhold() 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'
-
step
(hold=False)¶ 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)
-
subs
(*args, **kwds)¶ Substitute the given subexpressions in this expression.
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 sage: t.subs(b=19, x=z) (y + z)^3 + a^2 + 361
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 one or more relational expressions:
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 sage: t.subs(a == b, b == c) (x + y)^3 + b^2 + c^2
Any number of arguments is accepted:
sage: t.subs(a=b, b=c) (x + y)^3 + b^2 + c^2 sage: t.subs({a:b}, b=c) (x + y)^3 + b^2 + c^2 sage: t.subs([x == 3, y == 2], a == 2, {b:3}) 138
It can even accept lists of lists:
sage: eqn1 = (a*x + b*y == 0) sage: eqn2 = (1 + y == 0) sage: soln = solve([eqn1, eqn2], [x, y]) sage: soln [[x == b/a, y == -1]] sage: f = x + y sage: f.subs(soln) b/a - 1
Duplicate assignments will throw an error:
sage: t.subs({a:b}, a=c) Traceback (most recent call last): ... ValueError: duplicate substitution for a, got values b and c sage: t.subs([x == 1], a = 1, b = 2, x = 2) Traceback (most recent call last): ... ValueError: duplicate substitution for x, got values 1 and 2
All substitutions are performed at the same time:
sage: t.subs({a:b, b:c}) (x + y)^3 + b^2 + c^2
Substitutions are done term by term, in other words Sage is not able to identify partial sums in a substitution (see trac ticket #18396):
sage: f = x + x^2 + x^4 sage: f.subs(x = y) y^4 + y^2 + y sage: f.subs(x^2 == y) # one term is fine x^4 + x + y sage: f.subs(x + x^2 == y) # partial sum does not work x^4 + x^2 + x sage: f.subs(x + x^2 + x^4 == y) # whole sum is fine y
Note that it is the very same behavior as in Maxima:
sage: E = 'x^4 + x^2 + x' sage: subs = [('x','y'), ('x^2','y'), ('x^2+x','y'), ('x^4+x^2+x','y')] sage: cmd = '{}, {}={}' sage: for s1,s2 in subs: ....: maxima.eval(cmd.format(E, s1, s2)) 'y^4+y^2+y' 'y+x^4+x' 'x^4+x^2+x' 'y'
Or as in Maple:
sage: cmd = 'subs({}={}, {})' # optional - maple sage: for s1,s2 in subs: # optional - maple ....: maple.eval(cmd.format(s1,s2, E)) # optional - maple 'y^4+y^2+y' 'x^4+x+y' 'x^4+x^2+x' 'y'
But Mathematica does something different on the third example:
sage: cmd = '{} /. {} -> {}' # optional - mathematica sage: for s1,s2 in subs: # optional - mathematica ....: mathematica.eval(cmd.format(E,s1,s2)) # optional - mathematica 2 4 y + y + y 4 x + x + y 4 x + y y
The same, with formatting more suitable for cut and paste:
sage: for s1,s2 in subs: # optional - mathematica ....: mathematica(cmd.format(E,s1,s2)) # optional - mathematica y + y^2 + y^4 x + x^4 + y x^4 + y y
TESTS:
No arguments return the same expression:
sage: t = a^2 + b^2 + (x+y)^3 sage: t.subs() (x + y)^3 + a^2 + b^2
Similarly for a empty dictionary, empty tuples and empty lists:
sage: t.subs({}, (), [], ()) (x + y)^3 + a^2 + b^2
Invalid argument returns error:
sage: t.subs(5) Traceback (most recent call last): ... TypeError: not able to determine a substitution from 5
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
Check that the deprecated method
subs_expr
works as expected (see trac ticket #12834):sage: var('x,y,z'); f = x^3 + y^2 + z (x, y, z) sage: f.subs_expr(x^3 == y^2, z == 1) doctest:...: DeprecationWarning: subs_expr is deprecated. Please use substitute instead. See http://trac.sagemath.org/12834 for details. 2*y^2 + 1 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) sage: f.subs_expr(x^2 + y^2 == t) (x, y, t) |--> x^2 + y^2 + t + cos(x) + sin(y)
-
subs_expr
(*args, **kwds)¶ Deprecated: Use
substitute()
instead. See trac ticket #12834 for details.
-
substitute
(*args, **kwds)¶ Substitute the given subexpressions in this expression.
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 sage: t.subs(b=19, x=z) (y + z)^3 + a^2 + 361
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 one or more relational expressions:
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 sage: t.subs(a == b, b == c) (x + y)^3 + b^2 + c^2
Any number of arguments is accepted:
sage: t.subs(a=b, b=c) (x + y)^3 + b^2 + c^2 sage: t.subs({a:b}, b=c) (x + y)^3 + b^2 + c^2 sage: t.subs([x == 3, y == 2], a == 2, {b:3}) 138
It can even accept lists of lists:
sage: eqn1 = (a*x + b*y == 0) sage: eqn2 = (1 + y == 0) sage: soln = solve([eqn1, eqn2], [x, y]) sage: soln [[x == b/a, y == -1]] sage: f = x + y sage: f.subs(soln) b/a - 1
Duplicate assignments will throw an error:
sage: t.subs({a:b}, a=c) Traceback (most recent call last): ... ValueError: duplicate substitution for a, got values b and c sage: t.subs([x == 1], a = 1, b = 2, x = 2) Traceback (most recent call last): ... ValueError: duplicate substitution for x, got values 1 and 2
All substitutions are performed at the same time:
sage: t.subs({a:b, b:c}) (x + y)^3 + b^2 + c^2
Substitutions are done term by term, in other words Sage is not able to identify partial sums in a substitution (see trac ticket #18396):
sage: f = x + x^2 + x^4 sage: f.subs(x = y) y^4 + y^2 + y sage: f.subs(x^2 == y) # one term is fine x^4 + x + y sage: f.subs(x + x^2 == y) # partial sum does not work x^4 + x^2 + x sage: f.subs(x + x^2 + x^4 == y) # whole sum is fine y
Note that it is the very same behavior as in Maxima:
sage: E = 'x^4 + x^2 + x' sage: subs = [('x','y'), ('x^2','y'), ('x^2+x','y'), ('x^4+x^2+x','y')] sage: cmd = '{}, {}={}' sage: for s1,s2 in subs: ....: maxima.eval(cmd.format(E, s1, s2)) 'y^4+y^2+y' 'y+x^4+x' 'x^4+x^2+x' 'y'
Or as in Maple:
sage: cmd = 'subs({}={}, {})' # optional - maple sage: for s1,s2 in subs: # optional - maple ....: maple.eval(cmd.format(s1,s2, E)) # optional - maple 'y^4+y^2+y' 'x^4+x+y' 'x^4+x^2+x' 'y'
But Mathematica does something different on the third example:
sage: cmd = '{} /. {} -> {}' # optional - mathematica sage: for s1,s2 in subs: # optional - mathematica ....: mathematica.eval(cmd.format(E,s1,s2)) # optional - mathematica 2 4 y + y + y 4 x + x + y 4 x + y y
The same, with formatting more suitable for cut and paste:
sage: for s1,s2 in subs: # optional - mathematica ....: mathematica(cmd.format(E,s1,s2)) # optional - mathematica y + y^2 + y^4 x + x^4 + y x^4 + y y
TESTS:
No arguments return the same expression:
sage: t = a^2 + b^2 + (x+y)^3 sage: t.subs() (x + y)^3 + a^2 + b^2
Similarly for a empty dictionary, empty tuples and empty lists:
sage: t.subs({}, (), [], ()) (x + y)^3 + a^2 + b^2
Invalid argument returns error:
sage: t.subs(5) Traceback (most recent call last): ... TypeError: not able to determine a substitution from 5
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
Check that the deprecated method
subs_expr
works as expected (see trac ticket #12834):sage: var('x,y,z'); f = x^3 + y^2 + z (x, y, z) sage: f.subs_expr(x^3 == y^2, z == 1) doctest:...: DeprecationWarning: subs_expr is deprecated. Please use substitute instead. See http://trac.sagemath.org/12834 for details. 2*y^2 + 1 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) sage: f.subs_expr(x^2 + y^2 == t) (x, y, t) |--> x^2 + y^2 + t + cos(x) + sin(y)
-
substitute_expression
(*args, **kwds)¶ Deprecated: Use
substitute()
instead. See trac ticket #12834 for details.
-
substitute_function
(original, new)¶ 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)
TESTS:
Make sure trac ticket #17849 is fixed:
sage: ex = sin(x) + atan2(0,0,hold=True) sage: ex.substitute_function(sin,cos) arctan2(0, 0) + cos(x) sage: ex = sin(x) + hypergeometric([1, 1], [2], -1) sage: ex.substitute_function(sin,cos) cos(x) + hypergeometric((1, 1), (2,), -1)
-
subtract_from_both_sides
(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
-
sum
(*args, **kwds)¶ Return the symbolic sum \(\sum_{v = a}^b self\)
with respect to the variable \(v\) with endpoints \(a\) and \(b\).
INPUT:
v
- a variable or variable namea
- lower endpoint of the sumb
- upper endpoint of the sumalgorithm
- (default:'maxima'
) one of'maxima'
- use Maxima (the default)'maple'
- (optional) use Maple'mathematica'
- (optional) use Mathematica'giac'
- (optional) use Giac
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)
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 pi*(e^(2*pi) + 1)/((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
Note
- Sage can currently only understand a subset of the output of Maxima, Maple and Mathematica, so even if the chosen backend can perform the summation the result might not be convertable into a usable Sage expression.
TESTS:
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
This sum used to give a wrong result (trac ticket #9635) but now gives correct results with all relevant assumptions:
sage: (n,k,j)=var('n,k,j') sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) sage: assume(j>-1) sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) 1 sage: forget() sage: assume(n>=j) sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) sage: forget() sage: assume(j==-1) sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) 1 sage: forget() sage: assume(j<-1) sage: sum(binomial(n,k)*binomial(k-1,j)*(-1)**(k-1-j),k,j+1,n) -sum((-1)^(-j + k)*binomial(k - 1, j)*binomial(n, k), k, j + 1, n) sage: forget()
Check that trac ticket #16176 is fixed:
sage: n = var('n') sage: sum(log(1-1/n^2),n,2,oo) -log(2)
-
tan
(hold=False)¶ 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 use
unhold()
:sage: a = (pi/12).tan(hold=True); a.unhold() -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
-
tanh
(hold=False)¶ Return tanh of self.
We have \(\tanh(x) = \sinh(x) / \cosh(x)\).
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 use
unhold()
:sage: a = arcsinh(x).tanh(hold=True); a.unhold() 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
-
taylor
(*args)¶ Expand this symbolic expression in a truncated Taylor or Laurent series in the variable \(v\) around the point \(a\), containing terms through \((x - a)^n\). Functions in more variables is also supported.
INPUT:
*args
- the following notation is supportedx, a, n
- variable, point, degree(x, a), (y, b), n
- variables with points, degree of polynomial
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_relation
(ntests=20, domain=None, proof=True)¶ 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:
ntests
– (default20
) the number of iterations to rundomain
– (optional) the domain from which to draw the random values defaults toCIF
for equality testing andRIF
for order testingproof
– (defaultTrue
) ifFalse
and the domain is an interval field, regard overlapping (potentially equal) intervals as equal, and returnTrue
if all tests succeeded.
OUTPUT:
Boolean or
NotImplemented
, meaningTrue
– this relation holds in the domain and has no variables.False
– a contradiction was found.NotImplemented
– no contradiction found.
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(-x) == -cot(x)).test_relation() NotImplemented
Check that trac ticket #18896 is fixed:
sage: m=540579833922455191419978421211010409605356811833049025*sqrt(1/2) sage: m1=382247666339265723780973363167714496025733124557617743 sage: (m==m1).test_relation(domain=QQbar) False sage: (m==m1).test_relation() False
-
trailing_coeff
(s)¶ 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
-
trailing_coefficient
(s)¶ 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
-
trig_expand
(full=False, half_angles=False, plus=True, times=True)¶ 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:
full
- (default: False) To enhance user control of simplification, this function expands only one level at a time by default, expanding sums of angles or multiple angles. To obtain full expansion into sines and cosines immediately, set the optional parameter full to True.half_angles
- (default: False) If True, causes half-angles to be simplified away.plus
- (default: True) Controls the sum rule; expansion of sums (e.g. ‘sin(x + y)’) will take place only if plus is True.times
- (default: True) Controls the product rule, expansion of products (e.g. sin(2*x)) will take place only if times is True.
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()
andexpand_trig()
are the same
-
trig_reduce
(var=None)¶ 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:
self
- a symbolic expressionvar
- (default: None) the variable which is used for these transformations. If not specified, all variables are used.
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()
andreduce_trig()
are the same
-
trig_simplify
(expand=True)¶ Optionally expand and then employ identities such as \(\sin(x)^2 + \cos(x)^2 = 1\), \(\cosh(x)^2 - \sinh(x)^2 = 1\), \(\sin(x)\csc(x) = 1\), or \(\tanh(x)=\sinh(x)/\cosh(x)\) to simplify expressions containing tan, sec, etc., to sin, cos, sinh, cosh.
INPUT:
self
- symbolic expressionexpand
- (default:True) if True, expands trigonometric and hyperbolic functions of sums of angles and of multiple angles occurring inself
first. For best results,self
should be expanded. See alsoexpand_trig()
to get more controls on this expansion.
ALIAS:
trig_simplify()
andsimplify_trig()
are the sameEXAMPLES:
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)
-
truncate
()¶ Given a power series or expression, return the corresponding expression without the big oh.
INPUT:
self
– a series as output by theseries()
command.
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)
-
unhold
(exclude=None)¶ Evaluates any held operations (with the
hold
keyword) in the expressionINPUT:
self
– an expression with held operationsexclude
– (default: None) a list of operators to exclude from evaluation. Excluding arithmetic operators does not yet work (see trac ticket #10169).
OUTPUT:
A new expression with held operations, except those in
exclude
, evaluatedEXAMPLES:
sage: a = exp(I * pi, hold=True) sage: a e^(I*pi) sage: a.unhold() -1 sage: b = x.add(x, hold=True) sage: b x + x sage: b.unhold() 2*x sage: (a + b).unhold() 2*x - 1 sage: c = (x.mul(x, hold=True)).add(x.mul(x, hold=True), hold=True) sage: c x*x + x*x sage: c.unhold() 2*x^2 sage: sin(tan(0, hold=True), hold=True).unhold() 0 sage: sin(tan(0, hold=True), hold=True).unhold(exclude=[sin]) sin(0) sage: (e^sgn(0, hold=True)).unhold() 1 sage: (e^sgn(0, hold=True)).unhold(exclude=[exp]) e^0 sage: log(3).unhold() log(3)
-
unit
(s)¶ Return the unit of this expression when considered as a polynomial in
s
.See also
content()
,primitive_part()
, andunit_content_primitive()
.INPUT:
s
– a symbolic expression.
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
-
unit_content_primitive
(s)¶ Return the factorization into unit, content, and primitive part.
INPUT:
s
– a symbolic expression, usually a symbolic variable. The whole symbolic expressionself
will be considered as a univariate polynomial ins
.
OUTPUT:
A triple (unit, content, primitive polynomial)` containing the
unit
,content
, andprimitive polynomial
. Their product equalsself
.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)
-
variables
()¶ 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)
-
zeta
(hold=False)¶ 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 use
unhold()
:sage: a = SR(2).zeta(hold=True); a.unhold() 1/6*pi^2
TESTS:
sage: t = SR(1).zeta(); t Infinity
-
-
class
sage.symbolic.expression.
ExpressionIterator
¶ Bases:
object
-
next
()¶ x.next() -> the next value, or raise StopIteration
-
-
sage.symbolic.expression.
is_Expression
(x)¶ 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
-
sage.symbolic.expression.
is_SymbolicEquation
(x)¶ 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 booleanFalse
: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
-
sage.symbolic.expression.
solve_diophantine
(f, *args, **kwds)¶ Solve a Diophantine equation.
The argument, if not given as symbolic equation, is set equal to zero. It can be given in any form that can be converted to symbolic. Please see
Expression.solve_diophantine()
for a detailed synopsis.EXAMPLES:
sage: R.<a,b> = PolynomialRing(ZZ); R Multivariate Polynomial Ring in a, b over Integer Ring sage: solve_diophantine(a^2-3*b^2+1) [] sage: solve_diophantine(a^2-3*b^2+2) [(1/2*sqrt(3)*(sqrt(3) + 2)^t - 1/2*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t, 1/6*sqrt(3)*(sqrt(3) + 2)^t - 1/6*sqrt(3)*(-sqrt(3) + 2)^t + 1/2*(sqrt(3) + 2)^t + 1/2*(-sqrt(3) + 2)^t), (-1/2*sqrt(3)*(sqrt(3) + 2)^t + 1/2*sqrt(3)*(-sqrt(3) + 2)^t - 1/2*(sqrt(3) + 2)^t - 1/2*(-sqrt(3) + 2)^t, -1/6*sqrt(3)*(sqrt(3) + 2)^t + 1/6*sqrt(3)*(-sqrt(3) + 2)^t - 1/2*(sqrt(3) + 2)^t - 1/2*(-sqrt(3) + 2)^t)]