def test_roots_preprocessed(): E, F, J, L = symbols("E,F,J,L") f = -21601054687500000000*E**8*J**8/L**16 + \ 508232812500000000*F*x*E**7*J**7/L**14 - \ 4269543750000000*E**6*F**2*J**6*x**2/L**12 + \ 16194716250000*E**5*F**3*J**5*x**3/L**10 - \ 27633173750*E**4*F**4*J**4*x**4/L**8 + \ 14840215*E**3*F**5*J**3*x**5/L**6 + \ 54794*E**2*F**6*J**2*x**6/(5*L**4) - \ 1153*E*J*F**7*x**7/(80*L**2) + \ 633*F**8*x**8/160000 assert roots(f, x) == {} R1 = roots(f.evalf(), x, multiple=True) R2 = [-1304.88375606366, 97.1168816800648, 186.946430171876, 245.526792947065, 503.441004174773, 791.549343830097, 1273.16678129348, 1850.10650616851] w = Wild('w') p = w*E*J/(F*L**2) assert len(R1) == len(R2) for r1, r2 in zip(R1, R2): match = r1.match(p) assert match is not None and abs(match[w] - r2) < 1e-10
def test_roots2(): """Just test that calculating these roots does not hang (final result is not checked) """ a, b, c, d, x = symbols("a b c d x") f1 = x**2*c + (a/b) + x*c*d - a f2 = x**2*(a + b*(c-d)*a) + x*a*b*c/(b*d-d) + (a*d-c/d) assert roots(f1, x).values() == [1, 1] assert roots(f2, x).values() == [1, 1]
def test_roots_inexact(): R1 = sorted([ r.evalf() for r in roots(x**2 + x + 1, x) ]) R2 = sorted([ r for r in roots(x**2 + x + 1.0, x) ]) for r1, r2 in zip(R1, R2): assert abs(r1 - r2) < 1e-12 f = x**4 + 3.0*sqrt(2.0)*x**3 - (78.0 + 24.0*sqrt(3.0))*x**2 + 144.0*(2*sqrt(3.0) + 9.0) R1 = sorted(roots(f, multiple=True)) R2 = sorted([-12.7530479110482, -3.85012393732929, 4.89897948556636, 7.46155167569183]) for r1, r2 in zip(R1, R2): assert abs(r1 - r2) < 1e-10
def _indicial(self): list_coeff = self.annihilator.listofpoly R = self.annihilator.parent.base x = self.x s = R.zero y = R.one def _pole_degree(poly): root_all = roots(poly.rep, filter='Z') if 0 in root_all.keys(): return root_all[0] else: return 0 degree = [j.degree() for j in list_coeff] degree = max(degree) inf = 10 * (max(1, degree) + max(1, self.annihilator.order)) deg = lambda q: inf if q.is_zero else _pole_degree(q) b = deg(list_coeff[0]) print (b) for j in range(1, len(list_coeff)): b = min(b, deg(list_coeff[j]) - j) print(b) for i, j in enumerate(list_coeff): listofdmp = j.all_coeffs() degree = len(listofdmp) - 1 if - i - b <= 0: s = s + listofdmp[degree - i - b] * y y *= x - i return roots(s.rep, filter='R').keys()
def test_roots_binomial(): assert roots_binomial(Poly(5*x, x)) == [0] assert roots_binomial(Poly(5*x**4, x)) == [0, 0, 0, 0] assert roots_binomial(Poly(5*x + 2, x)) == [-Rational(2, 5)] A = 10**Rational(3, 4)/10 assert roots_binomial(Poly(5*x**4 + 2, x)) == \ [-A - A*I, -A + A*I, A - A*I, A + A*I] a1 = Symbol('a1', nonnegative=True) b1 = Symbol('b1', nonnegative=True) r0 = roots_quadratic(Poly(a1*x**2 + b1, x)) r1 = roots_binomial(Poly(a1*x**2 + b1, x)) assert powsimp(r0[0]) == powsimp(r1[0]) assert powsimp(r0[1]) == powsimp(r1[1]) for a, b, s, n in cartes((1, 2), (1, 2), (-1, 1), (2, 3, 4, 5)): if a == b and a != 1: # a == b == 1 is sufficient continue p = Poly(a*x**n + s*b) ans = roots_binomial(p) assert ans == _nsort(ans) # issue 8813 assert roots(Poly(2*x**3 - 16*y**3, x)) == { 2*y*(-S(1)/2 - sqrt(3)*I/2): 1, 2*y: 1, 2*y*(-S(1)/2 + sqrt(3)*I/2): 1}
def test_roots2(): """Just test that calculating these roots does not hang (final result is not checked) """ a, b, c, d, x = symbols("a,b,c,d,x") f1 = x**2*c + (a/b) + x*c*d - a f2 = x**2*(a + b*(c-d)*a) + x*a*b*c/(b*d-d) + (a*d-c/d) assert roots(f1, x).values() == [1, 1] assert roots(f2, x).values() == [1, 1] (zz, yy, xx, zy, zx, yx, k) = symbols("zz,yy,xx,zy,zx,yx,k") e1 = (zz-k)*(yy-k)*(xx-k) + zy*yx*zx + zx-zy-yx e2 = (zz-k)*yx*yx + zx*(yy-k)*zx + zy*zy*(xx-k) assert roots(e1 - e2, k).values() == [1, 1, 1]
def test_roots2(): """Just test that calculating these roots does not hang (final result is not checked) """ a, b, c, d, x = symbols("a,b,c,d,x") f1 = x**2 * c + (a / b) + x * c * d - a f2 = x**2 * (a + b * (c - d) * a) + x * a * b * c / (b * d - d) + (a * d - c / d) assert roots(f1, x).values() == [1, 1] assert roots(f2, x).values() == [1, 1] (zz, yy, xx, zy, zx, yx, k) = symbols("zz,yy,xx,zy,zx,yx,k") e1 = (zz - k) * (yy - k) * (xx - k) + zy * yx * zx + zx - zy - yx e2 = (zz - k) * yx * yx + zx * (yy - k) * zx + zy * zy * (xx - k) assert roots(e1 - e2, k).values() == [1, 1, 1]
def doit(self, **hints): if not hints.get('roots', True): return self _roots = roots(self.poly, multiple=True) if len(_roots) < self.poly.degree(): return self else: return Add(*[self.fun(r) for r in _roots])
def test_roots_inexact(): R1 = roots(x ** 2 + x + 1, x, multiple=True) R2 = roots(x ** 2 + x + 1.0, x, multiple=True) for r1, r2 in zip(R1, R2): assert abs(r1 - r2) < 1e-12 f = ( x ** 4 + 3.0 * sqrt(2.0) * x ** 3 - (78.0 + 24.0 * sqrt(3.0)) * x ** 2 + 144.0 * (2 * sqrt(3.0) + 9.0) ) R1 = roots(f, multiple=True) R2 = (-12.7530479110482, -3.85012393732929, 4.89897948556636, 7.46155167569183) for r1, r2 in zip(R1, R2): assert abs(r1 - r2) < 1e-10
def test_legendre(): assert legendre(0, x) == 1 assert legendre(1, x) == x assert legendre(2, x) == ((3 * x**2 - 1) / 2).expand() assert legendre(3, x) == ((5 * x**3 - 3 * x) / 2).expand() assert legendre(4, x) == ((35 * x**4 - 30 * x**2 + 3) / 8).expand() assert legendre(5, x) == ((63 * x**5 - 70 * x**3 + 15 * x) / 8).expand() assert legendre(6, x) == ((231 * x**6 - 315 * x**4 + 105 * x**2 - 5) / 16).expand() assert legendre(10, -1) == 1 assert legendre(11, -1) == -1 assert legendre(10, 1) == 1 assert legendre(11, 1) == 1 assert legendre(10, 0) != 0 assert legendre(11, 0) == 0 assert legendre(-1, x) == 1 k = Symbol('k') assert legendre(5 - k, x).subs(k, 2) == ((5 * x**3 - 3 * x) / 2).expand() assert roots(legendre(4, x), x) == { sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1, -sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1, sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1, -sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1, } n = Symbol("n") X = legendre(n, x) assert isinstance(X, legendre) assert unchanged(legendre, n, x) assert legendre(n, 0) == sqrt(pi) / (gamma(S.Half - n / 2) * gamma(n / 2 + 1)) assert legendre(n, 1) == 1 assert legendre(n, oo) is oo assert legendre(-n, x) == legendre(n - 1, x) assert legendre(n, -x) == (-1)**n * legendre(n, x) assert unchanged(legendre, -n + k, x) assert conjugate(legendre(n, x)) == legendre(n, conjugate(x)) assert diff(legendre(n, x), x) == \ n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1) assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n) _k = Dummy('k') assert legendre(n, x).rewrite("polynomial").dummy_eq( Sum((-1)**_k * (S.Half - x / 2)**_k * (x / 2 + S.Half)**(-_k + n) * binomial(n, _k)**2, (_k, 0, n))) raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(1)) raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(3))
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0): return self try: argroots = roots(self.args[0], x) result = 0 valid = True darg = abs(diff(self.args[0], x)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(x - r) / darg.subs(x, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def test_roots_slow(): """Just test that calculating these roots does not hang. """ a, b, c, d, x = symbols("a,b,c,d,x") f1 = x**2*c + (a/b) + x*c*d - a f2 = x**2*(a + b*(c - d)*a) + x*a*b*c/(b*d - d) + (a*d - c/d) assert list(roots(f1, x).values()) == [1, 1] assert list(roots(f2, x).values()) == [1, 1] (zz, yy, xx, zy, zx, yx, k) = symbols("zz,yy,xx,zy,zx,yx,k") e1 = (zz - k)*(yy - k)*(xx - k) + zy*yx*zx + zx - zy - yx e2 = (zz - k)*yx*yx + zx*(yy - k)*zx + zy*zy*(xx - k) assert list(roots(e1 - e2, k).values()) == [1, 1, 1] f = x**3 + 2*x**2 + 8 R = list(roots(f).keys()) assert not any(i for i in [f.subs(x, ri).n(chop=True) for ri in R])
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0): return self try: argroots = roots(self.args[0], x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x, r).is_zero: result = result + DiracDelta(x - r) / abs(darg.subs(x, r)) else: valid = False break if valid: return result except PolynomialError: pass return self
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], x) result = 0 valid = True darg = abs(diff(self.args[0], x)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(x - r)/darg.subs(x, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def test_issue_14522(): eq = Poly( x ** 4 + x ** 3 * (16 + 32 * I) + x ** 2 * (-285 + 386 * I) + x * (-2824 - 448 * I) - 2058 - 6053 * I, x, ) roots_eq = roots(eq) assert all(eq(r) == 0 for r in roots_eq)
def simplify(self, x): """simplify(self, x) Compute a simplified representation of the function using property number 4. x can be: - a symbol Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).simplify(x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).simplify(y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).simplify(x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Directdelta """ from sympy.polys.polyroots import roots if not self.args[0].has(x) or (len(self.args)>1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], x, \ multiple=True) result = 0 valid = True darg = diff(self.args[0], x) for r in argroots: #should I care about multiplicities of roots? if r.is_real and not darg.subs(x,r).is_zero: result = result + DiracDelta(x - r)/abs(darg.subs(x,r)) else: valid = False break if valid: return result except PolynomialError: pass return self
def test_roots_slow(): """Just test that calculating these roots does not hang. """ a, b, c, d, x = symbols("a,b,c,d,x") f1 = x**2*c + (a/b) + x*c*d - a f2 = x**2*(a + b*(c-d)*a) + x*a*b*c/(b*d-d) + (a*d-c/d) assert roots(f1, x).values() == [1, 1] assert roots(f2, x).values() == [1, 1] (zz, yy, xx, zy, zx, yx, k) = symbols("zz,yy,xx,zy,zx,yx,k") e1 = (zz-k)*(yy-k)*(xx-k) + zy*yx*zx + zx-zy-yx e2 = (zz-k)*yx*yx + zx*(yy-k)*zx + zy*zy*(xx-k) assert roots(e1 - e2, k).values() == [1, 1, 1] f = x**3 + 2*x**2 + 8 R = roots(f).keys() assert f.subs(x, R[0]).simplify() == 0 assert f.subs(x, R[1]).simplify() == 0 assert f.subs(x, R[2]).simplify() == 0
def test_roots_preprocessed(): E, F, J, L = symbols("E,F,J,L") f = ( -21601054687500000000 * E ** 8 * J ** 8 / L ** 16 + 508232812500000000 * F * x * E ** 7 * J ** 7 / L ** 14 - 4269543750000000 * E ** 6 * F ** 2 * J ** 6 * x ** 2 / L ** 12 + 16194716250000 * E ** 5 * F ** 3 * J ** 5 * x ** 3 / L ** 10 - 27633173750 * E ** 4 * F ** 4 * J ** 4 * x ** 4 / L ** 8 + 14840215 * E ** 3 * F ** 5 * J ** 3 * x ** 5 / L ** 6 + 54794 * E ** 2 * F ** 6 * J ** 2 * x ** 6 / (5 * L ** 4) - 1153 * E * J * F ** 7 * x ** 7 / (80 * L ** 2) + 633 * F ** 8 * x ** 8 / 160000 ) assert roots(f, x) == {} R1 = roots(f.evalf(), x, multiple=True) R2 = [ -1304.88375606366, 97.1168816800648, 186.946430171876, 245.526792947065, 503.441004174773, 791.549343830097, 1273.16678129348, 1850.10650616851, ] w = Wild("w") p = w * E * J / (F * L ** 2) assert len(R1) == len(R2) for r1, r2 in zip(R1, R2): match = r1.match(p) assert match is not None and abs(match[w] - r2) < 1e-10
def test_roots_slow(): """Just test that calculating these roots does not hang. """ a, b, c, d, x = symbols("a,b,c,d,x") f1 = x**2 * c + (a / b) + x * c * d - a f2 = x**2 * (a + b * (c - d) * a) + x * a * b * c / (b * d - d) + (a * d - c / d) assert roots(f1, x).values() == [1, 1] assert roots(f2, x).values() == [1, 1] (zz, yy, xx, zy, zx, yx, k) = symbols("zz,yy,xx,zy,zx,yx,k") e1 = (zz - k) * (yy - k) * (xx - k) + zy * yx * zx + zx - zy - yx e2 = (zz - k) * yx * yx + zx * (yy - k) * zx + zy * zy * (xx - k) assert roots(e1 - e2, k).values() == [1, 1, 1] f = x**3 + 2 * x**2 + 8 R = roots(f).keys() assert f.subs(x, R[0]).simplify() == 0 assert f.subs(x, R[1]).simplify() == 0 assert f.subs(x, R[2]).simplify() == 0
def test_roots_cubic(): assert roots_cubic(Poly(2*x**3, x)) == [0, 0, 0] assert roots_cubic(Poly(x**3 - 3*x**2 + 3*x - 1, x)) == [1, 1, 1] assert roots_cubic(Poly(x**3 + 1, x)) == \ [-1, S.Half - I*sqrt(3)/2, S.Half + I*sqrt(3)/2] assert roots_cubic(Poly(2*x**3 - 3*x**2 - 3*x - 1, x))[0] == \ S.Half + 3**Rational(1, 3)/2 + 3**Rational(2, 3)/2 eq = -x**3 + 2*x**2 + 3*x - 2 assert roots(eq, trig=True, multiple=True) == \ roots_cubic(Poly(eq, x), trig=True) == [ Rational(2, 3) + 2*sqrt(13)*cos(acos(8*sqrt(13)/169)/3)/3, -2*sqrt(13)*sin(-acos(8*sqrt(13)/169)/3 + pi/6)/3 + Rational(2, 3), -2*sqrt(13)*cos(-acos(8*sqrt(13)/169)/3 + pi/3)/3 + Rational(2, 3), ]
def test_roots_cubic(): assert roots_cubic(Poly(2*x**3, x)) == [0, 0, 0] assert roots_cubic(Poly(x**3 - 3*x**2 + 3*x - 1, x)) == [1, 1, 1] assert roots_cubic(Poly(x**3 + 1, x)) == \ [-1, S.Half - I*sqrt(3)/2, S.Half + I*sqrt(3)/2] assert roots_cubic(Poly(2*x**3 - 3*x**2 - 3*x - 1, x))[0] == \ S.Half + 3**Rational(1, 3)/2 + 3**Rational(2, 3)/2 eq = -x**3 + 2*x**2 + 3*x - 2 assert roots(eq, trig=True, multiple=True) == \ roots_cubic(Poly(eq, x), trig=True) == [ S(2)/3 + 2*sqrt(13)*cos(acos(8*sqrt(13)/169)/3)/3, -2*sqrt(13)*sin(-acos(8*sqrt(13)/169)/3 + pi/6)/3 + S(2)/3, -2*sqrt(13)*cos(-acos(8*sqrt(13)/169)/3 + pi/3)/3 + S(2)/3, ]
def evalf(self, points, method='RK4'): """ Finds numerical value of a holonomic function using numerical methods. (RK4 by default). A set of points (real or complex) must be provided which will be the path for the numerical integration. The path should be given as a list [x1, x2, ... xn]. The numerical values will be computed at each point in this order x1 --> x2 --> x3 ... --> xn. Returns values of the function at x1, x2, ... xn in a list. Examples ======= >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators >>> from sympy.polys.domains import ZZ, QQ >>> from sympy import symbols >>> x = symbols('x') >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx') >>> # a straight line on the real axis from (0 to 1) >>> r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] # using Runge-Kutta 4th order on e^x from 0.1 to 1. # exact solution at 1 is 2.71828182845905 >>> HolonomicFunction(Dx - 1, x, 0, [1]).evalf(r) [1.10517083333333, 1.22140257085069, 1.34985849706254, 1.49182424008069, 1.64872063859684, 1.82211796209193, 2.01375162659678, 2.22553956329232, 2.45960141378007, 2.71827974413517] # using Euler's method for the same >>> HolonomicFunction(Dx - 1, x, 0, [1]).evalf(r, method='Euler') [1.1, 1.21, 1.331, 1.4641, 1.61051, 1.771561, 1.9487171, 2.14358881, 2.357947691, 2.5937424601] One can also observe that the value obtained using Runge-Kutta 4th order is much more accurate than Euler's method. """ from sympy.holonomic.numerical import _evalf for i in roots(self.annihilator.listofpoly[-1].rep): if i == self.x0 or i in points: raise TypeError("Provided path contains a singularity") return _evalf(self, points, method=method)
def test_roots_cubic(): assert roots_cubic(Poly(2 * x**3, x)) == [0, 0, 0] assert roots_cubic(Poly(x**3 - 3 * x**2 + 3 * x - 1, x)) == [1, 1, 1] # valid for arbitrary y (issue 21263) r = root(y, 3) assert roots_cubic(Poly(x**3 - y, x)) == [ r, r * (-S.Half + sqrt(3) * I / 2), r * (-S.Half - sqrt(3) * I / 2) ] # simpler form when y is negative assert roots_cubic(Poly(x**3 - -1, x)) == \ [-1, S.Half - I*sqrt(3)/2, S.Half + I*sqrt(3)/2] assert roots_cubic(Poly(2*x**3 - 3*x**2 - 3*x - 1, x))[0] == \ S.Half + 3**Rational(1, 3)/2 + 3**Rational(2, 3)/2 eq = -x**3 + 2 * x**2 + 3 * x - 2 assert roots(eq, trig=True, multiple=True) == \ roots_cubic(Poly(eq, x), trig=True) == [ Rational(2, 3) + 2*sqrt(13)*cos(acos(8*sqrt(13)/169)/3)/3, -2*sqrt(13)*sin(-acos(8*sqrt(13)/169)/3 + pi/6)/3 + Rational(2, 3), -2*sqrt(13)*cos(-acos(8*sqrt(13)/169)/3 + pi/3)/3 + Rational(2, 3), ]
def test_roots_mixed(): f = -1936 - 5056 * x - 7592 * x ** 2 + 2704 * x ** 3 - 49 * x ** 4 _re, _im = intervals(f, all=True) _nroots = nroots(f) _sroots = roots(f, multiple=True) _re = [Interval(a, b) for (a, b), _ in _re] _im = [Interval(re(a), re(b)) * Interval(im(a), im(b)) for (a, b), _ in _im] _intervals = _re + _im _sroots = [r.evalf() for r in _sroots] _nroots = sorted(_nroots, key=lambda x: x.sort_key()) _sroots = sorted(_sroots, key=lambda x: x.sort_key()) for _roots in (_nroots, _sroots): for i, r in zip(_intervals, _roots): if r.is_real: assert r in i else: assert (re(r), im(r)) in i
def test_roots_mixed(): f = -1936 - 5056*x - 7592*x**2 + 2704*x**3 - 49*x**4 _re, _im = intervals(f, all=True) _nroots = nroots(f) _sroots = roots(f, multiple=True) _re = [ Interval(a, b) for (a, b), _ in _re ] _im = [ Interval(re(a), re(b))*Interval(im(a), im(b)) for (a, b), _ in _im ] _intervals = _re + _im _sroots = [ r.evalf() for r in _sroots ] _nroots = sorted(_nroots, key=lambda x: x.sort_key()) _sroots = sorted(_sroots, key=lambda x: x.sort_key()) for _roots in (_nroots, _sroots): for i, r in zip(_intervals, _roots): if r.is_real: assert r in i else: assert (re(r), im(r)) in i
def _indicial(self): """Computes the roots of Indicial equation. """ list_coeff = self.annihilator.listofpoly R = self.annihilator.parent.base x = self.x s = R.zero y = R.one def _pole_degree(poly): root_all = roots(poly.rep, filter='Z') if 0 in root_all.keys(): return root_all[0] else: return 0 degree = [j.degree() for j in list_coeff] degree = max(degree) inf = 10 * (max(1, degree) + max(1, self.annihilator.order)) deg = lambda q: inf if q.is_zero else _pole_degree(q) b = deg(list_coeff[0]) print (b) for j in range(1, len(list_coeff)): b = min(b, deg(list_coeff[j]) - j) print(b) for i, j in enumerate(list_coeff): listofdmp = j.all_coeffs() degree = len(listofdmp) - 1 if - i - b <= 0: s = s + listofdmp[degree - i - b] * y y *= x - i return roots(s.rep, filter='R').keys()
def test_roots_binomial(): assert roots_binomial(Poly(5 * x, x)) == [0] assert roots_binomial(Poly(5 * x ** 4, x)) == [0, 0, 0, 0] assert roots_binomial(Poly(5 * x + 2, x)) == [Rational(-2, 5)] A = 10 ** Rational(3, 4) / 10 assert roots_binomial(Poly(5 * x ** 4 + 2, x)) == [ -A - A * I, -A + A * I, A - A * I, A + A * I, ] _check(roots_binomial(Poly(x ** 8 - 2))) a1 = Symbol("a1", nonnegative=True) b1 = Symbol("b1", nonnegative=True) r0 = roots_quadratic(Poly(a1 * x ** 2 + b1, x)) r1 = roots_binomial(Poly(a1 * x ** 2 + b1, x)) assert powsimp(r0[0]) == powsimp(r1[0]) assert powsimp(r0[1]) == powsimp(r1[1]) for a, b, s, n in cartes((1, 2), (1, 2), (-1, 1), (2, 3, 4, 5)): if a == b and a != 1: # a == b == 1 is sufficient continue p = Poly(a * x ** n + s * b) ans = roots_binomial(p) assert ans == _nsort(ans) # issue 8813 assert roots(Poly(2 * x ** 3 - 16 * y ** 3, x)) == { 2 * y * (Rational(-1, 2) - sqrt(3) * I / 2): 1, 2 * y: 1, 2 * y * (Rational(-1, 2) + sqrt(3) * I / 2): 1, }
def test_issue_13340(): eq = Poly(y**3 + exp(x)*y + x, y, domain='EX') roots_d = roots(eq) assert len(roots_d) == 3
def _monotonic_sign(self): """Return the value closest to 0 that ``self`` may have if all symbols are signed and the result is uniformly the same sign for all values of symbols. If a symbol is only signed but not known to be an integer or the result is 0 then a symbol representative of the sign of self will be returned. Otherwise, None is returned if a) the sign could be positive or negative or b) self is not in one of the following forms: - L(x, y, ...) + A: a function linear in all symbols x, y, ... with an additive constant; if A is zero then the function can be a monomial whose sign is monotonic over the range of the variables, e.g. (x + 1)**3 if x is nonnegative. - A/L(x, y, ...) + B: the inverse of a function linear in all symbols x, y, ... that does not have a sign change from positive to negative for any set of values for the variables. - M(x, y, ...) + A: a monomial M whose factors are all signed and a constant, A. - A/M(x, y, ...) + B: the inverse of a monomial and constants A and B. - P(x): a univariate polynomial Examples ======== >>> from sympy.core.exprtools import _monotonic_sign as F >>> from sympy import Dummy, S >>> nn = Dummy(integer=True, nonnegative=True) >>> p = Dummy(integer=True, positive=True) >>> p2 = Dummy(integer=True, positive=True) >>> F(nn + 1) 1 >>> F(p - 1) _nneg >>> F(nn*p + 1) 1 >>> F(p2*p + 1) 2 >>> F(nn - 1) # could be negative, zero or positive """ if not self.is_real: return if (-self).is_Symbol: rv = _monotonic_sign(-self) return rv if rv is None else -rv if self.is_Symbol: s = self if s.is_prime: if s.is_odd: return S(3) else: return S(2) elif s.is_positive: if s.is_even: return S(2) elif s.is_integer: return S.One else: return _eps elif s.is_negative: if s.is_even: return S(-2) elif s.is_integer: return S.NegativeOne else: return -_eps if s.is_zero or s.is_nonpositive or s.is_nonnegative: return S.Zero return None # univariate polynomial free = self.free_symbols if len(free) == 1: if self.is_polynomial(): from sympy.polys.polytools import real_roots from sympy.polys.polyroots import roots from sympy.polys.polyerrors import PolynomialError x = free.pop() x0 = _monotonic_sign(x) if x0 == _eps or x0 == -_eps: x0 = S.Zero if x0 is not None: d = self.diff(x) if d.is_number: roots = [] else: try: roots = real_roots(d) except (PolynomialError, NotImplementedError): roots = [r for r in roots(d, x) if r.is_real] y = self.subs(x, x0) if x.is_nonnegative and all(r <= x0 for r in roots): if y.is_nonnegative and d.is_positive: if y: return y if y.is_positive else Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_negative: if y: return y if y.is_negative else Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) elif x.is_nonpositive and all(r >= x0 for r in roots): if y.is_nonnegative and d.is_negative: if y: return Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_positive: if y: return Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) else: n, d = self.as_numer_denom() den = None if n.is_number: den = _monotonic_sign(d) elif not d.is_number: if _monotonic_sign(n) is not None: den = _monotonic_sign(d) if den is not None and (den.is_positive or den.is_negative): v = n*den if v.is_positive: return Dummy('pos', positive=True) elif v.is_nonnegative: return Dummy('nneg', nonnegative=True) elif v.is_negative: return Dummy('neg', negative=True) elif v.is_nonpositive: return Dummy('npos', nonpositive=True) return None # multivariate c, a = self.as_coeff_Add() v = None if not a.is_polynomial(): # F/A or A/F where A is a number and F is a signed, rational monomial n, d = a.as_numer_denom() if not (n.is_number or d.is_number): return if ( a.is_Mul or a.is_Pow) and \ a.is_rational and \ all(p.exp.is_Integer for p in a.atoms(Pow) if p.is_Pow) and \ (a.is_positive or a.is_negative): v = S(1) for ai in Mul.make_args(a): if ai.is_number: v *= ai continue reps = {} for x in ai.free_symbols: reps[x] = _monotonic_sign(x) if reps[x] is None: return v *= ai.subs(reps) elif c: # signed linear expression if not any(p for p in a.atoms(Pow) if not p.is_number) and (a.is_nonpositive or a.is_nonnegative): free = list(a.free_symbols) p = {} for i in free: v = _monotonic_sign(i) if v is None: return p[i] = v or (_eps if i.is_nonnegative else -_eps) v = a.xreplace(p) if v is not None: rv = v + c if v.is_nonnegative and rv.is_positive: return rv.subs(_eps, 0) if v.is_nonpositive and rv.is_negative: return rv.subs(_eps, 0)
def test_roots(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x**9, x) == {S.Zero: 9} assert roots(((x-2)*(x+3)*(x-4)).expand(), x) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(2*x+1, x) == {-S.Half: 1} assert roots((2*x+1)**2, x) == {-S.Half: 2} assert roots((2*x+1)**5, x) == {-S.Half: 5} assert roots((2*x+1)**10, x) == {-S.Half: 10} assert roots(x**4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x**4 - 1)**2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2*x-3)**2).expand(), x) == { Rational(3,2): 2} assert roots(((2*x+3)**2).expand(), x) == {-Rational(3,2): 2} assert roots(((2*x-3)**3).expand(), x) == { Rational(3,2): 3} assert roots(((2*x+3)**3).expand(), x) == {-Rational(3,2): 3} assert roots(((2*x-3)**5).expand(), x) == { Rational(3,2): 5} assert roots(((2*x+3)**5).expand(), x) == {-Rational(3,2): 5} assert roots(((a*x-b)**5).expand(), x) == { b/a: 5} assert roots(((a*x+b)**5).expand(), x) == {-b/a: 5} assert roots(x**4-2*x**2+1, x) == {S.One: 2, -S.One: 2} assert roots(x**6-4*x**4+4*x**3-x**2, x) == \ {S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1} assert roots(x**8-1, x) == { 2**S.Half/2 + I*2**S.Half/2: 1, 2**S.Half/2 - I*2**S.Half/2: 1, -2**S.Half/2 + I*2**S.Half/2: 1, -2**S.Half/2 - I*2**S.Half/2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1 } f = -2016*x**2 - 5616*x**3 - 2056*x**4 + 3324*x**5 + 2176*x**6 - 224*x**7 - 384*x**8 - 64*x**9 assert roots(f) == {S(0): 2, -S(2): 2, S(2): 1, -S(7)/2: 1, -S(3)/2: 1, -S(1)/2: 1, S(3)/2: 1} assert roots((a+b+c)*x - (a+b+c+d), x) == {(a+b+c+d)/(a+b+c): 1} assert roots(x**3+x**2-x+1, x, cubics=False) == {} assert roots(((x-2)*(x+3)*(x-4)).expand(), x, cubics=False) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(((x-2)*(x+3)*(x-4)*(x-5)).expand(), x, cubics=False) == \ {-S(3): 1, S(2): 1, S(4): 1, S(5): 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x) == {-S(2): 1, -2*I: 1, 2*I: 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x, cubics=True) == \ {-2*I: 1, 2*I: 1, -S(2): 1} assert roots((x**2 - x)*(x**3 + 2*x**2 + 4*x + 8), x ) == \ {S(1): 1, S(0): 1, -S(2): 1, -2*I: 1, 2*I: 1} r1_2, r1_3, r1_9, r4_9, r19_27 = [ Rational(*r) \ for r in ((1,2), (1,3), (1,9), (4,9), (19,27)) ] U = -r1_2 - r1_2*I*3**r1_2 V = -r1_2 + r1_2*I*3**r1_2 W = (r19_27 + r1_9*33**r1_2)**r1_3 assert roots(x**3+x**2-x+1, x, cubics=True) == { -r1_3 - U*W - r4_9*(U*W)**(-1): 1, -r1_3 - V*W - r4_9*(V*W)**(-1): 1, -r1_3 - W - r4_9*( W)**(-1): 1, } f = (x**2+2*x+3).subs(x, 2*x**2 + 3*x).subs(x, 5*x-4) r1_2, r13_20, r1_100 = [ Rational(*r) \ for r in ((1,2), (13,20), (1,100)) ] assert roots(f, x) == { r13_20 + r1_100*(25 - 200*I*2**r1_2)**r1_2: 1, r13_20 - r1_100*(25 - 200*I*2**r1_2)**r1_2: 1, r13_20 + r1_100*(25 + 200*I*2**r1_2)**r1_2: 1, r13_20 - r1_100*(25 + 200*I*2**r1_2)**r1_2: 1, } f = x**4 + x**3 + x**2 + x + 1 r1_4, r1_8, r5_8 = [ Rational(*r) for r in ((1,4), (1,8), (5,8)) ] assert roots(f, x) == { -r1_4 + r1_4*5**r1_2 + I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 + r1_4*5**r1_2 - I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 + I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 - I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, } f = z**3 + (-2 - y)*z**2 + (1 + 2*y - 2*x**2)*z - y + 2*x**2 assert roots(f, z) == { S.One: 1, S.Half + S.Half*y + S.Half*(1 - 2*y + y**2 + 8*x**2)**S.Half: 1, S.Half + S.Half*y - S.Half*(1 - 2*y + y**2 + 8*x**2)**S.Half: 1, } assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=False) == {} assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=True) != {} assert roots(x**4-1, x, filter='Z') == {S.One: 1, -S.One: 1} assert roots(x**4-1, x, filter='I') == {I: 1, -I: 1} assert roots((x-1)*(x+1), x) == {S.One: 1, -S.One: 1} assert roots((x-1)*(x+1), x, predicate=lambda r: r.is_positive) == {S.One: 1} assert roots(x**4-1, x, filter='Z', multiple=True) == [-S.One, S.One] assert roots(x**4-1, x, filter='I', multiple=True) == [-I, I] assert roots(x**3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == [] f = x**6 - x**5 + x**4 - x**3 + x**2 - x + 1 assert roots(f) == { -I*sin(pi/7) + cos(pi/7): 1, -I*sin(2*pi/7) - cos(2*pi/7): 1, -I*sin(3*pi/7) + cos(3*pi/7): 1, I*sin(pi/7) + cos(pi/7): 1, I*sin(2*pi/7) - cos(2*pi/7): 1, I*sin(3*pi/7) + cos(3*pi/7): 1, } g = ((x**2 + 1)*f**2).expand() assert roots(g) == { -I*sin(pi/7) + cos(pi/7): 2, -I*sin(2*pi/7) - cos(2*pi/7): 2, -I*sin(3*pi/7) + cos(3*pi/7): 2, I*sin(pi/7) + cos(pi/7): 2, I*sin(2*pi/7) - cos(2*pi/7): 2, I*sin(3*pi/7) + cos(3*pi/7): 2, -I: 1, I: 1, }
def test_roots_composite(): assert len(roots(Poly(y**3 + y**2*sqrt(x) + y + x, y, composite=True))) == 3
def _lambert(eq, x, domain=S.Complexes): """ Given an expression assumed to be in the form ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0`` where X = g(x) and x = g^-1(X), return the Lambert solution, ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``. """ eq = _mexpand(expand_log(eq)) mainlog = _mostfunc(eq, log, x) if not mainlog: return [] # violated assumptions other = eq.subs(mainlog, 0) if isinstance(-other, log): eq = (eq - other).subs(mainlog, mainlog.args[0]) mainlog = mainlog.args[0] if not isinstance(mainlog, log): return [] # violated assumptions other = -(-other).args[0] eq += other if not x in other.free_symbols: return [] # violated assumptions d, f, X2 = _linab(other, x) logterm = collect(eq - other, mainlog) a = logterm.as_coefficient(mainlog) if a is None or x in a.free_symbols: return [] # violated assumptions logarg = mainlog.args[0] b, c, X1 = _linab(logarg, x) if X1 != X2: return [] # violated assumptions # invert the generator X1 so we have x(u) u = Dummy('rhs') xusolns = solve(X1 - u, x) # There are infinitely many branches for LambertW # but only branches for k = -1 and 0 might be real. The k = 0 # branch is real and the k = -1 branch is real if the LambertW argumen # in in range [-1/e, 0]. Since `solve` does not return infinite # solutions we will only include the -1 branch if it tests as real. # Otherwise, inclusion of any LambertW in the solution indicates to # the user that there are imaginary solutions corresponding to # different k values. lambert_real_branches = [-1, 0] sol = [] # solution of the given Lambert equation is like # sol = -c/b + (a/d)*LambertW(arg, k), # where arg = d/(a*b)*exp((c*d-b*f)/a/b) and k in lambert_real_branches. # Instead of considering the single arg, `d/(a*b)*exp((c*d-b*f)/a/b)`, # the individual `p` roots obtained when writing `exp((c*d-b*f)/a/b)` # as `exp(A/p) = exp(A)**(1/p)`, where `p` is an Integer, are used. # calculating args for LambertW num, den = ((c*d-b*f)/a/b).as_numer_denom() p, den = den.as_coeff_Mul() e = exp(num/den) t = Dummy('t') if p == 1: t = e args = [d/(a*b)*t] elif domain.is_subset(S.Reals): # print(l090) ind_ls = [d/(a*b)*t for t in roots(t**p - e, t).keys()] args = [] j = -1 for i in ind_ls: j += 1 if not isinstance(i,int): if not i.has(I): args.append(ind_ls[j]) elif isinstance(i,int): args.append(ind_ls[j]) else: args = [d/(a*b)*t for t in roots(t**p - e, t).keys()] if len(args) == 0: return S.EmptySet # calculating solutions from args for arg in args: for k in lambert_real_branches: w = LambertW(arg, k) if k and not w.is_real: continue rhs = -c/b + (a/d)*w for xu in xusolns: sol.append(xu.subs(u, rhs)) return sol
def to_sequence(self): """ Finds the recurrence relation in power series expansion of the function. Examples ======== >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators >>> from sympy.polys.domains import ZZ, QQ >>> from sympy import symbols >>> x = symbols('x') >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx') >>> HolonomicFunction(Dx - 1, x, 0, [1]).to_sequence() HolonomicSequence((-1) + (n + 1)Sn, n), u(0) = 1 See Also ======== HolonomicFunction.series References ========== hal.inria.fr/inria-00070025/document """ dict1 = {} n = symbols('n', integer=True) dom = self.annihilator.parent.base.dom R, _ = RecurrenceOperators(dom.old_poly_ring(n), 'Sn') for i, j in enumerate(self.annihilator.listofpoly): listofdmp = j.all_coeffs() degree = len(listofdmp) - 1 for k in range(degree + 1): coeff = listofdmp[degree - k] if coeff == 0: continue if i - k in dict1: dict1[i - k] += (coeff * rf(n - k + 1, i)) else: dict1[i - k] = (coeff * rf(n - k + 1, i)) sol = [] lower = min(dict1.keys()) upper = max(dict1.keys()) for j in range(lower, upper + 1): if j in dict1.keys(): sol.append(dict1[j].subs(n, n - lower)) else: sol.append(S(0)) # recurrence relation sol = RecurrenceOperator(sol, R) if not self._have_init_cond: return HolonomicSequence(sol) if self.x0 != 0: return HolonomicSequence(sol) # computing the initial conditions for recurrence order = sol.order all_roots = roots(sol.listofpoly[-1].rep, filter='Z') all_roots = all_roots.keys() if all_roots: max_root = max(all_roots) if max_root >= 0: order += max_root + 1 y0 = _extend_y0(self, order) u0 = [] # u(n) = y^n(0)/factorial(n) for i, j in enumerate(y0): u0.append(j / factorial(i)) return HolonomicSequence(sol, u0)
def test_roots(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x**9, x) == {S.Zero: 9} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x) == { -S(3): 1, S(2): 1, S(4): 1 } assert roots(2 * x + 1, x) == {-S.Half: 1} assert roots((2 * x + 1)**2, x) == {-S.Half: 2} assert roots((2 * x + 1)**5, x) == {-S.Half: 5} assert roots((2 * x + 1)**10, x) == {-S.Half: 10} assert roots(x**4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x**4 - 1)**2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2 * x - 3)**2).expand(), x) == {Rational(3, 2): 2} assert roots(((2 * x + 3)**2).expand(), x) == {-Rational(3, 2): 2} assert roots(((2 * x - 3)**3).expand(), x) == {Rational(3, 2): 3} assert roots(((2 * x + 3)**3).expand(), x) == {-Rational(3, 2): 3} assert roots(((2 * x - 3)**5).expand(), x) == {Rational(3, 2): 5} assert roots(((2 * x + 3)**5).expand(), x) == {-Rational(3, 2): 5} assert roots(((a * x - b)**5).expand(), x) == {b / a: 5} assert roots(((a * x + b)**5).expand(), x) == {-b / a: 5} assert roots(x**4 - 2 * x**2 + 1, x) == {S.One: 2, -S.One: 2} assert roots(x**6 - 4*x**4 + 4*x**3 - x**2, x) == \ {S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1} assert roots(x**8 - 1, x) == { sqrt(2) / 2 + I * sqrt(2) / 2: 1, sqrt(2) / 2 - I * sqrt(2) / 2: 1, -sqrt(2) / 2 + I * sqrt(2) / 2: 1, -sqrt(2) / 2 - I * sqrt(2) / 2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1 } f = -2016*x**2 - 5616*x**3 - 2056*x**4 + 3324*x**5 + 2176*x**6 - \ 224*x**7 - 384*x**8 - 64*x**9 assert roots(f) == { S(0): 2, -S(2): 2, S(2): 1, -S(7) / 2: 1, -S(3) / 2: 1, -S(1) / 2: 1, S(3) / 2: 1 } assert roots((a + b + c) * x - (a + b + c + d), x) == { (a + b + c + d) / (a + b + c): 1 } assert roots(x**3 + x**2 - x + 1, x, cubics=False) == {} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x, cubics=False) == { -S(3): 1, S(2): 1, S(4): 1 } assert roots(((x - 2)*(x + 3)*(x - 4)*(x - 5)).expand(), x, cubics=False) == \ {-S(3): 1, S(2): 1, S(4): 1, S(5): 1} assert roots(x**3 + 2 * x**2 + 4 * x + 8, x) == { -S(2): 1, -2 * I: 1, 2 * I: 1 } assert roots(x**3 + 2*x**2 + 4*x + 8, x, cubics=True) == \ {-2*I: 1, 2*I: 1, -S(2): 1} assert roots((x**2 - x)*(x**3 + 2*x**2 + 4*x + 8), x ) == \ {S(1): 1, S(0): 1, -S(2): 1, -2*I: 1, 2*I: 1} r1_2, r1_3, r1_9, r4_9, r19_27 = [ Rational(*r) for r in ((1, 2), (1, 3), (1, 9), (4, 9), (19, 27)) ] U = -r1_2 - r1_2 * I * 3**r1_2 V = -r1_2 + r1_2 * I * 3**r1_2 W = (r19_27 + r1_9 * 33**r1_2)**r1_3 assert roots(x**3 + x**2 - x + 1, x, cubics=True) == { -r1_3 - U * W - r4_9 * (U * W)**(-1): 1, -r1_3 - V * W - r4_9 * (V * W)**(-1): 1, -r1_3 - W - r4_9 * (W)**(-1): 1, } f = (x**2 + 2 * x + 3).subs(x, 2 * x**2 + 3 * x).subs(x, 5 * x - 4) r13_20, r1_20 = [Rational(*r) for r in ((13, 20), (1, 20))] s2 = sqrt(2) assert roots(f, x) == { r13_20 + r1_20 * sqrt(1 - 8 * I * s2): 1, r13_20 - r1_20 * sqrt(1 - 8 * I * s2): 1, r13_20 + r1_20 * sqrt(1 + 8 * I * s2): 1, r13_20 - r1_20 * sqrt(1 + 8 * I * s2): 1, } f = x**4 + x**3 + x**2 + x + 1 r1_4, r1_8, r5_8 = [Rational(*r) for r in ((1, 4), (1, 8), (5, 8))] assert roots(f, x) == { -r1_4 + r1_4 * 5**r1_2 + I * (r5_8 + r1_8 * 5**r1_2)**r1_2: 1, -r1_4 + r1_4 * 5**r1_2 - I * (r5_8 + r1_8 * 5**r1_2)**r1_2: 1, -r1_4 - r1_4 * 5**r1_2 + I * (r5_8 - r1_8 * 5**r1_2)**r1_2: 1, -r1_4 - r1_4 * 5**r1_2 - I * (r5_8 - r1_8 * 5**r1_2)**r1_2: 1, } f = z**3 + (-2 - y) * z**2 + (1 + 2 * y - 2 * x**2) * z - y + 2 * x**2 assert roots(f, z) == { S.One: 1, S.Half + S.Half * y + S.Half * sqrt(1 - 2 * y + y**2 + 8 * x**2): 1, S.Half + S.Half * y - S.Half * sqrt(1 - 2 * y + y**2 + 8 * x**2): 1, } assert roots(a * b * c * x**3 + 2 * x**2 + 4 * x + 8, x, cubics=False) == {} assert roots(a * b * c * x**3 + 2 * x**2 + 4 * x + 8, x, cubics=True) != {} assert roots(x**4 - 1, x, filter='Z') == {S.One: 1, -S.One: 1} assert roots(x**4 - 1, x, filter='I') == {I: 1, -I: 1} assert roots((x - 1) * (x + 1), x) == {S.One: 1, -S.One: 1} assert roots((x - 1) * (x + 1), x, predicate=lambda r: r.is_positive) == { S.One: 1 } assert roots(x**4 - 1, x, filter='Z', multiple=True) == [-S.One, S.One] assert roots(x**4 - 1, x, filter='I', multiple=True) == [-I, I] assert roots(x**3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == [] f = x**6 - x**5 + x**4 - x**3 + x**2 - x + 1 assert roots(f) == { -I * sin(pi / 7) + cos(pi / 7): 1, -I * sin(2 * pi / 7) - cos(2 * pi / 7): 1, -I * sin(3 * pi / 7) + cos(3 * pi / 7): 1, I * sin(pi / 7) + cos(pi / 7): 1, I * sin(2 * pi / 7) - cos(2 * pi / 7): 1, I * sin(3 * pi / 7) + cos(3 * pi / 7): 1, } g = ((x**2 + 1) * f**2).expand() assert roots(g) == { -I * sin(pi / 7) + cos(pi / 7): 2, -I * sin(2 * pi / 7) - cos(2 * pi / 7): 2, -I * sin(3 * pi / 7) + cos(3 * pi / 7): 2, I * sin(pi / 7) + cos(pi / 7): 2, I * sin(2 * pi / 7) - cos(2 * pi / 7): 2, I * sin(3 * pi / 7) + cos(3 * pi / 7): 2, -I: 1, I: 1, } r = roots(x**3 + 40 * x + 64) real_root = [rx for rx in r if rx.is_real][0] cr = 4 + 2 * sqrt(1074) / 9 assert real_root == -2 * cr**(S(1) / 3) + 20 / (3 * cr**(S(1) / 3)) eq = Poly((7 + 5 * sqrt(2)) * x**3 + (-6 - 4 * sqrt(2)) * x**2 + (-sqrt(2) - 1) * x + 2, x, domain='EX') assert roots(eq) == {-1 + sqrt(2): 1, -2 + 2 * sqrt(2): 1, -sqrt(2) + 1: 1} eq = Poly(41 * x**5 + 29 * sqrt(2) * x**5 - 153 * x**4 - 108 * sqrt(2) * x**4 + 175 * x**3 + 125 * sqrt(2) * x**3 - 45 * x**2 - 30 * sqrt(2) * x**2 - 26 * sqrt(2) * x - 26 * x + 24, x, domain='EX') assert roots(eq) == { -sqrt(2) + 1: 1, -2 + 2 * sqrt(2): 1, -1 + sqrt(2): 1, -4 + 4 * sqrt(2): 1, -3 + 3 * sqrt(2): 1 } eq = Poly(x**3 - 2 * x**2 + 6 * sqrt(2) * x**2 - 8 * sqrt(2) * x + 23 * x - 14 + 14 * sqrt(2), x, domain='EX') assert roots(eq) == { -2 * sqrt(2) + 2: 1, -2 * sqrt(2) + 1: 1, -2 * sqrt(2) - 1: 1 } assert roots(Poly((x + sqrt(2))**3 - 7, x, domain='EX')) == \ {-sqrt(2) - 7**(S(1)/3)/2 - sqrt(3)*7**(S(1)/3)*I/2: 1, -sqrt(2) - 7**(S(1)/3)/2 + sqrt(3)*7**(S(1)/3)*I/2: 1, -sqrt(2) + 7**(S(1)/3): 1}
def test_issue_16589(): eq = Poly( x**4 - 8 * sqrt(2) * x**3 + 4 * x**3 - 64 * sqrt(2) * x**2 + 1024 * x, x) roots_eq = roots(eq) assert 0 in roots_eq
def test_issue_13340(): eq = Poly(y**3 + exp(x) * y + x, y, domain='EX') roots_d = roots(eq) assert len(roots_d) == 3
def solve_riccati(fx, x, b0, b1, b2, gensol=False): """ The main function that gives particular/general solutions to Riccati ODEs that have atleast 1 rational particular solution. """ # Step 1 : Convert to Normal Form a = -b0*b2 + b1**2/4 - b1.diff(x)/2 + 3*b2.diff(x)**2/(4*b2**2) + b1*b2.diff(x)/(2*b2) - \ b2.diff(x, 2)/(2*b2) a_t = a.together() num, den = [Poly(e, x, extension=True) for e in a_t.as_numer_denom()] num, den = num.cancel(den, include=True) # Step 2 presol = [] # Step 3 : a(x) is 0 if num == 0: presol.append(1/(x + Dummy('C1'))) # Step 4 : a(x) is a non-zero constant elif x not in num.free_symbols.union(den.free_symbols): presol.extend([sqrt(a), -sqrt(a)]) # Step 5 : Find poles and valuation at infinity poles = roots(den, x) poles, muls = list(poles.keys()), list(poles.values()) val_inf = val_at_inf(num, den, x) if len(poles): # Check necessary conditions (outlined in the module docstring) if not check_necessary_conds(val_inf, muls): raise ValueError("Rational Solution doesn't exist") # Step 6 # Construct c-vectors for each singular point c = construct_c(num, den, x, poles, muls) # Construct d vectors for each singular point d = construct_d(num, den, x, val_inf) # Step 7 : Iterate over all possible combinations and return solutions # For each possible combination, generate an array of 0's and 1's # where 0 means pick 1st choice and 1 means pick the second choice. # NOTE: We could exit from the loop if we find 3 particular solutions, # but it is not implemented here as - # a. Finding 3 particular solutions is very rare. Most of the time, # only 2 particular solutions are found. # b. In case we exit after finding 3 particular solutions, it might # happen that 1 or 2 of them are redundant solutions. So, instead of # spending some more time in computing the particular solutions, # we will end up computing the general solution from a single # particular solution which is usually slower than computing the # general solution from 2 or 3 particular solutions. c.append(d) choices = product(*c) for choice in choices: m, ybar = compute_m_ybar(x, poles, choice, -val_inf//2) numy, deny = [Poly(e, x, extension=True) for e in ybar.together().as_numer_denom()] # Step 10 : Check if a valid solution exists. If yes, also check # if m is a non-negative integer if m.is_nonnegative == True and m.is_integer == True: # Step 11 : Find polynomial solutions of degree m for the auxiliary equation psol, coeffs, exists = solve_aux_eq(num, den, numy, deny, x, m) # Step 12 : If valid polynomial solution exists, append solution. if exists: # m == 0 case if psol == 1 and coeffs == 0: # p(x) = 1, so p'(x)/p(x) term need not be added presol.append(ybar) # m is a positive integer and there are valid coefficients elif len(coeffs): # Substitute the valid coefficients to get p(x) psol = psol.xreplace(coeffs) # y(x) = ybar(x) + p'(x)/p(x) presol.append(ybar + psol.diff(x)/psol) # Remove redundant solutions from the list of existing solutions remove = set() for i in range(len(presol)): for j in range(i+1, len(presol)): rem = remove_redundant_sols(presol[i], presol[j], x) if rem is not None: remove.add(rem) sols = [x for x in presol if x not in remove] # Step 15 : Inverse transform the solutions of the equation in normal form bp = -b2.diff(x)/(2*b2**2) - b1/(2*b2) # If general solution is required, compute it from the particular solutions if gensol: sols = [get_gen_sol_from_part_sol(sols, a, x)] # Inverse transform the particular solutions presol = [Eq(fx, riccati_inverse_normal(y, x, b1, b2, bp).cancel(extension=True)) for y in sols] return presol
def test_issue_14522(): eq = Poly(x**4 + x**3*(16 + 32*I) + x**2*(-285 + 386*I) + x*(-2824 - 448*I) - 2058 - 6053*I, x) roots_eq = roots(eq) assert all(eq(r) == 0 for r in roots_eq)
def _pole_degree(poly): root_all = roots(poly.rep, filter='Z') if 0 in root_all.keys(): return root_all[0] else: return 0
def test_roots(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x ** 9, x) == {S.Zero: 9} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(2 * x + 1, x) == {-S.Half: 1} assert roots((2 * x + 1) ** 2, x) == {-S.Half: 2} assert roots((2 * x + 1) ** 5, x) == {-S.Half: 5} assert roots((2 * x + 1) ** 10, x) == {-S.Half: 10} assert roots(x ** 4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x ** 4 - 1) ** 2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2 * x - 3) ** 2).expand(), x) == {Rational(3, 2): 2} assert roots(((2 * x + 3) ** 2).expand(), x) == {-Rational(3, 2): 2} assert roots(((2 * x - 3) ** 3).expand(), x) == {Rational(3, 2): 3} assert roots(((2 * x + 3) ** 3).expand(), x) == {-Rational(3, 2): 3} assert roots(((2 * x - 3) ** 5).expand(), x) == {Rational(3, 2): 5} assert roots(((2 * x + 3) ** 5).expand(), x) == {-Rational(3, 2): 5} assert roots(((a * x - b) ** 5).expand(), x) == {b / a: 5} assert roots(((a * x + b) ** 5).expand(), x) == {-b / a: 5} assert roots(x ** 4 - 2 * x ** 2 + 1, x) == {S.One: 2, -S.One: 2} assert roots(x ** 6 - 4 * x ** 4 + 4 * x ** 3 - x ** 2, x) == { S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1, } R1 = sorted([r.evalf() for r in roots(x ** 2 + x + 1, x)]) R2 = sorted([r for r in roots(x ** 2 + x + 1.0, x)]) assert R1 == R2 assert roots(x ** 8 - 1, x) == { 2 ** S.Half / 2 + I * 2 ** S.Half / 2: 1, 2 ** S.Half / 2 - I * 2 ** S.Half / 2: 1, -2 ** S.Half / 2 + I * 2 ** S.Half / 2: 1, -2 ** S.Half / 2 - I * 2 ** S.Half / 2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1, } assert roots( -2016 * x ** 2 - 5616 * x ** 3 - 2056 * x ** 4 + 3324 * x ** 5 + 2176 * x ** 6 - 224 * x ** 7 - 384 * x ** 8 - 64 * x ** 9, x, ) == {S(0): 2, -S(2): 2, S(2): 1, -S(7) / 2: 1, -S(3) / 2: 1, -S(1) / 2: 1, S(3) / 2: 1} assert roots((a + b + c) * x - (a + b + c + d), x) == {(a + b + c + d) / (a + b + c): 1} assert roots(x ** 3 + x ** 2 - x + 1, x, cubics=False) == {} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x, cubics=False) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(((x - 2) * (x + 3) * (x - 4) * (x - 5)).expand(), x, cubics=False) == { -S(3): 1, S(2): 1, S(4): 1, S(5): 1, } assert roots(x ** 3 + 2 * x ** 2 + 4 * x + 8, x) == {-S(2): 1, -2 * I: 1, 2 * I: 1} assert roots(x ** 3 + 2 * x ** 2 + 4 * x + 8, x, cubics=True) == {-2 * I: 1, 2 * I: 1, -S(2): 1} assert roots((x ** 2 - x) * (x ** 3 + 2 * x ** 2 + 4 * x + 8), x) == { S(1): 1, S(0): 1, -S(2): 1, -2 * I: 1, 2 * I: 1, } r1_2, r1_3, r1_9, r4_9, r19_27 = [Rational(*r) for r in ((1, 2), (1, 3), (1, 9), (4, 9), (19, 27))] U = r1_2 + r1_2 * I * 3 ** r1_2 V = r1_2 - r1_2 * I * 3 ** r1_2 W = (r19_27 + r1_9 * 33 ** r1_2) ** r1_3 assert roots(x ** 3 + x ** 2 - x + 1, x, cubics=True) == { -r1_3 + U * W + r4_9 * (U * W) ** (-1): 1, -r1_3 + V * W + r4_9 * (V * W) ** (-1): 1, -r1_3 - W - r4_9 * (W) ** (-1): 1, } f = (x ** 2 + 2 * x + 3).subs(x, 2 * x ** 2 + 3 * x).subs(x, 5 * x - 4) r1_2, r13_20, r1_100 = [Rational(*r) for r in ((1, 2), (13, 20), (1, 100))] assert roots(f, x) == { r13_20 + r1_100 * (25 - 200 * I * 2 ** r1_2) ** r1_2: 1, r13_20 - r1_100 * (25 - 200 * I * 2 ** r1_2) ** r1_2: 1, r13_20 + r1_100 * (25 + 200 * I * 2 ** r1_2) ** r1_2: 1, r13_20 - r1_100 * (25 + 200 * I * 2 ** r1_2) ** r1_2: 1, } f = x ** 4 + x ** 3 + x ** 2 + x + 1 r1_2, r1_4, r5_2 = [Rational(*r) for r in ((1, 2), (1, 4), (5, 2))] assert roots(f, x) == { -r1_4 + r1_4 * 5 ** r1_2 + r1_2 * (-r5_2 - r1_2 * 5 ** r1_2) ** r1_2: 1, -r1_4 + r1_4 * 5 ** r1_2 - r1_2 * (-r5_2 - r1_2 * 5 ** r1_2) ** r1_2: 1, -r1_4 - r1_4 * 5 ** r1_2 + r1_2 * (-r5_2 + r1_2 * 5 ** r1_2) ** r1_2: 1, -r1_4 - r1_4 * 5 ** r1_2 - r1_2 * (-r5_2 + r1_2 * 5 ** r1_2) ** r1_2: 1, } f = z ** 3 + (-2 - y) * z ** 2 + (1 + 2 * y - 2 * x ** 2) * z - y + 2 * x ** 2 assert roots(f, z) == { S.One: 1, S.Half + S.Half * y + S.Half * (1 - 2 * y + y ** 2 + 8 * x ** 2) ** S.Half: 1, S.Half + S.Half * y - S.Half * (1 - 2 * y + y ** 2 + 8 * x ** 2) ** S.Half: 1, } assert roots(a * b * c * x ** 3 + 2 * x ** 2 + 4 * x + 8, x, cubics=False) == {} assert roots(a * b * c * x ** 3 + 2 * x ** 2 + 4 * x + 8, x, cubics=True) != {} assert roots(x ** 4 - 1, x, filter="Z") == {S.One: 1, -S.One: 1} assert roots(x ** 4 - 1, x, filter="I") == {I: 1, -I: 1} assert roots((x - 1) * (x + 1), x) == {S.One: 1, -S.One: 1} assert roots((x - 1) * (x + 1), x, predicate=lambda r: r.is_positive) == {S.One: 1} assert roots(x ** 4 - 1, x, filter="Z", multiple=True) == [S.One, -S.One] assert roots(x ** 4 - 1, x, filter="I", multiple=True) in ([I, -I], [-I, I]) assert roots(x ** 3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == []
def series(self, n=6, coefficient=False, order=True): """ Finds the power series expansion of given holonomic function. Examples ======== >>> from sympy.holonomic.holonomic import HolonomicFunction, DifferentialOperators >>> from sympy.polys.domains import ZZ, QQ >>> from sympy import symbols >>> x = symbols('x') >>> R, Dx = DifferentialOperators(QQ.old_poly_ring(x),'Dx') >>> HolonomicFunction(Dx - 1, x, 0, [1]).series() # e^x 1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + O(x**6) >>> HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).series(n=8) # sin(x) x - x**3/6 + x**5/120 - x**7/5040 + O(x**8) See Also ======== HolonomicFunction.to_sequence """ recurrence = self.to_sequence() l = len(recurrence.u0) - 1 k = recurrence.recurrence.order x = self.x seq_dmp = recurrence.recurrence.listofpoly R = recurrence.recurrence.parent.base K = R.get_field() seq = [] if 0 in roots(seq_dmp[-1].rep, filter='Z').keys(): singular = True else: singular = False for i, j in enumerate(seq_dmp): seq.append(K.new(j.rep)) sub = [-seq[i] / seq[k] for i in range(k)] sol = [i for i in recurrence.u0] if l + 1 >= n: pass else: # use the initial conditions to find the next term for i in range(l + 1 - k, n - k): coeff = S(0) for j in range(k): if i + j >= 0: coeff += DMFsubs(sub[j], i) * sol[i + j] sol.append(coeff) if coefficient: return sol ser = S(0) for i, j in enumerate(sol): ser += x**i * j if order: return ser + Order(x**n, x) else: return ser
def test_issue_19113(): eq = cos(x)**3 - cos(x) + 1 raises(PolynomialError, lambda: roots(eq))
def _eval_expand_diracdelta(self, **hints): """ Compute a simplified representation of the function using property number 4. Pass ``wrt`` as a hint to expand the expression with respect to a particular variable. Explanation =========== ``wrt`` is: - a variable with respect to which a DiracDelta expression will get expanded. Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).expand(diracdelta=True, wrt=x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).expand(diracdelta=True, wrt=y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).expand(diracdelta=True, wrt=x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots wrt = hints.get('wrt', None) if wrt is None: free = self.free_symbols if len(free) == 1: wrt = free.pop() else: raise TypeError(filldedent(''' When there is more than 1 free symbol or variable in the expression, the 'wrt' keyword is required as a hint to expand when using the DiracDelta hint.''')) if not self.args[0].has(wrt) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], wrt) result = 0 valid = True darg = abs(diff(self.args[0], wrt)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(wrt - r)/darg.subs(wrt, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def test_issue_17454(): assert roots([1, -3 * (-4 - 4 * I)**2 / 8 + 12 * I, 0], multiple=True) == [0, 0]
def test_roots(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x**9, x) == {S.Zero: 9} assert roots(((x - 2)*(x + 3)*(x - 4)).expand(), x) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(2*x + 1, x) == {-S.Half: 1} assert roots((2*x + 1)**2, x) == {-S.Half: 2} assert roots((2*x + 1)**5, x) == {-S.Half: 5} assert roots((2*x + 1)**10, x) == {-S.Half: 10} assert roots(x**4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x**4 - 1)**2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2*x - 3)**2).expand(), x) == { Rational(3, 2): 2} assert roots(((2*x + 3)**2).expand(), x) == {-Rational(3, 2): 2} assert roots(((2*x - 3)**3).expand(), x) == { Rational(3, 2): 3} assert roots(((2*x + 3)**3).expand(), x) == {-Rational(3, 2): 3} assert roots(((2*x - 3)**5).expand(), x) == { Rational(3, 2): 5} assert roots(((2*x + 3)**5).expand(), x) == {-Rational(3, 2): 5} assert roots(((a*x - b)**5).expand(), x) == { b/a: 5} assert roots(((a*x + b)**5).expand(), x) == {-b/a: 5} assert roots(x**2 + (-a - 1)*x + a, x) == {a: 1, S.One: 1} assert roots(x**4 - 2*x**2 + 1, x) == {S.One: 2, -S.One: 2} assert roots(x**6 - 4*x**4 + 4*x**3 - x**2, x) == \ {S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1} assert roots(x**8 - 1, x) == { sqrt(2)/2 + I*sqrt(2)/2: 1, sqrt(2)/2 - I*sqrt(2)/2: 1, -sqrt(2)/2 + I*sqrt(2)/2: 1, -sqrt(2)/2 - I*sqrt(2)/2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1 } f = -2016*x**2 - 5616*x**3 - 2056*x**4 + 3324*x**5 + 2176*x**6 - \ 224*x**7 - 384*x**8 - 64*x**9 assert roots(f) == {S(0): 2, -S(2): 2, S(2): 1, -S(7)/2: 1, -S(3)/2: 1, -S(1)/2: 1, S(3)/2: 1} assert roots((a + b + c)*x - (a + b + c + d), x) == {(a + b + c + d)/(a + b + c): 1} assert roots(x**3 + x**2 - x + 1, x, cubics=False) == {} assert roots(((x - 2)*( x + 3)*(x - 4)).expand(), x, cubics=False) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(((x - 2)*(x + 3)*(x - 4)*(x - 5)).expand(), x, cubics=False) == \ {-S(3): 1, S(2): 1, S(4): 1, S(5): 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x) == {-S(2): 1, -2*I: 1, 2*I: 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x, cubics=True) == \ {-2*I: 1, 2*I: 1, -S(2): 1} assert roots((x**2 - x)*(x**3 + 2*x**2 + 4*x + 8), x ) == \ {S(1): 1, S(0): 1, -S(2): 1, -2*I: 1, 2*I: 1} r1_2, r1_3, r1_9, r4_9, r19_27 = [ Rational(*r) for r in ((1, 2), (1, 3), (1, 9), (4, 9), (19, 27)) ] U = -r1_2 - r1_2*I*3**r1_2 V = -r1_2 + r1_2*I*3**r1_2 W = (r19_27 + r1_9*33**r1_2)**r1_3 assert roots(x**3 + x**2 - x + 1, x, cubics=True) == { -r1_3 - U*W - r4_9*(U*W)**(-1): 1, -r1_3 - V*W - r4_9*(V*W)**(-1): 1, -r1_3 - W - r4_9*( W)**(-1): 1, } f = (x**2 + 2*x + 3).subs(x, 2*x**2 + 3*x).subs(x, 5*x - 4) r13_20, r1_20 = [ Rational(*r) for r in ((13, 20), (1, 20)) ] s2 = sqrt(2) assert roots(f, x) == { r13_20 + r1_20*sqrt(1 - 8*I*s2): 1, r13_20 - r1_20*sqrt(1 - 8*I*s2): 1, r13_20 + r1_20*sqrt(1 + 8*I*s2): 1, r13_20 - r1_20*sqrt(1 + 8*I*s2): 1, } f = x**4 + x**3 + x**2 + x + 1 r1_4, r1_8, r5_8 = [ Rational(*r) for r in ((1, 4), (1, 8), (5, 8)) ] assert roots(f, x) == { -r1_4 + r1_4*5**r1_2 + I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 + r1_4*5**r1_2 - I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 + I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 - I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, } f = z**3 + (-2 - y)*z**2 + (1 + 2*y - 2*x**2)*z - y + 2*x**2 assert roots(f, z) == { S.One: 1, S.Half + S.Half*y + S.Half*sqrt(1 - 2*y + y**2 + 8*x**2): 1, S.Half + S.Half*y - S.Half*sqrt(1 - 2*y + y**2 + 8*x**2): 1, } assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=False) == {} assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=True) != {} assert roots(x**4 - 1, x, filter='Z') == {S.One: 1, -S.One: 1} assert roots(x**4 - 1, x, filter='I') == {I: 1, -I: 1} assert roots((x - 1)*(x + 1), x) == {S.One: 1, -S.One: 1} assert roots( (x - 1)*(x + 1), x, predicate=lambda r: r.is_positive) == {S.One: 1} assert roots(x**4 - 1, x, filter='Z', multiple=True) == [-S.One, S.One] assert roots(x**4 - 1, x, filter='I', multiple=True) == [I, -I] assert roots(x**3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == [] f = x**6 - x**5 + x**4 - x**3 + x**2 - x + 1 assert roots(f) == { -I*sin(pi/7) + cos(pi/7): 1, -I*sin(2*pi/7) - cos(2*pi/7): 1, -I*sin(3*pi/7) + cos(3*pi/7): 1, I*sin(pi/7) + cos(pi/7): 1, I*sin(2*pi/7) - cos(2*pi/7): 1, I*sin(3*pi/7) + cos(3*pi/7): 1, } g = ((x**2 + 1)*f**2).expand() assert roots(g) == { -I*sin(pi/7) + cos(pi/7): 2, -I*sin(2*pi/7) - cos(2*pi/7): 2, -I*sin(3*pi/7) + cos(3*pi/7): 2, I*sin(pi/7) + cos(pi/7): 2, I*sin(2*pi/7) - cos(2*pi/7): 2, I*sin(3*pi/7) + cos(3*pi/7): 2, -I: 1, I: 1, } r = roots(x**3 + 40*x + 64) real_root = [rx for rx in r if rx.is_real][0] cr = 4 + 2*sqrt(1074)/9 assert real_root == -2*root(cr, 3) + 20/(3*root(cr, 3)) eq = Poly((7 + 5*sqrt(2))*x**3 + (-6 - 4*sqrt(2))*x**2 + (-sqrt(2) - 1)*x + 2, x, domain='EX') assert roots(eq) == {-1 + sqrt(2): 1, -2 + 2*sqrt(2): 1, -sqrt(2) + 1: 1} eq = Poly(41*x**5 + 29*sqrt(2)*x**5 - 153*x**4 - 108*sqrt(2)*x**4 + 175*x**3 + 125*sqrt(2)*x**3 - 45*x**2 - 30*sqrt(2)*x**2 - 26*sqrt(2)*x - 26*x + 24, x, domain='EX') assert roots(eq) == {-sqrt(2) + 1: 1, -2 + 2*sqrt(2): 1, -1 + sqrt(2): 1, -4 + 4*sqrt(2): 1, -3 + 3*sqrt(2): 1} eq = Poly(x**3 - 2*x**2 + 6*sqrt(2)*x**2 - 8*sqrt(2)*x + 23*x - 14 + 14*sqrt(2), x, domain='EX') assert roots(eq) == {-2*sqrt(2) + 2: 1, -2*sqrt(2) + 1: 1, -2*sqrt(2) - 1: 1} assert roots(Poly((x + sqrt(2))**3 - 7, x, domain='EX')) == \ {-sqrt(2) - root(7, 3)/2 - sqrt(3)*root(7, 3)*I/2: 1, -sqrt(2) - root(7, 3)/2 + sqrt(3)*root(7, 3)*I/2: 1, -sqrt(2) + root(7, 3): 1}
def _eval_expand_diracdelta(self, **hints): """Compute a simplified representation of the function using property number 4. Pass wrt as a hint to expand the expression with respect to a particular variable. wrt is: - a variable with respect to which a DiracDelta expression will get expanded. Examples ======== >>> from sympy import DiracDelta >>> from sympy.abc import x, y >>> DiracDelta(x*y).expand(diracdelta=True, wrt=x) DiracDelta(x)/Abs(y) >>> DiracDelta(x*y).expand(diracdelta=True, wrt=y) DiracDelta(y)/Abs(x) >>> DiracDelta(x**2 + x - 2).expand(diracdelta=True, wrt=x) DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 See Also ======== is_simple, Diracdelta """ from sympy.polys.polyroots import roots wrt = hints.get('wrt', None) if wrt is None: free = self.free_symbols if len(free) == 1: wrt = free.pop() else: raise TypeError(filldedent(''' When there is more than 1 free symbol or variable in the expression, the 'wrt' keyword is required as a hint to expand when using the DiracDelta hint.''')) if not self.args[0].has(wrt) or (len(self.args) > 1 and self.args[1] != 0 ): return self try: argroots = roots(self.args[0], wrt) result = 0 valid = True darg = abs(diff(self.args[0], wrt)) for r, m in argroots.items(): if r.is_real is not False and m == 1: result += self.func(wrt - r)/darg.subs(wrt, r) else: # don't handle non-real and if m != 1 then # a polynomial will have a zero in the derivative (darg) # at r valid = False break if valid: return result except PolynomialError: pass return self
def test_roots0(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x**9, x) == {S.Zero: 9} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x) == { -S(3): 1, S(2): 1, S(4): 1 } assert roots(2 * x + 1, x) == {Rational(-1, 2): 1} assert roots((2 * x + 1)**2, x) == {Rational(-1, 2): 2} assert roots((2 * x + 1)**5, x) == {Rational(-1, 2): 5} assert roots((2 * x + 1)**10, x) == {Rational(-1, 2): 10} assert roots(x**4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x**4 - 1)**2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2 * x - 3)**2).expand(), x) == {Rational(3, 2): 2} assert roots(((2 * x + 3)**2).expand(), x) == {Rational(-3, 2): 2} assert roots(((2 * x - 3)**3).expand(), x) == {Rational(3, 2): 3} assert roots(((2 * x + 3)**3).expand(), x) == {Rational(-3, 2): 3} assert roots(((2 * x - 3)**5).expand(), x) == {Rational(3, 2): 5} assert roots(((2 * x + 3)**5).expand(), x) == {Rational(-3, 2): 5} assert roots(((a * x - b)**5).expand(), x) == {b / a: 5} assert roots(((a * x + b)**5).expand(), x) == {-b / a: 5} assert roots(x**2 + (-a - 1) * x + a, x) == {a: 1, S.One: 1} assert roots(x**4 - 2 * x**2 + 1, x) == {S.One: 2, S.NegativeOne: 2} assert roots(x**6 - 4*x**4 + 4*x**3 - x**2, x) == \ {S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1} assert roots(x**8 - 1, x) == { sqrt(2) / 2 + I * sqrt(2) / 2: 1, sqrt(2) / 2 - I * sqrt(2) / 2: 1, -sqrt(2) / 2 + I * sqrt(2) / 2: 1, -sqrt(2) / 2 - I * sqrt(2) / 2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1 } f = -2016*x**2 - 5616*x**3 - 2056*x**4 + 3324*x**5 + 2176*x**6 - \ 224*x**7 - 384*x**8 - 64*x**9 assert roots(f) == { S.Zero: 2, -S(2): 2, S(2): 1, Rational(-7, 2): 1, Rational(-3, 2): 1, Rational(-1, 2): 1, Rational(3, 2): 1 } assert roots((a + b + c) * x - (a + b + c + d), x) == { (a + b + c + d) / (a + b + c): 1 } assert roots(x**3 + x**2 - x + 1, x, cubics=False) == {} assert roots(((x - 2) * (x + 3) * (x - 4)).expand(), x, cubics=False) == { -S(3): 1, S(2): 1, S(4): 1 } assert roots(((x - 2)*(x + 3)*(x - 4)*(x - 5)).expand(), x, cubics=False) == \ {-S(3): 1, S(2): 1, S(4): 1, S(5): 1} assert roots(x**3 + 2 * x**2 + 4 * x + 8, x) == { -S(2): 1, -2 * I: 1, 2 * I: 1 } assert roots(x**3 + 2*x**2 + 4*x + 8, x, cubics=True) == \ {-2*I: 1, 2*I: 1, -S(2): 1} assert roots((x**2 - x)*(x**3 + 2*x**2 + 4*x + 8), x ) == \ {S.One: 1, S.Zero: 1, -S(2): 1, -2*I: 1, 2*I: 1} r1_2, r1_3 = S.Half, Rational(1, 3) x0 = (3 * sqrt(33) + 19)**r1_3 x1 = 4 / x0 / 3 x2 = x0 / 3 x3 = sqrt(3) * I / 2 x4 = x3 - r1_2 x5 = -x3 - r1_2 assert roots(x**3 + x**2 - x + 1, x, cubics=True) == { -x1 - x2 - r1_3: 1, -x1 / x4 - x2 * x4 - r1_3: 1, -x1 / x5 - x2 * x5 - r1_3: 1, } f = (x**2 + 2 * x + 3).subs(x, 2 * x**2 + 3 * x).subs(x, 5 * x - 4) r13_20, r1_20 = [Rational(*r) for r in ((13, 20), (1, 20))] s2 = sqrt(2) assert roots(f, x) == { r13_20 + r1_20 * sqrt(1 - 8 * I * s2): 1, r13_20 - r1_20 * sqrt(1 - 8 * I * s2): 1, r13_20 + r1_20 * sqrt(1 + 8 * I * s2): 1, r13_20 - r1_20 * sqrt(1 + 8 * I * s2): 1, } f = x**4 + x**3 + x**2 + x + 1 r1_4, r1_8, r5_8 = [Rational(*r) for r in ((1, 4), (1, 8), (5, 8))] assert roots(f, x) == { -r1_4 + r1_4 * 5**r1_2 + I * (r5_8 + r1_8 * 5**r1_2)**r1_2: 1, -r1_4 + r1_4 * 5**r1_2 - I * (r5_8 + r1_8 * 5**r1_2)**r1_2: 1, -r1_4 - r1_4 * 5**r1_2 + I * (r5_8 - r1_8 * 5**r1_2)**r1_2: 1, -r1_4 - r1_4 * 5**r1_2 - I * (r5_8 - r1_8 * 5**r1_2)**r1_2: 1, } f = z**3 + (-2 - y) * z**2 + (1 + 2 * y - 2 * x**2) * z - y + 2 * x**2 assert roots(f, z) == { S.One: 1, S.Half + S.Half * y + S.Half * sqrt(1 - 2 * y + y**2 + 8 * x**2): 1, S.Half + S.Half * y - S.Half * sqrt(1 - 2 * y + y**2 + 8 * x**2): 1, } assert roots(a * b * c * x**3 + 2 * x**2 + 4 * x + 8, x, cubics=False) == {} assert roots(a * b * c * x**3 + 2 * x**2 + 4 * x + 8, x, cubics=True) != {} assert roots(x**4 - 1, x, filter='Z') == {S.One: 1, -S.One: 1} assert roots(x**4 - 1, x, filter='I') == {I: 1, -I: 1} assert roots((x - 1) * (x + 1), x) == {S.One: 1, -S.One: 1} assert roots((x - 1) * (x + 1), x, predicate=lambda r: r.is_positive) == { S.One: 1 } assert roots(x**4 - 1, x, filter='Z', multiple=True) == [-S.One, S.One] assert roots(x**4 - 1, x, filter='I', multiple=True) == [I, -I] ar, br = symbols('a, b', real=True) p = x**2 * (ar - br)**2 + 2 * x * (br - ar) + 1 assert roots(p, x, filter='R') == {1 / (ar - br): 2} assert roots(x**3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == [] f = x**6 - x**5 + x**4 - x**3 + x**2 - x + 1 assert roots(f) == { -I * sin(pi / 7) + cos(pi / 7): 1, -I * sin(pi * Rational(2, 7)) - cos(pi * Rational(2, 7)): 1, -I * sin(pi * Rational(3, 7)) + cos(pi * Rational(3, 7)): 1, I * sin(pi / 7) + cos(pi / 7): 1, I * sin(pi * Rational(2, 7)) - cos(pi * Rational(2, 7)): 1, I * sin(pi * Rational(3, 7)) + cos(pi * Rational(3, 7)): 1, } g = ((x**2 + 1) * f**2).expand() assert roots(g) == { -I * sin(pi / 7) + cos(pi / 7): 2, -I * sin(pi * Rational(2, 7)) - cos(pi * Rational(2, 7)): 2, -I * sin(pi * Rational(3, 7)) + cos(pi * Rational(3, 7)): 2, I * sin(pi / 7) + cos(pi / 7): 2, I * sin(pi * Rational(2, 7)) - cos(pi * Rational(2, 7)): 2, I * sin(pi * Rational(3, 7)) + cos(pi * Rational(3, 7)): 2, -I: 1, I: 1, } r = roots(x**3 + 40 * x + 64) real_root = [rx for rx in r if rx.is_real][0] cr = 108 + 6 * sqrt(1074) assert real_root == -2 * root(cr, 3) / 3 + 20 / root(cr, 3) eq = Poly((7 + 5 * sqrt(2)) * x**3 + (-6 - 4 * sqrt(2)) * x**2 + (-sqrt(2) - 1) * x + 2, x, domain='EX') assert roots(eq) == {-1 + sqrt(2): 1, -2 + 2 * sqrt(2): 1, -sqrt(2) + 1: 1} eq = Poly(41 * x**5 + 29 * sqrt(2) * x**5 - 153 * x**4 - 108 * sqrt(2) * x**4 + 175 * x**3 + 125 * sqrt(2) * x**3 - 45 * x**2 - 30 * sqrt(2) * x**2 - 26 * sqrt(2) * x - 26 * x + 24, x, domain='EX') assert roots(eq) == { -sqrt(2) + 1: 1, -2 + 2 * sqrt(2): 1, -1 + sqrt(2): 1, -4 + 4 * sqrt(2): 1, -3 + 3 * sqrt(2): 1 } eq = Poly(x**3 - 2 * x**2 + 6 * sqrt(2) * x**2 - 8 * sqrt(2) * x + 23 * x - 14 + 14 * sqrt(2), x, domain='EX') assert roots(eq) == { -2 * sqrt(2) + 2: 1, -2 * sqrt(2) + 1: 1, -2 * sqrt(2) - 1: 1 } assert roots(Poly((x + sqrt(2))**3 - 7, x, domain='EX')) == \ {-sqrt(2) + root(7, 3)*(-S.Half - sqrt(3)*I/2): 1, -sqrt(2) + root(7, 3)*(-S.Half + sqrt(3)*I/2): 1, -sqrt(2) + root(7, 3): 1}
def _monotonic_sign(self): """Return the value closest to 0 that ``self`` may have if all symbols are signed and the result is uniformly the same sign for all values of symbols. If a symbol is only signed but not known to be an integer or the result is 0 then a symbol representative of the sign of self will be returned. Otherwise, None is returned if a) the sign could be positive or negative or b) self is not in one of the following forms: - L(x, y, ...) + A: a function linear in all symbols x, y, ... with an additive constant; if A is zero then the function can be a monomial whose sign is monotonic over the range of the variables, e.g. (x + 1)**3 if x is nonnegative. - A/L(x, y, ...) + B: the inverse of a function linear in all symbols x, y, ... that does not have a sign change from positive to negative for any set of values for the variables. - M(x, y, ...) + A: a monomial M whose factors are all signed and a constant, A. - A/M(x, y, ...) + B: the inverse of a monomial and constants A and B. - P(x): a univariate polynomial Examples ======== >>> from sympy.core.exprtools import _monotonic_sign as F >>> from sympy import Dummy >>> nn = Dummy(integer=True, nonnegative=True) >>> p = Dummy(integer=True, positive=True) >>> p2 = Dummy(integer=True, positive=True) >>> F(nn + 1) 1 >>> F(p - 1) _nneg >>> F(nn*p + 1) 1 >>> F(p2*p + 1) 2 >>> F(nn - 1) # could be negative, zero or positive """ if not self.is_extended_real: return if (-self).is_Symbol: rv = _monotonic_sign(-self) return rv if rv is None else -rv if not self.is_Add and self.as_numer_denom()[1].is_number: s = self if s.is_prime: if s.is_odd: return S(3) else: return S(2) elif s.is_composite: if s.is_odd: return S(9) else: return S(4) elif s.is_positive: if s.is_even: if s.is_prime is False: return S(4) else: return S(2) elif s.is_integer: return S.One else: return _eps elif s.is_extended_negative: if s.is_even: return S(-2) elif s.is_integer: return S.NegativeOne else: return -_eps if s.is_zero or s.is_extended_nonpositive or s.is_extended_nonnegative: return S.Zero return None # univariate polynomial free = self.free_symbols if len(free) == 1: if self.is_polynomial(): from sympy.polys.polytools import real_roots from sympy.polys.polyroots import roots from sympy.polys.polyerrors import PolynomialError x = free.pop() x0 = _monotonic_sign(x) if x0 == _eps or x0 == -_eps: x0 = S.Zero if x0 is not None: d = self.diff(x) if d.is_number: currentroots = [] else: try: currentroots = real_roots(d) except (PolynomialError, NotImplementedError): currentroots = [r for r in roots(d, x) if r.is_extended_real] y = self.subs(x, x0) if x.is_nonnegative and all(r <= x0 for r in currentroots): if y.is_nonnegative and d.is_positive: if y: return y if y.is_positive else Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_negative: if y: return y if y.is_negative else Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) elif x.is_nonpositive and all(r >= x0 for r in currentroots): if y.is_nonnegative and d.is_negative: if y: return Dummy('pos', positive=True) else: return Dummy('nneg', nonnegative=True) if y.is_nonpositive and d.is_positive: if y: return Dummy('neg', negative=True) else: return Dummy('npos', nonpositive=True) else: n, d = self.as_numer_denom() den = None if n.is_number: den = _monotonic_sign(d) elif not d.is_number: if _monotonic_sign(n) is not None: den = _monotonic_sign(d) if den is not None and (den.is_positive or den.is_negative): v = n*den if v.is_positive: return Dummy('pos', positive=True) elif v.is_nonnegative: return Dummy('nneg', nonnegative=True) elif v.is_negative: return Dummy('neg', negative=True) elif v.is_nonpositive: return Dummy('npos', nonpositive=True) return None # multivariate c, a = self.as_coeff_Add() v = None if not a.is_polynomial(): # F/A or A/F where A is a number and F is a signed, rational monomial n, d = a.as_numer_denom() if not (n.is_number or d.is_number): return if ( a.is_Mul or a.is_Pow) and \ a.is_rational and \ all(p.exp.is_Integer for p in a.atoms(Pow) if p.is_Pow) and \ (a.is_positive or a.is_negative): v = S.One for ai in Mul.make_args(a): if ai.is_number: v *= ai continue reps = {} for x in ai.free_symbols: reps[x] = _monotonic_sign(x) if reps[x] is None: return v *= ai.subs(reps) elif c: # signed linear expression if not any(p for p in a.atoms(Pow) if not p.is_number) and (a.is_nonpositive or a.is_nonnegative): free = list(a.free_symbols) p = {} for i in free: v = _monotonic_sign(i) if v is None: return p[i] = v or (_eps if i.is_nonnegative else -_eps) v = a.xreplace(p) if v is not None: rv = v + c if v.is_nonnegative and rv.is_positive: return rv.subs(_eps, 0) if v.is_nonpositive and rv.is_negative: return rv.subs(_eps, 0)
def test_roots_composite(): assert len(roots(Poly(y**3 + y**2 * sqrt(x) + y + x, y, composite=True))) == 3
def test_roots(): assert roots(1, x) == {} assert roots(x, x) == {S.Zero: 1} assert roots(x**9, x) == {S.Zero: 9} assert roots(((x-2)*(x+3)*(x-4)).expand(), x) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(2*x+1, x) == {-S.Half: 1} assert roots((2*x+1)**2, x) == {-S.Half: 2} assert roots((2*x+1)**5, x) == {-S.Half: 5} assert roots((2*x+1)**10, x) == {-S.Half: 10} assert roots(x**4 - 1, x) == {I: 1, S.One: 1, -S.One: 1, -I: 1} assert roots((x**4 - 1)**2, x) == {I: 2, S.One: 2, -S.One: 2, -I: 2} assert roots(((2*x-3)**2).expand(), x) == { Rational(3,2): 2} assert roots(((2*x+3)**2).expand(), x) == {-Rational(3,2): 2} assert roots(((2*x-3)**3).expand(), x) == { Rational(3,2): 3} assert roots(((2*x+3)**3).expand(), x) == {-Rational(3,2): 3} assert roots(((2*x-3)**5).expand(), x) == { Rational(3,2): 5} assert roots(((2*x+3)**5).expand(), x) == {-Rational(3,2): 5} assert roots(((a*x-b)**5).expand(), x) == { b/a: 5} assert roots(((a*x+b)**5).expand(), x) == {-b/a: 5} assert roots(x**4-2*x**2+1, x) == {S.One: 2, -S.One: 2} assert roots(x**6-4*x**4+4*x**3-x**2, x) == \ {S.One: 2, -1 - sqrt(2): 1, S.Zero: 2, -1 + sqrt(2): 1} assert roots(x**8-1, x) == { 2**S.Half/2 + I*2**S.Half/2: 1, 2**S.Half/2 - I*2**S.Half/2: 1, -2**S.Half/2 + I*2**S.Half/2: 1, -2**S.Half/2 - I*2**S.Half/2: 1, S.One: 1, -S.One: 1, I: 1, -I: 1 } f = -2016*x**2 - 5616*x**3 - 2056*x**4 + 3324*x**5 + 2176*x**6 - 224*x**7 - 384*x**8 - 64*x**9 assert roots(f) == {S(0): 2, -S(2): 2, S(2): 1, -S(7)/2: 1, -S(3)/2: 1, -S(1)/2: 1, S(3)/2: 1} assert roots((a+b+c)*x - (a+b+c+d), x) == {(a+b+c+d)/(a+b+c): 1} assert roots(x**3+x**2-x+1, x, cubics=False) == {} assert roots(((x-2)*(x+3)*(x-4)).expand(), x, cubics=False) == {-S(3): 1, S(2): 1, S(4): 1} assert roots(((x-2)*(x+3)*(x-4)*(x-5)).expand(), x, cubics=False) == \ {-S(3): 1, S(2): 1, S(4): 1, S(5): 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x) == {-S(2): 1, -2*I: 1, 2*I: 1} assert roots(x**3 + 2*x**2 + 4*x + 8, x, cubics=True) == \ {-2*I: 1, 2*I: 1, -S(2): 1} assert roots((x**2 - x)*(x**3 + 2*x**2 + 4*x + 8), x ) == \ {S(1): 1, S(0): 1, -S(2): 1, -2*I: 1, 2*I: 1} r1_2, r1_3, r1_9, r4_9, r19_27 = [ Rational(*r) \ for r in ((1,2), (1,3), (1,9), (4,9), (19,27)) ] U = r1_2 + r1_2*I*3**r1_2 V = r1_2 - r1_2*I*3**r1_2 W = (r19_27 + r1_9*33**r1_2)**r1_3 assert roots(x**3+x**2-x+1, x, cubics=True) == { -r1_3 + U*W + r4_9*(U*W)**(-1): 1, -r1_3 + V*W + r4_9*(V*W)**(-1): 1, -r1_3 - W - r4_9*( W)**(-1): 1, } f = (x**2+2*x+3).subs(x, 2*x**2 + 3*x).subs(x, 5*x-4) r1_2, r13_20, r1_100 = [ Rational(*r) \ for r in ((1,2), (13,20), (1,100)) ] assert roots(f, x) == { r13_20 + r1_100*(25 - 200*I*2**r1_2)**r1_2: 1, r13_20 - r1_100*(25 - 200*I*2**r1_2)**r1_2: 1, r13_20 + r1_100*(25 + 200*I*2**r1_2)**r1_2: 1, r13_20 - r1_100*(25 + 200*I*2**r1_2)**r1_2: 1, } f = x**4 + x**3 + x**2 + x + 1 r1_4, r1_8, r5_8 = [ Rational(*r) for r in ((1,4), (1,8), (5,8)) ] assert roots(f, x) == { -r1_4 + r1_4*5**r1_2 + I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 + r1_4*5**r1_2 - I*(r5_8 + r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 + I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, -r1_4 - r1_4*5**r1_2 - I*(r5_8 - r1_8*5**r1_2)**r1_2: 1, } f = z**3 + (-2 - y)*z**2 + (1 + 2*y - 2*x**2)*z - y + 2*x**2 assert roots(f, z) == { S.One: 1, S.Half + S.Half*y + S.Half*(1 - 2*y + y**2 + 8*x**2)**S.Half: 1, S.Half + S.Half*y - S.Half*(1 - 2*y + y**2 + 8*x**2)**S.Half: 1, } assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=False) == {} assert roots(a*b*c*x**3 + 2*x**2 + 4*x + 8, x, cubics=True) != {} assert roots(x**4-1, x, filter='Z') == {S.One: 1, -S.One: 1} assert roots(x**4-1, x, filter='I') == {I: 1, -I: 1} assert roots((x-1)*(x+1), x) == {S.One: 1, -S.One: 1} assert roots((x-1)*(x+1), x, predicate=lambda r: r.is_positive) == {S.One: 1} assert roots(x**4-1, x, filter='Z', multiple=True) == [S.One, -S.One] assert roots(x**4-1, x, filter='I', multiple=True) in ([I, -I], [-I, I]) assert roots(x**3, x, multiple=True) == [S.Zero, S.Zero, S.Zero] assert roots(1234, x, multiple=True) == [] f = x**6 - x**5 + x**4 - x**3 + x**2 - x + 1 assert roots(f) == { -I*sin(pi/7) + cos(pi/7): 1, -I*sin(2*pi/7) - cos(2*pi/7): 1, -I*sin(3*pi/7) + cos(3*pi/7): 1, I*sin(pi/7) + cos(pi/7): 1, I*sin(2*pi/7) - cos(2*pi/7): 1, I*sin(3*pi/7) + cos(3*pi/7): 1, } g = ((x**2 + 1)*f**2).expand() assert roots(g) == { -I*sin(pi/7) + cos(pi/7): 2, -I*sin(2*pi/7) - cos(2*pi/7): 2, -I*sin(3*pi/7) + cos(3*pi/7): 2, I*sin(pi/7) + cos(pi/7): 2, I*sin(2*pi/7) - cos(2*pi/7): 2, I*sin(3*pi/7) + cos(3*pi/7): 2, -I: 1, I: 1, }