Beispiel #1
0
from irreduc_types import IRREDUCIBLE, UNKNOWN


class MurtyCriterion:
    def __init__(self, max_p=None):
        self.name = "Murty's irreducibility criterion"
        self.max_p = max_p

    def name(self):
        return self.name

    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


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], MurtyCriterion())
Beispiel #2
0
        # 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


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], OsadaCriterion())
    check_common(poly, sys.argv[1], OsadaCriterionNonSharp())
            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


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], EisensteinCriterionV2())
Beispiel #4
0
    def __init__(self):
        self.name = "Schur's irreducibility criterion"

    def name(self):
        return self.name

    def check(self, f):
        # http://www.math.uconn.edu/~kconrad/blurbs/gradnumthy/schurtheorem.pdf
        # Theorem 1, multiplied to get Z[x]
        n = f.degree()
        lead_coeff = f.LC()
        if abs(lead_coeff) != 1:
            return UNKNOWN, None
        fact = n
        for exp in reversed(range(1, n)):
            coeff = get_coeff(f, exp)
            if coeff % fact != 0:
                return UNKNOWN, None
            fact *= exp
        # fact now contains n!
        const_coeff = f.TC()
        if const_coeff != fact:
            return UNKNOWN, None

        return IRREDUCIBLE, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], SchurCriterion())
Beispiel #5
0
    def __init__(self):
        self.name = "Perron's (non-sharp) irreducibility criterion"

    def name(self):
        return self.name

    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:
            f1 = f.subs(VAR_X, 1)
            f2 = f.subs(VAR_X, -1)
            if f1 != 0 and f2 != 0:
                return IRREDUCIBLE, None
        return UNKNOWN, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], PerronCriterion())
    check_common(poly, sys.argv[1], PerronNonSharpCriterion())
Beispiel #6
0
        OsadaCriterion(max_p=max_p),
        OsadaCriterionNonSharp(max_p=max_p),
        PolyaCriterion(),
        LevitCriterion(),
        SchurCriterion(),
        BonciocatCriterion(),
        GaloisFieldsCriterion(),
        ComplexRootsCriterion2(),
        ComplexRootsCriterion(max_p=max_p),
        ComplexRootsCriterion3(max_p=max_p),
    ]

    tryWithSubs = []
    for criterion in criteria:
        poly=polys[0]
        if not check_common(poly[0], sub_name(poly[1], poly[2], poly[3]), criterion):
            tryWithSubs.append(criterion)

    print('')
    print('Trying failed criteria with substitutions')

    if subs:
        for criterion in tryWithSubs:
            # original poly does not satisfy this criterion directly, now try substitutions
            #print("No result for '%s', trying substitutions" % criterion.name)
            for poly in polys:
                check_common(poly[0], sub_name(poly[1], poly[2], poly[3]), criterion)
                if isinstance(criterion, GaloisFieldsCriterion):  # dirty hack
                        break

Beispiel #7
0
from irreduc_utils import create_polynomial, poly_all_exps, check_common
from irreduc_types import IRREDUCIBLE, UNKNOWN


class BrauerCriterion:
    def __init__(self):
        self.name = "Brauer's irreducibility criterion"

    def name(self):
        return self.name

    def check(self, f):
        # Polynomials - Prasolov - Theorem 2.2.6 ([Br])
        last = 0
        lead_coeff = f.LC()
        if abs(lead_coeff) != 1:
            return UNKNOWN, None
        for exp, coeff in poly_all_exps(f):
            if exp != f.degree():
                coeff = -coeff
                coeff *= lead_coeff # in case the original differs by multiple of -1
                if coeff < last or coeff <= 0:
                    return UNKNOWN, None
                last = coeff
        return IRREDUCIBLE, {"sign": lead_coeff}


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], BrauerCriterion())
Beispiel #8
0
                for n in range(0, m + 1):
                    for s in S:
                        new = s + n * xs[l - 1]
                        if new > 0 and (2 * new <= f.degree()):
                            tmp.add(new)

                S = S.union(tmp)

            S.remove(0)

            # we are interested only in those sets that are not just full set of {1,2,...,n/2}
            if S != trivial:
                Sps['S%i' % prime] = S

        if not Sps:
            return UNKNOWN, None

        # final part, intersection...
        inter = set.intersection(*list(Sps.values()))

        if len(inter) > 0:
            return UNKNOWN, None

        # we have succeeded!
        return IRREDUCIBLE, Sps


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], BonciocatCriterion())
        # all possible degrees of irreducible factors in Z[x]
        sums = {}
        trivial = set(range(1, f.degree() + 1))
        for p in irreduc_factors_degrees:
            sums_p = subsets_sums(irreduc_factors_degrees[p])
            if sums_p != trivial:
                sums[p] = sums_p

        if not sums:
            return UNKNOWN, None

        # then if intersection of these is empty or {deg(f)}, then lesser degree factor is impossible
        # thus polynomial will have to be irreducible
        inter = set.intersection(*list(sums.values()))
        if f.degree() in inter:
            inter.remove(f.degree())

        if not inter:
            # intersection is empty, imcompatible factors!
            res["degrees"] = sums

        if res:
            return IRREDUCIBLE, res

        return UNKNOWN, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], GaloisFieldsCriterion())
Beispiel #10
0
            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 (inside_unit_circle + on_unit_circle == 0):
                return IRREDUCIBLE, {
                    "inside/on": inside_unit_circle + on_unit_circle,
                    "outside": outside_unit_circle,
                    "p": p
                }
        except Exception as e:
            # could not get complex roots, too bad
            pass

        return UNKNOWN, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], ComplexRootsCriterion())
    check_common(poly, sys.argv[1], ComplexRootsCriterion2())
    check_common(poly, sys.argv[1], ComplexRootsCriterion3())
Beispiel #11
0

class PolyaCriterion:
    def __init__(self):
        self.name = "Polya's irreducibility criterion"

    def name(self):
        return self.name

    def check(self, f):
        # Polynomials by Prasolov, Theorem 2.2.8 (Polya)
        n = f.degree()
        m = (n + 1) // 2
        suitable = []
        rhs = sympy.factorial(m) / (2 ** m)
        for a in range(-20, 20 + 1):
            val = abs(f.eval(a))
            if val == 0:
                # clearly this is reducible...
                return REDUCIBLE, None
            if val < rhs:
                suitable.append(a)
        if len(suitable) >= n:
            return IRREDUCIBLE, {'a': suitable}
        return UNKNOWN, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], PolyaCriterion())

class CohnCriterion:
    def __init__(self, max_p=None):
        self.name = "Cohn's irreducibility criterion"
        self.max_p = max_p

    def name(self):
        return self.name

    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


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], CohnCriterion())
Beispiel #13
0
class LevitCriterion:
    def __init__(self):
        self.name = "Levit's irreducibility criterion"

    def name(self):
        return self.name

    def check(self, f):
        # Levit, Irreducibility of Polynomials with Low Absolute Values, Theorem 2
        n = f.degree()
        N = (n + 1) // 2
        suitable = []

        rhs = RisingFactorial((n//2)/2, N) / (2 ** (N-1))
        for a in range(-20, 20 + 1):
            val = abs(f.eval(a))
            if val == 0:
                # clearly this is reducible...
                return REDUCIBLE, None
            if val < rhs:
                suitable.append(a)
        if len(suitable) >= n:
            return IRREDUCIBLE, {'a': suitable}
        return UNKNOWN, None


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], LevitCriterion())
            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


if __name__ == '__main__':
    poly = create_polynomial(sys.argv[1])
    check_common(poly, sys.argv[1], DumasCriterion())