def poly_discriminant(p, symbol): """ Returns the discriminant of a polynomial with respect to symbol. The discriminant of a univariate polynomial p of degree n is defined as n**(n*(n-1)/2)/a_n*resultant(p, p'), where p' is the derivative of p and a_n is the leading coefficient of p. Because the resultant of two polynomials vanishes identically whenever the two polynomials share a root, and a polynomial shares a root with its derivative if and only if the root is a repeated root, it follows that the discriminant of a polynomial vanishes identically if and only if the polynomial has a repeated root. See also: <http://en.wikipedia.org/wiki/Discriminant> Example: >>> from sympy import discriminant, Poly >>> from sympy.abc import a, b, c, x >>> discriminant(Poly(a*x**2 + b*x + c, x), x) -4*a*c + b**2 >>> discriminant(Poly(2*x**5 + x**2 + 10, x), x) 500004320 >>> discriminant(Poly((x-1)*(x+1), x), x) 4 >>> discriminant(Poly((x-1)**2*(x+1), x), x) 0 """ if not isinstance(p, Poly): p = Poly(p, symbol) if not p.is_univariate: # We need to make p univariate for poly_resultant to work p = Poly(p.as_basic(), symbol) # Is there a better way to do this? if p.degree == 0: return S.Zero return (S(int((-1)**((p.degree)*(S(p.degree) - 1)/2)))/p.lead_coeff*\ poly_resultant(p, p.diff(symbol))).expand()
def poly_sqf(f, *symbols): """Compute square-free decomposition of an univariate polynomial. Given an univariate polynomial f over an unique factorization domain returns tuple (f_1, f_2, ..., f_n), where all A_i are co-prime and square-free polynomials and f = f_1 * f_2**2 * ... * f_n**n. >>> from sympy import * >>> x,y = symbols('xy') >>> p, q = poly_sqf(x*(x+1)**2, x) >>> p.as_basic() x >>> q.as_basic() 1 + x For more information on the implemented algorithm refer to: [1] M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition, Springer-Verlang, 2005 [2] J. von zur Gathen, J. Gerhard, Modern Computer Algebra, Second Edition, Cambridge University Press, 2003 """ if not isinstance(f, Poly): f = Poly(f, *symbols) elif symbols: raise SymbolsError("Redundant symbols were given") if f.is_multivariate: raise MultivariatePolyError(f) coeff, f = f.as_primitive() sqf = [] h = f.diff() g = poly_gcd(f, h) p = poly_div(f, g)[0] q = poly_div(h, g)[0] p, q = poly_reduce(p, q) while True: h = q - p.diff() if h.is_zero: break g = poly_gcd(p, h) sqf.append(g) p = poly_div(p, g)[0] q = poly_div(h, g)[0] p, q = poly_reduce(p, q) sqf.append(p) head, tail = sqf[0], sqf[1:] head = head.mul_term(coeff) return [head] + tail