我如何检查2个多项式是否是全等模(h(x),n)?

时间:2018-03-13 16:32:31

标签: python primes sympy

我目前正在尝试编写自己的AKS算法实现。可以看到伪代码(直接来自论文' PRIMES在P'中)here

我正在努力解决的部分是第5行if语句中的代码。这需要我们检查是否

(x + a)^ n = x ^ n + a(mod x ^ r - 1,n)

有谁知道我怎么做(在python中)?我相信这种一致性相当于说存在多项式q(x)和r(x)这样

f(x)= g(x)+(x ^ r - 1)* q(x)+ n * r(x)

虽然我不确定这一点。

我试图使用python复制这个if语句,并使用以下代码复制sympy包

if(sym.div(sym.div(mod_zero, x**r - 1)[1], n)[1] == 0):
     print("Congruent")

1 个答案:

答案 0 :(得分:1)

如果g被理解为零,则您的解释f(x) = g(x) + (x^r - 1) * q(x) + n * r(x)不正确,并且q和r具有整数系数。但这实际上是两个步骤:将余数的多项式除以(x^r - 1),然后将mod n应用于系数。

在SymPy术语中,比较是

trunc(rem((x + a)**n -(x**n + a), x**r - 1), n) == 0

其中rem找到多项式余数,trunc取系数mod n。例子:

x = poly("x")  
n = 35
r = 29
a = 7
trunc(rem((x + a)**n - (x**n + a), x**r - 1), n)

输出Poly(14*x**25 + 7*x**10 - 7*x**5 + 14*x - 14, x, domain='ZZ')

同时,将35替换为31,我们得到Poly(0, x, domain='ZZ'),它通过== 0测试。

加速比

优化的一种方法是在trunc之前应用rem,以便在除法之前使系数更小。

trunc(rem(trunc((x + a)**n - (x**n + a), n), x**r - 1), n)

这有点帮助。但是通过使用“galoistools”模块中的低级例程可以实现更大幅度的加速。它们以系数作为列表运行,如下所示:[1, a]x + a

from sympy.polys.galoistools import gf_lshift, gf_sub, gf_add_ground, gf_pow, gf_rem 
n = 35
r = 29
a = 7
f1 = gf_pow([1, a], n, n, ZZ) # (x + a)**n
f2 = gf_add_ground(gf_lshift([1], n, ZZ), a, n, ZZ) # x**n + a
g = gf_add_ground(gf_lshift([1], r, ZZ), -1, n, ZZ) # x**r - 1
print(gf_rem(gf_sub(f1, f2, n, ZZ), g, n, ZZ))

打印[14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 28, 0, 0, 0, 14, 21],它与之前的结果一致(模35)。

此表示中的零多项式为[]:因此,测试可以像

一样简单
if gf_rem(gf_sub(f1, f2, n, ZZ), g, n, ZZ):
    print("Composite")    # [] is falsy, other lists are truthy

galoistools代码不那么优雅,但速度提高了一个数量级。