def test_root_factors(): assert root_factors(Poly(1, x)) == [Poly(1, x)] assert root_factors(Poly(x, x)) == [Poly(x, x)] assert root_factors(x**2 - 1, x) == [x + 1, x - 1] assert root_factors(x**2 - y, x) == [x - sqrt(y), x + sqrt(y)] assert root_factors((x**4 - 1)**2) == \ [x + 1, x + 1, x - 1, x - 1, x - I, x - I, x + I, x + I] assert root_factors(Poly(x**4 - 1, x), filter='Z') == \ [Poly(x + 1, x), Poly(x - 1, x), Poly(x**2 + 1, x)] assert root_factors(8*x**2 + 12*x**4 + 6*x**6 + x**8, x, filter='Q') == \ [x, x, x**6 + 6*x**4 + 12*x**2 + 8] pytest.raises(ValueError, lambda: root_factors(Poly(x * y)))
def test_root_factors(): assert root_factors(Integer(1).as_poly(x)) == [Integer(1).as_poly(x)] assert root_factors(x.as_poly()) == [x.as_poly()] assert root_factors(x**2 - 1, x) == [x + 1, x - 1] assert root_factors(x**2 - y, x) == [x - sqrt(y), x + sqrt(y)] assert root_factors((x**4 - 1)**2) == \ [x + 1, x + 1, x - 1, x - 1, x - I, x - I, x + I, x + I] assert root_factors((x**4 - 1).as_poly(), filter='Z') == \ [(x + 1).as_poly(), (x - 1).as_poly(), (x**2 + 1).as_poly()] assert root_factors(8*x**2 + 12*x**4 + 6*x**6 + x**8, x, filter='Q') == \ [x, x, x**6 + 6*x**4 + 12*x**2 + 8] pytest.raises(ValueError, lambda: root_factors((x * y).as_poly()))
def test_root_factors(): assert root_factors(Poly(1, x)) == [Poly(1, x)] assert root_factors(Poly(x, x)) == [Poly(x, x)] assert root_factors(x**2 - 1, x) == [x + 1, x - 1] assert root_factors(x**2 - y, x) == [x - sqrt(y), x + sqrt(y)] assert root_factors((x**4 - 1)**2) == \ [x + 1, x + 1, x - 1, x - 1, x - I, x - I, x + I, x + I] assert root_factors(Poly(x**4 - 1, x), filter='Z') == \ [Poly(x + 1, x), Poly(x - 1, x), Poly(x**2 + 1, x)] assert root_factors(8*x**2 + 12*x**4 + 6*x**6 + x**8, x, filter='Q') == \ [x, x, x**6 + 6*x**4 + 12*x**2 + 8] pytest.raises(ValueError, lambda: root_factors(Poly(x*y)))
def _integrate(field=None): irreducibles = set() for poly in reducibles: for z in poly.free_symbols: if z in V: break # should this be: `irreducibles |= \ else: # set(root_factors(poly, z, filter=field))` continue # and the line below deleted? # | # V irreducibles |= set(root_factors(poly, z, filter=field)) log_coeffs, log_part = [], [] B = _symbols('B', len(irreducibles)) # Note: the ordering matters here for poly, b in reversed(list(ordered(zip(irreducibles, B)))): if poly.has(*V): poly_coeffs.append(b) log_part.append(b * log(poly)) # TODO: Currently it's better to use symbolic expressions here instead # of rational functions, because it's simpler and FracElement doesn't # give big speed improvement yet. This is because cancelation is slow # due to slow polynomial GCD algorithms. If this gets improved then # revise this code. candidate = poly_part / poly_denom + Add(*log_part) h = F - _derivation(candidate) / denom raw_numer = h.as_numer_denom()[0] # Rewrite raw_numer as a polynomial in K[coeffs][V] where K is a field # that we have to determine. We can't use simply atoms() because log(3), # sqrt(y) and similar expressions can appear, leading to non-trivial # domains. syms = set(poly_coeffs) | set(V) non_syms = set() def find_non_syms(expr): if expr.is_Integer or expr.is_Rational: pass # ignore trivial numbers elif expr in syms: pass # ignore variables elif not expr.has(*syms): non_syms.add(expr) elif expr.is_Add or expr.is_Mul or expr.is_Pow: list(map(find_non_syms, expr.args)) else: # TODO: Non-polynomial expression. This should have been # filtered out at an earlier stage. raise PolynomialError try: find_non_syms(raw_numer) except PolynomialError: return else: ground, _ = construct_domain(non_syms, field=True) coeff_ring = PolyRing(poly_coeffs, ground) ring = PolyRing(V, coeff_ring) numer = ring.from_expr(raw_numer) solution = solve_lin_sys(numer.coeffs(), coeff_ring) if solution is None: return else: solution = [(coeff_ring.symbols[coeff_ring.index(k)], v.as_expr()) for k, v in solution.items()] return candidate.subs(solution).subs( list(zip(poly_coeffs, [S.Zero] * len(poly_coeffs))))