SymPy 1.13 中文文档(五十四)

原文:docs.sympy.org/latest/index.html

数域

原文链接:docs.sympy.org/latest/modules/polys/numberfields.html

引言

像代数数论中许多其他计算一样,有理素数的分裂只能用有理方法处理。如果考虑用自动计算设备进行计算,这一事实非常重要。只需知道不可约多项式(f(x)),其零点生成所讨论的域即可。

—Olga Taussky,1953

像数域和代数数这样的概念对我们理解代数数论至关重要,但对于计算机而言,这个主题完全是关于多项式的:在(\mathbb{Q}[x])上通过不可约多项式(f(x) \in \mathbb{Q}[x])降阶。因此,它在 SymPy 的polys模块下找到了自然的归属。

多位作者(如 Taussky、Zimmer、Pohst 和 Zassenhaus,或者 Cohen)以不同的方式阐明了计算代数数论的主要目标,但无论如何,列表都围绕着一定的基本任务集中。作为 SymPy 中numberfields模块的目标,我们可以根据[Cohen93],第 4.9.3 节,列出以下列表。

对于数域(K = \mathbb{Q}(\theta)),其代数整数环标记为(\mathbb{Z}_K),计算:

  1. (\mathbb{Z}_K)的一个整数基底

  2. (\mathbb{Z}_K)中有理素数的分解

  3. 对于理想和元素的(\mathfrak{p})-adic 赋值

  4. (K)的 Galois 封闭的 Galois 群

  5. (K)的一组基本单位

  6. 规则(R(K))

  7. 类数

  8. 类群(Cl(K))的结构

  9. 决定一个给定理想是否为主理想,如果是,则计算一个生成元。

作为基础,并支持我们定义和处理数域和代数数的基本能力,我们也根据[Cohen93],第 4.5 节,设置以下问题。

  1. 给定一个代数数,可以通过根式和有理运算表达,甚至可以作为超越函数的特殊值,确定它在(\mathbb{Q})上的最小多项式。

  2. 子域问题:通过它们的生成元(\alpha)和(\beta)的最小多项式,给定两个数域(\mathbb{Q}(\alpha)),(\mathbb{Q}(\beta)),决定一个数域是否同构于另一个数域的子域,并展示嵌入。

  3. 域成员问题:给定两个代数数(\alpha),(\beta),决定(\alpha \in \mathbb{Q}(\beta))是否成立,如果成立,则写成(\alpha = f(\beta)),其中(f(x) \in \mathbb{Q}[x])。

  4. 原初元问题:给定几个代数数(\alpha_1, \ldots, \alpha_m),计算一个单一的代数数(\theta),使得(\mathbb{Q}(\alpha_1, \ldots, \alpha_m) = \mathbb{Q}(\theta))。

目前,SymPy 仅支持上述任务的子集,如果您有兴趣扩展支持,请贡献!提供所有剩余问题解决方案(以及已解决的问题)的出色来源是 [Cohen93]

在写作时,上述问题的现有解决方案可以在以下位置找到:

任务实现

|

  1. 整数基础
round_two()

|

  1. 素数分解
prime_decomp()

|

  1. (\mathfrak{p})-递值
prime_valuation()

|

  1. Galois 群
galois_group()

|

  1. 寻找最小多项式
minimal_polynomial()

|

  1. 子领域
field_isomorphism()

|

  1. 领域成员
to_number_field()

|

  1. 原始元素
primitive_element()

解决主要问题

整数基础

sympy.polys.numberfields.basis.round_two(T, radicals=None)

Zassenhaus 的“Round 2” 算法。

参数:

T : Poly, AlgebraicField

要么是在 ZZ 或 QQ 上的不可约多项式,定义数域,或者是代表数域本身的 AlgebraicField

根式 : dict, optional

这是任何 (p)-根式(如果计算的话)通过引用返回的一种方式。如果需要,传递一个空字典。如果算法达到计算环 (Z_K) 的 nilradical mod (p) 的点,则该字典中将以 p 为键存储此理想的 (\mathbb{F}_p)-基础。这对于其他算法(如素数分解)可能很有用。

返回:

(ZK, dK),其中:

ZK 是表示最大秩的 Submodule

dK 是字段 (K = \mathbb{Q}[x]/(T(x))) 的判别式。

说明

在 ZZ 或 QQ 上的不可约多项式T上执行 Zassenhaus 的“Round 2”算法。这计算了一个整数基和字段(K = \mathbb{Q}[x]/(T(x)))的判别式。

或者,您可以传递一个AlgebraicField 实例,替代多项式T,在这种情况下算法应用于该字段的原始元的最小多项式。

通常不必直接调用此函数,因为可以访问maximal_order()integral_basis()discriminant()方法的AlgebraicField

示例

通过 AlgebraicField 进行操作:

>>> from sympy import Poly, QQ
>>> from sympy.abc import x
>>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
>>> K = QQ.alg_field_from_poly(T, "theta")
>>> print(K.maximal_order())
Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2
>>> print(K.discriminant())
-503
>>> print(K.integral_basis(fmt='sympy'))
[1, theta, theta/2 + theta**2/2] 

直接调用:

>>> from sympy import Poly
>>> from sympy.abc import x
>>> from sympy.polys.numberfields.basis import round_two
>>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
>>> print(round_two(T))
(Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2, -503) 

在第二轮算法中有时会计算模(p)的零根式,这可能在进一步计算中很有用。传递一个字典在(radicals)下接收这些:

>>> T = Poly(x**3 + 3*x**2 + 5)
>>> rad = {}
>>> ZK, dK = round_two(T, radicals=rad)
>>> print(rad)
{3: Submodule[[-1, 1, 0], [-1, 0, 1]]} 

另见

AlgebraicField.maximal_orderAlgebraicField.integral_basisAlgebraicField.discriminant

参考文献

[R802]

Cohen, H. 计算代数数论课程.

质数分解

sympy.polys.numberfields.primes.prime_decomp(p, T=None, ZK=None, dK=None, radical=None)

计算在一个数域中有理质数p的分解。

参数:

p:int

想要分解的有理质数。

TPoly,可选

定义数域(K)中的单一不可约多项式。注意:TZK至少要提供一个。

ZKSubmodule,可选

如果已知,(K)的最大序。注意:TZK至少要提供一个。

dK:int,可选

如果已知,(K)的判别式。

radicalSubmodule,可选

如果已知,(K)的整数中的模p的零根式。

返回:

PrimeIdeal 实例列表。

解释

通常应通过 AlgebraicFieldprimes_above() 方法访问它。

示例

>>> from sympy import Poly, QQ
>>> from sympy.abc import x, theta
>>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
>>> K = QQ.algebraic_field((T, theta))
>>> print(K.primes_above(2))
[[ (2, x**2 + 1) e=1, f=1 ], [ (2, (x**2 + 3*x + 2)/2) e=1, f=1 ],
 [ (2, (3*x**2 + 3*x)/2) e=1, f=1 ]] 

参考文献

[R803]

Cohen, H. 计算代数数论课程. (见算法 6.2.9.)

class sympy.polys.numberfields.primes.PrimeIdeal(ZK, p, alpha, f, e=None)

一个代数整数环中的素理想。

__init__(ZK, p, alpha, f, e=None)

参数:

ZKSubmodule

此理想所在的最大阶。

p:int

此理想除以的有理素数。

alphaPowerBasisElement

使得理想等于 p*ZK + alpha*ZK

f:int

惯性度。

e:int,None,可选

如果已知分歧指数。 如果为 None,我们将在此计算它。

__add__(other)

转换为 Submodule 并添加到另一个 Submodule 中。

另请参阅

as_submodule

__mul__(other)

转换为 Submodule 并乘以另一个 Submodule 或有理数。

另请参阅

as_submodule

as_submodule()

将此素理想表示为 Submodule

返回:

Submodule

将等于 self.p * self.ZK + self.alpha * self.ZK

解释

PrimeIdeal 类用于捆绑关于素理想的信息,如其惯性度、分歧指数和双生成器表示,以及提供像 valuation()test_factor() 这样有用的方法。

然而,为了能够与其他理想或有理数相加和相乘,首先必须将其转换为一个支持这些操作的 Submodule 类。

在许多情况下,用户不需要刻意执行这种转换,因为算术运算符方法__add__()__mul__()会自动执行此操作。

将一个PrimeIdeal提升到非负整数次方也是支持的。

示例

>>> from sympy import Poly, cyclotomic_poly, prime_decomp
>>> T = Poly(cyclotomic_poly(7))
>>> P0 = prime_decomp(7, T)[0]
>>> print(P0**6 == 7*P0.ZK)
True 

请注意,在上述等式的两边,我们有一个Submodule。在下一个等式中,我们回顾到添加理想值会产生它们的最大公约数。这次,我们需要在右边有一个明确的转换为Submodule

>>> print(P0 + 7*P0.ZK == P0.as_submodule())
True 

另见

__add__, __mul__

property is_inert

说清楚我们在整数环中保留的有理素数是否惰性,即保持原样。

reduce_ANP(a)

将一个ANP减少到此素理想的“小代表”。

参数:

eltANP

要减少的元素。

返回:

ANP

减少后的元素。

另见

reduce_element, reduce_alg_num, Submodule.reduce_element

reduce_alg_num(a)

将一个AlgebraicNumber减少到此素理想的“小代表”。

参数:

eltAlgebraicNumber

要减少的元素。

返回:

AlgebraicNumber

减少后的元素。

另见

reduce_elementreduce_ANPSubmodule.reduce_element

reduce_element(elt)

PowerBasisElement减少到模这个素数理想的“小代表”。

参数:

eltPowerBasisElement

要减少的元素。

返回:

PowerBasisElement

被减少的元素。

参见

reduce_ANPreduce_alg_numSubmodule.reduce_element

repr(field_gen=None, just_gens=False)

打印这个素数理想的表示。

参数:

field_genSymbolNone,可选(默认为 None

用于场的生成器的符号。这将出现在我们对self.alpha的表示中。如果为None,我们使用self.ZK的定义多项式的变量。

just_gens:布尔值,可选(默认为 False

如果为True,仅打印“(p, alpha)”部分,显示素数理想的“生成器”。否则,打印形式为“[ (p, alpha) e=…, f=… ]”的字符串,给出分歧指数和惯性度,以及生成器。

示例

>>> from sympy import cyclotomic_poly, QQ
>>> from sympy.abc import x, zeta
>>> T = cyclotomic_poly(7, x)
>>> K = QQ.algebraic_field((T, zeta))
>>> P = K.primes_above(11)
>>> print(P[0].repr())
[ (11, x**3 + 5*x**2 + 4*x - 1) e=1, f=3 ]
>>> print(P[0].repr(field_gen=zeta))
[ (11, zeta**3 + 5*zeta**2 + 4*zeta - 1) e=1, f=3 ]
>>> print(P[0].repr(field_gen=zeta, just_gens=True))
(11, zeta**3 + 5*zeta**2 + 4*zeta - 1) 
test_factor()

计算这个素数理想的一个测试因子。

解释

为这个素数理想写下(\mathfrak{p}),(p)是它分解的有理素数。然后,为了计算(\mathfrak{p})-递减估值,有一个数(\beta \in \mathbb{Z}_K),使得(p/\mathfrak{p} = p \mathbb{Z}_K + \beta \mathbb{Z}_K)非常有用。

本质上,这与库默(Kummer)1847 年的论文(Ueber die Zerlegung…, Crelle vol. 35)中的数\Psi(或“试剂”)相同,其中发明了理想除法。

valuation(I)

计算整数理想 I 在这个素数理想上的(\mathfrak{p})-递减估值。

参数:

ISubmodule

参见

prime_valuation

p-递减估值

sympy.polys.numberfields.primes.prime_valuation(I, P)

计算整数理想 IP-递减估值。

参数:

I : Submodule

欲求其价值的整数理想。

P : PrimeIdeal

计算价值的质数。

返回:

int

示例

>>> from sympy import QQ
>>> from sympy.polys.numberfields import prime_valuation
>>> K = QQ.cyclotomic_field(5)
>>> P = K.primes_above(5)
>>> ZK = K.maximal_order()
>>> print(prime_valuation(25*ZK, P[0]))
8 

亦见:

PrimeIdeal.valuation

参考

[R804]

Cohen, H. A Course in Computational Algebraic Number Theory. (见算法 4.8.17。)

Galois 群

sympy.polys.numberfields.galoisgroups.galois_group(f, *gens, by_name=False, max_tries=30, randomize=False, **args)

计算多项式 f 的 Galois 群,直到 6 次。

参数:

f : 表达式

不可约多项式在 ZZ 或 QQ 上,其 Galois 群需确定。

gens : 符号的可选列表

f 转换为 Poly,并传递给 poly_from_expr() 函数。

by_name : bool,默认为 False

如果 True,则以名称返回 Galois 群。否则将其作为 PermutationGroup 返回。

max_tries : int,默认为 30

在生成 Tschirnhausen 变换的步骤中最多尝试这么多次。

randomize : bool,默认为 False

如果为 True,则在生成 Tschirnhausen 变换时使用随机系数。否则,按固定顺序尝试变换。这两种方法都从小系数和次数开始,并向上工作。

args : 可选

f 转换为 Poly,并传递给 poly_from_expr() 函数。

返回:

(G, alt) 进行配对

第一个元素 G 表示 Galois 群。它是 sympy.combinatorics.galois.S1TransitiveSubgroupssympy.combinatorics.galois.S2TransitiveSubgroups 等枚举类的实例,如果 by_nameTrue,则返回其名称;如果是 False,则返回一个 PermutationGroup

第二个元素是一个布尔值,表明群是否包含于交错群 (A_n) ((n) 是 T 的次数)。

引发:

ValueError

如果 f 的度数不支持。

MaxTriesException

如果在生成 Tschirnhausen 变换时尝试次数超过 max_tries 则无法完成。

示例

>>> from sympy import galois_group
>>> from sympy.abc import x
>>> f = x**4 + 1
>>> G, alt = galois_group(f)
>>> print(G)
PermutationGroup([
(0 1)(2 3),
(0 2)(1 3)]) 

该组返回时附带一个布尔值,指示它是否包含在交替群 (A_n) 中,其中 (n) 是 T 的次数。结合其他群属性,这有助于确定它是哪一个群:

>>> alt
True
>>> G.order()
4 

另外,可以通过名称返回该组:

>>> G_name, _ = galois_group(f, by_name=True)
>>> print(G_name)
S4TransitiveSubgroups.V 

然后可以通过调用名称的 get_perm_group() 方法获得该组:

>>> G_name.get_perm_group()
PermutationGroup([
(0 1)(2 3),
(0 2)(1 3)]) 

群名称是枚举类sympy.combinatorics.galois.S1TransitiveSubgroupssympy.combinatorics.galois.S2TransitiveSubgroups等的值。

另请参见

Poly.galois_group

查找最小多项式

sympy.polys.numberfields.minpoly.minimal_polynomial(ex, x=None, compose=True, polys=False, domain=None)

计算代数元素的最小多项式。

参数:

ex : 表达式

要计算其最小多项式的元素或表达式。

x : 符号,可选

最小多项式的自变量

compose : 布尔值,可选(默认值=True)

用于计算最小多项式的方法。如果 compose=True(默认值),则使用 _minpoly_compose,如果 compose=False,则使用格罗本基。

polys : 布尔值, 可选(默认值=False)

如果 True 返回 Poly 对象,否则返回 Expr 对象。

domain : 域,可选

基域

注意

默认情况下 compose=True,计算 ex 的子表达式的最小多项式,然后使用结果和因式分解对它们进行算术运算。如果 compose=False,则使用 groebner 的自下而上算法。默认算法更少停滞。

如果没有指定基域,将从表达式中自动生成。

示例

>>> from sympy import minimal_polynomial, sqrt, solve, QQ
>>> from sympy.abc import x, y 
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
x - sqrt(2)
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
>>> minimal_polynomial(sqrt(y), x)
x**2 - y 
sympy.polys.numberfields.minpoly.minpoly(ex, x=None, compose=True, polys=False, domain=None)

这是minimal_polynomial()的同义词。

子域问题

polys.numberfields.subfield 中的函数解决“子域问题”和相关问题,适用于代数数域。

根据 Cohen(参见[Cohen93] 第 4.5 节),我们可以将主要问题定义如下:

  • 子域问题:

    给定两个数域 (\mathbb{Q}(\alpha)),(\mathbb{Q}(\beta)),通过它们生成元 (\alpha) 和 (\beta) 的最小多项式,判断一个数域是否同构于另一个数域的子域。

从解决此问题的解中,流出以下问题的解:

  • 原始元素问题:

    给定几个代数数 (\alpha_1, \ldots, \alpha_m),计算一个单一的代数数 (\theta),使得 (\mathbb{Q}(\alpha_1, \ldots, \alpha_m) = \mathbb{Q}(\theta))。

  • 域同构问题:

    判断两个数域 (\mathbb{Q}(\alpha)),(\mathbb{Q}(\beta)) 是否同构。

  • 域成员问题:

    给定两个代数数 (\alpha)、(\beta),决定 (\alpha \in \mathbb{Q}(\beta)),如果是,则写成 (\alpha = f(\beta)) 其中 (f(x) \in \mathbb{Q}[x])。

sympy.polys.numberfields.subfield.field_isomorphism(a, b, *, fast=True)

在一个数域嵌入到另一个数域中。

参数:

a : Expr

任何表示代数数的表达式。

b : Expr

任何表示代数数的表达式。

fast : 布尔值,可选(默认为 True)

如果为 True,首先尝试一种可能更快的计算同构的方法,如果失败,则退回到较慢的方法。如果为 False,则直接使用保证返回结果的较慢方法。

返回:

有理数列表,或者为 None

如果 (\mathbb{Q}(a)) 不同构于 (\mathbb{Q}(b)) 的某个子域,则返回 None。否则,返回一个有序列表,表示 (\mathbb{Q}(b)) 中元素,其中 (a) 可能被映射到,以定义单同态,即从 (\mathbb{Q}(a)) 到 (\mathbb{Q}(b)) 的同构。列表的元素是 (b) 的降幂的系数。

解释

此函数寻找从 (\mathbb{Q}(a)) 到 (\mathbb{Q}(b)) 的同构。因此,它解决了子域问题。

示例

>>> from sympy import sqrt, field_isomorphism, I
>>> print(field_isomorphism(3, sqrt(2)))  
[3]
>>> print(field_isomorphism( I*sqrt(3), I*sqrt(3)/2))  
[2, 0] 
sympy.polys.numberfields.subfield.primitive_element(extension, x=None, *, ex=False, polys=False)

找到由几个生成元给出的数域的单一生成元。

参数:

extension : Expr 的列表

每个表达式必须表示代数数 (\alpha_i)。

x : Symbol,可选(默认为 None)

所需出现在原始元素 (\theta) 的计算最小多项式中的符号。如果为 None,则使用虚拟符号。

ex : 布尔值,可选(默认为 False)

当且仅当为True时,计算每个 (\alpha_i) 的表示,作为 (\theta) 的幂次在 (\mathbb{Q}) 上的线性组合。

polys : 布尔值,可选(默认为 False)

如果为 True,将最小多项式作为 Poly 返回。否则将其作为 Expr 返回。

返回:

一对 (f, coeffs) 或三元组 (f, coeffs, reps),其中:

f 是原始元素的最小多项式。coeffs 给出原始元素作为给定生成元的线性组合。如果传递了 ex=True,则 reps 存在,并且是有理数列表的列表。每个列表给出原始生成元的降幂系数,以恢复其中之一。

解释

基本问题是:给定几个代数数 (\alpha_1, \alpha_2, \ldots, \alpha_n),找到一个单一的代数数 (\theta),使得 (\mathbb{Q}(\alpha_1, \alpha_2, \ldots, \alpha_n) = \mathbb{Q}(\theta))。

此函数实际上保证 (\theta) 将是 (\alpha_i) 的线性组合,其系数为非负整数。

此外,如果需要,此函数将告诉您如何将每个 (\alpha_i) 表示为 (\theta) 的 (\mathbb{Q}) 线性组合的幂次元素。

Examples

>>> from sympy import primitive_element, sqrt, S, minpoly, simplify
>>> from sympy.abc import x
>>> f, lincomb, reps = primitive_element([sqrt(2), sqrt(3)], x, ex=True) 

然后 lincomb 告诉我们原始元素作为给定生成元 sqrt(2)sqrt(3) 的线性组合。

>>> print(lincomb)
[1, 1] 

这意味着原始元素是 (\sqrt{2} + \sqrt{3})。同时 f 是这个原始元素的最小多项式。

>>> print(f)
x**4 - 10*x**2 + 1
>>> print(minpoly(sqrt(2) + sqrt(3), x))
x**4 - 10*x**2 + 1 

最后,reps(仅因为我们设置了关键字参数 ex=True 而返回)告诉我们如何将每个生成元 (\sqrt{2}) 和 (\sqrt{3}) 作为 (\mathbb{Q}) 线性组合的幂次元素 (\sqrt{2} + \sqrt{3}) 的恢复方式。

>>> print([S(r) for r in reps[0]])
[1/2, 0, -9/2, 0]
>>> theta = sqrt(2) + sqrt(3)
>>> print(simplify(theta**3/2 - 9*theta/2))
sqrt(2)
>>> print([S(r) for r in reps[1]])
[-1/2, 0, 11/2, 0]
>>> print(simplify(-theta**3/2 + 11*theta/2))
sqrt(3) 
sympy.polys.numberfields.subfield.to_number_field(extension, theta=None, *, gen=None, alias=None)

在生成的域中表达一个代数数。

Parameters:

extension : Expr 或者 Expr 的列表

要么是要在另一个域中表达的代数数,要么是代数数的列表,其中一个原始元素将在另一个域中表达。

theta : Expr, None, optional (default=None)

如果代表代数数的 Expr,则其行为如 Explanation 中所述。如果为 None,则此函数简化为对 extension 调用 primitive_element() 并将计算得到的原始元素转换为 AlgebraicNumber

gen : Symbol, None, optional (default=None)

如果提供,则将用作返回的 AlgebraicNumber 的最小多项式的生成符号。

alias : str, Symbol, None, optional (default=None)

如果提供,则将用作返回的 AlgebraicNumber 的别名符号。

Returns:

AlgebraicNumber

属于 (\mathbb{Q}(\theta)) 并等于 (\eta)。

Raises:

IsomorphismFailed

如果 (\eta \not\in \mathbb{Q}(\theta))。

Explanation

给定两个代数数 (\eta, \theta),此函数要么将 (\eta) 表示为 (\mathbb{Q}(\theta)) 中的元素,要么在 (\eta \not\in \mathbb{Q}(\theta)) 时引发异常。

此函数本质上只是一种方便的工具,利用 field_isomorphism()(我们解决的子域问题)来解决这个域成员问题。

作为额外方便,此函数允许您传递代数数列 (\alpha_1, \alpha_2, \ldots, \alpha_n) 而不是 (\eta)。它会使用 primitive_element() 对 (\alpha_i) 列表计算 (\eta),作为原始元问题的解。

示例

>>> from sympy import sqrt, to_number_field
>>> eta = sqrt(2)
>>> theta = sqrt(2) + sqrt(3)
>>> a = to_number_field(eta, theta)
>>> print(type(a))
<class 'sympy.core.numbers.AlgebraicNumber'>
>>> a.root
sqrt(2) + sqrt(3)
>>> print(a)
sqrt(2)
>>> a.coeffs()
[1/2, 0, -9/2, 0] 

我们得到一个 AlgebraicNumber,其 .root 是 (\theta),其值是 (\eta),并且其 .coeffs() 显示如何用 (\theta) 的降幂写出 (\eta) 的 (\mathbb{Q})-线性组合。

另见

field_isomorphismprimitive_element

内部

代数数域

在 SymPy 中,代数数域由 AlgebraicField 类表示,这是 多项式域系统 的一部分。

表示代数数

表示代数数有多种不同的方式,对于不同的计算任务可能有不同的首选形式。参见 [Cohen93],第 4.2 节。

作为数域元素

在 SymPy 中,有一个区分数字和表达式类别的区别,分别在 sympy.core.numbers 模块中定义,在 polys 模块中定义域和域元素。这在 这里 有更详细的解释。

当涉及代数数时,sympy.core.numbers 模块提供 AlgebraicNumber 类,而 polys 模块提供 ANP 类。这是属于 AlgebraicField 域的域元素类型。

作为有限生成模块的元素

在计算代数数论中,有限生成的(\mathbb{Z})-模块具有至关重要的作用。例如,每个和每个理想都是这样一个模块。

特别地,在数域中,最大秩的序数——或整数环——是一个有限生成的(\mathbb{Z})-模块,其生成器形成该域的整基

允许我们表示这种模块及其元素的类,都在modules模块中提供。在这里,ModuleElement类提供了另一种表示代数数的方式。

有限生成模块

数域中的模块。

这里定义的类允许我们处理有限生成的自由模块,其生成器是代数数。

还有一个名为Module的抽象基类,它有两个具体子类,PowerBasisSubmodule

每个模块由其基础或生成器集合定义:

  • 对于PowerBasis,生成器是代数整数(\theta)的前(n)个幂(从零开始),其次数为(n)。 PowerBasis通过传递(\theta)的最小多项式或将(\theta)作为其原始元素的AlgebraicField来构造。

  • 对于Submodule,生成器是另一个模块的(\mathbb{Q})-线性组合的集合。那个模块则是Submodule的“父”模块。(\mathbb{Q})-线性组合的系数可以由整数矩阵和正整数分母给出。矩阵的每一列定义一个生成器。

>>> from sympy.polys import Poly, cyclotomic_poly, ZZ
>>> from sympy.abc import x
>>> from sympy.polys.matrices import DomainMatrix, DM
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5, x))
>>> A = PowerBasis(T)
>>> print(A)
PowerBasis(x**4 + x**3 + x**2 + x + 1)
>>> B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ), denom=3)
>>> print(B)
Submodule[[2, 0, 0, 0], [0, 2, 0, 0], [0, 0, 2, 0], [0, 0, 0, 2]]/3
>>> print(B.parent)
PowerBasis(x**4 + x**3 + x**2 + x + 1) 

因此,每个模块都是PowerBasisSubmodule的一个祖先,如果S是一个Submodule,那么它的祖先是S.parentS.parent.parent等。

ModuleElement类表示任何模块的生成器的线性组合。关键是,这个线性组合的系数不限于整数,而可以是任何有理数。这是必要的,以便任何和所有的代数整数都可以表示,从某个数域中的原始元素(\theta)的幂开始。例如,在二次域(\mathbb{Q}(\sqrt{d}))中,其中(d \equiv 1 \mod{4}),需要一个分母为 2。

ModuleElement可以由整数列向量和分母构造:

>>> U = Poly(x**2 - 5)
>>> M = PowerBasis(U)
>>> e = M(DM([[1], [1]], ZZ), denom=2)
>>> print(e)
[1, 1]/2
>>> print(e.module)
PowerBasis(x**2 - 5) 

PowerBasisElement类是ModuleElement的子类,表示PowerBasis的元素,并添加了直接在原始元素(\theta)的幂上表示的元素相关的功能。

与模块元素进行算术运算

虽然ModuleElement表示特定模块的生成器的线性组合,但要记住每个模块都是PowerBasis或其后代(沿着Submodule对象的链),因此实际上每个ModuleElement都表示某个域(\mathbb{Q}(\theta))中的代数数,其中(\theta)是某个PowerBasis的定义元素。因此,讨论给定的ModuleElement属于哪个数域是有意义的。

这意味着任意两个ModuleElement实例都可以相加、相减、相乘或相除,只要它们属于同一个数域。同样,由于 (\mathbb{Q}) 是每个数域的子域,任何ModuleElement也可以与任何有理数相加、相乘等。

>>> from sympy import QQ
>>> from sympy.polys.numberfields.modules import to_col
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
>>> e = A(to_col([0, 2, 0, 0]), denom=3)
>>> f = A(to_col([0, 0, 0, 7]), denom=5)
>>> g = C(to_col([1, 1, 1, 1]))
>>> e + f
[0, 10, 0, 21]/15
>>> e - f
[0, 10, 0, -21]/15
>>> e - g
[-9, -7, -9, -9]/3
>>> e + QQ(7, 10)
[21, 20, 0, 0]/30
>>> e * f
[-14, -14, -14, -14]/15
>>> e ** 2
[0, 0, 4, 0]/9
>>> f // g
[7, 7, 7, 7]/15
>>> f * QQ(2, 3)
[0, 0, 0, 14]/15 

然而,在对ModuleElement进行算术操作时必须要小心,因为结果所属的模块 (C) 将是两个操作数所属的模块 (A) 和 (B) 的最近公共祖先(NCA),而 (C) 可能与 (A) 和 (B) 中的任意一个或两个都不同。

>>> A = PowerBasis(T)
>>> B = A.submodule_from_matrix(2 * DomainMatrix.eye(4, ZZ))
>>> C = A.submodule_from_matrix(3 * DomainMatrix.eye(4, ZZ))
>>> print((B(0) * C(0)).module == A)
True 

在执行算术操作之前,两个操作数的副本会自动转换为 NCA 的元素(操作数本身不会被修改)。沿祖先链的向上转换非常简单:只需依次乘以每个Submodule的定义矩阵即可。

反过来,也支持向下转换,即将给定的ModuleElement表示为子模块中的一个元素,具体方法是represent()方法。但是一般来说,这种转换并不保证总是成功,因为给定的元素可能不属于子模块。这个问题通常在乘法时出现,因为模块在加法下封闭,但不一定在乘法下封闭。

乘法

一般来说,一个模块不一定在乘法下封闭,即不一定构成一个环。然而,在数域的背景下我们处理的许多模块实际上是环,而我们的类确实支持乘法。

具体来说,任何Module都可以尝试计算其自己的乘法表,但只有在尝试将属于它的两个ModuleElement实例相乘时才会这样做。

>>> A = PowerBasis(T)
>>> print(A._mult_tab is None)
True
>>> a = A(0)*A(1)
>>> print(A._mult_tab is None)
False 

每个PowerBasis本质上都是在乘法下封闭的,因此PowerBasis的实例总是可以成功地计算它们的乘法表。

当一个Submodule试图计算其乘法表时,它会将自己的每个生成元转换为其父模块中的元素,并在那里进行每个可能的配对的乘法运算,然后试图将结果表示为其自身的(\mathbb{Z})-线性组合,即其自身的生成元。只有当子模块实际上在乘法下是封闭的时,这个过程才会成功。

模同态

许多重要的数论算法需要计算一个或多个模同态的核。因此,我们有几个轻量级类,ModuleHomomorphismModuleEndomorphismInnerEndomorphismEndomorphismRing,它们提供了支持这些操作所需的最小机制。

类参考
class sympy.polys.numberfields.modules.Module

通用的有限生成模块。

这是一个抽象基类,不应直接实例化。两个具体的子类是PowerBasisSubmodule

每个Submodule都来源于另一个模块,通过其parent属性引用。如果S是一个子模块,则我们称S.parentS.parent.parent等为S的“祖先”。因此,每个Module要么是一个PowerBasis,要么是一个Submodule,其中某个祖先是PowerBasis

__call__(spec, denom=1)

生成属于此模块的ModuleElement

参数:

spec : DomainMatrix, int

指定ModuleElement的系数的分子。可以是整数向量,范围为 ZZ,其长度必须等于此模块生成器的数量(n),或者是整数j,(0 \leq j < n),表示单位矩阵(I_n)的第(n \times n)列的简写。

denom:整数,可选(默认=1)

ModuleElement的系数的分母。

返回:

ModuleElement

系数是spec向量的条目,除以denom

示例

>>> from sympy.polys import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis, to_col
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> e = A(to_col([1, 2, 3, 4]), denom=3)
>>> print(e)  
[1, 2, 3, 4]/3
>>> f = A(2)
>>> print(f)  
[0, 0, 1, 0] 
ancestors(include_self=False)

返回此模块的祖先模块列表,从基础的PowerBasis开始向下,可选包括self

另见

Module

basis_elements()

获取ModuleElement生成器列表。

element_from_rational(a)

返回一个表示有理数的ModuleElement

参数:

a:整数,ZZ,QQ

返回:

ModuleElement

解释

返回的ModuleElement将属于此模块的祖先链上的第一个模块(包括此模块本身),该链以单位元素开始。

示例

>>> from sympy.polys import Poly, cyclotomic_poly, QQ
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> a = A.element_from_rational(QQ(2, 3))
>>> print(a)  
[2, 0, 0, 0]/3 
endomorphism_ring()

形成此模块的EndomorphismRing

is_compat_col(col)

判断col是否适合此模块的列向量。

mult_tab()

获取此模块的乘法表(如果在乘法下封闭)。

返回:

字典的字典的列表

抛出:

ClosureFailure

如果模块在乘法下不封闭。

解释

计算表示乘法表上三角部分的字典M的字典的列表。

换句话说,如果0 <= i <= j < self.n,那么M[i][j]是系数列表c,使得g[i] * g[j] == sum(c[k]*g[k], k in range(self.n)),其中g是此模块生成器的列表。

如果j < i,则M[i][j]未定义。

示例

>>> from sympy.polys import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> print(A.mult_tab())  
{0: {0: [1, 0, 0, 0], 1: [0, 1, 0, 0], 2: [0, 0, 1, 0],     3: [0, 0, 0, 1]},
 1: {1: [0, 0, 1, 0], 2: [0, 0, 0, 1],     3: [-1, -1, -1, -1]},
 2: {2: [-1, -1, -1, -1], 3: [1, 0, 0, 0]},
 3: {3: [0, 1, 0, 0]}} 
property n

此模块的生成器数量。

nearest_common_ancestor(other)

定位此模块及另一个模块的最近公共祖先。

返回:

ModuleNone

另见

Module

property number_field

返回关联的AlgebraicField(如果有的话)。

返回:

AlgebraicFieldNone

解释

可以在Poly (f)上或者在AlgebraicField (K)上构造PowerBasis。在后一种情况下,PowerBasis及其所有后代模块将返回(K)作为其.number_field属性,而在前一种情况下,它们将全部返回None

one()

返回表示单位的ModuleElement,并属于该模块的第一个祖先(包括它自身),该祖先以单位开始。

property parent

如果有的话,返回此模块的父模块。

返回:

ModuleNone

解释

对于Submodule,这是其parent属性;对于PowerBasis,这是None

另请参见

Module

power_basis_ancestor()

返回这个模块的祖先的PowerBasis

另请参见

Module

represent(elt)

将模块元素表示为该模块生成器的整数线性组合。

参数:

eltModuleElement

要表示的模块元素。 必须属于此模块的某个祖先模块(包括此模块本身)。

返回:

DomainMatrix关于 ZZ

这将是一个列向量,表示该模块生成器的线性组合的系数,其等于给定的元素。

引发:

ClosureFailure

如果给定的元素不能表示为此模块上的 ZZ 线性组合。

解释

在我们的系统中,“表示”始终意味着将ModuleElement写成当前Module的生成元的 ZZ 线性组合。此外,传入的ModuleElement必须属于当前Module的祖先(或当前Module本身)。

最常见的应用是在Submodule中表示ModuleElement。例如,这涉及计算乘法表。

另一方面,在PowerBasis中表示是一个特例,这种情况通常不会在实践中出现,除非例如在ModuleEndomorphismPowerBasis上使用时。

在这种情况下,(1)传入的ModuleElement必须属于PowerBasis本身(因为后者没有适当的祖先),(2)它“可表示”当且仅当它属于(\mathbb{Z}[\theta])(尽管通常PowerBasisElement可以表示(\mathbb{Q}(\theta))中的任何元素,即任何代数数)。

示例

>>> from sympy import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis, to_col
>>> from sympy.abc import zeta
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> a = A(to_col([2, 4, 6, 8])) 

ModuleElement a 的所有系数都是偶数。如果我们在子模块B = 2*A中表示a,列向量中的系数将减半:

>>> B = A.submodule_from_gens([2*A(i) for i in range(4)])
>>> b = B.represent(a)
>>> print(b.transpose())  
DomainMatrix([[1, 2, 3, 4]], (1, 4), ZZ) 

然而,如此定义的B中的元素仍表示相同的代数数:

>>> print(a.poly(zeta).as_expr())
8*zeta**3 + 6*zeta**2 + 4*zeta + 2
>>> print(B(b).over_power_basis().poly(zeta).as_expr())
8*zeta**3 + 6*zeta**2 + 4*zeta + 2 

另请参阅

Submodule.representPowerBasis.represent

starts_with_unity()

判断模块的第一个生成元是否等于单位元。

submodule_from_gens(gens, hnf=True, hnf_modulus=None)

用属于本模块的 ModuleElement 列表生成的子模。

参数:

gens : 属于本模块的 ModuleElement 列表。

hnf : boolean, optional (默认=True)

如果为 True,则在形成 Submodule 前将矩阵缩减为 Hermite 正规形式。

hnf_modulus : int, None, optional (默认=None)

用于 HNF 缩减算法中的模数。参见 hermite_normal_form()

返回:

Submodule

示例

>>> from sympy.polys import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> gens = [A(0), 2*A(1), 3*A(2), 4*A(3)//5]
>>> B = A.submodule_from_gens(gens)
>>> print(B)  
Submodule[[5, 0, 0, 0], [0, 10, 0, 0], [0, 0, 15, 0], [0, 0, 0, 4]]/5 

另请参阅

submodule_from_matrix

submodule_from_matrix(B, denom=1)

用矩阵的列指示的本模块的元素生成的子模,带有可选的分母。

参数:

B : ZZ上的 DomainMatrix

每一列都给出了子模的一个生成元的系数的分子。因此,B 的行数必须等于当前模的生成元的数量。

denom : int, optional (默认=1)

所有生成元的公共分母的最小公倍数。

返回:

Submodule

引发:

ValueError

如果给定的矩阵 B 不是在 ZZ 上或其行数不等于当前模的生成元的数量。

示例

>>> from sympy.polys import Poly, cyclotomic_poly, ZZ
>>> from sympy.polys.matrices import DM
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> B = A.submodule_from_matrix(DM([
...     [0, 10, 0, 0],
...     [0,  0, 7, 0],
... ], ZZ).transpose(), denom=15)
>>> print(B)  
Submodule[[0, 10, 0, 0], [0, 0, 7, 0]]/15 

另请参阅

submodule_from_gens

whole_submodule()

返回一个等于整个模的子模。

说明

当您有一个 PowerBasis 并希望将其转换为 Submodule(以使用后者属于的方法)时,这将非常有用。

zero()

返回一个表示零的 ModuleElement

class sympy.polys.numberfields.modules.PowerBasis(T)

由代数整数的幂生成的模。

__init__(T)

参数:

T : Poly, AlgebraicField

(1)整数环上的首一、不可约、一元多项式,其根是幂基的生成元,或者(2)一个 代数域,其原始元素是幂基的生成元。

element_from_ANP(a)

将 ANP 转换为幂基元素。

element_from_alg_num(a)

将代数数转换为幂基元素。

element_from_poly(f)

在我们定义的最小多项式模除后,产生此模块的元素,表示 f

参数:

f : 多项式 over ZZ,与我们定义的多项式相同的变量。

返回:

幂基元素

represent(elt)

将模块元素表示为该模块生成器上的整数线性组合。

另请参阅

Module.representSubmodule.represent

class sympy.polys.numberfields.modules.Submodule(parent, matrix, denom=1, mult_tab=None)

另一个模块的子模块。

__init__(parent, matrix, denom=1, mult_tab=None)

参数:

parent : 模块

派生此模块的模块。

matrix : 域矩阵 over ZZ

其列定义此子模块生成器作为父生成器上的线性组合的矩阵。

denom : 整数, 可选 (默认为 1)

矩阵给定系数的分母。

mult_tab : 字典, None, 可选

如果已知,可以提供此模块的乘法表。

property QQ_matrix

域矩阵 over QQ,等于 self.matrix / self.denom,并保证为稠密矩阵。

返回:

域矩阵 over QQ

解释

取决于其形成方式,域矩阵 可能具有内部表示为稀疏或稠密的表现形式。我们在这里保证稠密表示,以便子模块的等价性测试总是符合预期。

示例

>>> from sympy.polys import Poly, cyclotomic_poly, ZZ
>>> from sympy.abc import x
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> T = Poly(cyclotomic_poly(5, x))
>>> A = PowerBasis(T)
>>> B = A.submodule_from_matrix(3*DomainMatrix.eye(4, ZZ), denom=6)
>>> C = A.submodule_from_matrix(DomainMatrix.eye(4, ZZ), denom=2)
>>> print(B.QQ_matrix == C.QQ_matrix)
True 
add(other, hnf=True, hnf_modulus=None)

将此 子模块 添加到另一个模块中。

参数:

other : 子模块

hnf : 布尔值, 可选 (默认为 True)

如果为True,将组合模块的矩阵减少到其 Hermite 正常形式。

hnf_modulus:ZZ,可选,默认为 None

如果提供了正整数,则在 HNF 约简中使用它作为模数。参见hermite_normal_form()

返回:

子模块

说明

这代表由两个模块生成器集合的并集生成的模块。

basis_element_pullbacks()

返回此子模块作为父模块中的基元素列表。

discard_before(r)

通过丢弃给定索引r之前的所有生成器来生成一个新的模块。

mul(other, hnf=True, hnf_modulus=None)

将此子模块乘以一个有理数,一个模元素或另一个子模块

参数:

other:整数,ZZ,QQ,模元素子模块

hnf:布尔值,可选(默认为 True)

如果为True,将产品模块的矩阵减少到其 Hermite 正常形式。

hnf_modulus:ZZ,可选,默认为 None

如果提供了正整数,则在 HNF 约简中使用它作为模数。参见hermite_normal_form()

返回:

子模块

说明

乘以有理数或模元素意味着形成其生成器为当前子模块所有生成器与此数量的乘积的子模块。

乘以另一个子模块意味着形成其生成器为一个子模块的一个生成器与另一个子模块的一个生成器的乘积的子模块。

reduce_element(elt)

如果此子模块(B)在方形、最大秩 Hermite 正常形式中具有定义矩阵(W),则给定父模块(A)的元素(x),我们产生一个元素(y \in A),使得(x - y \in B),并且(y)的第(i)个坐标满足(0 \leq y_i < w_{i,i})。这个代表(y)是唯一的,意味着每个余类(x + B)在此过程下都将其减少为它。

参数:

元素 : 模块元素

这个子模块的父模块的一个元素。

返回:

元素 : 模块元素

这个子模块的父模块的一个元素。

引发:

未实现错误

如果给定的 模块元素 不属于此子模块的父模块。

结构错误

如果这个子模块的定义矩阵不是方的、最大秩的 Hermite 正则形式。

解释

特别情况下,当 (A) 是数域 (K) 的一个幂基,而 (B) 是代表理想 (I) 的一个子模块时,这个操作代表了将 (K) 中的一个元素对 (I) 取模以得到一个“小”代表的几种重要方法之一。参见 [Cohen00] 第 1.4.3 节。

示例

>>> from sympy import QQ, Poly, symbols
>>> t = symbols('t')
>>> k = QQ.alg_field_from_poly(Poly(t**3 + t**2 - 2*t + 8))
>>> Zk = k.maximal_order()
>>> A = Zk.parent
>>> B = (A(2) - 3*A(0))*Zk
>>> B.reduce_element(A(2))
[3, 0, 0] 

参考文献

[Cohen00] (1,2)

Cohen, H. 计算数论的高级主题.

reduced()

生成这个子模块的简化版本。

返回:

子模块

解释

在简化版本中,保证 1 是唯一同时整除子模块的分母和子模块矩阵中每个条目的正整数。

represent(elt)

将一个模块元素表示为该模块生成元的整数线性组合。

另请参阅

Module.represent, PowerBasis.represent

class sympy.polys.numberfields.modules.ModuleElement(module, col, denom=1)

表示 模块 的一个元素。

注:不应直接构造。请使用 __call__() 方法或 make_mod_elt() 工厂函数代替。

__init__(module, col, denom=1)

参数:

模块 : 模块

属于此元素的模块。

: 域矩阵 over ZZ

给出此元素系数的分子的列向量。

分母 : int, 可选 (默认=1)

此元素的系数的分母。

__add__(other)

一个ModuleElement可以加到一个有理数,或者另一个ModuleElement

解释

当另一个加数是有理数时,它将被转换为一个ModuleElement(属于这个模块的第一个以单位开始的祖先)。

在所有情况下,和属于两个加数模块的最近公共祖先(NCA)。如果 NCA 不存在,我们返回NotImplemented

__mul__(other)

一个ModuleElement可以乘以有理数,或者另一个ModuleElement

解释

当乘数是一个有理数时,该产品通过直接操作这个ModuleElement的系数来计算。

当乘数是另一个ModuleElement时,该产品将属于两个操作数的模块的最近公共祖先(NCA),并且该 NCA 必须有一个乘法表。如果 NCA 不存在,我们返回NotImplemented。如果 NCA 没有乘法表,将会引发ClosureFailure

__mod__(m)

将这个ModuleElementSubmodule进行归约。

参数:

m:整数,ZZ,QQ,Submodule

如果是Submodule,相对于此归约self。如果是整数或有理数,则相对于我们自己模块乘以这个常数的Submodule进行归约。

参见

Submodule.reduce_element

property QQ_col

DomainMatrix 在 QQ 上,等于self.col / self.denom,并且保证是密集的。

参见

Submodule.QQ_matrix

column(domain=None)

获取此元素列的副本,可选择转换为域。

equiv(other)

如果它们表示相同的代数数,则ModuleElement可能测试为等价于有理数或另一个。

参数:

other:int,ZZ,QQ,ModuleElement

返回:

布尔值

引发:

UnificationFailed

如果selfother不共享PowerBasis祖先。

解释

此方法仅意在检查等价性的情况下进行测试;即,当other是可以与此一致化的ModuleElement(即,与此共享公共PowerBasis祖先)或者是一个有理数时(因为每个PowerBasis代表每个有理数)。

classmethod from_int_list(module, coeffs, denom=1)

从整数列表(而不是列向量)创建一个ModuleElement

is_compat(other)

测试other是否为另一个具有相同模块的ModuleElement

property n

此元素列的长度。

over_power_basis()

转换为我们PowerBasis祖先上的PowerBasisElement

reduced()

生成此ModuleElement的简化版本,即分母和所有分子系数的 gcd 为 1。

reduced_mod_p(p)

生成此ModuleElement的版本,其中所有分子系数已经对p取模。

to_ancestor(anc)

将其转换为属于此元素模块祖先的ModuleElement

参数:

ancModule

to_parent()

转换为此元素模块父级的ModuleElement

unify(other)

尝试生成一个与ModuleElement兼容的配对,一个等效于这个,另一个等效于另一个。

返回:

配对(e1, e2)

每个eiModuleElement,它们属于同一个Modulee1等效于selfe2等效于other

抛出:

UnificationFailed

如果selfother没有共同的祖先模块。

Explanation

我们搜索元素对的最近共同祖先模块,并在那里表示每个元素。

class sympy.polys.numberfields.modules.PowerBasisElement(module, col, denom=1)

子类,用于模块为PowerBasisModuleElement实例。

property T

访问PowerBasis的定义多项式。

as_expr(x=None)

self创建一个基本表达式。

property generator

返回一个Symbol,用于在多项式中表示此元素。

如果我们有一个关联的AlgebraicField,其原始元素具有别名符号,我们使用它。否则,我们使用定义功率基底的极小多项式的变量。

property is_rational

判断此元素是否表示一个有理数。

norm(T=None)

计算该数的范数。

numerator(x=None)

将该数的分子作为多项式获取在 ZZ 上。

poly(x=None)

将该数作为多项式获取在 QQ 上。

to_ANP()

转换为等效的ANP

to_alg_num()

尝试转换为等效的AlgebraicNumber

返回:

AlgebraicNumber

抛出:

StructureError

如果这个元素所属的PowerBasis没有关联的AlgebraicField

Explanation

一般来说,从AlgebraicNumberPowerBasisElement的转换会丢失信息,因为AlgebraicNumber指定了一个复数嵌入,而PowerBasisElement则没有。然而,在某些情况下,可以将PowerBasisElement转换回AlgebraicNumber,特别是当相关的PowerBasis引用了一个AlgebraicField时。

sympy.polys.numberfields.modules.make_mod_elt(module, col, denom=1)

工厂函数用于构建一个ModuleElement,但如果模块是PowerBasis,则确保它是PowerBasisElement

class sympy.polys.numberfields.modules.ModuleHomomorphism(domain, codomain, mapping)

从一个模块到另一个模块的同态映射。

__init__(domain, codomain, mapping)

参数:

domainModule

映射的定义域。

codomainModule

映射的值域。

mapping:可调用对象

任意可调用对象都可以被接受,但应选择代表实际模块同态的对象。特别是,应该接受定义域的元素并返回值域的元素。

示例:

>>> from sympy import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis, ModuleHomomorphism
>>> T = Poly(cyclotomic_poly(5))
>>> A = PowerBasis(T)
>>> B = A.submodule_from_gens([2*A(j) for j in range(4)])
>>> phi = ModuleHomomorphism(A, B, lambda x: 6*x)
>>> print(phi.matrix())  
DomainMatrix([[3, 0, 0, 0], [0, 3, 0, 0], [0, 0, 3, 0], [0, 0, 0, 3]], (4, 4), ZZ) 
kernel(modulus=None)

计算代表这个同态的核心的子模块。

参数:

modulus:int,可选

如果核心应该在模数p下计算,则为正的素数(p)。

返回:

Submodule

这个子模块的生成元跨越在 ZZ 上这个同态的核心,或者如果给定了模数,那么在 GF§上跨越。

matrix(modulus=None)

计算这个同态的矩阵。

参数:

modulus:int,可选

如果矩阵应该在模数p下被约简,则为正的素数(p)。

返回:

DomainMatrix

如果矩阵是在 ZZ 上,否则是在 GF§上,如果给定了模数。

class sympy.polys.numberfields.modules.ModuleEndomorphism(domain, mapping)

从一个模到其自身的同态映射。

__init__(domain, mapping)

参数:

定义域Module

映射的公共定义域和值域。

映射:可调用

接受任意可调用对象,但应选择以表示实际的模自同态。特别地,应接受并返回 定义域 的元素。

class sympy.polys.numberfields.modules.InnerEndomorphism(domain, multiplier)

模上的内部自同态,即乘以固定元素所对应的自同态。

__init__(domain, multiplier)

参数:

定义域Module

自同态的定义域和值域。

乘子ModuleElement

元素 (a) 定义映射为 (x \mapsto a x)。

class sympy.polys.numberfields.modules.EndomorphismRing(domain)

一个模的自同态环。

__init__(domain)

参数:

定义域Module

自同态的定义域和值域。

inner_endomorphism(multiplier)

形成属于这个自同态环的内部自同态。

参数:

乘子ModuleElement

定义内部自同态的元素 (a),即 (x \mapsto a x)。

返回:

InnerEndomorphism

represent(element)

将这个自同态环的元素表示为一个单列向量。

参数:

元素ModuleEndomorphism 属于这个环。

返回:

DomainMatrix

列向量等于将表示给定 元素 的矩阵的所有列竖直堆叠。

解释

设 (M) 是一个模,(E) 是其自同态环。设 (N) 是另一个模,并考虑一个同态 (\varphi: N \rightarrow E)。如果 (\varphi) 要用矩阵 (A) 表示,那么 (A) 的每一列必须表示 (E) 的一个元素。当 (E) 的元素本身可以表示为矩阵时,可以通过将这样一个矩阵的列堆叠成单列来实现这一点。

此方法支持计算这样的矩阵 (A),首先将这个自同态环的一个元素表示为矩阵,然后将该矩阵的列堆叠成单列。

示例

注意,在这些示例中,我们打印矩阵的转置,以便更容易检查其列。

>>> from sympy import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.modules import PowerBasis
>>> from sympy.polys.numberfields.modules import ModuleHomomorphism
>>> T = Poly(cyclotomic_poly(5))
>>> M = PowerBasis(T)
>>> E = M.endomorphism_ring() 

设 (\zeta) 是一个原始的五次单位根,是我们域的生成元,考虑由 (\zeta) 引出的整数环上的内部自同态 (\tau):

>>> zeta = M(1)
>>> tau = E.inner_endomorphism(zeta)
>>> tau.matrix().transpose()  
DomainMatrix(
 [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [-1, -1, -1, -1]],
 (4, 4), ZZ) 

矩阵表示的 (\tau) 如预期所示。第一列显示乘以 (\zeta) 将 (1) 带到 (\zeta),第二列显示将 (\zeta) 带到 (\zeta²),依此类推。

E 的同态的 represent 方法将它们堆叠到单列中:

>>> E.represent(tau).transpose()  
DomainMatrix(
 [[0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1, -1, -1, -1]],
 (1, 16), ZZ) 

当我们想要考虑一个具有 E 作为余域的同态 (\varphi) 时,这是有用的:

>>> phi = ModuleHomomorphism(M, E, lambda x: E.inner_endomorphism(x)) 

我们希望计算这样一个同态的矩阵:

>>> phi.matrix().transpose()  
DomainMatrix(
 [[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
 [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -1, -1, -1, -1],
 [0, 0, 1, 0, 0, 0, 0, 1, -1, -1, -1, -1, 1, 0, 0, 0],
 [0, 0, 0, 1, -1, -1, -1, -1, 1, 0, 0, 0, 0, 1, 0, 0]],
 (4, 16), ZZ) 

注意,(\tau) 的堆叠矩阵在此示例中作为第二列出现。这是因为 (\zeta) 是 M 的第二个基元素,并且 (\varphi(\zeta) = \tau)。

sympy.polys.numberfields.modules.find_min_poly(alpha, domain, x=None, powers=None)

找到一个在有单位元的有限生成环中满足一个元素的最小次数(不一定是不可约的)的多项式。

参数:

alpha : ModuleElement

期望找到其最小多项式的元素,并且其模具有乘法并以单位元开始。

domain : Domain

多项式的期望域。

x : Symbol,可选

多项式的期望变量。

powers : 列表,可选

如果需要,传递空列表。从零到最小多项式的次数,将 alpha 的幂(作为 ModuleElement 实例)记录在此处,我们在计算它们时。

返回:

PolyNone

对于 alpha 的最小多项式,如果在期望的域上找不到多项式,则返回 None

引发:

MissingUnityError

如果 alpha 属于的模不以单位元开头。

ClosureFailure

如果 alpha 属于的模不闭合于乘法。

示例

对于第 (n) 个旋缠域,(n) 为奇素数,考虑其根为长度为 ((n-1)/2) 的两个周期的二次方程。高斯的文章 356 告诉我们,根据 (n) 是 1 或 3 模 4,我们应该得到 (x² + x - (n-1)/4) 或 (x² + x + (n+1)/4)。

>>> from sympy import Poly, cyclotomic_poly, primitive_root, QQ
>>> from sympy.abc import x
>>> from sympy.polys.numberfields.modules import PowerBasis, find_min_poly
>>> n = 13
>>> g = primitive_root(n)
>>> C = PowerBasis(Poly(cyclotomic_poly(n, x)))
>>> ee = [g**(2*k+1) % n for k in range((n-1)//2)]
>>> eta = sum(C(e) for e in ee)
>>> print(find_min_poly(eta, QQ, x=x).as_expr())
x**2 + x - 3
>>> n = 19
>>> g = primitive_root(n)
>>> C = PowerBasis(Poly(cyclotomic_poly(n, x)))
>>> ee = [g**(2*k+2) % n for k in range((n-1)//2)]
>>> eta = sum(C(e) for e in ee)
>>> print(find_min_poly(eta, QQ, x=x).as_expr())
x**2 + x + 5 

实用程序

sympy.polys.numberfields.utilities.is_rat(c)

测试参数是否适合用作有理数。

解释

对于类型为 int、ZZ 或 QQ 的任何参数返回 True

另请参阅

is_int

sympy.polys.numberfields.utilities.is_int(c)

测试参数是否适合用作整数。

解释

对于类型为 int 或 ZZ 的任何参数返回 True

另请参阅

is_rat

sympy.polys.numberfields.utilities.get_num_denom(c)

给定 is_rat() 返回为 True 的任何参数,返回此数的分子和分母。

另见

is_rat

sympy.polys.numberfields.utilities.extract_fundamental_discriminant(a)

从整数 a 中提取基本判别式。

参数:

a: int, 必须是 0 或 1 模 4

返回:

字典对 (D, F)

抛出:

ValueError

如果 a 不是 4 的倍数余 0 或 1.

解释

给定任意 0 或 1 模 4 的有理整数 a,写成 (a = d f²),其中 (d) 要么是 1 要么是基本判别式,并返回给定的由 factorint() 返回格式相同的字典对 (D, F),分别给出 (d) 和 (f) 的素因子分解。

基本判别式 (d) 不同于单位,并且要么是 4 的倍数余 1 并且无平方因子,要么是 4 的倍数余 0 并且 (d/4) 是无平方因子并且余 2 或 3。这等同于某些二次域的判别式。

示例

>>> from sympy.polys.numberfields.utilities import extract_fundamental_discriminant
>>> print(extract_fundamental_discriminant(-432))
({3: 1, -1: 1}, {2: 2, 3: 1}) 

作为比较:

>>> from sympy import factorint
>>> print(factorint(-432))
{2: 4, 3: 3, -1: 1} 

参考文献

[R805]

Cohen, H. 计算代数数论课程.(见 Prop. 5.1.3)

class sympy.polys.numberfields.utilities.AlgIntPowers(T, modulus=None)

计算代数整数的幂。

解释

给定一个代数整数 (\theta) 由其在 ZZ 上的首一不可约多项式 T,此类计算 (\theta) 的任意高次幂的表示,作为 ZZ 上的线性组合,其中 (n = \deg(T))。

利用多项式 T 导出的 (\theta) 的幂的线性递归关系计算表示。见 [1],第 4.2.2 节。

可选地,可以将表示与模数减少。

示例

>>> from sympy import Poly, cyclotomic_poly
>>> from sympy.polys.numberfields.utilities import AlgIntPowers
>>> T = Poly(cyclotomic_poly(5))
>>> zeta_pow = AlgIntPowers(T)
>>> print(zeta_pow[0])
[1, 0, 0, 0]
>>> print(zeta_pow[1])
[0, 1, 0, 0]
>>> print(zeta_pow[4])  
[-1, -1, -1, -1]
>>> print(zeta_pow[24])  
[-1, -1, -1, -1] 

参考文献

[R806]

Cohen, H. 计算代数数论课程.

__init__(T, modulus=None)

参数:

T : Poly

定义代数整数的首一不可约多项式在 ZZ 上。

modulus : int, None, 可选

如果不是 None,所有表示将被减少到这个。

sympy.polys.numberfields.utilities.coeff_search(m, R)

为搜索多项式生成系数。

参数:

m : int

系数列表的长度。

R : int

系数的初始最大绝对值(搜索进行时将增加)。

返回:

generator

列表系数的无限生成器。

解释

导数系数始终为非负。在增加界限前,探索绝对值受限的所有组合。跳过全零列表,跳过任何重复。见示例。

示例

>>> from sympy.polys.numberfields.utilities import coeff_search
>>> cs = coeff_search(2, 1)
>>> C = [next(cs) for i in range(13)]
>>> print(C)
[[1, 1], [1, 0], [1, -1], [0, 1], [2, 2], [2, 1], [2, 0], [2, -1], [2, -2],
 [1, 2], [1, -2], [0, 2], [3, 3]] 
sympy.polys.numberfields.utilities.supplement_a_subspace(M)

将子空间的基扩展为整个空间的基。

参数:

M : DomainMatrix

列给出子空间的基。

返回:

DomainMatrix

此矩阵是可逆的,其前 (r) 列等于 M

提升:

DMRankError

如果 M 不是最大秩。

解释

给定一个秩为 (r) 的 (n \times r) 矩阵 M(因此 (r \leq n)),此函数计算一个可逆的 (n \times n) 矩阵 (B),使得 (B) 的前 (r) 列等于 M

这个操作可以解释为扩展子空间的基,从而给出整个空间的基。

具体来说,假设您有一个 (n)-维向量空间 (V),其基为 ({v_1, v_2, \ldots, v_n}),以及 (V) 的一个 (r)-维子空间 (W),其由基 ({w_1, w_2, \ldots, w_r}) 张成,其中 (w_j) 被给出作为 (v_i) 的线性组合。如果 M 的列表示这些 (w_j) 作为这种线性组合,则此函数计算的矩阵 (B) 的列给出一个新的基 ({u_1, u_2, \ldots, u_n}) 用于 (V),再次相对于 ({v_i}) 基,并且对于 (1 \leq j \leq r),有 (u_j = w_j)。

示例

注意:该函数按列处理,因此在这些示例中,我们打印矩阵的转置,以便更容易检查列。

>>> from sympy.polys.matrices import DM
>>> from sympy import QQ, FF
>>> from sympy.polys.numberfields.utilities import supplement_a_subspace
>>> M = DM([[1, 7, 0], [2, 3, 4]], QQ).transpose()
>>> print(supplement_a_subspace(M).to_Matrix().transpose())
Matrix([[1, 7, 0], [2, 3, 4], [1, 0, 0]]) 
>>> M2 = M.convert_to(FF(7))
>>> print(M2.to_Matrix().transpose())
Matrix([[1, 0, 0], [2, 3, -3]])
>>> print(supplement_a_subspace(M2).to_Matrix().transpose())
Matrix([[1, 0, 0], [2, 3, -3], [0, 1, 0]]) 

参考资料

[R807]

Cohen, H. 计算代数数论课程(见第 2.3.2 节。)

sympy.polys.numberfields.utilities.isolate(alg, eps=None, fast=False)

为实数代数数找到一个有理隔离区间。

参数:

alg:str, int, Expr

要隔离的代数数。必须是实数,才能使用此特定函数。但是,另请参阅Poly.intervals(),当您传递all=True时,它可以隔离复数根。

eps:正元素 QQ 中的元素,None,可选(默认为 None)

要传递给Poly.refine_root()的精度。

fast:布尔值,可选(默认为 False)

说明是否应该使用快速细化过程。(将传递给Poly.refine_root().)

返回:

一对有理数,定义给定代数数的隔离区间

代数数。

示例

>>> from sympy import isolate, sqrt, Rational
>>> print(isolate(sqrt(2)))  
(1, 2)
>>> print(isolate(sqrt(2), eps=Rational(1, 100)))
(24/17, 17/12) 

另请参阅

Poly.intervals

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值