我目前正在尝试编写自己的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")
答案 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代码不那么优雅,但速度提高了一个数量级。