python - 更改 SymPy 多项式中以 p 为模的系数

标签 python python-3.x sympy polynomials

我这个学期在研究生院学习了密码学类(class),我们讨论的主题之一是 NTRU。我正在尝试用纯 Python 编写这个代码,纯粹是作为一种爱好。当我试图找到多项式的逆模 p(在本例中 p = 3)时,SymPy 总是返回负系数,而我想要严格的正系数。这是我的代码。我会解释我的意思。

import sympy as sym
from sympy import GF

def make_poly(N,coeffs):
    """Create a polynomial in x."""
    x = sym.Symbol('x')
    coeffs = list(reversed(coeffs))
    y = 0
    for i in range(N):
        y += (x**i)*coeffs[i]
    y = sym.poly(y)
    return y

N = 7
p = 3
q = 41
f = [1,0,-1,1,1,0,-1]

f_poly = make_poly(N,f)

x = sym.Symbol('x')

Fp = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(p))
Fq = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(q))

print('\nf =',f_poly)
print('\nFp =',Fp)
print('\nFq =',Fq)

在此代码中,f_poly 是次数最多为 6 的多项式(次数最多为 N-1),其系数来自列表 f(f中的第一项是x最高幂的系数,继续按降序排列)。

现在,我想在卷积多项式环中找到f_poly的逆多项式Rp = (Z/pZ)[x]/(x^N - 1)(Z/pZ)[x](与 q 类似)。底部打印语句的输出是:

f = Poly(x**6 - x**4 + x**3 + x**2 - 1, x, domain='ZZ')
Fp = Poly(x**6 - x**5 + x**3 + x**2 + x + 1, x, modulus=3)
Fq = Poly(8*x**6 - 15*x**5 - 10*x**4 - 20*x**3 - x**2 + 2*x - 4, x, modulus=41)

这些多项式的模数是正确的,但我希望到处都有正系数,因为稍后在算法中涉及一些中心提升,所以我需要有正系数。结果应该是

Fp = x^6 + 2x^5 + x^3 + x^2 + x + 1
Fq = 8x^6 + 26x^5 + 31x^4 + 21x^3 + 40x^2 + 2x + 37

我得到的答案在模数方面是正确的,但我认为 SymPy 的 invert 正在将一些系数更改为负变体,而不是留在模内。

有什么方法可以更新这个多项式的系数,使其模数只有正系数,或者这只是 SymPy 函数的一个产物?我想保留 SymPy Poly 格式,以便稍后可以使用它的一些嵌入函数。任何见解将不胜感激!

最佳答案

这似乎取决于 GF 中有限域对象的实现方式“包裹”给定模数周围的整数。默认行为是 symmetric ,这意味着任何整数 x其中x % modulo <= modulo//2映射到x % modulo ,否则映射到 (x % modulo) - modulo 。所以GF(10)(5) == 5 ,而GF(10)(6) == -4 。您可以制作GF始终通过传递 symmetric=False 映射到正数论据:

import sympy as sym
from sympy import GF

def make_poly(N, coeffs):
    """Create a polynomial in x."""
    x = sym.Symbol('x')
    coeffs = list(reversed(coeffs))
    y = 0
    for i in range(N):
        y += (x**i)*coeffs[i]
    y = sym.poly(y)
    return y

N = 7
p = 3
q = 41
f = [1,0,-1,1,1,0,-1]

f_poly = make_poly(N,f)

x = sym.Symbol('x')

Fp = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(p, symmetric=False))
Fq = sym.polys.polytools.invert(f_poly,x**N-1,domain=GF(q, symmetric=False))

print('\nf =',f_poly)
print('\nFp =',Fp)
print('\nFq =',Fq)

现在您将得到您想要的多项式。 print(...) 的输出示例末尾的语句应如下所示:

f = Poly(x**6 - x**4 + x**3 + x**2 - 1, x, domain='ZZ')
Fp = Poly(x**6 + 2*x**5 + x**3 + x**2 + x + 1, x, modulus=3)
Fq = Poly(8*x**6 + 26*x**5 + 31*x**4 + 21*x**3 + 40*x**2 + 2*x + 37, x, modulus=41)

主要是作为我自己引用的注释,以下是您如何获得 Fp使用数学:

Fp = PolynomialMod[Algebra`PolynomialPowerMod`PolynomialPowerMod[x^6 - x^4 + x^3 + x^2 - 1, -1, x, x^7 - 1], 3]

输出:

1 + x + x^2 + x^3 + 2 x^5 + x^6

关于python - 更改 SymPy 多项式中以 p 为模的系数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53754480/

相关文章:

python-3.x - 取消酸洗错误 : invalid load key, '3'

python - 如何在python中调试导致后续异常的堆栈跟踪?

python-2.7 - 如何限制包含符号的 sympy FiniteSet

python - 是否可以显示 SymPy 在 `simplify()` 期间尝试的所有函数?

python-3.x - 如何在 selenium、python 3 中重新定位/禁用 GeckoDriver 的日志文件?

python - 在 SymPy 中明智地使用常量

python - 根据列表替换值,但将替换值保留在单独的列中

python - 从 Pillow 获取调试输出

python - vb.net 和 python 之间的 hmacsha1 输出十六进制字符串不同

python - Jupyter 通过 LaTeX 下载为 PDF 在空白处切断代码