def dup_ext_factor(f, K): """Factor univariate polynomials over algebraic number fields. """ n, lc = dup_degree(f), dup_LC(f, K) f = dup_monic(f, K) if n <= 0: return lc, [] if n == 1: return lc, [(f, 1)] f, F = dup_sqf_part(f, K), f s, g, r = dup_sqf_norm(f, K) factors = dup_factor_list_include(r, K.dom) if len(factors) == 1: return lc, [(f, n//dup_degree(f))] H = s*K.unit for i, (factor, _) in enumerate(factors): h = dup_convert(factor, K.dom, K) h, _, g = dup_inner_gcd(h, g, K) h = dup_shift(h, H, K) factors[i] = h factors = dup_trial_division(F, factors, K) return lc, factors
def dup_ext_factor(f, K): """Factor univariate polynomials over algebraic number fields. """ n, lc = dup_degree(f), dup_LC(f, K) f = dup_monic(f, K) if n <= 0: return lc, [] if n == 1: return lc, [(f, 1)] f, F = dup_sqf_part(f, K), f s, g, r = dup_sqf_norm(f, K) factors = dup_factor_list_include(r, K.dom) if len(factors) == 1: return lc, [(f, n // dup_degree(f))] H = s * K.unit for i, (factor, _) in enumerate(factors): h = dup_convert(factor, K.dom, K) h, _, g = dup_inner_gcd(h, g, K) h = dup_shift(h, H, K) factors[i] = h factors = dup_trial_division(F, factors, K) return lc, factors
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Zassenhaus algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Consider polynomial `f = 2*x**4 - 2`:: >>> from sympy.polys.factortools import dup_zz_factor >>> from sympy.polys.domains import ZZ >>> dup_zz_factor([2, 0, 0, 0, -2], ZZ) (2, [([1, -1], 1), ([1, 1], 1), ([1, 0, 1], 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H, factors = None, [] if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) for h in H: k = 0 while True: q, r = dup_div(f, h, K) if not r: f, k = q, k + 1 else: break factors.append((h, k)) return cont, _sort_factors(factors)
def dup_cyclotomic_p(f, K, irreducible=False): """ Efficiently test if ``f`` is a cyclotomic polnomial. Examples ======== >>> from sympy.polys.factortools import dup_cyclotomic_p >>> from sympy.polys.domains import ZZ >>> f = [1, 0, 1, 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 1, 0, 1] >>> dup_cyclotomic_p(f, ZZ) False >>> g = [1, 0, 1, 0, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 1, 0, 1] >>> dup_cyclotomic_p(g, ZZ) True """ if K.is_QQ: try: K0, K = K, K.get_ring() f = dup_convert(f, K0, K) except CoercionFailed: return False elif not K.is_ZZ: return False lc = dup_LC(f, K) tc = dup_TC(f, K) if lc != 1 or (tc != -1 and tc != 1): return False if not irreducible: coeff, factors = dup_factor_list(f, K) if coeff != K.one or factors != [(f, 1)]: return False n = dup_degree(f) g, h = [], [] for i in xrange(n, -1, -2): g.insert(0, f[i]) for i in xrange(n - 1, -1, -2): h.insert(0, f[i]) g = dup_sqr(dup_strip(g), K) h = dup_sqr(dup_strip(h), K) F = dup_sub(g, dup_lshift(h, 1, K), K) if K.is_negative(dup_LC(F, K)): F = dup_neg(F, K) if F == f: return True g = dup_mirror(f, K) if K.is_negative(dup_LC(g, K)): g = dup_neg(g, K) if F == g and dup_cyclotomic_p(g, K): return True G = dup_sqf_part(F, K) if dup_sqr(G, K) == F and dup_cyclotomic_p(G, K): return True return False
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Zassenhaus algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Consider polynomial `f = 2*x**4 - 2`:: >>> from sympy.polys.factortools import dup_zz_factor >>> from sympy.polys.domains import ZZ >>> dup_zz_factor([2, 0, 0, 0, -2], ZZ) (2, [([1, -1], 1), ([1, 1], 1), ([1, 0, 1], 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. **References** 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H, factors = None, [] if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) for h in H: k = 0 while True: q, r = dup_div(f, h, K) if not r: f, k = q, k+1 else: break factors.append((h, k)) return cont, _sort_factors(factors)
def dup_zz_cyclotomic_p(f, K, irreducible=False): """ Efficiently test if ``f`` is a cyclotomic polnomial. **Examples** >>> from sympy.polys.factortools import dup_zz_cyclotomic_p >>> from sympy.polys.domains import ZZ >>> f = [1, 0, 1, 0, 0, 0,-1, 0, 1, 0,-1, 0, 0, 0, 1, 0, 1] >>> dup_zz_cyclotomic_p(f, ZZ) False >>> g = [1, 0, 1, 0, 0, 0,-1, 0,-1, 0,-1, 0, 0, 0, 1, 0, 1] >>> dup_zz_cyclotomic_p(g, ZZ) True """ if K.is_QQ: try: K0, K = K, K.get_ring() f = dup_convert(f, K0, K) except CoercionFailed: return False elif not K.is_ZZ: return False lc = dup_LC(f, K) tc = dup_TC(f, K) if lc != 1 or (tc != -1 and tc != 1): return False if not irreducible: coeff, factors = dup_factor_list(f, K) if coeff != K.one or factors != [(f, 1)]: return False n = dup_degree(f) g, h = [], [] for i in xrange(n, -1, -2): g.insert(0, f[i]) for i in xrange(n-1, -1, -2): h.insert(0, f[i]) g = dup_sqr(dup_strip(g), K) h = dup_sqr(dup_strip(h), K) F = dup_sub(g, dup_lshift(h, 1, K), K) if K.is_negative(dup_LC(F, K)): F = dup_neg(F, K) if F == f: return True g = dup_mirror(f, K) if K.is_negative(dup_LC(g, K)): g = dup_neg(g, K) if F == g and dup_zz_cyclotomic_p(g, K): return True G = dup_sqf_part(F, K) if dup_sqr(G, K) == F and dup_zz_cyclotomic_p(G, K): return True return False
def test_dup_isolate_real_roots(): assert dup_isolate_real_roots([], ZZ) == [] assert dup_isolate_real_roots([3], ZZ) == [] assert dup_isolate_real_roots([5, 0], ZZ) == [((QQ(0), QQ(0)), 1)] assert dup_isolate_real_roots([7, 0, 0, 0, 0], ZZ) == [((QQ(0), QQ(0)), 4)] assert dup_isolate_real_roots([1, 1, 0], ZZ) == [((-QQ(1), -QQ(1)), 1), ((QQ(0), QQ(0)), 1)] assert dup_isolate_real_roots([1, -1, 0], ZZ) == [((QQ(0), QQ(0)), 1), ((QQ(1), QQ(1)), 1)] assert dup_isolate_real_roots([1, 0, 0, 1, 1], ZZ) == [] I = [((-QQ(2), -QQ(1)), 1), ((QQ(1), QQ(2)), 1)] assert dup_isolate_real_roots([1, 0, -2], ZZ) == I assert dup_isolate_real_roots([-1, 0, 2], ZZ) == I f = [ 16, -96, 24, 936, -1599, -2880, 9196, 552, -21831, 13968, 21690, -26784, -2916, 15552, -5832 ] g = dup_sqf_part(f, ZZ) assert dup_isolate_real_roots(f, ZZ) == \ [((-QQ(2), -QQ(3,2)), 2), ((-QQ(3,2), -QQ(1,1)), 3), (( QQ(1), QQ(3,2)), 3), (( QQ(3,2), QQ(3,2)), 4), ((QQ(5,3), QQ(2)), 2)] assert dup_isolate_real_roots_sqf(g, ZZ) == \ [(-QQ(2), -QQ(3,2)), (-QQ(3,2), -QQ(1,1)), ( QQ(1), QQ(3,2)), ( QQ(3,2), QQ(3,2)), (QQ(3,2), QQ(2))] assert dup_isolate_real_roots(g, ZZ) == \ [((-QQ(2), -QQ(3,2)), 1), ((-QQ(3,2), -QQ(1,1)), 1), (( QQ(1), QQ(3,2)), 1), (( QQ(3,2), QQ(3,2)), 1), ((QQ(3,2), QQ(2)), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=2) == [] assert dup_isolate_real_roots([1, -1], ZZ, sup=0) == [] assert dup_isolate_real_roots([1, -1], ZZ) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=1) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, sup=1) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=1, sup=1) == [((1, 1), 1)] f = [1, 0, -4, 0, 4] assert dup_isolate_real_roots(f, ZZ, inf=QQ(7, 4)) == [] assert dup_isolate_real_roots(f, ZZ, inf=QQ(7, 5)) == [((QQ(7, 5), QQ(3, 2)), 2)] assert dup_isolate_real_roots(f, ZZ, sup=QQ(7, 5)) == [((-2, -1), 2)] assert dup_isolate_real_roots(f, ZZ, sup=QQ(7, 4)) == [((-2, -1), 2), ((1, QQ(3, 2)), 2)] assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7, 4)) == [] assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7, 5)) == [((-QQ(3, 2), -QQ(7, 5)), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7, 5)) == [((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7, 4)) == [((-QQ(3, 2), -1), 2), ((1, 2), 2)] I = [((-2, -1), 2), ((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-2) == I assert dup_isolate_real_roots(f, ZZ, sup=+2) == I assert dup_isolate_real_roots(f, ZZ, inf=-2, sup=2) == I f = [1, -3, -1, 11, -8, -8, 12, -4, 0, 0, 0, 0] assert dup_isolate_real_roots(f, ZZ, basis=False) == \ [((-2, -1), 2), ((0, 0), 4), ((1, 1), 3), ((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, basis=True) == \ [((-2, -1), 2, [1, 0, -2]), ((0, 0), 4, [1, 0]), ((1, 1), 3, [1, -1]), ((1, 2), 2, [1, 0, -2])] raises(DomainError, "dup_isolate_real_roots([EX(1), EX(2)], EX)")
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Zassenhaus algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Consider polynomial `f = 2*x**4 - 2`:: >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_zz_factor(2*x**4 - 2) (2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== 1. [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H = None if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) factors = dup_trial_division(f, H, K) return cont, factors
def dup_zz_factor(f, K): """ Factor (non square-free) polynomials in `Z[x]`. Given a univariate polynomial `f` in `Z[x]` computes its complete factorization `f_1, ..., f_n` into irreducibles over integers:: f = content(f) f_1**k_1 ... f_n**k_n The factorization is computed by reducing the input polynomial into a primitive square-free polynomial and factoring it using Zassenhaus algorithm. Trial division is used to recover the multiplicities of factors. The result is returned as a tuple consisting of:: (content(f), [(f_1, k_1), ..., (f_n, k_n)) Examples ======== Consider the polynomial `f = 2*x**4 - 2`:: >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_zz_factor(2*x**4 - 2) (2, [(x - 1, 1), (x + 1, 1), (x**2 + 1, 1)]) In result we got the following factorization:: f = 2 (x - 1) (x + 1) (x**2 + 1) Note that this is a complete factorization over integers, however over Gaussian integers we can factor the last term. By default, polynomials `x**n - 1` and `x**n + 1` are factored using cyclotomic decomposition to speedup computations. To disable this behaviour set cyclotomic=False. References ========== .. [1] [Gathen99]_ """ cont, g = dup_primitive(f, K) n = dup_degree(g) if dup_LC(g, K) < 0: cont, g = -cont, dup_neg(g, K) if n <= 0: return cont, [] elif n == 1: return cont, [(g, 1)] if query('USE_IRREDUCIBLE_IN_FACTOR'): if dup_zz_irreducible_p(g, K): return cont, [(g, 1)] g = dup_sqf_part(g, K) H = None if query('USE_CYCLOTOMIC_FACTOR'): H = dup_zz_cyclotomic_factor(g, K) if H is None: H = dup_zz_zassenhaus(g, K) factors = dup_trial_division(f, H, K) return cont, factors
def test_dup_isolate_real_roots(): assert dup_isolate_real_roots([], ZZ) == [] assert dup_isolate_real_roots([3], ZZ) == [] assert dup_isolate_real_roots([5,0], ZZ) == [((QQ(0), QQ(0)), 1)] assert dup_isolate_real_roots([7,0,0,0,0], ZZ) == [((QQ(0), QQ(0)), 4)] assert dup_isolate_real_roots([1, 1,0], ZZ) == [((-QQ(1), -QQ(1)), 1), ((QQ(0), QQ(0)), 1)] assert dup_isolate_real_roots([1,-1,0], ZZ) == [(( QQ(0), QQ(0)), 1), ((QQ(1), QQ(1)), 1)] assert dup_isolate_real_roots([1,0,0,1,1], ZZ) == [] I = [((-QQ(2), -QQ(1)), 1), ((QQ(1), QQ(2)), 1)] assert dup_isolate_real_roots([1,0,-2], ZZ) == I assert dup_isolate_real_roots([-1,0,2], ZZ) == I f = [16,-96,24,936,-1599,-2880,9196,552,-21831,13968,21690,-26784,-2916,15552,-5832] g = dup_sqf_part(f, ZZ) assert dup_isolate_real_roots(f, ZZ) == \ [((-QQ(2), -QQ(3,2)), 2), ((-QQ(3,2), -QQ(1,1)), 3), (( QQ(1), QQ(3,2)), 3), (( QQ(3,2), QQ(3,2)), 4), ((QQ(5,3), QQ(2)), 2)] assert dup_isolate_real_roots_sqf(g, ZZ) == \ [(-QQ(2), -QQ(3,2)), (-QQ(3,2), -QQ(1,1)), ( QQ(1), QQ(3,2)), ( QQ(3,2), QQ(3,2)), (QQ(3,2), QQ(2))] assert dup_isolate_real_roots(g, ZZ) == \ [((-QQ(2), -QQ(3,2)), 1), ((-QQ(3,2), -QQ(1,1)), 1), (( QQ(1), QQ(3,2)), 1), (( QQ(3,2), QQ(3,2)), 1), ((QQ(3,2), QQ(2)), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=2) == [] assert dup_isolate_real_roots([1, -1], ZZ, sup=0) == [] assert dup_isolate_real_roots([1, -1], ZZ) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=1) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, sup=1) == [((1, 1), 1)] assert dup_isolate_real_roots([1, -1], ZZ, inf=1, sup=1) == [((1, 1), 1)] f = [1, 0, -4, 0, 4] assert dup_isolate_real_roots(f, ZZ, inf=QQ(7,4)) == [] assert dup_isolate_real_roots(f, ZZ, inf=QQ(7,5)) == [((QQ(7,5), QQ(3,2)), 2)] assert dup_isolate_real_roots(f, ZZ, sup=QQ(7,5)) == [((-2, -1), 2)] assert dup_isolate_real_roots(f, ZZ, sup=QQ(7,4)) == [((-2, -1), 2), ((1, QQ(3,2)), 2)] assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7,4)) == [] assert dup_isolate_real_roots(f, ZZ, sup=-QQ(7,5)) == [((-QQ(3,2), -QQ(7,5)), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7,5)) == [((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-QQ(7,4)) == [((-QQ(3,2), -1), 2), ((1, 2), 2)] I = [((-2, -1), 2), ((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, inf=-2) == I assert dup_isolate_real_roots(f, ZZ, sup=+2) == I assert dup_isolate_real_roots(f, ZZ, inf=-2, sup=2) == I f = [1, -3, -1, 11, -8, -8, 12, -4, 0, 0, 0, 0] assert dup_isolate_real_roots(f, ZZ, basis=False) == \ [((-2, -1), 2), ((0, 0), 4), ((1, 1), 3), ((1, 2), 2)] assert dup_isolate_real_roots(f, ZZ, basis=True) == \ [((-2, -1), 2, [1, 0, -2]), ((0, 0), 4, [1, 0]), ((1, 1), 3, [1, -1]), ((1, 2), 2, [1, 0, -2])] raises(DomainError, "dup_isolate_real_roots([EX(1), EX(2)], EX)")
def test_dup_sqf(): assert dup_sqf_part([], ZZ) == [] assert dup_sqf_p([], ZZ) == True assert dup_sqf_part([7], ZZ) == [1] assert dup_sqf_p([7], ZZ) == True assert dup_sqf_part([2,2], ZZ) == [1,1] assert dup_sqf_p([2,2], ZZ) == True assert dup_sqf_part([1,0,1,1], ZZ) == [1,0,1,1] assert dup_sqf_p([1,0,1,1], ZZ) == True assert dup_sqf_part([-1,0,1,1], ZZ) == [1,0,-1,-1] assert dup_sqf_p([-1,0,1,1], ZZ) == True assert dup_sqf_part([2,3,0,0], ZZ) == [2,3,0] assert dup_sqf_p([2,3,0,0], ZZ) == False assert dup_sqf_part([-2,3,0,0], ZZ) == [2,-3,0] assert dup_sqf_p([-2,3,0,0], ZZ) == False assert dup_sqf_list([], ZZ) == (0, []) assert dup_sqf_list([1], ZZ) == (1, []) assert dup_sqf_list([1,0], ZZ) == (1, [([1,0], 1)]) assert dup_sqf_list([2,0,0], ZZ) == (2, [([1,0], 2)]) assert dup_sqf_list([3,0,0,0], ZZ) == (3, [([1,0], 3)]) assert dup_sqf_list([ZZ(2),ZZ(4),ZZ(2)], ZZ) == \ (ZZ(2), [([ZZ(1),ZZ(1)], 2)]) assert dup_sqf_list([QQ(2),QQ(4),QQ(2)], QQ) == \ (QQ(2), [([QQ(1),QQ(1)], 2)]) assert dup_sqf_list([-1,1,0,0,1,-1], ZZ) == \ (-1, [([1,1,1,1], 1), ([1,-1], 2)]) assert dup_sqf_list([1,0,6,0,12,0,8,0,0], ZZ) == \ (1, [([1,0], 2), ([1,0,2], 3)]) K = FF(2) f = map(K, [1,0,1]) assert dup_sqf_list(f, K) == \ (K(1), [([K(1),K(1)], 2)]) K = FF(3) f = map(K, [1,0,0,2,0,0,2,0,0,1,0]) assert dup_sqf_list(f, K) == \ (K(1), [([K(1), K(0)], 1), ([K(1), K(1)], 3), ([K(1), K(2)], 6)]) f = [1,0,0,1] g = map(K, f) assert dup_sqf_part(f, ZZ) == f assert dup_sqf_part(g, K) == [K(1), K(1)] assert dup_sqf_p(f, ZZ) == True assert dup_sqf_p(g, K) == False A = [[1],[],[-3],[],[6]] D = [[1],[],[-5],[],[5],[],[4]] f, g = D, dmp_sub(A, dmp_mul(dmp_diff(D, 1, 1, ZZ), [[1,0]], 1, ZZ), 1, ZZ) res = dmp_resultant(f, g, 1, ZZ) assert dup_sqf_list(res, ZZ) == (45796, [([4,0,1], 3)]) assert dup_sqf_list_include([DMP([1, 0, 0, 0], ZZ), DMP([], ZZ), DMP([], ZZ)], ZZ[x]) == \ [([DMP([1, 0, 0, 0], ZZ)], 1), ([DMP([1], ZZ), DMP([], ZZ)], 2)]