CLRS中的miller-rabin伪代码是否存在主要的低效率?

时间:2018-01-23 13:53:39

标签: algorithm primes code-analysis pseudocode primality-test

这个问题实际上可能与Miller-Rabin素性测试程序无关;它可能只是简单的分析一些简单的伪代码。

在CLRS(算法导论3ed)的第969页上,介绍了Miller-Rabin的辅助功能:

WITNESS(a, n)
    let t and u be such that t >= 1, u is odd, and n-1 = 2^t u
    x_0 = MODULAR-EXPONENTIATION(a, u, n)
    for i = 1 to t
        x_i = x_{i-1}^2 mod n
        if x_i == 1 and x_{i-1} != 1 and x_{i-1} != n-1
            return TRUE
    if x_t != 1
        return TRUE
    return FALSE

我完全从教科书中复制了上述内容。

现在,只知道MODULAR-EXPONENTIATION返回0到n-1之间的结果,我认为上面的伪代码完全等同于

WITNESS(a, n)
    let t and u be such that t >= 1, u is odd, and n-1 = 2^t u
    x_0 = MODULAR-EXPONENTIATION(a, u, n)
    if x_0 == 1 or x_0 == n-1
        return FALSE
    else
        return TRUE

如果是这样,原始实现可能还有其他问题,因为如果我没弄错,Miller-Rabin见证了 需要某种循环。有人可以提供一个简单的反例来表明我错了吗?

2 个答案:

答案 0 :(得分:1)

对于n为素数,Miller-Rabin primality test被设计为TRUE,因此返回FALSE应仅适用于复合数。让我们用一个Python程序来测试它。

def wrongwitness(a, n):             #implementation of your shortcut
    u = n - 1
    t = 0
    while u % 2 == 0:               #n - 1 = 2^t * u
        u //= 2
        t += 1

    x_0 = pow(a, u, n)              #x0 = a ^ u (mod n), oops, where is t?

    if x_0 == 1 or x_0 == n - 1:
        return False
    else:
        return True

primes = [5, 7, 11, 13, 17, 19, 23, 29, 31]

for p in primes:         
    for a in range(2, p):           #1 < a < p
        if not wrongwitness(a, p):  #witness returned FALSE, though we have a prime number
            print("Found counter example: a = ", a, "and p = ", p )

这为我们的快捷方式实施提供了许多反例,只有a = 2p = 5a = 3p = 7。实际上所有(p - 1, p)元组都是反例。所以没有捷径,你必须按照教科书中的说明测试a^(n-1)的所有平方根。

P.S。:但是有一些方法可以减少你需要执行的计算次数。 Subsets of witnesses已被确定为n,最高为3,317,044,064,679,887,385,961,981。因此对于n&lt; 1,373,653例如足以测试a = 2和a = 3。

答案 1 :(得分:0)

对于本书中的那个,我们有WITNESS(2, 5) == FALSE

对于快捷方式,我们有WITNESS(2, 5) == TRUE,因此快捷方式错误。

顺便说一句,以下替代实现 有效,并且在找到x_i == 1的所有情况下立即更有效地终止。

WITNESS(a, n)
    let t and u be such that t >= 1, u is odd, and n-1 = 2^t u
    x_0 = MODULAR-EXPONENTIATION(a, u, n)
    for i = 1 to t
        x_i = x_{i-1}^2 mod n
        if x_i == 1 
            if x_{i-1} != 1 and x_{i-1} != n-1
                return TRUE
            else
                return FALSE
    return TRUE