快速素因子分解模块因子、分解、模块、快速

2023-09-11 02:49:55 作者:等一个旧人

我要寻找一个执行或清除算法获取的的 N 的首要因子在任一蟒蛇,伪code或别的也可读。有几个要求/事实:

的 N 的为1至〜20位数字 没有pre计算的查找表,记忆化是好的,但。 不需要用数学证明(如可以依靠,如果需要的哥德巴赫猜想) 不需要是precise,允许是概率性/确定性,如果需要

我需要一个快速的质因子分解算法,不仅为自己,而是使用在许多其他类似的算法计算欧拉的岛(N)的。

我试图从维基百科和其他算法,但要么我不明白他们(ECM),或者我不能创建的算法(波拉德 - 布伦特)工作实施

我在波拉德 - 布伦特算法很感兴趣,所以任何详细信息/它的实现将是非常好的。

谢谢!

修改

附近有一座小我创建了一个pretty的快速黄金/分解模块搞乱之后。它结合了优化的审判庭算法,波拉德 - 布伦特算法,米勒 - 拉宾检验并以最快的primesieve我发现在互联网上。 GCD是一个普通的欧几里得的GCD实现(二进制欧几里德的GCD是多慢然后定期的)。

赏金

哦喜悦,赏金可以获取!但是,我怎么能赢得它?

找到我的模块中的optimalization或缺陷。 在提供替代/更好的算法/实现。

这是最完整的/建设性的答案得到赏金。

和最后的模块本身:

 导入随机

高清primesbelow(N):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    #输入N> = 6,返回的素数,第2版的列表; = P&其中; N
    修正= N%6' 1
    N = {0:N,1:N-1,2:N + 4,3:N + 3,4:N + 2,5:N + 1} [N%6]
    筛= [真] *(N // 3)
    筛[0] = FALSE
    因为我在范围内(INT(N ** .5)// 3 + 1):
        如果筛[我]:
            K =(3 * I + 1)| 1
            筛[K * K // 3 :: 2 * K] = [假] *((N // 6  - (K * k)的// 6  -  1)// K + 1)
            筛[(K * K + 4 * K  -  2 * K *(我%2))// 3:2 * K] = [虚假] *((N // 6  - (K * K + 4 * K -  2 * K *(ⅰ%2))// 6  -  1)// K + 1)
    返回[2,3] + [(3 * I + 1)| 1对于i在范围(1,N- // 3  - 校正)如果筛[Ⅰ]]

smallprimeset =集(primesbelow(100000))
_smallprimeset = 100000
高清isprime(N,precision = 7):
    #http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
    如果n< 1:
        提高ValueError错误(出界,第一个参数必须是大于0)
    ELIF N'LT; = 3:
        返回N'GT; = 2
    ELIF N%2 == 0:
        返回False
    ELIF N'LT; _smallprimeset:
        在smallprimeset返回否


    D = N  -  1
    S = 0
    而D%2 == 0:
        ð// = 2
        S + 1 =

    对于重复的范围(precision):
        一个= random.randrange(2,N  -  2)
        X = POW(A,D,N)

        如果x == 1或x == N  -  1:继续

        当r在范围(S  -  1):
            X =战俘(X,2,N)
            如果x == 1:返回False
            如果x == N  -  1:突破
        其他:返回False

    返回True

#HTTPS://comeon$c$con.word$p$pss.com/2010/09/18/pollard-rho-brent-integer-factorization/
高清pollard_brent(N):
    如果n%2 == 0:返回2
    如果n%3 == 0:返回3

    Y,C,M = random.randint(1,N-1),random.randint(1,N-1),random.randint(1,N-1)
    克,R,Q = 1,1,1
    一边将== 1:
        X = Y
        因为我在范围(R):
            Y =(POW(Y,2,N)+ C)%N

        K = 0
        而K< r和克== 1:
            YS = Y
            因为我在范围内(分钟(M,R-K)):
                Y =(POW(Y,2,N)+ C)%N
                Q = Q * ABS(X-Y)%N
            G = GCD(Q,N)
            第k + = M
        R * = 2
    如果g = = N:
        而真正的:
            YS =(POW(YS,2,N)+ C)%N
            G = GCD(ABS(X  -  YS),N)
            如果G> 1:
                打破

    返回摹

smallprimes = primesbelow(1000)#似乎较低,但1000 * 1000 = 1000000,因此这将充分因素每个复合<百万
高清primefactors(N,排序= FALSE):
    因素= []

    对检查中smallprimes:
        而N%检查== 0:
            factors.append(检查)
            ñ// =检查
        如果检查> N:突破

    如果n< 2:收益因素

    而N'GT; 1:
        如果isprime(N):
            factors.append(N)
            打破
        系数= pollard_brent(N)#审判庭没有完全的因素,切换到波拉德,布伦特
        factors.extend(primefactors(因子))#改乘因素由波拉德布伦特返回的不一定是主要因素
        ñ// =因素

    如果排序:factors.sort()

    返回因素

高清分解(N):
    因素= {}
    对于P1在primefactors(N):
        尝试:
            因素[P1] + = 1
        除了KeyError异常:
            因素[P1] = 1
    返回因素

totients = {}
高清totient(N):
    如果n == 0:返回1

    尝试:返回totients [N]
    除了KeyError异常:通

    TOT = 1
    对p,实验中分解(n)的.items():
        TOT * =(P  -  1)* P **(EXP  -  1)

    totients [N] = TOT
    返回TOT

高清GCD(A,B):
    如果== B:返回
    而B> 0:A,B = B,A%B
    返回

高清LCM(A,B):
    返回ABS((一个//最大公约数(A,B))* B)
 
FM因子分解机 下

解决方案

波拉德,布伦特在用Python实现:

https://comeon$c$con.word$p$pss.com/2010/09/18/pollard-rho-brent-integer-factorization/

I am looking for an implementation or clear algorithm for getting the prime factorization of N in either python, pseudocode or anything else well-readable. There are a few demands/facts:

N is between 1 and ~20 digits No pre-calculated lookup table, memoization is fine though. Need not to be mathematically proven (e.g. could rely on the Goldbach conjecture if needed) Need not to be precise, is allowed to be probabilistic/deterministic if needed

I need a fast prime factorization algorithm, not only for itself, but for usage in many other algorithms like calculating the Euler phi(n).

I have tried other algorithms from Wikipedia and such but either I couldn't understand them (ECM) or I couldn't create a working implementation from the algorithm (Pollard-Brent).

I am really interested in the Pollard-Brent algorithm, so any more information/implementations on it would be really nice.

Thanks!

EDIT

After messing around a little I have created a pretty fast prime/factorization module. It combines an optimized trial division algorithm, the Pollard-Brent algorithm, a miller-rabin primality test and the fastest primesieve I found on the internet. gcd is a regular Euclid's GCD implementation (binary Euclid's GCD is much slower then the regular one).

Bounty

Oh joy, a bounty can be acquired! But how can I win it?

Find an optimalization or bug in my module. Provide alternative/better algorithms/implementations.

The answer which is the most complete/constructive gets the bounty.

And finally the module itself:

import random

def primesbelow(N):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    #""" Input N>=6, Returns a list of primes, 2 <= p < N """
    correction = N % 6 > 1
    N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
    sieve = [True] * (N // 3)
    sieve[0] = False
    for i in range(int(N ** .5) // 3 + 1):
        if sieve[i]:
            k = (3 * i + 1) | 1
            sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
            sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
    return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]

smallprimeset = set(primesbelow(100000))
_smallprimeset = 100000
def isprime(n, precision=7):
    # http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
    if n < 1:
        raise ValueError("Out of bounds, first argument must be > 0")
    elif n <= 3:
        return n >= 2
    elif n % 2 == 0:
        return False
    elif n < _smallprimeset:
        return n in smallprimeset


    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1

    for repeat in range(precision):
        a = random.randrange(2, n - 2)
        x = pow(a, d, n)

        if x == 1 or x == n - 1: continue

        for r in range(s - 1):
            x = pow(x, 2, n)
            if x == 1: return False
            if x == n - 1: break
        else: return False

    return True

# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
def pollard_brent(n):
    if n % 2 == 0: return 2
    if n % 3 == 0: return 3

    y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)
    g, r, q = 1, 1, 1
    while g == 1:
        x = y
        for i in range(r):
            y = (pow(y, 2, n) + c) % n

        k = 0
        while k < r and g==1:
            ys = y
            for i in range(min(m, r-k)):
                y = (pow(y, 2, n) + c) % n
                q = q * abs(x-y) % n
            g = gcd(q, n)
            k += m
        r *= 2
    if g == n:
        while True:
            ys = (pow(ys, 2, n) + c) % n
            g = gcd(abs(x - ys), n)
            if g > 1:
                break

    return g

smallprimes = primesbelow(1000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
def primefactors(n, sort=False):
    factors = []

    for checker in smallprimes:
        while n % checker == 0:
            factors.append(checker)
            n //= checker
        if checker > n: break

    if n < 2: return factors

    while n > 1:
        if isprime(n):
            factors.append(n)
            break
        factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
        factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
        n //= factor

    if sort: factors.sort()

    return factors

def factorization(n):
    factors = {}
    for p1 in primefactors(n):
        try:
            factors[p1] += 1
        except KeyError:
            factors[p1] = 1
    return factors

totients = {}
def totient(n):
    if n == 0: return 1

    try: return totients[n]
    except KeyError: pass

    tot = 1
    for p, exp in factorization(n).items():
        tot *= (p - 1)  *  p ** (exp - 1)

    totients[n] = tot
    return tot

def gcd(a, b):
    if a == b: return a
    while b > 0: a, b = b, a % b
    return a

def lcm(a, b):
    return abs((a // gcd(a, b)) * b)

解决方案

Pollard-Brent in implemented in Python:

https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/