ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SymPy 多项式模块基础功能完全指南:从多项式环理论到 div、gcd、factor 的实战用法

2026/9/15 15:22:39 拓冰建站 浏览量
SymPy 多项式模块基础功能完全指南:从多项式环理论到 div、gcd、factor 的实战用法 SymPy 多项式模块基础功能完全指南从多项式环理论到 div、gcd、factor 的实战用法【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympySymPy 的sympy.polys模块提供了覆盖多项式代数运算的完整工具链本文以官方教程 doc/src/modules/polys/basics.rst 为主体骨架系统讲解多项式表达式→多项式的转换规则、系数域domain与扩域extension机制以及除法、GCD/LCM、平方自由分解、因式分解、Gröbner 基与方程求解等核心函数的调用方法与底层原理。读完本文你将能准确判断某个表达式能否被当作多项式处理并能熟练使用div、gcd、lcm、sqf_list、factor、groebner、solve_poly_system等函数解决实际计算问题。引言与准备工作本教程讨论 SymPy 中与多项式相关的全部基础功能。运行所有代码示例前请先建立如下环境 from sympy import * x, y, z symbols(x,y,z) init_printing(use_unicodeFalse)init_printing(use_unicodeFalse)使用纯 ASCII 风格打印输出保证不同终端下显示一致。所有示例默认使用符号x、y、z作为变量读者可直接在 IPython、Jupyter Notebook 或 Python 交互式环境中复现。基本概念什么是 SymPy 中的多项式多项式、单项式与项给定一族符号(x_i)或其他合适的对象包括数字由它们经过有限次加法、减法、乘法得到的表达式称为关于生成元x_i的多项式表达式polynomial expression。根据分配律可以把乘法先于加减法执行这样得到的生成元乘积称为单项式monomial通常写成x_1^ν1 · x_2^ν2 ⋯ x_n^νn的形式其中指数ν_i是非负整数。也可以简写为x^ν其中x (x1, x2, …, xn)是生成元族ν (ν1, ν2, …, νn)是指数族。把所有指数相同的单项式合并后多项式表达式就成为各项c_ν x^ν之和这些项称为多项式的项term系数c_ν默认是整数。如果某些x_i本身就是显式数字它们会被吸收进系数而不是作为生成元这类系数通常是有理数、实数或复数。而像pi这样的符号数既可以是系数也可以是生成元取决于使用方式。一个由不同单项式求和而成的多项式表达式由其系数族(c_ν)唯一确定。SymPy 默认用以单项式为键、系数为值的字典来实现多项式另一种实现方式是用系数的嵌套列表。多项式环与系数域domain所有在生成元x_i上取整系数的多项式全体构成一个环ring环中元素的和、差、积仍然是同一组生成元上的多项式。这个环记作ℤ[x1, x2, …, xn]称为关于x_i的整系数多项式环。更一般地多项式的系数可以取自任意交换环A相应的多项式环记作A[x1, x2, …, xn]A本身也可以是多项式环。在 SymPy 中系数环被称为多项式环的domain系数域可以作为关键字参数传入默认情况下它由多项式参数的系数自动决定。用 as_poly 将表达式转换为多项式多项式表达式可以通过 Expr.as_poly 方法转换为Poly对象 e (x y)*(y - 2*z) e.as_poly() Poly(x*y - 2*x*z y**2 - 2*y*z, x, y, z, domainZZ)domainZZ表示系数域是整数环。如果表达式中含有非整数数字它们会被视为系数系数环随之扩展。特别是除以整数会产生有理系数 e (3*x/2 y)*(z - 1) e.as_poly() Poly(3/2*x*z - 3/2*x y*z - y, x, y, z, domainQQ)domainQQ表示系数域扩展为有理数域。符号数的处理规则符号数默认被视为生成元除非显式排除否则它们会被并入系数环 e (x 2*pi)*y e.as_poly() Poly(x*y 2*y*pi, x, y, pi, domainZZ) e.as_poly(x, y) Poly(x*y 2*pi*y, x, y, domainZZ[pi])第二种写法显式指定生成元只有x、y于是pi被并入系数环得到ZZ[pi]——即系数取自ℤ[π]。也可以用关键字参数domain直接指定系数域 e (x 2*pi)*y e.as_poly(domainZZ[pi]) Poly(x*y 2*pi*y, x, y, domainZZ[pi])注意环ℤ[π][x, y]与ℤ[π, x, y]在数学上等价区别只在于实现方式。函数作为新生成元与负幂陷阱如果表达式中含有生成元的函数而非其正整数幂这些函数会被解释为新的生成元 e x*sin(y) - y e.as_poly() Poly(x*(sin(y)) - y, x, y, sin(y), domainZZ)因为y与sin(y)代数独立它们可以同时作为生成元出现在多项式中。但多项式表达式绝不能包含生成元的负幂。下面这个例子虽然不报错结果却很危险 e x - 1/x e.as_poly() Poly(x - (1/x), x, 1/x, domainZZ)x与1/x x⁻¹被当作代数独立的变量对待尤其要注意它们的乘积不等于 1。因此应尽量避免在分母中出现生成元——即使当前实现不报错这种行为也是不受欢迎的未来版本可能改变。生成元的有理数幂也有类似问题例如x与√x x^(1/2)不会被识别为代数相关。extension 扩域正确处理代数数当表达式中含有代数数时可以通过设置关键字extension把它们并入系数环 e x sqrt(2) e.as_poly() Poly(x (sqrt(2)), x, sqrt(2), domainZZ) e.as_poly(extensionTrue) Poly(x sqrt(2), x, domainQQsqrt(2))默认设置extensionFalse时x与√2都会被错误地当作代数独立的变量而把系数放在扩域ℚ(√2)中平方根才会被正确地当作代数数处理。只要表达式中涉及代数数就强烈建议设置extensionTrue虽然当前实现并不强制。可整除性环论基础四则运算中的第四种运算——除法即乘法的逆运算在环中并不总能执行。若a、b是环A中的两个元素可能存在元素q使得a bq甚至可能存在多个。若同时a bq则b(q − q) 0于是b或q − q中至少一个为零或者它们都是零因子zero divisor乘积为零的非零元素。整环Integral domains没有零因子的交换环称为整环。常见的整数环、域以及整环上的多项式环都是整环。设A是整环考虑其非零元素集合P对乘法封闭。若a、b ∈ P且存在q ∈ P使a bq则q唯一称为a除以b的商a/b并且称a被b整除b是a的因子divisora是b的倍数multipleb是a的因数factor。P中的元素a是1的因子当且仅当它在A中可逆即存在逆元a⁻¹ 1/a。这样的元素称为单位unit。整数环的单位是1和-1域上多项式环中的可逆元素是非零常数多项式。若a、b互相整除则商a/b可逆等价地说b uau是单位这样的两个元素称为相伴associated。整数n的相伴元是n与-n域上多项式环中多项式的相伴元是其常数倍。P中每个元素都能被它的相伴元和单位整除。一个元素是不可约的irreducible当且仅当它没有其他因子且不是单位。整数环中的不可约元素是素数p及其相反数-p在域中每个非零元素都可逆因此不存在不可约元素。阶乘域Factorial domains整数环中每个非零元素都可表示为不可约元素与可选单位±1的乘积且任意两个这样的乘积含有相同数量的、按适当顺序相伴的不可约因子。具有此性质的整环称为阶乘域或唯一分解整环UFD。域上的一切多项式环都是阶乘域更一般地任何阶乘域上的多项式环也是阶乘域。域平凡地是阶乘域因为只有单位。阶乘域中的不可约元素通常称为素数。一族整数只有有限个公因子其中最大的一个能被所有公因子整除。更一般地整环中一族非零元素(a_i)的公因子d若能被所有公因子整除就称为该族的最大公因子gcd。gcd 若存在一般不唯一其所有相伴元都具有同样性质无歧义时记为d gcd(a1, …, an)。最小公倍数lcm类似地定义为能整除所有公倍数的公倍数m记为m lcm(a1, …, an)。在阶乘域中 gcd 总是存在原则上可把每个元素分解为素数次幂与可选单位的乘积对每个素数取各分解中出现的最小次幂其乘积即最大公因子lcm 则取各素数出现的最大次幂之积。欧几里得整环Euclidean domains计算 gcd 的实用算法可以在欧几里得整环中实现。它们是可配备函数w的整环w给每个非零元素赋一个非负整数且满足如下带余除法恒等式性质若a、b非零则存在q、r满足a qb r且r 0或w(r) w(b)。整数环和域上的一切一元多项式环都是欧几里得整环其w分别取绝对值w(a) |a|和次数w(a) deg(a)。Python 内建函数divmod实现了整数的带余除法也可用于 SymPy 的Integer divmod(Integer(53), Integer(7)) (7, 4)对多项式SymPy 提供函数div f 5*x**2 10*x 3 g 2*x 2 q, r div(f, g, domainQQ) 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 − q)b r可推出c q、r 0前提是w还满足附加性质若a、b非零则w(ab) ≥ w(b)。上面给出的两个w函数都满足该性质。并且总可以通过取x ≠ 0时w(xa)的最小值来重新定义w(a)。带余除法最主要的应用是借助欧几里得算法高效计算最大公因子它作用于欧几里得整环中的两个元素多个元素的 gcd 可通过迭代得到。SymPy 中计算整数 gcd 的函数目前是igcd定义于 sympy/core/intfunc.py底层基于欧几里得算法并自带缓存机制 igcd(2, 4) 2 igcd(5, 10, 15) 5对域上的一元多项式函数使用其常用名gcd返回的多项式是首一的monic f 4*x**2 - 1 g 8*x**3 1 gcd(f, g, domainQQ) x 1/2多项式的整除性ℤ[x] 中的判定整系数一元多项式环A ℤ[x]不是欧几里得整环但它仍然是阶乘域。设f、g是A中两个非零多项式若f在A中被g整除则它在有理系数多项式环B ℚ[x]中也被整除B是欧几里得整环可用带余除法判定。反过来若f gh对B中某个h成立则f在A中被g整除当且仅当h的系数全为整数——这需要考察系数的整除性。对A中多项式f设c是其系数的最大公因子则f在A中被常数多项式c整除商f/c p是系数没有非单位公因子的整系数多项式称为本原多项式primitive。有理系数多项式也可以写成f cp其中c是有理数、p本原c称为f的内容contentp称为其本原部分。这两个分量可用 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的内容和本原部分分别为c、c与p、p则ff (cc)(pp)且由高斯引理可知乘积pp仍本原于是有多项式乘积的内容等于各多项式内容的乘积乘积的本原部分等于各本原部分的乘积。回到ℤ[x]中的整除性假设f、g为整系数多项式且在ℚ[x]中的带余除法给出f ghh为有理系数多项式。由于f的内容等于g的内容乘以h的内容而h的系数全为整数当且仅当其内容为整数得到判定准则f在环ℤ[x]中被g整除当且仅当f在ℚ[x]中被g整除f的内容在ℤ中被g的内容整除。若f cp在ℤ[x]中不可约则c或p必为单位。若p不是单位则它在ℚ[x]中也必须不可约否则它可分解为两个多项式的乘积也就是它们本原部分的乘积其中必有一个为单位。因此ℤ[x]中的不可约元素有两类ℤ中的素数在ℚ[x]中不可约的本原多项式。由此可知ℤ[x]中每个多项式都是不可约元素的乘积——只需分别分解其内容和本原部分且乘积本质上唯一故ℤ[x]也是阶乘域。另一个重要推论是ℤ[x]中两个多项式的最大公因子可以高效地通过在两个欧几里得整环ℤ与ℚ[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注意这里默认domainZZ未显式指定因此 gcd 会考虑整数内容返回2*x 1与6*x 3而非首一形式。基本功能面向表达式的多项式运算下面这些函数为以 SymPy 表达式符号、和式等形式存在的多项式提供不同算法全部定义在 sympy/polys/polytools.py 中属于sympy.polys模块面向用户的公开 API。除法Division函数div提供带余多项式除法对多项式f、g计算q、r使f g·q r且deg(r) deg(q)。对系数在域如有理数域中的一元多项式q、r由此唯一确定 f 5*x**2 10*x 3 g 2*x 2 q, r div(f, g, domainQQ) q 5*x 5 --- - 2 2 r -2 (q*g r).expand() 2 5*x 10*x 3可以看到q含有非整数系数。如果只想在整系数多项式环中做除法可以指定额外的参数 q, r div(f, g, domainZZ) q 0 r 2 5*x 10*x 3但要小心ℤ[x]不再是欧几里得整环余数的次数不必小于f的次数。因为 2 不整除 52x不能整除5x²即使次数更小。但 g 5*x 1 q, r div(f, g, domainZZ) 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, domainQQ) 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, domainQQ) q a*x 2*a b --- - --- - 3 9 3 r 4*a 2*b --- - --- c 9 3从源码看div首先调用parallel_poly_from_expr把表达式转化为Poly对象然后调用F.div(G, autoopt.auto)完成除法sympy/polys/polytools.py。底层稠密表示的一元/多元除法实现在 sympy/polys/densearith.pydup_div/dmp_div系列并根据系数域选择伪除法pdiv、整环除法rr_div或域除法ff_div。相关的rem、quo、exquo函数分别返回余数、商和精确商签名一致。GCD 与 LCM有了除法就可以计算最大公因子与最小公倍数。当多项式是整系数时还会考虑内容content的 gcd f (12*x 12)*x g 16*x**2 gcd(f, g) 4*x而当多项式是有理系数时返回的多项式是首一的 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*ylcm 与 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从源码看gcd/lcm支持传入一个可迭代序列的用法自动转调gcd_list/lcm_list并会在系数为代数无理数时尝试ratsimp化简sympy/polys/polytools.py、sympy/polys/polytools.py。底层 gcd 算法位于 sympy/polys/euclidtools.pydup_gcd/dmp_gcd等其中整数系数使用启发式heugcdsympy/polys/heuristicgcd.py另有基于模运算的modgcdsympy/polys/modulargcd.py和稀疏表示下的 Zippel 算法sympy/polys/zippel.py可供不同场景选用。平方自由分解Square-free factorization一元多项式的平方自由分解是其所有 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/sqf_list返回(系数, [(因子, 重数), …])结构sqf直接返回分解后的表达式。底层实现见 sympy/polys/sqfreetools.pydup_sqf_list/dmp_sqf_list等模素数域上另有gf_sqf_list系列。因式分解Factorizationfactor提供一元与多元有理系数多项式的因式分解 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)factor的完整签名还支持deepTrue对复合表达式递归尝试因式分解以及返回(系数, [(因子, 重数), …])结构的factor_list。底层整系数分解算法实现在 sympy/polys/factortools.py其中 Zassenhaus 算法dup_zz_zassenhaus、Wang 的多元 Hensel 提升dmp_zz_wang、Mignotte 系数界dup_zz_mignotte_bound、本原性检验dup_zz_irreducible_p等构成完整的分解工具链算法选择可通过 sympy/polys/polyconfig.py 的配置项如USE_IRREDUCIBLE_IN_FACTOR、USE_CYCLOTOMIC_FACTOR调整。Gröbner 基SymPy 实现了 Buchberger 算法支持多种单项式序monomial order groebner([x**2 1, y**4*x x**3], x, y, orderlex) /[ 2 4 ] \ GroebnerBasis\[x 1, y - 1], x, y, domainZZ, orderlex/ groebner([x**2 1, y**4*x x**3, x*y*z**3], x, y, z, ordergrevlex) /[ 4 3 2 ] \ GroebnerBasis\[y - 1, z , x 1], x, y, z, domainZZ, ordergrevlex/从 sympy/polys/polytools.py 的 docstring 可知允许的order取值为lex字典序、grlex分次字典序、grevlex分次反字典序默认lex默认使用改进版 Buchberger 算法也可以通过methodf5b切换为 F5B 算法或使用sympy.polys.polyconfig.setup全局配置返回的GroebnerBasis对象还提供reduce、contains、fglm变换序、is_zero_dimensional等方法。底层实现位于 sympy/polys/groebnertools.py经典 Buchberger_buchberger、spoly、s_poly、F5B_f5b、f5_reduce、归约reduction、red_groebner、最小化与判定is_minimal、is_reduced、is_groebner等稀疏分布式模块运算见 sympy/polys/distributedmodules.py。求解方程Solving EquationsSymPy 提供尚不完备的求多项式复数根甚至符号根的方法以及求解部分多项式方程组的能力 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说明solve对多项式的符号求根依赖rootssympy/polys/polyroots.py其签名支持cubics、quartics、quintics、trig、auto等开关默认对三次、四次方程求根quinticsFalse表示默认不求一般五次方程的根式解由 Abel–Ruffini 定理一般五次以上方程无根式通解。底层针对线性、二次、三次roots_cubic、四次roots_quartic、二项式roots_binomial、分圆roots_cyclotomic等情形分派专用算法。solve_poly_systemsympy/solvers/polysys.py求解多项式方程组先把方程组通过parallel_poly_from_expr转化为Poly对两个未知数、各自次数不超过 2的特殊情形调用solve_biquadratic否则走通用的solve_generic基于 Gröbner 基strictTrue时若已知解集不完整例如并非所有解都能用根式表达会抛出UnsolvableFactorError。进一步阅读多项式环与系数域的完整 API 参考doc/src/modules/polys/reference.rst系数域domain概念详解doc/src/modules/polys/domainsintro.rst多项式环与分式域的内部实现doc/src/modules/polys/internals.rst多项式求解器专题doc/src/modules/polys/solvers.rst多项式模块总览doc/src/modules/polys/index.rst结合 sympy/polys/polytools.py 中的公开函数与 sympy/polys/tests/test_polytools.py 中的测试用例如test_div、test_gcd、test_sqf、test_factor、test_groebner、test_real_roots等读者可以进一步验证上述行为并深入理解 SymPy 多项式子系统的实现细节。【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考