模块的基本功能#
介绍#
本教程试图概述symphy中有关多项式的功能。所有代码示例假定:
>>> from sympy import *
>>> x, y, z = symbols('x,y,z')
>>> init_printing(use_unicode=False, wrap_line=False)
基本概念#
多项式#
给一个家庭 \((x_i)\) 对于符号或其他合适的对象,包括数字,通过反复的加法、减法和乘法得到的表达式称为 生成元中的多项式表达式 \(x_i\) .
根据分配定律,在加减法之前可以进行乘法运算。由此得到的发电机产品称为 单项式 . 它们通常是用表格写的 \(x_1^{{\nu_1}}x_2^{{\nu_2}}\cdots x_n^{{\nu_n}}\) 其中指数 \(\nu_i\) 是非负整数。这通常是方便的写这简短的作为 \(x^\nu\) 在哪里? \(x = (x_1, x_2, \ldots, x_n)\) 表示生成器和 \(\nu = (\nu_1, \nu_2, \ldots, \nu_n)\) 是指数族。
当具有相同指数的所有单项式被组合时,多项式表达式成为乘积之和 \(c_\nu x^\nu\) ,称为 条款 多项式的,其中 系数 \(c_\nu\) 是整数。如果 \(x_i\) 是显式数,它们包含在系数中,不被视为生成元。这些系数通常是有理数、实数或复数。一些符号数字,例如。, pi
,可以是系数或生成器。
多项式表达式是不同单项式的项之和,由其系数族唯一确定 \((c_\nu)\) . 这种表达习惯上称为 多项式的 不过,更确切地说,一旦给定了生成器,这个名称确实代表了系数族。SymPy默认将多项式作为字典实现,单项式作为键,系数作为值。另一个实现由嵌套的系数列表组成。
The set of all polynomials with integer coefficients in the generators \(x_i\) is a ring, i.e., the sums, differences and products of its elements are again polynomials in the same generators. This ring is denoted \(\mathbb{Z}[x_1, x_2, \ldots, x_n]\), or \(\mathbb{Z}[(x_i)]\), and called the ring of polynomials in the \(x_i\) with integer coefficients.
更一般地说,多项式的系数可以是任何交换环的元素 \(A\) ,然后表示相应的多项式环 \(A[x_1, x_2, \dots, x_n]\) . 戒指 \(A\) 也可以是多项式环。在SymPy中,系数环被称为 domain
它可以作为一个关键字参数给出。默认情况下,它由多项式参数的系数决定。
该方法可以将多项式表达式转化为多项式 sympy.core.expr.Expr.as_poly
::
>>> e = (x + y)*(y - 2*z)
>>> e.as_poly()
Poly(x*y - 2*x*z + y**2 - 2*y*z, x, y, z, domain='ZZ')
如果一个多项式表达式包含不是整数的数,则将它们视为系数,并相应地扩展系数环。尤其是,被整数除得到有理系数:
>>> e = (3*x/2 + y)*(z - 1)
>>> e.as_poly()
Poly(3/2*x*z - 3/2*x + y*z - y, x, y, z, domain='QQ')
符号数被认为是生成器,除非它们被明确排除在外,在这种情况下,它们与系数环相邻:
>>> e = (x + 2*pi)*y
>>> e.as_poly()
Poly(x*y + 2*y*pi, x, y, pi, domain='ZZ')
>>> e.as_poly(x, y)
Poly(x*y + 2*pi*y, x, y, domain='ZZ[pi]')
或者,可以通过关键字参数指定系数域:
>>> e = (x + 2*pi)*y
>>> e.as_poly(domain=ZZ[pi])
Poly(x*y + 2*pi*y, x, y, domain='ZZ[pi]')
注意戒指 \(\mathbb{{Z}}[\pi][x, y]\) 多项式的 \(x\) 和 \(y\) 系数为 \(\mathbb{{Z}}[\pi]\) 在数学上等价于 \(\mathbb{{Z}}[\pi, x, y]\) ,只是它们的实现不同。
如果表达式包含生成器的函数,而不是它们的正整数幂,则这些函数将被解释为新的生成器:
>>> e = x*sin(y) - y
>>> e.as_poly()
Poly(x*(sin(y)) - y, x, y, sin(y), domain='ZZ')
自从 \(y\) 和 \(\sin(y)\) 它们在代数上是独立的,它们都可以作为生成元出现在多项式中。然而, 多项式表达式不能包含生成器的负幂 ::
>>> e = x - 1/x
>>> e.as_poly()
Poly(x - (1/x), x, 1/x, domain='ZZ')
重要的是要认识到发电机 \(x\) 和 \(1/x = x^{{-1}}\) 作为代数自变量处理。尤其是他们的乘积不等于1。因此 分母中的生成器应该避免,即使它们在当前的实现中没有引起错误 . 这种行为是不可取的,将来可能会改变。发电机的合理功率也会出现类似的问题。比如说, \(x\) 和 \(\sqrt x = x^{{1/2}}\) 不被认为是代数依赖的。
如果表达式中有代数数,可以通过设置关键字将它们与系数环相连 extension
::
>>> e = x + sqrt(2)
>>> e.as_poly()
Poly(x + (sqrt(2)), x, sqrt(2), domain='ZZ')
>>> e.as_poly(extension=True)
Poly(x + sqrt(2), x, domain='QQ<sqrt(2)>')
使用默认设置 extension=False
,两者都是 \(x\) 和 \(\sqrt 2\) 被错误地认为是代数独立变量。其系数在扩展域中 \(\mathbb{Q}(\sqrt 2)\) 平方根被恰当地当作一个代数数来对待。设置 extension=True
无论何时涉及到代数数字,都绝对推荐使用,即使在当前实现中没有强制使用。
可分性#
第四个有理运算,除法,或倒数乘法,在环中通常是不可能的。如果 \(a\) 和 \(b\) 是环的两个元素 \(A\) ,则可能存在第三个元素 \(q\) 在里面 \(A\) 这样的话 \(a = bq\) . 事实上,可能存在几个这样的因素。
如果还有 \(a = bq'\) 对某些人来说 \(q'\) 在里面 \(A\) 然后 \(b(q - q') = 0\) . 因此 \(b\) 或 \(q - q'\) 是零,或者两者都是 零除数 ,其乘积为零的非零元素。
积分域#
没有零因子的交换环称为 积分域 . 大多数常见的环、整数环、域环和整域上的多项式环都是积分域。
现在假设 \(A\) 是一个积分域,并且考虑集合 \(P\) 在乘法下闭合的非零元素。如果 \(a\) 和 \(b\) 在 \(P\) ,并且存在一个元素 \(q\) 在里面 \(P\) 这样的话 \(a = bq\) 然后 \(q\) 是唯一的,叫做 商 , \(a/b\) 的 \(a\) 通过 \(b\) . 而且,据说
\(a\) 是 可除尽的 通过 \(b\) ,
\(b\) 是一个 除数 属于 \(a\) ,
\(a\) 是一个 倍数 属于 \(b\) ,
\(b\) 是一个 因素 属于 \(a\) .
元素 \(a\) 属于 \(P\) 是的除数 \(1\) 如果且仅当它是 可逆的 在里面 \(A\) ,反之亦然 \(a^{{-1}} = 1/a\) . 这些元素被称为 单位 . 整数环的单位是 \(1\) 和 \(-1\) . 域上多项式环中的可逆元素是非零常数多项式。
如果两个元素 \(P\) , \(a\) 和 \(b\) ,可被彼此整除,则商 \(a/b\) 与逆是可逆的 \(b/a\) ,或等效, \(b = ua\) 在哪里? \(u\) 是一个单位。据说这些元素是 相关 与,或 联系 彼此的。整数的关联 \(n\) 是 \(n\) 和 \(-n\) . 在域上的多项式环中,多项式的关联是它的常数倍数。
每个元素 \(P\) 可以被它的同伙和单位瓜分。元素是 不可约 如果它没有其他除数并且不是一个单位。整数环中的不可约元素是素数 \(p\) 以及它们的对立面 \(-p\) . 在一个域中,每个非零元素都是可逆的,并且没有不可约的元素。
阶乘域#
在整数环中,每个非零元素都可以表示为不可约元素的乘积,也可以是一个单位 \(\pm 1\) . 此外,任何两个这样的乘积具有相同数量的不可约因子,它们以适当的顺序相互关联。具有此属性的整型域称为 因式分解 或 唯一因子分解域 . 除了整数环外,域上的所有多项式环都是阶乘的,因此在任何阶乘域上更一般的多项式环也是阶乘环。字段是普通的阶乘,因为只有单位。阶乘域的不可约元素通常称为 素数 .
一个整数族只有有限个公约数,其中最大的公约数可被所有公约数整除。更一般地说,给定一个非零元素族 \((a_i)\) 在积分域中,公约数 \(d\) 的元素称为 最大公约数 ,缩写 gcd ,如果它是所有公约数的倍数。一个最大公约数,如果存在的话,通常不是唯一的;它的所有关联都有相同的性质。它表示为 \(d = \gcd(a_1,\ldots,a_n)\) 如果没有混淆的危险。A 最小公倍数 或 lcm ,一个家庭的 \((a_i)\) 被类似地定义为公共倍数 \(m\) 除以所有公倍数。它表示为 \(m = \operatorname{{lcm}}(a_1,\dots,a_n)\) .
在阶乘域中,最大公约数总是存在的。至少在原则上,可以通过将族中的每个元素分解为素数幂和可选单位的乘积,并对每个素数取因子分解中出现的最小幂。这些素数幂的乘积就是最大公约数。最小公倍数可以从与每个素数的最大幂乘积相同的因式分解中获得。
欧几里德域#
计算最大公约数的实用算法可以在 欧几里德域 . 它们是可以赋予函数的积分域 \(w\) 为域的每个非零元素分配一个非负整数,并具有以下属性:
如果 \(a\) 和 \(b\) 不是零,有 \(q\) 和 \(r\) 满足 部门标识
\(a = qb + r\)
也就是说 \(r = 0\) 或 \(w(r) < w(b)\) .
域上的整数环和所有一元多项式环都是具有 \(w(a) = |a|\) RESP \(w(a) = \deg(a)\) .
整数的除法标识在Python中作为内置函数实现 divmod
也可以应用于SymPy整数:
>>> divmod(Integer(53), Integer(7))
(7, 4)
对于多项式,除法恒等式是由函数在symmy中给出的 div()
::
>>> f = 5*x**2 + 10*x + 3
>>> g = 2*x + 2
>>> q, r = div(f, g, domain='QQ')
>>> q
5*x 5
--- + -
2 2
>>> r
-2
>>> (q*g + r).expand()
2
5*x + 10*x + 3
除法恒等式可用于确定欧氏域中元素的可除性。如果 \(r = 0\) 在部门的身份,那么 \(a\) 可分为 \(b\) . 相反,如果 \(a = cb\) 对于某些元素 \(c\) 然后 \((c - q)b = r\) . 因此 \(c = q\) 和 \(r = 0\) 如果 \(w\) 具有附加属性:
如果 \(a\) 和 \(b\) 那么不是零 \(w(ab) \ge w(b)\) .
上述函数可满足这一要求。(而且总是可以重新定义 \(w(a)\) 取最小值 \(w(xa)\) 对于 \(x \ne 0\) )
除法恒等式的主要应用是利用 Euclidean algorithm . 它适用于欧几里德域的两个元素。通过迭代可以得到多个元素的gcd。
在SymPy中计算整数的最大公约数的函数是 igcd()
::
>>> igcd(2, 4)
2
>>> igcd(5, 10, 15)
5
对于域上的一元多项式,函数有它的通用名 gcd()
,返回的多项式是monic::
>>> f = 4*x**2 - 1
>>> g = 8*x**3 + 1
>>> gcd(f, g, domain=QQ)
x + 1/2
多项式的可除性#
戒指 \(A = \mathbb{{Z}}[x]\) 整数环上的一元多项式不是欧几里德的,但它仍然是阶乘的。要了解这一点,请考虑 \(A\) .
让 \(f\) 和 \(g\) 是两个非零多项式 \(A\) .如果 \(f\) 可分为 \(g\) 在里面 \(A\) ,那么它在环中也是可分的 \(B = \mathbb{{Q}}[x]\) 具有有理系数的多项式。因为 \(B\) 是欧几里德的,这可以通过划分恒等式来确定。
相反地,假设 \(f = gh\) 对于某个多项式 \(h\) 在里面 \(B\) . 然后 \(f\) 可分为 \(g\) 在里面 \(A\) 当且仅当 \(h\) 是整数。要想知道什么时候是真的,有必要考虑系数的整除性。
对于多项式 \(f\) 在里面 \(A\) ,让 \(c\) 是其系数的最大公约数。那么 \(f\) 可被常数多项式整除 \(c\) 在里面 \(A\) ,以及商 \(f/c= p\) 除了一个多项式的系数之外,它的系数是没有公约数的。这种多项式叫做 原始的 . 有理系数多项式也可以写成 \(f = cp\) 在哪里 \(c\) 是一个有理数,并且 \(p\) 是一个本原多项式。常数 \(c\) 被称为 内容 属于 \(f\) 和 \(p\) 是吗? 原始部分 . 这些成分可以通过该方法找到 sympy.core.expr.Expr.as_content_primitive
::
>>> f = 6*x**2 - 3*x + 9
>>> c, p = f.as_content_primitive()
>>> c, p
2
(3, 2*x - x + 3)
>>> f = x**2/3 - x/2 + 1
>>> c, p = f.as_content_primitive()
>>> c, p
2
(1/6, 2*x - 3*x + 6)
让 \(f\), \(f'\) be polynomials with contents \(c\), \(c'\) and primitive parts \(p\), \(p'\). Then \(ff' = (cc')(pp')\) where the product \(pp'\) is primitive by Gauss's lemma . 因此
多项式乘积的内容是其内容的乘积,乘积的原始部分是原始部分的乘积。
回到环中的可除性 \(\mathbb{{Z}}[x]\) ,假设 \(f\) 和 \(g\) 是两个整系数多项式,其除法恒等式 \(\mathbb{{Q}}[x]\) 产生相等 \(f = gh\) 对于某个多项式 \(h\) 有理性的系数。那么 \(f\) 等于 \(g\) 乘以 \(h\) . AS \(h\) 具有整数系数当且仅当其内容为整数时,我们得到以下条件:
\(f\) 可分为 \(g\) 在拳击场上 \(\mathbb{{Z}}[x]\) 当且仅当
\(f\) 可分为 \(g\) 在里面 \(\mathbb{{Q}}[x]\) 和
内容 \(f\) 可被…的内容整除 \(g\) 在里面 \(\mathbb{{Z}}\) .
如果 \(f = cp\) 在 \(\mathbb{{Z}}[x]\) ,或者 \(c\) 或 \(p\) 必须是一个单位。如果 \(p\) 不是一个单位,它必须是不可约的也在 \(\mathbb{{Q}}[x]\) . 因为如果它是两个多项式的乘积,那么它也是它们的原始部分的乘积,其中一个必须是一个单位。因此有两种不可约元素 \(\mathbb{{Z}}[x]\) :
质数 \(\mathbb{{Z}}\) 和
不可约的本原多项式 \(\mathbb{{Q}}[x]\) .
因此每个多项式 \(\mathbb{{Z}}[x]\) 是不可约元素的产物。它只需将其内容和原始部分分开考虑。这些产品本质上是独一无二的;因此 \(\mathbb{{Z}}[x]\) 也是阶乘的。
另一个重要的结果是 \(\mathbb{{Z}}[x]\) 将欧几里德算法分别应用于欧几里德域中的内容和原始部分,可以有效地找到它们 \(\mathbb{{Z}}\) 和 \(\mathbb{{Q}}[x]\) . 这也在SymPy中实现:
>>> f = 4*x**2 - 1
>>> g = 8*x**3 + 1
>>> gcd(f, g)
2*x + 1
>>> gcd(6*f, 3*g)
6*x + 3
基本功能#
这些函数提供了处理多项式的不同算法,如符号、和等。
除法#
The function div()
provides division of polynomials with remainder. That
is, for polynomials f
and g
, it computes q
and r
, such that \(f =
g \cdot q + r\) and \(\deg(r) < \deg(q)\). For polynomials in one variables with
coefficients in a field, say, the rational numbers, q
and r
are uniquely
defined this way:
>>> f = 5*x**2 + 10*x + 3
>>> g = 2*x + 2
>>> q, r = div(f, g, domain='QQ')
>>> q
5*x 5
--- + -
2 2
>>> r
-2
>>> (q*g + r).expand()
2
5*x + 10*x + 3
正如你所看到的, q
具有非整数系数。如果只想在整系数多项式环中进行除法,可以指定一个附加参数:
>>> q, r = div(f, g, domain='ZZ')
>>> q
0
>>> r
2
5*x + 10*x + 3
但要注意的是,这个环不再是欧几里德环,余数的阶数不必小于 f
. 因为2不能除以5, \(2 x\) 不会分裂 \(5 x^2\) ,即使度数较小。但是:
>>> g = 5*x + 1
>>> q, r = div(f, g, domain='ZZ')
>>> q
x
>>> r
9*x + 3
>>> (q*g + r).expand()
2
5*x + 10*x + 3
这也适用于具有多个变量的多项式:
>>> f = x*y + y*z
>>> g = 3*x + 3*z
>>> q, r = div(f, g, domain='QQ')
>>> q
y
-
3
>>> r
0
在最后的例子中,所有三个变量 x
, y
和 z
假设是多项式的变量。但是如果有一些不相关的常数作为系数,可以显式地指定变量:
>>> a, b, c = symbols('a,b,c')
>>> f = a*x**2 + b*x + c
>>> g = 3*x + 2
>>> q, r = div(f, g, domain='QQ')
>>> q
a*x 2*a b
--- - --- + -
3 9 3
>>> r
4*a 2*b
--- - --- + c
9 3
GCD和LCM#
除法还需要计算最大公约数和最小公倍数。
当多项式具有整系数时,还考虑内容的gcd::
>>> f = (12*x + 12)*x
>>> g = 16*x**2
>>> gcd(f, g)
4*x
但是如果多项式有有理系数,那么返回的多项式是monic::
>>> f = 3*x**2/2
>>> g = 9*x/4
>>> gcd(f, g)
x
它也适用于多个变量。在这种情况下,变量是按字母顺序排列的,默认情况下,这会影响前导系数:
>>> f = x*y/2 + y**2
>>> g = 3*x + 6*y
>>> gcd(f, g)
x + 2*y
lcm与gcd相连,其中一个可以使用另一个进行计算:
>>> f = x*y**2 + x**2*y
>>> g = x**2*y**2
>>> gcd(f, g)
x*y
>>> lcm(f, g)
3 2 2 3
x *y + x *y
>>> (f*g).expand()
4 3 3 4
x *y + x *y
>>> (gcd(f, g, x, y)*lcm(f, g, x, y)).expand()
4 3 3 4
x *y + x *y
无平方因式分解#
一元多项式的无平方因式分解是1次、2次等所有因子(不一定不可约)的乘积:
>>> f = 2*x**2 + 5*x**3 + 4*x**4 + x**5
>>> sqf_list(f)
2
(1, [(x + 2, 1), (x + x, 2)])
>>> sqf(f)
2
/ 2 \
(x + 2)*\x + x/
因式分解#
此函数提供有理系数的一元多项式和多元多项式的因式分解:
>>> factor(x**4/2 + 5*x**3/12 - x**2/3)
2
x *(2*x - 1)*(3*x + 4)
----------------------
12
>>> factor(x**2 + 4*x*y + 4*y**2)
2
(x + 2*y)
格罗伯纳基地#
实现了Buchberger算法,支持各种单项式:
>>> groebner([x**2 + 1, y**4*x + x**3], x, y, order='lex')
/[ 2 4 ] \
GroebnerBasis\[x + 1, y - 1], x, y, domain=ZZ, order=lex/
>>> groebner([x**2 + 1, y**4*x + x**3, x*y*z**3], x, y, z, order='grevlex')
/[ 4 3 2 ] \
GroebnerBasis\[y - 1, z , x + 1], x, y, z, domain=ZZ, order=grevlex/
解方程#
我们有(不完全的)方法来求多项式的复根甚至符号根,以及解一些多项式方程组:
>>> from sympy import roots, solve_poly_system
>>> solve(x**3 + 2*x + 3, x)
____ ____
1 \/ 11 *I 1 \/ 11 *I
[-1, - - --------, - + --------]
2 2 2 2
>>> p = Symbol('p')
>>> q = Symbol('q')
>>> solve(x**2 + p*x + q, x)
__________ __________
/ 2 / 2
p \/ p - 4*q p \/ p - 4*q
[- - - -------------, - - + -------------]
2 2 2 2
>>> solve_poly_system([y - x, x - 5], x, y)
[(5, 5)]
>>> solve_poly_system([y**2 - x**3 + 1, y*x], x, y)
___ ___
1 \/ 3 *I 1 \/ 3 *I
[(0, -I), (0, I), (1, 0), (- - - -------, 0), (- - + -------, 0)]
2 2 2 2