def check(self, f, force_prime=None):
        # try for prime divisors of constant term (might add leading term later too)
        const_coeff = abs(f.TC())
        if const_coeff == 0:
            return REDUCIBLE, None

        if force_prime is not None:
            if const_coeff % force_prime != 0:
                return UNKNOWN, None
            primes = [force_prime]
        else:
            primes = sympy.ntheory.factorint(const_coeff)

        satisfies = []
        for p in primes:
            # calculate points for given prime p for all coeffs
            points = []
            for exp, coeff in poly_non_zero_exps(f):
                if coeff != 0:
                    coeff_factors = sympy.ntheory.factorint(coeff)
                    padic = coeff_factors[p] if p in coeff_factors else 0
                    points.append((exp, padic))

            # if this can be of any use, length of line between end points must not cross any integers
            first = points[0]
            last = points[-1]
            x_diff = abs(first[0] - last[0])
            y_diff = abs(first[1] - last[1])
            if sympy.gcd(x_diff, y_diff) != 1:
                continue

            # now just check if all the other points are above this line
            x1 = first[0]
            y1 = first[1]
            x2 = last[0]
            y2 = last[1]

            above = True
            for i in range(1, len(points) - 1):
                x, y = points[i]
                if (y - y1) * (x2 - x1) <= (x - x1) * (y2 - y1):
                    above = False
                    break
            if not above:
                continue

            satisfies.append(p)
        if satisfies:
            return IRREDUCIBLE, {"p": satisfies}
        return UNKNOWN, None
Ejemplo n.º 2
0
    def check(self, f):
        # http://cms.dm.uba.ar/academico/materias/2docuat2011/teoria_de_numeros/Irreducible.pdf
        # Theorem 1
        h = 0
        for exp, coeff in poly_non_zero_exps(f):
            if exp != f.degree():
                h = max(h, abs(coeff / f.LC()))

        nmin = int(math.ceil(h + 2))
        for n in range(nmin, nmin + 5):
            val = f.eval(n)
            if sympy.isprime(val) and (not self.max_p or val < self.max_p):
                return IRREDUCIBLE, {'n': n, 'p': val}
        return UNKNOWN, None
Ejemplo n.º 3
0
 def check(self, f):
     const_coeff = f.TC()
     if const_coeff == 0:
         return REDUCIBLE, None
     lead_coeff = f.LC()
     if lead_coeff != 1:
         return UNKNOWN, None
     a_nm1 = abs(get_coeff(f, f.degree() - 1))
     s = 1
     for exp, coeff in poly_non_zero_exps(f):
         if exp < f.degree() - 1:
             s += abs(coeff)
     if a_nm1 > s:
         return IRREDUCIBLE, None
     return UNKNOWN, None
Ejemplo n.º 4
0
    def check(self, f):
        # first we need to ensure coefficients are non-negative
        max_coeff = 0
        for exp, coeff in poly_non_zero_exps(f):
            if coeff < 0:
                return UNKNOWN, None
            max_coeff = max(max_coeff, coeff)

        check_range = 30
        for base in range(max_coeff + 1, max_coeff + 1 + check_range):
            val = f.subs(VAR_X, base)
            if sympy.isprime(val) and (not self.max_p or val < self.max_p):
                return IRREDUCIBLE, {"base": base, "p": val}

        return UNKNOWN, None
Ejemplo n.º 5
0
    def check(self, f):
        # Polynomials - Prasolov - Theorem 2.2.7 ([Os1]) part b)
        lead_coeff = f.LC()
        if lead_coeff != 1:
            return UNKNOWN, None

        const_coeff = abs(f.TC())
        if not sympy.isprime(const_coeff):
            return UNKNOWN, None

        if self.max_p and const_coeff >= self.max_p:
            return UNKNOWN, None

        s = 0
        for exp, coeff in poly_non_zero_exps(f):
            if exp != f.degree() and exp != 0:
                s += abs(coeff)

        if const_coeff < 1 + s:
            return UNKNOWN, None

        import mpmath

        # check if there are roots inside as well as outside of unit circle
        try:
            all = mpmath.polyroots(f.all_coeffs(), maxsteps=100)
            inside_unit_circle = 0
            outside_unit_circle = 0
            on_unit_circle = 0
            for root in all:
                root_size = abs(root)
                if root_size == 1:
                    on_unit_circle += 1
                elif root_size < 1:
                    inside_unit_circle += 1
                else:
                    outside_unit_circle += 1

            if on_unit_circle == 0:
                return IRREDUCIBLE, {'s': const_coeff,
                                                 "on": on_unit_circle}
        except mpmath.libmp.libhyper.NoConvergence:
            # could not get complex roots, too bad
            pass

        return UNKNOWN, None
Ejemplo n.º 6
0
    def check(self, f):
        # Polynomials - Prasolov - Theorem 2.2.7 ([Os1]) part a)
        lead_coeff = f.LC()
        if lead_coeff != 1:
            return UNKNOWN, None

        const_coeff = abs(f.TC())
        if not sympy.isprime(const_coeff):
            return UNKNOWN, None

        if self.max_p and const_coeff >= self.max_p:
            return UNKNOWN, None

        s = 0
        for exp, coeff in poly_non_zero_exps(f):
            if exp != f.degree() and exp != 0:
                s += abs(coeff)

        if const_coeff > 1 + s:
            return IRREDUCIBLE, {'s': const_coeff}
        return UNKNOWN, None
    def check(self, f):
        # see https://www.lehigh.edu/~shw2/preprints/eisenstein.pdf,
        # and https://math.stackexchange.com/questions/3589657/prove-polynomial-is-irreducible/3590300#3590300
        const_coeff = f.TC()
        if const_coeff == 0:
            return REDUCIBLE, None
        linear_coeff = get_coeff(f, 1)
        if linear_coeff == 0:
            return UNKNOWN, None
        primes = sympy.ntheory.factorint(linear_coeff)
        for p in primes:
            power = primes[p]
            if power == 1:
                # good candidate, it must not divide leading term
                lead_coeff = f.LC()
                if lead_coeff % p == 0:
                    # bad luck
                    continue
                # it must divide or other terms
                for exp, coeff in poly_non_zero_exps(f):
                    if exp != f.degree():
                        if coeff % p != 0:
                            # bad luck...
                            return UNKNOWN, None

                # finally the polynomial must not have rational roots
                numerators = sympy.ntheory.factorint(const_coeff)
                denominators = sympy.ntheory.factorint(lead_coeff)
                for num in numerators:
                    for denom in denominators:
                        for sign in (-1, 1):
                            if f.eval(sympy.Rational(sign * num, denom)) == 0:
                                # rational root...
                                return UNKNOWN, None

                return IRREDUCIBLE, {"p": p}
        return UNKNOWN, None