韦斯特文章中的例子#
介绍#
在本教程中,我们将从韦斯特的文章中给出一些例子,这些文章涉及到几种计算机代数系统的数学能力的比较和批判(参见 [Wester1999]) . 所有的例子都与多项式和代数计算有关,并且在所有的例子中都添加了特殊的注释。
实例#
本教程中的所有示例都是可计算的,因此您只需将它们复制并粘贴到pythonshell中,然后使用它们做一些有用的事情。所有计算均使用以下设置完成:
>>> from sympy import *
>>> init_printing(use_unicode=True, wrap_line=False)
>>> var('x,y,z,s,c')
(x, y, z, s, c)
简单一元多项式因式分解#
求多项式的因式分解 factor()
功能。默认情况下 factor()
以未赋值形式返回结果,因此输入多项式的内容不展开,如下例所示:
>>> factor(6*x - 10)
2⋅(3⋅x - 5)
以更系统的方式达到同样的效果 primitive()
函数,它返回输入多项式的内容和基元部分:
>>> primitive(6*x - 10)
(2, 3⋅x - 5)
备注
内容和基元部分只能在环上计算。一个多项式系数的简化 monic()
.
协变因式分解#
考虑一元多项式 f
, g
和 h
整数上:
>>> f = 64*x**34 - 21*x**47 - 126*x**8 - 46*x**5 - 16*x**60 - 81
>>> g = 72*x**60 - 25*x**25 - 19*x**23 - 22*x**39 - 83*x**52 + 54*x**10 + 81
>>> h = 34*x**19 - 25*x**16 + 70*x**7 + 20*x**3 - 91*x - 86
我们可以用 gcd()
功能:
>>> gcd(f, g)
1
我们看到了 f
和 g
没有共同因素。然而, f*h
和 g*h
有一个明显的因素 h
::
>>> gcd(expand(f*h), expand(g*h)) - h
0
同样可以用一元多项式的结果进行验证:
>>> resultant(expand(f*h), expand(g*h))
0
整数上的大型单变量多项式(在本例中为120次)的因式分解也是可能的:
>>> factor(expand(f*g))
⎛ 60 47 34 8 5 ⎞ ⎛ 60 52 39 25 23 10 ⎞
-⎝16⋅x + 21⋅x - 64⋅x + 126⋅x + 46⋅x + 81⎠⋅⎝72⋅x - 83⋅x - 22⋅x - 25⋅x - 19⋅x + 54⋅x + 81⎠
多元GCD与因子分解#
在单变量情况下可以做的,也可以对多元多项式做。考虑下面的多项式 f
, g
和 h
在里面 \(\mathbb{{Z}}[x,y,z]\) ::
>>> f = 24*x*y**19*z**8 - 47*x**17*y**5*z**8 + 6*x**15*y**9*z**2 - 3*x**22 + 5
>>> g = 34*x**5*y**8*z**13 + 20*x**7*y**7*z**7 + 12*x**9*y**16*z**4 + 80*y**14*z
>>> h = 11*x**12*y**7*z**13 - 23*x**2*y**8*z**10 + 47*x**17*y**5*z**8
如前所述,我们可以验证 f
和 g
没有共同因素:
>>> gcd(f, g)
1
然而, f*h
和 g*h
有一个明显的因素 h
::
>>> gcd(expand(f*h), expand(g*h)) - h
0
大多项式的多元因式分解也是可能的:
>>> factor(expand(f*g))
7 ⎛ 9 9 3 7 6 5 12 7⎞ ⎛ 22 17 5 8 15 9 2 19 8 ⎞
-2⋅y ⋅z⋅⎝6⋅x ⋅y ⋅z + 10⋅x ⋅z + 17⋅x ⋅y⋅z + 40⋅y ⎠⋅⎝3⋅x + 47⋅x ⋅y ⋅z - 6⋅x ⋅y ⋅z - 24⋅x⋅y ⋅z - 5⎠
支持指数符号#
多项式操作函数由 sympy.polys
主要用于整数指数。但是,用符号指数来计算是完全有效的,例如:
>>> n = var('n')
>>> gcd(x**n - x**(2*n), x**n)
n
x
Results may depend on powers being expanded (which will depend on
assumptions of the base):
>>> gcd(x**(n + 4), x**(n + 1) + 3*x**n)
1
>>> x = var('x', positive=True)
>>> gcd(x**(n + 4), x**(n + 1) + 3*x**n)
n
x
检验多项式是否有公共零点#
为了测试两个多项式是否有共同的根,我们可以使用 resultant()
功能。该理论认为,如果两个多项式的公共零点为零,则两个多项式的结果为零。例如::
>>> x = var('x')
>>> resultant(3*x**4 + 3*x**3 + x**2 - x - 2, x**3 - 3*x**2 + x + 5)
0
我们可以通过分解多项式来形象化这个事实:
>>> factor(3*x**4 + 3*x**3 + x**2 - x - 2)
⎛ 3 ⎞
(x + 1)⋅⎝3⋅x + x - 2⎠
>>> factor(x**3 - 3*x**2 + x + 5)
⎛ 2 ⎞
(x + 1)⋅⎝x - 4⋅x + 5⎠
在这两种情况下,我们都得到了因子 \(x + 1\) 它告诉我们共同的根是 \(x = -1\) .
规范化简单有理函数#
要从有理函数的分子和分母中去除公因子,请使用 cancel()
功能。例如::
>>> cancel((x**2 - 4)/(x**2 + 4*x + 4))
x - 2
─────
x + 2
展开表达式和因子分解#
我们可以很容易地工作,我们的表达式在扩展和因子形式。考虑一个多项式 f
以展开的形式。我们将其进行区分并将结果考虑回来:
>>> f = expand((x + 1)**20)
>>> g = diff(f, x)
>>> factor(g)
19
20⋅(x + 1)
同样可以通过系数形式实现:
>>> diff((x + 1)**20, x)
19
20⋅(x + 1)
分圆多项式的因式分解#
SymPy可以非常有效地分解多项式的形式 \(x^n \pm 1\) 关于分圆多项式:
>>> factor(x**15 - 1)
⎛ 2 ⎞ ⎛ 4 3 2 ⎞ ⎛ 8 7 5 4 3 ⎞
(x - 1)⋅⎝x + x + 1⎠⋅⎝x + x + x + x + 1⎠⋅⎝x - x + x - x + x - x + 1⎠
最初韦斯特的例子是 \(x^{{100}} - 1\) ,但出于可读性目的被截断。请注意,这并不是一个大的斗争 factor()
分解1000次以上的多项式。
高斯数上的单变量因子分解#
考虑一元多项式 f
整系数:
>>> f = 4*x**4 + 8*x**3 + 77*x**2 + 18*x + 153
我们要得到 f
超过高斯数。为此,我们使用 factor()
和以前一样,但这次我们 gaussian
关键字到 True
::
>>> factor(f, gaussian=True)
⎛ 3⋅ⅈ⎞ ⎛ 3⋅ⅈ⎞
4⋅⎜x - ───⎟⋅⎜x + ───⎟⋅(x + 1 - 4⋅ⅈ)⋅(x + 1 + 4⋅ⅈ)
⎝ 2 ⎠ ⎝ 2 ⎠
结果我们得到了 f
使用monic factors(这是在具有SymPy的字段中进行计算时的通用规则)。这个 gaussian
关键字对于提高代码的可读性很有用,但是可以使用更通用的语法计算相同的结果:
>>> factor(f, extension=I)
⎛ 3⋅ⅈ⎞ ⎛ 3⋅ⅈ⎞
4⋅⎜x - ───⎟⋅⎜x + ───⎟⋅(x + 1 - 4⋅ⅈ)⋅(x + 1 + 4⋅ⅈ)
⎝ 2 ⎠ ⎝ 2 ⎠
自动域扩展的计算#
考虑两个一元多项式 f
和 g
::
>>> f = x**3 + (sqrt(2) - 2)*x**2 - (2*sqrt(2) + 3)*x - 3*sqrt(2)
>>> g = x**2 - 2
我们想减少有理函数的分子和分母的度数 f/g
. 我们雇佣 cancel()
功能:
>>> cancel(f/g)
3 2 2
x - 2⋅x + √2⋅x - 3⋅x - 2⋅√2⋅x - 3⋅√2
───────────────────────────────────────
2
x - 2
不幸的是,没有什么有趣的事情发生。这是因为在默认情况下,SymPy处理 \(\sqrt{{2}}\) 作为生成器,得到分子的二元多项式。使 cancel()
识别的代数性质 \(\sqrt{{2}}\) ,需要使用 extension
关键词:
>>> cancel(f/g, extension=True)
2
x - 2⋅x - 3
────────────
x - √2
设置 extension=True
告诉 cancel()
求系数的最小代数数域 f/g
. 自动推断的域是 \(\mathbb{{Q}}(\sqrt{{2}})\) . 如果不想依赖自动推理,则可以通过设置 extension
具有显式代数数的关键字::
>>> cancel(f/g, extension=sqrt(2))
2
x - 2⋅x - 3
────────────
x - √2
多域上的单变量因子分解#
考虑一元多项式 f
整系数:
>>> f = x**4 - 3*x**2 + 1
用 sympy.polys
我们可以得到 f
在不同的领域,包括:
理性主义:
>>> factor(f) ⎛ 2 ⎞ ⎛ 2 ⎞ ⎝x - x - 1⎠⋅⎝x + x - 1⎠
有限域:
>>> factor(f, modulus=5) 2 2 (x - 2) ⋅(x + 2)
代数数:
>>> alg = AlgebraicNumber((sqrt(5) - 1)/2, alias='alpha') >>> factor(f, extension=alg) (x - α)⋅(x + α)⋅(x - 1 - α)⋅(x + α + 1)
多项式分解成线性因子#
目前,SymPy可以将多项式分解为不同域上的不可约项,这可以导致分解(成线性因子)。然而,目前还没有系统的方法来自动推断分裂域(代数数域)。将来将实现以下语法:
>>> factor(x**3 + x**2 - 7, split=True)
Traceback (most recent call last):
...
NotImplementedError: 'split' option is not implemented yet
注意这与 extension=True
,因为后者只告诉如何进行表达式解析,而不是计算的领域。我们可以模拟 split
几类多项式的关键字 solve()
功能。
有限域上的高级因子分解#
考虑一元多项式 f
整系数:
>>> f = x**11 + x + 1
我们可以考虑 f
在大的有限域上 \(F_{{65537}}\) ::
>>> factor(f, modulus=65537)
⎛ 2 ⎞ ⎛ 9 8 6 5 3 2 ⎞
⎝x + x + 1⎠⋅⎝x - x + x - x + x - x + 1⎠
并将得到的因式分解展开:
>>> expand(_)
11
x + x + 1
求多项式 f
. 这是用有限域上的对称多项式表示来完成的,同样的事情也可以用非对称表示来完成:
>>> factor(f, modulus=65537, symmetric=False)
⎛ 2 ⎞ ⎛ 9 8 6 5 3 2 ⎞
⎝x + x + 1⎠⋅⎝x + 65536⋅x + x + 65536⋅x + x + 65536⋅x + 1⎠
与对称表示一样,我们可以展开因式分解以得到输入多项式。但是,这次我们需要截断展开多项式模65537的系数:
>>> trunc(expand(_), 65537)
11
x + x + 1
将表达式用作多项式#
考虑一个多元多项式 f
在里面 \(\mathbb{{Z}}[x,y,z]\) ::
>>> f = expand((x - 2*y**2 + 3*z**3)**20)
我们要计算 f
. 为此,我们使用 factor
然而,通常我们注意到所考虑的多项式已经是展开形式,所以我们可以告诉因子分解例程跳过展开 f
::
>>> factor(f, expand=False)
20
⎛ 2 3⎞
⎝x - 2⋅y + 3⋅z ⎠
默认值 sympy.polys
将作为参数的所有表达式展开为多项式操作函数和 Poly
班级。如果我们知道扩展是不必要的,那么通过设置 expand=False
我们可以为复杂的输入节省很多时间。当使用以下表达式进行计算时,这一点非常重要:
>>> g = expand((sin(x) - 2*cos(y)**2 + 3*tan(z)**3)**20)
>>> factor(g, expand=False)
20
⎛ 2 3 ⎞
⎝-sin(x) + 2⋅cos (y) - 3⋅tan (z)⎠
计算约化Gröbner基#
要计算一组多项式的约化Gröbner基,请使用 groebner()
功能。该函数接受各种单项排序,例如: lex
, grlex
和 grevlex
,或用户定义的,通过 order
关键字。这个 lex
排序是最有趣的,因为它具有消去性,这意味着如果多项式方程组 groebner()
是零维(有有限个解)基的最后一个元素是一元多项式。考虑以下示例:
>>> f = expand((1 - c**2)**5 * (1 - s**2)**5 * (c**2 + s**2)**10)
>>> groebner([f, c**2 + s**2 - 1])
⎛⎡ 2 2 20 18 16 14 12 10⎤ ⎞
GroebnerBasis⎝⎣c + s - 1, c - 5⋅c + 10⋅c - 10⋅c + 5⋅c - c ⎦, s, c, domain=ℤ, order=lex⎠
结果是一个普通的Python列表,因此我们可以轻松地将一个函数应用于它的所有元素,例如,我们可以将这些元素因子:
>>> list(map(factor, _))
⎡ 2 2 10 5 5⎤
⎣c + s - 1, c ⋅(c - 1) ⋅(c + 1) ⎦
从上面我们可以很容易地找到多项式方程组的所有解。或者我们可以用 solve()
为了更系统地实现这一点:
>>> solve([f, s**2 + c**2 - 1], c, s)
[(-1, 0), (0, -1), (0, 1), (1, 0)]
代数数上的多元因式分解#
在不同的域上用多元多项式进行计算和在单变量情况下一样简单。例如,考虑下面的因式分解 \(\mathbb{{Q}}(\sqrt{{-3}})\) ::
>>> factor(x**3 + y**3, extension=sqrt(-3))
⎛ ⎛ 1 √3⋅ⅈ⎞⎞ ⎛ ⎛ 1 √3⋅ⅈ⎞⎞
(x + y)⋅⎜x + y⋅⎜- ─ - ────⎟⎟⋅⎜x + y⋅⎜- ─ + ────⎟⎟
⎝ ⎝ 2 2 ⎠⎠ ⎝ ⎝ 2 2 ⎠⎠
备注
目前不支持有限域上的多元多项式。
部分分数分解#
考虑一元有理函数 f
整系数:
>>> f = (x**2 + 2*x + 3)/(x**3 + 4*x**2 + 5*x + 2)
分解 f
变成部分分数使用 apart()
功能:
>>> apart(f)
3 2 2
───── - ───── + ────────
x + 2 x + 1 2
(x + 1)
要从部分分数返回有理函数,请使用 together()
和 cancel()
::
>>> cancel(together(_))
2
x + 2⋅x + 3
───────────────────
3 2
x + 4⋅x + 5⋅x + 2
文学类#
Michael J. Wester, A Critique of the Mathematical Abilities of CA Systems, 1999, https://www.math.unm.edu/~wester/cas/book/Wester.pdf