韦斯特文章中的例子#

介绍#

在本教程中,我们将从韦斯特的文章中给出一些例子,这些文章涉及到几种计算机代数系统的数学能力的比较和批判(参见 [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() .

协变因式分解#

考虑一元多项式 fgh 整数上:

>>> 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

我们看到了 fg 没有共同因素。然而, f*hg*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与因子分解#

在单变量情况下可以做的,也可以对多元多项式做。考虑下面的多项式 fgh 在里面 \(\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

如前所述,我们可以验证 fg 没有共同因素:

>>> gcd(f, g)
1

然而, f*hg*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 ⎠

自动域扩展的计算#

考虑两个一元多项式 fg ::

>>> 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() 功能。该函数接受各种单项排序,例如: lexgrlexgrevlex ,或用户定义的,通过 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

文学类#

[Wester1999]

Michael J. Wester, A Critique of the Mathematical Abilities of CA Systems, 1999, https://www.math.unm.edu/~wester/cas/book/Wester.pdf