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



我目前正在尝试编写自己的AKS算法实现。这个伪代码(直接取自论文"PRIMES is in P")可以在这里看到。

我正在努力解决的部分是第 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 和 sympy 包复制此if语句

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

如果 g 被理解为零,并且 q 和 r 具有整数系数,那么您f(x) = g(x) + (x^r - 1) * q(x) + n * r(x)解释并没有错。但这实际上是两个步骤:将多项式除法的余数除以(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测试。

加速

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

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代码不那么优雅,但快了一个数量级。

最新更新