数字域¶
介绍¶
与代数数论中的许多其他计算一样,有理素数的分裂只能通过 有理 方法来处理。如果考虑通过自动计算机器进行计算,这一事实非常重要。只需要知道不可约多项式 \(f(x)\),其零点生成所讨论的域。
—奥尔加·陶斯基,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\),计算:
\(\mathbb{Z}_K\) 的整基
\(\mathbb{Z}_K\) 中有理素数的分解
理想和元素的\(\mathfrak{p}\)-进赋值
伽罗瓦群的伽罗瓦闭包 \(K\)
一个基本单位为 \(K\) 的系统
调节器 \(R(K)\)
类编号
类群 \(Cl(K)\) 的结构
确定给定的理想是否是主理想,如果是,则计算一个生成元。
作为基础,为了支持我们定义和处理数域及代数数的基本能力,我们按照 [Cohen93] ,第4.5节,设置了以下问题。
给定一个代数数——通过根式和有理运算表示,或甚至作为某个超越函数的特殊值——确定其在 \(\mathbb{Q}\) 上的最小多项式。
子域问题:给定两个数域 \(\mathbb{Q}(\alpha)\) 和 \(\mathbb{Q}(\beta)\),通过它们的生成元 \(\alpha\) 和 \(\beta\) 的最小多项式,判断其中一个域是否同构于另一个域的子域,如果是,则展示一个嵌入。
域成员问题:给定两个代数数 \(\alpha\), \(\beta\),判断 \(\alpha \in \mathbb{Q}(\beta)\) 是否成立,如果成立则写出 \(\alpha = f(\beta)\) 对于某些 \(f(x) \in \mathbb{Q}[x]\)。
原始元素问题:给定若干代数数 \(\alpha_1, \ldots, \alpha_m\),计算一个代数数 \(\theta\),使得 \(\mathbb{Q}(\alpha_1, \ldots, \alpha_m) = \mathbb{Q}(\theta)\)。
目前,SymPy 仅支持上述列举任务的一部分,如果你有兴趣扩展支持,欢迎贡献!一个优秀的资源,提供了所有剩余问题(以及已解决的问题)的解决方案,是 [Cohen93]。
在撰写本文时,上述问题的现有解决方案可以在以下位置找到:
任务 |
实现 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
解决主要问题¶
积分基底¶
- sympy.polys.numberfields.basis.round_two(T, radicals=None)[源代码][源代码]¶
Zassenhaus 的“第二轮”算法。
- 参数:
- T
Poly
,AlgebraicField
要么 (1) 定义数域的不可约多项式在 ZZ 或 QQ 上,要么 (2) 一个表示数域本身的
AlgebraicField
。- 部首dict, 可选
这是一种让任何 \(p\)-根(如果计算了)通过引用返回的方式。如果需要,可以传递一个空字典。如果算法运行到计算整数环 \(Z_K\) 的 \(p\)-幂零根模 \(p\) 的阶段,那么这个理想的 \(\mathbb{F}_p\)-基将被存储在这个字典中,键为
p
。这对于其他算法(如素数分解)可能很有用。
- T
- 返回:
- 对
(ZK, dK)
,其中: ZK
是一个Submodule
,表示最大阶。dK
是域 \(K = \mathbb{Q}[x]/(T(x))\) 的判别式。
- 对
参考文献
[1]Cohen, H. 计算代数数论课程.
示例
通过代数域工作:
>>> 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]]}
质因数分解¶
- sympy.polys.numberfields.primes.prime_decomp(
- p,
- T=None,
- ZK=None,
- dK=None,
- radical=None,
计算有理素数 p 在数域中的分解。
- 参数:
- 返回:
- 列表
PrimeIdeal
实例。
- 列表
参考文献
[1]Cohen, H. 计算代数数论课程. (参见算法6.2.9.)
示例
>>> 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 ]]
- class sympy.polys.numberfields.primes.PrimeIdeal(ZK, p, alpha, f, e=None)[源代码][源代码]¶
环中代数整数的一个素理想。
- 属性:
is_inert
判断我们除以的有理素数是否为惰性,即
方法
将这个素理想表示为一个
子模
。reduce_ANP
(a)将
ANP
减少到这个素理想模下的“小代表”。将一个
AlgebraicNumber
减少到这个素理想的“小代表”模。reduce_element
(elt)将
PowerBasisElement
减少到此素理想模下的“小代表”。repr
([field_gen, just_gens])打印这个素理想的表示。
计算此素理想的测试因子。
valuation
(I)计算整理想 I 在这个素理想上的 $mathfrak{p}$-adic 赋值。
- __init__(ZK, p, alpha, f, e=None)[源代码][源代码]¶
- 参数:
- ZK子模块
这个理想存在的最大阶数。
- p整数
这个理想所整除的有理素数。
- alpha
PowerBasisElement
使得理想值等于
p*ZK + alpha*ZK
。- f整数
惯性度。
- e : int,
None
, 可选整数 分支指数,如果已经知道的话。如果为
None
,我们将在这里计算它。
- as_submodule()[源代码][源代码]¶
将这个素理想表示为一个
子模
。- 返回:
Submodule
将等于
self.p * self.ZK + self.alpha * self.ZK
。
示例
>>> 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
。在下一个等式中,我们回顾了添加理想值会得到它们的GCD。这次,我们需要在右边进行有意的转换为Submodule
:>>> print(P0 + 7*P0.ZK == P0.as_submodule()) True
- property is_inert¶
判断我们除以的有理素数是否是惰性的,即在我们整数环中保持素数。
- reduce_alg_num(a)[源代码][源代码]¶
将一个
AlgebraicNumber
减少到这个素理想的“小代表”模。- 参数:
- elt :
代数数
代数数 要减少的元素。
- elt :
- 返回:
AlgebraicNumber
简化后的元素。
- reduce_element(elt)[源代码][源代码]¶
将
PowerBasisElement
减少到此素理想模下的“小代表”。- 参数:
- elt
PowerBasisElement
要减少的元素。
- elt
- 返回:
PowerBasisElement
简化后的元素。
- repr(field_gen=None, just_gens=False)[源代码][源代码]¶
打印这个素理想的表示。
- 参数:
- field_gen :
Symbol
,None
, 可选 (默认=None)符号, 无, 可选 (默认=无) 用于字段生成器的符号。这将出现在我们对
self.alpha
的表示中。如果为None
,我们使用self.ZK
的定义多项式的变量。- just_gensbool, 可选 (默认=False)
如果
True
,则只打印“(p, alpha)”部分,显示素理想“仅生成元”。否则,打印形式为“[ (p, alpha) e=…, f=… ]”的字符串,给出分歧指数和惯性度,以及生成元。
- field_gen :
示例
>>> 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)
p-adic 赋值¶
- sympy.polys.numberfields.primes.prime_valuation(I, P)[源代码][源代码]¶
计算整理想数 I 的 P-adic 赋值。
- 参数:
- 我 :
Submodule
子模块 一个期望求其赋值的整理想法。
- P素理想
计算估值的质数。
- 我 :
- 返回:
- 整数
参考文献
[1]Cohen, H. 计算代数数论课程. (参见算法4.8.17.)
示例
>>> 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
伽罗瓦群¶
- sympy.polys.numberfields.galoisgroups.galois_group(
- f,
- *gens,
- by_name=False,
- max_tries=30,
- randomize=False,
- **args,
计算次数不超过6的多项式 f 的伽罗瓦群。
- 参数:
- f表达式
- 生成可选的符号列表
用于将 f 转换为 Poly,并将传递给
poly_from_expr()
函数。- 按名称bool, 默认 False
如果
True
,伽罗瓦群将按名称返回。否则,它将作为PermutationGroup
返回。- max_triesint, 默认 30
在这些涉及生成Tschirnhausen变换的步骤中,最多进行这么多次尝试。
- 随机化bool, 默认 False
如果
True
,则在生成Tschirnhausen变换时使用随机系数。否则,尝试按固定顺序进行变换。两种方法都从小系数和度数开始,并向上工作。- 参数可选的
用于将 f 转换为 Poly,并将传递给
poly_from_expr()
函数。
- 返回:
- 对
(G, alt)
第一个元素
G
表示伽罗瓦群。如果 by_name 为True
,它是sympy.combinatorics.galois.S1TransitiveSubgroups
sympy.combinatorics.galois.S2TransitiveSubgroups
等枚举类的一个实例;如果为False
,则是一个PermutationGroup
。第二个元素是一个布尔值,表示该组是否包含在交错群 \(A_n\) 中(\(n\) 是 T 的度数)。
- 对
- Raises:
- 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.S1TransitiveSubgroups
、sympy.combinatorics.galois.S2TransitiveSubgroups
等的值。
寻找最小多项式¶
- sympy.polys.numberfields.minpoly.minimal_polynomial(
- ex,
- x=None,
- compose=True,
- polys=False,
- domain=None,
计算代数元素的最小多项式。
- 参数:
- 示例表达式
要计算其最小多项式的元素或表达式。
- x符号, 可选
最小多项式的自变量
- 组合布尔值,可选(默认=True)
用于计算最小多项式的方法。如果
compose=True``(默认),则使用 ``_minpoly_compose
,如果compose=False
,则使用 Groebner 基。- 多边形布尔值,可选(默认=False)
如果
True
返回一个Poly
对象,否则返回一个Expr
对象。- 领域域, 可选
基础领域
注释
默认情况下
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表达式
任何表示代数数的表达式。
- b表达式
任何表示代数数的表达式。
- 快速布尔值,可选(默认=True)
如果
True
,我们首先尝试一种可能更快的计算同构的方法,如果失败则回退到一种较慢的方法。如果False
,我们直接使用较慢的方法,该方法保证返回结果。
- 返回:
- 有理数列表,或 None
如果 \(\mathbb{Q}(a)\) 与 \(\mathbb{Q}(b)\) 的某个子域不同构,则返回
None
。否则,返回一个有理数列表,表示 \(\mathbb{Q}(b)\) 中的一个元素,该元素可以映射 \(a\),以定义一个单态,即从 \(\mathbb{Q}(a)\) 到 \(\mathbb{Q}(b)\) 的某个子域的同构。列表中的元素是 \(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,
在给定多个生成元的情况下,找到一个数域的单一生成元。
- 参数:
- 返回:
- 配对 (f, coeffs) 或三元组 (f, coeffs, reps),其中:
f
是本原元素的最小多项式。coeffs
给出了本原元素作为给定生成元的线性组合。reps
仅在传递参数ex=True
时存在,并且是一个有理数列表的列表。每个列表给出了本原元素的下降幂的系数,以恢复原始的给定生成元之一。
示例
>>> 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}\) 恢复为原始元素 \(\sqrt{2} + \sqrt{3}\) 的幂次的 \(\mathbb{Q}\)-线性组合。>>> 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,
在由另一个代数数生成的域中表示一个代数数。
- 参数:
- 扩展 :
Expr
或Expr
列表Expr 或 Expr 列表 要么是要在另一个域中表示的代数数,要么是一个代数数列表,其本原元素要在另一个域中表示。
- theta :
Expr
, None, 可选 (默认=None)Expr, None, 可选 (默认=None) 如果是一个表示代数数的
Expr
,其行为如 解释 部分所述。如果是None
,则此函数简化为对extension
调用primitive_element()
并将计算出的原始元素转换为AlgebraicNumber
的简写。- gen :
Symbol
, None, 可选 (默认=None)符号, 无, 可选 (默认=无) 如果提供,这将作为返回的
AlgebraicNumber
中极小多项式的生成元符号。- 别名 : str,
Symbol
, None, 可选 (默认=None)str,Symbol
, None, optional (default=None) 如果提供,这将用作返回的
AlgebraicNumber
的别名符号。
- 扩展 :
- 返回:
- 代数数
属于 \(\mathbb{Q}(\theta)\) 且等于 \(\eta\)。
- Raises:
- 同构失败
如果 \(\eta \not\in \mathbb{Q}(\theta)\)。
示例
>>> 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()
展示了如何将 \(\eta\) 写成 \(\theta\) 的降幂的 \(\mathbb{Q}\)-线性组合。
内部机制¶
代数数域¶
代数数域在SymPy中由 AlgebraicField
类表示,它是 多项式域系统 的一部分。
表示代数数¶
表示代数数有几种不同的方法,不同的形式可能适用于不同的计算任务。参见 [Cohen93],第 4.2 节。
作为数字字段元素¶
在 SymPy 中,一方面,数字和表达式类定义在 sympy.core.numbers
模块中,另一方面,域和域元素定义在 polys
模块中。这方面的更多细节在 这里 有详细解释。
说到代数数,sympy.core.numbers
模块提供了 AlgebraicNumber
类,而 polys
模块提供了 ANP
类。这是属于 AlgebraicField
域的元素类型。
作为有限生成模的元素¶
在计算代数数论中,有限生成的 \(\mathbb{Z}\)-模是至关重要的。例如,每个序_和每个理想_都是这样的模。
特别是,数域中的最大阶——或称`整数环`_——是一个有限生成的\(\mathbb{Z}\)-模,其生成元构成该域的`整基`_。
允许我们表示这些模块及其元素的类在 modules
模块中提供。在这里,ModuleElement
类提供了另一种表示代数数的方式。
有限生成的模¶
数域中的模。
这里定义的类允许我们处理有限生成的自由模,其生成元是代数数。
有一个名为 Module
的抽象基类,它有两个具体子类,分别是 PowerBasis
和 Submodule
。
每个模块由其基础或生成器集合定义:
对于
PowerBasis
,生成器是代数整数 \(\theta\) 的前 \(n\) 次幂(从第零次开始),其中 \(\theta\) 的次数为 \(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)
因此,每个模块要么是一个 PowerBasis
,要么是一个 Submodule
,其某个祖先是一个 PowerBasis
。(如果 S
是一个 Submodule
,那么它的祖先是 S.parent
、S.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)
The 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}\)-线性组合。只有当子模块在乘法下封闭时,这一过程才会成功。
模同态¶
许多重要的数论算法需要计算一个或多个模同态的核。因此,我们提供了几个轻量级类,ModuleHomomorphism
、ModuleEndomorphism
、InnerEndomorphism
和 EndomorphismRing
,它们提供了支持这一点所需的最小必要机制。
类参考¶
- class sympy.polys.numberfields.modules.Module[源代码][源代码]¶
通用有限生成的模块。
这是一个抽象基类,不应直接实例化。两个具体的子类是
PowerBasis
和Submodule
。每个
Submodule
都源自另一个模块,通过其parent
属性引用。如果S
是一个子模块,那么我们将S.parent
、S.parent.parent
等称为S
的“祖先”。因此,每个Module
要么是PowerBasis
,要么是Submodule
,其某个祖先是PowerBasis
。- 属性:
n
此模块的生成器数量。
number_field
返回相关的
AlgebraicField
,如果有的话。parent
该模块的父模块(如果有)。
方法
__call__
(spec[, denom])生成一个属于此模块的
ModuleElement
。ancestors
([include_self])返回此模块的祖先模块列表,从基础的
PowerBasis
向下,可选地包括self
。获取作为此模块生成器的
ModuleElement
列表。返回一个表示有理数的
ModuleElement
。形成此模块的
EndomorphismRing
。is_compat_col
(col)判断 col 是否为本模块的合适列向量。
mult_tab
()获取此模块的乘法表(如果它在乘法下是封闭的)。
nearest_common_ancestor
(other)定位此模块与另一个模块的最近共同祖先。
one
()返回一个
ModuleElement
表示单位元,并且属于此模块的第一个祖先(包括自身),该祖先从单位元开始。返回作为此模块祖先的
PowerBasis
。represent
(elt)将模块元素表示为该模块生成元的整数线性组合。
判断模块的第一个生成器是否等于一。
submodule_from_gens
(gens[, hnf, hnf_modulus])从属于此模块的
ModuleElement
列表生成的子模块。submodule_from_matrix
(B[, denom])通过矩阵的列所指示的该模块的元素生成子模块,带有可选的分母。
返回一个等于此整个模块的子模块。
zero
()返回一个表示零的
ModuleElement
。- __call__(spec, denom=1)[源代码][源代码]¶
生成一个属于此模块的
ModuleElement
。- 参数:
- spec
DomainMatrix
, int 指定
ModuleElement
系数中的分子。可以是 ZZ 上的列向量,其长度必须等于该模块的生成元数量 \(n\),或者是一个整数j
,\(0 \leq j < n\),这是 \(n \times n\) 单位矩阵 \(I_n\) 中第 \(j\) 列的简写。- denomint, 可选 (默认=1)
系数分母为
ModuleElement
。
- spec
- 返回:
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
。参见
- basis_elements()[源代码][源代码]¶
获取作为此模块生成器的
ModuleElement
列表。
- element_from_rational(a)[源代码][源代码]¶
返回一个表示有理数的
ModuleElement
。- 参数:
- a整数
- 返回:
示例
>>> 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
。
- mult_tab()[源代码][源代码]¶
获取此模块的乘法表(如果它在乘法下是封闭的)。
- 返回:
- 字典的字典的列表
- Raises:
- ClosureFailure
如果该模块在乘法下不封闭。
示例
>>> 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¶
此模块的生成器数量。
- property number_field¶
返回相关的
AlgebraicField
,如果有的话。- 返回:
AlgebraicField
,None
- one()[源代码][源代码]¶
返回一个
ModuleElement
表示单位元,并且属于此模块的第一个祖先(包括自身),该祖先从单位元开始。
- power_basis_ancestor()[源代码][源代码]¶
返回作为此模块祖先的
PowerBasis
。参见
- represent(elt)[源代码][源代码]¶
将模块元素表示为该模块生成元的整数线性组合。
- 参数:
- elt模块元素
要表示的模块元素。必须属于此模块的某个祖先模块(包括此模块本身)。
- 返回:
DomainMatrix
在 ZZ 上这将是一个列向量,表示该模块生成元的线性组合的系数,该组合等于给定的元素。
- Raises:
- ClosureFailure
如果给定的元素不能表示为该模块上的 ZZ-线性组合。
示例
>>> 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_from_gens(
- gens,
- hnf=True,
- hnf_modulus=None,
从属于此模块的
ModuleElement
列表生成的子模块。- 参数:
- gens : 属于此模块的
ModuleElement
列表。列表 - hnf布尔值,可选(默认=True)
如果为真,我们将在形成
Submodule
之前将矩阵简化为 Hermite 正规形式。- hnf_modulusint, None, 可选 (默认=None)
在 HNF 约简算法中使用的模数。参见
hermite_normal_form()
。
- gens : 属于此模块的
- 返回:
示例
>>> 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(B, denom=1)[源代码][源代码]¶
通过矩阵的列所指示的该模块的元素生成子模块,带有可选的分母。
- 参数:
- B :
DomainMatrix
在 ZZ 上DomainMatrix 在 ZZ 上 每一列给出了子模块的一个生成元的系数的分子。因此,B 的行数必须等于当前模块的生成元数。
- denomint, 可选 (默认=1)
所有子模块生成器的共同点。
- B :
- 返回:
- Raises:
- 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
- zero()[源代码][源代码]¶
返回一个表示零的
ModuleElement
。
- class sympy.polys.numberfields.modules.PowerBasis(T)[源代码][源代码]¶
由代数整数的幂生成的模块。
- 属性:
n
此模块的生成器数量。
number_field
返回相关的
AlgebraicField
,如果有的话。parent
该模块的父模块(如果有)。
方法
__call__
(spec[, denom])生成一个属于此模块的
ModuleElement
。ancestors
([include_self])返回此模块的祖先模块列表,从基础的
PowerBasis
向下,可选地包括self
。basis_elements
()获取作为此模块生成器的
ModuleElement
列表。将一个 ANP 转换为 PowerBasisElement。
将一个 AlgebraicNumber 转换为 PowerBasisElement。
生成此模块的一个元素,表示 f 在约化模我们定义的最小多项式之后的值。
element_from_rational
(a)endomorphism_ring
()形成此模块的
EndomorphismRing
。is_compat_col
(col)判断 col 是否为本模块的合适列向量。
mult_tab
()nearest_common_ancestor
(other)定位此模块与另一个模块的最近共同祖先。
one
()返回一个
ModuleElement
表示单位元,并且属于此模块的第一个祖先(包括自身),该祖先从单位元开始。power_basis_ancestor
()返回作为此模块祖先的
PowerBasis
。represent
(elt)将模块元素表示为该模块生成元的整数线性组合。
starts_with_unity
()submodule_from_gens
(gens[, hnf, hnf_modulus])从属于此模块的
ModuleElement
列表生成的子模块。submodule_from_matrix
(B[, denom])通过矩阵的列所指示的该模块的元素生成子模块,带有可选的分母。
whole_submodule
()返回一个等于此整个模块的子模块。
zero
()返回一个表示零的
ModuleElement
。compute_mult_tab
- __init__(T)[源代码][源代码]¶
- 参数:
- T
Poly
,AlgebraicField
要么 (1) 是 ZZ 上的单项、不可约、单变量多项式,其根是幂基的生成元,要么 (2) 是一个
AlgebraicField
,其原始元素是幂基的生成元。
- T
- class sympy.polys.numberfields.modules.Submodule(parent, matrix, denom=1, mult_tab=None)[源代码][源代码]¶
另一个模块的子模块。
- 属性:
QQ_matrix
DomainMatrix
在 QQ 上,等于- 系数
- denom
- 矩阵
n
此模块的生成器数量。
number_field
返回相关的
AlgebraicField
,如果有的话。parent
该模块的父模块(如果有)。
方法
__call__
(spec[, denom])生成一个属于此模块的
ModuleElement
。add
(other[, hnf, hnf_modulus])将此
Submodule
添加到另一个中。ancestors
([include_self])返回此模块的祖先模块列表,从基础的
PowerBasis
向下,可选地包括self
。返回此子模块的基元素列表,作为子模块父模块的元素。
basis_elements
()获取作为此模块生成器的
ModuleElement
列表。通过丢弃给定索引 r 之前的所有生成器来生成一个新模块。
element_from_rational
(a)endomorphism_ring
()形成此模块的
EndomorphismRing
。is_compat_col
(col)判断 col 是否为本模块的合适列向量。
mul
(other[, hnf, hnf_modulus])将这个
Submodule
乘以一个有理数、一个ModuleElement
或另一个Submodule
。mult_tab
()nearest_common_ancestor
(other)定位此模块与另一个模块的最近共同祖先。
one
()返回一个
ModuleElement
表示单位元,并且属于此模块的第一个祖先(包括自身),该祖先从单位元开始。power_basis_ancestor
()返回作为此模块祖先的
PowerBasis
。reduce_element
(elt)如果子模 $B$ 在方阵、最大秩的 Hermite 标准形式下具有定义矩阵 $W$,那么,给定父模 $A$ 中的元素 $x$,我们生成一个元素 $y in A$,使得 $x - y in B$,并且 $y$ 的第 $i$ 个坐标满足 $0 leq y_i < w_{i,i}$。
reduced
()生成此子模块的简化版本。
represent
(elt)将模块元素表示为该模块生成元的整数线性组合。
starts_with_unity
()submodule_from_gens
(gens[, hnf, hnf_modulus])从属于此模块的
ModuleElement
列表生成的子模块。submodule_from_matrix
(B[, denom])通过矩阵的列所指示的该模块的元素生成子模块,带有可选的分母。
whole_submodule
()返回一个等于此整个模块的子模块。
zero
()返回一个表示零的
ModuleElement
。compute_mult_tab
is_compat_submodule
is_power_basis_submodule
is_sq_maxrank_HNF
- __init__(
- parent,
- matrix,
- denom=1,
- mult_tab=None,
- 参数:
- 父级 :
Module
模块 从中派生出此模块的模块。
- 矩阵 :
DomainMatrix
在 ZZ 上DomainMatrix 在 ZZ 上 定义此子模块生成器的矩阵,其列是父生成器上的线性组合。
- denomint, 可选 (默认=1)
矩阵给出的系数的分母。
- mult_tab : dict,
None
, 可选字典, 如果已知,可以提供此模块的乘法表。
- 父级 :
- property QQ_matrix¶
DomainMatrix
在 QQ 上,等于self.matrix / self.denom
,并保证是密集的。- 返回:
DomainMatrix
在 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)[源代码][源代码]¶
将此
Submodule
添加到另一个中。- 参数:
- 其他 :
子模块
子模块 - hnf布尔值,可选(默认=True)
如果
True
,将组合模块的矩阵简化为它的 Hermite 正规形式。- hnf_modulus : ZZ, None, 可选ZZ, 无, 可选
如果提供了一个正整数,将其用作 HNF 约简中的模数。参见
hermite_normal_form()
。
- 其他 :
- 返回:
- mul(other, hnf=True, hnf_modulus=None)[源代码][源代码]¶
将这个
Submodule
乘以一个有理数、一个ModuleElement
或另一个Submodule
。- 参数:
- 其他 : int, ZZ, QQ,
ModuleElement
,Submodule
整数 - hnf布尔值,可选(默认=True)
如果
True
,将乘积模块的矩阵简化为 Hermite 正规形式。- hnf_modulus : ZZ, None, 可选ZZ, 无, 可选
如果提供了一个正整数,将其用作 HNF 约简中的模数。参见
hermite_normal_form()
。
- 其他 : int, ZZ, QQ,
- 返回:
- 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\) 中的每个元素在此过程中都会归约到它。
- 参数:
- elt模块元素
此子模块的父模块的一个元素。
- 返回:
- elt模块元素
此子模块的父模块的一个元素。
- Raises:
- NotImplementedError
如果给定的
ModuleElement
不属于此子模块的父模块。- StructureError
如果此子模块的定义矩阵不是方阵,最大秩的Hermite标准形式。
参考文献
[Cohen00]Cohen, H. 计算数论中的高级主题.
示例
>>> 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]
- class sympy.polys.numberfields.modules.ModuleElement(module, col, denom=1)[源代码][源代码]¶
表示
Module
的一个元素。注意:不应直接构造。请使用
__call__()
方法或make_mod_elt()
工厂函数代替。- 属性:
QQ_col
DomainMatrix
在 QQ 上,等于- 系数
n
此元素列的长度。
方法
column
([domain])获取此元素的列副本,可选择转换为域。
equiv
(other)一个
ModuleElement
可以测试为与一个有理数或其他ModuleElement
等价,如果它们表示相同的代数数。from_int_list
(module, coeffs[, denom])从整数列表(而不是列向量)创建一个
ModuleElement
。is_compat
(other)测试其他是否是具有相同模块的另一个
ModuleElement
。转换为我们的
PowerBasis
祖先上的PowerBasisElement
。reduced
()生成此 ModuleElement 的简化版本,即分母与所有分子系数的最大公约数为 1 的版本。
生成一个
ModuleElement
的版本,其中所有分子系数都已对 p 取模。to_ancestor
(anc)转换为属于此元素模块的给定祖先的
ModuleElement
。转换为属于此元素模块的父级的
ModuleElement
。unify
(other)尝试创建一对兼容的
ModuleElement
,一个等同于此,另一个等同于另一个。- __init__(module, col, denom=1)[源代码][源代码]¶
- 参数:
- 模块 :
Module
模块 此元素所属的模块。
- col :
DomainMatrix
在 ZZ 上DomainMatrix 在 ZZ 上 给出此元素系数分子的列向量。
- denomint, 可选 (默认=1)
此元素系数的分母。
- 模块 :
- __add__(other)[源代码][源代码]¶
一个
ModuleElement
可以被添加到一个有理数,或者另一个ModuleElement
。
- __mul__(other)[源代码][源代码]¶
一个
ModuleElement
可以乘以一个有理数,或者乘以另一个ModuleElement
。
- __mod__(m)[源代码][源代码]¶
将这个
ModuleElement
模一个Submodule
。
- property QQ_col¶
DomainMatrix
在 QQ 上,等于self.col / self.denom
,并且保证是稠密的。
- equiv(other)[源代码][源代码]¶
一个
ModuleElement
可以测试为与一个有理数或其他ModuleElement
等价,如果它们表示相同的代数数。- 参数:
- 其他 : int, ZZ, QQ,
ModuleElement
整数
- 其他 : int, ZZ, QQ,
- 返回:
- 布尔
- Raises:
- 统一失败
如果
self
和other
没有共享一个共同的PowerBasis
祖先。
- classmethod from_int_list(
- module,
- coeffs,
- denom=1,
从整数列表(而不是列向量)创建一个
ModuleElement
。
- is_compat(other)[源代码][源代码]¶
测试其他是否是具有相同模块的另一个
ModuleElement
。
- property n¶
此元素列的长度。
- over_power_basis()[源代码][源代码]¶
转换为我们的
PowerBasis
祖先上的PowerBasisElement
。
- reduced_mod_p(p)[源代码][源代码]¶
生成一个
ModuleElement
的版本,其中所有分子系数都已对 p 取模。
- to_ancestor(anc)[源代码][源代码]¶
转换为属于此元素模块的给定祖先的
ModuleElement
。- 参数:
- anc模块
- to_parent()[源代码][源代码]¶
转换为属于此元素模块的父级的
ModuleElement
。
- unify(other)[源代码][源代码]¶
尝试创建一对兼容的
ModuleElement
,一个等同于此,另一个等同于另一个。- 返回:
- 配对
(e1, e2)
每个
ei
是一个ModuleElement
,它们属于同一个Module
,e1
等同于self
,而e2
等同于other
。
- 配对
- Raises:
- 统一失败
如果
self
和other
没有共同的祖先模块。
- class sympy.polys.numberfields.modules.PowerBasisElement(module, col, denom=1)[源代码][源代码]¶
用于
ModuleElement
实例的子类,其模块是PowerBasis
。- 属性:
QQ_col
DomainMatrix
在 QQ 上,等于T
访问
PowerBasis
的定义多项式。- 系数
generator
返回一个
Symbol
,用于在将此元素表示为多项式时使用。is_rational
判断此元素是否表示一个有理数。
n
此元素列的长度。
方法
as_expr
([x])从
self
创建一个基本表达式。column
([domain])获取此元素的列副本,可选择转换为域。
equiv
(other)一个
ModuleElement
可以测试为与一个有理数或其他ModuleElement
等价,如果它们表示相同的代数数。from_int_list
(module, coeffs[, denom])从整数列表(而不是列向量)创建一个
ModuleElement
。is_compat
(other)测试其他是否是具有相同模块的另一个
ModuleElement
。norm
([T])计算这个数的范数。
numerator
([x])将分子作为多项式从 ZZ 中获取。
over_power_basis
()转换为我们的
PowerBasis
祖先上的PowerBasisElement
。poly
([x])将数字作为 QQ 上的多项式获取。
reduced
()生成此 ModuleElement 的简化版本,即分母与所有分子系数的最大公约数为 1 的版本。
reduced_mod_p
(p)生成一个
ModuleElement
的版本,其中所有分子系数都已对 p 取模。to_ANP
()转换为等效的
ANP
。尝试转换为等价的
AlgebraicNumber
。to_ancestor
(anc)转换为属于此元素模块的给定祖先的
ModuleElement
。to_parent
()转换为属于此元素模块的父级的
ModuleElement
。unify
(other)尝试创建一对兼容的
ModuleElement
,一个等同于此,另一个等同于另一个。反向
- property T¶
访问
PowerBasis
的定义多项式。
- property generator¶
返回一个
Symbol
,用于在将此元素表示为多项式时使用。如果我们有一个关联的
AlgebraicField
,其原始元素有一个别名符号,我们使用该符号。否则,我们使用定义我们所属的幂基的最小多项式的变量。
- property is_rational¶
判断此元素是否表示一个有理数。
- to_alg_num()[源代码][源代码]¶
尝试转换为等价的
AlgebraicNumber
。- 返回:
- Raises:
- StructureError
如果这个元素所属的
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,
- 参数:
示例
>>> 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)
- class sympy.polys.numberfields.modules.ModuleEndomorphism(domain, mapping)[源代码][源代码]¶
从一个模块到自身的同态。
方法
kernel
([modulus])计算一个表示此同态核的子模块。
matrix
([modulus])计算这个同态的矩阵。
- class sympy.polys.numberfields.modules.InnerEndomorphism(domain, multiplier)[源代码][源代码]¶
一个模块上的内自同态,即对应于固定元素乘法的自同态。
方法
kernel
([modulus])计算一个表示此同态核的子模块。
matrix
([modulus])计算这个同态的矩阵。
- __init__(domain, multiplier)[源代码][源代码]¶
- 参数:
- 域 :
Module
模块 自同态的定义域和陪域。
- 乘数 :
ModuleElement
模块元素 定义映射的元素 \(a\) 为 \(x \mapsto a x\)。
- 域 :
- class sympy.polys.numberfields.modules.EndomorphismRing(domain)[源代码][源代码]¶
模上的自同态环。
方法
inner_endomorphism
(multiplier)构成属于这个自同态环的内自同态。
represent
(element)将这个自同态环的一个元素表示为一个单列向量。
- inner_endomorphism(multiplier)[源代码][源代码]¶
构成属于这个自同态环的内自同态。
- 参数:
- 乘数 :
ModuleElement
模块元素 元素 \(a\) 定义了内自同态 \(x \mapsto a x\)。
- 乘数 :
- 返回:
- represent(element)[源代码][源代码]¶
将这个自同态环的一个元素表示为一个单列向量。
- 参数:
- 元素 : 属于此环的
ModuleEndomorphism
。属于此环的模块自同态。
- 元素 : 属于此环的
- 返回:
DomainMatrix
列向量等于表示给定 元素 作为映射的矩阵的所有列的垂直堆叠。
示例
请注意,在这些示例中我们打印矩阵的转置,以便更容易检查它们的列。
>>> 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^2\),依此类推。
自同态环
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)
当我们想要考虑一个同态 \(\varphi\) 以
E
为陪域时,这很有用:>>> 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模块元素
要找到其最小多项式的元素,其模块具有乘法并从单位元开始。
- 域 :
Domain
领域 多项式所需的定义域。
- x :
Symbol
, 可选符号, 可选 多项式所需的变量。
- 权力列表,可选
如果需要,传递一个空列表。在计算过程中,从零次到最小多项式次数的 alpha 的幂(作为
ModuleElement
实例)将被记录在这里。
- 返回:
Poly
,None
alpha 的最小多项式,如果在所需域上找不到多项式,则为
None
。
- Raises:
- MissingUnityError
如果alpha所属的模块不以unity开头。
- ClosureFailure
如果alpha所属的模块在乘法下不封闭。
示例
对于第 \(n\) 个分圆域,\(n\) 是一个奇素数,考虑其根为长度 \((n-1)/2\) 的两个周期的二次方程。高斯的文章 356 告诉我们,根据 \(n\) 是 1 还是 3 mod 4,我们应分别得到 \(x^2 + x - (n-1)/4\) 或 \(x^2 + 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.get_num_denom(c)[源代码][源代码]¶
给定任何
is_rat()
为True
的参数,返回该数字的分子和分母。参见
- sympy.polys.numberfields.utilities.extract_fundamental_discriminant(a)[源代码][源代码]¶
从一个整数 a 中提取一个基本判别式。
- 参数:
- a: int, 必须是 0 或 1 mod 4
- 返回:
- 字典
(D, F)
对。
- 字典
- Raises:
- ValueError
如果 a 不是 0 或 1 mod 4。
参考文献
[1]Cohen, H. 计算代数数论课程. (参见命题 5.1.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}
- class sympy.polys.numberfields.utilities.AlgIntPowers(T, modulus=None)[源代码][源代码]¶
计算代数整数的幂。
方法
compute_up_through
获取
红色
参考文献
[1]Cohen, H. 计算代数数论课程.
示例
>>> 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]
- sympy.polys.numberfields.utilities.coeff_search(m, R)[源代码][源代码]¶
生成用于多项式搜索的系数。
- 参数:
- m整数
系数列表的长度。
- R整数
系数初始最大绝对值(随着搜索进行会增加)。
- 返回:
- 生成器
无限生成系数列表的生成器。
示例
>>> 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
这些列提供了子空间的基。
- M
- 返回:
DomainMatrix
这个矩阵是可逆的,并且它的前 \(r\) 列等于 M。
- Raises:
- DMRankError
如果 M 不是最大秩。
参考文献
[1]Cohen, H. 计算代数数论课程 (参见第2.3.2节.)
示例
注意:该函数以列为单位工作,因此在这些示例中我们打印矩阵的转置,以便更容易检查列。
>>> 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]])
- sympy.polys.numberfields.utilities.isolate(alg, eps=None, fast=False)[源代码][源代码]¶
为实代数数找到一个合理的隔离区间。
- 参数:
- algstr, int,
Expr
要隔离的代数数。必须是一个实数,才能使用这个特定的函数。不过,也可以参考
Poly.intervals()
,当你传递all=True
时,它会隔离复数根。- eps : QQ 的正元素, None, 可选 (默认=None)积极的元素
传递给
Poly.refine_root()
的精度- 快速布尔值,可选(默认=False)
说明是否应使用快速细化程序。(将传递给
Poly.refine_root()
。)
- algstr, int,
- 返回:
- 一对有理数定义了一个给定数的隔离区间
- 代数数。
示例
>>> from sympy import isolate, sqrt, Rational >>> print(isolate(sqrt(2))) (1, 2) >>> print(isolate(sqrt(2), eps=Rational(1, 100))) (24/17, 17/12)