def poly_factorize(poly): """Factorize multivariate polynomials into a sum of products of monomials. This function can be used to decompose polynomials into a form which minimizes the number of additions and multiplications, and which thus can be evaluated efficently.""" max_deg = {} if 'horner' in dir(sympy): return sympy.horner(poly) if not isinstance(poly, Poly): poly = Poly(sympy.expand(poly), *poly.atoms(Symbol)) denom, poly = poly.as_integer() # Determine the order of factorization. We proceed through the # symbols, starting with the one present in the highest order # in the polynomial. for i, sym in enumerate(poly.symbols): max_deg[i] = 0 for monom in poly.monoms: for i, symvar in enumerate(monom): max_deg[i] = max(max_deg[i], symvar) ret_poly = 0 monoms = list(poly.monoms) for isym, maxdeg in sorted(max_deg.items(), key=itemgetter(1), reverse=True): drop_idx = [] new_poly = [] for i, monom in enumerate(monoms): if monom[isym] > 0: drop_idx.append(i) new_poly.append((poly.coeff(*monom), monom)) if not new_poly: continue ret_poly += sympy.factor(Poly(new_poly, *poly.symbols)) for idx in reversed(drop_idx): del monoms[idx] # Add any remaining O(1) terms. new_poly = [] for i, monom in enumerate(monoms): new_poly.append((poly.coeff(*monom), monom)) if new_poly: ret_poly += Poly(new_poly, *poly.symbols) return ret_poly / denom
def ratint(f, x, **flags): """Performs indefinite integration of rational functions. Given a field K and a rational function f = p/q, where p and q are polynomials in K[x], returns a function g such that f = g'. >>> from sympy.integrals.rationaltools import ratint >>> from sympy.abc import x >>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x) -4*log(1 + x) + 4*log(-2 + x) - (6 + 12*x)/(1 - x**2) References ========== .. [Bro05] M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition, Springer-Verlag, 2005, pp. 35-70 """ if type(f) is not tuple: p, q = f.as_numer_denom() else: p, q = f p, q = Poly(p, x), Poly(q, x) g = poly_gcd(p, q) p = poly_div(p, g)[0] q = poly_div(q, g)[0] result, p = poly_div(p, q) result = result.integrate(x).as_basic() if p.is_zero: return result g, h = ratint_ratpart(p, q, x) P, Q = h.as_numer_denom() q, r = poly_div(P, Q, x) result += g + q.integrate(x).as_basic() if not r.is_zero: symbol = flags.get('symbol', 't') if not isinstance(symbol, Symbol): t = Symbol(symbol, dummy=True) else: t = symbol L = ratint_logpart(r, Q, x, t) real = flags.get('real') if real is None: if type(f) is not tuple: atoms = f.atoms() else: p, q = f atoms = p.atoms() \ | q.atoms() for elt in atoms - set([x]): if not elt.is_real: real = False break else: real = True eps = S(0) if not real: for h, q in L: eps += RootSum(Lambda(t, t*log(h.as_basic())), q) else: for h, q in L: R = log_to_real(h, q, x, t) if R is not None: eps += R else: eps += RootSum(Lambda(t, t*log(h.as_basic())), q) result += eps return result
def ratint(f, x, **flags): """Performs indefinite integration of rational functions. Given a field K and a rational function f = p/q, where p and q are polynomials in K[x], returns a function g such that f = g'. >>> from sympy import * >>> x = Symbol('x') >>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x) -4*log(1 + x) + 4*log(-2 + x) - (6 + 12*x)/(1 - x**2) References ========== .. [Bro05] M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition, Springer-Verlang, 2005, pp. 35-70 """ if type(f) is not tuple: p, q = f.as_numer_denom() else: p, q = f p, q = Poly(p, x), Poly(q, x) g = poly_gcd(p, q) p = poly_div(p, g)[0] q = poly_div(q, g)[0] result, p = poly_div(p, q) result = result.integrate(x).as_basic() if p.is_zero: return result g, h = ratint_ratpart(p, q, x) P, Q = h.as_numer_denom() q, r = poly_div(P, Q, x) result += g + q.integrate(x).as_basic() if not r.is_zero: symbol = flags.get('symbol', 't') if not isinstance(symbol, Symbol): t = Symbol(symbol, dummy=True) else: t = symbol L = ratint_logpart(r, Q, x, t) real = flags.get('real') if real is None: if type(f) is not tuple: atoms = f.atoms() else: p, q = f atoms = p.atoms() \ | q.atoms() for elt in atoms - set([x]): if not elt.is_real: real = False break else: real = True eps = S(0) if not real: for h, q in L: eps += RootSum(Lambda(t, t*log(h.as_basic())), q) else: for h, q in L: R = log_to_real(h, q, x, t) if R is not None: eps += R else: eps += RootSum(Lambda(t, t*log(h.as_basic())), q) result += eps return result