SymPy-1-13-中文文档-二十五-
SymPy 1.13 中文文档(二十五)
AGCA - 代数几何和交换代数模块
简介
代数几何是两种地中海文化理念的融合。它是阿拉伯科学中求解方程轻松计算的超越,与希腊的位置和形状艺术的叠加。这种编织最初在欧洲土地上产生,并在国际时尚的影响下不断完善。代数几何研究几何可信和代数可能之间的微妙平衡。每当这数学跷跷板的一边超过另一边时,人们立即失去兴趣并寻找更激动人心的娱乐。
—George R. Kempf(1944 – 2002)
代数几何通过代数方法(有时反之亦然)研究几何问题。虽然这是一个相当古老的主题,但当今理解的代数几何在很大程度上是 20 世纪的发展。在如 Riemann 和 Dedekind 的思想基础上,人们意识到多项式方程组的解集(称为代数变量)的性质与在该变量上的多项式函数集的行为(称为坐标环)之间存在密切联系。
在许多几何学科中,我们可以区分局部和全局的问题(及其方法)。代数几何中的局部研究基本上等同于研究某些环、它们的理想和模。后一主题也称为交换代数。它是代数几何学家的基本局部工具集,类似于微分分析是微分几何学家的局部工具集。
有关交换代数的良好概念介绍可以参考[Atiyah69]。更注重计算的介绍,以及该模块中大多数算法所依赖的工作,可以参考[Greuel2008]。
该模块的最终目标是允许在经典情况下(在一个域上)和更现代的算术情况下表达和解决局部和全局的几何问题。然而,到目前为止,几何功能还没有实现。当前,该模块仅提供关于域上的计算交换代数的工具。
所有代码示例假定
>>> from sympy import *
>>> x, y, z = symbols('x,y,z')
>>> init_printing(use_unicode=True)
参考资料
在本节中,我们记录了 AGCA 模块的使用方法。为了方便读者,我们插入了一些定义、例子和解释。
基础环
在交换代数中,几乎所有计算都是相对于“基础环”进行的。(例如,当询问一个理想的问题时,基础环是理想的子集。)原则上,所有“多项式域”都可以用作基础环。然而,实际上,只有在域上的多项式环及其各种局部化和商环中实现了有用的功能。
正如下面的示例所示,创建你感兴趣的对象的最便捷方法是从基地领域中构建它们,然后使用各种方法从旧对象中创建新对象。例如,在有理数域(\mathbb{Q})上,在原点处创建尖点立方体(y² = x³)的局部环:
>>> lr = QQ.old_poly_ring(x, y, order="ilex") / [y**2 - x**3]
>>> lr
ℚ[x, y, order=ilex]
───────────────────
╱ 3 2╲
╲- x + y ╱
注意如何使用 Python 列表表示法作为表达理想的捷径。您可以使用convert
方法将普通的 sympy 对象转换为 AGCA 模块理解的对象(尽管在许多情况下,这将自动完成 - 例如,列表被自动转换为理想,并在此过程中,符号(x)和(y)被自动转换为其他表示)。例如:
>>> X, Y = lr.convert(x), lr.convert(y) ; X
╱ 3 2╲
x + ╲- x + y ╱
>>> x**3 == y**2
False
>>> X**3 == Y**2
True
当不需要局部化时,可以使用更数学化的符号。例如,让我们创建三维仿射空间(\mathbb{A}³)的坐标环:
>>> ar = QQ.old_poly_ring(x, y, z); ar
ℚ[x, y, z]
更多细节,请参考以下类文档。注意,作为域的基础环是 AGCA 模块与其他多项式模块之间的重要重叠点。所有域都在多项式参考中有详细文档,因此我们在此仅展示一个摘要版本,包含最相关 AGCA 模块的方法。
class sympy.polys.domains.ring.Ring
表示一个环域。
free_module(rank)
生成自己的等级rank
自由模块。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2)
QQ[x]**2
ideal(*gens)
生成一个self
的理想。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x**2)
<x**2>
quotient_ring(e)
形成self
的商环。
这里e
可以是一个理想或一个可迭代对象。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).quotient_ring(QQ.old_poly_ring(x).ideal(x**2))
QQ[x]/<x**2>
>>> QQ.old_poly_ring(x).quotient_ring([x**2])
QQ[x]/<x**2>
为此重载了除法运算符:
>>> QQ.old_poly_ring(x)/[x**2]
QQ[x]/<x**2>
sympy.polys.domains.polynomialring.PolynomialRing(domain_or_ring, symbols=None, order=None)
表示多变量多项式环的类。
class sympy.polys.domains.quotientring.QuotientRing(ring, ideal)
表示(交换)商环的类。
通常不应该手动实例化它,而是应该使用基础环的构造函数进行构造。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x**3 + 1)
>>> QQ.old_poly_ring(x).quotient_ring(I)
QQ[x]/<x**3 + 1>
还有更简短的版本:
>>> QQ.old_poly_ring(x)/I
QQ[x]/<x**3 + 1>
>>> QQ.old_poly_ring(x)/[x**3 + 1]
QQ[x]/<x**3 + 1>
属性:
-
环 - 基础环
-
base_ideal - 用于形成商的理想。
模、理想及其基本性质
设(A)是一个环。一个(A)-模是一个集合(M),加上两个二元操作(+: M \times M \to M)和(\times: R \times M \to M),称为加法和标量乘法。这些操作需要满足某些公理,详见例如[Atiyah69]。这样,模是向量空间((A)为域)和阿贝尔群((A = \mathbb{Z}))的直接推广。(A)-模(M)的子模是集合(N \subset M),使得二元操作限制在(N)上,并且(N)成为具有这些操作的(A)-模。
环(A)本身具有一个自然的(A)-模结构,其中模中的加法和乘法与环中的加法和乘法一致。这个(A)-模也被写作(A)。(A)的一个(A)-子模被称为(A)的理想。在代数几何中,理想非常自然地出现。更一般的模可以看作是技术上方便的“活动空间”,超越了仅仅讨论理想。
如果(M),(N)是(A)-模块,则(M \times N)具有自然的(分量方式的)(A)-模块结构。类似地,更多组分的笛卡尔积上有(A)-模块结构。 (对于类别倾向者:带有此(A)-模块结构的有限多个(A)-模块的笛卡尔积,在所有(A)-模块的类别中是有限的双积。 对于无限多个组件,它是直积(但无限直和必须以不同方式构造)。)通常,(A)-模块(M)的重复积记为(M, M², M³ \ldots),或者对于任意指数集(I)为(M^I)。
如果(A)-模块(M)称为自由,则它等价于(A)-模块(A^I),对于某个(不一定有限的)指数集(I)(关于同构定义的定义,请参见下一节)。(I)的基数称为(M)的秩;可以证明这是良定义的。通常情况下,AGCA 模块只与有限秩的自由模块及其他密切相关的模块一起使用。创建模块的最简单方法是使用它们由对象的成员方法构成。例如,让我们在上面创建的(\mathbb{A}²)的坐标环上创建一个秩为 4 的自由模块,以及一个子模块:
>>> F = ar.free_module(4) ; F
4
ℚ[x, y, z]
>>> S = F.submodule([1, x, x**2, x**3], [0, 1, 0, y]) ; S
╱⎡ 2 3⎤ ╲
╲⎣1, x, x , x ⎦, [0, 1, 0, y]╱
注意 Python 列表可以用作模块元素(向量)的快捷表示法。通常,convert
方法可用于将 sympy/python 对象转换为内部 AGCA 表示(参见下面的详细参考)。
这里是模块、自由模块和子模块的详细文档:
class sympy.polys.agca.modules.Module(ring)
模块的抽象基类。
不要实例化 - 而是使用显式构造函数:
>>> from sympy import QQ
>>> from sympy.abc import x
>>> QQ.old_poly_ring(x).free_module(2)
QQ[x]**2
属性:
-
dtype - 元素类型
-
ring - 包含环
未实现的方法:
-
子模块
-
商模块
-
is_zero
-
is_submodule
-
multiply_ideal
子类中的convert
方法可能需要更改。
contains(elem)
如果elem
是该模块的元素,则返回 True。
convert(elem, M=None)
将elem
转换为该模块的内部表示。
如果M
不是None
,则应该是包含它的模块。
identity_hom()
返回self
上的单位同态。
is_submodule(other)
如果other
是self
的子模块,则返回 True。
is_zero()
如果self
是零模块,则返回 True。
multiply_ideal(other)
将self
乘以理想other
。
quotient_module(other)
生成商模块。
submodule(*gens)
生成一个子模块。
subset(other)
如果other
是self
的子集,则返回 True。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.subset([(1, x), (x, 2)])
True
>>> F.subset([(1/x, x), (x, 2)])
False
class sympy.polys.agca.modules.FreeModule(ring, rank)
自由模块的抽象基类。
附加属性:
- rank - 自由模块的秩
未实现的方法:
- 子模块
basis()
返回一组基元素。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(3).basis()
([1, 0, 0], [0, 1, 0], [0, 0, 1])
convert(elem, M=None)
将elem
转换为内部表示。
每当涉及不在内部表示中的元素时,将隐式调用此方法。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.convert([1, 0])
[1, 0]
dtype
别名为FreeModuleElement
identity_hom()
返回self
上的单位同态。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).identity_hom()
Matrix([
[1, 0], : QQ[x]**2 -> QQ[x]**2
[0, 1]])
is_submodule(other)
如果other
是self
的子模块,则返回 True。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([2, x])
>>> F.is_submodule(F)
True
>>> F.is_submodule(M)
True
>>> M.is_submodule(F)
False
is_zero()
如果self
是零模块,则返回 True。
(如果像这个实现假设的那样,系数环不是零环,那么这等价于秩为零。)
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(0).is_zero()
True
>>> QQ.old_poly_ring(x).free_module(1).is_zero()
False
multiply_ideal(other)
将self
乘以理想other
。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x)
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.multiply_ideal(I)
<[x, 0], [0, x]>
quotient_module(submodule)
返回一个商模块。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2)
>>> M.quotient_module(M.submodule([1, x], [x, 2]))
QQ[x]**2/<[1, x], [x, 2]>
或者更简洁地,使用重载的除法运算符:
>>> QQ.old_poly_ring(x).free_module(2) / [[1, x], [x, 2]]
QQ[x]**2/<[1, x], [x, 2]>
class sympy.polys.agca.modules.FreeModuleElement(module, data)
自由模块的元素。数据存储为元组。
class sympy.polys.agca.modules.SubModule(gens, container)
子模块的基类。
属性:
-
container - 包含模块
-
gens - generators (subset of containing module)
-
rank - 包含模块的秩
未实现的方法:
-
_contains
-
_syzygies
-
_in_terms_of_generators
-
_intersect
-
_module_quotient
可能需要在子类中更改的方法:
- reduce_element
convert(elem, M=None)
将elem
转换为内部表示。
大多数情况下会隐式调用。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2).submodule([1, x])
>>> M.convert([2, 2*x])
[2, 2*x]
identity_hom()
返回在self
上的恒同同态。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).identity_hom()
Matrix([
[1, 0], : <[x, x]> -> <[x, x]>
[0, 1]])
in_terms_of_generators(e)
用生成元表达元素e
。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([1, 0], [1, 1])
>>> M.in_terms_of_generators([x, x**2])
[DMP_Python([-1, 1, 0], QQ), DMP_Python([1, 0, 0], QQ)]
inclusion_hom()
返回表示self
包含映射的同态。
换句话说,从self
到self.container
的自然映射。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([x, x]).inclusion_hom()
Matrix([
[1, 0], : <[x, x]> -> QQ[x]**2
[0, 1]])
intersect(other, **options)
返回self
与子模块other
的交集。
示例
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x, y).free_module(2)
>>> F.submodule([x, x]).intersect(F.submodule([y, y]))
<[x*y, x*y]>
一些实现允许传递更多选项。目前,只有一个实现是relations=True
,在这种情况下,函数将返回三元组(res, rela, relb)
,其中res
是交集模块,rela
和relb
是系数向量列表,表示res
的生成元在self
的生成元(rela
)和other
的生成元(relb
)中的表达。
>>> F.submodule([x, x]).intersect(F.submodule([y, y]), relations=True)
(<[x*y, x*y]>, [(DMP_Python([[1, 0]], QQ),)], [(DMP_Python([[1], []], QQ),)])
上述结果说明:交集模块由单一元素((-xy, -xy) = -y (x, x) = -x (y, y))生成,其中((x, x))和((y, y))分别是被交集的两个模块的唯一生成元。
is_full_module()
如果self
是整个自由模块,则返回 True。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.submodule([x, 1]).is_full_module()
False
>>> F.submodule([1, 1], [1, 2]).is_full_module()
True
is_submodule(other)
如果other
是self
的子模块,则返回 True。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> M = F.submodule([2, x])
>>> N = M.submodule([2*x, x**2])
>>> M.is_submodule(M)
True
>>> M.is_submodule(N)
True
>>> N.is_submodule(M)
False
is_zero()
如果self
是零模块,则返回 True。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.submodule([x, 1]).is_zero()
False
>>> F.submodule([0, 0]).is_zero()
True
module_quotient(other, **options)
返回self
除以子模块other
的模块商。
换句话说,如果self
是模块(M),other
是(N),那么返回理想({f \in R | fN \subset M})。
示例
>>> from sympy import QQ
>>> from sympy.abc import x, y
>>> F = QQ.old_poly_ring(x, y).free_module(2)
>>> S = F.submodule([x*y, x*y])
>>> T = F.submodule([x, x])
>>> S.module_quotient(T)
<y>
一些实现允许传递更多选项。目前,只有一个实现是relations=True
,只有在other
是主理想时才能传递。在这种情况下,函数将返回一对(res, rel)
,其中res
是理想,rel
是系数向量列表,表示理想的生成元在self
的生成元中乘以other
的生成元的表达。
>>> S.module_quotient(T, relations=True)
(<y>, [[DMP_Python([[1]], QQ)]])
这意味着商理想由单一元素(y)生成,并且(y (x, x) = 1 (xy, xy)),((x, x))和((xy, xy))分别是(T)和(S)的生成元。
multiply_ideal(I)
将self
乘以理想I
。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x**2)
>>> M = QQ.old_poly_ring(x).free_module(2).submodule([1, 1])
>>> I*M
<[x**2, x**2]>
quotient_module(other, **opts)
返回一个商模块。
这等同于取包含模块的商模块的子模块。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> S1 = F.submodule([x, 1])
>>> S2 = F.submodule([x**2, x])
>>> S1.quotient_module(S2)
<[x, 1] + <[x**2, x]>>
或者更简洁地,使用重载的除法运算符:
>>> F.submodule([x, 1]) / [(x**2, x)]
<[x, 1] + <[x**2, x]>>
reduce_element(x)
将环中的元素x
模除理想self
。
这里的“reduce”没有特定的含义,它可以返回唯一的正常形式,稍微简化表达式,或者什么也不做。
submodule(*gens)
生成一个子模块。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2).submodule([x, 1])
>>> M.submodule([x**2, x])
<[x**2, x]>
syzygy_module(**opts)
计算self
生成元的 syzygy 模块。
假设(M)由环(R)上的(f_1, \ldots, f_n)生成。考虑同态(\phi: R^n \to M),定义为将((r_1, \ldots, r_n))映射至(r_1 f_1 + \cdots + r_n f_n)。syzygy 模块定义为(\phi)的核。
示例
syzygy 模块为零当且仅当生成元自由生成自由子模块:
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2).submodule([1, 0], [1, 1]).syzygy_module().is_zero()
True
一个稍微有趣的例子:
>>> M = QQ.old_poly_ring(x, y).free_module(2).submodule([x, 2*x], [y, 2*y])
>>> S = QQ.old_poly_ring(x, y).free_module(2).submodule([y, -x])
>>> M.syzygy_module() == S
True
union(other)
返回由self
和other
的并集生成的模块。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(1)
>>> M = F.submodule([x**2 + x]) # <x(x+1)>
>>> N = F.submodule([x**2 - 1]) # <(x-1)(x+1)>
>>> M.union(N) == F.submodule([x+1])
True
理想的创建与模块非常相似。例如,让我们验证节点三次曲线在原点确实是奇异的:
>>> I = lr.ideal(x, y)
>>> I == lr.ideal(x)
False
>>> I == lr.ideal(y)
False
我们在这里使用了这样一个事实,即一条曲线在某一点非奇异当且仅当局部环的极大理想是主理想,并且在这种情况下至少一个(x)和(y)必须是生成元。
这是理想类的详细文档。请注意,大多数关于理想属性(素性等)的方法尚未实现。
class sympy.polys.agca.ideals.Ideal(ring)
理想的抽象基类。
不要实例化 - 在环类中使用显式构造函数代替:
>>> from sympy import QQ
>>> from sympy.abc import x
>>> QQ.old_poly_ring(x).ideal(x+1)
<x + 1>
属性
- 环 - 此理想所属的环
未实现的方法:
-
_contains_elem
-
_contains_ideal
-
_quotient
-
_intersect
-
_union
-
_product
-
是否整个环
-
是否为零
-
是否为素理想,极大理想,主理想,根理想
-
是否为主理想
-
高度,深度
-
根理想
子类中可能应该重写的方法:
- reduce_element
contains(elem)
如果elem
是这个理想的一个元素则返回 True。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x+1, x-1).contains(3)
True
>>> QQ.old_poly_ring(x).ideal(x**2, x**3).contains(x)
False
depth()
计算self
的深度。
height()
计算self
的高度。
intersect(J)
计算self
与理想 J 的交集。
示例
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> R = QQ.old_poly_ring(x, y)
>>> R.ideal(x).intersect(R.ideal(y))
<x*y>
is_maximal()
如果self
是极大理想则返回 True。
is_primary()
如果self
是主理想则返回 True。
is_prime()
如果self
是素理想则返回 True。
is_principal()
如果self
是主理想则返回 True。
is_radical()
如果self
是根理想则返回 True。
is_whole_ring()
如果self
是整环则返回 True。
is_zero()
如果self
是零理想则返回 True。
product(J)
计算self
和J
的理想积。
即,计算由(xy)的乘积生成的理想,其中(x)是self
的元素,(y \in J)。
示例
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> QQ.old_poly_ring(x, y).ideal(x).product(QQ.old_poly_ring(x, y).ideal(y))
<x*y>
quotient(J, **opts)
计算self
除以J
的理想商。
即,如果self
是理想(I),计算集合(I : J = {x \in R | xJ \subset I })。
示例
>>> from sympy.abc import x, y
>>> from sympy import QQ
>>> R = QQ.old_poly_ring(x, y)
>>> R.ideal(x*y).quotient(R.ideal(x))
<y>
radical()
计算self
的根理想。
reduce_element(x)
将我们环的元素x
减少至理想self
。
这里的“reduce”没有具体的含义:它可以返回一个唯一的标准形式,简化表达式,或者什么也不做。
saturate(J)
计算self
通过J
的理想饱和。
即,如果self
是理想(I),计算集合(I : J^\infty = {x \in R | xJ^n \subset I \text{ for some } n})。
subset(other)
如果other
是self
的子集则返回 True。
这里的other
可能是一个理想。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x+1)
>>> I.subset([x**2 - 1, x**2 + 2*x + 1])
True
>>> I.subset([x**2 + 1, x + 1])
False
>>> I.subset(QQ.old_poly_ring(x).ideal(x**2 - 1))
True
union(J)
计算由self
和 J 的并集生成的理想。
示例
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x**2 - 1).union(QQ.old_poly_ring(x).ideal((x+1)**2)) == QQ.old_poly_ring(x).ideal(x+1)
True
如果 (M) 是 (A)-模块且 (N) 是 (A)-子模块,我们可以定义 (M) 的两个元素 (x) 和 (y) 等价,如果 (x - y \in N)。等价类的集合写作 (M/N),并且具有自然的 (A)-模块结构。这被称为 (M) 关于 (N) 的商模。如果 (K) 是包含 (N) 的 (M) 的子模块,则 (K/N) 以一种自然的方式是 (M/N) 的子模块。这样的模块称为子商模。这是商模和子商模的文档:
class sympy.polys.agca.modules.QuotientModule(ring, base, submodule)
商模类。
不要直接实例化这个类。对于子商模,请参见 SubQuotientModule 类。
属性:
-
base - 我们是其商的基模块
-
killed_module - 用于形成商的子模块
-
基模的秩
convert(elem, M=None)
将 elem
转换为内部表示。
每当计算涉及不在内部表示中的元素时,都会隐式调用此方法。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
>>> F.convert([1, 0])
[1, 0] + <[1, 2], [1, x]>
dtype
别名 QuotientModuleElement
identity_hom()
返回在 self
上的恒同同态。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
>>> M.identity_hom()
Matrix([
[1, 0], : QQ[x]**2/<[1, 2], [1, x]> -> QQ[x]**2/<[1, 2], [1, x]>
[0, 1]])
is_submodule(other)
如果 other
是 self
的子模块,则返回 True。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
>>> S = Q.submodule([1, 0])
>>> Q.is_submodule(S)
True
>>> S.is_submodule(Q)
False
is_zero()
如果 self
是零模块,则返回 True。
如果基模块与被杀死的子模块相同,则会发生这种情况。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> (F/[(1, 0)]).is_zero()
False
>>> (F/[(1, 0), (0, 1)]).is_zero()
True
quotient_hom()
返回到 self
的商同态。
即,返回表示从 self.base
到 self
的自然映射的同态。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = QQ.old_poly_ring(x).free_module(2) / [(1, 2), (1, x)]
>>> M.quotient_hom()
Matrix([
[1, 0], : QQ[x]**2 -> QQ[x]**2/<[1, 2], [1, x]>
[0, 1]])
submodule(*gens, **opts)
生成一个子模块。
这与取基模块的子模块的商是相同的。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> Q = QQ.old_poly_ring(x).free_module(2) / [(x, x)]
>>> Q.submodule([x, 0])
<[x, 0] + <[x, x]>>
class sympy.polys.agca.modules.QuotientModuleElement(module, data)
商模的元素。
eq(d1, d2)
相等比较。
class sympy.polys.agca.modules.SubQuotientModule(gens, container, **opts)
商模的子模块。
等价地,子模的商模。
不要直接实例化它,而是使用子模块或商模块构造方法:
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> S = F.submodule([1, 0], [1, x])
>>> Q = F/[(1, 0)]
>>> S/[(1, 0)] == Q.submodule([5, x])
True
属性:
-
base - 我们是其商的基模块
-
killed_module - 用于形成商的子模块
is_full_module()
如果 self
是整个自由模块,则返回 True。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> F.submodule([x, 1]).is_full_module()
False
>>> F.submodule([1, 1], [1, 2]).is_full_module()
True
quotient_hom()
返回到 self
的商同态。
即,返回从 self.base
到 self
的自然映射。
例子
>>> from sympy.abc import x
>>> from sympy import QQ
>>> M = (QQ.old_poly_ring(x).free_module(2) / [(1, x)]).submodule([1, 0])
>>> M.quotient_hom()
Matrix([
[1, 0], : <[1, 0], [1, x]> -> <[1, 0] + <[1, x]>, [1, x] + <[1, x]>>
[0, 1]])
模同态和 Syzygies
设 (M) 和 (N) 是 (A)-模块。满足各种明显性质的映射 (f: M \to N)(见[Atiyah69])被称为 (A)-模同态。在这种情况下,(M) 被称为定义域,N 被称为陪域。集合 ({x \in M | f(x) = 0}) 称为核 (ker(f)),而集合 ({f(x) | x \in M}) 称为像 (im(f))。核是 (M) 的子模,像是 (N) 的子模。同态 (f) 是单射当且仅当 (ker(f) = 0),是满射当且仅当 (im(f) = N)。双射同态称为同构。等价地,(ker(f) = 0) 并且 (im(f) = N)。(AGCA 模块中目前没有特殊名称的相关概念是cokernel,(coker(f) = N/im(f))。)
现在假设( M )是一个( A )-模。如果存在一个满同态( A^n \to M )(对于某些( n )),则( M )被称为有限生成的。如果选择这样的同态( f ),则( A^n )的标准基的像称为( M )的生成元。模( \ker(f) )称为关于生成元的syzygy 模块。如果一个模是有限生成的且有一个有限生成的 syzygy 模块,则称其为有限呈现模。有限呈现模的类别实质上是我们可以有意义地计算的最大类别。
一个重要的定理是,对于我们考虑的所有环,有限生成模的所有子模都是有限生成的,因此有限生成模和有限呈现模是相同的。
虽然最初看起来可能有些抽象,但是 syzygies 的概念实际上非常具有计算性。这是因为存在(相当简单的)算法来计算它们,而更一般的问题(核,交集等)通常可以简化为 syzygy 的计算。
让我们先谈一下 AGCA 模块中同态的定义。首先假设( f: M \to N )是( A )-模的任意同态。如果( K )是( M )的子模,则( f )自然地定义了一个新的同态( g: K \to N )(通过( g(x) = f(x) )),称为( f )在( K )上的限制。如果现在( K )包含在( f )的核中,则此外( f )还自然地定义了一个同态( g: M/K \to N )(同上公式!),我们称( f ) 降至 ( M/K )。类似地,如果( L )是( N )的子模,则存在一个自然的同态( g: M \to N/L ),我们称( g ) 通过 ( f )。最后,如果现在( L )包含( f )的像,则有一个自然的同态( g: M \to L )(同上定义),我们称( g )是通过限制像域从( f )获得的。还要注意这四个操作中的每一个都是可逆的,也就是说,给定( g ),可以总是(非唯一地)找到( f ),使得( g )是通过上述方式从( f )获得的。
注意,所有在 AGCA 中实现的模块都是通过连续取子模和商模从自由模块获得的。因此,为了解释如何在上述情况下定义任意模块之间的同态,我们只需解释如何定义自由模块的同态。但是,基本上通过自由模块的定义,从自由模块( A^n )到任何模块( M )的同态恰好等同于给出( M )的( n )个元素(标准基的像),而从自由模块( A^m )给出元素恰好等同于给出( A )的( m )个元素。因此,自由模块( A^n \to A^m )的同态可以通过矩阵指定,与向量空间的情况完全类似。
类Homomorphism
的函数restrict_domain
等可以用于执行上述操作,并且自由模的同态映射原则上可以手动实例化。由于这些操作如此常见,因此有一个方便的函数homomorphism
来通过上述方法定义任意模块之间的同态映射。这基本上是用户创建同态映射的唯一方法。
sympy.polys.agca.homomorphisms.homomorphism(domain, codomain, matrix)
创建一个同态映射对象。
此函数尝试通过矩阵matrix
从domain
到codomain
构建同态映射。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> R = QQ.old_poly_ring(x)
>>> T = R.free_module(2)
如果domain
是由(e_1, \ldots, e_n)生成的自由模,则matrix
应该是一个 n 元可迭代对象((b_1, \ldots, b_n)),其中(b_i)是codomain
的元素。构造的同态映射是将(e_i)发送到(b_i)的唯一同态映射。
>>> F = R.free_module(2)
>>> h = homomorphism(F, T, [[1, x], [x**2, 0]])
>>> h
Matrix([
[1, x**2], : QQ[x]**2 -> QQ[x]**2
[x, 0]])
>>> h([1, 0])
[1, x]
>>> h([0, 1])
[x**2, 0]
>>> h([1, 1])
[x**2 + 1, x]
如果domain
是自由模的子模,则matrix
确定从包含自由模到codomain
的同态映射,并且通过限制到domain
获得返回的同态映射。
>>> S = F.submodule([1, 0], [0, x])
>>> homomorphism(S, T, [[1, x], [x**2, 0]])
Matrix([
[1, x**2], : <[1, 0], [0, x]> -> QQ[x]**2
[x, 0]])
如果domain
是一个(子)商模 (N/K),那么matrix
确定了从(N)到codomain
的同态映射。如果核包含(K),则此同态映射下降到domain
并返回;否则会引发异常。
>>> homomorphism(S/[(1, 0)], T, [0, [x**2, 0]])
Matrix([
[0, x**2], : <[1, 0] + <[1, 0]>, [0, x] + <[1, 0]>, [1, 0] + <[1, 0]>> -> QQ[x]**2
[0, 0]])
>>> homomorphism(S/[(0, x)], T, [0, [x**2, 0]])
Traceback (most recent call last):
...
ValueError: kernel <[1, 0], [0, 0]> must contain sm, got <[0,x]>
最后,这里是实际同态映射类的详细参考:
class sympy.polys.agca.homomorphisms.ModuleHomomorphism(domain, codomain)
模块同态映射的抽象基类。不要实例化。
而不是,使用homomorphism
函数:
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> homomorphism(F, F, [[1, 0], [0, 1]])
Matrix([
[1, 0], : QQ[x]**2 -> QQ[x]**2
[0, 1]])
属性:
-
环 - 我们考虑的模块的环
-
域 - 域模
-
codomain - 积模
-
_ker - 缓存的核
-
_img - 缓存的图像
未实现的方法:
-
_ 核
-
_ 图像
-
_restrict_domain
-
_restrict_codomain
-
_quotient_domain
-
_quotient_codomain
-
_apply
-
_mul_scalar
-
_compose
-
_add
image()
计算self
的图像。
也就是说,如果self
是同态映射(\phi: M \to N),那么计算(im(\phi) = {\phi(x) | x \in M })。这是(N)的子模块。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> homomorphism(F, F, [[1, 0], [x, 0]]).image() == F.submodule([1, 0])
True
is_injective()
如果self
是单射,则返回 True。
也就是说,检查域的元素是否映射到相同的积模元素。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_injective()
False
>>> h.quotient_domain(h.kernel()).is_injective()
True
is_isomorphism()
如果self
是同构,则返回 True。
也就是说,检查每个域的元素是否具有精确一个原像。等效地,self
既是单射又是满射。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h = h.restrict_codomain(h.image())
>>> h.is_isomorphism()
False
>>> h.quotient_domain(h.kernel()).is_isomorphism()
True
is_surjective()
如果self
是满射,则返回 True。
也就是说,检查每个域的元素是否至少有一个原像。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_surjective()
False
>>> h.restrict_codomain(h.image()).is_surjective()
True
is_zero()
如果self
是零态射,则返回 True。
也就是说,检查域的每个元素是否在自身下映射为零。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h.is_zero()
False
>>> h.restrict_domain(F.submodule()).is_zero()
True
>>> h.quotient_codomain(h.image()).is_zero()
True
kernel()
计算self
的核。
也就是说,如果self
是同态映射(\phi: M \to N),那么计算(ker(\phi) = {x \in M | \phi(x) = 0})。这是(M)的子模块。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> homomorphism(F, F, [[1, 0], [x, 0]]).kernel()
<[x, -1]>
quotient_codomain(sm)
用codomain/sm
替换self
返回。
这里sm
必须是self.codomain
的子模块。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.quotient_codomain(F.submodule([1, 1]))
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
[0, 0]])
这与在左侧使用商映射进行组合相同:
>>> (F/[(1, 1)]).quotient_hom() * h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
[0, 0]])
quotient_domain(sm)
用domain/sm
替换self
返回。
这里sm
必须是self.kernel()
的子模块。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.quotient_domain(F.submodule([-x, 1]))
Matrix([
[1, x], : QQ[x]**2/<[-x, 1]> -> QQ[x]**2
[0, 0]])
restrict_codomain(sm)
返回self
,其余值被限制为sm
。
这里sm
必须是包含图像的self.codomain
的子模。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.restrict_codomain(F.submodule([1, 0]))
Matrix([
[1, x], : QQ[x]**2 -> <[1, 0]>
[0, 0]])
restrict_domain(sm)
返回self
,其定义被限制为sm
。
这里sm
必须是self.domain
的子模。
示例
>>> from sympy import QQ
>>> from sympy.abc import x
>>> from sympy.polys.agca import homomorphism
>>> F = QQ.old_poly_ring(x).free_module(2)
>>> h = homomorphism(F, F, [[1, 0], [x, 0]])
>>> h
Matrix([
[1, x], : QQ[x]**2 -> QQ[x]**2
[0, 0]])
>>> h.restrict_domain(F.submodule([1, 0]))
Matrix([
[1, x], : <[1, 0]> -> QQ[x]**2
[0, 0]])
这与仅在右侧与子模包含组合相同:
>>> h * F.submodule([1, 0]).inclusion_hom()
Matrix([
[1, x], : <[1, 0]> -> QQ[x]**2
[0, 0]])
有限扩展
设(A)为(交换)环,(B)为(A)的扩展环。若(B)中的元素(t)是(A)上(B)的生成器,则(B)中的所有元素都可以用(t)的系数为(A)的多项式表示。如果且仅如果(t)满足没有非平凡多项式关系,则表示是唯一的,此时(B)可以被视为(A)上的(单变量)多项式环。
一般情况下,以(t)为根的多项式形成一个非零理想。在实践中最重要的情况是由单一单项式生成的理想。如果(t)满足这样的多项式关系,则其最高幂(tn)可以写成较低幂的线性组合。归纳地,所有更高的幂(t)也有这样的表示。因此,较低的幂(ti)((i = 0, \dots, n-1))形成(B)的一组基础,然后称为(A)的有限扩展,或更准确地说是由单个元素(t)生成的单基有限扩展。
class sympy.polys.agca.extensions.MonogenicFiniteExtension(mod)
由整数元素生成的有限扩展。
生成器由从参数mod
导出的单变量单项式定义。
更短的别名是FiniteExtension
。
示例
二次整数环(\mathbb{Z}[\sqrt2]):
>>> from sympy import Symbol, Poly
>>> from sympy.polys.agca.extensions import FiniteExtension
>>> x = Symbol('x')
>>> R = FiniteExtension(Poly(x**2 - 2)); R
ZZ[x]/(x**2 - 2)
>>> R.rank
2
>>> R(1 + x)*(3 - 2*x)
x - 1
有限域(GF(5³)),由原始多项式(x³ + x² + 2)(在(\mathbb{Z}_5)上)定义。
>>> F = FiniteExtension(Poly(x**3 + x**2 + 2, modulus=5)); F
GF(5)[x]/(x**3 + x**2 + 2)
>>> F.basis
(1, x, x**2)
>>> F(x + 3)/(x**2 + 2)
-2*x**2 + x + 2
椭圆曲线的函数域:
>>> t = Symbol('t')
>>> FiniteExtension(Poly(t**2 - x**3 - x + 1, t, field=True))
ZZ(x)[t]/(t**2 - x**3 - x + 1)
dtype
别名为ExtensionElement
class sympy.polys.agca.extensions.ExtensionElement(rep, ext)
有限扩展的元素。
一个在扩展ext
的模modulus
的DMP
类的唯一多项式rep
表示。它由mod
的表示和modulus
的表示构成。
inverse()
乘法逆元。
引发:
NotInvertible
如果元素是零除数。
介绍 poly 模块的域
此页面介绍了 SymPy 的 sympy.polys
模块中使用的“域”的概念。重点是直接介绍如何使用这些域以及理解它们如何作为 Poly
类的内部部分使用。这是一个相对高级的主题,因此建议阅读 模块的基本功能 以获取更简介的对 Poly
类和 sympy.polys
模块的理解。有关域类的参考文档在 Poly Domains 的参考文档 中。利用这些域的内部功能在 多项式操作模块的内部 中有所记录。
域是什么?
对于大多数用户来说,域只在打印输出Poly
时才真正显著:
>>> from sympy import Symbol, Poly
>>> x = Symbol('x')
>>> Poly(x**2 + x)
Poly(x**2 + x, x, domain='ZZ')
>>> Poly(x**2 + x/2)
Poly(x**2 + 1/2*x, x, domain='QQ')
我们在这里看到一个 Poly
具有域 ZZ,代表整数,另一个具有域 QQ,代表有理数。这些指示了多项式系数的“域”来源。
从高层次来看,域表示形式概念,如整数集(\mathbb{Z})或有理数(\mathbb{Q})。这里的“域”一词是对数学概念“整环”的引用。
在内部,域对应于多项式所对应的不同计算实现和表达方式。Poly
对象本身有一个内部表示,作为系数的list
和表示这些系数实现的 domain
属性:
>>> p = Poly(x**2 + x/2)
>>> p
Poly(x**2 + 1/2*x, x, domain='QQ')
>>> p.domain
QQ
>>> p.rep
DMP_Python([1, 1/2, 0], QQ)
>>> p.rep.rep
[1, 1/2, 0]
>>> type(p.rep.rep[0])
<class 'sympy.external.pythonmpq.PythonMPQ'>
这里的域是 QQ,它表示域系统中有理数的实现。Poly
实例本身具有 Poly.domain
属性 QQ,然后是一个 PythonMPQ
系数列表,其中 PythonMPQ
是实现 QQ 域元素的类。系数列表 [1, 1/2, 0]
给出了多项式表达式 (1)*x**2 + (1/2)*x + (0)
的标准化低级表示。
本页面介绍了在 SymPy 中定义的不同域,它们的实现方式以及如何使用它们。它介绍了如何直接使用域和域元素,并解释了它们作为 Poly
对象的内部使用方式。这些信息对于 SymPy 的开发比对 sympy.polys
模块的用户更相关。
以符号表示表达式
数学表达式可以以多种不同的方式符号化表示。多项式域的目的是为不同类别的表达式提供合适的实现。本节考虑了数学表达式符号化表示的基本方法:“树形结构”、“密集多项式”和“稀疏多项式”。
树形结构表示
符号表达式的最一般表示形式是作为 树形结构,这是大多数普通 SymPy 表达式的表示形式,它们是 Expr
的实例(Basic
的子类)。我们可以使用 srepr()
函数来查看这种表示:
>>> from sympy import Symbol, srepr
>>> x = Symbol('x')
>>> e = 1 + 1/(2 + x**2)
>>> e
1 + 1/(x**2 + 2)
>>> print(srepr(e))
Add(Integer(1), Pow(Add(Pow(Symbol('x'), Integer(2)), Integer(2)), Integer(-1)))
在这里,表达式 e
被表示为一个 Add
节点,它有两个子节点 1
和 1/(x**2 + 2)
。子节点 1
被表示为一个 Integer
,而另一个子节点被表示为一个 Pow
,其基数为 x**2 + 2
,指数为 1
。然后 x**2 + 2
被表示为一个 Add
,其子节点为 x**2
和 2
,依此类推。通过这种方式,表达式被表示为一个树,其中内部节点是操作,如 Add
、Mul
、Pow
等,而叶节点是原子表达式类型,如 Integer
和 Symbol
。更多关于这种表示方法的信息,请参见高级表达式操作。
树形表示是 SymPy 中 Expr
架构的核心。它是一种高度灵活的表示方法,可以表示非常广泛的表达式。它还可以以不同方式表示等价表达式,例如:
>>> e = x*(x + 1)
>>> e
x*(x + 1)
>>> e.expand()
x**2 + x
这两个表达式虽然等价,但具有不同的树形表示:
>>> print(srepr(e))
Mul(Symbol('x'), Add(Symbol('x'), Integer(1)))
>>> print(srepr(e.expand()))
Add(Pow(Symbol('x'), Integer(2)), Symbol('x'))
能够以不同方式表示相同的表达式既是一种优势也是一种弱点。能够将表达式转换为不同形式以应对不同的任务是很有用的,但是具有非唯一表示使得很难判断两个表达式是否等价,而这对于许多计算算法来说是非常重要的。最重要的任务是能够判断一个表达式是否等于零,在一般情况下这是不可判定的(参见理查森定理),但在许多重要的特殊情况下是可判定的。
DUP 表示
限制允许表达式的特殊情况可以实现更高效的符号表示。正如我们之前看到的Poly
可以将多项式表示为系数列表。这意味着像x**4 + x + 1
这样的表达式可以简单地表示为[1, 0, 0, 1, 1]
。多项式表达式的这种系数列表表示称为“密集单变量多项式”(DUP)表示。在该表示内部,乘法、加法和关键的零测试算法比对应的树形表示要高效得多。我们可以通过查看Poly
实例的rep.rep
属性来看到这种表示:
>>> p = Poly(x**4 + x + 1)
>>> p.rep.rep
[1, 0, 0, 1, 1]
在 DUP 表示中,不可能用不同的方式表示相同的表达式。x*(x + 1)
和x**2 + x
之间没有区别,因为它们都是[1, 1, 0]
。这意味着比较两个表达式很容易:它们只有在所有系数都相等时才相等。零测试特别简单:多项式仅在所有系数都为零时为零(当然,我们需要对系数本身进行简单的零测试)。
我们可以比树形表示法更有效地创建在 DUP 表示法上操作的函数。实际上,许多标准 sympy 表达式的操作实际上是通过转换为多项式表示,然后执行计算来完成的。一个例子是factor()
函数:
>>> from sympy import factor
>>> e = 2*x**3 + 10*x**2 + 16*x + 8
>>> e
2*x**3 + 10*x**2 + 16*x + 8
>>> factor(e)
2*(x + 1)*(x + 2)**2
在内部,factor()
将把表达式从树形表示转换为 DUP 表示,然后使用函数dup_factor_list
:
>>> from sympy import ZZ
>>> from sympy.polys.factortools import dup_factor_list
>>> p = [ZZ(2), ZZ(10), ZZ(16), ZZ(8)]
>>> p
[2, 10, 16, 8]
>>> dup_factor_list(p, ZZ)
(2, [([1, 1], 1), ([1, 2], 2)])
有许多以dup_*
命名的函数用于操作 DUP 表示,这些函数在多项式操作模块内部有详细文档。还有以dmp_*
前缀命名的函数用于操作多元多项式。### DMP 表示
多元多项式(多个变量的多项式)可以表示为系数本身是多项式的多项式。例如,x**2*y + x**2 + x*y + y + 1
可以表示为以x
为多项式的多项式,其中系数本身是y
的多项式,即:(y + 1)*x**2 + (y)*x + (y+1)
。由于我们可以用系数列表表示一个多项式,多元多项式可以用系数列表的列表表示:
>>> from sympy import symbols
>>> x, y = symbols('x, y')
>>> p = Poly(x**2*y + x**2 + x*y + y + 1)
>>> p
Poly(x**2*y + x**2 + x*y + y + 1, x, y, domain='ZZ')
>>> p.rep.rep
[[1, 1], [1, 0], [1, 1]]
这种列表的(列表的…)系数表示称为“密集多元多项式”(DMP)表示。### 稀疏多项式表示
我们可以使用字典来代替列表,将非零单项式项映射到它们的系数。这被称为“稀疏多项式”表示。我们可以通过as_dict()
方法看到它的实现:
>>> Poly(7*x**20 + 8*x + 9).rep.rep
[7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9]
>>> Poly(7*x**20 + 8*x + 9).as_dict()
{(0,): 9, (1,): 8, (20,): 7}
此字典的键是x
的幂的指数,值是系数,因此例如7*x**20
在字典中变为(20,): 7
。键是一个元组,因此在多变量情况下,如4*x**2*y**3
可以表示为(2, 3): 4
。稀疏表示可以更高效,因为它避免了存储和操作零系数的需求。在具有大量生成器(变量)的情况下,稠密表示尤其低效,最好使用稀疏表示:
>>> from sympy import prod
>>> gens = symbols('x:10')
>>> gens
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
>>> p = Poly(prod(gens))
>>> p
Poly(x0*x1*x2*x3*x4*x5*x6*x7*x8*x9, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, domain='ZZ')
>>> p.rep.rep
[[[[[[[[[[1, 0], []], [[]]], [[[]]]], [[[[]]]]], [[[[[]]]]]], [[[[[[]]]]]]], [[[[[[[]]]]]]]], [[[[[[[[]]]]]]]]], [[[[[[[[[]]]]]]]]]]
>>> p.as_dict()
{(1, 1, 1, 1, 1, 1, 1, 1, 1, 1): 1}
在上一个输出中显示的字典表示将单项式(表示为幂的元组,如(1, 1, 1, ...)
即x0**1 * x1**1, ...
)映射到系数1
。与 DMP 表示相比,我们拥有一个更为扁平化的数据结构:它是一个只有一个键和值的dict
。对于处理稀疏表示的算法,可能比这个特定例子中的密集算法更为高效。
SymPy 的多项式模块实现了基于密集和稀疏表示的多项式表达式。还有其他实现不同特殊类别表达式的实现,可以作为这些多项式的系数。本页的其余部分将讨论这些表示形式及其使用方法。
域的基本用法
几个域已经预定义并可以直接使用,例如 ZZ 和 QQ,它们分别代表整数环(\mathbb{Z})和有理数域(\mathbb{Q})。Domain
对象用于构造元素,这些元素可以用于普通的算术运算。
>>> from sympy import ZZ
>>> z1 = ZZ(2)
>>> z1
2
>>> z1 + z1
4
>>> type(z1)
<class 'int'>
>>> z1 in ZZ
True
对于任何域的元素,基本运算+
、-
和*
(加法、减法和乘法)都能工作并生成新的域元素。使用/
(Python 的“真除法”运算符)进行除法不一定适用于所有域元素,除非已知该域是一个域。例如,两个 ZZ 中的元素相除可能会得到一个不是 ZZ 元素的float
:
>>> z1 / z1
1.0
>>> type(z1 / z1)
<class 'float'>
>>> ZZ.is_Field
False
对于非域的情况,/
的行为在不同的域的基础类型的不同实现中也可能不同。例如,使用SYMPY_GROUND_TYPES=flint
,在 ZZ 中除法运算会引发错误,而不是返回浮点数:
>>> z1 / z1
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'flint._flint.fmpz' and 'flint._flint.fmpz'
大多数表示非域环的域允许使用 Python 的地板除法//
和模除运算%
。例如,使用 ZZ:
>>> z1 // z1
1
>>> z1 % z1
0
QQ 域表示有理数的域并允许除法:
>>> from sympy import QQ
>>> q1 = QQ(1, 2)
>>> q1
1/2
>>> q2 = QQ(2, 3)
>>> q2
2/3
>>> q1 / q2
3/4
>>> type(q1)
<class 'sympy.external.pythonmpq.PythonMPQ'>
通常,预计将与任意域中的元素一起使用的代码不应使用除法运算符/
,//
和%
。只有运算符+
,-
,*
和**
(带非负整数指数)应假定可用于任意域元素。所有其他操作应作为Domain
对象的函数访问:
>>> ZZ.quo(ZZ(5), ZZ(3)) # 5 // 3
1
>>> ZZ.rem(ZZ(5), ZZ(3)) # 5 % 3
2
>>> ZZ.div(ZZ(5), ZZ(3)) # divmod(5, 3)
(1, 2)
>>> QQ.div(QQ(5), QQ(3))
(5/3, 0)
exquo()
函数用于计算精确商。这类似于a / b
,但预计除法是精确的(没有余数),否则将引发错误:
>>> QQ.exquo(QQ(5), QQ(3))
5/3
>>> ZZ.exquo(ZZ(4), ZZ(2))
2
>>> ZZ.exquo(ZZ(5), ZZ(3))
Traceback (most recent call last):
...
ExactQuotientFailed: 3 does not divide 5 in ZZ
一般而言,不能保证域元素的确切方法和属性超出基本算术运算。不应假定例如 ZZ 总是类型为int
。如果安装了gmpy
或gmpy2
,则使用mpz
或mpq
类型而不是 ZZ 和 QQ 的纯 Python 实现:
>>> from sympy import ZZ, QQ
>>> ZZ(2)
mpz(2)
>>> QQ(2, 3)
mpq(2, 3)
mpz
类型在大整数操作中比 Python 标准int
类型更快,尽管对于较小整数,差异不那么显著。代表有理数的mpq
类型在 C 中实现,而不是 Python,并且比未安装 gmpy 时使用的 QQ 的纯 Python 实现快几倍。
通常可以从域的dtype
属性检查元素的 Python 类型。安装 gmpy 时,ZZ 的 dtype 为(mpz),这不是实际类型,不能与(isinstance)一起使用。因此,可以使用of_type()
方法检查对象是否为dtype
的元素:
>>> z = ZZ(2)
>>> type(z)
<class 'int'>
>>> ZZ.dtype
<class 'int'>
>>> ZZ.of_type(z)
True
域元素与 sympy 表达式
请注意,域元素与普通 sympy 表达式不是相同类型,后者是Expr
的子类,如Integer
。普通 sympy 表达式通过sympify()
函数创建:
>>> from sympy import sympify
>>> z1_sympy = sympify(2) # Normal sympy object
>>> z1_sympy
2
>>> type(z1_sympy)
<class 'sympy.core.numbers.Integer'>
>>> from sympy import Expr
>>> isinstance(z1_sympy, Expr)
True
在使用域时,重要的是不要将 sympy 表达式与域元素混合使用,即使在简单情况下有时可能会有效。每个域对象都有方法 to_sympy()
和 from_sympy()
用于在 sympy 表达式和域元素之间进行转换:
>>> z_sympy = sympify(2)
>>> z_zz = ZZ.from_sympy(z_sympy)
>>> z_zz
2
>>> type(z_sympy)
<class 'sympy.core.numbers.Integer'>
>>> type(z_zz)
<class 'int'>
>>> ZZ.to_sympy(z_zz)
2
>>> type(ZZ.to_sympy(z_zz))
<class 'sympy.core.numbers.Integer'>
任何特定的域只能表示一些 sympy 表达式,因此如果表达式不能在域中表示,则转换将失败:
>>> from sympy import sqrt
>>> e = sqrt(2)
>>> e
sqrt(2)
>>> ZZ.from_sympy(e)
Traceback (most recent call last):
...
CoercionFailed: expected an integer, got sqrt(2)
我们已经看到,在某些情况下,我们可以使用域对象本身作为构造函数,例如 QQ(2)
。只要给定的参数对于域的 dtype
是有效的,通常这样做是有效的。尽管在交互式会话和演示中使用这种方法很方便,但通常最好使用 from_sympy()
方法从 sympy 表达式(或可以 sympify 为 sympy 表达式的对象)构造域元素。
在域中工作时,重要的是不要将域元素与其他 Python 类型(如 int
、float
)以及标准的 sympy Expr
表达式混合使用。需要注意的是,某些 Python 操作将会在不经意间执行此操作。例如,sum
函数将使用常规的 int
值零,因此 sum([a, b])
实际上会被计算为 (0 + a) + b
,其中 0
的类型是 int
。
每个域至少是一个环,如果不是一个域,那么它保证具有两个特定元素,分别对应于 (1) 和 (0)。域对象提供这些作为属性的域元素 one
和 zero
。这些对于像 Python 的 sum
函数非常有用,该函数允许提供一个替代对象作为“零”:
>>> ZZ.one
1
>>> ZZ.zero
0
>>> sum([ZZ(1), ZZ(2)]) # don't do this (even it sometimes works)
3
>>> sum([ZZ(1), ZZ(2)], ZZ.zero) # provide the zero from the domain
3
在域中执行计算的标准模式如下:
-
从 sympy
Expr
实例开始,表示表达式。 -
选择一个能够表示表达式的适当域。
-
使用
from_sympy()
将所有表达式转换为域元素。 -
使用域元素执行计算。
-
使用
to_sympy()
将转换回Expr
。
这里是sum
函数的实现示例,说明了这些步骤并对一些整数求和,但是使用了域元素而不是标准的 sympy 表达式进行计算:
def sum_domain(expressions_sympy):
"""Sum sympy expressions but performing calculations in domain ZZ"""
# Convert to domain
expressions_dom = [ZZ.from_sympy(e) for e in expressions_sympy]
# Perform calculations in the domain
result_dom = ZZ.zero
for e_dom in expressions_dom:
result_dom += e_dom
# Convert the result back to Expr
result_sympy = ZZ.to_sympy(result_dom)
return result_sympy
高斯整数和高斯有理数
到目前为止我们见过的两个示例域是 ZZ 和 QQ,分别表示整数和有理数。还有其他简单的域,如 ZZ_I 和 QQ_I,分别表示高斯整数和高斯有理数。高斯整数是形如 (a\sqrt{-1} + b) 的数,其中 (a) 和 (b) 是整数。高斯有理数类似地定义,不同之处在于 (a) 和 (b) 可以是有理数。我们可以像这样使用高斯域:
>>> from sympy import ZZ_I, QQ_I, I
>>> z = ZZ_I.from_sympy(1 + 2*I)
>>> z
(1 + 2*I)
>>> z**2
(-3 + 4*I)
注意与树形表示中计算方式的对比,需要使用 expand()
来获得简化形式:
>>> from sympy import expand, I
>>> z = 1 + 2*I
>>> z**2
(1 + 2*I)**2
>>> expand(z**2)
-3 + 4*I
ZZ_I 和 QQ_I 域由类 GaussianIntegerRing
和 GaussianRationalField
实现,它们的元素分别由 GaussianInteger
和 GaussianRational
表示。在 ZZ_I 或 QQ_I 的内部表示中,一个元素简单地是 (a, b)
,其中 a
和 b
分别是 ZZ 或 QQ 的元素。域 ZZ_I 是一个与 ZZ 类似属性的环,而 QQ_I 则像 QQ 一样是一个域:
>>> ZZ.is_Field
False
>>> QQ.is_Field
True
>>> ZZ_I.is_Field
False
>>> QQ_I.is_Field
True
由于 QQ_I 是一个域,非零元素总是可以进行除法,而在 ZZ_I 中我们有最大公约数(GCD)的重要概念:
>>> e1 = QQ_I.from_sympy(1+I)
>>> e2 = QQ_I.from_sympy(2-I/2)
>>> e1/e2
(6/17 + 10/17*I)
>>> ZZ_I.gcd(ZZ_I(5), ZZ_I.from_sympy(1+2*I))
(1 + 2*I)
有限域
到目前为止,我们看到了域 ZZ, QQ, ZZ_I 和 QQ_I。还有代表 有限域 的领域,尽管这些的实现尚不完整。可以用 FF
或 GF
构建一个素数阶有限域 GF(p)。可以用 GF(p) 构建一个素数阶有限域 (p) 的领域:
>>> from sympy import GF
>>> K = GF(5)
>>> two = K(2)
>>> two
2 mod 5
>>> two ** 2A
4 mod 5
>>> two ** 3
3 mod 5
FF
也是 GF
的别名(分别代表“有限域”和“伽罗瓦域”)。它们是等效的,FF(n)
和 GF(n)
都将创建一个领域,该领域是 FiniteField
的实例。关联的领域元素将是 PythonFiniteField
或 GMPYFiniteField
的实例,具体取决于是否安装了 gmpy
。
有限阶域 (p^n) (其中 (n \ne 1))尚未实现。可以使用例如 GF(6)
或 GF(9)
,但得到的领域不是一个域。它只是模 6
或 9
的整数集,因此具有零除数和非可逆元素:
>>> K = GF(6)
>>> K(3) * K(2)
0 mod 6
很高兴看到对素数幂次有限域的适当实现,但目前在 SymPy 中尚不可用(欢迎贡献!)。
实数域和复数域
域 RR 和 CC 在数学上分别对应于 实数 和 复数,(\mathbb{R}) 和 (\mathbb{C})。这些的实现使用浮点数运算。在实践中,这意味着这些领域用于表示包含浮点数的表达式。域 RR 的元素是 RealElement
类的实例,并具有用于表示 mpmath
中浮点数的 mpf
元组。域 CC 的元素是 ComplexElement
类的实例,并具有表示实部和虚部的 mpf
元组对。有关浮点数的表示方式,请参阅 mpmath 文档:
>>> from sympy import RR, CC
>>> xr = RR(3)
>>> xr
3.0
>>> xr._mpf_
(0, 3, 0, 2)
>>> zc = CC(3+1j)
>>> zc
(3.0 + 1.0j)
>>> zc._mpc_
((0, 3, 0, 2), (0, 1, 0, 1))
在这些域中使用近似浮点算术会带来所有通常的问题。sympy.polys
模块中的许多算法基本上是为精确算术而设计的,因此使用这些域可能会有问题:
>>> RR('0.1') + RR('0.2') == RR('0.3')
False
由于这些是使用mpmath
(一个多精度库)实现的,因此可以使用不同的工作精度创建不同的域。默认域 RR 和 CC 使用 53 位二进制精度,类似于标准的双精度浮点数,对应于大约 15 位十进制数字:
>>> from sympy.polys.domains.realfield import RealField
>>> RR.precision
53
>>> RR.dps
15
>>> RR(1) / RR(3)
0.333333333333333
>>> RR100 = RealField(100)
>>> RR100.precision
100
>>> RR100.dps
29
>>> RR100(1) / RR100(3)
0.33333333333333333333333333333
然而,这里的实现存在一个 bug,实际上所有RealElement
都使用了全局精度设置。这意味着刚刚创建的RR100
已经改变了全局精度,我们需要在这里的 doctest 中恢复它:
>>> RR(1) / RR(3) # wrong result!
0.33333333333333333333333333333
>>> dummy = RealField(53) # hack to restore precision
>>> RR(1) / RR(3) # restored
0.333333333333333
(显然,这应该被修复!)
代数数域
有理数的代数扩张称为代数数域,在 sympy 中实现为 QQ。这些的自然语法应该类似于QQ(sqrt(2))
,但是QQ()
已经被重载为 QQ 元素的构造函数。这些域可以使用algebraic_field()
方法创建,例如QQ.algebraic_field(sqrt(2))
。所得到的域将是AlgebraicField
的一个实例,其元素为ANP
的实例。
对于这些的打印支持较少,但我们可以使用to_sympy()
来利用对应的Expr
打印支持:
>>> K = QQ.algebraic_field(sqrt(2))
>>> K
QQ<sqrt(2)>
>>> b = K.one + K.from_sympy(sqrt(2))
>>> b
ANP([1, 1], [1, 0, -2], QQ)
>>> K.to_sympy(b)
1 + sqrt(2)
>>> b ** 2
ANP([2, 3], [1, 0, -2], QQ)
>>> K.to_sympy(b**2)
2*sqrt(2) + 3
原始打印显示立即显示了元素的内部表示,作为ANP
实例。域(\mathbb{Q}(\sqrt{2}))由形如(a\sqrt{2}+b)的数构成,其中(a)和(b)是有理数。因此,这个域中的每个数可以表示为一对(a, b)
,它们是 QQ 元素的元素。域元素将这两个元素存储在列表中,并且还存储扩展元素(\sqrt{2})的最小多项式的列表表示。有一个 sympy 函数minpoly()
可以计算有理数上任意代数表达式的最小多项式:
>>> from sympy import minpoly, Symbol
>>> x = Symbol('x')
>>> minpoly(sqrt(2), x)
x**2 - 2
在作为系数列表的稠密多项式表示中,该多项式如上所示为[1, 0, -2]
,如ANP
中QQ<sqrt(2)>
元素的显示。
也可以创建具有多个生成元的代数数域,例如(\mathbb{Q}(\sqrt{2},\sqrt{3})):
>>> K = QQ.algebraic_field(sqrt(2), sqrt(3))
>>> K
QQ<sqrt(2) + sqrt(3)>
>>> sqrt2 = K.from_sympy(sqrt(2))
>>> sqrt3 = K.from_sympy(sqrt(3))
>>> p = (K.one + sqrt2) * (K.one + sqrt3)
>>> p
ANP([1/2, 1, -3/2], [1, 0, -10, 0, 1], QQ)
>>> K.to_sympy(p)
1 + sqrt(2) + sqrt(3) + sqrt(6)
>>> K.to_sympy(p**2)
4*sqrt(6) + 6*sqrt(3) + 8*sqrt(2) + 12
这里的代数扩展(\mathbb{Q}(\sqrt{2},\sqrt{3}))被转换为(同构的)(\mathbb{Q}(\sqrt{2}+\sqrt{3})),具有单个生成元(\sqrt{2}+\sqrt{3})。由于原始元定理,总是可以找到类似这样的单一生成元。有一个 sympy 函数primitive_element()
,可以计算扩展的原始元的最小多项式:
>>> from sympy import primitive_element, minpoly
>>> e = primitive_element([sqrt(2), sqrt(3)], x)
>>> e[0]
x**4 - 10*x**2 + 1
>>> e[0].subs(x, sqrt(2) + sqrt(3)).expand()
0
最小多项式x**4 - 10*x**2 + 1
具有密集列表表示[1, 0, -10, 0, 1]
,如上述ANP
输出。原始元定理的含义是,所有代数数域都可以表示为有某个最小多项式的有理数扩展。在代数数域上的计算只需利用最小多项式,这使得可以计算所有算术操作,还可以进行如多项式因式分解等更高级别的操作。
多项式环域
多项式环也实现了表示像K[x]这样的环,其中K
域中的系数是生成元x
的多项式:
>>> from sympy import ZZ, symbols
>>> x = symbols('x')
>>> K = ZZ[x]
>>> K
ZZ[x]
>>> x_dom = K(x)
>>> x_dom + K.one
x + 1
所有前述讨论的操作都适用于多项式环的元素:
>>> p = x_dom + K.one
>>> p
x + 1
>>> p + p
2*x + 2
>>> p - p
0
>>> p * p
x**2 + 2*x + 1
>>> p ** 3
x**3 + 3*x**2 + 3*x + 1
>>> K.exquo(x_dom**2 - K.one, x_dom - K.one)
x + 1
K[x]
的元素的内部表示不同于普通 sympy(Expr
)表达式的表示方式。任何表达式的Expr
表示都是作为一个树,例如:
>>> from sympy import srepr
>>> K = ZZ[x]
>>> p_expr = x**2 + 2*x + 1
>>> p_expr
x**2 + 2*x + 1
>>> srepr(p_expr)
"Add(Pow(Symbol('x'), Integer(2)), Mul(Integer(2), Symbol('x')), Integer(1))"
这里表达式是一个树,顶部节点是Add
,其子节点是Pow
等。这种树形表示使得可以以不同的方式表示等价表达式,例如:
>>> x = symbols('x')
>>> p_expr = x*(x + 1) + x
>>> p_expr
x*(x + 1) + x
>>> p_expr.expand()
x**2 + 2*x
对比之下,域ZZ[x]
仅表示多项式,并通过简单地存储展开多项式的非零系数来实现(“稀疏”多项式表示)。特别地,ZZ[x]
的元素被表示为 Python dict
。它们的类型是PolyElement
,它是dict
的一个子类。将其转换为普通的dict
显示内部表示:
>>> x = symbols('x')
>>> K = ZZ[x]
>>> x_dom = K(x)
>>> p_dom = K(3)*x_dom**2 + K(2)*x_dom + K(7)
>>> p_dom
3*x**2 + 2*x + 7
>>> dict(p_dom)
{(0,): 7, (1,): 2, (2,): 3}
这种内部形式使得无法表示未展开的乘法,因此ZZ[x]
元素的任何乘法都将被展开:
>>> x = symbols('x')
>>> K = ZZ[x]
>>> x_dom = K(x)
>>> p_expr = x * (x + 1) + x
>>> p_expr
x*(x + 1) + x
>>> p_dom = x_dom * (x_dom + K.one) + x_dom
>>> p_dom
x**2 + 2*x
这些相同的考虑也适用于幂次:
>>> (x + 1) ** 2
(x + 1)**2
>>> (x_dom + K.one) ** 2
x**2 + 2*x + 1
我们还可以构造多变量多项式环:
>>> x, y = symbols('x, y')
>>> K = ZZ[x,y]
>>> xk = K(x)
>>> yk = K(y)
>>> xk**2*yk + xk + yk
x**2*y + x + y
也可以构造嵌套的多项式环(尽管效率较低)。环K[x][y]
在形式上等价于K[x,y]
,尽管它们在 sympy 中的实现不同:
>>> K = ZZ[x][y]
>>> p = K(x**2 + x*y + y**2)
>>> p
y**2 + x*y + x**2
>>> dict(p)
{(0,): x**2, (1,): x, (2,): 1}
这里像x**2
这样的系数也是PolyElement
的实例,因此这是一个dict
,其中值也是dict
。完整的表示更像是:
>>> {k: dict(v) for k, v in p.items()}
{(0,): {(2,): 1}, (1,): {(1,): 1}, (2,): {(0,): 1}}
多变量环域ZZ[x,y]
作为一个单一扁平化的dict
有更高效的表示:
>>> K = ZZ[x,y]
>>> p = K(x**2 + x*y + y**2)
>>> p
x**2 + x*y + y**2
>>> dict(p)
{(0, 2): 1, (1, 1): 1, (2, 0): 1}
这些表示方式之间的效率差异随生成器数量的增加而增大,即ZZ[x,y,z,t,...]
与ZZ[x][y][z][t]...
。
旧(密集)多项式环
在上一节中,我们看到多项式环如K[x]的域表示使用了将单项式指数映射到系数的稀疏多项式表示。还有一个使用密集 DMP 表示的K[x]的旧版本。我们可以使用poly_ring()
和old_poly_ring()
创建这两个版本的K[x],其中语法K[x]
等同于K.poly_ring(x)
:
>>> K1 = ZZ.poly_ring(x)
>>> K2 = ZZ.old_poly_ring(x)
>>> K1
ZZ[x]
>>> K2
ZZ[x]
>>> K1 == ZZ[x]
True
>>> K2 == ZZ[x]
False
>>> p1 = K1.from_sympy(x**2 + 1)
>>> p2 = K2.from_sympy(x**2 + 1)
>>> p1
x**2 + 1
>>> p2
DMP_Python([1, 0, 1], ZZ)
>>> type(K1)
<class 'sympy.polys.domains.polynomialring.PolynomialRing'>
>>> type(p1)
<class 'sympy.polys.rings.PolyElement'>
>>> type(K2)
<class 'sympy.polys.domains.old_polynomialring.GlobalPolynomialRing'>
>>> type(p2)
<class 'sympy.polys.polyclasses.DMP_Python'>
旧多项式环域的内部表示是DMP
表示,作为(列表的)系数:
>>> repr(p2)
'DMP_Python([1, 0, 1], ZZ, ZZ[x])'
多项式的DMP
表示法最显著的用途是作为Poly
内部表示(本文档后面会进一步讨论)。
PolyRing vs PolynomialRing
你可能只是想在某个特定多项式环中执行计算,而不用担心为任意域实现某些功能。在这种情况下,你可以直接使用ring()
函数构造环:
>>> from sympy import ring
>>> K, xr, yr = ring([x, y], ZZ)
>>> K
Polynomial ring in x, y over ZZ with lex order
>>> xr**2 - yr**2
x**2 - y**2
>>> (xr**2 - yr**2) // (xr - yr)
x + y
这里的对象K
表示环,并且是PolyRing
的一个实例,但不是多项式域(不是Domain
子类的实例,因此不能与Poly
一起使用)。这样,多项式环的实现可以独立于域系统使用。
域系统的目的是提供一个统一的接口,用于处理和转换表达式的不同表示形式。为了使PolyRing
实现在这一背景下可用,PolynomialRing
类是对PolyRing
类的包装,提供了域系统期望的接口。这使得多项式环的此实现可用作设计用于处理来自不同域的表达式的更广泛代码库的一部分。多项式环的域是与由ring()
返回的环不同的对象,尽管它们都具有相同的元素:
>>> K, xr, yr = ring([x, y], ZZ)
>>> K
Polynomial ring in x, y over ZZ with lex order
>>> K2 = ZZ[x,y]
>>> K2
ZZ[x,y]
>>> K2.ring
Polynomial ring in x, y over ZZ with lex order
>>> K2.ring == K
True
>>> K(x+y)
x + y
>>> K2(x+y)
x + y
>>> type(K(x+y))
<class 'sympy.polys.rings.PolyElement'>
>>> type(K2(x+y))
<class 'sympy.polys.rings.PolyElement'>
>>> K(x+y) == K2(x+y)
True
有理函数域
有些域被分类为域,而其他则不是。域与非域域之间的主要区别在于,在域中,总是可以用任何非零元素除以任何元素。通常可以通过get_field()
方法将任何域转换为包含该域的域:
>>> from sympy import ZZ, QQ, symbols
>>> x, y = symbols('x, y')
>>> ZZ.is_Field
False
>>> QQ.is_Field
True
>>> QQ[x]
QQ[x]
>>> QQ[x].is_Field
False
>>> QQ[x].get_field()
QQ(x)
>>> QQ[x].get_field().is_Field
True
>>> QQ.frac_field(x)
QQ(x)
这引入了一个新的域类型 K(x),表示在另一个域 K
上生成器 x
的有理函数域。不可能使用 ()
语法构造域 QQ(x)
,因此创建它的最简单方法是使用域方法 frac_field()
(QQ.frac_field(x)
) 或 get_field()
(QQ[x].get_field()
)。frac_field()
方法是更直接的方法。
有理函数域 K(x) 是 RationalField
的一个实例。该域表示形式为 (p(x) / q(x)) 的函数,其中 (p) 和 (q) 是多项式。域元素表示为 K[x] 中的一对多项式:
>>> K = QQ.frac_field(x)
>>> xk = K(x)
>>> f = xk / (K.one + xk**2)
>>> f
x/(x**2 + 1)
>>> f.numer
x
>>> f.denom
x**2 + 1
>>> QQ[x].of_type(f.numer)
True
>>> QQ[x].of_type(f.denom)
True
在这个域中分子和分母之间的约分是自动进行的:
>>> p1 = xk**2 - 1
>>> p2 = xk - 1
>>> p1
x**2 - 1
>>> p2
x - 1
>>> p1 / p2
x + 1
计算这种约分可能会很慢,这使得有理函数域可能比多项式环或代数域慢。
就像多项式环的情况一样,有分数域既有新(稀疏)版本也有旧(稠密)版本。
>>> K1 = QQ.frac_field(x)
>>> K2 = QQ.old_frac_field(x)
>>> K1
QQ(x)
>>> K2
QQ(x)
>>> type(K1)
<class 'sympy.polys.domains.fractionfield.FractionField'>
>>> type(K2)
<class 'sympy.polys.domains.old_fractionfield.FractionField'>
就像多项式环的情况一样,有理函数域的实现可以独立于域系统使用:
>>> from sympy import field
>>> K, xf, yf = field([x, y], ZZ)
>>> xf / (1 - yf)
-x/(y - 1)
这里 K
是 FracField
的一个实例,而不是 RationalField
,后者适用于域 ZZ(x,y)
。
表达式域
最后要考虑的域是“表达式域”,也称为 EX。使用其他域无法表示的表达式始终可以使用表达式域表示。EX 的元素实际上只是 Expr
实例的包装器:
>>> from sympy import EX
>>> p = EX.from_sympy(1 + x)
>>> p
EX(x + 1)
>>> type(p)
<class 'sympy.polys.domains.expressiondomain.ExpressionDomain.Expression'>
>>> p.ex
x + 1
>>> type(p.ex)
<class 'sympy.core.add.Add'>
对于其他域,表达式的域表示通常比由Expr
使用的树表示更有效。在 EX 中,内部表示是Expr
,因此显然不是更有效。EX 域的目的是能够用与其他域一致的接口包装任意表达式。当找不到合适的域表示时,EX 域作为备用使用。尽管这并未提供特定的效率,但允许实现的算法在处理没有适当域表示的表达式时仍可用。
选择一个域
在上述描述的工作流程中,思路是从一些 sympy 表达式开始,选择一个域,并将所有表达式转换为该域,以便执行一些计算。显然产生的问题是如何选择适当的域来表示一些 sympy 表达式。为此,有一个函数construct_domain()
,它接受一个表达式列表,并将选择一个域并将所有表达式转换为该域:
>>> from sympy import construct_domain, Integer
>>> elements_sympy = [Integer(3), Integer(2)] # elements as Expr instances
>>> elements_sympy
[3, 2]
>>> K, elements_K = construct_domain(elements_sympy)
>>> K
ZZ
>>> elements_K
[3, 2]
>>> type(elements_sympy[0])
<class 'sympy.core.numbers.Integer'>
>>> type(elements_K[0])
<class 'int'>
在这个例子中,我们看到两个整数3
和2
可以在域 ZZ 中表示。这些表达式已被转换为该域的元素,在这种情况下意味着int
类型而不是Expr
的实例。当输入可以被 sympify 时,不需要显式创建Expr
实例,因此例如construct_domain([3, 2])
将给出与上述相同的输出。
给定更复杂的输入,construct_domain()
将选择更复杂的域:
>>> from sympy import Rational, symbols
>>> x, y = symbols('x, y')
>>> construct_domain([Rational(1, 2), Integer(3)])[0]
QQ
>>> construct_domain([2*x, 3])[0]
ZZ[x]
>>> construct_domain([x/2, 3])[0]
QQ[x]
>>> construct_domain([2/x, 3])[0]
ZZ(x)
>>> construct_domain([x, y])[0]
ZZ[x,y]
如果在输入中发现任何非整数有理数,则基础域将是 QQ 而不是 ZZ。如果输入中发现任何符号,则将创建一个PolynomialRing
。如果输入中有多个符号,则还可以创建一个多变量多项式环如QQ[x,y]
。如果分母中出现任何符号,则将创建一个RationalField
,例如QQ(x)
。
上述一些领域是域,其他则是(非域)环。在某些情境下,需要一个域领域,以便进行除法操作,为此construct_domain()
提供了一个field=True
选项,即使表达式可以在非域环中表示,也将强制构造一个域领域:
>>> construct_domain([1, 2], field=True)[0]
QQ
>>> construct_domain([2*x, 3], field=True)[0]
ZZ(x)
>>> construct_domain([x/2, 3], field=True)[0]
ZZ(x)
>>> construct_domain([2/x, 3], field=True)[0]
ZZ(x)
>>> construct_domain([x, y], field=True)[0]
ZZ(x,y)
默认情况下,construct_domain()
不会构造代数扩展域,而是使用 EX 域(ExpressionDomain
)。关键字参数 extension=True
可用于构造一个AlgebraicField
,如果输入是无理但代数的。
>>> from sympy import sqrt
>>> construct_domain([sqrt(2)])[0]
EX
>>> construct_domain([sqrt(2)], extension=True)[0]
QQ<sqrt(2)>
>>> construct_domain([sqrt(2), sqrt(3)], extension=True)[0]
QQ<sqrt(2) + sqrt(3)>
当输入中存在代数独立的超越元素时,将构造一个PolynomialRing
或RationalField
,将这些超越元素视为生成器:
>>> from sympy import sin, cos
>>> construct_domain([sin(x), y])[0]
ZZ[y,sin(x)]
但是,如果存在输入不是代数独立的可能性,则该领域将是 EX:
>>> construct_domain([sin(x), cos(x)])[0]
EX
这里 sin(x)
和 cos(x)
并不是代数独立的,因为 sin(x)**2 + cos(x)**2 = 1
。
在不同领域之间转换元素
在不同领域中进行的计算通常是有用的。然而,重要的是避免将领域元素与普通的 sympy 表达式和其他 Python 类型混合,同样重要的是避免将来自不同领域的元素混合。convert_from()
方法用于将一个领域的元素转换为另一个领域的元素:
>>> num_zz = ZZ(3)
>>> ZZ.of_type(num_zz)
True
>>> num_qq = QQ.convert_from(num_zz, ZZ)
>>> ZZ.of_type(num_qq)
False
>>> QQ.of_type(num_qq)
True
可以调用convert()
方法,而不需要指定源领域作为第二个参数,例如:
>>> QQ.convert(ZZ(2))
2
这是因为 convert()
可以检查 ZZ(2)
的类型,并尝试确定它是哪个域 (ZZ) 的元素。像 ZZ 和 QQ 这样的某些域被视为特殊情况,以使其工作。更复杂域的元素是 DomainElement
的子类实例,该类具有 parent()
方法,可以识别元素所属的域。例如在多项式环 ZZ[x]
中我们有:
>>> from sympy import ZZ, Symbol
>>> x = Symbol('x')
>>> K = ZZ[x]
>>> K
ZZ[x]
>>> p = K(x) + K.one
>>> p
x + 1
>>> type(p)
<class 'sympy.polys.rings.PolyElement'>
>>> p.parent()
ZZ[x]
>>> p.parent() == K
True
不过,通过将源域指定为第二个参数调用 convert_from()
更为高效:
>>> QQ.convert_from(ZZ(2), ZZ)
2
统一域
当我们想要结合来自两个不同域的元素,并对它们进行混合计算时,我们需要
-
选择一个能表示两者所有元素的新域。
-
将所有元素转换到新域。
-
在新域中执行计算。
从第 1 点中产生的关键问题是如何选择一个能够表示两个域元素的域。为此,有 unify()
方法:
>>> x1, K1 = ZZ(2), ZZ
>>> y2, K2 = QQ(3, 2), QQ
>>> K1
ZZ
>>> K2
QQ
>>> K3 = K1.unify(K2)
>>> K3
QQ
>>> x3 = K3.convert_from(x1, K1)
>>> y3 = K3.convert_from(y2, K2)
>>> x3 + y3
7/2
unify()
方法将找到一个包含两个域的公共域,在这个例子中 ZZ.unify(QQ)
得到的是 QQ,因为 ZZ 的每个元素都可以表示为 QQ 的元素。这意味着所有的输入 (x1
和 y2
) 都可以转换为公共域 K3
中的元素(作为 x3
和 y3
)。一旦在公共域中,我们可以安全地使用像 +
这样的算术操作。在这个例子中,一个域是另一个域的超集,我们看到 K1.unify(K2) == K2
,所以实际上不需要转换 y2
。总的来说,然而 K1.unify(K2)
可以给出一个既不等于 K1
也不等于 K2
的新域。
unify()
方法理解如何组合不同的多项式环域以及如何统一基础域:
>>> ZZ[x].unify(ZZ[y])
ZZ[x,y]
>>> ZZ[x,y].unify(ZZ[y])
ZZ[x,y]
>>> ZZ[x].unify(QQ)
QQ[x]
同样可以统一代数域和有理函数域:
>>> K1 = QQ.algebraic_field(sqrt(2))[x]
>>> K2 = QQ.algebraic_field(sqrt(3))[y]
>>> K1
QQ<sqrt(2)>[x]
>>> K2
QQ<sqrt(3)>[y]
>>> K1.unify(K2)
QQ<sqrt(2) + sqrt(3)>[x,y]
>>> QQ.frac_field(x).unify(ZZ[y])
ZZ(x,y)
多项式内部
现在我们可以理解 Poly
类在内部如何工作。这是 Poly
的公共接口:
>>> from sympy import Poly, symbols, ZZ
>>> x, y, z, t = symbols('x, y, z, t')
>>> p = Poly(x**2 + 1, x, domain=ZZ)
>>> p
Poly(x**2 + 1, x, domain='ZZ')
>>> p.gens
(x,)
>>> p.domain
ZZ
>>> p.all_coeffs()
[1, 0, 1]
>>> p.as_expr()
x**2 + 1
这是Poly
的内部实现:
>>> d = p.rep # internal representation of Poly
>>> d
DMP_Python([1, 0, 1], ZZ)
>>> d.rep # internal representation of DMP
[1, 0, 1]
>>> type(d.rep)
<class 'list'>
>>> type(d.rep[0])
<class 'int'>
>>> d.dom
ZZ
Poly
实例的内部表示是一个DMP
的实例,它是旧多项式环域old_poly_ring()
中用于域元素的类。它将多项式表示为系数列表,这些系数本身是域的元素,并保持对它们域的引用(在本例中是 ZZ)。
选择一个 Poly 的域。
如果没有为Poly
构造器指定域,则会使用construct_domain()
推断。像field=True
这样的参数会传递给construct_domain()
:
>>> from sympy import sqrt
>>> Poly(x**2 + 1, x)
Poly(x**2 + 1, x, domain='ZZ')
>>> Poly(x**2 + 1, x, field=True)
Poly(x**2 + 1, x, domain='QQ')
>>> Poly(x**2/2 + 1, x)
Poly(1/2*x**2 + 1, x, domain='QQ')
>>> Poly(x**2 + sqrt(2), x)
Poly(x**2 + sqrt(2), x, domain='EX')
>>> Poly(x**2 + sqrt(2), x, extension=True)
Poly(x**2 + sqrt(2), x, domain='QQ<sqrt(2)>')
也可以使用扩展参数来指定扩展的生成器,即使不需要扩展来表示系数,尽管直接使用construct_domain()
时无法使用。扩展元素列表将传递给primitive_element()
以创建适当的AlgebraicField
域:
>>> from sympy import construct_domain
>>> Poly(x**2 + 1, x)
Poly(x**2 + 1, x, domain='ZZ')
>>> Poly(x**2 + 1, x, extension=sqrt(2))
Poly(x**2 + 1, x, domain='QQ<sqrt(2)>')
>>> Poly(x**2 + 1, x, extension=[sqrt(2), sqrt(3)])
Poly(x**2 + 1, x, domain='QQ<sqrt(2) + sqrt(3)>')
>>> construct_domain([1, 0, 1], extension=sqrt(2))[0]
ZZ
(或许construct_domain()
在这里应该像Poly
一样做…)
选择生成器。
如果除了生成器之外还有其他符号,则会创建多项式环或有理函数域域。在这种情况下,系数使用的域是稀疏(“new”)多项式环:
>>> p = Poly(x**2*y + z, x)
>>> p
Poly(y*x**2 + z, x, domain='ZZ[y,z]')
>>> p.gens
(x,)
>>> p.domain
ZZ[y,z]
>>> p.domain == ZZ[y,z]
True
>>> p.domain == ZZ.poly_ring(y, z)
True
>>> p.domain == ZZ.old_poly_ring(y, z)
False
>>> p.rep.rep
[y, 0, z]
>>> p.rep.rep[0]
y
>>> type(p.rep.rep[0])
<class 'sympy.polys.rings.PolyElement'>
>>> dict(p.rep.rep[0])
{(1, 0): 1}
这里我们有一种稠密和稀疏实现的奇怪混合体。Poly
实例将自己视为生成器x
的单变量多项式,但系数来自域ZZ[y,z]
。Poly
的内部表示是“稠密单变量多项式”(DUP)格式的系数列表。然而,每个系数都是在y
和z
中稀疏多项式的实现。
如果我们将x
、y
和z
都作为Poly
的生成器,则得到完全密集的 DMP 列表表示:
>>> p = Poly(x**2*y + z, x, y, z)
>>> p
Poly(x**2*y + z, x, y, z, domain='ZZ')
>>> p.rep
DMP_Python([[[1], []], [[]], [[1, 0]]], ZZ)
>>> p.rep.rep
[[[1], []], [[]], [[1, 0]]]
>>> p.rep.rep[0][0][0]
1
>>> type(p.rep.rep[0][0][0])
<class 'int'>
另一方面,我们可以通过选择一个表达式中根本不存在的生成器,为Poly
创建完全稀疏的表示:
>>> p = Poly(x**2*y + z, t)
>>> p
Poly(x**2*y + z, t, domain='ZZ[x,y,z]')
>>> p.rep
DMP_Python([x**2*y + z], ZZ[x,y,z])
>>> p.rep.rep[0]
x**2*y + z
>>> type(p.rep.rep[0])
<class 'sympy.polys.rings.PolyElement'>
>>> dict(p.rep.rep[0])
{(0, 0, 1): 1, (2, 1, 0): 1}
如果未向Poly
构造函数提供生成器,则将尝试选择生成器,使表达式在这些生成器上是多项式的。在表达式是一些符号的多项式表达式的常见情况下,这些符号将被视为生成器。然而,其他非符号表达式也可以被视为生成器:
>>> Poly(x**2*y + z)
Poly(x**2*y + z, x, y, z, domain='ZZ')
>>> from sympy import pi, exp
>>> Poly(exp(x) + exp(2*x) + 1)
Poly((exp(x))**2 + (exp(x)) + 1, exp(x), domain='ZZ')
>>> Poly(pi*x)
Poly(x*pi, x, pi, domain='ZZ')
>>> Poly(pi*x, x)
Poly(pi*x, x, domain='ZZ[pi]')
代数相关的生成器。
将exp(x)
或pi
作为Poly
或其多项式环域的生成器是数学上有效的,因为这些对象是超越的,所以包含它们的环扩展同构于多项式环。由于x
和exp(x)
是代数无关的,因此也可以同时将它们作为同一个Poly
的生成器使用。然而,一些其他的生成器组合是无效的,比如x
和sqrt(x)
或sin(x)
和cos(x)
。这些例子是无效的,因为生成器不是代数无关的(例如sqrt(x)**2 = x
和sin(x)**2 + cos(x)**2 = 1
)。尽管如此,该实现无法检测这些代数关系:
>>> from sympy import sin, cos, sqrt
>>> Poly(x*exp(x)) # fine
Poly(x*(exp(x)), x, exp(x), domain='ZZ')
>>> Poly(sin(x)+cos(x)) # not fine
Poly((cos(x)) + (sin(x)), cos(x), sin(x), domain='ZZ')
>>> Poly(x + sqrt(x)) # not fine
Poly(x + (sqrt(x)), x, sqrt(x), domain='ZZ')
对于像这样的Poly
进行计算是不可靠的,因为在这种实现中零测试将无法正常工作:
>>> p1 = Poly(x, x, sqrt(x))
>>> p2 = Poly(sqrt(x), x, sqrt(x))
>>> p1
Poly(x, x, sqrt(x), domain='ZZ')
>>> p2
Poly((sqrt(x)), x, sqrt(x), domain='ZZ')
>>> p3 = p1 - p2**2
>>> p3 # should be zero...
Poly(x - (sqrt(x))**2, x, sqrt(x), domain='ZZ')
>>> p3.as_expr()
0
可以通过以下方式改进Poly
的这一方面:
-
通过引入能够表示更多代数扩展类的新域来扩展域系统。
-
在
construct_domain()
中改进代数依赖的检测。 -
改进生成器的自动选择。
上述示例表明,拥有一个能够表示更一般的代数扩展的域将非常有用(代数域
仅适用于 QQ 的扩展)。改进代数依赖的检测更加困难,但至少可以处理像sin(x)
和cos(x)
这样的常见情况。在选择生成器时,应能够认识到sqrt(x)
可以是x + sqrt(x)
的唯一生成器:
>>> Poly(x + sqrt(x)) # this could be improved!
Poly(x + (sqrt(x)), x, sqrt(x), domain='ZZ')
>>> Poly(x + sqrt(x), sqrt(x)) # this could be improved!
Poly((sqrt(x)) + x, sqrt(x), domain='ZZ[x]')
多项式域的参考文档
此页面列出了 polys 模块中域的参考文档。推荐阅读模块的基本功能以获得 polys 模块的一般介绍。建议阅读介绍多项式模块中的域以了解域系统的基本功能和使用方法的介绍。此页面列出了Domain
类及其子类(例如 ZZ
等具体域)的参考文档,以及表示域元素的类。
域
这里我们记录了各种已实现的基础域(详见介绍多项式模块中的域)。有三种Domain
子类:抽象域、具体域和“实现域”。抽象域不能(有用地)被实例化,并且仅仅汇集了许多其他域共享的功能。具体域意味着可以实例化并用于多项式操作算法中。在某些情况下,实现数据类型的方式有多种可能性。例如,依赖于系统上可用的库,整数可以使用 Python 内置整数或使用 gmpy 实现。请注意,根据可用的库会自动创建各种别名。因此,例如 ZZ
总是指向系统中最有效的整数环的实现。
抽象域
class sympy.polys.domains.domain.Domain
polys 域系统中所有域的超类。
参见介绍多项式模块中的域以了解域系统的介绍。
Domain
类是所有具体域类型的抽象基类。有许多不同的Domain
子类,每个子类都有一个关联的 dtype
,它是表示域元素的类。Poly
的系数是域的元素,必须是 Domain
的子类。
示例
最常见的示例域是整数 ZZ 和有理数 QQ。
>>> from sympy import Poly, symbols, Domain
>>> x, y = symbols('x, y')
>>> p = Poly(x**2 + y)
>>> p
Poly(x**2 + y, x, y, domain='ZZ')
>>> p.domain
ZZ
>>> isinstance(p.domain, Domain)
True
>>> Poly(x**2 + y/2)
Poly(x**2 + 1/2*y, x, y, domain='QQ')
可以直接使用域对象(例如 (ZZ 或 QQ)作为 dtype
元素的构造函数。
>>> from sympy import ZZ, QQ
>>> ZZ(2)
2
>>> ZZ.dtype
<class 'int'>
>>> type(ZZ(2))
<class 'int'>
>>> QQ(1, 2)
1/2
>>> type(QQ(1, 2))
<class 'sympy.polys.domains.pythonrational.PythonRational'>
相应的域元素可以用于算术运算 +,-,*,**
,根据域的不同,可能还可以使用 /,//,%
的某些组合。例如,在 ZZ 中,//
(地板除法)和 %
(模除法)都可以使用,但 /
(真除法)不能使用。由于 QQ 是一个 Field
,它的元素可以使用 /
,但不应使用 //
和 %
。一些域有 gcd()
方法。
>>> ZZ(2) + ZZ(3)
5
>>> ZZ(5) // ZZ(2)
2
>>> ZZ(5) % ZZ(2)
1
>>> QQ(1, 2) / QQ(2, 3)
3/4
>>> ZZ.gcd(ZZ(4), ZZ(2))
2
>>> QQ.gcd(QQ(2,7), QQ(5,3))
1/21
>>> ZZ.is_Field
False
>>> QQ.is_Field
True
还有许多其他的域,包括:
每个域都由一个域对象和一个元素域的实现类(dtype
)表示。例如,K[x] 域由一个域对象表示,该对象是 PolynomialRing
的一个实例,其元素始终是 PolyElement
的实例。这个实现类以比 SymPy 表达式(类型为 Expr
)更高效的方式表示特定类型的数学表达式。域方法 from_sympy()
和 to_sympy()
用于在 Expr
和域元素之间进行转换。
>>> from sympy import Symbol, ZZ, Expr
>>> x = Symbol('x')
>>> K = ZZ[x] # polynomial ring domain
>>> K
ZZ[x]
>>> type(K) # class of the domain
<class 'sympy.polys.domains.polynomialring.PolynomialRing'>
>>> K.dtype # class of the elements
<class 'sympy.polys.rings.PolyElement'>
>>> p_expr = x**2 + 1 # Expr
>>> p_expr
x**2 + 1
>>> type(p_expr)
<class 'sympy.core.add.Add'>
>>> isinstance(p_expr, Expr)
True
>>> p_domain = K.from_sympy(p_expr)
>>> p_domain # domain element
x**2 + 1
>>> type(p_domain)
<class 'sympy.polys.rings.PolyElement'>
>>> K.to_sympy(p_domain) == p_expr
True
方法 convert_from()
用于将域元素从一个域转换到另一个域。
>>> from sympy import ZZ, QQ
>>> ez = ZZ(2)
>>> eq = QQ.convert_from(ez, ZZ)
>>> type(ez)
<class 'int'>
>>> type(eq)
<class 'sympy.polys.domains.pythonrational.PythonRational'>
不同域的元素不应混合在算术或其他操作中:它们应首先转换为一个公共域。域方法 unify()
用于找到一个可以表示两个给定域所有元素的域。
>>> from sympy import ZZ, QQ, symbols
>>> x, y = symbols('x, y')
>>> ZZ.unify(QQ)
QQ
>>> ZZ[x].unify(QQ)
QQ[x]
>>> ZZ[x].unify(QQ[y])
QQ[x,y]
如果一个域是 Ring
,那么可能有一个关联的 Field
,反之亦然。方法 get_field()
和 get_ring()
将找到或创建相关联的域。
>>> from sympy import ZZ, QQ, Symbol
>>> x = Symbol('x')
>>> ZZ.has_assoc_Field
True
>>> ZZ.get_field()
QQ
>>> QQ.has_assoc_Ring
True
>>> QQ.get_ring()
ZZ
>>> K = QQ[x]
>>> K
QQ[x]
>>> K.get_field()
QQ(x)
另见
DomainElement
一些表达式的最小域的抽象基类
construct_domain
构造一些表达式的最小域。
abs(a)
a
的绝对值,意味着 __abs__
。
add(a, b)
a
和 b
的和,意味着 __add__
。
alg_field_from_poly(poly, alias=None, root_index=-1)
便捷方法,根据根索引在多项式的根上构造代数扩展。
参数:
poly : Poly
生成扩展的多项式。
alias : 字符串,可选(默认为 None)
扩展的生成器的符号名称。例如“alpha”或“theta”。
root_index : 整数,可选(默认为-1)
指定所需的多项式根。排序方式由
ComplexRootOf
类定义。在二次和旋转多边形场合的常见情况下,默认值为-1
选择最自然的选择(正实轴或虚轴上的平方根,即 (\mathrm{e}^{2\pi i/n}))。
示例
>>> from sympy import QQ, Poly
>>> from sympy.abc import x
>>> f = Poly(x**2 - 2)
>>> K = QQ.alg_field_from_poly(f)
>>> K.ext.minpoly == f
True
>>> g = Poly(8*x**3 - 6*x - 1)
>>> L = QQ.alg_field_from_poly(g, "alpha")
>>> L.ext.minpoly == g
True
>>> L.to_sympy(L([1, 1, 1]))
alpha**2 + alpha + 1
algebraic_field(*extension, alias=None)
返回一个代数域,即 (K(\alpha, \ldots))。
almosteq(a, b, tolerance=None)
检查 a
和 b
是否几乎相等。
characteristic()
返回此域的特征。
cofactors(a, b)
返回 a
和 b
的最大公因数及其余子。
convert(element, base=None)
将 element
转换为 self.dtype
。
convert_from(element, base)
根据基域给定的域元素将 element
转换为 self.dtype
。
cyclotomic_field(n, ss=False, alias='zeta', gen=None, root_index=-1)
便捷方法,构造旋转多边形场。
参数:
n : 整数
构造第
n
个旋转多边形场。
ss : 布尔值,可选(默认为 False)
如果为真,在别名字符串上附加 n 作为下标。
alias : 字符串,可选(默认为“zeta”)
生成器的符号名称。
gen : Symbol
,可选(默认为 None)
欲定义该领域的旋转多边形的变量。如果为
None
,将使用虚拟变量。
root_index : 整数,可选(默认为-1)
指定所需的多项式根。排序方式由
ComplexRootOf
类定义。默认值为-1
选择根 (\mathrm{e}^{2\pi i/n})。
示例
>>> from sympy import QQ, latex
>>> K = QQ.cyclotomic_field(5)
>>> K.to_sympy(K([-1, 1]))
1 - zeta
>>> L = QQ.cyclotomic_field(7, True)
>>> a = L.to_sympy(L([-1, 1]))
>>> print(a)
1 - zeta7
>>> print(latex(a))
1 - \zeta_{7}
denom(a)
返回 a
的分母。
div(a, b)
a 和 b 的商和余数。类似于 divmod(a, b)
参数:
a:域元素
被除数
b:域元素
除数
返回:
(q, r): 域元素的元组
商和余数
异常:
当除数为零时,抛出 ZeroDivisionError。
说明
在一些 Field
域上工作时,这与 divmod(a, b)
本质上相同,例如 QQ。在任意 Domain
上工作时,应使用 div()
方法而不是 divmod
。
关键不变性是,如果 q, r = K.div(a, b)
,那么 a == b*q + r
。
K.div(a, b)
的结果与元组 (K.quo(a, b), K.rem(a, b))
相同,只是如果需要商和余数,则使用 div()
更有效率。
示例
我们可以使用 K.div
替代 divmod
进行地板除法和余数运算。
>>> from sympy import ZZ, QQ
>>> ZZ.div(ZZ(5), ZZ(2))
(2, 1)
如果 K
是一个 Field
,则除法总是精确的,并且余数为 zero
。
>>> QQ.div(QQ(5), QQ(2))
(5/2, 0)
注意事项
如果安装了 gmpy
,则 dtype
将使用 gmpy.mpq
类型作为 QQ 的类型。gmpy.mpq
类型定义了 divmod
,但其行为不佳,因此应使用 div()
而不是 divmod
。
>>> a = QQ(1)
>>> b = QQ(3, 2)
>>> a
mpq(1,1)
>>> b
mpq(3,2)
>>> divmod(a, b)
(mpz(0), mpq(1,1))
>>> QQ.div(a, b)
(mpq(2,3), mpq(0,1))
在 QQ 中使用 //
或 %
会导致不正确的结果,因此应使用 div()
。
参见
quo
模拟 a // b
rem
模拟 a % b
exquo
模拟 a / b
drop(*symbols)
从该域中删除生成器。
dtype: type | None = None
此 Domain
中元素的类型(类):
>>> from sympy import ZZ, QQ, Symbol
>>> ZZ.dtype
<class 'int'>
>>> z = ZZ(2)
>>> z
2
>>> type(z)
<class 'int'>
>>> type(z) == ZZ.dtype
True
每个域都有一个关联的 dtype(“数据类型”),即关联域元素的类。
参见
of_type
evalf(a, prec=None, **options)
返回 a
的数值近似。
exquo(a, b)
a 和 b 的精确商。模拟 a / b
。
参数:
a: 域元素
被除数
b: 域元素
除数
返回:
q: 域元素
精确商
引发:
ExactQuotientFailed: 如果无法进行精确除法。
ZeroDivisionError: 当除数为零时。
解释
这本质上与 a / b
相同,但如果除法不精确(即存在任何余数),则会引发错误,并且结果始终是域元素。在工作于不是 Field
的 Domain
中时(例如 ZZ 或 K[x]),应使用 exquo
而不是 /
。
关键不变量是如果 q = K.exquo(a, b)
(且 exquo
没有引发异常),则 a == b*q
。
例子
我们可以使用 K.exquo
而不是 /
进行精确除法。
>>> from sympy import ZZ
>>> ZZ.exquo(ZZ(4), ZZ(2))
2
>>> ZZ.exquo(ZZ(5), ZZ(2))
Traceback (most recent call last):
...
ExactQuotientFailed: 2 does not divide 5 in ZZ
在像 QQ 这样的 Field
上,除法(非零除数)总是精确的,因此在这种情况下可以使用 /
而不是 exquo()
。
>>> from sympy import QQ
>>> QQ.exquo(QQ(5), QQ(2))
5/2
>>> QQ(5) / QQ(2)
5/2
注意
由于默认的 dtype
对于 ZZ 是 int
(或 mpz
),所以应避免使用 a / b
,因为它会给出一个不是域元素的 float
。
>>> ZZ(4) / ZZ(2)
2.0
>>> ZZ(5) / ZZ(2)
2.5
另一方面,使用 (SYMPY_GROUND_TYPES=flint) 在 ZZ 中的元素是 flint.fmpz
,并且除法将引发异常:
>>> ZZ(4) / ZZ(2)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for /: 'fmpz' and 'fmpz'
在 ZZ 使用 /
将导致不正确的结果,因此应该使用 exquo()
而不是 /
。
参见
quo
a // b
的类似物
rem
a % b
的类似物
div
divmod(a, b)
的类似物
exsqrt(a)
如果 a
是平方的,域内 a
的主要平方根。
解释
此方法的实现应返回域内的元素 b
,使得 b * b == a
,如果没有这样的 b
则返回 None
。对于不精确的域如 RR 和 CC,在这个相等性上可以容忍微小差异。在可能的情况下,应遵循一致的规则选择“主要”平方根。
参见
sqrt
,is_square
frac_field(*symbols, order=LexOrder())
返回一个分式域,即 (K(X))。
from_AlgebraicField(a, K0)
将代数数转换为 dtype
。
from_ComplexField(a, K0)
将复数元素转换为 dtype
。
from_ExpressionDomain(a, K0)
将 EX
对象转换为 dtype
。
from_ExpressionRawDomain(a, K0)
将 EX
对象转换为 dtype
。
from_FF(a, K0)
将 ModularInteger(int)
转换为 dtype
。
from_FF_gmpy(a, K0)
将 ModularInteger(mpz)
转换为 dtype
。
from_FF_python(a, K0)
将 ModularInteger(int)
转换为 dtype
。
from_FractionField(a, K0)
将有理函数转换为 dtype
。
from_GlobalPolynomialRing(a, K0)
将多项式转换为 dtype
。
from_MonogenicFiniteExtension(a, K0)
将 ExtensionElement
转换为 dtype
。
from_PolynomialRing(a, K0)
将多项式转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq
对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python 的 Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将实数元素对象转换为dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz
对象转换为 dtype
。
from_ZZ_python(a, K0)
将 Python 的 int
对象转换为 dtype
。
from_sympy(a)
将 SymPy 表达式转换为该域的元素。
参数:
expr: Expr
一个普通的 SymPy 表达式,类型为
Expr
。
返回:
a: 域元素
该
Domain
的一个元素。
说明
参见to_sympy()
以获取说明和示例。
另见
to_sympy
, convert_from
gcd(a, b)
返回a
和b
的最大公约数。
gcdex(a, b)
a
和b
的扩展欧几里得算法。
get_exact()
返回与self
相关联的精确域。
get_field()
返回与self
相关联的域。
get_ring()
返回与self
相关联的环。
half_gcdex(a, b)
a
和b
的半扩展欧几里得算法。
has_assoc_Field = False
布尔标志,指示域是否具有关联的Field
。
>>> from sympy import ZZ
>>> ZZ.has_assoc_Field
True
>>> ZZ.get_field()
QQ
另见
is_Field
, get_field
has_assoc_Ring = False
布尔标志,指示域是否具有关联的Ring
。
>>> from sympy import QQ
>>> QQ.has_assoc_Ring
True
>>> QQ.get_ring()
ZZ
另见
is_Field
, get_ring
inject(*symbols)
将生成器注入到此域。
invert(a, b)
返回a mod b
的倒数,暗示某事。
is_Field = False
布尔标志,指示域是否为Field
。
>>> from sympy import ZZ, QQ
>>> ZZ.is_Field
False
>>> QQ.is_Field
True
另见
is_PID
, is_Ring
, get_field
, has_assoc_Field
is_PID = False
布尔标志,指示域是否为主理想域。
>>> from sympy import ZZ
>>> ZZ.has_assoc_Field
True
>>> ZZ.get_field()
QQ
另见
is_Field
, get_field
is_Ring = False
布尔标志,指示域是否为Ring
。
>>> from sympy import ZZ
>>> ZZ.is_Ring
True
基本上每个Domain
都代表一个环,所以这个标志并不那么有用。
参见
is_PID
, is_Field
, get_ring
, has_assoc_Ring
is_negative(a)
如果 a
是负数则返回 True。
is_nonnegative(a)
如果 a
是非负数则返回 True。
is_nonpositive(a)
如果 a
是非正数则返回 True。
is_one(a)
如果 a
是一则返回 True。
is_positive(a)
如果 a
是正数则返回 True。
is_square(a)
返回 a
在域中是否是平方数。
解释
如果在域中存在元素 b
使得 b * b == a
,则返回 True
,否则返回 False
。对于像 RR 和 CC 这样的不精确域,可以容忍此等式的微小差异。
参见
exsqrt
is_zero(a)
如果 a
是零则返回 True。
lcm(a, b)
返回 a
和 b
的最小公倍数。
log(a, b)
返回 a
的以 b
为底的对数。
map(seq)
递归地将 self
应用于 seq
的所有元素。
mul(a, b)
a
和 b
的乘积,意味着 __mul__
。
n(a, prec=None, **options)
返回 a
的数值近似。
neg(a)
返回 a
的相反数,意味着 __neg__
。
numer(a)
返回 a
的分子。
of_type(element)
检查 a
是否是 dtype
类型。
old_frac_field(*symbols, **kwargs)
返回一个分式域,即 (K(X))。
old_poly_ring(*symbols, **kwargs)
返回一个多项式环,即 (K[X])。
one: Any = None
Domain
的唯一元素:
>>> from sympy import QQ
>>> QQ.one
1
>>> QQ.of_type(QQ.one)
True
参见
of_type
, zero
poly_ring(*symbols, order=LexOrder())
返回一个多项式环,即 (K[X])。
pos(a)
返回 a
的正数,意味着 __pos__
。
pow(a, b)
将 a
的 b
次幂返回,意味着 __pow__
。
quo(a, b)
a 和 b 的商。a // b
的类似物。
K.quo(a, b)
等同于 K.div(a, b)[0]
。详见 div()
以获取更多解释。
参见
rem
a % b
的类似物
div
divmod(a, b)
的类似物
exquo
a / b
的类似物
rem(a, b)
a 和 b 的模除。a % b
的类似物。
K.rem(a, b)
等同于 K.div(a, b)[1]
。详见 div()
以获取更多解释。
参见
quo
a // b
的类似物
div
divmod(a, b)
的类似物
exquo
a / b
的类似物
revert(a)
如果可能则返回 a**(-1)
。
sqrt(a)
返回a
的(可能是不精确的)平方根。
解释
不同域中“不精确平方根”的普遍定义不存在。不建议为除 ZZ 外的其他域实现此方法。
另见
exsqrt
sub(a, b)
a
和 b
的差异,意味着 __sub__
。
to_sympy(a)
将域元素 a 转换为 SymPy 表达式(Expr)。
参数:
a:域元素
这个
Domain
的一个元素。
返回:
expr: Expr
一个类型为
Expr
的普通 SymPy 表达式。
解释
将Domain
元素a转换为Expr
。大多数公共 SymPy 函数与Expr
对象一起工作。Domain
的元素具有不同的内部表示。不可能将域元素与Expr
混合使用,因此每个域都有to_sympy()
和from_sympy()
方法来将其域元素转换为和从Expr
。
示例
构造 QQ 领域的元素,然后将其转换为Expr
。
>>> from sympy import QQ, Expr
>>> q_domain = QQ(2)
>>> q_domain
2
>>> q_expr = QQ.to_sympy(q_domain)
>>> q_expr
2
尽管打印形式看起来相似,但这些对象并非同一类型。
>>> isinstance(q_domain, Expr)
False
>>> isinstance(q_expr, Expr)
True
构造K[x]领域的元素并转换为Expr
。
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> K = QQ[x]
>>> x_domain = K.gens[0] # generator x as a domain element
>>> p_domain = x_domain**2/3 + 1
>>> p_domain
1/3*x**2 + 1
>>> p_expr = K.to_sympy(p_domain)
>>> p_expr
x**2/3 + 1
from_sympy()
方法用于从普通的 SymPy 表达式到域元素的相反转换。
>>> p_domain == p_expr
False
>>> K.from_sympy(p_expr) == p_domain
True
>>> K.to_sympy(p_domain) == p_expr
True
>>> K.from_sympy(K.to_sympy(p_domain)) == p_domain
True
>>> K.to_sympy(K.from_sympy(p_expr)) == p_expr
True
from_sympy()
方法使得交互式构造域元素更加容易。
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> K = QQ[x]
>>> K.from_sympy(x**2/3 + 1)
1/3*x**2 + 1
另见
from_sympy
,convert_from
property tp
dtype
的别名
unify(K1, symbols=None)
构造包含K0
和K1
元素的最小域。
已知领域(从最小到最大):
-
GF(p)
-
ZZ
-
QQ
-
RR(prec, tol)
-
CC(prec, tol)
-
ALG(a, b, c)
-
K[x, y, z]
-
K(x, y, z)
-
EX
unify_composite(K1)
统一至少一个是复合的两个域。
zero: Any = None
The zero element of the Domain
:
>>> from sympy import QQ
>>> QQ.zero
0
>>> QQ.of_type(QQ.zero)
True
See also
of_type
, one
class sympy.polys.domains.domainelement.DomainElement
Represents an element of a domain.
Mix in this trait into a class whose instances should be recognized as elements of a domain. Method parent()
gives that domain.
parent()
Get the domain associated with self
Examples
>>> from sympy import ZZ, symbols
>>> x, y = symbols('x, y')
>>> K = ZZ[x,y]
>>> p = K(x)**2 + K(y)**2
>>> p
x**2 + y**2
>>> p.parent()
ZZ[x,y]
Notes
This is used by convert()
to identify the domain associated with a domain element.
class sympy.polys.domains.field.Field
Represents a field domain.
div(a, b)
Division of a
and b
, implies __truediv__
.
exquo(a, b)
Exact quotient of a
and b
, implies __truediv__
.
gcd(a, b)
Returns GCD of a
and b
.
This definition of GCD over fields allows to clear denominators in (primitive()).
Examples
>>> from sympy.polys.domains import QQ
>>> from sympy import S, gcd, primitive
>>> from sympy.abc import x
>>> QQ.gcd(QQ(2, 3), QQ(4, 9))
2/9
>>> gcd(S(2)/3, S(4)/9)
2/9
>>> primitive(2*x/3 + S(4)/9)
(2/9, 3*x + 2)
get_field()
Returns a field associated with self
.
get_ring()
Returns a ring associated with self
.
is_unit(a)
Return true if a
is a invertible
lcm(a, b)
Returns LCM of a
and b
.
>>> from sympy.polys.domains import QQ
>>> from sympy import S, lcm
>>> QQ.lcm(QQ(2, 3), QQ(4, 9))
4/3
>>> lcm(S(2)/3, S(4)/9)
4/3
quo(a, b)
Quotient of a
and b
, implies __truediv__
.
rem(a, b)
Remainder of a
and b
, implies nothing.
revert(a)
Returns a**(-1)
if possible.
class sympy.polys.domains.ring.Ring
Represents a ring domain.
denom(a)
Returns denominator of (a).
div(a, b)
Division of a
and b
, implies __divmod__
.
exquo(a, b)
Exact quotient of a
and b
, implies __floordiv__
.
free_module(rank)
Generate a free module of rank rank
over self.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).free_module(2)
QQ[x]**2
get_ring()
Returns a ring associated with self
.
ideal(*gens)
Generate an ideal of self
.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).ideal(x**2)
<x**2>
invert(a, b)
Returns inversion of a mod b
.
numer(a)
Returns numerator of a
.
quo(a, b)
Quotient of a
and b
, implies __floordiv__
.
quotient_ring(e)
Form a quotient ring of self
.
Here e
can be an ideal or an iterable.
>>> from sympy.abc import x
>>> from sympy import QQ
>>> QQ.old_poly_ring(x).quotient_ring(QQ.old_poly_ring(x).ideal(x**2))
QQ[x]/<x**2>
>>> QQ.old_poly_ring(x).quotient_ring([x**2])
QQ[x]/<x**2>
The division operator has been overloaded for this:
>>> QQ.old_poly_ring(x)/[x**2]
QQ[x]/<x**2>
rem(a, b)
Remainder of a
and b
, implies __mod__
.
revert(a)
Returns a**(-1)
if possible.
class sympy.polys.domains.simpledomain.SimpleDomain
Base class for simple domains, e.g. ZZ, QQ.
inject(*gens)
Inject generators into this domain.
class sympy.polys.domains.compositedomain.CompositeDomain
Base class for composite domains, e.g. ZZ[x], ZZ(X).
drop(*symbols)
Drop generators from this domain.
get_exact()
Returns an exact version of this domain.
inject(*symbols)
Inject generators into this domain.
property is_Exact
Returns True
if this domain is exact.
set_domain(domain)
Set the ground domain of this domain.
GF(p)
class sympy.polys.domains.FiniteField(mod, symmetric=True)
Finite field of prime order GF(p)
A GF(p) domain represents a finite field (\mathbb{F}_p) of prime order as Domain
in the domain system (see Introducing the Domains of the poly module).
A Poly
created from an expression with integer coefficients will have the domain ZZ. However, if the modulus=p
option is given then the domain will be a finite field instead.
>>> from sympy import Poly, Symbol
>>> x = Symbol('x')
>>> p = Poly(x**2 + 1)
>>> p
Poly(x**2 + 1, x, domain='ZZ')
>>> p.domain
ZZ
>>> p2 = Poly(x**2 + 1, modulus=2)
>>> p2
Poly(x**2 + 1, x, modulus=2)
>>> p2.domain
GF(2)
可以使用模参数来在 GF(p) 上因式分解多项式,也可以通过明确指定域来实现。域也可以以字符串形式给出。
>>> from sympy import factor, GF
>>> factor(x**2 + 1)
x**2 + 1
>>> factor(x**2 + 1, modulus=2)
(x + 1)**2
>>> factor(x**2 + 1, domain=GF(2))
(x + 1)**2
>>> factor(x**2 + 1, domain='GF(2)')
(x + 1)**2
也可以使用 GF(p) 与 cancel()
和 gcd()
函数。
>>> from sympy import cancel, gcd
>>> cancel((x**2 + 1)/(x + 1))
(x**2 + 1)/(x + 1)
>>> cancel((x**2 + 1)/(x + 1), domain=GF(2))
x + 1
>>> gcd(x**2 + 1, x + 1)
1
>>> gcd(x**2 + 1, x + 1, domain=GF(2))
x + 1
直接使用域 GF(p) 可以用作构造函数来创建支持操作 +,-,*,**,/
的实例。
>>> from sympy import GF
>>> K = GF(5)
>>> K
GF(5)
>>> x = K(3)
>>> y = K(2)
>>> x
3 mod 5
>>> y
2 mod 5
>>> x * y
1 mod 5
>>> x / y
4 mod 5
注意
也可以创建一个 GF(p) 域,其阶数为非素数,但生成的环不是域:它只是模 n
的整数环。
>>> K = GF(9)
>>> z = K(3)
>>> z
3 mod 9
>>> z**2
0 mod 9
很好地实现素数幂域 (GF(p**n)
) 将很有帮助,但这些在 SymPY 中尚未实现。
characteristic()
返回此域的特征。
exsqrt(a)
如果 a
是二次剩余,则返回模 p 的平方根。
解释
总是返回不大于 p // 2
的平方根。
from_FF(a, K0=None)
将 ModularInteger(int)
转换为 dtype
。
from_FF_gmpy(a, K0=None)
将 ModularInteger(mpz)
转换为 dtype
。
from_FF_python(a, K0=None)
将 ModularInteger(int)
转换为 dtype
。
from_QQ(a, K0=None)
将 Python 的 Fraction
转换为 dtype
。
from_QQ_gmpy(a, K0=None)
将 GMPY 的 mpq
转换为 dtype
。
from_QQ_python(a, K0=None)
将 Python 的 Fraction
转换为 dtype
。
from_RealField(a, K0)
将 mpmath 的 mpf
转换为 dtype
。
from_ZZ(a, K0=None)
将 Python 的 int
转换为 dtype
。
from_ZZ_gmpy(a, K0=None)
将 GMPY 的 mpz
转换为 dtype
。
from_ZZ_python(a, K0=None)
将 Python 的 int
转换为 dtype
。
from_sympy(a)
将 SymPy 的整数转换为 SymPy 的 Integer
。
get_field()
返回与 self
关联的字段。
is_negative(a)
如果 a
是负数,则返回 True。
is_nonnegative(a)
如果 a
是非负数,则返回 True。
is_nonpositive(a)
如果 a
是非正数,则返回 True。
is_positive(a)
如果 a
是正数,则返回 True。
is_square(a)
如果 a
对模 p 是二次剩余,则返回 True。
to_int(a)
将 val
转换为 Python 的 int
对象。
to_sympy(a)
将 a
转换为 SymPy 对象。
class sympy.polys.domains.PythonFiniteField(mod, symmetric=True)
基于 Python 整数的有限域。
class sympy.polys.domains.GMPYFiniteField(mod, symmetric=True)
基于 GMPY 整数的有限域。 ## ZZ
ZZ 域表示整数 integers (\mathbb{Z}) 作为 Domain
在域系统中(参见 Introducing the Domains of the poly module)。
默认情况下,从具有整数系数的表达式创建的 Poly
将具有域 ZZ。
>>> from sympy import Poly, Symbol
>>> x = Symbol('x')
>>> p = Poly(x**2 + 1)
>>> p
Poly(x**2 + 1, x, domain='ZZ')
>>> p.domain
ZZ
相应的 分式域 是有理数 QQ 的域。反过来,ZZ 是 QQ 的 整数环:
>>> from sympy import ZZ, QQ
>>> ZZ.get_field()
QQ
>>> QQ.get_ring()
ZZ
直接使用域 ZZ 可以用作构造函数来创建支持操作 +,-,*,**,//,%
的实例(真除法 /
不应与 ZZ 一起使用 - 参见 exquo()
域方法):
>>> x = ZZ(5)
>>> y = ZZ(2)
>>> x // y # floor division
2
>>> x % y # modulo division (remainder)
1
gcd()
方法可用于计算任意两个元素的 gcd:
>>> ZZ.gcd(ZZ(10), ZZ(2))
2
SymPy 中有两种 ZZ 的实现。如果安装了 gmpy
或 gmpy2
,则 ZZ 将由 GMPYIntegerRing
实现,并且元素将是 gmpy.mpz
类型的实例。否则,如果未安装 gmpy
和 gmpy2
,则 ZZ 将由 PythonIntegerRing
实现,使用 Python 的标准内置 int
类型。对于更大的整数,使用 gmpy
可能更有效率,因此在可用时推荐使用。
class sympy.polys.domains.IntegerRing
表示整数的域 ZZ
是 (\mathbb{Z})。
IntegerRing
类作为 Domain
在域系统中表示整数环。IntegerRing
是 PythonIntegerRing
和 GMPYIntegerRing
的超类,根据是否安装 gmpy
或 gmpy2
中的一个来实现 ZZ。
另见
Domain
algebraic_field(*extension, alias=None)
返回一个代数域,即 (\mathbb{Q}(\alpha, \ldots))。
参数:
extension:一个或多个 Expr
。
扩展的生成元。这些应该是代数上 (\mathbb{Q}) 的表达式。
alias:str,Symbol
,可选(默认为 None)
如果提供,这将被用作返回的
AlgebraicField
的原始元的别名符号。
返回:
AlgebraicField
表示代数域扩展的
Domain
。
示例
>>> from sympy import ZZ, sqrt
>>> ZZ.algebraic_field(sqrt(2))
QQ<sqrt(2)>
exsqrt(a)
如果 a
是一个平方数,则返回 a
的非负平方根。
另见
is_square
factorial(a)
计算 a
的阶乘。
from_AlgebraicField(a, K0)
将 ANP
对象转换为 ZZ。
参见 convert()
。
from_EX(a, K0)
将 Expression
转换为 GMPY 的 mpz
。
from_FF(a, K0)
将 ModularInteger(int)
转换为 GMPY 的 mpz
。
from_FF_gmpy(a, K0)
将 ModularInteger(mpz)
转换为 GMPY 的 mpz
。
from_FF_python(a, K0)
将 ModularInteger(int)
转换为 GMPY 的 mpz
。
from_QQ(a, K0)
将 Python 的 Fraction
转换为 GMPY 的 mpz
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq
转换为 GMPY 的 mpz
。
from_QQ_python(a, K0)
将 Python 的 Fraction
转换为 GMPY 的 mpz
。
from_RealField(a, K0)
将 mpmath
的 mpf
转换为 GMPY 的 mpz
。
from_ZZ(a, K0)
将 Python 的 int
转换为 GMPY 的 mpz
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz
转换为 GMPY 的 mpz
。
from_ZZ_python(a, K0)
将 Python 的 int
转换为 GMPY 的 mpz
。
from_sympy(a)
将 SymPy 的整数转换为 dtype
。
gcd(a, b)
计算 a
和 b
的最大公约数。
gcdex(a, b)
计算 a
和 b
的扩展最大公约数。
get_field()
返回关联的分式域 QQ。
返回:
QQ:
关联的分式域 QQ,表示有理数 (\mathbb{Q}) 的
Domain
。
示例
>>> from sympy import ZZ
>>> ZZ.get_field()
QQ
is_square(a)
如果 a
是完全平方数,则返回 True
。
解释
如果存在整数 b
满足 b * b == a
,则整数 a
是完全平方数。
lcm(a, b)
计算 a
和 b
的最小公倍数。
log(a, b)
a 的以 b 为底的对数。
参数:
a: number
b: number
返回:
(\lfloor\log(a, b)\rfloor):
a 的以 b 为底的对数的下取整。
示例
>>> from sympy import ZZ
>>> ZZ.log(ZZ(8), ZZ(2))
3
>>> ZZ.log(ZZ(9), ZZ(2))
3
注意事项
此函数使用基于 float
的 math.log
,因此对于大整数参数将失败。
sqrt(a)
计算 a
的平方根。
to_sympy(a)
将 a
转换为 SymPy 对象。
class sympy.polys.domains.PythonIntegerRing
基于 Python 的 int
类型的整数环。
如果未安装 gmpy
和 gmpy2
,将使用 ZZ。元素是标准 Python int
类型的实例。
class sympy.polys.domains.GMPYIntegerRing
基于 GMPY 的 mpz
类型的整数环。
如果安装了 gmpy
或 gmpy2
,这将是 ZZ 的实现。元素将是类型为 gmpy.mpz
的对象。
factorial(a)
计算 a
的阶乘。
from_FF_gmpy(a, K0)
将 ModularInteger(mpz)
转换为 GMPY 的 mpz
。
from_FF_python(a, K0)
将 ModularInteger(int)
转换为 GMPY 的 mpz
。
from_QQ(a, K0)
将 Python 的 Fraction
转换为 GMPY 的 mpz
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq
转换为 GMPY 的 mpz
。
from_QQ_python(a, K0)
将 Python 的 Fraction
转换为 GMPY 的 mpz
。
from_RealField(a, K0)
将 mpmath
的 mpf
转换为 GMPY 的 mpz
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz
转换为 GMPY 的 mpz
。
from_ZZ_python(a, K0)
将 Python 的 int
转换为 GMPY 的 mpz
。
from_sympy(a)
将 SymPy 的整数转换为 dtype
。
gcd(a, b)
计算 a
和 b
的最大公约数。
gcdex(a, b)
计算 a
和 b
的扩展最大公约数。
lcm(a, b)
计算 a
和 b
的最小公倍数。
sqrt(a)
计算 a
的平方根。
to_sympy(a)
将 a
转换为 SymPy 对象。 ## QQ
QQ 领域将有理数(rationals (\mathbb{Q}))表示为 Domain
的一部分(见 Introducing the Domains of the poly module)。
默认情况下,从具有有理数系数的表达式创建的 Poly
将具有 QQ 域:
>>> from sympy import Poly, Symbol
>>> x = Symbol('x')
>>> p = Poly(x**2 + x/2)
>>> p
Poly(x**2 + 1/2*x, x, domain='QQ')
>>> p.domain
QQ
相应的整数环是整数 ZZ 的 Domain
。相反,QQ 是整数环的分式域:
>>> from sympy import ZZ, QQ
>>> QQ.get_ring()
ZZ
>>> ZZ.get_field()
QQ
当直接使用域 QQ 时,可以作为构造函数用于创建实例,这些实例支持操作+,-,*,**,/
(对于 QQ,非零除数总是可以进行真除/
):
>>> x = QQ(5)
>>> y = QQ(2)
>>> x / y # true division
5/2
SymPy 中有两种 QQ 的实现。如果安装了gmpy
或gmpy2
,则 QQ 将由GMPYRationalField
实现,元素将是gmpy.mpq
类型的实例。否则,如果未安装gmpy
和gmpy2
,则 QQ 将由PythonRationalField
实现,这是 SymPy 的纯 Python 类之一。优选gmpy
实现,因为速度显著更快。
class sympy.polys.domains.RationalField
抽象基类,用于领域 QQ。
RationalField
类将有理数域(\mathbb{Q})作为Domain
的一部分来表示。RationalField
是PythonRationalField
和GMPYRationalField
的超类之一,具体实现取决于是否安装了gmpy
或gmpy2
。QQ 的实现将由安装了gmpy
或gmpy2
的情况下的GMPYRationalField
提供,其元素将是gmpy.mpq
类型的实例。否则,如果未安装gmpy
和gmpy2
,则 QQ 将由纯 Python 类PythonRationalField
实现。gmpy
实现优选,因为它速度显著更快。
另见
Domain
algebraic_field(*extension, alias=None)
返回一个代数域,即(\mathbb{Q}(\alpha, \ldots))。
参数:
扩展:一个或多个Expr
扩展的生成器。这些应该是在(\mathbb{Q})上代数的表达式。
别名:str,Symbol
,None,可选(默认=None)
如果提供,将用作返回的
AlgebraicField
的原始元素的别名符号。
返回:
AlgebraicField
代表代数域扩展的
Domain
。
示例
>>> from sympy import QQ, sqrt
>>> QQ.algebraic_field(sqrt(2))
QQ<sqrt(2)>
denom(a)
返回a
的分母。
div(a, b)
a
和b
的除法,意味着__truediv__
。
exquo(a, b)
a
和b
的精确商,意味着__truediv__
。
exsqrt(a)
如果a
是平方数,则为a
的非负平方根。
另见
is_square
from_AlgebraicField(a, K0)
将ANP
对象转换为 QQ。
参见convert()
from_GaussianRationalField(a, K0)
将 GaussianElement
对象转换为 dtype
。
from_QQ(a, K0)
将 Python 的 Fraction
对象转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq
对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python 的 Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将 mpmath 的 mpf
对象转换为 dtype
。
from_ZZ(a, K0)
将 Python 的 int
对象转换为 dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz
对象转换为 self.dtype
。
from_ZZ_python(a, K0)
将 Python 的 int
对象转换为 dtype
。
from_sympy(a)
将 SymPy 的 Integer 转换为 dtype
。
get_ring()
返回与 self
关联的环。
is_square(a)
如果 a
是平方数,则返回 True
。
解释
如果存在有理数 b
使得 b * b == a
,则有理数 a
是平方数。
numer(a)
返回 a
的分子。
quo(a, b)
a
和 b
的商,意味着 __truediv__
。
rem(a, b)
a
和 b
的余数,无特殊意义。
to_sympy(a)
将 a
转换为 SymPy 对象。
class sympy.polys.domains.PythonRationalField
基于 MPQ 的有理数域。
如果未安装 gmpy
和 gmpy2
,则将用作 QQ。元素是 MPQ 的实例。
class sympy.polys.domains.GMPYRationalField
基于 GMPY 的 mpq
类型的有理数域。
如果安装了 gmpy
或 gmpy2
,则将实现为 QQ。元素将是 gmpy.mpq
类型。
denom(a)
返回 a
的分母。
div(a, b)
a
和 b
的除法,意味着 __truediv__
。
exquo(a, b)
a
和 b
的精确商,意味着 __truediv__
。
factorial(a)
返回 a
的阶乘。
from_GaussianRationalField(a, K0)
将 GaussianElement
对象转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq
对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python 的 Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将 mpmath 的 mpf
对象转换为 dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz
对象转换为 dtype
。
from_ZZ_python(a, K0)
将 Python 的 int
对象转换为 dtype
。
from_sympy(a)
将 SymPy 的 Integer 转换为 dtype
。
get_ring()
返回与 self
相关联的环。
numer(a)
返回 a
的分子。
quo(a, b)
a
和 b
的商,意味着 __truediv__
。
rem(a, b)
a
和 b
的余数,无特殊意义。
to_sympy(a)
将 a
转换为 SymPy 对象。
class sympy.external.pythonmpq.PythonMPQ(numerator, denominator=None)
旨在与 gmpy2 的 mpq 兼容的有理数实现。
也比 fractions.Fraction 稍快。
PythonMPQ 应被视为不可变的,尽管不会采取措施来防止突变(因为这可能会减慢计算速度)。## MPQ
MPQ
类型可以是 PythonMPQ
或者来自 gmpy2
的 mpq
类型。
Gaussian 域
Gaussian 域 ZZ_I 和 QQ_I 共享公共超类 GaussianElement
用于域元素和 GaussianDomain
用于域本身。
class sympy.polys.domains.gaussiandomains.GaussianDomain
Gaussian 域的基类。
from_AlgebraicField(a, K0)
将从 ZZ 或 QQ 转换为 self.dtype
的元素。
from_QQ(a, K0)
将 GMPY 的 mpq 转换为 self.dtype
。
from_QQ_gmpy(a, K0)
将 GMPY 的 mpq 转换为 self.dtype
。
from_QQ_python(a, K0)
将 QQ_python 元素转换为 self.dtype
。
from_ZZ(a, K0)
将 ZZ_python 元素转换为 self.dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的 mpz 转换为 self.dtype
。
from_ZZ_python(a, K0)
将 ZZ_python 元素转换为 self.dtype
。
from_sympy(a)
将 SymPy 对象转换为 self.dtype
。
inject(*gens)
将生成器注入到此域中。
is_negative(element)
对于任何 GaussianElement
返回 False
。
is_nonnegative(element)
对于任何 GaussianElement
返回 False
。
is_nonpositive(element)
返回任何 高斯元素
的 False
。
is_positive(element)
返回任何 高斯元素
的 False
。
to_sympy(a)
将 a
转换为 SymPy 对象。
class sympy.polys.domains.gaussiandomains.GaussianElement(x, y=0)
高斯型域元素的基类。
classmethod new(x, y)
创建相同域的新高斯元素。
parent()
这是所属的域 (ZZ_I 或 QQ_I) 的元素。
quadrant()
返回象限索引 0-3。
0 包含在象限 0 中。
ZZ_I
class sympy.polys.domains.gaussiandomains.GaussianIntegerRing
高斯整数环 ZZ_I
ZZ_I 域将 高斯整数 (\mathbb{Z}[i]) 表示为域系统中的 Domain
(参见 Introducing the Domains of the poly module)。
默认情况下,从整数和 I
((\sqrt{-1}))的组合构成的表达式创建的 Poly
将具有域 ZZ_I。
>>> from sympy import Poly, Symbol, I
>>> x = Symbol('x')
>>> p = Poly(x**2 + I)
>>> p
Poly(x**2 + I, x, domain='ZZ_I')
>>> p.domain
ZZ_I
ZZ_I 域可用于分解在高斯整数上可约的多项式。
>>> from sympy import factor
>>> factor(x**2 + 1)
x**2 + 1
>>> factor(x**2 + 1, domain='ZZ_I')
(x - I)*(x + I)
对应的 分式域 是高斯有理数的域 QQ_I。相反,ZZ_I 是 QQ_I 的 整数环。
>>> from sympy import ZZ_I, QQ_I
>>> ZZ_I.get_field()
QQ_I
>>> QQ_I.get_ring()
ZZ_I
直接使用域时,ZZ_I 可作为构造函数使用。
>>> ZZ_I(3, 4)
(3 + 4*I)
>>> ZZ_I(5)
(5 + 0*I)
ZZ_I 的域元素是支持环操作 +,-,*,**
的 高斯整数
实例。
>>> z1 = ZZ_I(5, 1)
>>> z2 = ZZ_I(2, 3)
>>> z1
(5 + 1*I)
>>> z2
(2 + 3*I)
>>> z1 + z2
(7 + 4*I)
>>> z1 * z2
(7 + 17*I)
>>> z1 ** 2
(24 + 10*I)
地板除法 (//
) 和模除法 (%
) 在 高斯整数
(参见 div()
方法) 上均有效。
>>> z3, z4 = ZZ_I(5), ZZ_I(1, 3)
>>> z3 // z4 # floor division
(1 + -1*I)
>>> z3 % z4 # modulo division (remainder)
(1 + -2*I)
>>> (z3//z4)*z4 + z3%z4 == z3
True
在 ZZ_I 中,真除法 (/
) 给出 QQ_I 的一个元素。可以使用 exquo()
方法在 ZZ_I 上进行精确除法。
>>> z1 / z2
(1 + -1*I)
>>> ZZ_I.exquo(z1, z2)
(1 + -1*I)
>>> z3 / z4
(1/2 + -3/2*I)
>>> ZZ_I.exquo(z3, z4)
Traceback (most recent call last):
...
ExactQuotientFailed: (1 + 3*I) does not divide (5 + 0*I) in ZZ_I
gcd()
方法可用于计算任意两个元素的 gcd。
>>> ZZ_I.gcd(ZZ_I(10), ZZ_I(2))
(2 + 0*I)
>>> ZZ_I.gcd(ZZ_I(5), ZZ_I(2, 1))
(2 + 1*I)
dtype
高斯整数
的别名。
from_GaussianIntegerRing(a, K0)
将 ZZ_I 元素转换为 ZZ_I。
from_GaussianRationalField(a, K0)
将 QQ_I 元素转换为 ZZ_I。
gcd(a, b)
在 ZZ_I 上 a 和 b 的最大公约数。
get_field()
返回与 self
关联的一个字段。
get_ring()
返回与 self
关联的一个环。
lcm(a, b)
在 ZZ_I 上的 a 和 b 的最小公倍数。
normalize(d, *args)
返回与 d
关联的第一象限元素。
也将其他参数乘以相同的 i 的幂次。
class sympy.polys.domains.gaussiandomains.GaussianInteger(x, y=0)
高斯整数:ZZ_I 的域元素。
>>> from sympy import ZZ_I
>>> z = ZZ_I(2, 3)
>>> z
(2 + 3*I)
>>> type(z)
<class 'sympy.polys.domains.gaussiandomains.GaussianInteger'>
``` ## QQ_I
```py
class sympy.polys.domains.gaussiandomains.GaussianRationalField
高斯有理数域 QQ_I
QQ_I 域将高斯有理数 (\mathbb{Q}(i)) 表示为域系统中的Domain
(参见引入多项式模块的域)。
默认情况下,从具有有理数和I
((\sqrt{-1}))组合的系数表达式创建的Poly
将具有域 QQ_I。
>>> from sympy import Poly, Symbol, I
>>> x = Symbol('x')
>>> p = Poly(x**2 + I/2)
>>> p
Poly(x**2 + I/2, x, domain='QQ_I')
>>> p.domain
QQ_I
即使系数不包含I
或全为整数,polys 选项gaussian=True
也可以用来指定域应为 QQ_I。
>>> Poly(x**2)
Poly(x**2, x, domain='ZZ')
>>> Poly(x**2 + I)
Poly(x**2 + I, x, domain='ZZ_I')
>>> Poly(x**2/2)
Poly(1/2*x**2, x, domain='QQ')
>>> Poly(x**2, gaussian=True)
Poly(x**2, x, domain='QQ_I')
>>> Poly(x**2 + I, gaussian=True)
Poly(x**2 + I, x, domain='QQ_I')
>>> Poly(x**2/2, gaussian=True)
Poly(1/2*x**2, x, domain='QQ_I')
QQ_I 域可用于分解在高斯有理数上是可约的多项式。
>>> from sympy import factor, QQ_I
>>> factor(x**2/4 + 1)
(x**2 + 4)/4
>>> factor(x**2/4 + 1, domain='QQ_I')
(x - 2*I)*(x + 2*I)/4
>>> factor(x**2/4 + 1, domain=QQ_I)
(x - 2*I)*(x + 2*I)/4
还可以使用 polys 函数如apart()
明确指定 QQ_I 域。
>>> from sympy import apart
>>> apart(1/(1 + x**2))
1/(x**2 + 1)
>>> apart(1/(1 + x**2), domain=QQ_I)
I/(2*(x + I)) - I/(2*(x - I))
对应的整数环 是高斯整数 ZZ_I 的域。反之,QQ_I 是 ZZ_I 的分式域。
>>> from sympy import ZZ_I, QQ_I, QQ
>>> ZZ_I.get_field()
QQ_I
>>> QQ_I.get_ring()
ZZ_I
直接使用域 QQ_I 时,可以作为构造函数使用。
>>> QQ_I(3, 4)
(3 + 4*I)
>>> QQ_I(5)
(5 + 0*I)
>>> QQ_I(QQ(2, 3), QQ(4, 5))
(2/3 + 4/5*I)
QQ_I 的域元素是支持字段操作+,-,*,**,/
的GaussianRational
实例。
>>> z1 = QQ_I(5, 1)
>>> z2 = QQ_I(2, QQ(1, 2))
>>> z1
(5 + 1*I)
>>> z2
(2 + 1/2*I)
>>> z1 + z2
(7 + 3/2*I)
>>> z1 * z2
(19/2 + 9/2*I)
>>> z2 ** 2
(15/4 + 2*I)
在 QQ_I 中,真除法(/
) 给出 QQ_I 的元素,并且始终是精确的。
>>> z1 / z2
(42/17 + -2/17*I)
>>> QQ_I.exquo(z1, z2)
(42/17 + -2/17*I)
>>> z1 == (z1/z2)*z2
True
对于GaussianRational
,可以使用 floor (//
) 和 modulo (%
) 运算(参见div()
),但是由于除法始终是精确的,因此没有余数。
>>> z1 // z2
(42/17 + -2/17*I)
>>> z1 % z2
(0 + 0*I)
>>> QQ_I.div(z1, z2)
((42/17 + -2/17*I), (0 + 0*I))
>>> (z1//z2)*z2 + z1%z2 == z1
True
as_AlgebraicField()
作为AlgebraicField
的等价域。
denom(a)
获取a
的分母。
dtype
GaussianRational
的别名
from_ComplexField(a, K0)
将 ComplexField 元素转换为 QQ_I。
from_GaussianIntegerRing(a, K0)
将 ZZ_I 元素转换为 QQ_I。
from_GaussianRationalField(a, K0)
将 QQ_I 元素转换为 QQ_I。
get_field()
返回与self
相关的字段。
get_ring()
返回与self
相关联的环。
numer(a)
获取a
的分子。
class sympy.polys.domains.gaussiandomains.GaussianRational(x, y=0)
高斯有理数:QQ_I 的域元素
>>> from sympy import QQ_I, QQ
>>> z = QQ_I(QQ(2, 3), QQ(4, 5))
>>> z
(2/3 + 4/5*I)
>>> type(z)
<class 'sympy.polys.domains.gaussiandomains.GaussianRational'>
``` ## QQ<a>
```py
class sympy.polys.domains.AlgebraicField(dom, *ext, alias=None)
QQ 域将代数数域 (\mathbb{Q}(a)) 表示为域系统中的Domain
(参见引入多项式模块的域)。
从涉及algebraic numbers的表达式创建的Poly
将把代数数视为生成器(如果未指定生成器参数)。
>>> from sympy import Poly, Symbol, sqrt
>>> x = Symbol('x')
>>> Poly(x**2 + sqrt(2))
Poly(x**2 + (sqrt(2)), x, sqrt(2), domain='ZZ')
这是一个多变量多项式,其中sqrt(2)
被视为生成器(变量)之一。如果明确指定生成器,则sqrt(2)
将被视为系数,但默认情况下使用 EX 域。要在 QQ域中创建Poly
,可以给定参数extension=True
。
>>> Poly(x**2 + sqrt(2), x)
Poly(x**2 + sqrt(2), x, domain='EX')
>>> Poly(x**2 + sqrt(2), x, extension=True)
Poly(x**2 + sqrt(2), x, domain='QQ<sqrt(2)>')
如果系数全为有理数但需要扩展域(例如因式分解多项式),也可以显式指定代数域扩展的生成器。
>>> Poly(x**2 + 1)
Poly(x**2 + 1, x, domain='ZZ')
>>> Poly(x**2 + 1, extension=sqrt(2))
Poly(x**2 + 1, x, domain='QQ<sqrt(2)>')
可以使用extension
参数在 QQ域上因式分解多项式,或者明确指定域。
>>> from sympy import factor, QQ
>>> factor(x**2 - 2)
x**2 - 2
>>> factor(x**2 - 2, extension=sqrt(2))
(x - sqrt(2))*(x + sqrt(2))
>>> factor(x**2 - 2, domain='QQ<sqrt(2)>')
(x - sqrt(2))*(x + sqrt(2))
>>> factor(x**2 - 2, domain=QQ.algebraic_field(sqrt(2)))
(x - sqrt(2))*(x + sqrt(2))
可以使用参数extension=True
,但这只会创建包含系数的扩展,通常不足以因式分解多项式。
>>> p = x**3 + sqrt(2)*x**2 - 2*x - 2*sqrt(2)
>>> factor(p) # treats sqrt(2) as a symbol
(x + sqrt(2))*(x**2 - 2)
>>> factor(p, extension=True)
(x - sqrt(2))*(x + sqrt(2))**2
>>> factor(x**2 - 2, extension=True) # all rational coefficients
x**2 - 2
>>> from sympy import cancel, gcd
>>> cancel((x**2 - 2)/(x - sqrt(2)))
(x**2 - 2)/(x - sqrt(2))
>>> cancel((x**2 - 2)/(x - sqrt(2)), extension=sqrt(2))
x + sqrt(2)
>>> gcd(x**2 - 2, x - sqrt(2))
1
>>> gcd(x**2 - 2, x - sqrt(2), extension=sqrt(2))
x - sqrt(2)
在直接使用域时,可以使用 QQ作为构造函数创建实例,从而支持+,-,*,**,/
等操作。algebraic_field()
方法用于构造特定的 QQ域。from_sympy()
方法可用于从普通的 SymPy 表达式创建域元素。
>>> K = QQ.algebraic_field(sqrt(2))
>>> K
QQ<sqrt(2)>
>>> xk = K.from_sympy(3 + 4*sqrt(2))
>>> xk
ANP([4, 3], [1, 0, -2], QQ)
QQ的元素是ANP
的实例,它们具有有限的打印支持。原始显示显示元素的内部表示,例如列表[4, 3]
,表示形式为a * sqrt(2) + b * 1
,其中a
和b
是 QQ 中的元素,分别代表1
和sqrt(2)
的系数。生成器(x**2 - 2)
的最小多项式也显示在 DUP representation 中,表示为列表[1, 0, -2]
。我们可以使用to_sympy()
以获得更好的元素打印形式并查看操作的结果。
>>> xk = K.from_sympy(3 + 4*sqrt(2))
>>> yk = K.from_sympy(2 + 3*sqrt(2))
>>> xk * yk
ANP([17, 30], [1, 0, -2], QQ)
>>> K.to_sympy(xk * yk)
17*sqrt(2) + 30
>>> K.to_sympy(xk + yk)
5 + 7*sqrt(2)
>>> K.to_sympy(xk ** 2)
24*sqrt(2) + 41
>>> K.to_sympy(xk / yk)
sqrt(2)/14 + 9/7
任何表示代数数的表达式都可以用来生成一个 QQ域,只要能计算其最小多项式。使用minpoly()
函数进行此操作。
>>> from sympy import exp, I, pi, minpoly
>>> g = exp(2*I*pi/3)
>>> g
exp(2*I*pi/3)
>>> g.is_algebraic
True
>>> minpoly(g, x)
x**2 + x + 1
>>> factor(x**3 - 1, extension=g)
(x - 1)*(x - exp(2*I*pi/3))*(x + 1 + exp(2*I*pi/3))
也可以从多个扩展元素生成一个代数域。
>>> K = QQ.algebraic_field(sqrt(2), sqrt(3))
>>> K
QQ<sqrt(2) + sqrt(3)>
>>> p = x**4 - 5*x**2 + 6
>>> factor(p)
(x**2 - 3)*(x**2 - 2)
>>> factor(p, domain=K)
(x - sqrt(2))*(x + sqrt(2))*(x - sqrt(3))*(x + sqrt(3))
>>> factor(p, extension=[sqrt(2), sqrt(3)])
(x - sqrt(2))*(x + sqrt(2))*(x - sqrt(3))*(x + sqrt(3))
多个扩展元素总是组合在一起形成一个单一的原始元素。在[sqrt(2), sqrt(3)]
的情况下,选择的原始元素是sqrt(2) + sqrt(3)
,这就是为什么该域显示为QQ<sqrt(2) + sqrt(3)>
。使用primitive_element()
函数计算原始元素的最小多项式。
>>> from sympy import primitive_element
>>> primitive_element([sqrt(2), sqrt(3)], x)
(x**4 - 10*x**2 + 1, [1, 1])
>>> minpoly(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
从域中可以使用ext
和orig_ext
属性访问生成域的扩展元素,它们是AlgebraicNumber
的实例。作为DMP
实例的原始元素的最小多项式可用作mod
。
>>> K = QQ.algebraic_field(sqrt(2), sqrt(3))
>>> K
QQ<sqrt(2) + sqrt(3)>
>>> K.ext
sqrt(2) + sqrt(3)
>>> K.orig_ext
(sqrt(2), sqrt(3))
>>> K.mod
DMP_Python([1, 0, -10, 0, 1], QQ)
从域的discriminant()
方法可以获取其判别式,从integral_basis()
方法可以获取整基。后者默认返回ANP
实例的列表,但可以通过传递fmt
参数使其返回Expr
或AlgebraicNumber
实例。域的最大秩,或整数环,也可以从maximal_order()
方法获取,作为Submodule
。
>>> zeta5 = exp(2*I*pi/5)
>>> K = QQ.algebraic_field(zeta5)
>>> K
QQ<exp(2*I*pi/5)>
>>> K.discriminant()
125
>>> K = QQ.algebraic_field(sqrt(5))
>>> K
QQ<sqrt(5)>
>>> K.integral_basis(fmt='sympy')
[1, 1/2 + sqrt(5)/2]
>>> K.maximal_order()
Submodule[[2, 0], [1, 1]]/2
有理素数在域的素理想中的分解由primes_above()
方法计算,该方法返回PrimeIdeal
实例的列表。
>>> zeta7 = exp(2*I*pi/7)
>>> K = QQ.algebraic_field(zeta7)
>>> K
QQ<exp(2*I*pi/7)>
>>> K.primes_above(11)
[(11, _x**3 + 5*_x**2 + 4*_x - 1), (11, _x**3 - 4*_x**2 - 5*_x - 1)]
当域的最小多项式的次数足够小时,可以计算域的 Galois 闭包的 Galois 群。
>>> K.galois_group(by_name=True)[0]
S6TransitiveSubgroups.C6
注意事项
目前无法在除 QQ 以外的任何域上生成代数扩展。理想情况下,可以生成类似QQ(x)(sqrt(x**2 - 2))
的扩展。这等同于商环QQ(x)[y]/(y**2 - x**2 + 2)
,在QuotientRing
和MonogenicFiniteExtension
类中有两种实现这种商环/扩展。尽管如此,这些实现都需要一些工作才能完全可用。
algebraic_field(*extension, alias=None)
返回一个代数域,即(\mathbb{Q}(\alpha, \ldots))。
denom(a)
返回a
的分母。
discriminant()
获取域的判别式。
dtype
ANP
的别名
ext
用于扩展的原始元素。
>>> from sympy import QQ, sqrt
>>> K = QQ.algebraic_field(sqrt(2), sqrt(3))
>>> K.ext
sqrt(2) + sqrt(3)
from_AlgebraicField(a, K0)
将 AlgebraicField 元素‘a’转换为另一个 AlgebraicField
from_GaussianIntegerRing(a, K0)
将高斯整数元素‘a’转换为dtype
。
from_GaussianRationalField(a, K0)
将高斯有理数元素‘a’转换为dtype
。
from_QQ(a, K0)
将 Python 的Fraction
对象转换为dtype
。
from_QQ_gmpy(a, K0)
将 GMPY 的mpq
对象转换为dtype
。
from_QQ_python(a, K0)
将 Python 的Fraction
对象转换为dtype
。
from_RealField(a, K0)
将 mpmath 的mpf
对象转换为dtype
。
from_ZZ(a, K0)
将 Python 的int
对象转换为dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的mpz
对象转换为dtype
。
from_ZZ_python(a, K0)
将 Python 的int
对象转换为dtype
。
from_sympy(a)
将 SymPy 的表达式转换为dtype
。
galois_group(by_name=False, max_tries=30, randomize=False)
计算此域的 Galois 闭包的 Galois 群。
示例
如果域是 Galois 域,则群的阶数将等于域的次数:
>>> from sympy import QQ
>>> from sympy.abc import x
>>> k = QQ.alg_field_from_poly(x**4 + 1)
>>> G, _ = k.galois_group()
>>> G.order()
4
如果域不是 Galois 域,则其 Galois 闭包是一个适当的扩展,并且 Galois 群的阶数将大于域的次数:
>>> k = QQ.alg_field_from_poly(x**4 - 2)
>>> G, _ = k.galois_group()
>>> G.order()
8
另请参阅
sympy.polys.numberfields.galoisgroups.galois_group
的别名
get_ring()
返回与self
相关联的环。
integral_basis(fmt=None)
获取域的整数基。
参数:
fmt:str,可选(默认为 None)
如果为
None
,则返回ANP
实例的列表。如果为"sympy"
,则使用self.to_sympy()
将列表中的每个元素转换为Expr
。如果为"alg"
,则使用self.to_alg_num()
将列表中的每个元素转换为AlgebraicNumber
。
示例
>>> from sympy import QQ, AlgebraicNumber, sqrt
>>> alpha = AlgebraicNumber(sqrt(5), alias='alpha')
>>> k = QQ.algebraic_field(alpha)
>>> B0 = k.integral_basis()
>>> B1 = k.integral_basis(fmt='sympy')
>>> B2 = k.integral_basis(fmt='alg')
>>> print(B0[1])
ANP([mpq(1,2), mpq(1,2)], [mpq(1,1), mpq(0,1), mpq(-5,1)], QQ)
>>> print(B1[1])
1/2 + alpha/2
>>> print(B2[1])
alpha/2 + 1/2
在最后两种情况下,我们得到易读的表达式,由于涉及不同类型,打印方式略有不同:
>>> print(type(B1[1]))
<class 'sympy.core.add.Add'>
>>> print(type(B2[1]))
<class 'sympy.core.numbers.AlgebraicNumber'>
另请参阅
to_sympy
, to_alg_num
, maximal_order
is_negative(a)
如果a
为负数,则返回 True。
is_nonnegative(a)
如果a
是非负数,则返回 True。
is_nonpositive(a)
如果a
是非正数,则返回 True。
is_positive(a)
如果a
为正数,则返回 True。
maximal_order()
计算字段的最大秩或整数环。
返回:
子模块
。
另请参阅
整体基础
mod
扩展的原始元素的最小多项式。
>>> from sympy import QQ, sqrt
>>> K = QQ.algebraic_field(sqrt(2))
>>> K.mod
DMP([1, 0, -2], QQ)
numer(a)
返回a
的分子。
orig_ext
给定用于生成扩展的原始元素。
>>> from sympy import QQ, sqrt
>>> K = QQ.algebraic_field(sqrt(2), sqrt(3))
>>> K.orig_ext
(sqrt(2), sqrt(3))
primes_above(p)
计算位于给定有理素数p之上的素数理想。
to_alg_num(a)
将dtype
的a
转换为AlgebraicNumber
。
to_sympy(a)
将dtype
的a
转换为 SymPy 对象。## RR
class sympy.polys.domains.RealField(prec=53, dps=None, tol=None)
给定精度的实数。
almosteq(a, b, tolerance=None)
检查a
和b
是否几乎相等。
exsqrt(a)
非负数的平方根,对于a >= 0
,否则为None
。
说明
由于浮点舍入误差,平方根可能略有不准确。
from_sympy(expr)
将 SymPy 的数字转换为dtype
。
gcd(a, b)
返回a
和b
的最大公约数。
get_exact()
返回与self
相关的精确域。
get_ring()
返回与self
相关的环。
is_square(a)
如果a >= 0
则返回 True,否则返回 False。
lcm(a, b)
返回a
和b
的最小公倍数。
to_rational(element, limit=True)
将实数转换为有理数。
to_sympy(element)
将element
转换为 SymPy 数字。
class sympy.polys.domains.mpelements.RealElement(val=(0, 0, 0, 0), **kwargs)
实域的一个元素。## CC
class sympy.polys.domains.ComplexField(prec=53, dps=None, tol=None)
给定精度的复数。
almosteq(a, b, tolerance=None)
检查a
和b
是否几乎相等。
exsqrt(a)
返回a
的主复数平方根。
说明
主平方根的参数始终在((-\frac{\pi}{2}, \frac{\pi}{2}])之间。由于浮点舍入误差,平方根可能略有不准确。
from_sympy(expr)
将 SymPy 的数字转换为dtype
。
gcd(a, b)
返回a
和b
的最大公约数。
get_exact()
返回与self
相关的精确域。
get_ring()
返回与self
相关的环。
is_negative(element)
对于任何ComplexElement
返回False
。
is_nonnegative(element)
对于任何ComplexElement
返回False
。
is_nonpositive(element)
对于任何ComplexElement
返回False
。
is_positive(element)
对于任何ComplexElement
返回False
。
is_square(a)
返回 True
。每个复数都有一个复平方根。
lcm(a, b)
返回 (a) 和 (b) 的最小公倍数。
to_sympy(element)
将 element
转换为 SymPy 数字。
class sympy.polys.domains.mpelements.ComplexElement(real=0, imag=0)
复杂域的一个元素。 ## K[x]
class sympy.polys.domains.PolynomialRing(domain_or_ring, symbols=None, order=None)
表示多变量多项式环的类。
factorial(a)
返回 (a) 的阶乘。
from_AlgebraicField(a, K0)
将代数数转换为 dtype
。
from_ComplexField(a, K0)
将 mpmath (mpf) 对象转换为 dtype
。
from_FractionField(a, K0)
将有理函数转换为 dtype
。
from_GaussianIntegerRing(a, K0)
将 GaussianInteger
对象转换为 dtype
。
from_GaussianRationalField(a, K0)
将 GaussianRational
对象转换为 dtype
。
from_GlobalPolynomialRing(a, K0)
从旧多项式环转换为 dtype
。
from_PolynomialRing(a, K0)
将多项式转换为 dtype
。
from_QQ(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY (mpq) 对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将 mpmath mpf
对象转换为 dtype
。
from_ZZ(a, K0)
将 Python (int) 对象转换为 (dtype)。
from_ZZ_gmpy(a, K0)
将 GMPY (mpz) 对象转换为 (dtype)。
from_ZZ_python(a, K0)
将 Python (int) 对象转换为 (dtype)。
from_sympy(a)
将 SymPy 表达式转换为 (dtype)。
gcd(a, b)
返回 (a) 和 (b) 的最大公约数。
gcdex(a, b)
(a) 和 (b) 的扩展最大公约数。
get_field()
返回与 (self) 关联的一个域。
is_negative(a)
如果 LC(a)
是负则返回 True。
is_nonnegative(a)
如果 LC(a)
非负则返回 True。
is_nonpositive(a)
如果 LC(a)
非正则返回 True。
is_positive(a)
如果 LC(a)
是正则返回 True。
is_unit(a)
如果 a
是 self
的单元返回 True
。
lcm(a, b)
返回 (a) 和 (b) 的最小公倍数。
to_sympy(a)
将 (a) 转换为 SymPy 对象。 ## K(x)
class sympy.polys.domains.FractionField(domain_or_field, symbols=None, order=None)
表示多变量有理函数域的类。
denom(a)
返回 a
的分母。
factorial(a)
返回 a
的阶乘。
from_AlgebraicField(a, K0)
将代数数转换为 dtype
。
from_ComplexField(a, K0)
将 mpmath mpf
对象转换为 dtype
。
from_FractionField(a, K0)
将有理函数转换为 dtype
。
from_GaussianIntegerRing(a, K0)
将 GaussianInteger
对象转换为 dtype
。
from_GaussianRationalField(a, K0)
将 GaussianRational
对象转换为 dtype
。
from_PolynomialRing(a, K0)
将多项式转换为 dtype
。
from_QQ(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY mpq
对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将 mpmath mpf
对象转换为 dtype
。
from_ZZ(a, K0)
将 Python int
对象转换为 dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY mpz
对象转换为 dtype
。
from_ZZ_python(a, K0)
将 Python int
对象转换为 dtype
。
from_sympy(a)
将 SymPy 表达式转换为 dtype
。
get_ring()
返回与 self
关联的一个域。
is_negative(a)
如果 LC(a)
是负则返回 True。
is_nonnegative(a)
如果 LC(a)
非负则返回 True。
is_nonpositive(a)
如果 LC(a)
非正则返回 True。
is_positive(a)
如果 LC(a)
是正则返回 True。
numer(a)
返回 a
的分子。
to_sympy(a)
将 a
转换为 SymPy 对象。 ## EX
class sympy.polys.domains.ExpressionDomain
一个表示任意表达式的类。
class Expression(ex)
任意表达式。
denom(a)
返回 a
的分母。
dtype
Expression
的别名。
from_AlgebraicField(a, K0)
将 ANP
对象转换为 dtype
。
from_ComplexField(a, K0)
将 mpmath mpc
对象转换为 dtype
。
from_ExpressionDomain(a, K0)
将 EX
对象转换为 dtype
。
from_FractionField(a, K0)
将 DMF
对象转换为 dtype
。
from_GaussianIntegerRing(a, K0)
将 GaussianRational
对象转换为 dtype
。
from_GaussianRationalField(a, K0)
将 GaussianRational
对象转换为 dtype
。
from_PolynomialRing(a, K0)
将 DMP
对象转换为 dtype
。
from_QQ(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_QQ_gmpy(a, K0)
将 GMPY mpq
对象转换为 dtype
。
from_QQ_python(a, K0)
将 Python Fraction
对象转换为 dtype
。
from_RealField(a, K0)
将 mpmath mpf
对象转换为 dtype
。
from_ZZ(a, K0)
将 Python 的int
对象转换为dtype
。
from_ZZ_gmpy(a, K0)
将 GMPY 的mpz
对象转换为dtype
。
from_ZZ_python(a, K0)
将 Python 的int
对象转换为dtype
。
from_sympy(a)
将 SymPy 表达式转换为dtype
。
get_field()
返回与self
相关联的字段。
get_ring()
返回与self
相关联的环。
is_negative(a)
如果a
为负数则返回 True。
is_nonnegative(a)
如果a
为非负数则返回 True。
is_nonpositive(a)
如果a
为非正数则返回 True。
is_positive(a)
如果a
为正数则返回 True。
numer(a)
返回a
的分子。
to_sympy(a)
将a
转换为 SymPy 对象。
class ExpressionDomain.Expression(ex)
任意表达式。
商环
class sympy.polys.domains.quotientring.QuotientRing(ring, ideal)
表示(交换)商环的类。
通常不应手动实例化此对象,而是应在构造中使用基本环的构造函数。
>>> from sympy.abc import x
>>> from sympy import QQ
>>> I = QQ.old_poly_ring(x).ideal(x**3 + 1)
>>> QQ.old_poly_ring(x).quotient_ring(I)
QQ[x]/<x**3 + 1>
可以有更短的版本:
>>> QQ.old_poly_ring(x)/I
QQ[x]/<x**3 + 1>
>>> QQ.old_poly_ring(x)/[x**3 + 1]
QQ[x]/<x**3 + 1>
属性:
-
环 - 基本环
-
基本理想 - 用于形成商的理想
稀疏多项式
稀疏多项式表示为字典。
sympy.polys.rings.ring(symbols, domain, order=LexOrder())
构造一个多项式环,返回(ring, x_1, ..., x_n)
。
参数:
symbols:str
Symbol/Expr 或 str、Symbol/Expr 序列(非空)
domain:Domain
或可转换类型
order:MonomialOrder
或可转换类型,可选,默认为lex
示例
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex
>>> R, x, y, z = ring("x,y,z", ZZ, lex)
>>> R
Polynomial ring in x, y, z over ZZ with lex order
>>> x + y + z
x + y + z
>>> type(_)
<class 'sympy.polys.rings.PolyElement'>
sympy.polys.rings.xring(symbols, domain, order=LexOrder())
构造一个多项式环,返回(ring, (x_1, ..., x_n))
。
参数:
symbols:str
Symbol/Expr 或 str、Symbol/Expr 序列(非空)
domain:Domain
或可转换类型
order:MonomialOrder
或可转换类型,可选,默认为lex
示例
>>> from sympy.polys.rings import xring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex
>>> R, (x, y, z) = xring("x,y,z", ZZ, lex)
>>> R
Polynomial ring in x, y, z over ZZ with lex order
>>> x + y + z
x + y + z
>>> type(_)
<class 'sympy.polys.rings.PolyElement'>
sympy.polys.rings.vring(symbols, domain, order=LexOrder())
构造一个多项式环,并将x_1, ..., x_n
注入全局命名空间。
参数:
symbols:str
Symbol/Expr 或 str、Symbol/Expr 序列(非空)
domain:Domain
或可转换类型
order:MonomialOrder
或可转换类型,可选,默认为lex
示例
>>> from sympy.polys.rings import vring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex
>>> vring("x,y,z", ZZ, lex)
Polynomial ring in x, y, z over ZZ with lex order
>>> x + y + z # noqa:
x + y + z
>>> type(_)
<class 'sympy.polys.rings.PolyElement'>
sympy.polys.rings.sring(exprs, *symbols, **options)
构造一个环,从选项和输入表达式中派生生成器和域。
参数:
exprs:Expr
或Expr
序列(可简化)
symbols:Symbol
/Expr
序列
options:由Options
理解的关键字参数
示例
>>> from sympy import sring, symbols
>>> x, y, z = symbols("x,y,z")
>>> R, f = sring(x + 2*y + 3*z)
>>> R
Polynomial ring in x, y, z over ZZ with lex order
>>> f
x + 2*y + 3*z
>>> type(_)
<class 'sympy.polys.rings.PolyElement'>
class sympy.polys.rings.PolyRing(symbols, domain, order=LexOrder())
多元分布式多项式环。
add(*objs)
添加一系列多项式或多项式容器。
示例
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> R, x = ring("x", ZZ)
>>> R.add([ x**2 + 2*i + 3 for i in range(4) ])
4*x**2 + 24
>>> _.factor_list()
(4, [(x**2 + 6, 1)])
add_gens(symbols)
将symbols
的元素作为生成器添加到self
compose(other)
将other
的生成器添加到self
中
drop(*gens)
从此环中移除指定的生成器。
drop_to_ground(*gens)
从环中删除指定的生成元并将其注入到其域中。
index(gen)
计算 self.gens
中 gen
的索引。
monomial_basis(i)
返回第 i
个基础元素。
mul(*objs)
将一系列多项式或多项式容器相乘。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> R, x = ring("x", ZZ)
>>> R.mul([ x**2 + 2*i + 3 for i in range(4) ])
x**8 + 24*x**6 + 206*x**4 + 744*x**2 + 945
>>> _.factor_list()
(1, [(x**2 + 3, 1), (x**2 + 5, 1), (x**2 + 7, 1), (x**2 + 9, 1)])
symmetric_poly(n)
返回此环生成器上的度为 n 的基本对称多项式。
class sympy.polys.rings.PolyElement
多变量分布多项式环中的元素。
almosteq(p2, tolerance=None)
多项式的近似相等性测试。
cancel(g)
取消有理函数 f/g
中的公因子。
例子
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)
>>> (2*x**2 - 2).cancel(x**2 - 2*x + 1)
(2*x + 2, x - 1)
coeff(element)
返回紧挨给定单项式的系数。
参数:
element:PolyElement(带有 is_monomial = True
)或 1
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y, z = ring("x,y,z", ZZ)
>>> f = 3*x**2*y - x*y*z + 7*z**3 + 23
>>> f.coeff(x**2*y)
3
>>> f.coeff(x*y)
0
>>> f.coeff(1)
23
coeff_wrt(x, deg)
相对于 x**deg
的 self
的系数。
将 self
视为 x
中的一元多项式,找到作为其他生成元的多项式 x**deg
的系数。
参数:
x:生成元或生成元索引
用于计算表达式的生成元或生成元索引。
deg:整数
计算表达式的单项式的次数。
返回:
PolyElement
作为同一环中多项式的
x**deg
的系数。
例子
>>> from sympy.polys import ring, ZZ
>>> R, x, y, z = ring("x, y, z", ZZ)
>>> p = 2*x**4 + 3*y**4 + 10*z**2 + 10*x*z**2
>>> deg = 2
>>> p.coeff_wrt(2, deg) # Using the generator index
10*x + 10
>>> p.coeff_wrt(z, deg) # Using the generator
10*x + 10
>>> p.coeff(z**2) # shows the difference between coeff and coeff_wrt
10
另见
coeff
, coeffs
coeffs(order=None)
多项式的有序系数列表。
参数:
order:MonomialOrder
或可强制类型转换,可选
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring("x, y", ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>> f.coeffs()
[2, 1]
>>> f.coeffs(grlex)
[1, 2]
const()
返回常数系数。
content()
返回多项式系数的最大公约数。
copy()
返回多项式 self
的副本。
多项式是可变的;如果有人希望保留一个多项式并且打算使用原地操作,则可以复制多项式。此方法进行浅复制。
例子
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.rings import ring
>>> R, x, y = ring('x, y', ZZ)
>>> p = (x + y)**2
>>> p1 = p.copy()
>>> p2 = p
>>> p[R.zero_monom] = 3
>>> p
x**2 + 2*x*y + y**2 + 3
>>> p1
x**2 + 2*x*y + y**2
>>> p2
x**2 + 2*x*y + y**2 + 3
degree(x=None)
x
的主导次数或主变量。
注意,0 的次数为负无穷 (float('-inf')
)
degrees()
包含所有变量中的领先次数的元组。
注意,0 的次数为负无穷 (float('-inf')
)
diff(x)
在 x
中计算偏导数。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring("x,y", ZZ)
>>> p = x + x**2*y**3
>>> p.diff(x)
2*x*y**3 + 1
div(fv)
除法算法,见 [CLO] p64。
多项式数组的 fv
。
返回 qv, r
,使得 self = sum(fv[i]*qv[i]) + r
所有多项式都要求不是 Laurent 多项式。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring('x, y', ZZ)
>>> f = x**3
>>> f0 = x - y**2
>>> f1 = x - y
>>> qv, r = f.div((f0, f1))
>>> qv[0]
x**2 + x*y**2 + y**4
>>> qv[1]
0
>>> r
y**6
imul_num(c)
将多项式 p
乘以系数环中的元素,如果 p
不是生成元之一,则原地乘;否则,不原地乘。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring('x, y', ZZ)
>>> p = x + y**2
>>> p1 = p.imul_num(3)
>>> p1
3*x + 3*y**2
>>> p1 is p
True
>>> p = x
>>> p1 = p.imul_num(3)
>>> p1
3*x
>>> p1 is p
False
itercoeffs()
多项式系数的系数迭代器。
itermonoms()
多项式单项式的单项式迭代器。
iterterms()
多项式项的项迭代器。
leading_expv()
根据单项式顺序的领先单项式元组。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y, z = ring('x, y, z', ZZ)
>>> p = x**4 + x**3*y + x**2*z**2 + z**7
>>> p.leading_expv()
(4, 0, 0)
leading_monom()
领先单项式作为多项式元素。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring('x, y', ZZ)
>>> (3*x*y + y**2).leading_monom()
x*y
leading_term()
领先项作为多项式元素。
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring('x, y', ZZ)
>>> (3*x*y + y**2).leading_term()
3*x*y
listcoeffs()
多项式系数的无序列表。
listmonoms()
多项式单项式的无序列表。
listterms()
多项式项的无序列表。
monic()
将所有系数除以领先系数。
monoms(order=None)
多项式单项式的有序列表。
参数:
order:MonomialOrder
或可强制转换的,可选
例子
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring("x, y", ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>> f.monoms()
[(2, 3), (1, 7)]
>>> f.monoms(grlex)
[(1, 7), (2, 3)]
pdiv(g, x=None)
计算与多项式self
相对于g
的伪除。
伪除算法用于找到伪商q
和伪余数r
,使得m*f = g*q + r
,其中m
表示乘数,f
是被除多项式。
伪商q
和伪余数r
是关于变量x
的多项式,其中r
相对于x
的度严格小于g
相对于x
的度。
乘数m
被定义为LC(g, x) ^ (deg(f, x) - deg(g, x) + 1)
,其中LC(g, x)
表示g
的主导系数。
在prem
方法的上下文中,环中的多变量多项式,如R[x,y,z]
,被视为具有多项式系数的单变量多项式,如R[x,y][z]
。当相对于变量z
除以f
和g
时,伪商q
和伪余数r
满足m*f = g*q + r
,其中deg(r, z) < deg(g, z)
,且m = LC(g, z)^(deg(f, z) - deg(g, z) + 1)
。
在这个函数中,伪余数r
可以通过prem
方法获得,伪商q
可以通过pquo
方法获得,函数pdiv
本身返回一个元组(q, r)
。
参数:
g:PolyElement
被除多项式。
x:生成器或生成器索引,可选
多项式的主变量及默认为第一个生成器。
返回:
PolyElement
伪除多项式(元组
q
和r
)。
引发:
ZeroDivisionError:如果g
是零多项式。
例子
>>> from sympy.polys import ring, ZZ
>>> R, x, y = ring("x, y", ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2
>>> f.pdiv(g) # first generator is chosen by default if it is not given
(2*x + 2*y - 2, -4*y + 4)
>>> f.div(g) # shows the difference between pdiv and div
(0, x**2 + x*y)
>>> f.pdiv(g, y) # generator is given
(2*x**3 + 2*x**2*y + 6*x**2 + 2*x*y + 8*x + 4, 0)
>>> f.pdiv(g, 1) # generator index is given
(2*x**3 + 2*x**2*y + 6*x**2 + 2*x*y + 8*x + 4, 0)
另见
prem
比(f.pdiv(g)[1])更高效地计算仅伪余数。
pquo
仅返回伪商。
pexquo
仅返回无余项的精确伪商。
div
返回f
和g
多项式的商和余数。
pexquo(g, x=None)
多变量多项式环中的精确多项式伪商。
例子
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2*y
>>> h = 2*x + 2
>>> f.pexquo(g)
2*x
>>> f.exquo(g) # shows the differnce between pexquo and exquo
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x + 2*y does not divide x**2 + x*y
>>> f.pexquo(h)
Traceback (most recent call last):
...
ExactQuotientFailed: 2*x + 2 does not divide x**2 + x*y
另见
prem
,pdiv
,pquo
,sympy.polys.domains.ring.Ring.exquo
pquo(g, x=None)
多变量多项式环中的多项式伪商。
例子
>>> from sympy.polys import ring, ZZ
>>> R, x,y = ring("x,y", ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2*y
>>> h = 2*x + 2
>>> f.pquo(g)
2*x
>>> f.quo(g) # shows the difference between pquo and quo
0
>>> f.pquo(h)
2*x + 2*y - 2
>>> f.quo(h) # shows the difference between pquo and quo
0
另见
prem
, pdiv
, pexquo
, sympy.polys.domains.ring.Ring.quo
prem(g, x=None)
多项式self
相对于g
的伪余数。
将f
除以g
时,相对于z
的伪商q
和伪余数r
满足m*f = g*q + r
,其中deg(r,z) < deg(g,z)
,并且m = LC(g,z)**(deg(f,z) - deg(g,z)+1)
。
参见pdiv()
以了解伪除法的解释。
参数:
g:PolyElement
被
self
除以的多项式。
x:生成器或生成器索引,可选
多项式的主变量,默认为第一个生成器。
Returns:
PolyElement
伪余数多项式。
Raises:
ZeroDivisionError:如果g
是零多项式。
示例
>>> from sympy.polys import ring, ZZ
>>> R, x, y = ring("x, y", ZZ)
>>> f = x**2 + x*y
>>> g = 2*x + 2
>>> f.prem(g) # first generator is chosen by default if it is not given
-4*y + 4
>>> f.rem(g) # shows the differnce between prem and rem
x**2 + x*y
>>> f.prem(g, y) # generator is given
0
>>> f.prem(g, 1) # generator index is given
0
另请参阅
pdiv
, pquo
, pexquo
, sympy.polys.domains.ring.Ring.rem
primitive()
返回内容和原始多项式。
square()
多项式的平方
示例
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> _, x, y = ring('x, y', ZZ)
>>> p = x + y**2
>>> p.square()
x**2 + 2*x*y**2 + y**4
strip_zero()
消除零系数的单项式。
subresultants(g, x=None)
计算两个多项式self
和g
的次结果 PRS。
参数:
g:PolyElement
第二个多项式。
x:生成器或生成器索引
计算次结果序列的变量。
Returns:
R:列表
返回一个表示次结果 PRS 的多项式列表。
示例
>>> from sympy.polys import ring, ZZ
>>> R, x, y = ring("x, y", ZZ)
>>> f = x**2*y + x*y
>>> g = x + y
>>> f.subresultants(g) # first generator is chosen by default if not given
[x**2*y + x*y, x + y, y**3 - y**2]
>>> f.subresultants(g, 0) # generator index is given
[x**2*y + x*y, x + y, y**3 - y**2]
>>> f.subresultants(g, y) # generator is given
[x**2*y + x*y, x + y, x**3 + x**2]
symmetrize()
用基本对称多项式重新表达self。
Returns:
三元组(p, r, m)
p
是一个PolyElement
,代表我们尝试将self表示为基本对称多项式函数的结果。p
中的每个变量代表一个基本对称多项式,映射由m
给出。
r
是余数。
m
是一个列表,给出了从p
中的变量到基本对称多项式的映射。三元组满足方程
p.compose(m) + r == self
。如果余数r
为零,则self是对称的。如果不为零,则我们无法将self表示为对称的。
Explanation
如果这个PolyElement
属于(n)变量的环,我们可以尝试将其写成(n)变量的基本对称多项式的函数。我们计算对称部分和任何无法对称化的余数的余数。
示例
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> R, x, y = ring("x,y", ZZ)
>>> f = x**2 + y**2
>>> f.symmetrize()
(x**2 - 2*y, 0, [(x, x + y), (y, x*y)])
>>> f = x**2 - y**2
>>> f.symmetrize()
(x**2 - 2*y, -2*y**2, [(x, x + y), (y, x*y)])
另请参见
sympy.polys.polyfuncs.symmetrize
参考
[R783]
Lauer, E. Symmetrical polynomials 算法,Proc. 1976 ACM Symp. on Symbolic and Algebraic Computing,NY 242-247。dl.acm.org/doi/pdf/10.1145/800205.806342
tail_degree(x=None)
x
的尾度或主变量。
注意,0 的度为负无穷(float('-inf')
)
tail_degrees()
包含所有变量的尾度的元组。
注意,0 的度为负无穷(float('-inf')
)
terms(order=None)
有序多项式项的列表。
参数:
order:MonomialOrder
或者可强制转换的,可选
示例
>>> from sympy.polys.rings import ring
>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.orderings import lex, grlex
>>> _, x, y = ring("x, y", ZZ, lex)
>>> f = x*y**7 + 2*x**2*y**3
>>> f.terms()
[((2, 3), 2), ((1, 7), 1)]
>>> f.terms(grlex)
[((1, 7), 1), ((2, 3), 2)]
稀疏有理函数
稀疏多项式表示为字典。
sympy.polys.fields.field(symbols, domain, order=LexOrder())
构造新的有理函数域,返回(域,x1,…,xn)。
sympy.polys.fields.xfield(symbols, domain, order=LexOrder())
构造新的有理函数域,返回(域,(x1,…,xn))。
sympy.polys.fields.vfield(symbols, domain, order=LexOrder())
构造新的有理函数域,并将生成器注入全局命名空间。
sympy.polys.fields.sfield(exprs, *symbols, **options)
根据选项和输入表达式构造一个域,并生成域。
参数:
exprs:py:class:(~.Expr) 或者 Expr
的序列(可简化)
符号:Symbol
/Expr
的序列
选项:被Options
理解的关键字参数
示例
>>> from sympy import exp, log, symbols, sfield
>>> x = symbols("x")
>>> K, f = sfield((x*log(x) + 4*x**2)*exp(1/x + log(x)/3)/x**2)
>>> K
Rational function field in x, exp(1/x), log(x), x**(1/3) over ZZ with lex order
>>> f
(4*x**2*(exp(1/x)) + x*(exp(1/x))*(log(x)))/((x**(1/3))**5)
class sympy.polys.fields.FracField(symbols, domain, order=LexOrder())
多变量分布有理函数域。
class sympy.polys.fields.FracElement(numer, denom=None)
多变量分布有理函数域的元素。
diff(x)
计算x
中的偏导数。
示例
>>> from sympy.polys.fields import field
>>> from sympy.polys.domains import ZZ
>>> _, x, y, z = field("x,y,z", ZZ)
>>> ((x**2 + y)/(z + 1)).diff(x)
2*x/(z + 1)
密集多项式
class sympy.polys.polyclasses.DMP(rep, dom, lev=None)
在(K)上的密集多变量多项式。
LC()
返回f
的首系数。
TC()
返回f
的尾系数。
abs()
使f
中的所有系数均为正。
add(g)
添加两个多变量多项式f
和g
。
add_ground(c)
将一个地域域的元素添加到f
。
all_coeffs()
返回f
的所有系数。
all_monoms()
返回f
中的所有单项式。
all_terms()
返回f
的所有项。
cancel(g, include=True)
取消有理函数f/g
中的公因子。
cauchy_lower_bound()
计算f
的非零根的柯西下界。
cauchy_upper_bound()
计算f
的根的柯西上界。
clear_denoms()
清除分母,但保留地域域。
coeffs(order=None)
按字典序返回f
中的所有非零系数。
cofactors(g)
返回f
和g
的 GCD 及其余式。
compose(g)
计算f
和g
的函数组合。
content()
返回多项式系数的 GCD。
convert(dom)
将f
转换为在新域上的DMP
。
count_complex_roots(inf=None, sup=None)
在[inf, sup]
中计算f
的复根的数量。
count_real_roots(inf=None, sup=None)
返回f
在[inf, sup]
中的实根数。
decompose()
计算f
的函数分解。
deflate()
通过将(x_i^m)映射到(y_i)来减少(f)的次数。
degree(j=0)
返回f
在x_j
中的主导度。
degree_list()
返回f
的次数列表。
diff(m=1, j=0)
计算f
在x_j
处的m
阶导数。
discriminant()
计算f
的判别式。
div(g)
f
和g
的多项式除法及余数。
eject(dom, front=False)
将选定的生成器弹出到基域。
eval(a, j=0)
在给定点a
处评估f
在x_j
中。
exclude()
从f
中删除无用的生成器。
返回移除的生成器和新排除的f
。
示例
>>> from sympy.polys.polyclasses import DMP
>>> from sympy.polys.domains import ZZ
>>> DMP([[[ZZ(1)]], [[ZZ(1)], [ZZ(2)]]], ZZ).exclude()
([2], DMP_Python([[1], [1, 2]], ZZ))
exquo(g)
计算f
和g
的多项式精确商。
exquo_ground(c)
通过基域元素精确除f
的商。
factor_list()
返回f
的不可约因子列表。
factor_list_include()
返回f
的不可约因子列表。
classmethod from_list(rep, lev, dom)
给定原生系数列表,创建cls
的实例。
classmethod from_sympy_list(rep, lev, dom)
给定 SymPy 系数列表,创建cls
的实例。
gcd(g)
返回f
和g
的多项式最大公约数。
gcdex(g)
扩展欧几里得算法,如果是一元的。
gff_list()
计算f
的最大阶乘因子分解。
ground_new(coeff)
构造f
的新基域实例。
half_gcdex(g)
半扩展欧几里得算法,如果是一元的。
homogeneous_order()
返回f
的齐次阶数。
homogenize(s)
返回f
的齐次多项式。
inject(front=False)
将基域生成器注入到f
中。
integrate(m=1, j=0)
计算f
在x_j
中的m
阶不定积分。
intervals(all=False, eps=None, inf=None, sup=None, fast=False, sqf=False)
计算f
的根的隔离区间。
invert(g)
如果可能,对f
关于g
取模倒数。
property is_cyclotomic
如果f
是循环多项式,则返回True
。
property is_ground
如果f
是基域的元素,则返回True
。
property is_homogeneous
如果f
是齐次多项式,则返回True
。
property is_irreducible
如果f
在其域中没有因子,则返回True
。
property is_linear
如果f
在所有变量中都是线性的,则返回True
。
property is_monic
如果f
的首项系数为 1,则返回True
。
property is_monomial
如果f
为零或只有一项,则返回True
。
property is_one
如果f
是单位多项式,则返回True
。
property is_primitive
如果f
的系数的最大公约数为 1,则返回True
。
property is_quadratic
如果f
在所有变量中都是二次的,则返回True
。
property is_sqf
如果f
是无平方根多项式,则返回True
。
property is_zero
如果f
是零多项式,则返回True
。
l1_norm()
返回f
的 l1 范数。
l2_norm_squared()
返回f
的平方 l2 范数。
lcm(g)
返回f
和g
的多项式最小公倍数。
lift()
将代数系数转换为有理数。
max_norm()
返回f
的最大范数。
mignotte_sep_bound_squared()
计算f
根分离的平方 Mignotte 界。
monic()
将f
的所有系数除以LC(f)
。
monoms(order=None)
返回f
中按字典序的所有非零单项式。
mul(g)
将两个多变量多项式f
和g
相乘。
mul_ground(c)
将f
乘以基域的元素。
neg()
反转f
中所有系数。
norm()
计算Norm(f)
。
nth(*N)
返回f
的第n
个系数。
pdiv(g)
f
和g
的多项式伪除法。
permute(P)
返回在(K[x_{P(1)}, ..., x_{P(n)}])中的多项式。
示例
>>> from sympy.polys.polyclasses import DMP
>>> from sympy.polys.domains import ZZ
>>> DMP([[[ZZ(2)], [ZZ(1), ZZ(0)]], [[]]], ZZ).permute([1, 0, 2])
DMP_Python([[[2], []], [[1, 0], []]], ZZ)
>>> DMP([[[ZZ(2)], [ZZ(1), ZZ(0)]], [[]]], ZZ).permute([1, 2, 0])
DMP_Python([[[1], []], [[2, 0], []]], ZZ)
pexquo(g)
f
和g
的多项式精确伪商。
pow(n)
将f
提升到非负幂n
。
pquo(g)
f
和g
的多项式伪商。
prem(g)
f
和g
的多项式伪余数。
primitive()
返回f
的内容和一个原始形式。
quo(g)
计算f
和g
的多项式商。
quo_ground(c)
通过基域元素除f
的商。
refine_root(s, t, eps=None, steps=None, fast=False)
精确化到给定精度的隔离区间。
eps
应为一个有理数。
rem(g)
计算 f
和 g
的多项式余数。
property rep
获取 f
的表示。
resultant(g, includePRS=False)
通过 PRS 计算 f
和 g
的结果。
revert(n)
计算 f**(-1)
模 x**n
。
shift(a)
高效计算 Taylor 移位 f(x + a)
。
shift_list(a)
高效计算 Taylor 移位 f(X + A)
。
slice(m, n, j=0)
取 f
的项的连续子序列。
sqf_list(all=False)
返回 f
的平方自由因子列表。
sqf_list_include(all=False)
返回 f
的平方自由因子列表。
sqf_norm()
计算 f
的平方自由规范。
sqf_part()
计算 f
的平方自由部分。
sqr()
对多变量多项式 f
进行平方。
sturm()
计算 f
的斯图姆序列。
sub(g)
将两个多变量多项式 f
和 g
相减。
sub_ground(c)
从地面域中减去 f
的一个元素。
subresultants(g)
计算 f
和 g
的子结果 PRS 序列。
terms(order=None)
返回 f
中按字典顺序的所有非零项。
terms_gcd()
从多项式 f
中删除项的最大公因数。
to_best()
如果可能,转换为 DUP_Flint。
当域或级别改变时应使用此方法,可能可以从 DMP_Python 转换为 DUP_Flint。
to_dict(zero=False)
将 f
转换为具有本机系数的字典表示。
to_exact()
使地面域精确。
to_field()
使地面域成为一个域。
to_list()
将 f
转换为具有本机系数的列表表示。
to_ring()
使地面域成为一个环。
to_sympy_dict(zero=False)
将 f
转换为具有 SymPy 系数的字典表示。
to_sympy_list()
将 f
转换为具有 SymPy 系数的列表表示。
to_tuple()
将 f
转换为具有本机系数的元组表示。
这是哈希所需的。
total_degree()
返回 f
的总次数。
transform(p, q)
评估功能变换 q**n * f(p/q)
。
trunc(p)
将 f
减去常数 p
的模。
unify_DMP(g)
统一并返回 f
和 g
的 DMP
实例。
class sympy.polys.polyclasses.DMF(rep, dom, lev=None)
在域 (K) 上的密集多变量分数。
add(g)
将两个多变量分数 f
和 g
相加。
add_ground(c)
向 f
添加地面域的一个元素。
cancel()
从 f.num
和 f.den
中删除公共因子。
denom()
返回 f
的分母。
exquo(g)
计算分数 f
和 g
的商。
frac_unify(g)
统一两个多变量分数的表示。
half_per(rep, kill=False)
创建给定表示的 DMP。
invert(check=True)
计算分数 f
的逆。
property is_one
如果 f
是单位分数,返回 True
。
property is_zero
如果 f
是零分数,返回 True
。
mul(g)
乘以两个多变量分数 f
和 g
。
neg()
反转 f
中的所有系数。
numer()
返回 f
的分子。
per(num, den, cancel=True, kill=False)
根据给定表示创建 DMF。
poly_unify(g)
统一多变量分数和多项式。
pow(n)
将 f
提升到非负幂 n
。
quo(g)
计算分数 f
和 g
的商。
sub(g)
将两个多变量分数 f
和 g
相减。
class sympy.polys.polyclasses.ANP(rep, mod, dom)
在域上的密集代数数多项式。
LC()
返回 f
的首项系数。
TC()
返回 f
的尾数系数。
add_ground(c)
向 f
添加地面域的一个元素。
convert(dom)
将 f
转换为新域上的 ANP
。
property is_ground
如果 f
是地面域的元素,返回 True
。
property is_one
如果 f
是单位代数数,返回 True
。
property is_zero
如果 f
是零代数数,返回 True
。
mod_to_list()
将 f.mod
作为具有本机系数的列表返回。
mul_ground(c)
将 f
乘以地面域的一个元素。
pow(n)
将 f
提升到非负幂 n
。
quo_ground(c)
以地面域元素为除数f
的商。
sub_ground(c)
从地面域元素中减去f
。
to_dict()
将f
转换为具有本地系数的字典表示。
to_list()
将f
转换为具有本地系数的列表表示。
to_sympy_dict()
将f
转换为具有 SymPy 系数的字典表示。
to_sympy_list()
将f
转换为具有 SymPy 系数的列表表示。
to_tuple()
将f
转换为具有本地系数的元组表示。
这对于哈希是必需的。
unify(g)
统一两个代数数的表示。
unify_ANP(g)
统一并返回f
和g
的DMP
实例。