SymPy-1-13-中文文档-十-
SymPy 1.13 中文文档(十)
Solveset
这是solvers
中solveset
模块的官方文档。它包含关于我们解方程新模块的常见问题。
注意
想要一个适合初学者的指南,专注于解决常见类型的方程,请参阅 Solve Equations。
solve()
有什么问题:
SymPy 已经有一个相当强大的 solve
函数。但是它有一些缺陷。例如:
-
它没有一致的输出类型来处理各种类型的解决方案。它需要始终返回很多类型的解决方案:
-
单一解:(x = 1)
-
多解方程:(x² = 1)
-
无解:(x² + 1 = 0 ; x \in \mathbb{R})
-
解的区间:(\lfloor x \rfloor = 0)
-
无限多解:(\sin(x) = 0)
-
多元函数有点解:(x² + y² = 0)
-
多元函数有非点解:(x² + y² = 1)
-
方程组:(x + y = 1) 和 (x - y = 0)
-
关系表达式:(x > 0)
-
而且最重要的案例是:“我们不知道”
-
-
输入 API 有很多参数,使用起来可能会有困难。
-
有时候在使用临界点找出函数的极大值和极小值时,知道它是否返回了所有的解决方案是很重要的。
solve
不能保证这一点。
为什么要使用 Solveset?
-
solveset
有一个备选的一致的输入和输出接口:solveset
返回一个集合对象,而集合对象负责处理所有类型的输出。对于它不“知道”所有解决方案的情况,会返回一个具有部分解决方案的ConditionSet
。对于输入,它只接受方程、要解的变量和可选的参数domain
,这个参数表示解方程的定义域。 -
solveset
可以返回无限多个解。例如,求解 (\sin{(x)} = 0) 会返回 ({2 n \pi | n \in \mathbb{Z}} \cup {2 n \pi + \pi | n \in \mathbb{Z}}),而solve
只返回区间 ([0, \pi])。 -
在复数域和实数域中,对方程求解器在代码级别和接口级别上有明确的分离。例如,在复数域中解 (e^x = 1),返回所有解的集合,即 ({2 n i \pi | n \in \mathbb{Z}}),而在实数域中,仅返回 ({0})。
为什么我们要将集合作为输出类型使用?
SymPy 有一个完善的集合模块,可以表示数学中大多数集合容器,比如:
FiniteSet
表示离散数字的有限集。
Interval
表示实数区间作为一个集合。
ProductSet
表示集合的笛卡尔积。
ImageSet
表示数学函数下的集合的像
>>> from sympy import ImageSet, S, Lambda >>> from sympy.abc import x >>> squares = ImageSet(Lambda(x, x**2), S.Naturals) # {x**2 for x in N} >>> 4 in squares True
ComplexRegion
表示在阿格朗平面的区域中所有复数的集合。
ConditionSet
表示满足给定条件的元素集合。
此外,还有预定义的集合类,如:
Naturals
, (\mathbb{N})表示自然数(或计数数),即从 1 开始的所有正整数。
Naturals0
, (\mathbb{N_0})表示整数,即所有非负整数,包括 0。
Integers
, (\mathbb{Z})表示所有整数:正数、负数和零。
Reals
, (\mathbb{R})表示所有实数的集合。
Complexes
, (\mathbb{C})表示所有复数的集合。
EmptySet
, (\emptyset)表示空集。
上述六个集合都可以作为单例集合,如
S.Integers
。
它能够执行大多数数学中的集合运算:
Union
Intersection
Complement
SymmetricDifference
使用集合作为解算器的输出的主要原因是它可以一致地表示许多类型的解。对于单变量情况,它可以表示:
- 无解(由空集)。
- 有限多的解(通过
FiniteSet
)。- 无限多的解,包括可数和不可数的无限多解(使用
ImageSet
模块)。Interval
- 方程的解集也可能是奇怪的,如有理数的集合。
没有其他 Python 对象(列表、字典、生成器、Python 集合)能够提供我们集合模块试图模拟的数学集的灵活性。使用集合的第二个原因是它们接近数学家处理的实体,这样更容易对它们进行推理。当可能时,集合对象遵循 Pythonic 约定,即 x in A
和 for i in A
都在可以计算时起作用。使用更接近数学实体的对象的另一个优势是用户不必“学习”我们的表示,她可以从她的数学经验中传递她的期望。
对于多变量情况,我们将解表示为 n 维空间中的一组点集,点由有序元组的 FiniteSet
表示,这是 (\mathbb{R}^n) 或 (\mathbb{C}^n) 中的点。
请注意,一般的 FiniteSet
是无序的,但带有元组作为其唯一参数的 FiniteSet
是有序的,因为元组是有序的。因此,元组中的顺序被映射到变量的预定义顺序,而返回解决方案。
例如:
>>> from sympy import FiniteSet
>>> FiniteSet(1, 2, 3) # Unordered
{1, 2, 3}
>>> FiniteSet((1, 2, 3)) # Ordered
{(1, 2, 3)}
为什么不使用字典作为输出?
在程序上处理字典很容易,但在数学上它们并不是非常精确的,使用它们很快会导致不一致和混乱。例如:
存在许多情况我们不知道完整的解决方案,我们可能希望输出一个部分解决方案,考虑方程 (fg = 0)。这个方程的解是以下两个方程的解的并集:(f = 0),(g = 0)。假设我们能解决 (f = 0),但尚不支持解决 (g = 0)。在这种情况下,我们不能使用字典表示给定方程 (fg = 0) 的部分解决方案。使用
ConditionSet
对象解决了这个问题。(\left{sol_f \cup {x | x ∊ \mathbb{R} ∧ g = 0}\right}),其中 (\left{sol_f\right}) 是方程 (f = 0) 的解。
使用字典可能会导致意外的结果,比如:
solve(Eq(x**2, 1), x) != solve(Eq(y**2, 1), y)
- 在数学上,这是没有意义的。在这里使用
FiniteSet
解决了这个问题。它也不能表示像 (|x| < 1) 这样的方程的解,这在阿尔干平面中是半径为 1 的圆盘。使用
ComplexRegion
实现解决了这个问题。
solveset
的输入 API
solveset
具有更简单的输入 API,不像 solve
。它最多接受三个参数:
solveset(equation, variable=None, domain=S.Complexes)
方程
要解决的方程。
变量
要解决的方程的变量。
域
方程的解决域。
solveset
移除了 solve
的 flags
参数,这使得输入 API 更加复杂且输出 API 不一致。
这个域参数是什么?
Solveset 设计为与被解决的变量的假设无关,而是使用 domain
参数来决定分派给解算器的方程,即 solveset_real
或 solveset_complex
。这与旧的 solve
不同,后者考虑变量的假设。
>>> from sympy import solveset, S
>>> from sympy.abc import x
>>> solveset(x**2 + 1, x) # domain=S.Complexes is default
{-I, I}
>>> solveset(x**2 + 1, x, domain=S.Reals)
EmptySet
解方程所采用的一般方法是什么?
Solveset 使用各种方法来解决方程,以下是方法论的简要概述:
- 首先考虑
domain
参数,以确定用户感兴趣的解决方案的域。- 如果给定函数是一个关系式 (
>=
,<=
,>
,<
),且域为实数,则使用solve_univariate_inequality
并返回解。目前尚不支持解决复数不等式的复数解,例如 (x² < 0)。- 基于
domain
,方程被分派到solveset_real
或solveset_complex
中的一个函数来解决,分别在复数域或实数域中解决给定的方程。- 如果给定表达式是两个或更多函数的乘积,比如说 (gh = 0),那么给定方程的解是方程 (g = 0) 和 (h = 0) 的并集,当且仅当 (g) 和 (h) 都对有限输入有限时。因此,解是递归构建的。
- 如果函数是三角函数或双曲函数,则调用函数
_solve_real_trig
,通过将其转换为复数指数形式来解决它。- 现在检查函数是否存在
Piecewise
表达式的任何实例,如果有,则将其转换为显式表达式和设置对,并进行递归求解。- 相应的求解器现在尝试使用例程
invert_real
和invert_complex
反转方程。这些例程基于数学反函数的概念(虽然不完全相同)。它将实数/复数值方程 (f(x) = y) 简化为一组方程:({g(x) = h_1(y), g(x) = h_2(y), ..., g(x) = h_n(y) }),其中 (g(x)) 比 (f(x)) 更简单。这需要一些工作来查找更复杂表达式的反函数。- 在反转之后,方程检查是否有根式或绝对值(模)部分,然后方法
_solve_radical
尝试通过诸如平方、立方等技术简化根式,并且_solve_abs
迭代地解决嵌套的绝对值。- 如果上述方法都不成功,则使用多项式的方法如下:
- 解决有理函数的方法
_solve_as_rational
被调用。根据定义域,分别调用相应的多项式求解器_solve_as_poly_real
或_solve_as_poly_complex
来将f
作为多项式求解。- 底层方法
_solve_as_poly
使用多项式技术解方程,如果它已经是多项式方程或者可以通过变量变换变成多项式方程。solveset
返回的最终解集是上述解集和输入定义域的交集。
如何操作并返回无限解?
在实数域中,我们使用集合模块中的
ImageSet
类返回无限解。ImageSet
是数学函数下的一个集合的图像。例如,要表示方程 (\sin{(x)} = 0) 的解,我们可以使用ImageSet
如下:>>> from sympy import ImageSet, Lambda, pi, S, Dummy, pprint >>> n = Dummy('n') >>> pprint(ImageSet(Lambda(n, 2*pi*n), S.Integers), use_unicode=True) {2⋅n⋅π │ n ∊ ℤ}
这里
n
是一个虚拟变量。基本上是整数集合在函数 (2\pi n) 下的图像。在复数域中,我们使用复数集合,它们在集合模块中实现为
ComplexRegion
类,用来表示阿格朗平面中的无限解。例如,要表示方程 (|z| = 1) 的解,即单位圆,我们可以使用ComplexRegion
如下:>>> from sympy import ComplexRegion, FiniteSet, Interval, pi, pprint >>> pprint(ComplexRegion(FiniteSet(1)*Interval(0, 2*pi), polar=True), use_unicode=True) {r⋅(ⅈ⋅sin(θ) + cos(θ)) │ r, θ ∊ {1} × 0, 2⋅π)}
FiniteSet
在ProductSet
中是 (r) 的值域,即圆的半径,而Interval
是 (\theta) 的范围,表示阿格朗平面中单位圆上的角度。注意:我们还有用于以直角坐标形式表示解的非极坐标形式符号。例如,在阿格朗平面的前两象限中表示
ComplexRegion
,我们可以写成:>>> from sympy import ComplexRegion, Interval, pi, oo, pprint >>> pprint(ComplexRegion(Interval(-oo, oo)*Interval(0, oo)), use_unicode=True) {x + y⋅ⅈ │ x, y ∊ (-∞, ∞) × [0, ∞)}
其中区间是复数集合 (x + iy) 的 (x) 和 (y) 的范围。
solveset
如何确保不返回任何错误的解?
计算代数系统中的求解器基于启发式算法,因此通常很难确保在每种可能情况下都能达到 100%的正确性。然而,在许多情况下,我们仍然可以确保正确性。
Solveset
尝试在可能的情况下验证正确性。例如:考虑方程 (|x| = n)。解这个方程的一个天真的方法会返回
{-n, n}
作为其解,这是不正确的,因为只有当n
是正数时,{-n, n}
才可能是其解。Solveset 也会返回这些信息以确保正确性。>>> from sympy import symbols, S, pprint, solveset >>> x, n = symbols('x, n') >>> pprint(solveset(abs(x) - n, x, domain=S.Reals), use_unicode=True) {x │ x ∊ {-n, n} ∧ (n ∈ [0, ∞))}
尽管在这方面仍需大量工作。
基于搜索的求解器和逐步解决方案
注意:这还在开发中。
引入 [
ConditionSet
后,解方程可以看作是集合转换。以下是我们可以用来解方程的抽象视图。
- 在给定集合上应用各种集合转换。
- 定义解的可用性度量,或者某些解比其他解更好的概念。
- 不同的转换可以是树的节点。
- 可以应用适当的搜索技术来获得最佳解决方案。
ConditionSet
给我们提供了以形如 ({x|f(x)=0; x \in S}) 和 ({x|f(x)>0; x \in S}) 的形式表示未评估的方程和不等式的能力,但ConditionSet
更强大的地方在于它允许我们将中间步骤写为集合到集合的转换。一些转换包括:
组合:({x|f(g(x))=0;x \in S} \Rightarrow {x|g(x)=y; x \in S, y \in {z|f(z)=0; z \in S}})
多项式求解器:({x | P(x) = 0;x \in S} \Rightarrow {x_1,x_2, ... ,x_n} \cap S),
其中 (x_i) 是 (P(x)) 的根。
反转求解器:({x|f(x)=0;x \in S} \Rightarrow {g(0)| \text{ 所有的 } g \text{ 使得 } f(g(x)) = x})
logcombine:({x| \log(f(x)) + \log(g(x));x \in S})
(\Rightarrow {x| \log(f(x).g(x)); x \in S} \text{ 如果 } f(x) > 0 \text{ 和 } g(x) > 0) (\Rightarrow {x| \log(f(x)) + \log(g(x));x \in S} \text{ 否则})
产品求解:({x|f(x)g(x)=0; x \in S})
(\Rightarrow {x|f(x)=0; x \in S} \cup {x|g(x)=0; x \in S}) (\text{ 给定 } f(x) \text{ 和 } g(x) \text{ 是有界的。}) (\Rightarrow {x|f(x)g(x)=0; x \in S}, \text{ 否则})
由于输出类型与输入类型相同,这些变换的任何组合也是有效的变换。我们的目标是找到变换序列(给定原子),将给定的条件集转换为非条件集,如 FiniteSet、Interval、整数集及其并、交、补或图像集。我们可以为每个集合分配一个成本函数,使得我们对这种形式的集合越喜欢,成本函数的值就越小。这样,我们的问题现在被简化为在图中找到从初始 ConditionSet 到值最低的集合的路径,其中原子变换形成边。
如何处理仅部分解已知的情况?
创建一个通用方程求解器,它可以解决我们在数学中遇到的每一个方程,是计算代数系统中的理想情况。对于无法解决或只能部分解决的情况,使用
ConditionSet
并充当未评估的 solveset 对象。请注意,在数学上,找到方程的完全解集是不可判定的。参见 Richardson's theorem。
ConditionSet
基本上是满足给定条件的元素集合。例如,要表示实域中方程的解:[(x² - 4)(\sin(x) + x)]
我们可以表示为:
({-2, 2} ∪ {x | x \in \mathbb{R} ∧ x + \sin(x) = 0})
对于 solve 和 solveset 的计划是什么?
solveset
仍然不能做到的事情有些,而 solve
可以,比如解非线性多元和 LambertW 类型的方程。因此,它还不能完全替代 solve
。随着 solveset
中的算法成熟,solveset
可能能够在 solve
中替换一些算法。
如何处理解集中的符号参数?
Solveset 处于初步开发阶段,因此并非所有情况下符号参数处理得当,但在这方面已经做了一些工作来表达我们对符号参数的思想。例如,考虑对于实数 (x) 解 (|x| = n),其中 (n) 是符号参数。Solveset 根据符号参数 (n) 的定义域返回 (x) 的值:
([0, \infty) \cap {n}) \cup ((-\infty, 0] \cap {-n}).]
这简单地意味着当 (n) 属于
Interval
([0, \infty)) 时,(n) 是解,当 (-n) 属于Interval
((- \infty, 0]) 时,(-n) 是解。还有其他情况需要处理,例如解 (2^x + (a - 2)) 对 (x) 的方程,其中 (a) 是符号参数。目前,它返回解作为与 (\mathbb{R}) 的交集,这是微不足道的,因为它不反映 (a) 在解中的定义域。
最近,我们还实现了一个在表达式的有限集(与区间的交集)中找到其非空域的函数。这对处理符号参数很有用。例如:
>>> from sympy import Symbol, FiniteSet, Interval, not_empty_in, sqrt, oo >>> from sympy.abc import x >>> not_empty_in(FiniteSet(x/2).intersect(Interval(0, 1)), x) Interval(0, 2) >>> not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) Union(Interval(1, 2), Interval(-sqrt(2), -1))
参考
Solveset 模块参考
使用 solveset()
解方程或表达式(假定等于 0)的单变量。可以如下解方程 (x² == 1):
>>> from sympy import solveset
>>> from sympy import Symbol, Eq
>>> x = Symbol('x')
>>> solveset(Eq(x**2, 1), x)
{-1, 1}
或者可以手动将方程重写为等于 0 的表达式:
>>> solveset(x**2 - 1, x)
{-1, 1}
solveset()
的第一个参数是一个表达式(等于零)或一个方程,第二个参数是要解方程的符号。
sympy.solvers.solveset.solveset(f, symbol=None, domain=Complexes)
解给定的不等式或方程,输出为集合
参数:
f:表达式或关系。
目标方程或不等式
symbol:符号
要解方程的变量
domain:集合
方程的解决域
返回:
集合
一个值的集合 (symbol),其中 (f) 为 True 或等于零。如果 (f) 为 False 或非零,则返回
EmptySet
。如果尚未实现评估完整解决方案的算法,则返回ConditionSet
作为未解决的对象。
solveset
声称其返回的解集是完整的。
引发:
NotImplementedError
尚未实现在复杂域中解决不等式的算法。
ValueError
输入无效。
RuntimeError
这是一个错误,请报告给 GitHub 问题跟踪器。
注释
Python 将 0 和 1 解释为 False 和 True,但在此函数中,它们分别指的是表达式的解。因此,0 和 1 分别返回域和 EmptySet,而 True 和 False 返回相反的值(因为它们被假定为关系表达式的解)。
示例
>>> from sympy import exp, sin, Symbol, pprint, S, Eq
>>> from sympy.solvers.solveset import solveset, solveset_real
- 默认域为复数域。不指定域将导致在复数域中解方程(这与符号上的假设无关):
>>> x = Symbol('x')
>>> pprint(solveset(exp(x) - 1, x), use_unicode=False)
{2*n*I*pi | n in Integers}
>>> x = Symbol('x', real=True)
>>> pprint(solveset(exp(x) - 1, x), use_unicode=False)
{2*n*I*pi | n in Integers}
- 如果要使用
solveset
在实数域中解决方程,请提供一个实数域。(使用solveset_real
可自动完成此操作。)
>>> R = S.Reals
>>> x = Symbol('x')
>>> solveset(exp(x) - 1, x, R)
{0}
>>> solveset_real(exp(x) - 1, x)
{0}
解决方案不受符号假设的影响:
>>> p = Symbol('p', positive=True)
>>> pprint(solveset(p**2 - 4))
{-2, 2}
当返回一个 ConditionSet
时,将具有可能改变集合的假设的符号替换为更通用的符号:
>>> i = Symbol('i', imaginary=True)
>>> solveset(Eq(i**2 + i*sin(i), 1), i, domain=S.Reals)
ConditionSet(_R, Eq(_R**2 + _R*sin(_R) - 1, 0), Reals)
- 只能在实数域上解决不等式。使用复数域会导致 NotImplementedError。
>>> solveset(exp(x) > 1, x, R)
Interval.open(0, oo)
另请参阅
solveset_real
实数域求解器
solveset_complex
用于复数域的求解器
sympy.solvers.solveset.solveset_real(f, symbol)
sympy.solvers.solveset.solveset_complex(f, symbol)
sympy.solvers.solveset.invert_real(f_x, y, x)
反转一个实值函数。与 invert_complex()
相同,但在反转之前将域设置为 S.Reals
。
sympy.solvers.solveset.invert_complex(f_x, y, x, domain=Complexes)
将复值方程 (f(x) = y) 简化为一组方程
[\left{g(x) = h_1(y),\ g(x) = h_2(y),\ \dots,\ g(x) = h_n(y) \right}]
其中 (g(x)) 是比 (f(x)) 更简单的函数。返回值是一个元组 ((g(x), \mathrm{set}_h)),其中 (g(x)) 是 (x) 的函数,(\mathrm{set}_h) 是函数集合 (\left{h_1(y), h_2(y), \dots, h_n(y)\right})。这里,(y) 不一定是一个符号。
(\mathrm{set}_h) 包含函数及其在有效域内的信息,通过集合运算获得。例如,如果在实数域中反转 (y = |x| - n),那么 (\mathrm{set}_h) 不仅仅是 ({-n, n}),因为 (n) 的性质未知;而是:
默认情况下,使用复数域,这意味着即使是看似简单的函数如 (\exp(x)),其在复数域中通过 (\log) 的反演结果与在实数域中获得的结果也大不相同。(对于 (\exp(x)),在复数域中通过 (\log) 的反演是多值的,具有无限多个分支。)
如果只处理实数值(或者不确定使用哪个函数),你可能应该将域设置为 S.Reals
(或使用自动执行此操作的 invert_real
)。
示例
>>> from sympy.solvers.solveset import invert_complex, invert_real
>>> from sympy.abc import x, y
>>> from sympy import exp
何时 exp(x) == y?
>>> invert_complex(exp(x), y, x)
(x, ImageSet(Lambda(_n, I*(2*_n*pi + arg(y)) + log(Abs(y))), Integers))
>>> invert_real(exp(x), y, x)
(x, Intersection({log(y)}, Reals))
何时 exp(x) == 1?
>>> invert_complex(exp(x), 1, x)
(x, ImageSet(Lambda(_n, 2*_n*I*pi), Integers))
>>> invert_real(exp(x), 1, x)
(x, {0})
参见
invert_real
, invert_complex
sympy.solvers.solveset.domain_check(f, symbol, p)
如果点 p 是无限的,或者 f 的任何子表达式是无限的,或者在用 p 替换符号后变为无限,则返回 False。如果没有满足这些条件的情况,则返回 True。
示例
>>> from sympy import Mul, oo
>>> from sympy.abc import x
>>> from sympy.solvers.solveset import domain_check
>>> g = 1/(1 + (1/(x + 1))**2)
>>> domain_check(g, x, -1)
False
>>> domain_check(x**2, x, 0)
True
>>> domain_check(1/x, x, oo)
False
- 该函数依赖于假设,即方程的原始形式未被自动简化改变。
>>> domain_check(x/x, x, 0) # x/x is automatically simplified to 1
True
- 要处理自动评估,请使用 evaluate=False:
>>> domain_check(Mul(x, 1/x, evaluate=False), x, 0)
False
sympy.solvers.solveset.solvify(f, symbol, domain)
使用 solveset 解方程并根据 (solve) 输出 API 返回解。
返回:
我们根据 (solveset) 返回的解类型对输出进行分类。
抛出:
未实现错误
ConditionSet 是输入。
解决方案 | 输出
FiniteSet | 列表
ImageSet,| 列表(如果 (f) 是周期的)并集 |
并集 | 列表(包含 FiniteSet)
EmptySet | 空列表
其他 | 无
示例
>>> from sympy.solvers.solveset import solvify
>>> from sympy.abc import x
>>> from sympy import S, tan, sin, exp
>>> solvify(x**2 - 9, x, S.Reals)
[-3, 3]
>>> solvify(sin(x) - 1, x, S.Reals)
[pi/2]
>>> solvify(tan(x), x, S.Reals)
[0]
>>> solvify(exp(x) - 1, x, S.Complexes)
>>> solvify(exp(x) - 1, x, S.Reals)
[0]
sympy.solvers.solveset.linear_eq_to_matrix(equations, *symbols)
将给定的方程组转换为矩阵形式。这里的 (equations) 必须是符号 (symbols) 的线性方程组。元素 M[i, j]
对应于第 (i) 个方程中第 (j) 个符号的系数。
矩阵形式对应于增广矩阵形式。例如:
[4x + 2y + 3z = 1][3x + y + z = -6][2x + 4y + 9z = 2]
此系统将返回 A 和 b 为:
执行的唯一简化是将Eq(a, b)
(\Rightarrow a - b)转换。
Raises:
非线性错误
方程包含一个非线性项。
数值错误
符号未给出或不唯一。
示例
>>> from sympy import linear_eq_to_matrix, symbols
>>> c, x, y, z = symbols('c, x, y, z')
符号的系数(数字或符号)将作为矩阵返回:
>>> eqns = [c*x + z - 1 - c, y + z, x - y]
>>> A, b = linear_eq_to_matrix(eqns, [x, y, z])
>>> A
Matrix([
[c, 0, 1],
[0, 1, 1],
[1, -1, 0]])
>>> b
Matrix([
[c + 1],
[ 0],
[ 0]])
此例程不会简化表达式,并且如果遇到非线性,则会引发错误:
>>> eqns = [ ... (x**2 - 3*x)/(x - 3) - 3, ... y**2 - 3*y - y*(y - 4) + x - 4] >>> linear_eq_to_matrix(eqns, [x, y]) Traceback (most recent call last): ... NonlinearError: symbol-dependent term can be ignored using `strict=False`
简化这些方程将丢弃第一个可去的奇异性,并显示第二个的线性结构:
>>> [e.simplify() for e in eqns] [x - 3, x + y - 4]
必须在调用此例程之前执行任何这样的简化,以消除非线性项。
sympy.solvers.solveset.linsolve(system, *symbols)
解 N 个线性方程组,M 个变量;支持欠定和超定系统。可能的解数为零、一或无限。零解引发 ValueError,而无限解以给定符号的参数形式表示。对于唯一解,返回有序元组的FiniteSet
。
支持所有标准输入格式:对于给定的方程组,给出了相应的输入类型如下:
[3x + 2y - z = 1][2x - 2y + 4z = -2][2x - y + 2z = 0]
- 增广矩阵形式,
system
如下所示:
system = Matrix([[3, 2, -1, 1], [2, -2, 4, -2], [2, -1, 2, 0]])
- 方程列表形式
system = [3x + 2y - z - 1, 2x - 2y + 4z + 2, 2x - y + 2z]
- 输入的 A 和 b 以矩阵形式(从 Ax = b)给出:
A = Matrix([[3, 2, -1], [2, -2, 4], [2, -1, 2]])
b = Matrix([[1], [-2], [0]])
system = (A, b)
符号始终可以传递,但实际上只有在以下两种情况下才需要:1)传递一个方程组并且 2)将系统作为欠定矩阵传递,并且希望控制结果中自由变量的名称。如果对于情况 1 没有使用符号,则会引发错误,但如果对于情况 2 没有提供符号,则会提供内部生成的符号。在为情况 2 提供符号时,矩阵 A 中的列数至少应与符号相同。
这里使用的算法是高斯-约当消元法,消元后得到行梯形形式的矩阵。
返回:
包含有序元组值的有限集 FiniteSet
未知数为(system)具有解决方案。(包裹
FiniteSet 中的元组用于维护一致的
解决方案格式始终贯穿 solveset。
如果线性系统不一致,则返回 EmptySet。
Raises:
数值错误
输入无效。符号未给出。
示例
>>> from sympy import Matrix, linsolve, symbols
>>> x, y, z = symbols("x, y, z")
>>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
>>> b = Matrix([3, 6, 9])
>>> A
Matrix([
[1, 2, 3],
[4, 5, 6],
[7, 8, 10]])
>>> b
Matrix([
[3],
[6],
[9]])
>>> linsolve((A, b), [x, y, z])
{(-1, 2, 0)}
- 参数化解:如果系统欠定,函数将返回以给定符号为参数的参数解。自由的符号将保持不变。例如,在下面的系统中,(z)被返回为变量(z)的解;它可以取任何值。
>>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> b = Matrix([3, 6, 9])
>>> linsolve((A, b), x, y, z)
{(z - 1, 2 - 2*z, z)}
如果没有给出符号,则将使用内部生成的符号。第三位置的tau0
表示(与之前一样),第三个变量 - 无论其名称如何 - 可以取任何值:
>>> linsolve((A, b))
{(tau0 - 1, 2 - 2*tau0, tau0)}
- 作为输入的方程组列表
>>> Eqns = [3*x + 2*y - z - 1, 2*x - 2*y + 4*z + 2, - x + y/2 - z]
>>> linsolve(Eqns, x, y, z)
{(1, -2, -2)}
- 作为输入的增广矩阵
>>> aug = Matrix([[2, 1, 3, 1], [2, 6, 8, 3], [6, 8, 18, 5]])
>>> aug
Matrix([
[2, 1, 3, 1],
[2, 6, 8, 3],
[6, 8, 18, 5]])
>>> linsolve(aug, x, y, z)
{(3/10, 2/5, 0)}
- 为符号系数求解
>>> a, b, c, d, e, f = symbols('a, b, c, d, e, f')
>>> eqns = [a*x + b*y - c, d*x + e*y - f]
>>> linsolve(eqns, x, y)
{((-b*f + c*e)/(a*e - b*d), (a*f - c*d)/(a*e - b*d))}
- 退化系统返回给定符号的解集。
>>> system = Matrix(([0, 0, 0], [0, 0, 0], [0, 0, 0]))
>>> linsolve(system, x, y)
{(x, y)}
- 对于空系统,linsolve 返回空集
>>> linsolve([], x)
EmptySet
- 如果检测到任何非线性,则会引发错误,即使可以通过扩展删除
>>> linsolve([x*(1/x - 1)], x)
Traceback (most recent call last):
...
NonlinearError: nonlinear term: 1/x
>>> linsolve([x*(y + 1)], x, y)
Traceback (most recent call last):
...
NonlinearError: nonlinear cross-term: x*(y + 1)
>>> linsolve([x**2 - 1], x)
Traceback (most recent call last):
...
NonlinearError: nonlinear term: x**2
sympy.solvers.solveset.nonlinsolve(system, *symbols)
解(N)个非线性方程与(M)个变量的系统,这意味着支持欠定和超定系统。也支持正维系统(系统具有无限多个解被称为正维系统)。在正维系统中,解将依赖于至少一个符号。返回实数解和复数解(如果存在)。
参数:
系统:方程组列表
方程组的目标系统
symbols:符号列表
符号应作为序列给出,例如列表
返回:
一个FiniteSet
的有序元组,其值为(symbols),以便(system)
有解。元组中的值顺序与符号出现的顺序相同
参数(symbols)。
请注意,一般的FiniteSet
是无序的,解决方案
这里返回的解不仅仅是一个FiniteSet
的解集,而是
是一个FiniteSet
的有序元组,即第一个也是唯一的
FiniteSet
的参数是一个解的元组,即
有序,因此,返回的解决方案是有序的。
还请注意,解也可以作为有序元组返回,
FiniteSet 只是元组周围的包装 {}
。没有其他
除了维持一致性外,没有其他重要性
解决方案的输出格式始终保持在解集中。
对于给定的方程组,各自的输入类型
给定如下:
[xy - 1 = 0][4x² + y² - 5 = 0]
system = [x*y - 1, 4*x**2 + y**2 - 5]
symbols = [x, y]
抛出:
ValueError
输入无效。未给出符号。
AttributeError
输入的符号不是(Symbol)类型。
例子
>>> from sympy import symbols, nonlinsolve
>>> x, y, z = symbols('x, y, z', real=True)
>>> nonlinsolve([x*y - 1, 4*x**2 + y**2 - 5], [x, y])
{(-1, -1), (-1/2, -2), (1/2, 2), (1, 1)}
- 正维系统和补集:
>>> from sympy import pprint
>>> from sympy.polys.polytools import is_zero_dimensional
>>> a, b, c, d = symbols('a, b, c, d', extended_real=True)
>>> eq1 = a + b + c + d
>>> eq2 = a*b + b*c + c*d + d*a
>>> eq3 = a*b*c + b*c*d + c*d*a + d*a*b
>>> eq4 = a*b*c*d - 1
>>> system = [eq1, eq2, eq3, eq4]
>>> is_zero_dimensional(system)
False
>>> pprint(nonlinsolve(system, [a, b, c, d]), use_unicode=False)
-1 1 1 -1
{(---, -d, -, {d} \ {0}), (-, -d, ---, {d} \ {0})}
d d d d
>>> nonlinsolve([(x+y)**2 - 4, x + y - 2], [x, y])
{(2 - y, y)}
2. 如果一些方程不是多项式,则(nonlinsolve)将调用substitution
函数并返回实数和复数解(如果存在)。
>>> from sympy import exp, sin
>>> nonlinsolve([exp(x) - sin(y), y**2 - 4], [x, y])
{(ImageSet(Lambda(_n, I*(2*_n*pi + pi) + log(sin(2))), Integers), -2),
(ImageSet(Lambda(_n, 2*_n*I*pi + log(sin(2))), Integers), 2)}
3. 如果系统是非线性多项式且零维的,则使用solve_poly_system()
返回解(如果有实数和复数解):
>>> from sympy import sqrt
>>> nonlinsolve([x**2 - 2*y**2 -2, x*y - 2], [x, y])
{(-2, -1), (2, 1), (-sqrt(2)*I, sqrt(2)*I), (sqrt(2)*I, -sqrt(2)*I)}
4. nonlinsolve
可以解决一些线性系统(零维或正维),因为它使用sympy.polys.polytools.groebner()
函数获取 Groebner 基础,然后使用substitution
函数将基础作为新系统。但不推荐使用nonlinsolve
解决线性系统,因为一般的线性系统最好使用linsolve()
。
>>> nonlinsolve([x + 2*y -z - 3, x - y - 4*z + 9, y + z - 4], [x, y, z])
{(3*z - 5, 4 - z, z)}
5. 只有多项式方程且仅有实数解的系统使用solve_poly_system()
求解:
>>> e1 = sqrt(x**2 + y**2) - 10
>>> e2 = sqrt(y**2 + (-x + 10)**2) - 3
>>> nonlinsolve((e1, e2), (x, y))
{(191/20, -3*sqrt(391)/20), (191/20, 3*sqrt(391)/20)}
>>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [x, y])
{(1, 2), (1 - sqrt(5), 2 + sqrt(5)), (1 + sqrt(5), 2 - sqrt(5))}
>>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [y, x])
{(2, 1), (2 - sqrt(5), 1 + sqrt(5)), (2 + sqrt(5), 1 - sqrt(5))}
6. 最好使用符号而不是三角函数或Function
。例如,用符号替换(\sin(x)),用符号替换(f(x))等。从nonlinsolve
获取解决方案,然后使用solveset()
得到(x)的值。
比老解算器 _solve_system
更好的nonlinsolve
:
1. 正维系统求解器:nonlinsolve
可以返回正维系统的解。它找到正维系统的 Groebner 基础(称为基础),然后我们可以开始解方程(首先解最少变量的方程),使用 solveset 并将已解决的解值代入其他方程(基础方程)中,以获得最小变量的解。重要的是我们如何替换已知值以及替换到哪些方程中。
2. 实数和复数解:nonlinsolve
返回实数和复数解。如果系统中的所有方程都是多项式,则使用solve_poly_system()
返回实数和复数解。如果系统中的所有方程不是多项式方程,则使用substitution
方法处理这些多项式和非多项式方程,以解决未解决的变量。在解决实数和复数解时,使用solveset_real
和solveset_complex
。对于实数和复数解,_solve_using_known_values
在substitution
内部使用(当存在非多项式方程时将调用substitution
)。如果解是有效的,则将其一般解添加到最终结果中。
3. 补集
和交集
将被添加:nonlinsolve 在substitution
函数执行期间保持补集和交集的字典。如果solveset
在执行期间找到任何变量的补集或交集,那么在返回最终解之前将添加该变量的补集或交集。
transolve
sympy.solvers.solveset._transolve(f, symbol, domain)
解超越方程的函数。这是solveset
的一个辅助函数,应在内部使用。_transolve
目前支持以下类型的方程:
- 指数方程
- 对数方程
参数:
f:需要解决的任何超越方程。
这应该是一个表达式,假设等于
0
。
symbol:要解方程的变量。
这需要是
Symbol
类的。
domain:方程解的集合。
这应该是
Set
类的。
返回:
集合
symbol
的一组值,使得f
等于零。如果f
在相应域中没有解,则返回EmptySet
。如果尚未实现评估完整解的算法,则返回ConditionSet
作为未解决的对象。
如何使用_transolve
不应独立使用_transolve
作为一个独立函数,因为它假设方程(f
)和symbol
来自solveset
并可能经历了一些修改。要将_transolve
作为一个独立函数使用,方程(f
)和symbol
应作为它们由solveset
传递的样子传递。
示例
>>> from sympy.solvers.solveset import _transolve as transolve
>>> from sympy.solvers.solvers import _tsolve as tsolve
>>> from sympy import symbols, S, pprint
>>> x = symbols('x', real=True) # assumption added
>>> transolve(5**(x - 3) - 3**(2*x + 1), x, S.Reals)
{-(log(3) + 3*log(5))/(-log(5) + 2*log(3))}
_transolve
的工作原理
_transolve
使用两种类型的辅助函数来解决特定类别的方程:
识别辅助函数:确定给定方程是否属于某一类方程。返回True
或False
。
解决辅助函数:一旦确定了方程,相应的辅助函数将解决方程或返回solveset
更好处理的方程形式。
- 模块背后的哲学
_transolve
的目的是接受生成器中不是多项式的方程,并通过有效的转换将它们转换为这样的形式,或者直接解决它们。每类支持的超越函数都使用一对辅助函数来实现这一目的。其中一个识别方程的超越形式,另一个要么解决它,要么重新将其重塑为solveset
可以处理的可处理形式。例如,形如 (ab^{f(x)} - cd^{g(x)} = 0) 的方程在某些假设下可以转换为 (\log(a) + f(x)\log(b) - \log(c) - g(x)\log(d) = 0),并且如果 (f(x)) 和 (g(x)) 是多项式形式,则可以使用solveset
解决。
_transolve
为何优于_tsolve
- 更好的输出
_transolve
以更简化的形式提供表达式。
考虑一个简单的指数方程
>>> f = 3**(2*x) - 2**(x + 3)
>>> pprint(transolve(f, x, S.Reals), use_unicode=False)
-3*log(2)
{------------------}
-2*log(3) + log(2)
>>> pprint(tsolve(f, x), use_unicode=False)
/ 3 \
| --------|
| log(2/9)|
[-log\2 /]
- 可扩展的
_transolve
的 API 被设计成易于扩展,即解决给定类别方程的代码被封装在辅助函数中,而不是与 _transolve
代码混合在一起。
- 模块化
_transolve
被设计为模块化,即为每一类方程实现一个单独的识别和解决助手。这样可以轻松修改或更改任何直接实现在辅助函数中的方法,而不会干扰 API 的实际结构。
- 更快的计算
通过 _transolve
解方程要比通过 _tsolve
快得多。在 solve
中,尝试计算每一种可能性以获取解决方案。这一系列尝试使得解决过程有些慢。在 _transolve
中,只有在识别特定类型的方程后才开始计算。
如何添加新的方程类别
添加新的方程类别求解器是一个三步骤过程:
-
确定方程的类型
确定它们所属的方程类别的类型:可以是
Add
、Pow
等类型。使用不同的内部函数处理每种类型。编写识别和解决助手,并从例程中使用它们来处理给定类型的方程(如果需要添加)。def add_type(lhs, rhs, x): .... if _is_exponential(lhs, x): new_eq = _solve_exponential(lhs, rhs, x) .... rhs, lhs = eq.as_independent(x) if lhs.is_Add: result = add_type(lhs, rhs, x)
-
定义识别助手。
-
定义解决助手。
除此之外,添加方程求解器时需要注意的一些其他事项:
-
命名约定:识别助手的名称应为
_is_class
,其中类将是方程类别的名称或缩写。求解助手将命名为_solve_class
。例如,对于指数方程,它变为_is_exponential
和_solve_expo
。 -
识别助手应该接受两个输入参数,待检查的方程和正在寻找解的变量,而解决助手则需要一个额外的域参数。
-
请务必考虑边界情况。
-
为每个辅助函数添加测试。
-
为您的辅助函数添加文档字符串,描述已实现的方法。辅助函数的文档应标识:
-
辅助函数的目的,
-
用于识别和解决方程的方法,
-
一个正确性的证明
-
辅助函数的返回值
-
sympy.solvers.solveset._is_exponential(f, symbol)
如果一个或多个项仅包含 symbol
的指数,则返回 True
,否则返回 False
。
参数:
f : 表达式
要检查的方程
symbol : 符号
检查方程的变量
示例
>>> from sympy import symbols, cos, exp
>>> from sympy.solvers.solveset import _is_exponential as check
>>> x, y = symbols('x y')
>>> check(y, y)
False
>>> check(x**y - 1, y)
True
>>> check(x**y*2**y - 1, y)
True
>>> check(exp(x + 3) + 3**x, x)
True
>>> check(cos(2**x), x)
False
- 辅助函数背后的哲学
该函数提取方程的每一项,并检查它是否符合相对于 symbol
的指数形式。
sympy.solvers.solveset._solve_exponential(lhs, rhs, symbol, domain)
用于解决(支持的)指数方程的辅助函数。
指数方程目前最多由两项组成,其中一项或两项具有依赖于符号的指数。
例如
[5^{2x + 3} - 5^{3x - 1}][4^{5 - 9x} - e^{2 - x}]
参数:
lhs, rhs : 表达式
要解决的指数方程,(lhs = rhs)
symbol : 符号
在其中解方程的变量
domain : 集合
一个解方程式的集合。
返回:
满足给定方程的解集。
如果方程无法解决,就会出现 ConditionSet
或
如果假设没有适当定义,在这种情况下
返回具有不同风格的 ConditionSet
,其中
方程式的解(解)与所需的假设。
例子
>>> from sympy.solvers.solveset import _solve_exponential as solve_expo
>>> from sympy import symbols, S
>>> x = symbols('x', real=True)
>>> a, b = symbols('a b')
>>> solve_expo(2**x + 3**x - 5**x, 0, x, S.Reals) # not solvable
ConditionSet(x, Eq(2**x + 3**x - 5**x, 0), Reals)
>>> solve_expo(a**x - b**x, 0, x, S.Reals) # solvable but incorrect assumptions
ConditionSet(x, (a > 0) & (b > 0), {0})
>>> solve_expo(3**(2*x) - 2**(x + 3), 0, x, S.Reals)
{-3*log(2)/(-2*log(3) + log(2))}
>>> solve_expo(2**x - 4**x, 0, x, S.Reals)
{0}
- 方法的正确性证明
对数函数是指数函数的反函数。指数和对数之间的定义关系是:
[{\log_b x} = y \enspace if \enspace b^y = x]
因此,如果我们给出一个包含指数项的方程,我们可以将每个项转换为其相应的对数形式。这通过取对数和使用对数恒等式扩展方程来实现,以便 solveset
轻松处理。
例如:
[3^{2x} = 2^{x + 3}]
对两边取对数将减少方程为
[(2x)\log(3) = (x + 3)\log(2)]
可以很容易地由 solveset
处理此形式。
sympy.solvers.solveset._solve_logarithm(lhs, rhs, symbol, domain)
辅助解决可以化简为单个 (\log) 实例的对数方程。
目前对数方程是包含可以使用各种对数恒等式将其化简为单个 (\log) 项或常数的方程。
例如:
[\log(x) + \log(x - 4)]
可以简化为:
[\log(x(x - 4))]
参数:
lhs, rhs : 表达式
要解决的对数方程,(lhs = rhs)
symbol : 符号
在其中解方程的变量
domain : 集合
一个解方程式的集合。
返回:
满足给定方程的解集。
如果方程无法解决,则返回 ConditionSet
。
例子
>>> from sympy import symbols, log, S
>>> from sympy.solvers.solveset import _solve_logarithm as solve_log
>>> x = symbols('x')
>>> f = log(x - 3) + log(x + 3)
>>> solve_log(f, 0, x, S.Reals)
{-sqrt(10), sqrt(10)}
- 正确性的证明
对数是另一种写指数的方法,并且由以下定义
[{\log_b x} = y \enspace if \enspace b^y = x]
当方程的一边包含单个对数时,可以通过将方程重写为等效的指数方程来解决该方程,如上定义。但是,如果一边包含多个对数,则需要使用对数的性质将其压缩为单个对数。
举个例子
[\log(2x) - 15 = 0]
包含单个对数,因此我们可以直接将其重写为指数形式
[x = \frac{e^{15}}{2}]
但是如果方程具有多个对数,例如
[\log(x - 3) + \log(x + 3) = 0]
我们使用对数恒等式将其转换为简化形式
使用,
[\log(a) + \log(b) = \log(ab)]
方程变为,
[\log((x - 3)(x + 3))]
这个方程包含一个对数,可以通过重写为指数形式来解决。
sympy.solvers.solveset._is_logarithmic(f, symbol)
如果方程是 (a\log(f(x)) + b\log(g(x)) + ... + c) 形式,则返回 True
,否则返回 False
。
参数:
f : 表达式
要检查的方程式
symbol : 符号
在其中检查方程的变量
返回:
如果方程是对数的,则返回 True
。
例子
>>> from sympy import symbols, tan, log
>>> from sympy.solvers.solveset import _is_logarithmic as check
>>> x, y = symbols('x y')
>>> check(log(x + 2) - log(x + 3), x)
True
>>> check(tan(log(2*x)), x)
False
>>> check(x*log(x), x)
False
>>> check(x + log(x), x)
False
>>> check(y + log(x), x)
True
- 辅助工具背后的哲学
该函数提取每个项并检查其是否对于symbol
是对数的。
丢番图方程(DEs)
查看丢番图方程
不等式
查看不等式求解器
普通微分方程(ODEs)
查看 ODE(常微分方程)。
偏微分方程(PDEs)
查看 PDE(偏微分方程)。
abc
此模块将所有拉丁字母和希腊字母作为符号导出,因此您可以方便地进行以下操作
>>> from sympy.abc import x, y
而不是看起来稍微笨拙的
>>> from sympy import symbols
>>> x, y = symbols('x y')
注意事项
1. 在撰写本文时,名称 O
、S
、I
、N
、E
和 Q
与 SymPy 中定义的名称发生冲突。如果您同时从 sympy.abc
和 sympy
导入它们,第二个导入将“获胜”。这仅适用于 * 导入,应仅用于短暂的代码,例如交互会话和不会存活到下一个 SymPy 升级的临时脚本,其中 sympy
可能包含不同的名称。
2. 此模块不会按需定义符号名称,即 from sympy.abc import foo
将报告错误,因为 sympy.abc
中不包含名称 foo
。要获取名为 foo
的符号,仍然需要使用 Symbol('foo')
或 symbols('foo')
。您可以自由混合使用 sympy.abc
和 Symbol
/symbols
,尽管仅使用一种方法获取符号往往会使代码更易读。
该模块还定义了一些特殊名称,以帮助检测哪些名称与默认的 SymPy 命名空间冲突。
_clash1
定义所有与 SymPy 对象冲突的单字母变量;_clash2
定义冲突的多字母符号;_clash
是两者的并集。如果希望在 sympification 期间传递 locals
而不是这些名称的非符号对象,则可以使用它们。
示例
>>> from sympy import S
>>> from sympy.abc import _clash1, _clash2, _clash
>>> S("Q & C", locals=_clash1)
C & Q
>>> S('pi(x)', locals=_clash2)
pi(x)
>>> S('pi(C, Q)', locals=_clash)
pi(C, Q)
代数
介绍
SymPy 的 Algebras 模块提供了对四元数的基本代数操作的支持。
四元数参考
此部分列出了由 Algebras 模块实现的类。
class sympy.algebras.Quaternion(a=0, b=0, c=0, d=0, real_field=True, norm=None)
提供基本的四元数操作。四元数对象可以实例化为 Quaternion(a, b, c, d)
,如 (q = a + bi + cj + dk)。
参数:
norm:None 或 数字
预定义四元数范数。如果给定一个值,Quaternion.norm 返回这个预定义的值,而不是计算范数。
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 2, 3, 4)
>>> q
1 + 2*i + 3*j + 4*k
复数域上的四元数可以定义为:
>>> from sympy import Quaternion
>>> from sympy import symbols, I
>>> x = symbols('x')
>>> q1 = Quaternion(x, x**3, x, x**2, real_field = False)
>>> q2 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
>>> q1
x + x**3*i + x*j + x**2*k
>>> q2
(3 + 4*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k
定义符号单位四元数:
>>> from sympy import Quaternion
>>> from sympy.abc import w, x, y, z
>>> q = Quaternion(w, x, y, z, norm=1)
>>> q
w + x*i + y*j + z*k
>>> q.norm()
1
参考文献
[R1]
www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/
[R2]
en.wikipedia.org/wiki/Quaternion
add(other)
添加四元数。
参数:
other:四元数
要添加到当前(self)四元数的四元数。
返回:
四元数
将当前(self)添加到其他四元数后的结果四元数
示例
>>> from sympy import Quaternion
>>> from sympy import symbols
>>> q1 = Quaternion(1, 2, 3, 4)
>>> q2 = Quaternion(5, 6, 7, 8)
>>> q1.add(q2)
6 + 8*i + 10*j + 12*k
>>> q1 + 5
6 + 2*i + 3*j + 4*k
>>> x = symbols('x', real = True)
>>> q1.add(x)
(x + 1) + 2*i + 3*j + 4*k
复数域上的四元数:
>>> from sympy import Quaternion
>>> from sympy import I
>>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
>>> q3.add(2 + 3*I)
(5 + 7*I) + (2 + 5*I)*i + 0*j + (7 + 8*I)*k
angle()
返回以实轴平面为单位测量的四元数的角度。
解释
给定四元数 (q = a + bi + cj + dk),其中 (a),(b),(c) 和 (d) 是实数,返回由四元数给定的角度
[\theta := 2 \operatorname{atan_2}\left(\sqrt{b² + c² + d²}, {a}\right)]
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(1, 4, 4, 4)
>>> q.angle()
2*atan(4*sqrt(3))
arc_coplanar(other)
如果输入四元数表示的变换弧发生在同一平面上,则返回 True。
参数:
other:一个四元数
返回:
True:如果两个四元数的平面相同,除了方向/符号。
False:如果两个四元数的平面不相同,除了方向/符号。
None:如果其中任何一个四元数的平面是未知的。
解释
当它们的轴平行时,两个四元数在这个弧的意义上被称为共面。一个四元数的平面是其法向量。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q1 = Quaternion(1, 4, 4, 4)
>>> q2 = Quaternion(3, 8, 8, 8)
>>> Quaternion.arc_coplanar(q1, q2)
True
>>> q1 = Quaternion(2, 8, 13, 12)
>>> Quaternion.arc_coplanar(q1, q2)
False
参见
vector_coplanar
, is_pure
axis()
返回 (\mathbf{Ax}(q)),即四元数 (q) 的轴。
解释
给定四元数 (q = a + bi + cj + dk),返回 (\mathbf{Ax}(q)),即该四元数的向量部分的单位向量等于 (\mathbf{U}[\mathbf{V}(q)])。轴始终是一个虚数单位,其平方等于 (-1 + 0i + 0j + 0k)。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(1, 1, 1, 1)
>>> q.axis()
0 + sqrt(3)/3*i + sqrt(3)/3*j + sqrt(3)/3*k
参见
vector_part
exp()
返回 (q) 的指数,由 (e^q) 给出。
返回:
四元数
四元数的指数。
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 2, 3, 4)
>>> q.exp()
E*cos(sqrt(29))
+ 2*sqrt(29)*E*sin(sqrt(29))/29*i
+ 3*sqrt(29)*E*sin(sqrt(29))/29*j
+ 4*sqrt(29)*E*sin(sqrt(29))/29*k
classmethod from_Matrix(elements)
返回从列向量的元素生成的四元数。如果 vector_only 是 True,则仅返回长度为 3 的矩阵的虚部。
参数:
元素:长度为 3 或 4 的矩阵、列表或元组。如果长度为 3,则
假设实部为零。默认值:False
返回:
四元数
由输入元素创建的四元数。
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> q = Quaternion.from_Matrix([a, b, c, d])
>>> q
a + b*i + c*j + d*k
>>> q = Quaternion.from_Matrix([b, c, d])
>>> q
0 + b*i + c*j + d*k
classmethod from_axis_angle(vector, angle)
给定轴和旋转角度后返回旋转四元数。
参数:
向量:包含三个数字的元组
给定轴的向量表示。
角度:数字
轴旋转的角度(以弧度表示)。
返回:
四元数
从给定轴和旋转角度计算的归一化旋转四元数。
示例
>>> from sympy import Quaternion
>>> from sympy import pi, sqrt
>>> q = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), 2*pi/3)
>>> q
1/2 + 1/2*i + 1/2*j + 1/2*k
classmethod from_euler(angles, seq)
返回由欧拉角表示的旋转的四元数等效物,其序列由seq
定义。
参数:
角度:包含 3 个数字的列表、元组或矩阵
欧拉角(以弧度表示)。
seq:长度为 3 的字符串
表示旋转序列。对于外部旋转,
seq
必须全部小写,并且其元素必须来自集合{'x', 'y', 'z'}
。对于内部旋转,seq
必须全部大写,并且其元素必须来自集合{'X', 'Y', 'Z'}
返回:
四元数
从给定序列中的欧拉角计算的归一化旋转四元数。
示例
>>> from sympy import Quaternion
>>> from sympy import pi
>>> q = Quaternion.from_euler([pi/2, 0, 0], 'xyz')
>>> q
sqrt(2)/2 + sqrt(2)/2*i + 0*j + 0*k
>>> q = Quaternion.from_euler([0, pi/2, pi] , 'zyz')
>>> q
0 + (-sqrt(2)/2)*i + 0*j + sqrt(2)/2*k
>>> q = Quaternion.from_euler([0, pi/2, pi] , 'ZYZ')
>>> q
0 + sqrt(2)/2*i + 0*j + sqrt(2)/2*k
classmethod from_rotation_matrix(M)
返回等效于矩阵的四元数。仅当矩阵是特殊正交矩阵(正交且 det(M) = 1)时,四元数才会被归一化。
参数:
M:矩阵
要转换为等效四元数的输入矩阵。M 必须是特殊正交矩阵(正交且 det(M) = 1),以使四元数被归一化。
返回:
四元数
等效于给定矩阵的四元数。
示例
>>> from sympy import Quaternion
>>> from sympy import Matrix, symbols, cos, sin, trigsimp
>>> x = symbols('x')
>>> M = Matrix([[cos(x), -sin(x), 0], [sin(x), cos(x), 0], [0, 0, 1]])
>>> q = trigsimp(Quaternion.from_rotation_matrix(M))
>>> q
sqrt(2)*sqrt(cos(x) + 1)/2 + 0*i + 0*j + sqrt(2 - 2*cos(x))*sign(sin(x))/2*k
index_vector()
返回四元数的索引向量。
返回:
四元数:表示提供的四元数的索引向量。
说明
索引向量由(\mathbf{T}(q))给出,四元数(q)的模(或大小)乘以(\mathbf{Ax}(q)),即(q)的轴。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(2, 4, 2, 4)
>>> q.index_vector()
0 + 4*sqrt(10)/3*i + 2*sqrt(10)/3*j + 4*sqrt(10)/3*k
另请参阅
axis
,norm
integrate(*args)
计算四元数的积分。
返回:
四元数
与给定变量一起进行四元数积分。
示例
四元数的不定积分:
>>> from sympy import Quaternion
>>> from sympy.abc import x
>>> q = Quaternion(1, 2, 3, 4)
>>> q.integrate(x)
x + 2*x*i + 3*x*j + 4*x*k
四元数的定积分:
>>> from sympy import Quaternion
>>> from sympy.abc import x
>>> q = Quaternion(1, 2, 3, 4)
>>> q.integrate((x, 1, 5))
4 + 8*i + 12*j + 16*k
inverse()
返回四元数的逆。
is_pure()
如果四元数是纯的,则返回 true;如果四元数不是纯的,则返回 false;如果未知,则返回 none。
说明
纯四元数(也称为向量四元数)是具有标量部分等于 0 的四元数。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(0, 8, 13, 12)
>>> q.is_pure()
True
另请参阅
scalar_part
is_zero_quaternion()
如果四元数是零四元数,则返回 true;如果不是零四元数,则返回 false;如果值未知,则返回 None。
说明
零四元数是标量部分和向量部分均为 0 的四元数。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(1, 0, 0, 0)
>>> q.is_zero_quaternion()
False
>>> q = Quaternion(0, 0, 0, 0)
>>> q.is_zero_quaternion()
True
另请参阅
scalar_part
, vector_part
log()
返回四元数的对数,即 (\log q)。
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 2, 3, 4)
>>> q.log()
log(sqrt(30))
+ 2*sqrt(29)*acos(sqrt(30)/30)/29*i
+ 3*sqrt(29)*acos(sqrt(30)/30)/29*j
+ 4*sqrt(29)*acos(sqrt(30)/30)/29*k
mensor()
返回四元数模(大小)的自然对数。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(2, 4, 2, 4)
>>> q.mensor()
log(2*sqrt(10))
>>> q.norm()
2*sqrt(10)
参见
norm
mul(other)
乘积四元数。
参数:
other : 四元数或符号
与当前(self)四元数相乘的四元数。
返回:
四元数
与另一个四元数相乘后的结果四元数。
示例
>>> from sympy import Quaternion
>>> from sympy import symbols
>>> q1 = Quaternion(1, 2, 3, 4)
>>> q2 = Quaternion(5, 6, 7, 8)
>>> q1.mul(q2)
(-60) + 12*i + 30*j + 24*k
>>> q1.mul(2)
2 + 4*i + 6*j + 8*k
>>> x = symbols('x', real = True)
>>> q1.mul(x)
x + 2*x*i + 3*x*j + 4*x*k
复数域上的四元数:
>>> from sympy import Quaternion
>>> from sympy import I
>>> q3 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
>>> q3.mul(2 + 3*I)
(2 + 3*I)*(3 + 4*I) + (2 + 3*I)*(2 + 5*I)*i + 0*j + (2 + 3*I)*(7 + 8*I)*k
norm()
返回四元数的模。
normalize()
返回四元数的标准形式。
orthogonal(other)
返回两个四元数的正交性。
参数:
other : 一个四元数
返回:
True : 如果两个作为 3D 向量的纯四元数是正交的。
False : 如果两个作为 3D 向量的纯四元数不正交。
None : 如果两个作为 3D 向量的纯四元数是正交的情况未知。
解释
当两个纯四元数的乘积是反交换时称为正交。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(0, 4, 4, 4)
>>> q1 = Quaternion(0, 8, 8, 8)
>>> q.orthogonal(q1)
False
>>> q1 = Quaternion(0, 2, 2, 0)
>>> q = Quaternion(0, 2, -2, 0)
>>> q.orthogonal(q1)
True
parallel(other)
如果两个作为 3D 向量的纯四元数是平行的,则返回 True。
参数:
other : 一个四元数
返回:
True : 如果两个作为 3D 向量的纯四元数是平行的。
False : 如果两个作为 3D 向量的纯四元数不平行。
None : 如果两个作为 3D 向量的纯四元数是平行的情况未知。
解释
当两个向量积可交换时,两个纯四元数称为平行。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(0, 4, 4, 4)
>>> q1 = Quaternion(0, 8, 8, 8)
>>> q.parallel(q1)
True
>>> q1 = Quaternion(0, 8, 13, 12)
>>> q.parallel(q1)
False
pow(p)
计算四元数的 p 次幂。
参数:
p : 整数
应用于四元数的幂。
返回:
四元数
返回当前四元数的 p 次幂。如果 p = -1,则返回其逆。
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 2, 3, 4)
>>> q.pow(4)
668 + (-224)*i + (-336)*j + (-448)*k
pow_cos_sin(p)
计算以余弦-正弦形式的 p 次幂。
参数:
p : 整数
应用于四元数的幂。
返回:
四元数
以余弦-正弦形式给出的 p 次幂。
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 2, 3, 4)
>>> q.pow_cos_sin(4)
900*cos(4*acos(sqrt(30)/30))
+ 1800*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*i
+ 2700*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*j
+ 3600*sqrt(29)*sin(4*acos(sqrt(30)/30))/29*k
property product_matrix_left
返回与哈密顿乘积等效的 4 x 4 矩阵,从左边计算。当将四元数元素视为列向量时,这可能很有用。给定四元数 (q = a + bi + cj + dk) 其中 a, b, c 和 d 是实数,从左侧的乘积矩阵是:
[\begin{split}M = \begin{bmatrix} a &-b &-c &-d \ b & a &-d & c \ c & d & a &-b \ d &-c & b & a \end{bmatrix}\end{split}]
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> q1 = Quaternion(1, 0, 0, 1)
>>> q2 = Quaternion(a, b, c, d)
>>> q1.product_matrix_left
Matrix([
[1, 0, 0, -1],
[0, 1, -1, 0],
[0, 1, 1, 0],
[1, 0, 0, 1]])
>>> q1.product_matrix_left * q2.to_Matrix()
Matrix([
[a - d],
[b - c],
[b + c],
[a + d]])
这等同于:
>>> (q1 * q2).to_Matrix()
Matrix([
[a - d],
[b - c],
[b + c],
[a + d]])
property product_matrix_right
返回与哈密顿乘积等效的 4 x 4 矩阵,从右边计算。当将四元数元素视为列向量时,这可能很有用。给定四元数 (q = a + bi + cj + dk) 其中 a, b, c 和 d 是实数,从左侧的乘积矩阵是:
[\begin{split}M = \begin{bmatrix} a &-b &-c &-d \ b & a & d &-c \ c &-d & a & b \ d & c &-b & a \end{bmatrix}\end{split}]
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> q1 = Quaternion(a, b, c, d)
>>> q2 = Quaternion(1, 0, 0, 1)
>>> q2.product_matrix_right
Matrix([
[1, 0, 0, -1],
[0, 1, 1, 0],
[0, -1, 1, 0],
[1, 0, 0, 1]])
注意参数已交换:矩阵表示右侧的四元数,但仍然被视为从左侧进行矩阵乘法。
>>> q2.product_matrix_right * q1.to_Matrix()
Matrix([
[ a - d],
[ b + c],
[-b + c],
[ a + d]])
这等价于:
>>> (q1 * q2).to_Matrix()
Matrix([
[ a - d],
[ b + c],
[-b + c],
[ a + d]])
static rotate_point(pin, r)
返回旋转后点 pin 的坐标(一个 3 元组)。
参数:
pin : 元组
一个需要旋转的点的 3 元素元组。
r : 四元数或元组
旋转的轴和角度。
需要注意的是,当 r 是一个元组时,它必须是 (轴, 角度) 的形式
返回:
元组
旋转后点的坐标。
示例
>>> from sympy import Quaternion
>>> from sympy import symbols, trigsimp, cos, sin
>>> x = symbols('x')
>>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
>>> trigsimp(Quaternion.rotate_point((1, 1, 1), q))
(sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)
>>> (axis, angle) = q.to_axis_angle()
>>> trigsimp(Quaternion.rotate_point((1, 1, 1), (axis, angle)))
(sqrt(2)*cos(x + pi/4), sqrt(2)*sin(x + pi/4), 1)
scalar_part()
返回四元数 q 的标量部分((\mathbf{S}(q)))。
解释
给定四元数 (q = a + bi + cj + dk),返回 (\mathbf{S}(q) = a)。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(4, 8, 13, 12)
>>> q.scalar_part()
4
set_norm(norm)
设置已实例化四元数的范数。
参数:
norm : None 或 数字
预定义四元数的范数。如果给定值,则
Quaternion.norm
返回此预定义值而不是计算范数
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> q = Quaternion(a, b, c, d)
>>> q.norm()
sqrt(a**2 + b**2 + c**2 + d**2)
设置范数:
>>> q.set_norm(1)
>>> q.norm()
1
移除设置的范数:
>>> q.set_norm(None)
>>> q.norm()
sqrt(a**2 + b**2 + c**2 + d**2)
to_Matrix(vector_only=False)
将四元数的元素作为列向量返回。默认情况下,返回长度为 4 的Matrix
,其中实部为第一个元素。如果vector_only
为True
,则仅返回长度为 3 的虚部作为Matrix
。
参数:
vector_only : 布尔值
如果为 True,则仅返回虚部。默认值:False
返回:
矩阵
由四元数的元素构造的列向量。
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> q = Quaternion(a, b, c, d)
>>> q
a + b*i + c*j + d*k
>>> q.to_Matrix()
Matrix([
[a],
[b],
[c],
[d]])
>>> q.to_Matrix(vector_only=True)
Matrix([
[b],
[c],
[d]])
to_axis_angle()
返回四元数的旋转轴和角度。
返回:
元组
(轴, 角度) 元组
示例
>>> from sympy import Quaternion
>>> q = Quaternion(1, 1, 1, 1)
>>> (axis, angle) = q.to_axis_angle()
>>> axis
(sqrt(3)/3, sqrt(3)/3, sqrt(3)/3)
>>> angle
2*pi/3
to_euler(seq, angle_addition=True, avoid_square_root=False)
返回表示与四元数相同旋转的欧拉角,按给定的seq
顺序。这实现了[R3]中描述的方法。
对于退化情况(万向锁情况),第三个角度设置为零。
参数:
seq : 长度为 3 的字符串
表示旋转顺序。对于外部旋转,seq 必须全小写,并且其元素必须来自集合
{'x', 'y', 'z'}
。对于内部旋转,seq 必须全大写,并且其元素必须来自集合{'X', 'Y', 'Z'}
angle_addition : 布尔值
当为 True 时,第一个和第三个角度由两个简单的
atan2
表达式的加减给出。当为 False 时,第一个和第三个角度分别由一个更复杂的atan2
表达式给出。该等价表达式如下:[\operatorname{atan_2} (b,a) \pm \operatorname{atan_2} (d,c) = \operatorname{atan_2} (bc\pm ad, ac\mp bd)]
默认值:True
avoid_square_root : 布尔值
当为 True 时,第二个角度计算使用基于
acos
的表达式,稍微复杂一些但避免了平方根。当为 False 时,第二个角度使用atan2
计算,这更简单并且在数值上更好(某些acos
的数值实现在接近零时存在问题)。默认值:False
返回:
元组
由四元数计算得到的欧拉角
示例
>>> from sympy import Quaternion
>>> from sympy.abc import a, b, c, d
>>> euler = Quaternion(a, b, c, d).to_euler('zyz')
>>> euler
(-atan2(-b, c) + atan2(d, a),
2*atan2(sqrt(b**2 + c**2), sqrt(a**2 + d**2)),
atan2(-b, c) + atan2(d, a))
参考文献
[R3] (1,2)
doi.org/10.1371/journal.pone.0276302
to_rotation_matrix(v=None, homogeneous=True)
返回等效的旋转变换矩阵,表示围绕原点的四元数旋转,如果未传递 v
。
参数:
v:元组或无
默认值:无
homogeneous:布尔值
当为真时,提供一个可能对符号计算更有效但对直接评估不那么有效的表达式。这两个公式在数学上是等效的。默认值:真
返回:
元组
返回等效的旋转变换矩阵,表示围绕原点的四元数旋转,如果未传递
v
。
示例
>>> from sympy import Quaternion
>>> from sympy import symbols, trigsimp, cos, sin
>>> x = symbols('x')
>>> q = Quaternion(cos(x/2), 0, 0, sin(x/2))
>>> trigsimp(q.to_rotation_matrix())
Matrix([
[cos(x), -sin(x), 0],
[sin(x), cos(x), 0],
[ 0, 0, 1]])
生成一个 4x4 变换矩阵(用于绕非原点旋转)如果点(v)作为参数传递。
classmethod vector_coplanar(q1, q2, q3)
如果将纯四元数的轴视为 3D 向量 q1
、q2
和 q3
共面,则返回真。
参数:
q1
一个纯四元数。
q2
一个纯四元数。
q3
一个纯四元数。
返回:
True:如果纯四元数的轴被视为 3D 向量
q1、q2 和 q3 共面。
False:如果将纯四元数的轴视为 3D 向量
q1、q2 和 q3 不共面。
None:如果将纯四元数的轴视为 3D 向量
q1、q2 和 q3 是否共面是未知的。
说明
如果将四元数视为 3D 向量,则三个纯四元数是向量共面的。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q1 = Quaternion(0, 4, 4, 4)
>>> q2 = Quaternion(0, 8, 8, 8)
>>> q3 = Quaternion(0, 24, 24, 24)
>>> Quaternion.vector_coplanar(q1, q2, q3)
True
>>> q1 = Quaternion(0, 8, 16, 8)
>>> q2 = Quaternion(0, 8, 3, 12)
>>> Quaternion.vector_coplanar(q1, q2, q3)
False
另请参阅
axis
, is_pure
vector_part()
返回 (\mathbf{V}(q)),四元数 (q) 的向量部分。
说明
给定四元数 (q = a + bi + cj + dk),返回 (\mathbf{V}(q) = bi + cj + dk)。
示例
>>> from sympy.algebras.quaternion import Quaternion
>>> q = Quaternion(1, 1, 1, 1)
>>> q.vector_part()
0 + 1*i + 1*j + 1*k
>>> q = Quaternion(4, 8, 13, 12)
>>> q.vector_part()
0 + 8*i + 13*j + 12*k
具体
超几何项
在递归求解和求和中,超几何项占据了中心舞台。正式地说,这些是被一阶线性递推算子消灭的序列。简单地说,如果给定项 (a(n)),则如果其连续项比是 (n) 的有理函数,则它是超几何的。
要检查一个序列是否是这种类型,可以使用 is_hypergeometric
方法,该方法在 Basic 类中可用。以下是涉及多项式的简单示例:
>>> from sympy import *
>>> n, k = symbols('n,k')
>>> (n**2 + 1).is_hypergeometric(n)
True
当然,多项式是超几何的,但还有更复杂的这种类型的序列吗?以下是一些简单的例子:
>>> factorial(n).is_hypergeometric(n)
True
>>> binomial(n, k).is_hypergeometric(n)
True
>>> rf(n, k).is_hypergeometric(n)
True
>>> ff(n, k).is_hypergeometric(n)
True
>>> gamma(n).is_hypergeometric(n)
True
>>> (2**n).is_hypergeometric(n)
True
我们看到在具体数学的求和和其他部分中使用的所有特殊物种都是超几何的。还要注意,二项式系数以及升序和降序阶乘在它们的参数中都是超几何的:
>>> binomial(n, k).is_hypergeometric(k)
True
>>> rf(n, k).is_hypergeometric(k)
True
>>> ff(n, k).is_hypergeometric(k)
True
进一步说,所有先前显示的例子都适用于整数线性参数:
>>> factorial(2*n).is_hypergeometric(n)
True
>>> binomial(3*n+1, k).is_hypergeometric(n)
True
>>> rf(n+1, k-1).is_hypergeometric(n)
True
>>> ff(n-1, k+1).is_hypergeometric(n)
True
>>> gamma(5*n).is_hypergeometric(n)
True
>>> (2**(n-7)).is_hypergeometric(n)
True
然而,非线性参数使得这些序列无法成为超几何序列:
>>> factorial(n**2).is_hypergeometric(n)
False
>>> (2**(n**3 + 1)).is_hypergeometric(n)
False
如果需要的不仅仅是判断是否为超几何序列的知识,可以使用 hypersimp()
函数。它将尝试简化组合表达式,并且如果给定的项是超几何的,则返回最小度数多项式的商。否则,将返回 (None) 表示序列不是超几何的:
>>> hypersimp(factorial(2*n), n)
2*(n + 1)*(2*n + 1)
>>> hypersimp(factorial(n**2), n)
具体类参考
class sympy.concrete.summations.Sum(function, *symbols, **assumptions)
表示未计算的求和。
说明
Sum
表示一个有限或无限级数,第一个参数是级数项的一般形式,第二个参数是 (dummy_variable, start, end)
,其中 dummy_variable
取从 start
到 end
的所有整数值。根据长期以来的数学约定,包含结束项在内的求和。
有限和
对于有限和(和假定有限的符号限制),我们遵循 Karr [1] 描述的求和惯例,特别是第 1.4 节的定义 3。这个和:
[\sum_{m \leq i < n} f(i)]
对于 (m < n),具有显而易见的含义,即:
[\sum_{m \leq i < n} f(i) = f(m) + f(m+1) + \ldots + f(n-2) + f(n-1)]
上限值 (f(n)) 排除。如果 (m = n),则空集的和为零:
[\sum_{m \leq i < n} f(i) = 0 \quad \mathrm{for} \quad m = n]
最后,对于所有其他空集的求和,我们假设以下定义:
[\sum_{m \leq i < n} f(i) = - \sum_{n \leq i < m} f(i) \quad \mathrm{for} \quad m > n]
需要注意的是,Karr 定义了所有上限为排除的求和。这与通常的数学符号形成对比,但不影响求和约定。确实,我们有:
[\sum_{m \leq i < n} f(i) = \sum_{i = m}^{n - 1} f(i)]
符号差异是故意的,以强调其含义,顶部的限制被设置为包含。
例子
>>> from sympy.abc import i, k, m, n, x
>>> from sympy import Sum, factorial, oo, IndexedBase, Function
>>> Sum(k, (k, 1, m))
Sum(k, (k, 1, m))
>>> Sum(k, (k, 1, m)).doit()
m**2/2 + m/2
>>> Sum(k**2, (k, 1, m))
Sum(k**2, (k, 1, m))
>>> Sum(k**2, (k, 1, m)).doit()
m**3/3 + m**2/2 + m/6
>>> Sum(x**k, (k, 0, oo))
Sum(x**k, (k, 0, oo))
>>> Sum(x**k, (k, 0, oo)).doit()
Piecewise((1/(1 - x), Abs(x) < 1), (Sum(x**k, (k, 0, oo)), True))
>>> Sum(x**k/factorial(k), (k, 0, oo)).doit()
exp(x)
这里有用符号索引进行求和的示例。您可以使用 Function 或 IndexedBase 类:
>>> f = Function('f')
>>> Sum(f(n), (n, 0, 3)).doit()
f(0) + f(1) + f(2) + f(3)
>>> Sum(f(n), (n, 0, oo)).doit()
Sum(f(n), (n, 0, oo))
>>> f = IndexedBase('f')
>>> Sum(f[n]**2, (n, 0, 3)).doit()
f[0]**2 + f[1]**2 + f[2]**2 + f[3]**2
一个例子显示求和的符号结果对于看似荒谬的极限值仍然有效。然后 Karr 约定允许我们根据上述规则交换极限,从而为这些求和给出完全有效的解释:
>>> S = Sum(i, (i, 1, n)).doit()
>>> S
n**2/2 + n/2
>>> S.subs(n, -4)
6
>>> Sum(i, (i, 1, -4)).doit()
6
>>> Sum(-i, (i, -3, 0)).doit()
6
Karr 求和约定的显式示例:
>>> S1 = Sum(i**2, (i, m, m+n-1)).doit()
>>> S1
m**2*n + m*n**2 - m*n + n**3/3 - n**2/2 + n/6
>>> S2 = Sum(i**2, (i, m+n, m-1)).doit()
>>> S2
-m**2*n - m*n**2 + m*n - n**3/3 + n**2/2 - n/6
>>> S1 + S2
0
>>> S3 = Sum(i, (i, m, m-1)).doit()
>>> S3
0
另见
summation
, Product
, sympy.concrete.products.product
参考文献
[R98]
Michael Karr,“Summation in Finite Terms”,Journal of the ACM,Volume 28 Issue 2,April 1981,Pages 305-350 dl.acm.org/doi/10.1145/322248.322255
[R99]
en.wikipedia.org/wiki/Summation#Capital-sigma_notation
[R100]
en.wikipedia.org/wiki/Empty_sum
euler_maclaurin(m=0, n=0, eps=0, eval_integral=True)
返回自身的 Euler-Maclaurin 近似,其中 m 是直接求和的前导项数,n 是尾部项数。
当 m = n = 0 时,这只是对应积分加上一阶端点修正。
返回 (s, e),其中 s 是 Euler-Maclaurin 近似,e 是估计的误差(取尾部省略项的大小):
>>> from sympy.abc import k, a, b
>>> from sympy import Sum
>>> Sum(1/k, (k, 2, 5)).doit().evalf()
1.28333333333333
>>> s, e = Sum(1/k, (k, 2, 5)).euler_maclaurin()
>>> s
-log(2) + 7/20 + log(5)
>>> from sympy import sstr
>>> print(sstr((s.evalf(), e.evalf()), full_prec=True))
(1.26629073187415, 0.0175000000000000)
端点可以是符号的:
>>> s, e = Sum(1/k, (k, a, b)).euler_maclaurin()
>>> s
-log(a) + log(b) + 1/(2*b) + 1/(2*a)
>>> e
Abs(1/(12*b**2) - 1/(12*a**2))
如果函数是至多 2n+1 次的多项式,则 Euler-Maclaurin 公式变得精确(并返回 e = 0):
>>> Sum(k, (k, 2, b)).euler_maclaurin()
(b**2/2 + b/2 - 1, 0)
>>> Sum(k, (k, 2, b)).doit()
b**2/2 + b/2 - 1
当指定非零 eps 时,只要剩余项小于 epsilon,就结束求和。
eval_zeta_function(f, limits)
检查函数是否与 zeta 函数匹配。
如果匹配,则返回 (Piecewise) 表达式,因为 zeta 函数只有在 (s > 1) 和 (q > 0) 时收敛。
is_absolutely_convergent()
检查无穷级数的绝对收敛性。
检查无穷级数的绝对收敛性。
例子
>>> from sympy import Sum, Symbol, oo
>>> n = Symbol('n', integer=True)
>>> Sum((-1)**n, (n, 1, oo)).is_absolutely_convergent()
False
>>> Sum((-1)**n/n**2, (n, 1, oo)).is_absolutely_convergent()
True
另见
Sum.is_convergent
参考文献
[R101]
en.wikipedia.org/wiki/Absolute_convergence
is_convergent()
检查 Sum 的收敛性。
解释
我们将无穷级数和乘积的收敛性研究分为两部分。
第一部分:一个问题是所有项是否良好定义,即它们在求和中是有限的,在乘积中也是非零的。零在乘积中类似于(负)无穷大,即 (e^{-\infty} = 0)。
第二部分:第二部分是在忽略了无穷大和乘积中的零后的收敛性问题,假设它们的数量是有限的。这意味着我们只考虑求和或乘积的尾部,从某个点开始,所有项都是良定义的。
例如,在形如:
[\sum_{1 \leq i < \infty} \frac{1}{n² + an + b}]
其中 a 和 b 是数字的求和中,例程将返回 true,即使在项序列中存在无穷大(至多两个)。类似的乘积会是:
[\prod_{1 \leq i < \infty} e^{\frac{1}{n² + an + b}}]
这是收敛性的解释方式。它关注于极限时发生的情况。寻找不良项是另一个独立的问题。
注意:确保用户自行负责确保求和或乘积的定义良好。
有多种测试用于检查收敛性,如发散测试,根测试,积分测试,交替级数测试,比较测试,狄利克雷测试。如果求和收敛则返回 true,发散则返回 false,如果无法检查则返回 NotImplementedError。
示例
>>> from sympy import factorial, S, Sum, Symbol, oo
>>> n = Symbol('n', integer=True)
>>> Sum(n/(n - 1), (n, 4, 7)).is_convergent()
True
>>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent()
False
>>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent()
False
>>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent()
True
参见
Sum.is_absolutely_convergent
, sympy.concrete.products.Product.is_convergent
参考
[R102]
en.wikipedia.org/wiki/Convergence_tests
reverse_order(*indices)
反转求和中的极限顺序。
解释
reverse_order(self, *indices)
反转表达式self
中的一些限制,它可以是Sum
或Product
。参数indices
中的选择器指定了要反转限制的索引。这些选择器可以是变量名或从最内层限制元组开始计数的数值索引。
示例
>>> from sympy import Sum
>>> from sympy.abc import x, y, a, b, c, d
>>> Sum(x, (x, 0, 3)).reverse_order(x)
Sum(-x, (x, 4, -1))
>>> Sum(x*y, (x, 1, 5), (y, 0, 6)).reverse_order(x, y)
Sum(x*y, (x, 6, 0), (y, 7, -1))
>>> Sum(x, (x, a, b)).reverse_order(x)
Sum(-x, (x, b + 1, a - 1))
>>> Sum(x, (x, a, b)).reverse_order(0)
Sum(-x, (x, b + 1, a - 1))
在指定反转哪些限制时应优先使用变量名,但是如果有几个符号具有相同名称,则索引计数符号非常方便。
>>> S = Sum(x**2, (x, a, b), (x, c, d))
>>> S
Sum(x**2, (x, a, b), (x, c, d))
>>> S0 = S.reverse_order(0)
>>> S0
Sum(-x**2, (x, b + 1, a - 1), (x, c, d))
>>> S1 = S0.reverse_order(1)
>>> S1
Sum(x**2, (x, b + 1, a - 1), (x, d + 1, c - 1))
当然,我们可以混合两种表示法:
>>> Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(x, 1)
Sum(x*y, (x, b + 1, a - 1), (y, 6, 1))
>>> Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(y, x)
Sum(x*y, (x, b + 1, a - 1), (y, 6, 1))
参见
sympy.concrete.expr_with_intlimits.ExprWithIntLimits.index
, reorder_limit
, sympy.concrete.expr_with_intlimits.ExprWithIntLimits.reorder
参考
[R103]
Michael Karr,《有限项求和》,ACM 期刊,第 28 卷第 2 期,1981 年 4 月,305-350 页 dl.acm.org/doi/10.1145/322248.322255
class sympy.concrete.products.Product(function, *symbols, **assumptions)
表示未评估的乘积。
解释
Product
表示一个有限或无限的乘积,第一个参数是序列中项的一般形式,第二个参数是 (dummy_variable, start, end)
,其中 dummy_variable
取从 start
到 end
的所有整数值。根据长期以来的数学惯例,最后一项包括在乘积中。
有限乘积
对于有限乘积(以及假设为有限的符号极限乘积),我们遵循卡尔描述的和约定的类似方式 [1],特别是第 1.4 节的定义 3。乘积:
[\prod_{m \leq i < n} f(i)]
对于 (m < n),具有 明显的含义,即:
[\prod_{m \leq i < n} f(i) = f(m) f(m+1) \cdot \ldots \cdot f(n-2) f(n-1)]
具有排除上限值 (f(n))。如果且仅如果 (m = n),则空集的乘积为一:
[\prod_{m \leq i < n} f(i) = 1 \quad \mathrm{for} \quad m = n]
最后,对于所有空集合上的其他乘积,我们假设以下定义:
[\prod_{m \leq i < n} f(i) = \frac{1}{\prod_{n \leq i < m} f(i)} \quad \mathrm{for} \quad m > n]
需要注意的是,在上文中我们定义所有带有排除上限的乘积。这与通常的数学表示形式相反,但不影响乘积约定。确实,我们有:
[\prod_{m \leq i < n} f(i) = \prod_{i = m}^{n - 1} f(i)]
其中符号上的差异是故意的,以强调含义,极限的排版在顶部是包含的。
示例
>>> from sympy.abc import a, b, i, k, m, n, x
>>> from sympy import Product, oo
>>> Product(k, (k, 1, m))
Product(k, (k, 1, m))
>>> Product(k, (k, 1, m)).doit()
factorial(m)
>>> Product(k**2,(k, 1, m))
Product(k**2, (k, 1, m))
>>> Product(k**2,(k, 1, m)).doit()
factorial(m)**2
瓦利斯的π乘积:
>>> W = Product(2*i/(2*i-1) * 2*i/(2*i+1), (i, 1, oo))
>>> W
Product(4*i**2/((2*i - 1)*(2*i + 1)), (i, 1, oo))
当前的直接计算失败:
>>> W.doit()
Product(4*i**2/((2*i - 1)*(2*i + 1)), (i, 1, oo))
但是我们可以通过有限乘积的极限逼近无限乘积:
>>> from sympy import limit
>>> W2 = Product(2*i/(2*i-1)*2*i/(2*i+1), (i, 1, n))
>>> W2
Product(4*i**2/((2*i - 1)*(2*i + 1)), (i, 1, n))
>>> W2e = W2.doit()
>>> W2e
4**n*factorial(n)**2/(2**(2*n)*RisingFactorial(1/2, n)*RisingFactorial(3/2, n))
>>> limit(W2e, n, oo)
pi/2
同样的公式也可以计算 sin(pi/2):
>>> from sympy import combsimp, pi, gamma, simplify
>>> P = pi * x * Product(1 - x**2/k**2, (k, 1, n))
>>> P = P.subs(x, pi/2)
>>> P
pi**2*Product(1 - pi**2/(4*k**2), (k, 1, n))/2
>>> Pe = P.doit()
>>> Pe
pi**2*RisingFactorial(1 - pi/2, n)*RisingFactorial(1 + pi/2, n)/(2*factorial(n)**2)
>>> limit(Pe, n, oo).gammasimp()
sin(pi**2/2)
>>> Pe.rewrite(gamma)
(-1)**n*pi**2*gamma(pi/2)*gamma(n + 1 + pi/2)/(2*gamma(1 + pi/2)*gamma(-n + pi/2)*gamma(n + 1)**2)
具有下限大于上限的产品:
>>> Product(1/i, (i, 6, 1)).doit()
120
>>> Product(i, (i, 2, 5)).doit()
120
空产品:
>>> Product(i, (i, n, n-1)).doit()
1
显示了一个示例,即使在极限看似荒谬的情况下,产品的符号结果仍然有效。然后,根据上述规则,卡尔约定允许我们对这些产品进行完全有效的解释:
>>> P = Product(2, (i, 10, n)).doit()
>>> P
2**(n - 9)
>>> P.subs(n, 5)
1/16
>>> Product(2, (i, 10, 5)).doit()
1/16
>>> 1/Product(2, (i, 6, 9)).doit()
1/16
卡尔总和约定应用于乘积的明确示例:
>>> P1 = Product(x, (i, a, b)).doit()
>>> P1
x**(-a + b + 1)
>>> P2 = Product(x, (i, b+1, a-1)).doit()
>>> P2
x**(a - b - 1)
>>> simplify(P1 * P2)
1
和另一个:
>>> P1 = Product(i, (i, b, a)).doit()
>>> P1
RisingFactorial(b, a - b + 1)
>>> P2 = Product(i, (i, a+1, b-1)).doit()
>>> P2
RisingFactorial(a + 1, -a + b - 1)
>>> P1 * P2
RisingFactorial(b, a - b + 1)*RisingFactorial(a + 1, -a + b - 1)
>>> combsimp(P1 * P2)
1
另请参见
Sum
,summation
,product
参考文献
[R104]
迈克尔·卡尔,“有限术语的总和”,ACM 期刊,第 28 卷第 2 期,1981 年 4 月,305-350 页 dl.acm.org/doi/10.1145/322248.322255
[R105]
zh.wikipedia.org/wiki/%E4%B9%98%E6%B3%95
[R106]
zh.wikipedia.org/wiki/%E7%A9%BA%E4%BA%A7%E4%B9%98%E7%A7%AF
is_convergent()
请参阅 Sum.is_convergent()
的文档,了解 SymPy 中收敛的解释。
解释
无限乘积:
[\prod_{1 \leq i < \infty} f(i)]
由部分乘积序列定义:
[\prod_{i=1}^{n} f(i) = f(1) f(2) \cdots f(n)]
当 ( n ) 无限增大时。该乘积在且仅在和式收敛到非零值时收敛:
[\sum_{1 \leq i < \infty} \log{f(n)}]
收敛。
示例
>>> from sympy import Product, Symbol, cos, pi, exp, oo
>>> n = Symbol('n', integer=True)
>>> Product(n/(n + 1), (n, 1, oo)).is_convergent()
False
>>> Product(1/n**2, (n, 1, oo)).is_convergent()
False
>>> Product(cos(pi/n), (n, 1, oo)).is_convergent()
True
>>> Product(exp(-n**2), (n, 1, oo)).is_convergent()
False
参考文献
[R107]
en.wikipedia.org/wiki/Infinite_product
reverse_order(*indices)
反转产品中限制的顺序。
解释
reverse_order(expr, *indices)
反转表达式 expr
中的一些限制条件,可以是 Sum
或 Product
。参数 indices
中的选择器指定要反转限制条件的索引。这些选择器可以是变量名或从内部限制元组开始计数的数值索引。
示例
>>> from sympy import gamma, Product, simplify, Sum
>>> from sympy.abc import x, y, a, b, c, d
>>> P = Product(x, (x, a, b))
>>> Pr = P.reverse_order(x)
>>> Pr
Product(1/x, (x, b + 1, a - 1))
>>> Pr = Pr.doit()
>>> Pr
1/RisingFactorial(b + 1, a - b - 1)
>>> simplify(Pr.rewrite(gamma))
Piecewise((gamma(b + 1)/gamma(a), b > -1), ((-1)**(-a + b + 1)*gamma(1 - a)/gamma(-b), True))
>>> P = P.doit()
>>> P
RisingFactorial(a, -a + b + 1)
>>> simplify(P.rewrite(gamma))
Piecewise((gamma(b + 1)/gamma(a), a > 0), ((-1)**(-a + b + 1)*gamma(1 - a)/gamma(-b), True))
当指定要反转的限制条件时,应优先使用变量名,但索引计数符号在多个同名符号的情况下非常有用。
>>> S = Sum(x*y, (x, a, b), (y, c, d))
>>> S
Sum(x*y, (x, a, b), (y, c, d))
>>> S0 = S.reverse_order(0)
>>> S0
Sum(-x*y, (x, b + 1, a - 1), (y, c, d))
>>> S1 = S0.reverse_order(1)
>>> S1
Sum(x*y, (x, b + 1, a - 1), (y, d + 1, c - 1))
当然,我们可以混合使用这两种符号:
>>> Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(x, 1)
Sum(x*y, (x, b + 1, a - 1), (y, 6, 1))
>>> Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(y, x)
Sum(x*y, (x, b + 1, a - 1), (y, 6, 1))
另见
sympy.concrete.expr_with_intlimits.ExprWithIntLimits.index
, reorder_limit
, sympy.concrete.expr_with_intlimits.ExprWithIntLimits.reorder
参考文献
[R108]
Michael Karr,“Summation in Finite Terms”,Journal of the ACM,Volume 28 Issue 2,April 1981,Pages 305-350 dl.acm.org/doi/10.1145/322248.322255
class sympy.concrete.expr_with_intlimits.ExprWithIntLimits(function, *symbols, **assumptions)
产品和和的超类。
另见
sympy.concrete.expr_with_limits.ExprWithLimits
, sympy.concrete.products.Product
, sympy.concrete.summations.Sum
change_index(var, trafo, newvar=None)
更改和积的索引。
对索引变量 ( x ) 执行线性变换 ( x \mapsto a x + b )。允许的 ( a ) 值仅限于 ( \pm 1 )。在索引变更后也可以指定一个新变量。
解释
change_index(expr, var, trafo, newvar=None)
其中 var
指定要变换的索引变量 ( x )。变换 trafo
必须是线性的,并且以 var
的形式给出。如果提供了可选参数 newvar
,则最终表达式中的 var
将被替换为 newvar
。
示例
>>> from sympy import Sum, Product, simplify
>>> from sympy.abc import x, y, a, b, c, d, u, v, i, j, k, l
>>> S = Sum(x, (x, a, b))
>>> S.doit()
-a**2/2 + a/2 + b**2/2 + b/2
>>> Sn = S.change_index(x, x + 1, y)
>>> Sn
Sum(y - 1, (y, a + 1, b + 1))
>>> Sn.doit()
-a**2/2 + a/2 + b**2/2 + b/2
>>> Sn = S.change_index(x, -x, y)
>>> Sn
Sum(-y, (y, -b, -a))
>>> Sn.doit()
-a**2/2 + a/2 + b**2/2 + b/2
>>> Sn = S.change_index(x, x+u)
>>> Sn
Sum(-u + x, (x, a + u, b + u))
>>> Sn.doit()
-a**2/2 - a*u + a/2 + b**2/2 + b*u + b/2 - u*(-a + b + 1) + u
>>> simplify(Sn.doit())
-a**2/2 + a/2 + b**2/2 + b/2
>>> Sn = S.change_index(x, -x - u, y)
>>> Sn
Sum(-u - y, (y, -b - u, -a - u))
>>> Sn.doit()
-a**2/2 - a*u + a/2 + b**2/2 + b*u + b/2 - u*(-a + b + 1) + u
>>> simplify(Sn.doit())
-a**2/2 + a/2 + b**2/2 + b/2
>>> P = Product(i*j**2, (i, a, b), (j, c, d))
>>> P
Product(i*j**2, (i, a, b), (j, c, d))
>>> P2 = P.change_index(i, i+3, k)
>>> P2
Product(j**2*(k - 3), (k, a + 3, b + 3), (j, c, d))
>>> P3 = P2.change_index(j, -j, l)
>>> P3
Product(l**2*(k - 3), (k, a + 3, b + 3), (l, -d, -c))
当仅处理符号时,我们可以进行一般的线性转换:
>>> Sn = S.change_index(x, u*x+v, y)
>>> Sn
Sum((-v + y)/u, (y, b*u + v, a*u + v))
>>> Sn.doit()
-v*(a*u - b*u + 1)/u + (a**2*u**2/2 + a*u*v + a*u/2 - b**2*u**2/2 - b*u*v + b*u/2 + v)/u
>>> simplify(Sn.doit())
a**2*u/2 + a/2 - b**2*u/2 + b/2
然而,最后的结果可能与通常的求和不一致,其中索引增量始终为 1。这很明显,因为我们仅在 u
等于 +1 或 -1 时才返回原始值。
见也
sympy.concrete.expr_with_intlimits.ExprWithIntLimits.index
, reorder_limit
, sympy.concrete.expr_with_intlimits.ExprWithIntLimits.reorder
, sympy.concrete.summations.Sum.reverse_order
, sympy.concrete.products.Product.reverse_order
property has_empty_sequence
如果对空序列计算求和或乘积,则返回 True。
示例
>>> from sympy import Sum, Product, Symbol
>>> m = Symbol('m')
>>> Sum(m, (m, 1, 0)).has_empty_sequence
True
>>> Sum(m, (m, 1, 1)).has_empty_sequence
False
>>> M = Symbol('M', integer=True, positive=True)
>>> Product(m, (m, 1, M)).has_empty_sequence
False
>>> Product(m, (m, 2, M)).has_empty_sequence
>>> Product(m, (m, M + 1, M)).has_empty_sequence
True
>>> N = Symbol('N', integer=True, positive=True)
>>> Sum(m, (m, N, M)).has_empty_sequence
>>> N = Symbol('N', integer=True, negative=True)
>>> Sum(m, (m, N, M)).has_empty_sequence
False
见也
has_reversed_limits
, has_finite_limits
index(x)
返回在极限列表中的虚拟变量的索引。
解释
index(expr, x)
返回表达式 expr
中变量 x
在极限中的索引。注意,我们从最内层的极限元组开始以 0 开始计数。
示例
>>> from sympy.abc import x, y, a, b, c, d
>>> from sympy import Sum, Product
>>> Sum(x*y, (x, a, b), (y, c, d)).index(x)
0
>>> Sum(x*y, (x, a, b), (y, c, d)).index(y)
1
>>> Product(x*y, (x, a, b), (y, c, d)).index(x)
0
>>> Product(x*y, (x, a, b), (y, c, d)).index(y)
1
见也
reorder_limit
, reorder
, sympy.concrete.summations.Sum.reverse_order
, sympy.concrete.products.Product.reverse_order
reorder(*arg)
在包含求和或乘积的表达式中重新排序极限。
解释
expr.reorder(*arg)
根据给定的元组列表 arg
重新排序表达式 expr
中的极限。这些元组可以包含数值索引、索引变量名称或二者的组合。
示例
>>> from sympy import Sum, Product
>>> from sympy.abc import x, y, z, a, b, c, d, e, f
>>> Sum(x*y, (x, a, b), (y, c, d)).reorder((x, y))
Sum(x*y, (y, c, d), (x, a, b))
>>> Sum(x*y*z, (x, a, b), (y, c, d), (z, e, f)).reorder((x, y), (x, z), (y, z))
Sum(x*y*z, (z, e, f), (y, c, d), (x, a, b))
>>> P = Product(x*y*z, (x, a, b), (y, c, d), (z, e, f))
>>> P.reorder((x, y), (x, z), (y, z))
Product(x*y*z, (z, e, f), (y, c, d), (x, a, b))
我们还可以通过计数选择索引变量,从最内层开始:
>>> Sum(x**2, (x, a, b), (x, c, d)).reorder((0, 1))
Sum(x**2, (x, c, d), (x, a, b))
当然,我们也可以混合使用这两种方案:
>>> Sum(x*y, (x, a, b), (y, c, d)).reorder((y, x))
Sum(x*y, (y, c, d), (x, a, b))
>>> Sum(x*y, (x, a, b), (y, c, d)).reorder((y, 0))
Sum(x*y, (y, c, d), (x, a, b))
见也
reorder_limit
, index
, sympy.concrete.summations.Sum.reverse_order
, sympy.concrete.products.Product.reverse_order
reorder_limit(x, y)
交换 Sum 或 Product 表达式的两个限制元组。
说明
expr.reorder_limit(x, y)
交换两个限制元组。参数 x
和 y
是对应于要交换的两个限制的索引变量的整数。表达式 expr
必须是 Sum 或 Product。
示例
>>> from sympy.abc import x, y, z, a, b, c, d, e, f
>>> from sympy import Sum, Product
>>> Sum(x*y*z, (x, a, b), (y, c, d), (z, e, f)).reorder_limit(0, 2)
Sum(x*y*z, (z, e, f), (y, c, d), (x, a, b))
>>> Sum(x**2, (x, a, b), (x, c, d)).reorder_limit(1, 0)
Sum(x**2, (x, c, d), (x, a, b))
>>> Product(x*y*z, (x, a, b), (y, c, d), (z, e, f)).reorder_limit(0, 2)
Product(x*y*z, (z, e, f), (y, c, d), (x, a, b))
另请参阅
index
, reorder
, sympy.concrete.summations.Sum.reverse_order
, sympy.concrete.products.Product.reverse_order
具体函数参考
sympy.concrete.summations.summation(f, *symbols, **kwargs)
计算符号与符号的和。
说明
符号的表示法类似于积分中使用的符号。summation(f, (i, a, b))
计算 f 对于 i 从 a 到 b 的求和,即,
b
____
\ `
summation(f, (i, a, b)) = ) f
/___,
i = a
如果无法计算和,则返回一个未计算的 Sum 对象。通过引入额外的符号元组可以计算重复的和:
.. rubric:: Examples
>>> from sympy import summation, oo, symbols, log
>>> i, n, m = symbols('i n m', integer=True)
>>> summation(2*i - 1, (i, 1, n))
n**2
>>> summation(1/2**i, (i, 0, oo))
2
>>> summation(1/log(n)**n, (n, 2, oo))
Sum(log(n)**(-n), (n, 2, oo))
>>> summation(i, (i, 0, n), (n, 0, m))
m**3/6 + m**2/2 + m/3
>>> from sympy.abc import x
>>> from sympy import factorial
>>> summation(x**n/factorial(n), (n, 0, oo))
exp(x)
另请参阅
Sum
, Product
, sympy.concrete.products.product
sympy.concrete.products.product(*args, **kwargs)
计算乘积。
说明
符号的表示法类似于求和或积分中使用的符号。product(f, (i, a, b))
计算 f 对于 i 从 a 到 b 的乘积,即,
b
_____
product(f(n), (i, a, b)) = | | f(n)
| |
i = a
如果无法计算乘积,则返回一个未计算的 Product 对象。通过引入额外的符号元组可以计算重复的乘积:
.. rubric:: Examples
>>> from sympy import product, symbols
>>> i, n, m, k = symbols('i n m k', integer=True)
>>> product(i, (i, 1, k))
factorial(k)
>>> product(m, (i, 1, k))
m**k
>>> product(i, (i, 1, k), (k, 1, n))
Product(factorial(k), (k, 1, n))
sympy.concrete.gosper.gosper_normal(f, g, n, polys=True)
计算 f
和 g
的 Gosper 正常形式。
说明
给定相对质的一元多项式 f
和 g
,将它们的商重写为以下定义的正常形式:
[\frac{f(n)}{g(n)} = Z \cdot \frac{A(n) C(n+1)}{B(n) C(n)}]
其中 Z
是任意常数,A
, B
, C
是关于 n
的首一多项式,并具有以下性质:
-
(\gcd(A(n), B(n+h)) = 1 \forall h \in \mathbb{N})
-
(\gcd(B(n), C(n+1)) = 1)
-
(\gcd(A(n), C(n)) = 1)
此正常形式,或者说是有理分解,是 Gosper 算法和求解差分方程的关键步骤。它还可以用来判断两个超几何项是否相似。
此过程将返回一个包含分解元素的元组,形式为(Z*A, B, C)
。
示例
>>> from sympy.concrete.gosper import gosper_normal
>>> from sympy.abc import n
>>> gosper_normal(4*n+5, 2*(4*n+1)*(2*n+3), n, polys=False)
(1/4, n + 3/2, n + 1/4)
sympy.concrete.gosper.gosper_term(f, n)
计算 f
的 Gosper 超几何项。
解释
假设 f
是一个超几何项,使得:
[s_n = \sum_{k=0}^{n-1} f_k]
并且 (f_k) 不依赖于 (n)。返回一个超几何项 (g_n),使得 (g_{n+1} - g_n = f_n)。
示例
>>> from sympy.concrete.gosper import gosper_term
>>> from sympy import factorial
>>> from sympy.abc import n
>>> gosper_term((4*n + 1)*factorial(n)/factorial(2*n + 1), n)
(-n - 1/2)/(n + 1/4)
sympy.concrete.gosper.gosper_sum(f, k)
Gosper 的超几何求和算法。
解释
给定一个超几何项 f
,使得:
[s_n = \sum_{k=0}^{n-1} f_k]
并且 (f(n)) 不依赖于 (n),返回 (g_{n} - g(0)),其中 (g_{n+1} - g_n = f_n),或者如果 (s_n) 无法作为超几何项和的封闭形式表示,则返回 None
。
示例
>>> from sympy.concrete.gosper import gosper_sum
>>> from sympy import factorial
>>> from sympy.abc import n, k
>>> f = (4*k + 1)*factorial(k)/factorial(2*k + 1)
>>> gosper_sum(f, (k, 0, n))
(-factorial(n) + 2*factorial(2*n + 1))/factorial(2*n + 1)
>>> _.subs(n, 2) == sum(f.subs(k, i) for i in [0, 1, 2])
True
>>> gosper_sum(f, (k, 3, n))
(-60*factorial(n) + factorial(2*n + 1))/(60*factorial(2*n + 1))
>>> _.subs(n, 5) == sum(f.subs(k, i) for i in [3, 4, 5])
True
参考资料
[R109]
Marko Petkovsek, Herbert S. Wilf, Doron Zeilberger, A = B, AK Peters, Ltd., Wellesley, MA, USA, 1997, pp. 73–100
核心
sympify
sympy.core.sympify.sympify(a, locals=None, convert_xor=True, strict=False, rational=False, evaluate=None)
将任意表达式转换为可以在 SymPy 内部使用的类型。
参数:
a:
- SymPy 中定义的任何对象
- 标准的数字 Python 类型:
int
、long
、float
、Decimal
- 字符串(如
"0.09"
、"2e-19"
或'sin(x)'
)- 布尔值,包括
None
(将None
保持不变)- 包含上述任何内容的字典、列表、集合或元组
convert_xor:布尔型,可选
如果为真,则将
^
视为指数运算。如果为假,则将^
视为 XOR 本身。仅在输入为字符串时使用。
locals:SymPy 中定义的任何对象,可选
为了使字符串被识别,可以导入到命名空间字典中并作为本地传递。
strict:布尔型,可选
如果严格选项设置为
True
,则仅对已定义显式转换的类型进行转换。在其他情况下,将引发SympifyError
。
rational:布尔型,可选
如果为
True
,则将浮点数转换为Rational
。如果为False
,则让浮点数保持原样。仅在输入为字符串时使用。
evaluate:布尔型,可选
如果为 False,则算术和运算符将转换为它们的 SymPy 等效项。如果为 True,则将评估表达式并返回结果。
解释
它将 Python 整数转换为Integer
的实例,浮点数转换为Float
的实例等。它还能够强制转换从Basic
继承的符号表达式。这在与 SAGE 合作时非常有用。
警告
请注意,此函数使用eval
,因此不应用于未经过滤的输入。
如果参数已经是 SymPy 理解的类型,则不会执行任何操作,只会返回该值。这可以用于函数开始时确保使用正确的类型。
示例
>>> from sympy import sympify
>>> sympify(2).is_integer
True
>>> sympify(2).is_real
True
>>> sympify(2.0).is_real
True
>>> sympify("2.0").is_real
True
>>> sympify("2e-45").is_real
True
如果无法转换表达式,则会引发SympifyError
。
>>> sympify("x***2")
Traceback (most recent call last):
...
SympifyError: SympifyError: "could not parse 'x***2'"
当尝试使用sympify
解析非 Python 语法时,会引发SympifyError
:
>>> sympify("2x+1")
Traceback (most recent call last):
...
SympifyError: Sympify of expression 'could not parse '2x+1'' failed
要解析非 Python 语法,请使用sympy.parsing.sympy_parser
中的parse_expr
。
>>> from sympy.parsing.sympy_parser import parse_expr
>>> parse_expr("2x+1", transformations="all")
2*x + 1
有关transformations
的更多详细信息,请参见parse_expr()
本地
sympify 发生时可以访问通过from sympy import *
加载的所有内容;在字符串中使用的任何未由该导入定义的内容都将转换为符号。在以下示例中,bitcount
函数被视为符号,O
被解释为Order
对象(与级数一起使用),在错误使用时将引发错误:
>>> s = 'bitcount(42)'
>>> sympify(s)
bitcount(42)
>>> sympify("O(x)")
O(x)
>>> sympify("O + 1")
Traceback (most recent call last):
...
TypeError: unbound method...
为了让bitcount
被识别,可以将其导入到命名空间字典中,并作为局部变量传递:
>>> ns = {}
>>> exec('from sympy.core.evalf import bitcount', ns)
>>> sympify(s, locals=ns)
6
为了将O
解释为符号,在命名空间字典中将其标识为符号。有多种方法可以做到这一点;以下三种都是可能的方式:
>>> from sympy import Symbol
>>> ns["O"] = Symbol("O") # method 1
>>> exec('from sympy.abc import O', ns) # method 2
>>> ns.update(dict(O=Symbol("O"))) # method 3
>>> sympify("O + 1", locals=ns)
O + 1
如果您希望所有单字母和希腊字母变量都是符号,那么可以使用那里定义的冲突符号字典作为私有变量: _clash1
(单字母变量), _clash2
(多字母希腊名称)或 _clash
(在abc
中定义的单字母和多字母名称)。
>>> from sympy.abc import _clash1
>>> set(_clash1) # if this fails, see issue #23903
{'E', 'I', 'N', 'O', 'Q', 'S'}
>>> sympify('I & Q', _clash1)
I & Q
严格
如果选项strict
设置为True
,则仅转换已定义显式转换的类型。在其他情况下,将引发 SympifyError。
>>> print(sympify(None))
None
>>> sympify(None, strict=True)
Traceback (most recent call last):
...
SympifyError: SympifyError: None
自版本 1.6 起弃用:当所有其他转换方法失败时,sympify(obj)
自动退回到str(obj)
,但这已被弃用。strict=True
将禁用此弃用行为。请参阅在 sympify()中的字符串回退。
评估
如果选项evaluate
设置为False
,则算术和运算符将转换为它们的 SymPy 等效项,并添加evaluate=False
选项。嵌套的Add
或Mul
将首先解嵌套。这通过 AST 转换完成,替换运算符为它们的 SymPy 等效项,因此如果操作数重新定义任何这些操作,则不会使用重新定义的运算符。如果参数 a 不是字符串,则在传递给 sympify 之前对数学表达式进行评估,因此添加evaluate=False
仍将返回表达式的评估结果。
>>> sympify('2**2 / 3 + 5')
19/3
>>> sympify('2**2 / 3 + 5', evaluate=False)
2**2/3 + 5
>>> sympify('4/2+7', evaluate=True)
9
>>> sympify('4/2+7', evaluate=False)
4/2 + 7
>>> sympify(4/2+7, evaluate=False)
9.00000000000000
扩展
要将sympify
扩展为转换自定义对象(不是从Basic
派生),只需为您的类定义一个_sympy_
方法。即使是对您不拥有的类也可以通过子类化或在运行时添加该方法来完成。
>>> from sympy import Matrix
>>> class MyList1(object):
... def __iter__(self):
... yield 1
... yield 2
... return
... def __getitem__(self, i): return list(self)[i]
... def _sympy_(self): return Matrix(self)
>>> sympify(MyList1())
Matrix([
[1],
[2]])
如果您无法控制类定义,也可以使用全局字典converter
。键是类,值是一个接受单个参数并返回所需 SymPy 对象的函数,例如converter[MyList] = lambda x: Matrix(x)
。
>>> class MyList2(object): # XXX Do not do this if you control the class!
... def __iter__(self): # Use _sympy_!
... yield 1
... yield 2
... return
... def __getitem__(self, i): return list(self)[i]
>>> from sympy.core.sympify import converter
>>> converter[MyList2] = lambda x: Matrix(x)
>>> sympify(MyList2())
Matrix([
[1],
[2]])
注意
当输入为字符串时,关键字rational
和convert_xor
仅在使用时使用。
Convert_xor
>>> sympify('x^y',convert_xor=True)
x**y
>>> sympify('x^y',convert_xor=False)
x ^ y
有理数
>>> sympify('0.1',rational=False)
0.1
>>> sympify('0.1',rational=True)
1/10
有时,在 sympification 期间的自动简化会导致表达式在结构上与输入时大不相同。直到不再进行此类自动简化为止,kernS
函数可能有些用处。在下面的示例中,您可以看到如何通过使用kernS
来将表达式简化为(-1),而在自动简化时则不会这样做。
>>> from sympy.core.sympify import kernS
>>> from sympy.abc import x
>>> -2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1
-1
>>> s = '-2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1'
>>> sympify(s)
-1
>>> kernS(s)
-2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1
``` ## 假设
本模块包含处理假设的机制。还请考虑指南假设。
所有符号对象都有假设属性,可以通过`.is_<assumption name>`属性访问。
假设确定符号对象的某些属性,并且可能有 3 个可能的值:`True`、`False`、`None`。如果对象具有该属性,则返回 `True`,如果不具有或不能确定(即不合适),则返回 `False`:
```py
>>> from sympy import I
>>> I.is_algebraic
True
>>> I.is_real
False
>>> I.is_prime
False
当属性无法确定(或者方法未实现)时,将返回 None
。例如,一个通用符号 x
可能是正数也可能不是,因此对于 x.is_positive
返回 None
。
默认情况下,所有符号值都属于给定上下文中最大的集合,而不指定属性。例如,具有整数属性的符号也是实数、复数等。
以下是可能的假设名称列表:
可交换的
对象在乘法操作中与任何其他对象都是可交换的。参见 [12]。
complex
对象只能取复数集合中的值。参见 [13]。
虚数
对象的值是可以写成实数乘以虚数单位 I
的数。参见 [R112]。请注意,0
不被视为虚数,请参见 issue #7649。
实数
对象只能取实数集合中的值。
extended_real
对象只能取实数、oo
和 -oo
集合中的值。
整数
对象只能取整数集合中的值。
奇数
偶数
对象只能取奇(偶)整数集合中的值 [R111]。
质数
对象是一个大于 1 且没有除了 1 和自身以外正除数的自然数。参见 [R115]。
复合数
对象是一个正整数,至少有一个除了 1 或该数本身以外的正除数。参见 [R113]。
zero
对象的值为 0。
非零
对象是一个非零的实数。
有理数
对象只能取有理数集合中的值。
algebraic
对象只能取代数数集合中的值 [11]。
超越数
对象只能取超越数集合中的值 [10]。
无理数
对象的值不能用 Rational
精确表示,参见 [R114]。
有限的
无穷大
对象的绝对值是有界的(任意大)。参见 [R116]、[R117]、[R118]。
负数
非负数
对象只能取负(非负)值 [R110]。
正数
nonpositive
对象只能取正(非正)值。
extended_negative
extended_nonnegative
extended_positive
extended_nonpositive
extended_nonzero
与没有扩展部分相同,但也包括具有相应符号的无穷大,例如,extended_positive 包括 oo
Hermite
反埃尔米特
对象属于埃尔米特(反埃尔米特)算子的领域。
示例
>>> from sympy import Symbol
>>> x = Symbol('x', real=True); x
x
>>> x.is_real
True
>>> x.is_complex
True
参见
另见
sympy.core.numbers.ImaginaryUnit
sympy.core.numbers.Zero
sympy.core.numbers.One
sympy.core.numbers.Infinity
sympy.core.numbers.NegativeInfinity
sympy.core.numbers.ComplexInfinity
注释
任何 SymPy 表达式的完全解析假设可以按如下方式获取:
>>> from sympy.core.assumptions import assumptions
>>> x = Symbol('x',positive=True)
>>> assumptions(x + I)
{'commutative': True, 'complex': True, 'composite': False, 'even':
False, 'extended_negative': False, 'extended_nonnegative': False,
'extended_nonpositive': False, 'extended_nonzero': False,
'extended_positive': False, 'extended_real': False, 'finite': True,
'imaginary': False, 'infinite': False, 'integer': False, 'irrational':
False, 'negative': False, 'noninteger': False, 'nonnegative': False,
'nonpositive': False, 'nonzero': False, 'odd': False, 'positive':
False, 'prime': False, 'rational': False, 'real': False, 'zero':
False}
开发者注意事项
当前(可能是不完整的)值存储在obj._assumptions dictionary
中;访问对象/类的属性或属性方法的查询将返回值并更新字典。
>>> eq = x**2 + I
>>> eq._assumptions
{}
>>> eq.is_finite
True
>>> eq._assumptions
{'finite': True, 'infinite': False}
对于Symbol
,可能感兴趣的假设有两个位置。assumptions0
属性给出从给定初始假设导出的完整假设集。后者的假设存储在Symbol._assumptions_orig
中。
>>> Symbol('x', prime=True, even=True)._assumptions_orig
{'even': True, 'prime': True}
_assumptions_orig
不一定是规范化的,也没有经过任何过滤:它记录了用于实例化符号的假设,并(为了存储目的)表示需要重建符号的全部假设的更紧凑表示形式。
参考文献
[R110]
en.wikipedia.org/wiki/Negative_number
[R111]
en.wikipedia.org/wiki/Parity_%28mathematics%29
[R112]
en.wikipedia.org/wiki/Imaginary_number
[R113]
en.wikipedia.org/wiki/Composite_number
[R114]
en.wikipedia.org/wiki/Irrational_number
[R115]
en.wikipedia.org/wiki/Prime_number
[R116]
[R117]
docs.python.org/3/library/math.html#math.isfinite
[R118]
numpy.org/doc/stable/reference/generated/numpy.isfinite.html
## 缓存
sympy.core.cache.__cacheit(maxsize)
缓存装饰器。
重要:缓存函数的结果必须是不可变的
示例
>>> from sympy import cacheit
>>> @cacheit
... def f(a, b):
... return a+b
>>> @cacheit
... def f(a, b): # noqa: F811
... return [a, b] # <-- WRONG, returns mutable object
要强制cacheit
检查返回结果的可变性和一致性,请将环境变量SYMPY_USE_CACHE
设置为‘debug’ ## 基本
class sympy.core.basic.Basic(*args)
所有 SymPy 对象的基类。
注释与约定
- 当访问某个实例的参数时,始终使用
.args
:
>>> from sympy import cot
>>> from sympy.abc import x, y
>>> cot(x).args
(x,)
>>> cot(x).args[0]
x
>>> (x*y).args
(x, y)
>>> (x*y).args[1]
y
- 永远不要使用内部方法或变量(以
_
为前缀的那些):
>>> cot(x)._args # do not use this, use cot(x).args instead
(x,)
-
通过“SymPy 对象”,我们指的是可以由
sympify
返回的东西。但并非所有使用 SymPy 遇到的对象都是 Basic 的子类。例如,可变对象不是:>>> from sympy import Basic, Matrix, sympify >>> A = Matrix([[1, 2], [3, 4]]).as_mutable() >>> isinstance(A, Basic) False
>>> B = sympify(A) >>> isinstance(B, Basic) True
property args: tuple[Basic, ...]
返回‘self’的参数的元组。
示例
>>> from sympy import cot
>>> from sympy.abc import x, y
>>> cot(x).args
(x,)
>>> cot(x).args[0]
x
>>> (x*y).args
(x, y)
>>> (x*y).args[1]
y
注意
永远不要使用 self._args,总是使用 self.args。只有在创建新函数时,在 new 中使用 _args。不要覆盖 Basic 的 .args()(以便在需要时容易更改接口)。
as_content_primitive(radical=False, clear=True)
一个存根,允许在计算表达式的内容和基本组成部分时跳过 Basic args(如 Tuple)。
另见
sympy.core.expr.Expr.as_content_primitive
as_dummy()
返回表达式,其中具有结构绑定符号的任何对象都被替换为该对象中唯一的、规范的符号,并且仅具有默认的交换性假设为 True。当应用于符号时,将返回一个具有相同交换性的新符号。
示例
>>> from sympy import Integral, Symbol
>>> from sympy.abc import x
>>> r = Symbol('r', real=True)
>>> Integral(r, (r, x)).as_dummy()
Integral(_0, (_0, x))
>>> _.variables[0].is_real is None
True
>>> r.as_dummy()
_r
注意事项
任何具有结构绑定变量的对象应该有一个属性,(bound_symbols),返回出现在对象中的那些符号。
property assumptions0
返回对象 (type) 的假设。
例如:
Symbol('x', real=True) Symbol('x', integer=True)
是不同的对象。换句话说,除了 Python 类型(本例中为 Symbol)之外,初始假设也形成它们的类型信息。
示例
>>> from sympy import Symbol
>>> from sympy.abc import x
>>> x.assumptions0
{'commutative': True}
>>> x = Symbol("x", positive=True)
>>> x.assumptions0
{'commutative': True, 'complex': True, 'extended_negative': False,
'extended_nonnegative': True, 'extended_nonpositive': False,
'extended_nonzero': True, 'extended_positive': True, 'extended_real':
True, 'finite': True, 'hermitian': True, 'imaginary': False,
'infinite': False, 'negative': False, 'nonnegative': True,
'nonpositive': False, 'nonzero': True, 'positive': True, 'real':
True, 'zero': False}
atoms(*types)
返回形成当前对象的原子。
默认情况下,仅返回真正原子且不能分解为更小部分的对象:符号、数字和诸如 I 和 pi 之类的数字符号。但是,可以请求任何类型的原子,如下所示。
示例
>>> from sympy import I, pi, sin
>>> from sympy.abc import x, y
>>> (1 + x + 2*sin(y + I*pi)).atoms()
{1, 2, I, pi, x, y}
如果给出了一个或多个类型,则结果将仅包含那些类型的原子。
>>> from sympy import Number, NumberSymbol, Symbol
>>> (1 + x + 2*sin(y + I*pi)).atoms(Symbol)
{x, y}
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number)
{1, 2}
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol)
{1, 2, pi}
>>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol, I)
{1, 2, I, pi}
注意,I(虚数单位)和 zoo(复杂无穷大)是特殊类型的数字符号,不属于 NumberSymbol 类。
也可以隐式地给出类型:
>>> (1 + x + 2*sin(y + I*pi)).atoms(x) # x is a Symbol
{x, y}
使用隐式选项时,请检查您的假设。例如,S(1).is_Integer = True
,但type(S(1))
是One
,SymPy 原子的特殊类型,而type(S(2))
是Integer
类型,并将在表达式中找到所有整数:
>>> from sympy import S
>>> (1 + x + 2*sin(y + I*pi)).atoms(S(1))
{1}
>>> (1 + x + 2*sin(y + I*pi)).atoms(S(2))
{1, 2}
最后,atoms() 的参数可以选择超出原子的原子:可以列出任何 SymPy 类型(加载在 core/init.py 中),并且在递归扫描表达式参数时找到那些类型的“原子”:
>>> from sympy import Function, Mul
>>> from sympy.core.function import AppliedUndef
>>> f = Function('f')
>>> (1 + f(x) + 2*sin(y + I*pi)).atoms(Function)
{f(x), sin(y + I*pi)}
>>> (1 + f(x) + 2*sin(y + I*pi)).atoms(AppliedUndef)
{f(x)}
>>> (1 + x + 2*sin(y + I*pi)).atoms(Mul)
{I*pi, 2*sin(y + I*pi)}
property canonical_variables
返回一个字典,将定义在 self.bound_symbols
中的任何变量映射到表达式中不与任何自由符号冲突的符号。
示例
>>> from sympy import Lambda
>>> from sympy.abc import x
>>> Lambda(x, 2*x).canonical_variables
{x: _0}
classmethod class_key()
类的良好顺序。
compare(other)
如果对象在规范意义上小于、等于或大于其他对象,则返回-1、0、1。非 Basic 总是大于 Basic。如果比较的类名都出现在(ordering_of_classes)中,则比较将取决于它们在该列表中的出现顺序。如果其中任何一个不出现在该列表中,则基于类名进行比较。如果类名相同,则基于可散列内容的长度进行比较。相同长度的内容项目然后按照相同规则依次比较。如果从未有过差异,则返回 0。
示例
>>> from sympy.abc import x, y
>>> x.compare(y)
-1
>>> x.compare(x)
0
>>> y.compare(x)
1
count(query)
统计匹配子表达式的数量。
count_ops(visual=None)
count_ops 的包装器,返回操作计数。
doit(**hints)
评估默认情况下不评估的对象,如限制、积分、求和和乘积。所有这类对象将被递归评估,除非通过'hints'排除了某些类型,或者除非设置了'deep'提示为'False'。
>>> from sympy import Integral
>>> from sympy.abc import x
>>> 2*Integral(x, x)
2*Integral(x, x)
>>> (2*Integral(x, x)).doit()
x**2
>>> (2*Integral(x, x)).doit(deep=False)
2*Integral(x, x)
dummy_eq(other, symbol=None)
比较两个表达式并处理虚拟符号。
示例
>>> from sympy import Dummy
>>> from sympy.abc import x, y
>>> u = Dummy('u')
>>> (u**2 + 1).dummy_eq(x**2 + 1)
True
>>> (u**2 + 1) == (x**2 + 1)
False
>>> (u**2 + y).dummy_eq(x**2 + y, x)
True
>>> (u**2 + y).dummy_eq(x**2 + y, y)
False
find(query, group=False)
找到所有与查询匹配的子表达式。
property free_symbols: set[Basic]
从 self 的原子中返回那些是自由符号。
并非所有的自由符号都是 Symbol。例如:IndexedBase('I')[0].free_symbols
对于大多数表达式,所有符号都是自由符号。对于某些类,情况并非如此。例如,积分使用作为绑定变量的符号,因此积分有一个方法可以返回除这些符号外的所有符号。导数还跟踪它将执行导数的符号;这些也是绑定变量,因此它有自己的 free_symbols 方法。
任何使用绑定变量的其他方法都应实现一个 free_symbols 方法。
classmethod fromiter(args, **assumptions)
从可迭代对象创建一个新对象。
这是一个便利函数,允许从任何可迭代对象创建对象,而无需首先转换为列表或元组。
示例
>>> from sympy import Tuple
>>> Tuple.fromiter(i for i in range(5))
(0, 1, 2, 3, 4)
property func
表达式中的顶级函数。
对于所有对象,应该满足以下条件:
>> x == x.func(*x.args)
示例
>>> from sympy.abc import x
>>> a = 2*x
>>> a.func
<class 'sympy.core.mul.Mul'>
>>> a.args
(2, x)
>>> a.func(*a.args)
2*x
>>> a == a.func(*a.args)
True
has(*patterns)
测试是否有任何子表达式与任何模式匹配。
示例
>>> from sympy import sin
>>> from sympy.abc import x, y, z
>>> (x**2 + sin(x*y)).has(z)
False
>>> (x**2 + sin(x*y)).has(x, y, z)
True
>>> x.has(x)
True
注意has
是一个结构算法,不涉及数学知识。考虑以下半开区间:
>>> from sympy import Interval
>>> i = Interval.Lopen(0, 5); i
Interval.Lopen(0, 5)
>>> i.args
(0, 5, True, False)
>>> i.has(4) # there is no "4" in the arguments
False
>>> i.has(0) # there *is* a "0" in the arguments
True
相反,使用contains
来确定一个数字是否在区间内:
>>> i.contains(4)
True
>>> i.contains(0)
False
注意,expr.has(*patterns)
与any(expr.has(p) for p in patterns)
完全等效。特别是当模式列表为空时返回False
。
>>> x.has()
False
has_free(*patterns)
如果 self 作为自由表达式具有对象 x,则返回 True,否则返回 False。
示例
>>> from sympy import Integral, Function
>>> from sympy.abc import x, y
>>> f = Function('f')
>>> g = Function('g')
>>> expr = Integral(f(x), (f(x), 1, g(y)))
>>> expr.free_symbols
{y}
>>> expr.has_free(g(y))
True
>>> expr.has_free(*(x, f(x)))
False
这也适用于子表达式和类型:
>>> expr.has_free(g)
True
>>> (x + y + 1).has_free(y + 1)
True
has_xfree(s: set[Basic])
如果 self 的任何模式作为自由参数存在,则返回 True,否则返回 False。这类似于(Basic.has_free),但只会报告精确的参数匹配。
示例
>>> from sympy import Function
>>> from sympy.abc import x, y
>>> f = Function('f')
>>> f(x).has_xfree({f})
False
>>> f(x).has_xfree({f(x)})
True
>>> f(x + 1).has_xfree({x})
True
>>> f(x + 1).has_xfree({x + 1})
True
>>> f(x + y + 1).has_xfree({x + 1})
False
property is_comparable
如果 self 可以计算为实数(或已经是实数),则返回 True,否则返回 False。
示例
>>> from sympy import exp_polar, pi, I
>>> (I*exp_polar(I*pi/2)).is_comparable
True
>>> (I*exp_polar(I*pi*2)).is_comparable
False
结果错误并不意味着 (self) 不能重写成一个可比较的形式。例如,下面计算的差异为零,但在简化之前不能精确计算为零:
>>> e = 2**pi*(1 + 2**pi)
>>> dif = e - e.expand()
>>> dif.is_comparable
False
>>> dif.n(2)._prec
1
is_same(b, approx=None)
如果 approx
被提供,则返回 True,如果 a 和 b 在结构上相同,否则返回 False。默认情况下,只有相同类型的数字才会比较相等,因此 S.Half != Float(0.5)。
示例
在 SymPy 中(不像 Python),如果两个数字的类型不同,则它们不会比较相同:
>>> from sympy import S
>>> 2.0 == S(2)
False
>>> 0.5 == S.Half
False
通过提供一个比较两个数字的函数,可以忽略这样的差异。例如,equal_valued
将为具有 2 的次幂分母的十进制数返回 True,而不考虑精度。
>>> from sympy import Float
>>> from sympy.core.numbers import equal_valued
>>> (S.Half/4).is_same(Float(0.125, 1), equal_valued)
True
>>> Float(1, 2).is_same(Float(1, 10), equal_valued)
True
但是,没有 2 的次幂分母的十进制数将比较为不相同。
>>> Float(0.1, 9).is_same(Float(0.1, 10), equal_valued)
False
但是可以通过提供一个函数来忽略任意差异,以测试两个数字的等价性:
>>> import math
>>> Float(0.1, 9).is_same(Float(0.1, 10), math.isclose)
True
即使类型不同,其他对象可能会比较相同。此例程仅在两个表达式在类类型上完全相同时返回 True。
>>> from sympy import eye, Basic
>>> eye(1) == S(eye(1)) # mutable vs immutable
True
>>> Basic.is_same(eye(1), S(eye(1)))
False
match(pattern, old=False)
模式匹配。
通配符匹配全部。
当表达式(self)与模式不匹配时返回 None
。否则返回一个字典,如下所示:
pattern.xreplace(self.match(pattern)) == self
示例
>>> from sympy import Wild, Sum
>>> from sympy.abc import x, y
>>> p = Wild("p")
>>> q = Wild("q")
>>> r = Wild("r")
>>> e = (x+y)**(x+y)
>>> e.match(p**p)
{p_: x + y}
>>> e.match(p**q)
{p_: x + y, q_: x + y}
>>> e = (2*x)**2
>>> e.match(p*q**r)
{p_: 4, q_: x, r_: 2}
>>> (p*q**r).xreplace(e.match(p*q**r))
4*x**2
结构绑定符号在匹配过程中被忽略:
>>> Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, p)))
{p_: 2}
但如果需要的话,它们可以被识别出来:
>>> Sum(x, (x, 1, 2)).match(Sum(q, (q, 1, p)))
{p_: 2, q_: x}
old
标志将提供旧式模式匹配,在这种匹配中,表达式和模式本质上是为了给出匹配而解决的。除非 old=True
,否则以下两个都会返回 None:
>>> (x - 2).match(p - x, old=True)
{p_: 2*x - 2}
>>> (2/x).match(p*x, old=True)
{p_: 2/x**2}
matches(expr, repl_dict=None, old=False)
在 self
和 expr
中的通配符匹配的帮助方法。
示例
>>> from sympy import symbols, Wild, Basic
>>> a, b, c = symbols('a b c')
>>> x = Wild('x')
>>> Basic(a + x, x).matches(Basic(a + b, c)) is None
True
>>> Basic(a + x, x).matches(Basic(a + b + c, b + c))
{x_: b + c}
rcall(*args)
递归地应用于表达式树中的参数。
该方法用于模拟操作符的常见滥用符号。例如,在 SymPy 中,以下内容将无法工作:
(x+Lambda(y, 2*y))(z) == x+2*z
,
然而,您可以使用:
>>> from sympy import Lambda
>>> from sympy.abc import x, y, z
>>> (x + Lambda(y, 2*y)).rcall(z)
x + 2*z
refine(assumption=True)
请参见 sympy.assumptions 中的 refine 函数。
replace(query, value, map=False, simultaneous=True, exact=None)
用value
替换self
中匹配的子表达式。
如果 map = True
,则还返回映射 {old: new},其中 old
是通过查询找到的子表达式,new
是其替换值。如果表达式本身与查询不匹配,则返回的值将是 self.xreplace(map)
,否则应该是 self.subs(ordered(map.items()))
。
遍历表达式树并从树底部到树顶部执行匹配子表达式的替换。默认方法是同时进行替换,因此所做的更改仅针对一次。如果不希望或引起问题,则可以将 simultaneous
设置为 False。
此外,如果使用包含多个通配符号的表达式来匹配子表达式,并且 exact
标志为 None,则将其设置为 True,因此仅当每个出现在匹配模式中的通配符都收到非零值时,匹配才会成功。将其设置为 False 接受匹配 0;而设置为 True 则接受所有具有 0 的匹配。有关注意事项,请参见下面的示例。
列出了查询和替换值的可能组合列表:
示例
初始设置
>>> from sympy import log, sin, cos, tan, Wild, Mul, Add
>>> from sympy.abc import x, y
>>> f = log(sin(x)) + tan(sin(x**2))
1.1. 类型 -> 类型
obj.replace(type, newtype)
当找到类型为 type
的对象时,用其参数传递给 newtype
的结果替换它。
>>> f.replace(sin, cos)
log(cos(x)) + tan(cos(x**2))
>>> sin(x).replace(sin, cos, map=True)
(cos(x), {sin(x): cos(x)})
>>> (x*y).replace(Mul, Add)
x + y
1.2. 类型 -> 函数
obj.replace(type, func)
当找到类型为 type
的对象时,将 func
应用于其参数。 func
必须编写以处理 type
的参数数量。
>>> f.replace(sin, lambda arg: sin(2*arg))
log(sin(2*x)) + tan(sin(2*x**2))
>>> (x*y).replace(Mul, lambda *args: sin(2*Mul(*args)))
sin(2*x*y)
2.1. 模式 -> 表达式
obj.replace(pattern(wild), expr(wild))
使用带有通配符号的 pattern
替换子表达式为表达式。
>>> a, b = map(Wild, 'ab')
>>> f.replace(sin(a), tan(a))
log(tan(x)) + tan(tan(x**2))
>>> f.replace(sin(a), tan(a/2))
log(tan(x/2)) + tan(tan(x**2/2))
>>> f.replace(sin(a), a)
log(x) + tan(x**2)
>>> (x*y).replace(a*x, a)
y
默认情况下,当使用多个通配符号进行匹配时,匹配是精确的:除非匹配对所有通配符号都给出非零值,否则匹配失败:
>>> (2*x + y).replace(a*x + b, b - a)
y - 2
>>> (2*x).replace(a*x + b, b - a)
2*x
当设置为 False 时,结果可能不直观:
>>> (2*x).replace(a*x + b, b - a, exact=False)
2/x
2.2. 模式 -> 函数
obj.replace(pattern(wild), lambda wild: expr(wild))
所有行为与 2.1 中相同,但现在使用的是基于模式变量的函数而不是表达式:
>>> f.replace(sin(a), lambda a: sin(2*a))
log(sin(2*x)) + tan(sin(2*x**2))
3.1. 函数 -> 函数
obj.replace(filter, func)
如果 filter(e)
为真,则用 func(e)
替换子表达式 e
。
>>> g = 2*sin(x**3)
>>> g.replace(lambda expr: expr.is_Number, lambda expr: expr**2)
4*sin(x**9)
查询本身也是目标表达式的目标,但是以不做两次更改的方式进行。
>>> e = x*(x*y + 1)
>>> e.replace(lambda x: x.is_Mul, lambda x: 2*x)
2*x*(2*x*y + 1)
当匹配单个符号时,(exact) 默认为 True,但这可能或可能不是所需的行为:
在这里,我们希望 (exact=False):
>>> from sympy import Function
>>> f = Function('f')
>>> e = f(1) + f(0)
>>> q = f(a), lambda a: f(a + 1)
>>> e.replace(*q, exact=False)
f(1) + f(2)
>>> e.replace(*q, exact=True)
f(0) + f(2)
但在这里,匹配的性质使得选择正确的设置变得棘手:
>>> e = x**(1 + y)
>>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=False)
x
>>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=True)
x**(-x - y + 1)
>>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=False)
x
>>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=True)
x**(1 - y)
最好使用描述目标表达式更精确的查询形式:
>>> (1 + x**(1 + y)).replace(
... lambda x: x.is_Pow and x.exp.is_Add and x.exp.args[0] == 1,
... lambda x: x.base**(1 - (x.exp - 1)))
...
x**(1 - y) + 1
另见
subs
替换由对象本身定义的子表达式。
xreplace
在表达树中进行精确的节点替换;还能够使用匹配规则
rewrite(*args, deep=True, **hints)
使用定义的规则重写 self。
重写将一个表达式转换为另一个,在数学上是等效的但结构不同的表达式。例如,您可以将三角函数重写为复指数函数或将组合函数重写为伽马函数。
此方法采用 模式 和 规则 作为位置参数。 模式 是可选参数,定义将进行转换的表达式类型。如果未传递,则将重新编写所有可能的表达式。 规则 定义如何重新编写表达式。
参数:
args : 表达式
一个 规则 或 模式 和 规则。 - 模式 是一种类型或可迭代类型。 - 规则 可以是任何对象。
deep : 布尔值,可选
如果为
True
,则子表达式会递归转换。默认为True
。
示例
如果未指定 pattern,则将转换所有可能的表达式。
>>> from sympy import cos, sin, exp, I
>>> from sympy.abc import x
>>> expr = cos(x) + I*sin(x)
>>> expr.rewrite(exp)
exp(I*x)
模式可以是类型或类型的可迭代对象。
>>> expr.rewrite(sin, exp)
exp(I*x)/2 + cos(x) - exp(-I*x)/2
>>> expr.rewrite([cos,], exp)
exp(I*x)/2 + I*sin(x) + exp(-I*x)/2
>>> expr.rewrite([cos, sin], exp)
exp(I*x)
可通过定义 _eval_rewrite()
方法实现重写行为。
>>> from sympy import Expr, sqrt, pi
>>> class MySin(Expr):
... def _eval_rewrite(self, rule, args, **hints):
... x, = args
... if rule == cos:
... return cos(pi/2 - x, evaluate=False)
... if rule == sqrt:
... return sqrt(1 - cos(x)**2)
>>> MySin(MySin(x)).rewrite(cos)
cos(-cos(-x + pi/2) + pi/2)
>>> MySin(x).rewrite(sqrt)
sqrt(1 - cos(x)**2)
支持为了向后兼容性原因定义 _eval_rewrite_as_[...]()
方法。这可能在将来会被移除,不推荐使用它。
>>> class MySin(Expr):
... def _eval_rewrite_as_cos(self, *args, **hints):
... x, = args
... return cos(pi/2 - x, evaluate=False)
>>> MySin(x).rewrite(cos)
cos(-x + pi/2)
simplify(**kwargs)
参见 sympy.simplify 中的 simplify 函数
sort_key(order=None)
返回排序关键字。
示例
>>> from sympy import S, I
>>> sorted([S(1)/2, I, -I], key=lambda x: x.sort_key())
[1/2, -I, I]
>>> S("[x, 1/x, 1/x**2, x**2, x**(1/2), x**(1/4), x**(3/2)]")
[x, 1/x, x**(-2), x**2, sqrt(x), x**(1/4), x**(3/2)]
>>> sorted(_, key=lambda x: x.sort_key())
[x**(-2), 1/x, x**(1/4), sqrt(x), x, x**(3/2), x**2]
subs(*args, **kwargs)
在 sympify args 之后,在表达式中用 new 替换 old。
(args) 可能是:
-
两个参数,例如 foo.subs(old, new)
-
一个可迭代的参数,例如 foo.subs(iterable)。可迭代对象可以是
一个可迭代的容器,包含 (old, new) 对。在这种情况下,
替换按给定顺序处理,后续模式可能会影响已进行的替换。
一个字典或集合,其键/值项对应于旧/新对。
在这种情况下,旧/新对将按 op 计数排序,并在平局时按参数数量和默认排序关键字排序。然后处理结果排序后的列表作为可迭代容器(见前述)。
如果关键字 simultaneous
设置为 True,则子表达式将在所有替换完成后再进行评估。
示例
>>> from sympy import pi, exp, limit, oo
>>> from sympy.abc import x, y
>>> (1 + x*y).subs(x, pi)
pi*y + 1
>>> (1 + x*y).subs({x:pi, y:2})
1 + 2*pi
>>> (1 + x*y).subs([(x, pi), (y, 2)])
1 + 2*pi
>>> reps = [(y, x**2), (x, 2)]
>>> (x + y).subs(reps)
6
>>> (x + y).subs(reversed(reps))
x**2 + 2
>>> (x**2 + x**4).subs(x**2, y)
y**2 + y
仅替换 x2 而不替换 x4,使用 xreplace:
>>> (x**2 + x**4).xreplace({x**2: y})
x**4 + y
若要延迟评估直到所有替换完成,请将关键字 simultaneous
设置为 True:
>>> (x/y).subs([(x, 0), (y, 0)])
0
>>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
nan
这还具有不允许后续替换影响已进行替换的额外功能:
>>> ((x + y)/y).subs({x + y: y, y: x + y})
1
>>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
y/(x + y)
为了获得规范结果,无序可迭代对象会按照长度、参数数量和默认排序关键字进行排序,以打破任何平局。所有其他可迭代对象保持不排序状态。
>>> from sympy import sqrt, sin, cos
>>> from sympy.abc import a, b, c, d, e
>>> A = (sqrt(sin(2*x)), a)
>>> B = (sin(2*x), b)
>>> C = (cos(2*x), c)
>>> D = (x, d)
>>> E = (exp(x), e)
>>> expr = sqrt(sin(2*x))*sin(exp(x)*x)*cos(2*x) + sin(2*x)
>>> expr.subs(dict([A, B, C, D, E]))
a*c*sin(d*e) + b
结果表达式表示旧参数与新参数的字面替换。这可能不反映表达式的极限行为:
>>> (x**3 - 3*x).subs({x: oo})
nan
>>> limit(x**3 - 3*x, x, oo)
oo
如果替换后将进行数值评估,则最好将替换传递给 evalf,如
>>> (1/x).evalf(subs={x: 3.0}, n=21)
0.333333333333333333333
而不是
>>> (1/x).subs({x: 3.0}).evalf(21)
0.333333333333333314830
因为前者将确保获得所需的精度水平。
另请参阅
replace
能够进行类似通配符匹配、匹配解析和条件替换的替换功能
xreplace
在表达式树中确切节点替换;还能够使用匹配规则
sympy.core.evalf.EvalfMixin.evalf
计算给定公式到所需的精度水平
xreplace(rule)
在表达式中替换对象的出现。
参数:
rule:类似字典
表示替换规则
返回:
xreplace:替换的结果
示例
>>> from sympy import symbols, pi, exp
>>> x, y, z = symbols('x y z')
>>> (1 + x*y).xreplace({x: pi})
pi*y + 1
>>> (1 + x*y).xreplace({x: pi, y: 2})
1 + 2*pi
仅当在表达式树中匹配到整个节点时才进行替换:
>>> (x*y + z).xreplace({x*y: pi})
z + pi
>>> (x*y*z).xreplace({x*y: pi})
x*y*z
>>> (2*x).xreplace({2*x: y, x: z})
y
>>> (2*2*x).xreplace({2*x: y, x: z})
4*z
>>> (x + y + 2).xreplace({x + y: 2})
x + y + 2
>>> (x + 2 + exp(x + 2)).xreplace({x + 2: y})
x + exp(y) + 2
xreplace 不区分自由符号和绑定符号。在以下情况下,subs(x, y)不会改变 x,因为它是一个绑定符号,但 xreplace 会:
>>> from sympy import Integral
>>> Integral(x, (x, 1, 2*x)).xreplace({x: y})
Integral(y, (y, 1, 2*y))
尝试用一个表达式替换 x 会引发错误:
>>> Integral(x, (x, 1, 2*x)).xreplace({x: 2*y})
ValueError: Invalid limits given: ((2*y, 1, 4*y),)
另请参阅
replace
替换能够进行类似通配符的匹配,匹配解析和条件替换
subs
根据对象本身定义的子表达式的替换。
class sympy.core.basic.Atom(*args)
一个原子事物的父类。原子是没有子表达式的表达式。
示例
符号,数字,有理数,整数,...但不包括:Add,Mul,Pow,... ## 单例
class sympy.core.singleton.SingletonRegistry
单例类的注册表(可作为S
访问)。
解释
此类作为两个单独的事物。
第一件事是SingletonRegistry
。在 SymPy 中有几个类经常出现,它们被单例化,也就是说,通过一些元编程,它们被设计成只能实例化一次(详见sympy.core.singleton.Singleton
类的详细信息)。例如,每次创建Integer(0)
时,都会返回相同的实例,sympy.core.numbers.Zero
。所有单例实例都是S
对象的属性,因此Integer(0)
也可以作为S.Zero
访问。
单例化提供了两个优点:它节省内存,并允许快速比较。它节省内存,因为无论单例化对象在内存中出现多少次,它们都指向内存中的同一个单一实例。快速比较来自于在 Python 中可以使用is
来比较确切的实例(通常情况下,需要使用==
来比较)。is
通过内存地址比较对象,并且非常快速。
示例
>>> from sympy import S, Integer
>>> a = Integer(0)
>>> a is S.Zero
True
在大多数情况下,某些对象被设计为单例化是一个用户不需要担心的实现细节。在 SymPy 库代码中,通常使用is
比较是为了性能目的。对于最终用户来说,S
的主要优点是方便访问某些难以输入的实例,如S.Half
(而不是Rational(1, 2)
)。
当使用is
比较时,请确保参数已经过符号化。例如,
>>> x = 0
>>> x is S.Zero
False
当使用==
时,这个问题并不是一个问题,这在大多数用例中是推荐的:
>>> 0 == S.Zero
True
第二件事 S
是 sympy.core.sympify.sympify()
的快捷方式。sympy.core.sympify.sympify()
是将 Python 对象(如 int(1)
)转换为 SymPy 对象(如 Integer(1)
)的函数。它还将表达式的字符串形式转换为 SymPy 表达式,例如 sympify("x**2")
-> Symbol("x")**2
。 S(1)
和 sympify(1)
是相同的(基本上,S.__call__
被定义为调用 sympify
)。
这是为了方便起见,因为 S
是一个单字母。这对定义有理数特别有用。考虑一个表达式 x + 1/2
。如果你直接在 Python 中输入这个表达式,它会评估 1/2
并给出 0.5
,因为两个参数都是整数(另请参见 两个终极注意事项:^ 和 /)。然而,在 SymPy 中,你通常希望两个整数的商能够精确地得到一个有理数。Python 评估的方式是,至少一侧的操作数需要是 SymPy 对象才能进行 SymPy 评估。你可以将这写成 x + Rational(1, 2)
,但这样键入的量比较多。一个更短的版本是 x + S(1)/2
。由于 S(1)
返回 Integer(1)
,除法将返回一个 Rational
类型,因为它会调用 Integer.__truediv__
,它知道如何返回一个 Rational
。
class sympy.core.singleton.Singleton(*args, **kwargs)
单例类的元类。
解释
单例类只有一个实例,每次实例化类时都会返回这个实例。此外,可以通过全局注册对象 S
作为 S.<class_name>
来访问这个实例。
示例
>>> from sympy import S, Basic
>>> from sympy.core.singleton import Singleton
>>> class MySingleton(Basic, metaclass=Singleton):
... pass
>>> Basic() is Basic()
False
>>> MySingleton() is MySingleton()
True
>>> S.MySingleton is MySingleton()
True
注意事项
实例的创建被延迟到第一次访问该值时。(SymPy 版本在 1.0 之前会在类创建时创建实例,这可能导致导入循环。) ## 表达式
class sympy.core.expr.Expr(*args)
代数表达式的基类。
解释
所有需要定义算术操作的内容应该继承这个类,而不是 Basic
(Basic
应该仅用于参数存储和表达式操作,即模式匹配、替换等)。
如果你想要重写表达式的比较:应该使用 _eval_is_ge 进行不等式比较,或者使用多重分发的 _eval_is_eq。_eval_is_ge 如果 x >= y 则返回 true,如果 x < y 则返回 false,如果两种类型不可比较或比较不确定则返回 None。
另请参阅
sympy.core.basic.Basic
apart(x=None, **args)
参见 sympy.polys 中的 apart
函数。
args_cnc(cset=False, warn=True, split_1=True)
返回 self 的 [可交换因子,非可交换因子]。
解释
self 被视为一个乘积,并且保持因子的顺序。如果 cset
为 True,可交换因子将返回为一个集合。如果有重复因子(如可能发生在未评估的乘积中),则除非显式将 warn
设置为 False,否则会引发错误。
注意:-1 与数字始终分开,除非 split_1 为 False。
示例
>>> from sympy import symbols, oo
>>> A, B = symbols('A B', commutative=0)
>>> x, y = symbols('x y')
>>> (-2*x*y).args_cnc()
[[-1, 2, x, y], []]
>>> (-2.5*x).args_cnc()
[[-1, 2.5, x], []]
>>> (-2*x*A*B*y).args_cnc()
[[-1, 2, x, y], [A, B]]
>>> (-2*x*A*B*y).args_cnc(split_1=False)
[[-2, x, y], [A, B]]
>>> (-2*x*y).args_cnc(cset=True)
[{-1, 2, x, y}, []]
参数始终被视为 Mul:
>>> (-2 + x + A).args_cnc()
[[], [x - 2 + A]]
>>> (-oo).args_cnc() # -oo is a singleton
[[-1, oo], []]
as_coeff_Add(rational=False) → tuple['Number', Expr]
高效地提取求和的系数。
as_coeff_Mul(rational: bool = False) → tuple['Number', Expr]
高效地提取乘积的系数。
as_coeff_add(*deps) → tuple[Expr, tuple[Expr, ...]]
返回元组(c, args),其中 self 被写成 Add,a
。
c 应该是一个 Rational,加到 Add 的任何独立于 deps 的项上。
args 应该是a
的所有其他项的元组;如果 self 是一个 Number 或者 self 独立于 deps(当给定时),args 为空。
当你不确定 self 是否是 Add,但你想要将 self 视为 Add,或者你想要处理 self 尾部的各个参数作为 Add 时,应该使用这个方法。
-
如果你知道 self 是一个 Add 并且只想要头部,使用 self.args[0];
-
如果你不想处理尾部的参数但需要尾部,则使用 self.as_two_terms(),它会给出头部和尾部。
-
如果你想要将 self 分成独立部分和依赖部分,请使用
self.as_independent(*deps)
>>> from sympy import S
>>> from sympy.abc import x, y
>>> (S(3)).as_coeff_add()
(3, ())
>>> (3 + x).as_coeff_add()
(3, (x,))
>>> (3 + x + y).as_coeff_add(x)
(y + 3, (x,))
>>> (3 + y).as_coeff_add(x)
(y + 3, ())
as_coeff_exponent(x) → tuple[Expr, Expr]
c*x**e -> c,e
,其中 x 可以是任何符号表达式。
as_coeff_mul(*deps, **kwargs) → tuple[Expr, tuple[Expr, ...]]
返回元组(c, args),其中 self 被写成 Mul,m
。
c 应该是一个 Rational,乘以任何独立于 deps 的 Mul 的因子。
args 应该是 m 的所有其他因子的元组;如果 self 是一个 Number 或者 self 独立于 deps(当给定时),args 为空。
当你不确定 self 是否是 Mul,但你想要将 self 视为 Mul,或者你想要处理 self 尾部的各个参数作为 Mul 时,应该使用这个方法。
-
如果你知道 self 是一个 Mul 并且只想要头部,使用 self.args[0];
-
如果你不想处理尾部的参数但需要尾部,则使用 self.as_two_terms(),它会给出头部和尾部;
-
如果你想要将 self 分成独立部分和依赖部分,请使用
self.as_independent(*deps)
>>> from sympy import S
>>> from sympy.abc import x, y
>>> (S(3)).as_coeff_mul()
(3, ())
>>> (3*x*y).as_coeff_mul()
(3, (x, y))
>>> (3*x*y).as_coeff_mul(x)
(3*y, (x,))
>>> (3*y).as_coeff_mul(x)
(3*y, ())
as_coefficient(expr)
在给定表达式中提取符号系数。换句话说,这个函数将‘self’分解为‘expr’和‘expr’-free 系数的乘积。如果无法进行这种分解,它将返回 None。
示例
>>> from sympy import E, pi, sin, I, Poly
>>> from sympy.abc import x
>>> E.as_coefficient(E)
1
>>> (2*E).as_coefficient(E)
2
>>> (2*sin(E)*E).as_coefficient(E)
两个项中都有 E,所以返回一个和。(如果希望得到与 E 完全匹配的项的系数,则可以选择返回表达式中的常数。或者,为了更高的精度,可以使用 Poly 的方法指示所需的项,从中获取系数。)
>>> (2*E + x*E).as_coefficient(E)
x + 2
>>> _.args[0] # just want the exact match
2
>>> p = Poly(2*E + x*E); p
Poly(x*E + 2*E, x, E, domain='ZZ')
>>> p.coeff_monomial(E)
2
>>> p.nth(0, 1)
2
由于以下内容无法写成包含 E 作为因子的乘积,因此返回 None。(如果需要系数2*x
,则应该使用coeff
方法。)
>>> (2*E*x + x).as_coefficient(E)
>>> (2*E*x + x).coeff(E)
2*x
>>> (E*(x + 1) + x).as_coefficient(E)
>>> (2*pi*I).as_coefficient(pi*I)
2
>>> (2*I).as_coefficient(pi*I)
另请参阅
coeff
返回具有给定因子的项的和
as_coeff_Add
将一个表达式中的加法常数与表达式分开
as_coeff_Mul
将一个表达式中的乘法常数与表达式分开
as_independent
将依赖于 x 的项/因子与其他项分开
sympy.polys.polytools.Poly.coeff_monomial
高效地找到 Poly 中单项式的单一系数。
sympy.polys.polytools.Poly.nth
类似于coeff_monomial
,但使用了单项式项的幂。
as_coefficients_dict(*syms)
返回一个将项映射到它们的有理系数的字典。由于字典是默认字典,对于不存在的项的查询将返回系数为 0。
如果提供了符号syms
,则独立于它们的任何乘法项将被视为系数,并将返回一个常规字典,其键为依赖于syms
的生成器,值为它们对应的系数。
示例
>>> from sympy.abc import a, x, y
>>> (3*x + a*x + 4).as_coefficients_dict()
{1: 4, x: 3, a*x: 1}
>>> _[a]
0
>>> (3*a*x).as_coefficients_dict()
{a*x: 3}
>>> (3*a*x).as_coefficients_dict(x)
{x: 3*a}
>>> (3*a*x).as_coefficients_dict(y)
{1: 3*a*x}
as_content_primitive(radical=False, clear=True)
此方法应递归地从所有参数中移除有理数,并返回该(内容)和新的self
(primitive)。内容应始终为正,并且Mul(*foo.as_content_primitive()) == foo
。如果可能,原始形式不需要处于规范形式,并且应尽量保留底层结构(即不应将expand_mul
应用于self
)。
示例
>>> from sympy import sqrt
>>> from sympy.abc import x, y, z
>>> eq = 2 + 2*x + 2*y*(3 + 3*y)
as_content_primitive
函数是递归的,并保留结构:
>>> eq.as_content_primitive()
(2, x + 3*y*(y + 1) + 1)
整数幂将从基数中提取有理数:
>>> ((2 + 6*x)**2).as_content_primitive()
(4, (3*x + 1)**2)
>>> ((2 + 6*x)**(2*y)).as_content_primitive()
(1, (2*(3*x + 1))**(2*y))
一旦它们的as_content_primitives
被添加,术语可能最终会合并:
>>> ((5*(x*(1 + y)) + 2*x*(3 + 3*y))).as_content_primitive()
(11, x*(y + 1))
>>> ((3*(x*(1 + y)) + 2*x*(3 + 3*y))).as_content_primitive()
(9, x*(y + 1))
>>> ((3*(z*(1 + y)) + 2.0*x*(3 + 3*y))).as_content_primitive()
(1, 6.0*x*(y + 1) + 3*z*(y + 1))
>>> ((5*(x*(1 + y)) + 2*x*(3 + 3*y))**2).as_content_primitive()
(121, x**2*(y + 1)**2)
>>> ((x*(1 + y) + 0.4*x*(3 + 3*y))**2).as_content_primitive()
(1, 4.84*x**2*(y + 1)**2)
原始的激进内容也可以从原始中分解出来:
>>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive(radical=True)
(2, sqrt(2)*(1 + 2*sqrt(5)))
如果clear=False
(默认为 True),则不会从加法中删除内容,如果可以分布以留下一个或多个具有整数系数的项。
>>> (x/2 + y).as_content_primitive()
(1/2, x + 2*y)
>>> (x/2 + y).as_content_primitive(clear=False)
(1, x/2 + y)
as_expr(*gens)
将多项式转换为 SymPy 表达式。
示例
>>> from sympy import sin
>>> from sympy.abc import x, y
>>> f = (x**2 + x*y).as_poly(x, y)
>>> f.as_expr()
x**2 + x*y
>>> sin(x).as_expr()
sin(x)
as_independent(*deps, **hint) → tuple[Expr, Expr]
对乘积或加法进行大多数简单的分离,其参数不依赖于deps
。要尽可能完整地分离变量,请首先使用分离方法,例如:
-
separatevars()
将乘法、加法和幂(包括指数)转换为乘法 -
.expand(mul=True)
将加法或乘法转换为加法 -
.expand(log=True)
将对数表达式转换为加法。
这里唯一非朴素的事情是尊重变量的非交换顺序,并且无论提示如何,对于零的self
始终返回(0, 0)。
对于非零的self
,返回的元组(i
,d
)有以下解释:
-
i
将没有出现在deps
中的变量。 -
当
self
为加法时,d
将包含包含在deps
中的变量的项,或者等于 0(当self
为加法时)或 1(当self
为乘法时)。 -
如果
self
是一个加法,则self = i + d
。 -
如果
self
是一个乘法,则self = i*d
-
否则返回(
self
,S.One
)或(S.One
,self
)。
要强制表达式被视为加法,使用提示as_Add=True
。
示例
– self
是一个加法
>>> from sympy import sin, cos, exp
>>> from sympy.abc import x, y, z
>>> (x + x*y).as_independent(x)
(0, x*y + x)
>>> (x + x*y).as_independent(y)
(x, x*y)
>>> (2*x*sin(x) + y + x + z).as_independent(x)
(y + z, 2*x*sin(x) + x)
>>> (2*x*sin(x) + y + x + z).as_independent(x, y)
(z, 2*x*sin(x) + x + y)
– self
是一个乘积。
>>> (x*sin(x)*cos(y)).as_independent(x)
(cos(y), x*sin(x))
当self
为乘法时,非交换术语并非总是可以分离出来
>>> from sympy import symbols
>>> n1, n2, n3 = symbols('n1 n2 n3', commutative=False)
>>> (n1 + n1*n2).as_independent(n2)
(n1, n1*n2)
>>> (n2*n1 + n1*n2).as_independent(n2)
(0, n1*n2 + n2*n1)
>>> (n1*n2*n3).as_independent(n1)
(1, n1*n2*n3)
>>> (n1*n2*n3).as_independent(n2)
(n1, n2*n3)
>>> ((x-n1)*(x-y)).as_independent(x)
(1, (x - y)*(x - n1))
– self
是其他任何东西:
>>> (sin(x)).as_independent(x)
(1, sin(x))
>>> (sin(x)).as_independent(y)
(sin(x), 1)
>>> exp(x+y).as_independent(x)
(1, exp(x + y))
– 强制self
被视为加法:
>>> (3*x).as_independent(x, as_Add=True)
(0, 3*x)
– 强制self
被视为乘法:
>>> (3+x).as_independent(x, as_Add=False)
(1, x + 3)
>>> (-3+x).as_independent(x, as_Add=False)
(1, x - 3)
注意以下与上面不同的地方在于使依赖项术语上的常数为正。
>>> (y*(-3+x)).as_independent(x)
(y, x - 3)
– 对真独立性测试使用 .as_independent()
.has() 的例子。前者仅考虑自由符号中的符号,而后者考虑所有符号
>>> from sympy import Integral
>>> I = Integral(x, (x, 1, 2))
>>> I.has(x)
True
>>> x in I.free_symbols
False
>>> I.as_independent(x) == (I, 1)
True
>>> (I + x).as_independent(x) == (I, x)
True
注意:在尝试获取独立项时,可能需要先使用分离方法。在这种情况下,重要的是跟踪您发送到此例程的内容,以便知道如何解释返回的值
>>> from sympy import separatevars, log
>>> separatevars(exp(x+y)).as_independent(x)
(exp(y), exp(x))
>>> (x + x*y).as_independent(y)
(x, x*y)
>>> separatevars(x + x*y).as_independent(y)
(x, y + 1)
>>> (x*(1 + y)).as_independent(y)
(x, y + 1)
>>> (x*(1 + y)).expand(mul=True).as_independent(y)
(x, x*y)
>>> a, b=symbols('a b', positive=True)
>>> (log(a*b).expand(log=True)).as_independent(b)
(log(a), log(b))
另请参阅
separatevars
, expand_log
, sympy.core.add.Add.as_two_terms
, sympy.core.mul.Mul.as_two_terms
, as_coeff_mul
as_leading_term(*symbols, logx=None, cdir=0)
返回 self 的主导(非零)系列展开项。
_eval_as_leading_term 例程用于此目的,并且它们必须始终返回非零值。
示例
>>> from sympy.abc import x
>>> (1 + x + x**2).as_leading_term(x)
1
>>> (1/x**2 + x + x**2).as_leading_term(x)
x**(-2)
as_numer_denom()
返回表达式的分子和分母。
表达式 -> a/b -> a, b
这只是一个存根,应由对象的类方法定义以获取任何其他内容。
另请参阅
normal
返回 a/b
而不是 (a, b)
as_ordered_factors(order=None)
返回有序因子列表(如果是 Mul),否则返回 [self]。
as_ordered_terms(order=None, data=False)
将表达式转换为项的有序列表。
示例
>>> from sympy import sin, cos
>>> from sympy.abc import x
>>> (sin(x)**2*cos(x) + sin(x)**2 + 1).as_ordered_terms()
[sin(x)**2*cos(x), sin(x)**2, 1]
as_poly(*gens, **args)
将 self
转换为多项式或返回 None
。
解释
>>> from sympy import sin
>>> from sympy.abc import x, y
>>> print((x**2 + x*y).as_poly())
Poly(x**2 + x*y, x, y, domain='ZZ')
>>> print((x**2 + x*y).as_poly(x, y))
Poly(x**2 + x*y, x, y, domain='ZZ')
>>> print((x**2 + sin(y)).as_poly(x, y))
None
as_powers_dict()
将 self 作为因子的字典返回,其中每个因子都被视为一个幂。键是因子的基数,而值是相应的指数。如果表达式是 Mul 并包含非交换因子,则应谨慎使用结果字典,因为它们出现的顺序将在字典中丢失。
另请参阅
as_ordered_factors
用于非交换应用的替代方法,返回因子的有序列表。
args_cnc
类似于 as_ordered_factors,但保证将交换和非交换因子分开。
as_real_imag(deep=True, **hints)
对 self
执行复杂展开,并返回一个包含实部和虚部的元组。此方法不能与 re() 和 im() 函数混淆,后者在评估时不进行复杂展开。
然而,可以展开 re() 和 im() 函数,并且与调用此函数一次获得完全相同的结果。
>>> from sympy import symbols, I
>>> x, y = symbols('x,y', real=True)
>>> (x + y*I).as_real_imag()
(x, y)
>>> from sympy.abc import z, w
>>> (z + w*I).as_real_imag()
(re(z) - im(w), re(w) + im(z))
as_terms()
将表达式转换为项列表。
aseries(x=None, n=6, bound=0, hir=False)
自我的渐近级数展开。这相当于 self.series(x, oo, n)
。
参数:
self : 表达式
要展开其级数的表达式。
x : 符号
它是要计算的表达式的变量。
n : 值
用于表示以
x**n
为单位的顺序的值,直到展开系列。
hir:布尔值
将此参数设置为 True 以生成分层系列。它在早期阶段停止递归,并可能提供更漂亮和更有用的结果。
bound:值,整数
使用
bound
参数来给出其规范形式中重写系数的限制。
返回:
表达式
表达式的渐近级数展开。
示例
>>> from sympy import sin, exp
>>> from sympy.abc import x
>>> e = sin(1/x + exp(-x)) - sin(1/x)
>>> e.aseries(x)
(1/(24*x**4) - 1/(2*x**2) + 1 + O(x**(-6), (x, oo)))*exp(-x)
>>> e.aseries(x, n=3, hir=True)
-exp(-2*x)*sin(1/x)/2 + exp(-x)*cos(1/x) + O(exp(-3*x), (x, oo))
>>> e = exp(exp(x)/(1 - 1/x))
>>> e.aseries(x)
exp(exp(x)/(1 - 1/x))
>>> e.aseries(x, bound=3)
exp(exp(x)/x**2)*exp(exp(x)/x)*exp(-exp(x) + exp(x)/(1 - 1/x) - exp(x)/x - exp(x)/x**2)*exp(exp(x))
对于有理表达式,此方法可能返回原始表达式而不带有 Order 项。 >>> (1/x).aseries(x, n=8) 1/x
注意
此算法直接来源于 Gruntz 提供的限制计算算法,主要使用 mrv 和 rewrite 子例程。该算法的整体思想首先是查找给定表达式 f 的最快变化子表达式 w,然后在 w 的系列中展开 f。然后同样的事情递归地在主导系数上进行,直到获得常数系数。
如果给定表达式 f 的最快变化子表达式是 f 本身,则算法尝试找到 mrv 集的规范表示,并使用此规范表示重写 f。
如果展开包含顺序项,则其将是O(x ** (-n))
或O(w ** (-n))
,其中w
属于self
的最快变化表达式。
参见
Expr.aseries
请参阅此包装器的文档字符串以获取完整详细信息。
参考资料
[R119]
Gruntz, Dominik. A new algorithm for computing asymptotic series. In: Proc. 1993 Int. Symp. Symbolic and Algebraic Computation. 1993. pp. 239-244.
[R120]
Gruntz thesis - p90
[R121]
en.wikipedia.org/wiki/Asymptotic_expansion
cancel(*gens, **args)
请参阅 sympy.polys 中的 cancel 函数
coeff(x, n=1, right=False, _first=True)
返回包含x**n
的术语中的系数。如果n
为零,则将返回所有独立于x
的术语。
解释
当x
是非交换时,可以返回x
左侧(默认)或右侧的系数。当x
是交换时,关键字‘right’被忽略。
示例
>>> from sympy import symbols
>>> from sympy.abc import x, y, z
您可以选择具有明确负数的项:
>>> (-x + 2*y).coeff(-1)
x
>>> (x - 2*y).coeff(-1)
2*y
您可以选择没有有理系数的项:
>>> (x + 2*y).coeff(1)
x
>>> (3 + 2*x + 4*x**2).coeff(1)
0
您可以通过将 n=0 使 x 独立选择项;在这种情况下,将返回 expr.as_independent(x)[0](而不是 None 将返回 0):
>>> (3 + 2*x + 4*x**2).coeff(x, 0)
3
>>> eq = ((x + 1)**3).expand() + 1
>>> eq
x**3 + 3*x**2 + 3*x + 2
>>> [eq.coeff(x, i) for i in reversed(range(4))]
[1, 3, 3, 2]
>>> eq -= 2
>>> [eq.coeff(x, i) for i in reversed(range(4))]
[1, 3, 3, 0]
您可以选择具有数字项的项:
>>> (-x - 2*y).coeff(2)
-y
>>> from sympy import sqrt
>>> (x + sqrt(2)*x).coeff(sqrt(2))
x
匹配是精确的:
>>> (3 + 2*x + 4*x**2).coeff(x)
2
>>> (3 + 2*x + 4*x**2).coeff(x**2)
4
>>> (3 + 2*x + 4*x**2).coeff(x**3)
0
>>> (z*(x + y)**2).coeff((x + y)**2)
z
>>> (z*(x + y)**2).coeff(x + y)
0
此外,没有进行因式分解,因此1 + z*(1 + y)
不是从以下获得的:
>>> (x + z*(x + x*y)).coeff(x)
1
如果需要进行此类因式分解,可以先使用 factor_terms:
>>> from sympy import factor_terms
>>> factor_terms(x + z*(x + x*y)).coeff(x)
z*(y + 1) + 1
>>> n, m, o = symbols('n m o', commutative=False)
>>> n.coeff(n)
1
>>> (3*n).coeff(n)
3
>>> (n*m + m*n*m).coeff(n) # = (1 + m)*n*m
1 + m
>>> (n*m + m*n*m).coeff(n, right=True) # = (1 + m)*n*m
m
如果存在多个可能的系数,则返回 0:
>>> (n*m + m*n).coeff(n)
0
如果只有一个可能的系数,则返回它:
>>> (n*m + x*m*n).coeff(m*n)
x
>>> (n*m + x*m*n).coeff(m*n, right=1)
1
参见
as_coefficient
将表达式分解为系数和因子
as_coeff_Add
将一个表达式中的加法常数与其分开
as_coeff_Mul
将乘法常数与表达式分开
as_independent
将 x 相关的项/因子与其他项分开
sympy.polys.polytools.Poly.coeff_monomial
在 Poly 中高效地找到单项式的单一系数
sympy.polys.polytools.Poly.nth
类似于 coeff_monomial,但使用单项式项的幂
collect(syms, func=None, evaluate=True, exact=False, distribute_order_term=True)
查看 sympy.simplify 中的 collect 函数
combsimp()
查看 sympy.simplify 中的 combsimp 函数
compute_leading_term(x, logx=None)
弃用的函数,用于计算系列的主导项。
as_leading_term 仅允许用于.series()的结果,这是计算系列的包装器。
conjugate()
返回‘self’的复共轭。
could_extract_minus_sign()
如果自身具有-1 作为主要因子或者在求和中负号的字面意义比正号多,则返回 True,否则返回 False。
示例
>>> from sympy.abc import x, y
>>> e = x - y
>>> {i.could_extract_minus_sign() for i in (e, -e)}
{False, True}
虽然y - x
被视为-(x - y)
,因为它在没有-1 主要因子的情况下是一个乘积,所以下面的结果是错误的:
>>> (x*(y - x)).could_extract_minus_sign()
False
要将某物放入与符号相关的规范形式,请使用(signsimp):
>>> from sympy import signsimp
>>> signsimp(x*(y - x))
-x*(x - y)
>>> _.could_extract_minus_sign()
True
equals(other, failing_expression=False)
如果 self == other,则返回 True,如果不是,则返回 False 或 None。如果 failing_expression 为 True,则会返回未简化为 0 的表达式,而不是 None。
解释
如果self
是一个非零的数(或复数),则结果为 False。
如果self
是一个数字且未评估为零,则将使用 evalf 来测试表达式是否评估为零。如果是这样,并且结果具有显著性(即精度为-1,用于有理数结果,或大于 1),则将使用 evalf 值来返回 True 或 False。
expand(deep=True, modulus=None, power_base=True, power_exp=True, mul=True, log=True, multinomial=True, basic=True, **hints)
使用提示扩展表达式。
查看 sympy.core.function 中 expand()函数的文档字符串以获取更多信息。
property expr_free_symbols
类似于free_symbols
,但仅在它们包含在表达式节点中时返回自由符号。
示例
>>> from sympy.abc import x, y
>>> (x + y).expr_free_symbols
{x, y}
如果表达式包含在非表达式对象中,则不返回自由符号。比较:
>>> from sympy import Tuple
>>> t = Tuple(x + y)
>>> t.expr_free_symbols
set()
>>> t.free_symbols
{x, y}
extract_additively(c)
如果可以从 self 中减去 c 并使所有匹配系数向零移动,则返回 self - c,否则返回 None。
示例
>>> from sympy.abc import x, y
>>> e = 2*x + 3
>>> e.extract_additively(x + 1)
x + 2
>>> e.extract_additively(3*x)
>>> e.extract_additively(4)
>>> (y*(x + 1)).extract_additively(x + 1)
>>> ((x + 1)*(x + 2*y + 1) + 3).extract_additively(x + 1)
(x + 1)*(x + 2*y) + 3
另请参阅
extract_multiplicatively
,coeff
,as_coefficient
extract_branch_factor(allow_half=False)
尝试以良好的方式将 self 写成exp_polar(2*pi*I*n)*z
。返回(z, n)。
>>> from sympy import exp_polar, I, pi
>>> from sympy.abc import x, y
>>> exp_polar(I*pi).extract_branch_factor()
(exp_polar(I*pi), 0)
>>> exp_polar(2*I*pi).extract_branch_factor()
(1, 1)
>>> exp_polar(-pi*I).extract_branch_factor()
(exp_polar(I*pi), -1)
>>> exp_polar(3*pi*I + x).extract_branch_factor()
(exp_polar(x + I*pi), 1)
>>> (y*exp_polar(-5*pi*I)*exp_polar(3*pi*I + 2*pi*x)).extract_branch_factor()
(y*exp_polar(2*pi*x), -1)
>>> exp_polar(-I*pi/2).extract_branch_factor()
(exp_polar(-I*pi/2), 0)
如果 allow_half 为 True,则还提取 exp_polar(I*pi):
>>> exp_polar(I*pi).extract_branch_factor(allow_half=True)
(1, 1/2)
>>> exp_polar(2*I*pi).extract_branch_factor(allow_half=True)
(1, 1)
>>> exp_polar(3*I*pi).extract_branch_factor(allow_half=True)
(1, 3/2)
>>> exp_polar(-I*pi).extract_branch_factor(allow_half=True)
(1, -1/2)
extract_multiplicatively(c)
如果无法以一种良好的方式使 self 成为 c * something 的形式(即保留 self 参数的性质),则返回 None。
示例
>>> from sympy import symbols, Rational
>>> x, y = symbols('x,y', real=True)
>>> ((x*y)**3).extract_multiplicatively(x**2 * y)
x*y**2
>>> ((x*y)**3).extract_multiplicatively(x**4 * y)
>>> (2*x).extract_multiplicatively(2)
x
>>> (2*x).extract_multiplicatively(3)
>>> (Rational(1, 2)*x).extract_multiplicatively(3)
x/6
factor(*gens, **args)
参见 sympy.polys.polytools 中的 factor() 函数
fourier_series(limits=None)
计算 self 的 Fourier 正/余弦级数。
参见 sympy.series.fourier 中的 fourier_series()
的文档字符串,详见。
fps(x=None, x0=0, dir=1, hyper=True, order=4, rational=True, full=False)
计算 self 的形式幂级数。
参见 fps()
函数的文档字符串,详见 sympy.series.formal。
gammasimp()
参见 sympy.simplify 中的 gammasimp 函数
getO()
如果存在加法 O(..) 符号则返回,否则返回 None。
getn()
返回表达式的次序。
说明
次序由 O(…) 项决定。如果没有 O(…) 项,则返回 None。
示例
>>> from sympy import O
>>> from sympy.abc import x
>>> (1 + x + O(x**2)).getn()
2
>>> (1 + x).getn()
integrate(*args, **kwargs)
参见 sympy.integrals 中的 integrate 函数
invert(g, *gens, **args)
返回 self
对 g
的模乘逆,其中 self
(和 g
)可能是符号表达式。
参见也
sympy.core.intfunc.mod_inverse
, sympy.polys.polytools.invert
is_algebraic_expr(*syms)
测试给定表达式在给定符号 syms 中是否是代数的。当未给定 syms 时,将使用所有自由符号。有理函数不必以展开或任何规范形式出现。
对于具有符号指数的“代数表达式”,此函数返回 False。这是对 is_rational_function 的简单扩展,包括有理数指数。
示例
>>> from sympy import Symbol, sqrt
>>> x = Symbol('x', real=True)
>>> sqrt(1 + x).is_rational_function()
False
>>> sqrt(1 + x).is_algebraic_expr()
True
该函数不会尝试进行任何非平凡简化,这可能会导致一个看起来不是代数表达式的表达式变成代数表达式。
>>> from sympy import exp, factor
>>> a = sqrt(exp(x)**2 + 2*exp(x) + 1)/(exp(x) + 1)
>>> a.is_algebraic_expr(x)
False
>>> factor(a).is_algebraic_expr()
True
参见也
is_rational_function
参考文献
[R122]
en.wikipedia.org/wiki/Algebraic_expression
is_constant(*wrt, **flags)
如果 self 是常数则返回 True,如果不是则返回 False,如果无法确定是否常数则返回 None。
说明
如果一个表达式没有自由符号则它是一个常数。如果有自由符号则可能是一个常数,也许(但不一定)是零。为了测试这样的表达式,尝试了几种策略:
- 在两个随机点的数值评估。如果两个评估给出不同的值,并且这些值的精度大于 1,则 self 不是常数。如果评估结果一致或无法获得任何精度,则不做决定。只有在
wrt
与自由符号不同时才进行数值测试。
2)相对于‘wrt’中的变量(或者如果省略,则相对于所有自由符号)的微分,以查看表达式是否恒定。即使表达式是恒定的(请参见 test_expr.py 中添加的测试),这也不总是导致一个表达式为零。如果所有导数都为零,则 self 相对于给定符号是常数。
3)找出具有自由符号的分母表达式的零点。如果有零点,则它将不是常数。对于不是常数的表达式,它给出更多的负面答案。
如果既不能评估也不能区分表达式是否恒定,则返回 None,除非两个数值恰好相同且标志failing_number
为 True – 在这种情况下,将返回数值。
如果传递了标志 simplify=False,self 将不会被简化;默认值为 True,因为在测试之前应该简化 self。
示例
>>> from sympy import cos, sin, Sum, S, pi
>>> from sympy.abc import a, n, x, y
>>> x.is_constant()
False
>>> S(2).is_constant()
True
>>> Sum(x, (x, 1, 10)).is_constant()
True
>>> Sum(x, (x, 1, n)).is_constant()
False
>>> Sum(x, (x, 1, n)).is_constant(y)
True
>>> Sum(x, (x, 1, n)).is_constant(n)
False
>>> Sum(x, (x, 1, n)).is_constant(x)
True
>>> eq = a*cos(x)**2 + a*sin(x)**2 - a
>>> eq.is_constant()
True
>>> eq.subs({x: pi, a: 2}) == eq.subs({x: pi, a: 3}) == 0
True
>>> (0**x).is_constant()
False
>>> x.is_constant()
False
>>> (x**x).is_constant()
False
>>> one = cos(x)**2 + sin(x)**2
>>> one.is_constant()
True
>>> ((one - 1)**(x + 1)).is_constant() in (True, False) # could be 0 or 1
True
is_meromorphic(x, a)
这测试一个表达式在给定符号x
在点a
处作为函数是否是亚黎函数。
此方法旨在作为一个快速测试,如果没有简化或更详细的分析,将返回 None。
示例
>>> from sympy import zoo, log, sin, sqrt
>>> from sympy.abc import x
>>> f = 1/x**2 + 1 - 2*x**3
>>> f.is_meromorphic(x, 0)
True
>>> f.is_meromorphic(x, 1)
True
>>> f.is_meromorphic(x, zoo)
True
>>> g = x**log(3)
>>> g.is_meromorphic(x, 0)
False
>>> g.is_meromorphic(x, 1)
True
>>> g.is_meromorphic(x, zoo)
False
>>> h = sin(1/x)*x**2
>>> h.is_meromorphic(x, 0)
False
>>> h.is_meromorphic(x, 1)
True
>>> h.is_meromorphic(x, zoo)
True
多值函数被认为是亚黎函数,当它们的分支是亚黎函数时。因此,大多数函数在除了基本奇异点和分支点以外的任何地方都是亚黎函数。特别是,在分支切线上也将是亚黎函数,除了在其端点处。
>>> log(x).is_meromorphic(x, -1)
True
>>> log(x).is_meromorphic(x, 0)
False
>>> sqrt(x).is_meromorphic(x, -1)
True
>>> sqrt(x).is_meromorphic(x, 0)
False
property is_number
如果self
没有自由符号和未定义函数(具体是 AppliedUndef),则返回 True。这将比if not self.free_symbols
更快,因为一旦遇到自由符号或未定义函数,is_number
将失败。
示例
>>> from sympy import Function, Integral, cos, sin, pi
>>> from sympy.abc import x
>>> f = Function('f')
>>> x.is_number
False
>>> f(1).is_number
False
>>> (2*x).is_number
False
>>> (2 + Integral(2, x)).is_number
False
>>> (2 + Integral(2, (x, 1, 2))).is_number
True
并非所有的数字在 SymPy 的意义上都是数字:
>>> pi.is_number, pi.is_Number
(True, False)
如果某个东西是一个数,它应该评估为一个具有实部和虚部的数;然而,结果可能不可比较,因为结果的实部和/或虚部可能没有精度。
>>> cos(1).is_number and cos(1).is_comparable
True
>>> z = cos(1)**2 + sin(1)**2 - 1
>>> z.is_number
True
>>> z.is_comparable
False
参见
sympy.core.basic.Basic.is_comparable
is_polynomial(*syms)
如果 self 是 syms 中的一个多项式,则返回 True,否则返回 False。
这检查 self 是否是 syms 中的一个精确多项式。对于具有符号指数的“多项式”表达式,此函数返回 False。因此,你应该能够对返回 True 的表达式应用多项式算法,并且如果 expr.is_polynomial(*syms)返回 True,则 Poly(expr, *syms)应该工作。多项式不必处于展开形式。如果没有给出符号,则表达式中的所有自由符号都将被使用。
这不是假设系统的一部分。你不能做 Symbol(‘z’, polynomial=True)。
示例
>>> from sympy import Symbol, Function
>>> x = Symbol('x')
>>> ((x**2 + 1)**4).is_polynomial(x)
True
>>> ((x**2 + 1)**4).is_polynomial()
True
>>> (2**x + 1).is_polynomial(x)
False
>>> (2**x + 1).is_polynomial(2**x)
True
>>> f = Function('f')
>>> (f(x) + 1).is_polynomial(x)
False
>>> (f(x) + 1).is_polynomial(f(x))
True
>>> (1/f(x) + 1).is_polynomial(f(x))
False
>>> n = Symbol('n', nonnegative=True, integer=True)
>>> (x**n + 1).is_polynomial(x)
False
此函数不会尝试任何可能导致一个表达式成为多项式但看起来不是多项式的非平凡简化。
>>> from sympy import sqrt, factor, cancel
>>> y = Symbol('y', positive=True)
>>> a = sqrt(y**2 + 2*y + 1)
>>> a.is_polynomial(y)
False
>>> factor(a)
y + 1
>>> factor(a).is_polynomial(y)
True
>>> b = (y**2 + 2*y + 1)/(y + 1)
>>> b.is_polynomial(y)
False
>>> cancel(b)
y + 1
>>> cancel(b).is_polynomial(y)
True
参见 .is_rational_function()
is_rational_function(*syms)
测试函数是否为给定符号 syms 中的两个多项式的比率。当未给出 syms 时,将使用所有自由符号。有理函数不必处于扩展或任何规范形式中。
对于具有符号指数的“有理函数”表达式,此函数返回 False。因此,您应该能够调用.as_numer_denom()并对结果应用多项式算法,以便对此返回 True 的表达式进行操作。
这不是假设系统的一部分。您无法执行 Symbol('z',rational_function=True)。
示例
>>> from sympy import Symbol, sin
>>> from sympy.abc import x, y
>>> (x/y).is_rational_function()
True
>>> (x**2).is_rational_function()
True
>>> (x/sin(y)).is_rational_function(y)
False
>>> n = Symbol('n', integer=True)
>>> (x**n + 1).is_rational_function(x)
False
此函数不尝试对可能导致表达式不是有理函数的非平凡简化进行任何简化。
>>> from sympy import sqrt, factor
>>> y = Symbol('y', positive=True)
>>> a = sqrt(y**2 + 2*y + 1)/y
>>> a.is_rational_function(y)
False
>>> factor(a)
(y + 1)/y
>>> factor(a).is_rational_function(y)
True
另请参见is_algebraic_expr()
。
leadterm(x, logx=None, cdir=0)
返回作为元组(a, b)
的主导项a*x**b
。
示例
>>> from sympy.abc import x
>>> (1+x+x**2).leadterm(x)
(1, 0)
>>> (1/x**2+x+x**2).leadterm(x)
(1, -2)
limit(x, xlim, dir='+')
计算极限 x->xlim。
lseries(x=None, x0=0, dir='+', logx=None, cdir=0)
系列的项的迭代器的系列的包装器。
注意:无限系列将产生无限迭代器。例如,以下示例将永远不会终止。它将继续打印 sin(x)系列的项:
for term in sin(x).lseries(x):
print term
lseries()
比nseries()
的优点在于,很多时候你只是对系列中的下一个项感兴趣(即例如第一个项),但你不知道应该在nseries()
中使用“n”参数询问多少个项。
另请参见nseries()
。
normal()
返回表达式作为分数。
表达式 -> a/b
另请参见
as_numer_denom
返回(a, b)
而不是a/b
nseries(x=None, x0=0, n=6, dir='+', logx=None, cdir=0)
如果假设允许,则是到_eval_nseries
的包装,否则到系列。
如果给定 x,x0 为 0,dir='+',并且 self 具有 x,则调用 _eval_nseries。这会在最内层表达式中计算“n”个项,然后通过“交叉乘法”构建最终系列。
可选的logx
参数可用于在返回的系列中替换任何 log(x)为符号值,以避免在 0 处评估 log(x)。应提供用于替代 log(x)的符号。
优点 - 它很快,因为我们不必提前确定需要计算多少项。
缺点 - 您可能得到比预期更少的术语,但始终附加正确的 O(x**n)项,因此结果,尽管可能更短,也将是正确的。
如果这些假设中的任何一个不符合,则此功能将被视为对 series 的包装器,后者将尝试更努力返回正确数量的项。
另请参见lseries()
。
示例
>>> from sympy import sin, log, Symbol
>>> from sympy.abc import x, y
>>> sin(x).nseries(x, 0, 6)
x - x**3/6 + x**5/120 + O(x**6)
>>> log(x+1).nseries(x, 0, 5)
x - x**2/2 + x**3/3 - x**4/4 + O(x**5)
处理logx
参数 - 在以下示例中,展开失败,因为sin
在-oo 处没有渐近展开(当 log(x)作为 x 趋近于 0 的极限时):
>>> e = sin(log(x))
>>> e.nseries(x, 0, 6)
Traceback (most recent call last):
...
PoleError: ...
...
>>> logx = Symbol('logx')
>>> e.nseries(x, 0, 6, logx=logx)
sin(logx)
在下面的例子中,展开有效,但只有在使用logx
参数时才返回自身:
>>> e = x**y
>>> e.nseries(x, 0, 2)
x**y
>>> e.nseries(x, 0, 2, logx=logx)
exp(logx*y)
nsimplify(constants=(), tolerance=None, full=False)
请参阅 sympy.simplify 中的 nsimplify 函数
powsimp(*args, **kwargs)
请参阅 sympy.simplify 中的 powsimp 函数
primitive()
返回可以从每个项中非递归提取的正有理数(即,将 self 视为 Add)。这类似于 as_coeff_Mul() 方法,但 primitive 总是提取正有理数(不提取负数或浮点数)。
示例
>>> from sympy.abc import x
>>> (3*(x + 1)**2).primitive()
(3, (x + 1)**2)
>>> a = (6*x + 2); a.primitive()
(2, 3*x + 1)
>>> b = (x/2 + 3); b.primitive()
(1/2, x + 6)
>>> (a*b).primitive() == (1, a*b)
True
radsimp(**kwargs)
参见 sympy.simplify 中的 radsimp 函数
ratsimp()
参见 sympy.simplify 中的 ratsimp 函数
removeO()
如果存在,移除加法 O(..) 符号
round(n=None)
返回到给定小数位数的 x 的四舍五入值。
如果结果是复数,则对该数的实部和虚部应用 round。
示例
>>> from sympy import pi, E, I, S, Number
>>> pi.round()
3
>>> pi.round(2)
3.14
>>> (2*pi + E*I).round()
6 + 3*I
round 方法具有截断效应:
>>> (2*pi + I/10).round()
6
>>> (pi/10 + 2*I).round()
2*I
>>> (pi/10 + E*I).round(2)
0.31 + 2.72*I
注释
Python 的 round
函数使用 SymPy 的 round
方法,因此它始终返回 SymPy 数字(而不是 Python 的浮点数或整数):
>>> isinstance(round(S(123), -2), Number)
True
separate(deep=False, force=False)
参见 sympy.simplify 中的 separate 函数
series(x=None, x0=0, n=6, dir='+', logx=None, cdir=0)
关于 x = x0
的“自我”级数展开,要么按需逐个给出级数项(当 n=None 时是懒惰级数),要么在 n != None 时一次性给出所有项。
返回以 x = x0
点为中心,关于 x
展开到 O((x - x0)**n, x, x0)
的级数展开(默认 n 为 6)。
如果 x=None
并且 self
是一元符号,则会提供该一元符号,否则会引发错误。
参数:
expr :表达式
要展开其级数的表达式。
x :符号
它是要计算的表达式的变量。
x0 :数值
计算
x
的值。可以是从-oo
到oo
的任何值。
n :数值
表示按
x**n
展开级数的阶数,展开到该阶数。
dir :字符串,可选
级数展开可以是双向的。如果
dir="+"
,则 (x->x0+)。如果pydir="-", then (x->x0-). For infinite ``x0
(oo
或-oo
),则dir
参数从无穷大的方向确定(例如对于oo
,dir="-"
)。
logx :可选
用于将返回的级数中的任何 log(x) 替换为符号值,而不是计算实际值。
cdir :可选
它代表复杂方向,并指示需要从哪个方向评估展开。
返回:
Expr :表达式
关于 x0 的表达式的级数展开
异常:
TypeError
如果“n”和“x0”是无穷对象
PoleError
如果“x0”是一个无限对象
示例
>>> from sympy import cos, exp, tan
>>> from sympy.abc import x, y
>>> cos(x).series()
1 - x**2/2 + x**4/24 + O(x**6)
>>> cos(x).series(n=4)
1 - x**2/2 + O(x**4)
>>> cos(x).series(x, x0=1, n=2)
cos(1) - (x - 1)*sin(1) + O((x - 1)**2, (x, 1))
>>> e = cos(x + exp(y))
>>> e.series(y, n=2)
cos(x + 1) - y*sin(x + 1) + O(y**2)
>>> e.series(x, n=2)
cos(exp(y)) - x*sin(exp(y)) + O(x**2)
如果 n=None
,则将返回级数项的生成器。
>>> term=cos(x).series(n=None)
>>> [next(term) for i in range(2)]
[1, -x**2/2]
对于 dir=+
(默认),从右侧计算级数;对于 dir=-
,从左侧计算级数。对于光滑函数,此标志不会改变结果。
>>> abs(x).series(dir="+")
x
>>> abs(x).series(dir="-")
-x
>>> f = tan(x)
>>> f.series(x, 2, 6, "+")
tan(2) + (1 + tan(2)**2)*(x - 2) + (x - 2)**2*(tan(2)**3 + tan(2)) +
(x - 2)**3*(1/3 + 4*tan(2)**2/3 + tan(2)**4) + (x - 2)**4*(tan(2)**5 +
5*tan(2)**3/3 + 2*tan(2)/3) + (x - 2)**5*(2/15 + 17*tan(2)**2/15 +
2*tan(2)**4 + tan(2)**6) + O((x - 2)**6, (x, 2))
>>> f.series(x, 2, 3, "-")
tan(2) + (2 - x)*(-tan(2)**2 - 1) + (2 - x)**2*(tan(2)**3 + tan(2))
+ O((x - 2)**3, (x, 2))
对于有理表达式,此方法可能返回原始表达式而不包括 Order 项。>>> (1/x).series(x, n=8) 1/x
taylor_term(n, x, *previous_terms)
泰勒级数项的通用方法。
该方法速度较慢,因为需要 n 次求导。子类可以重新定义此方法,通过使用“previous_terms”使其更快。
together(*args, **kwargs)
参见 sympy.polys 中的 together 函数
trigsimp(**args)
参见 sympy.simplify 中的 trigsimp 函数
class sympy.core.expr.UnevaluatedExpr(arg, **kwargs)
除非释放,否则不计算的表达式。
示例
>>> from sympy import UnevaluatedExpr
>>> from sympy.abc import x
>>> x*(1/x)
1
>>> x*UnevaluatedExpr(1/x)
x*1/x
class sympy.core.expr.AtomicExpr(*args)
既是原子又是 Exprs 的对象的父类。
例如:Symbol, Number, Rational, Integer, … 但不包括:Add, Mul, Pow, … ## symbol
class sympy.core.symbol.Symbol(name, **assumptions)
Symbol 类用于创建符号变量。
参数:
AtomicExpr:变量名称
布尔值:带有布尔值(True 或 False)的假设
解释
符号变量是数学符号的占位符,可以表示数字、常数或任何其他数学实体,并可用于数学表达式和进行符号计算。
假设:
commutative = True positive = True real = True imaginary = True complex = True 完整列表的更多假设- 谓词
您可以在构造函数中覆盖默认假设。
示例
>>> from sympy import Symbol
>>> x = Symbol("x", positive=True)
>>> x.is_positive
True
>>> x.is_negative
False
传入希腊字母:
>>> from sympy import Symbol
>>> alpha = Symbol('alpha')
>>> alpha
α
尾随数字会自动视为前面名称中的下标。向符号添加下标的一般格式:<var_name> = Symbol('<symbol_name>_
>>> from sympy import Symbol
>>> alpha_i = Symbol('alpha_i')
>>> alpha_i
αᵢ
class sympy.core.symbol.Wild(name, exclude=(), properties=(), **assumptions)
Wild 符号可以匹配任何东西,或者不包含明确排除的内容。
参数:
name : 字符串
Wild 实例的名称。
exclude : 可迭代对象,可选
exclude
中的实例将不会被匹配。
properties : 函数的可迭代集合,可选
函数,每个函数以表达式作为输入并返回一个
bool
值。properties
中的所有函数都需要返回True
,以便 Wild 实例能够匹配表达式。
示例
>>> from sympy import Wild, WildFunction, cos, pi
>>> from sympy.abc import x, y, z
>>> a = Wild('a')
>>> x.match(a)
{a_: x}
>>> pi.match(a)
{a_: pi}
>>> (3*x**2).match(a*x)
{a_: 3*x}
>>> cos(x).match(a)
{a_: cos(x)}
>>> b = Wild('b', exclude=[x])
>>> (3*x**2).match(b*x)
>>> b.match(a)
{a_: b_}
>>> A = WildFunction('A')
>>> A.match(a)
{a_: A_}
提示
使用 Wild 时,请确保使用 exclude 关键字使模式更精确。没有 exclude 模式,您可能会获得在技术上正确但不符合预期的匹配项。例如,使用上述情况而没有 exclude:
>>> from sympy import symbols
>>> a, b = symbols('a b', cls=Wild)
>>> (2 + 3*y).match(a*x + b*y)
{a_: 2/x, b_: 3}
这在技术上是正确的,因为(2/x)x + 3y == 2 + 3*y,但您可能希望它根本不匹配。问题在于,您实际上不希望 a 和 b 包含 x 和 y,并且 exclude 参数允许您精确指定这一点。使用 exclude 参数,该模式将不会匹配。
>>> a = Wild('a', exclude=[x, y])
>>> b = Wild('b', exclude=[x, y])
>>> (2 + 3*y).match(a*x + b*y)
Exclude 还有助于消除匹配的歧义。
>>> E = 2*x**3*y*z
>>> a, b = symbols('a b', cls=Wild)
>>> E.match(a*b)
{a_: 2*y*z, b_: x**3}
>>> a = Wild('a', exclude=[x, y])
>>> E.match(a*b)
{a_: z, b_: 2*x**3*y}
>>> a = Wild('a', exclude=[x, y, z])
>>> E.match(a*b)
{a_: 2, b_: x**3*y*z}
Wild 也接受一个properties
参数:
>>> a = Wild('a', properties=[lambda k: k.is_Integer])
>>> E.match(a*b)
{a_: 2, b_: x**3*y*z}
class sympy.core.symbol.Dummy(name=None, dummy_index=None, **assumptions)
Dummy 符号是唯一的,即使它们具有相同的名称:
示例
>>> from sympy import Dummy
>>> Dummy("x") == Dummy("x")
False
如果未提供名称,则将使用内部计数的字符串值。当需要临时变量且表达式中使用的变量名称不重要时,这很有用。
>>> Dummy()
_Dummy_10
sympy.core.symbol.symbols(names, *, cls=<class 'sympy.core.symbol.Symbol'>, **args) → Any
将字符串转换为Symbol
类的实例。
symbols()
函数返回从names
参数获取名称的符号序列,该参数可以是逗号或空格分隔的字符串,或者是字符串序列:
>>> from sympy import symbols, Function
>>> x, y, z = symbols('x,y,z')
>>> a, b, c = symbols('a b c')
输出类型取决于输入参数的属性:
>>> symbols('x')
x
>>> symbols('x,')
(x,)
>>> symbols('x,y')
(x, y)
>>> symbols(('a', 'b', 'c'))
(a, b, c)
>>> symbols(['a', 'b', 'c'])
[a, b, c]
>>> symbols({'a', 'b', 'c'})
{a, b, c}
如果需要一个单一符号的可迭代容器,则将seq
参数设置为True
或在符号名称末尾加上逗号:
>>> symbols('x', seq=True)
(x,)
为了减少输入,支持使用范围语法创建索引符号。范围由冒号表示,并且范围类型由冒号右侧的字符确定。如果该字符是数字,则将左侧所有连续的数字视为非负起始值(如果冒号左侧没有数字,则起始值为 0),将右侧所有连续的数字视为结束值加 1:
>>> symbols('x:10')
(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)
>>> symbols('x5:10')
(x5, x6, x7, x8, x9)
>>> symbols('x5(:2)')
(x50, x51)
>>> symbols('x5:10,y:5')
(x5, x6, x7, x8, x9, y0, y1, y2, y3, y4)
>>> symbols(('x5:10', 'y:5'))
((x5, x6, x7, x8, x9), (y0, y1, y2, y3, y4))
如果冒号右侧的字符是字母,则左侧的单个字母(如果没有,则为‘a’)作为起始,并且使用字母范围中的所有字符直到右侧的字母作为范围:
>>> symbols('x:z')
(x, y, z)
>>> symbols('x:c') # null range
()
>>> symbols('x(:c)')
(xa, xb, xc)
>>> symbols(':c')
(a, b, c)
>>> symbols('a:d, x:z')
(a, b, c, d, x, y, z)
>>> symbols(('a:d', 'x:z'))
((a, b, c, d), (x, y, z))
支持多个范围;应通过括号分隔连续的数值范围,以消除一个范围的结束数字与下一个范围的开始数字之间的歧义:
>>> symbols('x:2(1:3)')
(x01, x02, x11, x12)
>>> symbols(':3:2') # parsing is from left to right
(00, 01, 10, 11, 20, 21)
只有一个括号包围的范围被删除,因此要包含括号周围的范围,请将它们双倍。要包含空格、逗号或冒号,请使用反斜杠进行转义:
>>> symbols('x((a:b))')
(x(a), x(b))
>>> symbols(r'x(:1\,:2)') # or r'x((:1)\,(:2))'
(x(0,0), x(0,1))
所有新创建的符号都根据args
设置了假设:
>>> a = symbols('a', integer=True)
>>> a.is_integer
True
>>> x, y, z = symbols('x,y,z', real=True)
>>> x.is_real and y.is_real and z.is_real
True
尽管其名称如此,symbols()
可以创建类似符号的对象,如 Function 或 Wild 类的实例。要实现此目的,请将cls
关键字参数设置为所需类型:
>>> symbols('f,g,h', cls=Function)
(f, g, h)
>>> type(_[0])
<class 'sympy.core.function.UndefinedFunction'>
sympy.core.symbol.var(names, **args)
创建符号并将它们注入全局命名空间。
解释
这将使用相同的参数调用 symbols()
并将结果放入全局命名空间。建议在库代码中不使用 var()
,而是使用 symbols()
:
.. rubric:: Examples
>>> from sympy import var
>>> var('x')
x
>>> x # noqa: F821
x
>>> var('a,ab,abc')
(a, ab, abc)
>>> abc # noqa: F821
abc
>>> var('x,y', real=True)
(x, y)
>>> x.is_real and y.is_real # noqa: F821
True
详见 symbols()
文档,了解可以传递给 var()
的参数类型详细信息。 ## intfunc
sympy.core.intfunc.num_digits(n, base=10)
返回以给定基数表示 n 所需的位数。
参数:
n: 整数
被计算其位数的数字。
b: 整数
计算数字计算的基数。
示例
>>> from sympy.core.intfunc import num_digits
>>> num_digits(10)
2
>>> num_digits(10, 2) # 1010 -> 4 digits
4
>>> num_digits(-100, 16) # -64 -> 2 digits
2
另请参阅
sympy.ntheory.digits.digits
, sympy.ntheory.digits.count_digits
sympy.core.intfunc.trailing(n)
计算 n 的二进制表示中末尾零位数的数量,即确定能整除 n 的最大 2 的幂次数。
示例
>>> from sympy import trailing
>>> trailing(128)
7
>>> trailing(63)
0
另请参阅
sympy.ntheory.factor_.multiplicity
sympy.core.intfunc.ilcm(*args)
计算整数的最小公倍数。
示例
>>> from sympy import ilcm
>>> ilcm(5, 10)
10
>>> ilcm(7, 3)
21
>>> ilcm(5, 10, 15)
30
sympy.core.intfunc.igcd(*args)
计算非负整数的最大公约数。
解释
该算法基于著名的欧几里得算法[R123]。为了提高速度,igcd()
具有自己的缓存机制。如果不需要缓存机制,可以使用sympy.external.gmpy.gcd
。
示例
>>> from sympy import igcd
>>> igcd(2, 4)
2
>>> igcd(5, 10, 15)
5
参考文献
[R123] (1,2)
en.wikipedia.org/wiki/Euclidean_algorithm
sympy.core.intfunc.igcd_lehmer(a, b)
计算两个整数的最大公约数。
解释
欧几里德算法用于计算两个(正)整数 (a) 和 (b) 的最大公约数 gcd(a, b)
,基于除法恒等式 $$ a = q \times b + r$$,其中商 (q) 和余数 (r) 是整数,且 (0 \le r < b)。然后,(a) 和 (b) 的每个公约数都可以整除 (r),由此可知 gcd(a, b) == gcd(b, r)
。该算法通过构造序列 r0, r1, r2, …,其中 r0 = a,r1 = b,并且每个 rn 都是前两个元素的余数来实现。
在 Python 中,q = a // b
和 r = a % b
分别通过地板除法和取余操作获得。这些是最昂贵的算术操作,特别是对于大的 a 和 b。
利用观察到的商 qn = r(n-1) // rn
,即使 a 和 b 非常大,勒默算法 [R124] 中的商通常也是小整数。因此,这些商通常可以从相对较少的最显著位确定。
通过不计算欧几里德序列中的每个长余数来进一步提高算法效率。余数是从选定的最显著部分的 a 和 b 导出的整数系数的线性组合。只有当从 a 和 b 的最显著部分确定了商后,才计算出新的一对连续余数,并且算法从这一对重新开始。
参考文献
[R124] (1,2)
en.wikipedia.org/wiki/Lehmer%27s_GCD_algorithm
sympy.core.intfunc.igcdex(a, b)
返回 x, y, g,使得 g = xa + yb = gcd(a, b)。
示例
>>> from sympy.core.intfunc import igcdex
>>> igcdex(2, 3)
(-1, 1, 1)
>>> igcdex(10, 12)
(-1, 1, 2)
>>> x, y, g = igcdex(100, 2004)
>>> x, y, g
(-20, 1, 4)
>>> x*100 + y*2004
4
sympy.core.intfunc.isqrt(n)
返回不大于 (\sqrt{n}) 的最大整数。
参数:
n : 非负整数
返回:
整数 : (\left\lfloor\sqrt{n}\right\rfloor)
抛出:
数值错误
如果 n 为负数。
类型错误
如果 n 的类型无法与
int
比较。因此,对于str
报错TypeError
,但对于float
则不会。
示例
>>> from sympy.core.intfunc import isqrt
>>> isqrt(0)
0
>>> isqrt(9)
3
>>> isqrt(10)
3
>>> isqrt("30")
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
>>> from sympy.core.numbers import Rational
>>> isqrt(Rational(-1, 2))
Traceback (most recent call last):
...
ValueError: n must be nonnegative
sympy.core.intfunc.integer_nthroot(y, n)
返回一个元组,其中 x = (\left\lfloor y^{(1/n)} \right\rfloor),并返回一个布尔值,指示结果是否精确(即,是否满足 (x^n == y))。
示例
>>> from sympy import integer_nthroot
>>> integer_nthroot(16, 2)
(4, True)
>>> integer_nthroot(26, 2)
(5, False)
若要简单确定一个数是否为完全平方数,应使用 is_square 函数:
>>> from sympy.ntheory.primetest import is_square
>>> is_square(26)
False
另请参见
sympy.ntheory.primetest.is_square
, integer_log
sympy.core.intfunc.integer_log(n, b)
返回 (e, bool)
,其中 e 是最大非负整数,使得 (|n| \geq |b^e|),并且 bool
为 True 如果 (n = b^e)。
示例
>>> from sympy import integer_log
>>> integer_log(125, 5)
(3, True)
>>> integer_log(17, 9)
(1, False)
如果底数为正数且数字为负数,则返回值除了 2 以外始终相同:
>>> integer_log(-4, 2)
(2, False)
>>> integer_log(-16, 4)
(0, False)
当底数为负时,仅当指数的奇偶性符合底数的符号时,返回的值才为 True:
>>> integer_log(4, -2)
(2, True)
>>> integer_log(8, -2)
(3, False)
>>> integer_log(-8, -2)
(3, True)
>>> integer_log(-4, -2)
(2, False)
请参见
integer_nthroot
,sympy.ntheory.primetest.is_square
,sympy.ntheory.factor_.multiplicity
,sympy.ntheory.factor_.perfect_power
sympy.core.intfunc.mod_inverse(a, m)
返回数 (c),使得 (a \times c = 1 \pmod{m}),其中 (c) 与 (m) 的符号相同。如果不存在这样的值,则引发 ValueError。
举例
>>> from sympy import mod_inverse, S
假设我们希望找到模 11 下的数 3 的乘法逆元 (x)。这等同于找到 (x) 使得 (3x = 1 \pmod{11})。满足这个同余的一个 (x) 的值是 4。因为 (3 \times 4 = 12) 并且 (12 = 1 \pmod{11})。这是 mod_inverse
返回的值:
>>> mod_inverse(3, 11)
4
>>> mod_inverse(-3, 11)
7
当 (a) 和 (m) 的分子之间有一个公因数时,逆元不存在:
>>> mod_inverse(2, 4)
Traceback (most recent call last):
...
ValueError: inverse of 2 mod 4 does not exist
>>> mod_inverse(S(2)/7, S(5)/2)
7/2
参考文献
[R125]
[R126]
扩展欧几里得算法 ## numbers
class sympy.core.numbers.Number(*obj)
表示 SymPy 中的原子数。
解释
浮点数由 Float 类表示。任意大小的有理数由 Rational 类表示。任意大小的整数由 Integer 类表示。Float 和 Rational 是 Number 的子类;Integer 是 Rational 的子类。
例如,2/3
表示为 Rational(2, 3)
,它与使用 Python 除法 2/3
得到的浮点数是不同的对象。即使对于在二进制中精确表示的数字,如 Rational(1, 2)
和 Float(0.5)
,它们在 SymPy 中的使用方式也有所不同。在符号计算中应优先选择有理数形式。
其他类型的数,如代数数 sqrt(2)
或复数 3 + 4*I
,因为不是原子,所以不是 Number 类的实例。
请参见
Float
,Integer
,Rational
as_coeff_Add(rational=False)
高效地提取求和的系数。
as_coeff_Mul(rational=False)
高效地提取乘积的系数。
cofactors(other)
计算 (self) 和 (other) 的最大公约数及其余因子。
gcd(other)
计算 (self) 和 (other) 的最大公约数。
lcm(other)
计算 (self) 和 (other) 的最小公倍数。
class sympy.core.numbers.Float(num, dps=None, precision=None)
表示任意精度浮点数。
举例
>>> from sympy import Float
>>> Float(3.5)
3.50000000000000
>>> Float(3)
3.00000000000000
从字符串(以及 Python 的 int
和 long
类型)创建浮点数将给出至少 15 位数的精度,但精度将自动增加以捕获输入的所有数字。
>>> Float(1)
1.00000000000000
>>> Float(10**20)
100000000000000000000.
>>> Float('1e20')
100000000000000000000.
然而,浮点数(Python 的 float
类型)只保留 15 位精度:
>>> Float(1e20)
1.00000000000000e+20
>>> Float(1.23456789123456789)
1.23456789123457
最好将高精度的十进制数作为字符串输入:
>>> Float('1.23456789123456789')
1.23456789123456789
也可以指定所需的数字位数:
>>> Float('1e-3', 3)
0.00100
>>> Float(100, 4)
100.0
如果将空字符串发送给精度,Float 可以自动计算有效数字;空格或下划线也是允许的。(自动计数仅适用于字符串、整数和长整数)。
>>> Float('123 456 789.123_456', '')
123456789.123456
>>> Float('12e-3', '')
0.012
>>> Float(3, '')
3.
如果一个数字用科学计数法写成,那么指数前的数字被认为是有效的,如果出现小数点,则“e”只表示如何移动小数点:
>>> Float('60.e2', '') # 2 digits significant
6.0e+3
>>> Float('60e2', '') # 4 digits significant
6000.
>>> Float('600e-2', '') # 3 digits significant
6.00
注释
浮点数本质上是不精确的,除非它们的值是二进制精确值。
>>> approx, exact = Float(.1, 1), Float(.125, 1)
为了计算目的,evalf 需要能够更改精度,但这不会增加不精确值的准确性。以下是一个值为 0.1 的最准确的 5 位近似值,只有 1 位精度:
>>> approx.evalf(5)
0.099609
相比之下,0.125 在二进制中是精确的(就像在十进制中一样),因此可以传递给 Float 或 evalf 以获得匹配精度的任意精度:
>>> Float(exact, 5)
0.12500
>>> exact.evalf(20)
0.12500000000000000000
尝试从浮点数创建高精度的 Float 不是不允许的,但必须记住正在以高精度获得底层浮点数(而不是表面的十进制值)。例如,0.3 没有有限的二进制表示。最接近的有理数是分数 5404319552844595/2**54。因此,如果尝试获得 0.3 的 20 位精度的 Float,你将看不到与 0.3 后面跟着 19 个零的相同结果:
>>> Float(0.3, 20)
0.29999999999999998890
如果你想要一个 20 位数值的十进制 0.3(而不是浮点数近似值 0.3),你应该将 0.3 作为字符串发送。底层表示仍然是二进制,但使用的精度高于 Python 的浮点数:
>>> Float('0.3', 20)
0.30000000000000000000
尽管可以使用 Float 增加现有 Float 的精度,但这不会增加准确性 - 底层值不会改变:
>>> def show(f): # binary rep of Float
... from sympy import Mul, Pow
... s, m, e, b = f._mpf_
... v = Mul(int(m), Pow(2, int(e), evaluate=False), evaluate=False)
... print('%s at prec=%s' % (v, f._prec))
...
>>> t = Float('0.3', 3)
>>> show(t)
4915/2**14 at prec=13
>>> show(Float(t, 20)) # higher prec, not higher accuracy
4915/2**14 at prec=70
>>> show(Float(t, 2)) # lower prec
307/2**10 at prec=10
当在 Float 上使用 evalf 时也会发生同样的情况:
>>> show(t.evalf(20))
4915/2**14 at prec=70
>>> show(t.evalf(2))
307/2**10 at prec=10
最后,可以使用 mpf 元组(n,c,p)实例化 Float,以产生数字 (-1)nc2p:
>>> n, c, p = 1, 5, 0
>>> (-1)**n*c*2**p
-5
>>> Float((1, 5, 0))
-5.00000000000000
实际的 mpf 元组还包含元组的最后一个元素中 c 的位数:
>>> _._mpf_
(1, 5, 0, 3)
这对于实例化不是必需的,也不同于精度。mpf 元组和精度是 Float 跟踪的两个独立数量。
在 SymPy 中,Float 是可以用任意精度计算的数字。虽然浮点数 'inf' 和 'nan' 不是这样的数字,但 Float 可以创建这些数字:
>>> Float('-inf')
-oo
>>> _.is_Float
False
浮点数中的零只有一个值。正零和负零的值不是分开的。
class sympy.core.numbers.Rational(p, q=None, gcd=None)
表示任意大小的有理数(p/q)。
示例
>>> from sympy import Rational, nsimplify, S, pi
>>> Rational(1, 2)
1/2
Rational 在接受输入时是不偏见的。如果传递了一个浮点数,将返回二进制表示的底层值:
>>> Rational(.5)
1/2
>>> Rational(.2)
3602879701896397/18014398509481984
如果希望获得浮点数的简化表示,则考虑将分母限制在所需值或将浮点数转换为字符串(这大致相当于将分母限制在 10**12):
>>> Rational(str(.2))
1/5
>>> Rational(.2).limit_denominator(10**12)
1/5
当传递字符串字面值时,将获得任意精度的有理数:
>>> Rational("1.23")
123/100
>>> Rational('1e-2')
1/100
>>> Rational(".1")
1/10
>>> Rational('1e-2/3.2')
1/320
其他类型的字符串可以通过 sympify() 函数进行转换,将浮点数转换为表达式或简单分数可以使用 nsimplify 处理:
>>> S('.[3]') # repeating digits in brackets
1/3
>>> S('3**2/10') # general expressions
9/10
>>> nsimplify(.3) # numbers that have a simple form
3/10
但如果输入不能简化为字面意义上的有理数,则会引发错误:
>>> Rational(pi)
Traceback (most recent call last):
...
TypeError: invalid input: pi
低级
访问分子和分母如 .p 和 .q:
>>> r = Rational(3, 4)
>>> r
3/4
>>> r.p
3
>>> r.q
4
注意 p 和 q 返回整数(而不是 SymPy 整数),因此在表达式中使用它们时需要注意:
>>> r.p/r.q
0.75
如果需要一个未评估的有理数,可以传递 gcd=1
,这将保留分子和分母的公因数,不会被消除。然而,不能在分母中留下负值。
>>> Rational(2, 4, gcd=1)
2/4
>>> Rational(2, -4, gcd=1).q
4
另请参阅
sympy.core.sympify.sympify
,sympy.simplify.simplify.nsimplify
as_coeff_Add(rational=False)
高效地提取求和的系数。
as_coeff_Mul(rational=False)
高效地提取乘积的系数。
as_content_primitive(radical=False, clear=True)
返回元组 (R, self/R),其中 R 是从 self 提取的正有理数。
示例
>>> from sympy import S
>>> (S(-3)/2).as_content_primitive()
(3/2, -1)
查看 Expr.as_content_primitive 的文档字符串以获取更多示例。
factors(limit=None, use_trial=True, use_rho=False, use_pm1=False, verbose=False, visual=False)
一个封装到 factorint 的包装器,返回小于限制值(或便宜计算的)的 self 的因子。默认情况下禁用特殊的因子分解方法,因此仅使用试除法。
limit_denominator(max_denominator=1000000)
最接近 self 的有理数,其分母最多为 max_denominator。
示例
>>> from sympy import Rational
>>> Rational('3.141592653589793').limit_denominator(10)
22/7
>>> Rational('3.141592653589793').limit_denominator(100)
311/99
class sympy.core.numbers.Integer(i)
表示任意大小的整数。
示例
>>> from sympy import Integer
>>> Integer(3)
3
如果传递浮点数或有理数给 Integer,则会丢弃其小数部分;效果相当于向零舍入。
>>> Integer(3.8)
3
>>> Integer(-3.8)
-3
如果字符串可以解析为整数,则接受字符串作为输入:
>>> Integer("9" * 20)
99999999999999999999
很少需要显式实例化 Integer,因为在 SymPy 表达式中使用 Python 整数时会自动转换为 Integer。
class sympy.core.numbers.AlgebraicNumber(expr, coeffs=None, alias=None, **args)
表示 SymPy 中代数数的类。
符号上,该类的一个实例表示一个元素 (\alpha \in \mathbb{Q}(\theta) \hookrightarrow \mathbb{C})。也就是说,代数数 (\alpha) 被表示为特定数域 (\mathbb{Q}(\theta)) 的一个元素,这个数域以一种特定的方式嵌入到复数域中。
形式上,原始元素 (\theta) 由两个数据点给出:(1)其最小多项式(定义了 (\mathbb{Q}(\theta))),以及(2)作为该多项式根的特定复数(定义了嵌入 (\mathbb{Q}(\theta) \hookrightarrow \mathbb{C}))。最后,我们表示的代数数 (\alpha) 是由 (\theta) 的多项式的系数给出的。
static __new__(cls, expr, coeffs=None, alias=None, **args)
构造一个属于数域 ( k = \mathbb{Q}(\theta) ) 的新代数数 (\alpha)。
有四个待确定的实例属性:
属性 | 类型/含义 |
---|---|
root |
表示(\theta)为复数的Expr |
minpoly |
Poly ,(\theta)的最小多项式 |
rep |
DMP 将(\alpha)表示为(\theta)的多项式 |
alias |
Symbol 代表(\theta),或者为None |
参见参数部分以了解它们是如何确定的。
参数:
expr : Expr
,或者是对((m, r))的一对
有三种不同的构造模式,具体取决于作为expr传递的内容。
(1) expr 是一个
AlgebraicNumber
:在这种情况下,我们首先从expr复制所有四个实例属性。如果也提供了coeffs,我们将组合这两个系数多项式(见下文)。如果提供了alias,则覆盖之。(2) expr 是任何其他类型的
Expr
:那么root
将等于expr。因此,它必须表达一个代数量,并且我们将计算其minpoly
。(3) expr 是有序对((m, r)),给出
minpoly
(m),及其根root
(r),二者共同定义了(\theta)。在这种情况下,(m)可以是一个单变量的Poly
,或者任何表示相同含义的Expr
,而(r)必须是某个表示(m)根的Expr
,包括根据复数的明确表达式以及ComplexRootOf
或AlgebraicNumber
的实例。
coeffs : 列表,ANP
,默认为 None(可选)
这定义了
rep
,将代数数(\alpha)表示为(\theta)的多项式。如果是列表,则元素应为整数或有理数。如果是
ANP
,则使用其to_list()
方法获取其系数。如果为None
,则系数列表默认为[1, 0]
,这意味着(\alpha = \theta)是域的原始元素。如果 expr 是一个
AlgebraicNumber
,让 (g(x)) 是它的rep
多项式,让 (f(x)) 是由 coeffs 定义的多项式。那么self.rep
将表示组合 ((f \circ g)(x))。
alias:字符串,Symbol
,默认为 None
,可选(默认值为 None
)
这是为原始元素提供名称的一种方法。我们描述了 expr 参数定义原始元素值的几种方式,但是没有一种方法给它起一个名字。例如,在这里,alias 可以设置为
Symbol('theta')
,以便在打印 (\alpha) 或使用as_poly()
方法渲染为多项式时出现该符号。
举例
请记住,我们正在构造一个代数数作为域元素 (\alpha \in \mathbb{Q}(\theta))。
>>> from sympy import AlgebraicNumber, sqrt, CRootOf, S
>>> from sympy.abc import x
示例(1):(\alpha = \theta = \sqrt{2})
>>> a1 = AlgebraicNumber(sqrt(2))
>>> a1.minpoly_of_element().as_expr(x)
x**2 - 2
>>> a1.evalf(10)
1.414213562
示例(2):(\alpha = 3 \sqrt{2} - 5), (\theta = \sqrt{2})。我们可以继续上一个示例:
>>> a2 = AlgebraicNumber(a1, [3, -5])
>>> a2.as_expr()
-5 + 3*sqrt(2)
或者从头开始:
>>> a2 = AlgebraicNumber(sqrt(2), [3, -5])
>>> a2.as_expr()
-5 + 3*sqrt(2)
示例(3):(\alpha = 6 \sqrt{2} - 11), (\theta = \sqrt{2})。同样,我们可以基于前一个示例,并且我们看到系数多项式是组合的:
>>> a3 = AlgebraicNumber(a2, [2, -1])
>>> a3.as_expr()
-11 + 6*sqrt(2)
反映了事实,即 ((2x - 1) \circ (3x - 5) = 6x - 11)。
示例(4):(\alpha = \sqrt{2}),(\theta = \sqrt{2} + \sqrt{3})。最简单的方法是使用 to_number_field()
函数:
>>> from sympy import to_number_field
>>> a4 = to_number_field(sqrt(2), sqrt(2) + sqrt(3))
>>> a4.minpoly_of_element().as_expr(x)
x**2 - 2
>>> a4.to_root()
sqrt(2)
>>> a4.primitive_element()
sqrt(2) + sqrt(3)
>>> a4.coeffs()
[1/2, 0, -9/2, 0]
但是如果你已经知道了正确的系数,你可以直接构造它:
>>> a4 = AlgebraicNumber(sqrt(2) + sqrt(3), [S(1)/2, 0, S(-9)/2, 0])
>>> a4.to_root()
sqrt(2)
>>> a4.primitive_element()
sqrt(2) + sqrt(3)
示例(5):在第五旋轉数域中构造黄金比例作为一个元素,假设我们已经知道它的系数。这次我们引入别名 (\zeta) 作为该域的原始元素:
>>> from sympy import cyclotomic_poly
>>> from sympy.abc import zeta
>>> a5 = AlgebraicNumber(CRootOf(cyclotomic_poly(5), -1),
... [-1, -1, 0, 0], alias=zeta)
>>> a5.as_poly().as_expr()
-zeta**3 - zeta**2
>>> a5.evalf()
1.61803398874989
(索引 -1
到 CRootOf
选择具有最大实部和虚部的复数根,这种情况下是 (\mathrm{e}^{2i\pi/5})。参见 ComplexRootOf
。)
示例(6):在上一个示例的基础上,构造数 (2 \phi \in \mathbb{Q}(\phi)),其中 (\phi) 是黄金比例:
>>> from sympy.abc import phi
>>> a6 = AlgebraicNumber(a5.to_root(), coeffs=[2, 0], alias=phi)
>>> a6.as_poly().as_expr()
2*phi
>>> a6.primitive_element().evalf()
1.61803398874989
请注意,我们需要使用 a5.to_root()
,因为将 a5
作为第一个参数传递会将数 (2 \phi) 构造为域 (\mathbb{Q}(\zeta)) 的一个元素:
>>> a6_wrong = AlgebraicNumber(a5, coeffs=[2, 0])
>>> a6_wrong.as_poly().as_expr()
-2*zeta**3 - 2*zeta**2
>>> a6_wrong.primitive_element().evalf()
0.309016994374947 + 0.951056516295154*I
as_expr(x=None)
从 self
创建一个基本表达式。
as_poly(x=None)
从 self
创建一个 Poly 实例。
coeffs()
返回代数数的所有 SymPy 系数。
field_element(coeffs)
以同一数域的另一个元素形式。
参数:
coeffs:列表,ANP
类似于类
构造器
的 coeffs 参数,将新元素定义为原始元素的多项式。如果是列表,则其元素应为整数或有理数。如果是
ANP
,我们使用其系数(使用其to_list()
方法)。
解释
如果我们表示 (\alpha \in \mathbb{Q}(\theta)),构造另一个属于同一数域 (\mathbb{Q}(\theta)) 的元素 (\beta)。
示例
>>> from sympy import AlgebraicNumber, sqrt
>>> a = AlgebraicNumber(sqrt(5), [-1, 1])
>>> b = a.field_element([3, 2])
>>> print(a)
1 - sqrt(5)
>>> print(b)
2 + 3*sqrt(5)
>>> print(b.primitive_element() == a.primitive_element())
True
另见
代数数
property is_aliased
如果设置了 alias
,则返回 True
。
property is_primitive_element
判断此代数数 (\alpha \in \mathbb{Q}(\theta)) 是否等于其数域的原始元素 (\theta)。
minpoly_of_element()
计算此代数数的最小多项式。
解释
回想一下,我们表示一个元素 (\alpha \in \mathbb{Q}(\theta))。我们的实例属性 self.minpoly
是我们原始元素 (\theta) 的最小多项式。此方法计算 (\alpha) 的最小多项式。
native_coeffs()
返回一个代数数的所有本地系数。
primitive_element()
获取数域 (\mathbb{Q}(\theta)) 中此代数数 (\alpha) 所属的原始元素 (\theta)。
返回:
代数数
to_algebraic_integer()
将 self
转换为代数整数。
to_primitive_element(radicals=True)
将 self
转换为一个 代数数
实例,该实例等于其自身的原始元素。
参数:
根式:布尔值,可选(默认为 True)
如果为
True
,则我们将尝试返回一个根式表达式中的代数数
。如果不可能(或者 radicals 为False
),则root
将是ComplexRootOf
。
返回:
代数数
解释
如果我们表示 (\alpha \in \mathbb{Q}(\theta)),(\alpha \neq \theta),构造一个新的 代数数
来表示 (\alpha \in \mathbb{Q}(\alpha))。
示例
>>> from sympy import sqrt, to_number_field
>>> from sympy.abc import x
>>> a = to_number_field(sqrt(2), sqrt(2) + sqrt(3))
代数数
a
在域 (\mathbb{Q}(\sqrt{2} + \sqrt{3})) 中代表数字 (\sqrt{2})。将 a
渲染为多项式,
>>> a.as_poly().as_expr(x)
x**3/2 - 9*x/2
反映了 (\sqrt{2} = \theta³/2 - 9 \theta/2) 这一事实,其中 (\theta = \sqrt{2} + \sqrt{3})。
a
不等于其自身的原始元素。其最小多项式
>>> a.minpoly.as_poly().as_expr(x)
x**4 - 10*x**2 + 1
是关于 (\theta) 的。
转换为一个原始元素,
>>> a_prim = a.to_primitive_element()
>>> a_prim.minpoly.as_poly().as_expr(x)
x**2 - 2
我们得到一个 代数数
,其 minpoly
与该数本身相同。
另见
is_primitive_element
to_root(radicals=True, minpoly=None)
转换为一个 Expr
,而不是一个 AlgebraicNumber
,具体来说,要么是 ComplexRootOf
,或者在可能的情况下是一个根式表达式。
参数:
radicals:布尔值,可选(默认为 True)
如果为
True
,则尝试返回根式表达式的根。如果不可能,将返回一个ComplexRootOf
。
minpoly:Poly
如果已经预先计算了
self
的最小多项式,则可以传入以节省时间。
class sympy.core.numbers.NumberSymbol
approximation(number_cls)
返回一个包含 NumberSymbol 值的 number_cls 端点的区间。如果未实现,则返回 None。
sympy.core.numbers.RealNumber
别名为 Float
sympy.core.numbers.seterr(divide=False)
SymPy 是否应在 0/0 时抛出异常或返回 NaN?
divide == True …. 抛出异常 divide == False … 返回 NaN
class sympy.core.numbers.Zero
数字零。
Zero 是一个单例,可以通过 S.Zero
访问。
示例
>>> from sympy import S, Integer
>>> Integer(0) is S.Zero
True
>>> 1/S.Zero
zoo
参考文献
[R127]
class sympy.core.numbers.One
数字一。
One 是一个单例,可以通过 S.One
访问。
示例
>>> from sympy import S, Integer
>>> Integer(1) is S.One
True
参考文献
[R128]
en.wikipedia.org/wiki/1_%28number%29
class sympy.core.numbers.NegativeOne
数字负一。
NegativeOne 是一个单例,可以通过 S.NegativeOne
访问。
示例
>>> from sympy import S, Integer
>>> Integer(-1) is S.NegativeOne
True
参见
One
参考文献
[R129]
en.wikipedia.org/wiki/%E2%88%921_%28number%29
class sympy.core.numbers.Half
有理数 1/2。
Half 是一个单例,可以通过 S.Half
访问。
示例
>>> from sympy import S, Rational
>>> Rational(1, 2) is S.Half
True
参考文献
[R130]
en.wikipedia.org/wiki/One_half
class sympy.core.numbers.NaN
非数字。
解释
这用作不定数的数值占位符。NaN 的大多数运算会产生另一个 NaN。大多数不定形式,如 0/0
或 pyoo - oo` produce NaN. Two exceptions are ``0**0
和 oo**0
,都会产生 1
(这与 Python 的浮点数一致)。
NaN 与浮点数的 nan 松散相关,后者在 IEEE 754 浮点数标准中定义,并对应于 Python 的 float('nan')
。下面会说明它们的差异。
NaN 在数学上与任何其他值都不相等,甚至不等于自身。这解释了下面示例中 Eq
和 ==
的最初反直觉结果。
NaN 不可比较,因此不等式会引发 TypeError。这与浮点数的 nan 不同,后者所有不等式均为假。
NaN 是一个单例,可以通过 S.NaN
访问,或者可以导入为 nan
。
例子
>>> from sympy import nan, S, oo, Eq
>>> nan is S.NaN
True
>>> oo - oo
nan
>>> nan + 1
nan
>>> Eq(nan, nan) # mathematical equality
False
>>> nan == nan # structural equality
True
参考文献
[R131]
class sympy.core.numbers.Infinity
正无穷大量。
解释
在实分析中,符号 (\infty) 表示无界极限:(x\to\infty) 意味着 (x) 增长无限。
无穷大常被用来不仅定义极限,而且作为扩展实数系统中的一个值。标记为 (+\infty) 和 (-\infty) 的点可以添加到实数的拓扑空间中,从而产生实数的二点紧致化。在此基础上添加代数属性给我们扩展了的实数。
Infinity 是一个单例,可以通过 S.Infinity
访问,或者可以导入为 oo
。
例子
>>> from sympy import oo, exp, limit, Symbol
>>> 1 + oo
oo
>>> 42/oo
0
>>> x = Symbol('x')
>>> limit(exp(x), x, oo)
oo
参见
NegativeInfinity
, NaN
参考文献
[R132]
en.wikipedia.org/wiki/Infinity
class sympy.core.numbers.NegativeInfinity
负无穷大量。
NegativeInfinity 是一个单例,可以通过 S.NegativeInfinity
访问。
参见
Infinity
class sympy.core.numbers.ComplexInfinity
复数无穷大。
解释
在复分析中,符号 (\tilde\infty),称为“复无穷大”,表示具有无限大小但未确定复相位的量。
ComplexInfinity 是一个单例,可以通过 S.ComplexInfinity
访问,或者可以导入为 zoo
。
例子
>>> from sympy import zoo
>>> zoo + 42
zoo
>>> 42/zoo
0
>>> zoo + zoo
nan
>>> zoo*zoo
zoo
参见
Infinity
class sympy.core.numbers.Exp1
(e) 常数。
解释
超越数 (e = 2.718281828\ldots) 是自然对数和指数函数的底数,(e = \exp(1))。有时称为欧拉数或纳皮尔常数。
Exp1 是一个单例,可以通过 S.Exp1
访问,或者可以导入为 E
。
例子
>>> from sympy import exp, log, E
>>> E is exp(1)
True
>>> log(E)
1
参考文献
[R133]
en.wikipedia.org/wiki/E_%28mathematical_constant%29
class sympy.core.numbers.ImaginaryUnit
虚数单位,(i = \sqrt{-1})。
I 是一个单例,可以通过 S.I
访问,或者可以导入为 I
。
例子
>>> from sympy import I, sqrt
>>> sqrt(-1)
I
>>> I*I
-1
>>> 1/I
-I
参考文献
[R134]
en.wikipedia.org/wiki/Imaginary_unit
class sympy.core.numbers.Pi
圆周率 (\pi) 常数。
解释
超越数 (\pi = 3.141592654\ldots) 表示圆周率与其直径的比率,单位圆的面积,三角函数的半周期以及数学中的许多其他内容。
圆周率是一个单例,可以通过 S.Pi
访问,或者可以导入为 pi
。
例子
>>> from sympy import S, pi, oo, sin, exp, integrate, Symbol
>>> S.Pi
pi
>>> pi > 3
True
>>> pi.is_irrational
True
>>> x = Symbol('x')
>>> sin(x + 2*pi)
sin(x)
>>> integrate(exp(-x**2), (x, -oo, oo))
sqrt(pi)
参考文献
[R135]
class sympy.core.numbers.EulerGamma
欧拉-马斯切罗尼常数。
解释
(\gamma = 0.5772157\ldots)(也称为欧拉常数)是分析和数论中经常出现的数学常数。它被定义为调和级数与自然对数之间的极限差:
[\gamma = \lim\limits_{n\to\infty} \left(\sum\limits_{k=1}^n\frac{1}{k} - \ln n\right)]
欧拉-马斯谢罗常数是一个单例,可以通过 S.EulerGamma
访问。
示例
>>> from sympy import S
>>> S.EulerGamma.is_irrational
>>> S.EulerGamma > 0
True
>>> S.EulerGamma > 1
False
参考
[R136]
en.wikipedia.org/wiki/Euler%E2%80%93Mascheroni_constant
class sympy.core.numbers.Catalan
卡塔兰常数。
解释
(G = 0.91596559\ldots) 是由无限级数给出的
[G = \sum_{k=0}^{\infty} \frac{(-1)^k}{(2k+1)²}]
卡塔兰常数是一个单例,可以通过 S.Catalan
访问。
示例
>>> from sympy import S
>>> S.Catalan.is_irrational
>>> S.Catalan > 0
True
>>> S.Catalan > 1
False
参考
[R137]
en.wikipedia.org/wiki/Catalan%27s_constant
class sympy.core.numbers.GoldenRatio
黄金比例,(\phi)。
解释
(\phi = \frac{1 + \sqrt{5}}{2}) 是一个代数数。如果两个量的比率等于它们的和与较大量的比率,那么它们就处于黄金比例,即它们的最大量。
黄金比例是一个单例,可以通过 S.GoldenRatio
访问。
示例
>>> from sympy import S
>>> S.GoldenRatio > 1
True
>>> S.GoldenRatio.expand(func=True)
1/2 + sqrt(5)/2
>>> S.GoldenRatio.is_irrational
True
参考
[R138]
en.wikipedia.org/wiki/Golden_ratio
class sympy.core.numbers.TribonacciConstant
三波那契常数。
解释
三波那契数类似于斐波那契数,但是不是从两个预定项开始,而是从三个预定项开始,后面的每一项是前三项的和。
三波那契常数是相邻三波那契数趋向的比率。它是多项式 (x³ - x² - x - 1 = 0) 的根,同时满足方程 (x + x^{-3} = 2)。
三波那契常数是一个单例,可以通过 S.TribonacciConstant
访问。
示例
>>> from sympy import S
>>> S.TribonacciConstant > 1
True
>>> S.TribonacciConstant.expand(func=True)
1/3 + (19 - 3*sqrt(33))**(1/3)/3 + (3*sqrt(33) + 19)**(1/3)/3
>>> S.TribonacciConstant.is_irrational
True
>>> S.TribonacciConstant.n(20)
1.8392867552141611326
参考
[R139]
en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers#Tribonacci_numbers
sympy.core.numbers.mod_inverse(a, m)
返回数 (c),使得 (a \times c = 1 \pmod{m}),其中 (c) 的符号与 (m) 相同。如果不存在这样的值,则引发 ValueError。
示例
>>> from sympy import mod_inverse, S
假设我们希望找到模 11 下的数 3 的乘法逆元 (x)。这等同于找到满足 (3x = 1 \pmod{11}) 的 (x)。满足这个同余的一个值是 4。因为 (3 \times 4 = 12) 并且 (12 = 1 \pmod{11})。这是 mod_inverse
返回的值:
>>> mod_inverse(3, 11)
4
>>> mod_inverse(-3, 11)
7
当分子 (a) 和 (m) 之间有公共因子时,逆元不存在:
>>> mod_inverse(2, 4)
Traceback (most recent call last):
...
ValueError: inverse of 2 mod 4 does not exist
>>> mod_inverse(S(2)/7, S(5)/2)
7/2
参考
[R140]
en.wikipedia.org/wiki/Modular_multiplicative_inverse
[R141]
en.wikipedia.org/wiki/Extended_Euclidean_algorithm
sympy.core.numbers.equal_valued(x, y)
比较将普通浮点数作为有理数处理的表达式。
示例
>>> from sympy import S, symbols, Rational, Float
>>> from sympy.core.numbers import equal_valued
>>> equal_valued(1, 2)
False
>>> equal_valued(1, 1)
True
在 SymPy 表达式中,Floats 与对应的 Rationals 比较不相等:
>>> x = symbols('x')
>>> x**2 == x**2.0
False
然而,单个 Float 与 Rational 比较相等:
>>> Rational(1, 2) == Float(0.5)
False
在未来的 SymPy 版本中,这可能会改变,以使 Rational 和 Float 比较不相等。此函数提供了当前预期的==
行为,以便在未来更改==
行为时仍然可以使用。
>>> equal_valued(1, 1.0) # Float vs Rational
True
>>> equal_valued(S(1).n(3), S(1).n(5)) # Floats of different precision
True
说明
在未来的 SymPy 版本中,Float 和 Rational 可能会比较不相等,不同精度的浮点数可能会比较不相等。在这种情况下,需要一个函数来检查一个数是否等于 1 或 0 等。这个想法是,不再测试if x == 1:
如果我们想接受像1.0
这样的浮点数,那么测试可以写成if equal_valued(x, 1):
或if equal_valued(x, 2):
。由于这个函数旨在用于期望一个或两个操作数为具体数字(如 1 或 0)的情况,所以该函数不会递归通过任何复合表达式的参数来比较任何嵌套浮点数。
参考文献
[R142]
github.com/sympy/sympy/pull/20033
## power
class sympy.core.power.Pow(b, e, evaluate=None)
定义表达式 x**y 为“x 的 y 次幂”
自版本 1.7 起不推荐使用:在核心操作符(Mul
、Add
和Pow
)中使用非Expr
子类的参数已被弃用。有关详情,请参阅 Core operators no longer accept non-Expr args。
单例定义涉及(0, 1, -1, oo, -oo, I, -I):
expr | value | reason |
---|---|---|
z**0 | 1 | 尽管关于 0**0 的论点存在,参见[2]。 |
z**1 | z | |
(-oo)**(-1) | 0 | |
(-1)**-1 | -1 | |
S.Zero**-1 | zoo | 这并非严格正确,因为 0**-1 可能未定义,但在某些假设基数为正时很方便。 |
1**-1 | 1 | |
oo**-1 | 0 | |
0**oo | 0 | 因为对于所有接近 0 的复数 z,z**oo -> 0。 |
0**-oo | zoo | 这并非严格正确,因为 0**oo 可能在复平面中正负值之间震荡或旋转。但是,当基数为正时,这是方便的。 |
1oo 1-oo | nan | 因为存在 lim(x(t),t)=1,lim(y(t),t)=oo(或-oo),但 lim(x(t)**y(t), t) != 1。参见[3]。 |
b**zoo | nan | 因为 b**z 在 z -> zoo 时没有极限。 |
(-1)oo (-1)(-oo) | nan | 因为极限中存在振荡。 |
oo**oo | oo | |
oo**-oo | 0 | |
(-oo)oo (-oo)-oo | nan | |
ooI (-oo)I | nan | 可以将 ooe 最好视为 x 趋于 oo 时实数 xe 的极限。如果 e 是 I,则极限不存在,使用 nan 表示。 |
oo(1+I) (-oo)(1+I) | zoo | 如果 e 的实部为正,则 abs(x**e) 的极限为 oo。因此极限值为 zoo。 |
oo(-1+I) -oo(-1+I) | 0 | 如果 e 的实部为负,则极限为 0。 |
因为符号计算比浮点计算更灵活,并且我们更倾向于不返回不正确的答案,所以我们选择不遵循所有 IEEE 754 的约定。这有助于我们避免在计算极限时额外的测试案例代码。
另请参阅
sympy.core.numbers.Infinity
, sympy.core.numbers.NegativeInfinity
, sympy.core.numbers.NaN
参考
[R143]
en.wikipedia.org/wiki/Exponentiation
[R144]
en.wikipedia.org/wiki/Zero_to_the_power_of_zero
[R145]
en.wikipedia.org/wiki/Indeterminate_forms
as_base_exp()
返回 self 的基数和指数。
解释
如果基数小于 1,则返回 1/有理数,-exp。如果不需要此额外处理,则基数和 exp 属性将给出原始参数。
示例
>>> from sympy import Pow, S
>>> p = Pow(S.Half, 2, evaluate=False)
>>> p.as_base_exp()
(2, -2)
>>> p.args
(1/2, 2)
>>> p.base, p.exp
(1/2, 2)
as_content_primitive(radical=False, clear=True)
返回元组 (R, self/R),其中 R 是从 self 中提取的正有理数。
示例
>>> from sympy import sqrt
>>> sqrt(4 + 4*sqrt(2)).as_content_primitive()
(2, sqrt(1 + sqrt(2)))
>>> sqrt(3 + 3*sqrt(2)).as_content_primitive()
(1, sqrt(3)*sqrt(1 + sqrt(2)))
>>> from sympy import expand_power_base, powsimp, Mul
>>> from sympy.abc import x, y
>>> ((2*x + 2)**2).as_content_primitive()
(4, (x + 1)**2)
>>> (4**((1 + y)/2)).as_content_primitive()
(2, 4**(y/2))
>>> (3**((1 + y)/2)).as_content_primitive()
(1, 3**((y + 1)/2))
>>> (3**((5 + y)/2)).as_content_primitive()
(9, 3**((y + 1)/2))
>>> eq = 3**(2 + 2*x)
>>> powsimp(eq) == eq
True
>>> eq.as_content_primitive()
(9, 3**(2*x))
>>> powsimp(Mul(*_))
3**(2*x + 2)
>>> eq = (2 + 2*x)**y
>>> s = expand_power_base(eq); s.is_Mul, s
(False, (2*x + 2)**y)
>>> eq.as_content_primitive()
(1, (2*(x + 1))**y)
>>> s = expand_power_base(_[1]); s.is_Mul, s
(True, 2**y*(x + 1)**y)
有关更多示例,请参阅 Expr.as_content_primitive 的文档字符串。 ## mul
class sympy.core.mul.Mul(*args, evaluate=None, _sympify=True)
表示代数场中乘法操作的表达式。
自版本 1.7 弃用:在核心运算符(Mul
、Add
和 Pow
)中使用非 Expr 子类的参数。有关详细信息,请参阅不再接受非 Expr 参数的核心运算符。
Mul()
的每个参数都必须是 Expr
。在 SymPy 中大多数标量对象上的中缀运算符 *
都调用此类。
Mul()
的另一个用途是表示抽象乘法的结构,以便其参数可以被替换以返回不同的类。有关此内容,请参阅示例部分。
Mul()
会评估参数,除非传递了 evaluate=False
。评估逻辑包括:
-
展平
Mul(x, Mul(y, z))
->Mul(x, y, z)
-
去除身份
Mul(x, 1, y)
->Mul(x, y)
-
通过
.as_base_exp()
收集指数Mul(x, x**2)
->Pow(x, 3)
-
项排序
Mul(y, x, 2)
->Mul(2, x, y)
由于乘法可以是矢量空间操作,参数可能具有不同的 sympy.core.kind.Kind()
。结果对象的种类将自动推断。
示例
>>> from sympy import Mul
>>> from sympy.abc import x, y
>>> Mul(x, 1)
x
>>> Mul(x, x)
x**2
如果传递了 evaluate=False
,则结果不会被评估。
>>> Mul(1, 2, evaluate=False)
1*2
>>> Mul(x, x, evaluate=False)
x*x
Mul()
也表示乘法操作的一般结构。
>>> from sympy import MatrixSymbol
>>> A = MatrixSymbol('A', 2,2)
>>> expr = Mul(x,y).subs({y:A})
>>> expr
x*A
>>> type(expr)
<class 'sympy.matrices.expressions.matmul.MatMul'>
另请参见
MatMul
as_coeff_Mul(rational=False)
高效地提取乘积的系数。
as_content_primitive(radical=False, clear=True)
返回元组(R, self/R),其中 R 是从 self 中提取的正有理数。
示例
>>> from sympy import sqrt
>>> (-3*sqrt(2)*(2 - 2*sqrt(2))).as_content_primitive()
(6, -sqrt(2)*(1 - sqrt(2)))
查看Expr.as_content_primitive
的文档字符串以获取更多示例。
as_ordered_factors(order=None)
将表达式转换为因子的有序列表。
示例
>>> from sympy import sin, cos
>>> from sympy.abc import x, y
>>> (2*x*y*sin(x)*cos(x)).as_ordered_factors()
[2, x, y, sin(x), cos(x)]
as_two_terms()
返回 self 的头部和尾部。
这是获取表达式头部和尾部的最有效方式。
-
如果只需要头部,请使用 self.args[0];
-
如果要处理尾部的参数,则使用 self.as_coef_mul(),它在将其视为 Mul 时给出头部和包含尾部参数的元组。
-
如果希望在将 self 视为 Add 时获取系数,请使用 self.as_coeff_add()[0]
示例
>>> from sympy.abc import x, y
>>> (3*x*y).as_two_terms()
(3, x*y)
classmethod flatten(seq)
通过结合相关术语返回可交换、非可交换和顺序参数。
注意
-
在类似
a*b*c
的表达式中,Python 将其通过 SymPy 处理为Mul(Mul(a, b), c)
。这可能会产生不良后果。- 有时术语不能像预期的那样组合:{参见
github.com/sympy/sympy/issues/4596
}
>>> from sympy import Mul, sqrt
- 有时术语不能像预期的那样组合:{参见
from sympy.abc import x, y, z
2*(x + 1) # this is the 2-arg Mul behavior
2*x + 2
y(x + 1)2
2y(x + 1)
2(x + 1)y # 2-arg result will be obtained first
y(2x + 2)
Mul(2, x + 1, y) # all 3 args simultaneously processed
2y(x + 1)
2((x + 1)y) # parentheses can control this behavior
2y(x + 1)
具有复合基数的幂可能找不到单个基数来组合,除非所有参数一次处理。在这种情况下可能需要后处理。{参见 [`github.com/sympy/sympy/issues/5728`](https://github.com/sympy/sympy/issues/5728)} ```py >>> a = sqrt(x*sqrt(y)) >>> a**3 (x*sqrt(y))**(3/2) >>> Mul(a,a,a) (x*sqrt(y))**(3/2) >>> a*a*a x*sqrt(y)*sqrt(x*sqrt(y)) >>> _.subs(a.base, z).subs(z, a.base) (x*sqrt(y))**(3/2)
+ 如果正在相乘的术语超过两个,则所有先前的术语将对每个新的参数重新处理。因此,如果每个`a`、`b`和`c`都是`Mul`表达式,那么`a*b*c`(或通过`*=`逐步建立乘积)将会两次处理`a`和`b`的所有参数:一次是计算`a*b`时,另一次是乘以`c`时。
使用`Mul(a, b, c)`将会处理所有参数一次。
-
Mul
的结果会根据参数进行缓存,因此仅对Mul(a, b, c)
调用一次flatten
。如果可以结构化计算使得参数最有可能重复,那么可以节省计算答案的时间。例如,假设你有一个 Mul,M,希望除以d[i]
并乘以n[i]
,并且你怀疑n
中有许多重复。最好计算M*n[i]/d[i]
而不是M/d[i]*n[i]
,因为每次n[i]
重复时,乘积M*n[i]
将返回而无需扁平化 – 将返回缓存的值。如果首先除以d[i]
(而这些与n[i]
相比更独特),那么将创建一个新的 Mul,M/d[i]
其参数将在乘以n[i]
时再次遍历。{参见
github.com/sympy/sympy/issues/5706
}如果缓存关闭,则此考虑无效。
注
上述说明的有效性取决于 Mul 和 flatten 的实现细节,这些细节可能随时更改。 因此,只有在您的代码非常关注性能时才应考虑它们。
从序列中删除 1 已由 AssocOp.new 处理。
sympy.core.mul.prod(a, start=1)
返回数组元素的乘积。从整数 1 开始,所以如果只有
ints 被包括在内,然后返回一个 int 结果。
示例
>>> from sympy import prod, S
>>> prod(range(3))
0
>>> type(_) is int
True
>>> prod([S(2), 3])
6
>>> _.is_Integer
True
您可以从 1 以外的某个值开始产品:
>>> prod([1, 2], 3)
6
``` ## add
```py
class sympy.core.add.Add(*args, evaluate=None, _sympify=True)
表示代数组的加法操作的表达式。
自版本 1.7 起不推荐使用:在核心运算符(Mul
、Add
和Pow
)中使用非 Expr 参数已被弃用。 有关详细信息,请参阅 Core operators no longer accept non-Expr args。
Add()
的每个参数都必须是Expr
。 SymPy 中大多数标量对象上的中缀运算符+
调用这个类。
Add()
的另一个用途是表示抽象加法结构,以便可以替换其参数以返回不同的类。 有关此内容,请参阅示例部分。
如果未传递evaluate=False
,则Add()
会评估参数。 评估逻辑包括:
-
展平
Add(x, Add(y, z))
->Add(x, y, z)
-
去除标识
Add(x, 0, y)
->Add(x, y)
-
通过
.as_coeff_Mul()
进行系数收集Add(x, 2*x)
->Mul(3, x)
-
项排序
Add(y, x, 2)
->Add(2, x, y)
如果没有传递参数,则返回标识元素 0。 如果传递单个元素,则返回该元素。
请注意,Add(*args)
比sum(args)
更有效,因为它会展平参数。 sum(a, b, c, ...)
以递归方式添加参数,即a + (b + (c + ...))
,具有二次复杂度。 另一方面,Add(a, b, c, d)
不假设嵌套结构,使得复杂度为线性。
由于加法是组操作,每个参数都应具有相同的sympy.core.kind.Kind()
。
示例
>>> from sympy import Add, I
>>> from sympy.abc import x, y
>>> Add(x, 1)
x + 1
>>> Add(x, x)
2*x
>>> 2*x**2 + 3*x + I*y + 2*y + 2*x/5 + 1.0*y + 1
2*x**2 + 17*x/5 + 3.0*y + I*y + 1
如果传递evaluate=False
,结果不会被评估。
>>> Add(1, 2, evaluate=False)
1 + 2
>>> Add(x, x, evaluate=False)
x + x
Add()
还表示加法操作的一般结构。
>>> from sympy import MatrixSymbol
>>> A,B = MatrixSymbol('A', 2,2), MatrixSymbol('B', 2,2)
>>> expr = Add(x,y).subs({x:A, y:B})
>>> expr
A + B
>>> type(expr)
<class 'sympy.matrices.expressions.matadd.MatAdd'>
请注意,打印机不会按照 args 的顺序显示。
>>> Add(x, 1)
x + 1
>>> Add(x, 1).args
(1, x)
参见
MatAdd
as_coeff_Add(rational=False, deps=None)
高效地提取求和的系数。
as_coeff_add(*deps)
返回一个元组(coeff, args),其中 self 被视为 Add,coeff 是数字项,args 是所有其他项的元组。
示例
>>> from sympy.abc import x
>>> (7 + 3*x).as_coeff_add()
(7, (3*x,))
>>> (7*x).as_coeff_add()
(0, (7*x,))
as_content_primitive(radical=False, clear=True)
返回元组(R, self/R),其中 R 是从 self 中提取的正有理数。 如果 radical 为 True(默认为 False),则将删除常见的根,并将其包含为原始表达式的因子。
示例
>>> from sympy import sqrt
>>> (3 + 3*sqrt(2)).as_content_primitive()
(3, 1 + sqrt(2))
基本内容也可以从原始元素中分解出来:
>>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive(radical=True)
(2, sqrt(2)*(1 + 2*sqrt(5)))
有关更多示例,请参阅 Expr.as_content_primitive 的文档字符串。
as_numer_denom()
将表达式分解为其分子部分和分母部分。
示例
>>> from sympy.abc import x, y, z
>>> (x*y/z).as_numer_denom()
(x*y, z)
>>> (x*(y + 1)/y**7).as_numer_denom()
(x*(y + 1), y**7)
另见
sympy.core.expr.Expr.as_numer_denom
as_real_imag(deep=True, **hints)
返回表示复数的元组。
示例
>>> from sympy import I
>>> (7 + 9*I).as_real_imag()
(7, 9)
>>> ((1 + I)/(1 - I)).as_real_imag()
(0, 1)
>>> ((1 + 2*I)*(1 + 3*I)).as_real_imag()
(-5, 5)
as_two_terms()
返回 self 的头部和尾部。
这是获取表达式头部和尾部的最有效方式。
-
如果您只想获取头部,请使用
self.args[0]
; -
如果您想处理尾部的参数,请使用
self.as_coef_add()
,它返回头部和作为 Add 处理时尾部参数的元组。 -
如果您希望在将 self 视为 Mul 时获取系数,请使用
self.as_coeff_mul()[0]
>>> from sympy.abc import x, y
>>> (3*x - 2*y + 5).as_two_terms()
(5, 3*x - 2*y)
extract_leading_order(symbols, point=None)
返回主导项及其顺序。
示例
>>> from sympy.abc import x
>>> (x + 1 + 1/x**5).extract_leading_order(x)
((x**(-5), O(x**(-5))),)
>>> (1 + x).extract_leading_order(x)
((1, O(1)),)
>>> (x + x**2).extract_leading_order(x)
((x, O(x)),)
classmethod flatten(seq)
获取嵌套 Add 的序列“seq”并返回一个扁平化列表。
返回:(可交换部分,非可交换部分,顺序符号)
应用结合性,所有术语均可相对于加法交换。
注意:去除 0 已由 AssocOp.new 处理。
另见
sympy.core.mul.Mul.flatten
primitive()
返回(R, self/R)
其中R`
是self`
的有理 GCD。
R
仅从每个术语的主导系数中收集。
示例
>>> from sympy.abc import x, y
>>> (2*x + 4*y).primitive()
(2, x + 2*y)
>>> (2*x/3 + 4*y/9).primitive()
(2/9, 3*x + 2*y)
>>> (2*x/3 + 4.2*y).primitive()
(1/3, 2*x + 12.6*y)
不进行术语因子的子处理:
>>> ((2 + 2*x)*x + 2).primitive()
(1, x*(2*x + 2) + 2)
递归处理可以使用as_content_primitive()
方法完成:
>>> ((2 + 2*x)*x + 2).as_content_primitive()
(2, x*(x + 1) + 1)
另见:polytools.py 中的 primitive()函数 ## mod
class sympy.core.mod.Mod(p, q)
表示符号表达式的模运算。
参数:
p : Expr
被除数。
q : Expr
除数。
注意
使用的约定与 Python 相同:余数始终与除数具有相同的符号。
许多对象在模n
下的求值速度比直接(或根本)求值要快得多。为此,必须使用evaluate=False
来防止急切求值:
>>> from sympy import binomial, factorial, Mod, Pow
>>> Mod(Pow(2, 10**16, evaluate=False), 97)
61
>>> Mod(factorial(10**9, evaluate=False), 10**9 + 9)
712524808
>>> Mod(binomial(10**18, 10**12, evaluate=False), (10**5 + 3)**2)
3744312326
示例
>>> from sympy.abc import x, y
>>> x**2 % y
Mod(x**2, y)
>>> _.subs({x: 5, y: 6})
1
``` ## 关系型
```py
class sympy.core.relational.Relational(lhs, rhs, rop=None, **assumptions)
所有关系类型的基类。
参数:
rop : str or None
指示实例化的子类。有效值可以在 Relational.ValidRelationOperator 的键中找到。
解释
Relational 的子类通常应直接实例化,但可以使用有效的rop
值实例化 Relational 以分派到适当的子类。
示例
>>> from sympy import Rel
>>> from sympy.abc import x, y
>>> Rel(y, x + x**2, '==')
Eq(y, x**2 + x)
可以使用rop
参数在创建时定义关系类型。可以使用其rel_op
属性获取现有表达式的关系类型。以下是所有关系类型的表格,以及它们的rop
和rel_op
值:
Relation | rop |
rel_op |
---|---|---|
Equality |
== or eq or None |
== |
Unequality |
!= or ne |
!= |
GreaterThan |
>= or ge |
>= |
LessThan |
<= or le |
<= |
StrictGreaterThan |
> or gt |
> |
StrictLessThan |
< or lt |
< |
例如,将rop
设置为==
会产生一个Equality
关系,Eq()
。设置rop
为eq
或不指定rop
也是如此。也就是说,下面的前三个Rel()
都会产生相同的结果。使用表中不同行的rop
,例如,将rop
设置为lt
会产生一个StrictLessThan
不等式:
>>> from sympy import Rel
>>> from sympy.abc import x, y
>>> Rel(y, x + x**2, '==')
Eq(y, x**2 + x)
>>> Rel(y, x + x**2, 'eq')
Eq(y, x**2 + x)
>>> Rel(y, x + x**2)
Eq(y, x**2 + x)
>>> Rel(y, x + x**2, 'lt')
y < x**2 + x
要获得现有表达式的关系类型,请获取其rel_op
属性。例如,上述Equality
关系的rel_op
为==
,上述严格小于不等式的rel_op
为<
:
>>> from sympy import Rel
>>> from sympy.abc import x, y
>>> my_equality = Rel(y, x + x**2, '==')
>>> my_equality.rel_op
'=='
>>> my_inequality = Rel(y, x + x**2, 'lt')
>>> my_inequality.rel_op
'<'
property canonical
通过在 rhs 上放置一个数字、规范地移除一个符号或以规范的顺序对 args 进行排序来返回关系的规范形式。不尝试进行其他简化。
示例
>>> from sympy.abc import x, y
>>> x < 2
x < 2
>>> _.reversed.canonical
x < 2
>>> (-y < x).canonical
x > -y
>>> (-y > x).canonical
x < -y
>>> (-y < -x).canonical
x < y
规范化递归应用:
>>> from sympy import Eq
>>> Eq(x < y, y > x).canonical
True
equals(other, failing_expression=False)
如果关系的两侧在数学上完全相同且关系类型相同,则返回 True。如果failing_expression
为 True,则返回其真值未知的表达式。
property lhs
关系的左侧。
property negated
返回否定的关系。
示例
>>> from sympy import Eq
>>> from sympy.abc import x
>>> Eq(x, 1)
Eq(x, 1)
>>> _.negated
Ne(x, 1)
>>> x < 1
x < 1
>>> _.negated
x >= 1
笔记
这与~
/Not
基本相同。不同之处在于,即使evaluate=False
,negated
也返回关系。因此,在代码中检查例如反向的关系时非常有用,因为它不受(evaluate)标志的影响。
property reversed
返回两侧关系颠倒。
示例
>>> from sympy import Eq
>>> from sympy.abc import x
>>> Eq(x, 1)
Eq(x, 1)
>>> _.reversed
Eq(1, x)
>>> x < 1
x < 1
>>> _.reversed
1 > x
property reversedsign
返回带有符号反转的关系。
示例
>>> from sympy import Eq
>>> from sympy.abc import x
>>> Eq(x, 1)
Eq(x, 1)
>>> _.reversedsign
Eq(-x, -1)
>>> x < 1
x < 1
>>> _.reversedsign
-x > -1
property rhs
关系的右侧。
property strict
返回严格版本的不等式或自身
示例
>>> from sympy.abc import x
>>> (x <= 1).strict
x < 1
>>> _.strict
x < 1
property weak
返回非严格版本的不等式或自身
示例
>>> from sympy.abc import x
>>> (x < 1).weak
x <= 1
>>> _.weak
x <= 1
sympy.core.relational.Rel
别名为Relational
sympy.core.relational.Eq
别名为Equality
sympy.core.relational.Ne
别名为Unequality
sympy.core.relational.Lt
别名为StrictLessThan
sympy.core.relational.Le
别名为LessThan
sympy.core.relational.Gt
别名为StrictGreaterThan
sympy.core.relational.Ge
别名为GreaterThan
class sympy.core.relational.Equality(lhs, rhs, **options)
两个对象之间的相等关系。
解释
表示两个对象相等。如果可以轻松地显示它们明确相等(或不相等),则会简化为 True(或 False)。否则,关系将保持为未评估的 Equality 对象。对此对象使用simplify
函数以进行更复杂的等式关系评估。
通常,可以使用关键字参数evaluate=False
来防止任何评估。
示例
>>> from sympy import Eq, simplify, exp, cos
>>> from sympy.abc import x, y
>>> Eq(y, x + x**2)
Eq(y, x**2 + x)
>>> Eq(2, 5)
False
>>> Eq(2, 5, evaluate=False)
Eq(2, 5)
>>> _.doit()
False
>>> Eq(exp(x), exp(x).rewrite(cos))
Eq(exp(x), sinh(x) + cosh(x))
>>> simplify(_)
True
笔记
Python 将 1 和 True(以及 0 和 False)视为相等;SymPy 则不是。整数将始终与布尔值比较为不相等:
>>> Eq(True, 1), True == 1
(False, True)
这个类与 == 操作符不同。== 操作符用于测试两个表达式之间的精确结构相等性;而这个类则是数学上比较表达式。
如果任何一个对象定义了 _eval_Eq
方法,则可以用它来替换默认算法。如果 lhs._eval_Eq(rhs)
或 rhs._eval_Eq(lhs)
返回除 None 外的任何值,则该返回值将替换等式。如果 _eval_Eq
返回 None,则将像往常一样创建一个等式对象。
由于此对象已经是一个表达式,如果尝试从 Eq(x, y)
创建 (x - y),它不会响应 as_expr
方法。如果 eq = Eq(x, y)
,则写 (eq.lhs - eq.rhs) 可以得到 x - y
。
自版本 1.5 弃用:Eq(expr)
的单个参数是 Eq(expr, 0)
的简写,但这种行为已弃用,将在 SymPy 的未来版本中移除。
另见
sympy.logic.boolalg.Equivalent
用于表示两个布尔表达式之间的相等性
as_poly(*gens, **kwargs)
返回 lhs-rhs 作为多项式
示例
>>> from sympy import Eq
>>> from sympy.abc import x
>>> Eq(x**2, 1).as_poly(x)
Poly(x**2 - 1, x, domain='ZZ')
integrate(*args, **kwargs)
参见 sympy.integrals 中的 integrate 函数
class sympy.core.relational.GreaterThan(lhs, rhs, **options)
表示不等式的类。
解释
*Than
类表示不等关系,其中左侧通常比右侧大或小。例如,GreaterThan 类表示不等关系,其中左侧至少与右侧一样大,如果不是更大的话。在数学符号中表示为:
lhs (\ge) rhs
总共有四个 *Than
类,用于表示四种不等式:
类名 | 符号 |
---|---|
GreaterThan | >= |
LessThan | <= |
StrictGreaterThan | > |
StrictLessThan | < |
所有类都接受两个参数,lhs 和 rhs。
签名示例 | 数学等价物 |
---|---|
GreaterThan(lhs, rhs) | lhs (\ge) rhs |
LessThan(lhs, rhs) | lhs (\le) rhs |
StrictGreaterThan(lhs, rhs) | lhs (>) rhs |
StrictLessThan(lhs, rhs) | lhs (<) rhs |
除了关系的正常 .lhs 和 .rhs 外,*Than
不等式对象还具有 .lts 和 .gts 属性,分别表示“小于侧”和“大于侧”的运算符。在算法中使用 .lts 和 .gts 而不是 .lhs 和 .rhs 作为不等方向的假设,会更明确地表达某一段代码的意图,并使其对客户端代码的更改更具鲁棒性:
>>> from sympy import GreaterThan, StrictGreaterThan
>>> from sympy import LessThan, StrictLessThan
>>> from sympy import And, Ge, Gt, Le, Lt, Rel, S
>>> from sympy.abc import x, y, z
>>> from sympy.core.relational import Relational
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> '%s >= %s is the same as %s <= %s' % (e.gts, e.lts, e.lts, e.gts)
'x >= 1 is the same as 1 <= x'
示例
通常不直接实例化这些类,而是使用各种便利方法:
>>> for f in [Ge, Gt, Le, Lt]: # convenience wrappers
... print(f(x, 2))
x >= 2
x > 2
x <= 2
x < 2
另一个选择是直接使用 Python 的不等式运算符(>=
、>
、<=
、<
)。它们相对于 Ge
、Gt
、Le
和 Lt
的优势在于,可以编写更“数学化”的语句,而不是在数学中散布奇怪的函数调用。但是,还有一些需要注意的(次要)注意事项(请搜索下面的‘注意事项’)。
>>> x >= 2
x >= 2
>>> _ == Ge(x, 2)
True
但是,也完全可以不那么简洁和方便地实例化一个 *Than
类:
>>> Rel(x, 1, ">")
x > 1
>>> Relational(x, 1, ">")
x > 1
>>> StrictGreaterThan(x, 1)
x > 1
>>> GreaterThan(x, 1)
x >= 1
>>> LessThan(x, 1)
x <= 1
>>> StrictLessThan(x, 1)
x < 1
注意事项
当使用 Python 的运算符时,有几个需要注意的地方。
第一个是你写的不一定是你得到的:
>>> 1 < x x > 1
由于 Python 解析语句的顺序,它可能不会立即找到两个可比较的对象。当评估
1 < x
时,Python 认识到数字 1 是本地数,而 x 不是。因为本地 Python 数字不知道如何与 SymPy 对象进行比较,Python 将尝试反射操作,x > 1
,这是被评估的形式,因此返回。如果语句的顺序很重要(例如对于控制台的视觉输出),可以通过以下几种方法来解决这个问题:
- 在比较之前“sympify”文字
>>> S(1) < x 1 < x
(2) 使用其中一个包装器或上述 less 方法
>>> Lt(1, x) 1 < x >>> Relational(1, x, "<") 1 < x
第二个需要注意的地方涉及在文字关系涉及等式测试时写等式:
>>> e = x < 1; e x < 1 >>> e == e # neither side is a literal True >>> e == x < 1 # expecting True, too False >>> e != x < 1 # expecting False x < 1 >>> x < 1 != x < 1 # expecting False or the same thing as before Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
解决此问题的方法是将文字关系用括号括起来:
>>> e == (x < 1) True >>> e != (x < 1) False >>> (x < 1) != (x < 1) False
第三个需要注意的地方涉及不涉及 ==
或 !=
的链式不等式。偶尔,人们可能会尝试写成:
>>> e = x < y < z Traceback (most recent call last): ... TypeError: symbolic boolean expression has no truth value.
由于 Python 的实现细节或决策 [R146],SymPy 无法使用该语法创建链式不等式,因此必须使用 And:
>>> e = And(x < y, y < z) >>> type( e ) And >>> e (x < y) & (y < z)
尽管这也可以使用‘&’运算符完成,但不能使用‘and’运算符完成:
>>> (x < y) & (y < z) (x < y) & (y < z) >>> (x < y) and (y < z) Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
[R146]
Python 的实现细节是,它没有可靠的方法来确定正在构建链式不等式。链式比较运算符按对分析,使用and
逻辑进行评估(参见 docs.python.org/3/reference/expressions.html#not-in
)。这样做是高效的,因此每个比较的对象只评估一次,比较可以短路。例如,Python 将 1 > 2 > 3
评估为 (1 > 2) and (2 > 3)
。and
运算符将每一侧强制转换为 bool,在短路时返回对象本身。由于 -Than 运算符会有意引发 TypeError,因为 SymPy 无法确定符号表达式的数学顺序。因此,如果我们计算 x > y > z
,其中 x
、y
和 z
是符号,Python 大致将语句转换为以下步骤:
- x > y > z
- (x > y) 和 (y > z)
- (GreaterThanObject) 和 (y > z)
- (GreaterThanObject.bool()) 和 (y > z)
- TypeError
由于第二步添加了 and
,语句变成了一个弱三元语句,并且第一个对象的 __bool__
方法会引发 TypeError。因此,创建链式不等式是不可能的。
在 Python 中,无法重写
and
运算符,或控制其短路的方式,因此无法使类似x > y > z
的表达式起作用。曾经有一个 PEP 提议修改此行为,PEP 335,但该提议在 2012 年 3 月正式关闭。
class sympy.core.relational.LessThan(lhs, rhs, **options)
类不等式的表示。
解释
*Than
类表示不等关系,其中左侧通常比右侧大或小。例如,GreaterThan 类表示一种不等关系,其中左侧至少与右侧一样大,如果不是更大。在数学符号中:
lhs (\ge) rhs
总共有四个*Than
类,用于表示四种不等式:
类名 | 符号 |
---|---|
大于 | >= |
小于 | <= |
严格大于 | > |
严格小于 | < |
所有类都接受两个参数,lhs 和 rhs。
签名示例 | 数学等效物 |
---|---|
大于(lhs,rhs) | lhs (\ge) rhs |
小于(lhs,rhs) | lhs (\le) rhs |
严格大于(lhs,rhs) | lhs (>) rhs |
严格小于(lhs,rhs) | lhs (<) rhs |
除了 Relations 的正常.lhs 和.rhs 之外,*Than
不等式对象还具有.lts 和.gts 属性,它们分别表示操作符的“小于侧”和“大于侧”。在算法中使用.lts 和.gts 而不是.lhs 和.rhs 作为不等方向的假设,将更明确地表达特定代码段的意图,并使其对客户端代码变更更加鲁棒:
>>> from sympy import GreaterThan, StrictGreaterThan
>>> from sympy import LessThan, StrictLessThan
>>> from sympy import And, Ge, Gt, Le, Lt, Rel, S
>>> from sympy.abc import x, y, z
>>> from sympy.core.relational import Relational
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> '%s >= %s is the same as %s <= %s' % (e.gts, e.lts, e.lts, e.gts)
'x >= 1 is the same as 1 <= x'
示例
通常不直接实例化这些类,而是使用各种便利方法:
>>> for f in [Ge, Gt, Le, Lt]: # convenience wrappers
... print(f(x, 2))
x >= 2
x > 2
x <= 2
x < 2
另一种选择是直接使用 Python 的不等运算符(>=
,>
,<=
,<
)。它们相对于Ge
,Gt
,Le
和Lt
的优势在于可以编写更“数学化”的语句,而不是用奇怪的函数调用来弄乱数学表达。但是也有一些(轻微的)注意事项需要注意(在下面搜索“坑”)。
>>> x >= 2
x >= 2
>>> _ == Ge(x, 2)
True
但也完全可以不那么简洁和方便地实例化*Than
类:
>>> Rel(x, 1, ">")
x > 1
>>> Relational(x, 1, ">")
x > 1
>>> StrictGreaterThan(x, 1)
x > 1
>>> GreaterThan(x, 1)
x >= 1
>>> LessThan(x, 1)
x <= 1
>>> StrictLessThan(x, 1)
x < 1
注意事项
使用 Python 运算符时要注意的一些“坑”。
第一个问题是你所写的并不总是你得到的:
>>> 1 < x x > 1
由于 Python 解析语句的顺序,可能无法立即找到两个可比较的对象。当评估
1 < x
时,Python 认识到数字 1 是本机数字,而 x 不是。因为本机 Python 数字不知道如何与 SymPy 对象比较,Python 将尝试反射操作x > 1
,这是评估的形式,因此返回。如果语句的顺序很重要(例如用于控制台的可视输出),可以通过几种方式解决这个问题:
- 将字面量转换为符号进行比较
>>> S(1) < x 1 < x
(2)使用上述包装器或较不简洁的方法之一
>>> Lt(1, x) 1 < x >>> Relational(1, x, "<") 1 < x
第二个需要注意的地方涉及在关系测试中写入一个或两个测试的文字关系时。
>>> e = x < 1; e x < 1 >>> e == e # neither side is a literal True >>> e == x < 1 # expecting True, too False >>> e != x < 1 # expecting False x < 1 >>> x < 1 != x < 1 # expecting False or the same thing as before Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
对于这种情况的解决方法是将文字关系放在括号中:
>>> e == (x < 1) True >>> e != (x < 1) False >>> (x < 1) != (x < 1) False
第三个需要注意的地方涉及不涉及 ==
或 !=
的链式不等式。有时会有人试图写成:
>>> e = x < y < z Traceback (most recent call last): ... TypeError: symbolic boolean expression has no truth value.
由于 Python 的一个实现细节或决定[R147],SymPy 无法使用该语法创建链式不等式,因此必须使用 And:
>>> e = And(x < y, y < z) >>> type( e ) And >>> e (x < y) & (y < z)
尽管这也可以使用 ‘&’ 操作符完成,但不能使用 ‘and’ 操作符:
>>> (x < y) & (y < z) (x < y) & (y < z) >>> (x < y) and (y < z) Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
[R147]
Python 中的这个实现细节是,它没有可靠的方法来确定是否正在构建链式不等式。链式比较运算符会成对地进行评估,使用and
逻辑(参见 docs.python.org/3/reference/expressions.html#not-in
)。这样做的效率很高,因此每个比较的对象只评估一次,比较可以短路。例如,1 > 2 > 3
在 Python 中被评估为 (1 > 2) and (2 > 3)
。and
操作符会将每一侧强制转换为布尔值,在短路时返回对象本身。比较运算符的布尔值会故意引发 TypeError,因为 SymPy 无法确定符号表达式的数学顺序。因此,如果我们计算 x > y > z
,其中 x
、y
和 z
是符号,Python 大致将该语句转换为以下步骤:
- x > y > z
- (x > y) and (y > z)
- (GreaterThanObject) 和 (y > z)
- (GreaterThanObject.bool()) 和 (y > z)
- TypeError
在第 2 步添加了 and
,语句被转换为弱三元语句,并且第一个对象的 __bool__
方法将引发 TypeError。因此,创建链式不等式是不可能的。
在 Python 中,无法重写
and
操作符,或控制它如何短路,因此不可能使类似x > y > z
的表达式工作。曾有一个 PEP 提议改变这一点,PEP 335,但它在 2012 年 3 月正式关闭。
class sympy.core.relational.Unequality(lhs, rhs, **options)
两个对象之间的不等关系。
解释
表示两个对象不相等。如果可以确定它们是相等的,则结果将减少为 False;如果确定它们不相等,则结果将减少为 True。否则,关系将保持为 Unequality 对象。
示例
>>> from sympy import Ne
>>> from sympy.abc import x, y
>>> Ne(y, x+x**2)
Ne(y, x**2 + x)
注意
这个类与 != 操作符不同。!= 操作符测试两个表达式之间的结构完全相等性;而这个类则是数学上比较表达式。
这个类实际上是 Equality 的反义。因此,它使用相同的算法,包括任何可用的_eval_Eq 方法。
另请参见
Equality
class sympy.core.relational.StrictGreaterThan(lhs, rhs, **options)
不等式的类表示。
解释
*Than
类表示不等关系,其中左侧通常比右侧大或小。例如,GreaterThan 类表示一个不等关系,其中左侧至少与右侧一样大,如果不是更大的话。在数学符号中:
lhs (\ge) rhs
总共有四个 *Than
类,用于表示四种不等式:
类名 | 符号 |
---|---|
GreaterThan | >= |
LessThan | <= |
StrictGreaterThan | > |
StrictLessThan | < |
所有类都接受两个参数,lhs 和 rhs。
Signature Example | Math Equivalent |
---|---|
GreaterThan(lhs, rhs) | lhs (\ge) rhs |
LessThan(lhs, rhs) | lhs (\le) rhs |
StrictGreaterThan(lhs, rhs) | lhs (>) rhs |
StrictLessThan(lhs, rhs) | lhs (<) rhs |
除了关系的正常 .lhs 和 .rhs 之外,*Than
不等式对象还具有 .lts 和 .gts 属性,分别表示操作符的“小于一侧”和“大于一侧”。在算法中使用 .lts 和 .gts 而不是 .lhs 和 .rhs 作为不等式方向的假设,将更明确地表达代码的意图,并使其对客户端代码的更改同样更健壮:
>>> from sympy import GreaterThan, StrictGreaterThan
>>> from sympy import LessThan, StrictLessThan
>>> from sympy import And, Ge, Gt, Le, Lt, Rel, S
>>> from sympy.abc import x, y, z
>>> from sympy.core.relational import Relational
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> '%s >= %s is the same as %s <= %s' % (e.gts, e.lts, e.lts, e.gts)
'x >= 1 is the same as 1 <= x'
示例
通常不直接实例化这些类,而是使用各种方便的方法:
>>> for f in [Ge, Gt, Le, Lt]: # convenience wrappers
... print(f(x, 2))
x >= 2
x > 2
x <= 2
x < 2
另一种选择是直接使用 Python 的不等式操作符 (>=
, >
, <=
, <
)。它们相比于 Ge
, Gt
, Le
, 和 Lt
类的主要优势在于可以编写更“数学化”的语句,而不是用怪异的函数调用来散布数学公式。但是,有一些(轻微的)需要注意的小问题(搜索以下的 ‘gotcha’)。
>>> x >= 2
x >= 2
>>> _ == Ge(x, 2)
True
然而,也可以不那么简洁和方便地实例化 *Than
类:
>>> Rel(x, 1, ">")
x > 1
>>> Relational(x, 1, ">")
x > 1
>>> StrictGreaterThan(x, 1)
x > 1
>>> GreaterThan(x, 1)
x >= 1
>>> LessThan(x, 1)
x <= 1
>>> StrictLessThan(x, 1)
x < 1
注意
使用 Python 操作符时,有几个“gotcha”需要注意。
第一个是你所写的并不总是你所得到的:
>>> 1 < x x > 1
由于 Python 解析语句的顺序,可能不会立即找到两个可比较的对象。当评估
1 < x
时,Python 识别到数字 1 是本机数字,而 x 不是。因为本机 Python 数字不知道如何与 SymPy 对象比较,Python 将尝试反射操作x > 1
,这是评估的形式,因此返回。如果语句的顺序很重要(例如视觉输出到控制台),可以通过几种方式来解决这个烦恼:
- 在比较之前“符号化”文字
>>> S(1) < x 1 < x
(2) 使用以上描述的包装器或不那么简洁的方法之一
>>> Lt(1, x) 1 < x >>> Relational(1, x, "<") 1 < x
第二个“gotcha”涉及在文字关系涉及的测试之间写相等测试时,其中一个或两个测试的一侧涉及文字关系:
>>> e = x < 1; e x < 1 >>> e == e # neither side is a literal True >>> e == x < 1 # expecting True, too False >>> e != x < 1 # expecting False x < 1 >>> x < 1 != x < 1 # expecting False or the same thing as before Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
对于这种情况的解决方案是将文字关系包裹在括号中:
>>> e == (x < 1) True >>> e != (x < 1) False >>> (x < 1) != (x < 1) False
第三个“gotcha”涉及链式不等式,不涉及 ==
或 !=
。偶尔,人们可能会想要写:
>>> e = x < y < z Traceback (most recent call last): ... TypeError: symbolic boolean expression has no truth value.
由于 Python 的一个实现细节或决定[R148],SymPy 无法使用该语法创建链式不等式,因此必须使用 And:
>>> e = And(x < y, y < z) >>> type( e ) And >>> e (x < y) & (y < z)
尽管这也可以通过‘&’运算符来实现,但不能使用‘and’运算符:
>>> (x < y) & (y < z) (x < y) & (y < z) >>> (x < y) and (y < z) Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
[R148]
这个实现细节是 Python 没有可靠的方法来确定是否正在构建链式不等式。链式比较操作符会成对地使用and
逻辑进行评估(参见docs.python.org/3/reference/expressions.html#not-in
)。这是一种高效的方式,使得每个比较对象只被评估一次,并且可以短路。例如,Python 将1 > 2 > 3
评估为(1 > 2) and (2 > 3)
。and
运算符会将每一侧强制转换为 bool 值,在短路时返回对象本身。--Than 运算符的 bool 值将故意引发 TypeError,因为 SymPy 无法确定符号表达式的数学排序。因此,如果我们计算x > y > z
,其中x
、y
和z
是符号,Python 将大致将语句转换为以下步骤:
- x > y > z
- (x > y) and (y > z)
- (GreaterThanObject) and (y > z)
- (GreaterThanObject.bool()) and (y > z)
- TypeError
由于在第二步中添加了and
,语句变成了一个弱三元语句,并且第一个对象的__bool__
方法将引发 TypeError。因此,创建链式不等式是不可能的。
在 Python 中,没有办法重写
and
运算符,或者控制它如何短路,因此无法使类似于x > y > z
的东西工作。曾经有一个 PEP 尝试改变这一点,PEP 335,但于 2012 年 3 月正式关闭。
class sympy.core.relational.StrictLessThan(lhs, rhs, **options)
不等式的类表示。
解释
*Than
类表示不等关系,其中左侧通常大于或小于右侧。例如,GreaterThan 类表示一个不等关系,其中左侧至少与右侧一样大,如果不是更大。在数学符号中表示为:
lhs (\ge) rhs
总共有四个*Than
类,用来表示四种不等式:
Class Name | Symbol |
---|---|
GreaterThan | >= |
LessThan | <= |
StrictGreaterThan | > |
StrictLessThan | < |
所有类都接受两个参数,lhs 和 rhs。
Signature Example | Math Equivalent |
---|---|
GreaterThan(lhs, rhs) | lhs (\ge) rhs |
LessThan(lhs, rhs) | lhs (\le) rhs |
StrictGreaterThan(lhs, rhs) | lhs (>) rhs |
StrictLessThan(lhs, rhs) | lhs (<) rhs |
除了常规的 .lhs 和 .rhs 关系外,*Than
不等式对象还具有 .lts 和 .gts 属性,分别表示运算符的“小于侧”和“大于侧”。在算法中使用 .lts 和 .gts 而不是 .lhs 和 .rhs 作为不等式方向的假设,将更明确地表达某段代码的意图,并使其对客户端代码更加鲁棒:
>>> from sympy import GreaterThan, StrictGreaterThan
>>> from sympy import LessThan, StrictLessThan
>>> from sympy import And, Ge, Gt, Le, Lt, Rel, S
>>> from sympy.abc import x, y, z
>>> from sympy.core.relational import Relational
>>> e = GreaterThan(x, 1)
>>> e
x >= 1
>>> '%s >= %s is the same as %s <= %s' % (e.gts, e.lts, e.lts, e.gts)
'x >= 1 is the same as 1 <= x'
示例
通常不直接实例化这些类,而是使用各种便利方法:
>>> for f in [Ge, Gt, Le, Lt]: # convenience wrappers
... print(f(x, 2))
x >= 2
x > 2
x <= 2
x < 2
另一个选择是直接使用 Python 的不等式运算符(>=
, >
, <=
, <
)。它们与 Ge
, Gt
, Le
, Lt
等对应的主要优势在于,可以编写更“数学化”的语句,而不是用奇怪的函数调用来弄乱数学表达式。但是,需要注意其中的某些(小)注意事项(下文搜索‘gotcha’)。
>>> x >= 2
x >= 2
>>> _ == Ge(x, 2)
True
然而,实例化一个 *Than
类的方式虽然不太简洁且不太方便,但也是完全有效的:
>>> Rel(x, 1, ">")
x > 1
>>> Relational(x, 1, ">")
x > 1
>>> StrictGreaterThan(x, 1)
x > 1
>>> GreaterThan(x, 1)
x >= 1
>>> LessThan(x, 1)
x <= 1
>>> StrictLessThan(x, 1)
x < 1
注意
使用 Python 运算符时,需要注意几个“gotcha”。
第一个注意事项是,你写的内容并不总是你得到的内容:
>>> 1 < x x > 1
由于 Python 解析语句的顺序,可能不会立即找到两个可比较的对象。当评估
1 < x
时,Python 会识别数字 1 是本地数字,而 x 则不是。因为本地 Python 数字不知道如何与 SymPy 对象比较,Python 将尝试反射操作x > 1
,这是被评估和返回的形式。如果语句的顺序很重要(例如用于控制台的可视输出),可以通过几种方法避免这种烦恼:
- 在比较之前“符号化”字面值
>>> S(1) < x 1 < x
(2) 使用上述其中一个包装器或不太简洁的方法
>>> Lt(1, x) 1 < x >>> Relational(1, x, "<") 1 < x
第二个注意事项涉及在关系之间写等式测试时,当测试的一侧或两侧涉及字面关系时:
>>> e = x < 1; e x < 1 >>> e == e # neither side is a literal True >>> e == x < 1 # expecting True, too False >>> e != x < 1 # expecting False x < 1 >>> x < 1 != x < 1 # expecting False or the same thing as before Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
对于这种情况的解决方案是,将字面不等式用括号括起来:
>>> e == (x < 1) True >>> e != (x < 1) False >>> (x < 1) != (x < 1) False
第三个注意事项涉及链式不等式,不涉及 ==
或 !=
。偶尔,你可能会想要写:
>>> e = x < y < z Traceback (most recent call last): ... TypeError: symbolic boolean expression has no truth value.
由于 Python 的实现细节或决策 [R149],SymPy 无法使用该语法创建链式不等式,因此必须使用 And:
>>> e = And(x < y, y < z) >>> type( e ) And >>> e (x < y) & (y < z)
尽管可以使用 ‘&’ 运算符来完成此操作,但无法使用 ‘and’ 运算符:
>>> (x < y) & (y < z) (x < y) & (y < z) >>> (x < y) and (y < z) Traceback (most recent call last): ... TypeError: cannot determine truth value of Relational
[R149]
这个实现细节是 Python 没有可靠的方法来确定是否正在构建一个链式不等式。链式比较运算符使用and
逻辑成对评估(见docs.python.org/3/reference/expressions.html#not-in
)。这样做是为了高效地,使得每个被比较的对象仅被评估一次,并且比较可以短路。例如,1 > 2 > 3
在 Python 中被评估为(1 > 2) and (2 > 3)
。and
运算符将每一侧强制转换为 bool,在短路时返回对象本身。--Than 运算符的 bool 故意引发类型错误,因为 SymPy 无法确定符号表达式的数学排序。因此,如果我们计算x > y > z
,其中x
,y
和z
是 Symbols,Python 大致将语句转换为以下步骤:
- x > y > z
- (x > y) and (y > z)
- (GreaterThanObject) and (y > z)
- (GreaterThanObject.bool()) and (y > z)
- 类型错误
由于第 2 步添加的and
,语句变成了一个弱三元语句,并且第一个对象的__bool__
方法将引发类型错误。因此,创建一个链式不等式是不可能的。
在 Python 中,无法重写
and
运算符,或控制其短路的方式,因此无法使类似x > y > z
的语法生效。曾有一份 PEP 提案试图改变这一点,PEP 335,但于 2012 年 3 月正式关闭。 ## 多维
class sympy.core.multidimensional.vectorize(*mdargs)
将标量转为接受多维参数的函数。
例子
>>> from sympy import vectorize, diff, sin, symbols, Function
>>> x, y, z = symbols('x y z')
>>> f, g, h = list(map(Function, 'fgh'))
>>> @vectorize(0)
... def vsin(x):
... return sin(x)
>>> vsin([1, x, y])
[sin(1), sin(x), sin(y)]
>>> @vectorize(0, 1)
... def vdiff(f, y):
... return diff(f, y)
>>> vdiff([f(x, y, z), g(x, y, z), h(x, y, z)], [x, y, z])
[[Derivative(f(x, y, z), x), Derivative(f(x, y, z), y), Derivative(f(x, y, z), z)], [Derivative(g(x, y, z), x), Derivative(g(x, y, z), y), Derivative(g(x, y, z), z)], [Derivative(h(x, y, z), x), Derivative(h(x, y, z), y), Derivative(h(x, y, z), z)]]
``` ## 函数
```py
class sympy.core.function.Lambda(signature, expr)
Lambda(x, expr)表示一个类似 Python 中的‘lambda x: expr’的 lambda 函数。具有多个变量的函数写作为 Lambda((x, y, …), expr)。
例子
一个简单的例子:
>>> from sympy import Lambda
>>> from sympy.abc import x
>>> f = Lambda(x, x**2)
>>> f(4)
16
对于多变量函数,请使用:
>>> from sympy.abc import y, z, t
>>> f2 = Lambda((x, y, z, t), x + y**z + t**z)
>>> f2(1, 2, 3, 4)
73
也可以解包元组参数:
>>> f = Lambda(((x, y), z), x + y + z)
>>> f((1, 2), 3)
6
多个参数的便捷快捷方式:
>>> p = x, y, z
>>> f = Lambda(p, x + y*z)
>>> f(*p)
x + y*z
property bound_symbols
用于函数内部表示的变量
property expr
函数的返回值
property is_identity
如果这个Lambda
是一个恒等函数,则返回True
。
property signature
要解包为变量的参数的预期形式
property variables
用于函数内部表示的变量
class sympy.core.function.WildFunction(*args)
WildFunction 函数匹配任何函数(及其参数)。
例子
>>> from sympy import WildFunction, Function, cos
>>> from sympy.abc import x, y
>>> F = WildFunction('F')
>>> f = Function('f')
>>> F.nargs
Naturals0
>>> x.match(F)
>>> F.match(F)
{F_: F_}
>>> f(x).match(F)
{F_: f(x)}
>>> cos(x).match(F)
{F_: cos(x)}
>>> f(x, y).match(F)
{F_: f(x, y)}
要匹配具有给定参数数量的函数,请在实例化时将nargs
设置为所需的值:
>>> F = WildFunction('F', nargs=2)
>>> F.nargs
{2}
>>> f(x).match(F)
>>> f(x, y).match(F)
{F_: f(x, y)}
要匹配具有一系列参数的函数,请将nargs
设置为包含所需参数数量的元组,例如,如果nargs = (1, 2)
,则将匹配具有 1 个或 2 个参数的函数。
>>> F = WildFunction('F', nargs=(1, 2))
>>> F.nargs
{1, 2}
>>> f(x).match(F)
{F_: f(x)}
>>> f(x, y).match(F)
{F_: f(x, y)}
>>> f(x, y, 1).match(F)
class sympy.core.function.Derivative(expr, *variables, **kwargs)
对给定表达式进行关于符号的微分。
例子
>>> from sympy import Derivative, Function, symbols, Subs
>>> from sympy.abc import x, y
>>> f, g = symbols('f g', cls=Function)
>>> Derivative(x**2, x, evaluate=True)
2*x
导数去嵌套保留变量的顺序:
>>> Derivative(Derivative(f(x, y), y), x)
Derivative(f(x, y), y, x)
连续相同符号合并为给定符号和计数的元组:
>>> Derivative(f(x), x, x, y, x)
Derivative(f(x), (x, 2), y, x)
如果无法执行导数,并且 evaluate 为 True,则将分化变量的顺序设置为规范:
>>> Derivative(f(x, y), y, x, evaluate=True)
Derivative(f(x, y), x, y)
可以计算对未定义函数的导数:
>>> Derivative(f(x)**2, f(x), evaluate=True)
2*f(x)
当链规则用于评估导数时,这样的导数会显示出来:
>>> f(g(x)).diff(x)
Derivative(f(g(x)), g(x))*Derivative(g(x), x)
替换用于表示带有非符号或函数参数的函数的导数:
>>> f(2*x + 3).diff(x) == 2*Subs(f(y).diff(y), y, 2*x + 3)
True
注意
高阶导数的简化:
因为在执行多次差异化时可以进行大量简化,所以结果将以相当保守的方式自动简化,除非关键字 simplify
设置为 False。
>>> from sympy import sqrt, diff, Function, symbols
>>> from sympy.abc import x, y, z
>>> f, g = symbols('f,g', cls=Function)
>>> e = sqrt((x + 1)**2 + x)
>>> diff(e, (x, 5), simplify=False).count_ops()
136
>>> diff(e, (x, 5)).count_ops()
30
变量的顺序:
如果 evaluate 设置为 True 并且无法评估表达式,则差异化符号列表将被排序,即假设表达式具有连续的导数直到所要求的顺序。
对非符号的导数:
大多数情况下,不可对非符号进行差异化。例如,我们不允许对 (xy) 进行差异化,因为在表达式中定义 (xy) 出现的多种方式:非常严格的定义会使得 (xyz).diff(x*y) == 0。也不允许对定义的函数(如 cos(x))进行导数计算:
>>> (x*y*z).diff(x*y)
Traceback (most recent call last):
...
ValueError: Can't calculate derivative wrt x*y.
为了更容易处理变分计算,允许对 AppliedUndef 和 Derivatives 进行导数计算。例如,在欧拉-拉格朗日方法中,可以写成 F(t, u, v),其中 u = f(t) 且 v = f’(t)。这些变量可以明确地写成时间的函数:
>>> from sympy.abc import t
>>> F = Function('F')
>>> U = f(t)
>>> V = U.diff(t)
对于 f(t) 的导数可以直接得到:
>>> direct = F(t, U, V).diff(U)
当尝试对非符号进行差异化时,将非符号暂时转换为符号,同时执行差异化,并获得相同的答案:
>>> indirect = F(t, U, V).subs(U, x).diff(x).subs(x, U)
>>> assert direct == indirect
此非符号替换的含义是,所有函数都被视为独立于其他函数,并且符号独立于包含它们的函数:
>>> x.diff(f(x))
0
>>> g(x).diff(f(x))
0
这也意味着假设导数仅依赖于差异化变量,而不依赖于被差异化表达式中的任何内容:
>>> F = f(x)
>>> Fx = F.diff(x)
>>> Fx.diff(F) # derivative depends on x, not F
0
>>> Fxx = Fx.diff(x)
>>> Fxx.diff(Fx) # derivative depends on x, not Fx
0
最后一个例子可以通过显示 Fx 在 Fxx 中用 y 替换来明确:
>>> Fxx.subs(Fx, y) Derivative(y, x)
由于这本身将评估为零,不同 iating wrt Fx 也将是零:
>>> _.doit() 0
用具体表达式替换未定义的函数
必须小心地用包含与函数定义和差异化变量一致的变量的表达式替换未定义的函数,否则将得到不一致的结果。考虑以下例子:
>>> eq = f(x)*g(y)
>>> eq.subs(f(x), x*y).diff(x, y).doit()
y*Derivative(g(y), y) + g(y)
>>> eq.diff(x, y).subs(f(x), x*y).doit()
y*Derivative(g(y), y)
结果不同,因为 (f(x)) 被替换为涉及差异化变量的表达式。在抽象情况下,对 (y) 的 (f(x)) 的差异化为 0;在具体情况下,(y) 的存在使得该导数非零,并产生额外的 (g(y)) 项。
定义对象的差异化
对象必须定义 ._eval_derivative(symbol)
方法,该方法返回微分结果。此函数仅需要考虑表达式包含符号的非平凡情况,并且应在内部调用 diff() 方法(而不是 _eval_derivative);Derivative 应是唯一调用 _eval_derivative 的对象。
任何类都可以允许相对于自身进行导数操作(同时指示其标量性质)。请参阅 Expr._diff_wrt 的文档字符串。
另请参阅
_sort_variable_count
property _diff_wrt
表达式可能相对于导数进行微分,如果它处于基本形式中。
示例
>>> from sympy import Function, Derivative, cos
>>> from sympy.abc import x
>>> f = Function('f')
>>> Derivative(f(x), x)._diff_wrt
True
>>> Derivative(cos(x), x)._diff_wrt
False
>>> Derivative(x + 1, x)._diff_wrt
False
如果评估,Derivative 可能是将不是有效的差异化变量的未评估形式。例如,
>>> Derivative(f(f(x)), x).doit()
Derivative(f(x), x)*Derivative(f(f(x)), f(x))
这样的表达式将出现与处理任何其他乘积时相同的歧义,比如 2*x
,因此 _diff_wrt
为 False:
>>> Derivative(f(f(x)), x)._diff_wrt
False
classmethod _sort_variable_count(vc)
将(变量,计数)对排序为规范顺序,同时保留在微分过程中不对易变量的顺序:
-
符号和函数彼此交换
-
导数彼此对易
-
导数不与包含的任何内容对易
-
如果它与另一个对象具有共同的自由符号,则不允许任何其他对象对易
示例
>>> from sympy import Derivative, Function, symbols
>>> vsort = Derivative._sort_variable_count
>>> x, y, z = symbols('x y z')
>>> f, g, h = symbols('f g h', cls=Function)
连续项目折叠成一个对:
>>> vsort([(x, 1), (x, 1)])
[(x, 2)]
>>> vsort([(y, 1), (f(x), 1), (y, 1), (f(x), 1)])
[(y, 2), (f(x), 2)]
排序是规范的。
>>> def vsort0(*v):
... # docstring helper to
... # change vi -> (vi, 0), sort, and return vi vals
... return [i[0] for i in vsort([(i, 0) for i in v])]
>>> vsort0(y, x)
[x, y]
>>> vsort0(g(y), g(x), f(y))
[f(y), g(x), g(y)]
符号尽可能向左移动,但绝不移动到具有其变量中相同符号的导数左侧;对于始终在符号后排序的 AppliedUndef,同样适用:
>>> dfx = f(x).diff(x)
>>> assert vsort0(dfx, y) == [y, dfx]
>>> assert vsort0(dfx, x) == [dfx, x]
as_finite_difference(points=1, x0=None, wrt=None)
将 Derivative 实例表达为有限差分。
参数:
points:序列或系数,可选
如果序列:用于生成有限差分权重的独立变量的离散值(长度>= order+1)。如果它是系数,则将用作围绕
x0
的长度为 order+1 的等距序列的步长。默认值:1(步长 1)
x0:数字或符号,可选
独立变量的值(
wrt
)是导数近似的值。默认情况下与wrt
相同。
wrt:符号,可选
“关于”用于近似(部分)导数的变量。如果未提供,则要求导数是普通的。默认值:
None
。
示例
>>> from sympy import symbols, Function, exp, sqrt, Symbol
>>> x, h = symbols('x h')
>>> f = Function('f')
>>> f(x).diff(x).as_finite_difference()
-f(x - 1/2) + f(x + 1/2)
默认步长和点数为 1 和order + 1
。我们可以通过将符号作为参数传递来更改步长:
>>> f(x).diff(x).as_finite_difference(h)
-f(-h/2 + x)/h + f(h/2 + x)/h
我们还可以指定用于序列中使用的离散化值:
>>> f(x).diff(x).as_finite_difference([x, x+h, x+2*h])
-3*f(x)/(2*h) + 2*f(h + x)/h - f(2*h + x)/(2*h)
该算法不限于使用等距间隔,也不需要围绕 x0
进行近似,但我们可以得到一个表达式,估计在偏移处的导数:
>>> e, sq2 = exp(1), sqrt(2)
>>> xl = [x-h, x+h, x+e*h]
>>> f(x).diff(x, 1).as_finite_difference(xl, x+h*sq2)
2*h*((h + sqrt(2)*h)/(2*h) - (-sqrt(2)*h + h)/(2*h))*f(E*h + x)/...
要使用非等距间隔步骤近似 Derivative
环绕 x0
,算法支持将未定义函数分配给 points
:
>>> dx = Function('dx')
>>> f(x).diff(x).as_finite_difference(points=dx(x), x0=x-h)
-f(-h + x - dx(-h + x)/2)/dx(-h + x) + f(-h + x + dx(-h + x)/2)/dx(-h + x)
也支持偏导数:
>>> y = Symbol('y')
>>> d2fdxdy=f(x,y).diff(x,y)
>>> d2fdxdy.as_finite_difference(wrt=x)
-Derivative(f(x - 1/2, y), y) + Derivative(f(x + 1/2, y), y)
我们可以在复合表达式中对 Derivative
实例应用 as_finite_difference
,使用 replace
:
>>> (1 + 42**f(x).diff(x)).replace(lambda arg: arg.is_Derivative,
... lambda arg: arg.as_finite_difference())
42**(-f(x - 1/2) + f(x + 1/2)) + 1
另请参阅
sympy.calculus.finite_diff.apply_finite_diff
, sympy.calculus.finite_diff.differentiate_finite
, sympy.calculus.finite_diff.finite_diff_weights
doit_numerically(z0)
在数值上评估导数在 z
处的值。
当我们能够表示点上的导数时,这应该折叠到普通的 evalf
中。目前,我们需要一个特殊的方法。
sympy.core.function.diff(f, *symbols, **kwargs)
对符号求解 f
的导数。
解释
这只是一个包装器,用于统一 .diff()
和 Derivative
类;其接口类似于 integrate()
。您可以像对待 Derivative
一样对多个变量使用相同的快捷方式。例如,diff(f(x), x, x, x)
和 diff(f(x), x, 3)
都返回 f(x)
的三阶导数。
您可以传递 evaluate=False
以获取未评估的 Derivative
类。请注意,如果没有符号(例如 diff(f(x), x, 0)
),则结果将是函数(零阶导数),即使 evaluate=False
。
示例
>>> from sympy import sin, cos, Function, diff
>>> from sympy.abc import x, y
>>> f = Function('f')
>>> diff(sin(x), x)
cos(x)
>>> diff(f(x), x, x, x)
Derivative(f(x), (x, 3))
>>> diff(f(x), x, 3)
Derivative(f(x), (x, 3))
>>> diff(sin(x)*cos(y), x, 2, y, 2)
sin(x)*cos(y)
>>> type(diff(sin(x), x))
cos
>>> type(diff(sin(x), x, evaluate=False))
<class 'sympy.core.function.Derivative'>
>>> type(diff(sin(x), x, 0))
sin
>>> type(diff(sin(x), x, 0, evaluate=False))
sin
>>> diff(sin(x))
cos(x)
>>> diff(sin(x*y))
Traceback (most recent call last):
...
ValueError: specify differentiation variables to differentiate sin(x*y)
注意 diff(sin(x))
的语法仅用于交互式会话的便利性,应避免在库代码中使用。
另请参阅
Derivative
idiff
隐式计算导数
参考
[R150]
reference.wolfram.com/legacy/v5_2/Built-inFunctions/AlgebraicComputation/Calculus/D.html
class sympy.core.function.FunctionClass(*args, **kwargs)
函数类的基类。FunctionClass
是 type
的子类。
使用 Function('<function name>' [, 签名])
创建未定义函数类。
property nargs
返回函数允许的参数数量的集合。
示例
>>> from sympy import Function
>>> f = Function('f')
如果函数可以接受任意数量的参数,则返回整数集合:
>>> Function('f').nargs
Naturals0
如果函数被初始化为接受一个或多个参数,则将返回相应的集合:
>>> Function('f', nargs=1).nargs
{1}
>>> Function('f', nargs=(2, 1)).nargs
{1, 2}
在应用后,未定义的函数也具有 nargs
属性;通过检查 args
属性始终可以获得实际的参数数量:
>>> f = Function('f')
>>> f(1).nargs
Naturals0
>>> len(f(1).args)
1
class sympy.core.function.Function(*args)
应用数学函数的基类。
它还充当未定义函数类的构造函数。
有关如何子类化 Function
和可以定义哪些方法的详细信息,请参见编写自定义函数指南。
示例
未定义函数
要创建一个未定义的函数,请将函数名称的字符串传递给 Function
。
>>> from sympy import Function, Symbol
>>> x = Symbol('x')
>>> f = Function('f')
>>> g = Function('g')(x)
>>> f
f
>>> f(x)
f(x)
>>> g
g(x)
>>> f(x).diff(x)
Derivative(f(x), x)
>>> g.diff(x)
Derivative(g(x), x)
假设可以像Symbol
一样传递给Function
。或者,您可以使用带有函数名称和假设的Symbol
来命名函数,并且函数将继承与Symbol
相关联的名称和假设:
>>> f_real = Function('f', real=True)
>>> f_real(x).is_real
True
>>> f_real_inherit = Function(Symbol('f', real=True))
>>> f_real_inherit(x).is_real
True
注意函数上的假设与调用它的变量的假设无关。如果要添加关系,请子类化Function
并定义自定义假设处理方法。请参阅 Assumptions 部分的编写自定义函数指南获取更多详细信息。
自定义函数子类
编写自定义函数指南有几个完整示例,展示了如何子类化Function
以创建自定义函数。
as_base_exp()
返回方法作为 2 元组(基数,指数)。
fdiff(argindex=1)
返回函数的第一阶导数。
classmethod is_singular(a)
检查参数是否是本质奇点或分支点,或者函数是非全纯的。
注意
并非所有函数都相同
SymPy 定义了许多函数(如cos
和factorial
)。它还允许用户创建作为参数持有者的通用函数。此类函数的创建方式与符号相同:
>>> from sympy import Function, cos
>>> from sympy.abc import x
>>> f = Function('f')
>>> f(2) + f(x)
f(2) + f(x)
如果您想查看表达式中出现的函数,可以使用 atoms 方法:
>>> e = (f(x) + cos(x) + 2)
>>> e.atoms(Function)
{f(x), cos(x)}
如果您只想要您定义的函数,而不是 SymPy 函数,请搜索 AppliedUndef:
>>> from sympy.core.function import AppliedUndef
>>> e.atoms(AppliedUndef)
{f(x)}
class sympy.core.function.Subs(expr, variables, point, **assumptions)
表示表达式的未评估替换。
Subs(expr, x, x0)
表示在 expr 中用 x0 替换 x 后得到的表达式。
参数:
expr:Expr
一个表达式。
x:元组,变量
一个变量或不同变量的列表。
x0:元组或元组列表
与这些变量相对应的点或评估点列表。
示例
>>> from sympy import Subs, Function, sin, cos
>>> from sympy.abc import x, y, z
>>> f = Function('f')
当特定替换无法进行时创建 Subs。在导数中的 x 无法替换为 0,因为 0 不是一个有效的差异化变量:
>>> f(x).diff(x).subs(x, 0)
Subs(Derivative(f(x), x), x, 0)
一旦 f 已知,就可以进行导数计算和在 0 处的评估:
>>> _.subs(f, sin).doit() == sin(x).diff(x).subs(x, 0) == cos(0)
True
Subs 也可以直接使用一个或多个变量创建:
>>> Subs(f(x)*sin(y) + z, (x, y), (0, 1))
Subs(z + f(x)*sin(y), (x, y), (0, 1))
>>> _.doit()
z + f(0)*sin(1)
注意
Subs
对象通常用于表示在某一点计算的未评估导数。
变量可以是表达式,但它们受 subs()的限制,因此通常最好仅对变量使用符号,因为在这种情况下不会有歧义。
没有自动展开 - 使用方法.doit()来影响对象及其表达式内部的所有可能的替换。
在评估非符号点处的导数时,将返回一个 Subs 对象。还可以计算 Subs 对象的导数 - 在这种情况下,表达式总是会被展开(对于未评估的形式,请使用 Derivative())。
为了允许表达式在执行时结合,内部使用 Subs 表达式的表示来使表面上不同的表达式进行比较:
>>> a, b = Subs(x, x, 0), Subs(y, y, 0)
>>> a + b
2*Subs(x, x, 0)
使用像(has)这样的方法时可能会导致意外后果,因为它们被缓存:
>>> s = Subs(x, x, 0)
>>> s.has(x), s.has(y)
(True, False)
>>> ss = s.subs(x, y)
>>> ss.has(x), ss.has(y)
(True, False)
>>> s, ss
(Subs(x, x, 0), Subs(y, y, 0))
property bound_symbols
要评估的变量
property expr
替换操作的表达式
property point
用于替换变量的值
property variables
要评估的变量
sympy.core.function.expand(e, deep=True, modulus=None, power_base=True, power_exp=True, mul=True, log=True, multinomial=True, basic=True, **hints)
使用给定的提示方法展开表达式。
解释
除非显式设置为 False,否则将评估以下提示:basic
,log
,multinomial
,mul
,power_base
和power_exp
。以下提示受支持但仅在设置为 True 时应用:complex
,func
和trig
。此外,其他提示也支持一些或所有其他提示的元提示:frac
,numer
,denom
,modulus
和force
。所有提示都支持deep
。此外,Expr 的子类还可以定义自己的提示或元提示。
basic
提示用于在调用expand
时自动完成对象的任何特殊重写(以及像mul
这样的其他提示)。这是一个捕获所有提示的提示,用于处理可能不被现有提示名称描述的任何扩展。要使用此提示,对象应重写_eval_expand_basic
方法。对象还可以定义其自己的展开方法,这些方法不会默认运行。请参阅下面的 API 部分。
如果将deep
设置为True
(默认值),诸如函数参数之类的东西将被递归展开。使用deep=False
仅在顶层展开。
如果使用了force
提示,将忽略关于变量的假设以进行展开。
提示
这些提示默认情况下会运行
Mul
在加法上分配乘法:
>>> from sympy import cos, exp, sin
>>> from sympy.abc import x, y, z
>>> (y*(x + z)).expand(mul=True)
x*y + y*z
多项式
展开(x + y + …)**n
,其中 n 是正整数。
>>> ((x + y + z)**2).expand(multinomial=True)
x**2 + 2*x*y + 2*x*z + y**2 + 2*y*z + z**2
Power_exp
将指数中的加法展开为乘以基数。
>>> exp(x + y).expand(power_exp=True)
exp(x)*exp(y)
>>> (2**(x + y)).expand(power_exp=True)
2**x*2**y
Power_base
将乘以基数的幂分开。
这仅在默认情况下发生,如果假设允许,或者使用force
元提示:
>>> ((x*y)**z).expand(power_base=True)
(x*y)**z
>>> ((x*y)**z).expand(power_base=True, force=True)
x**z*y**z
>>> ((2*y)**z).expand(power_base=True)
2**z*y**z
注意,在某些情况下,SymPy 会自动执行此展开:
>>> (x*y)**2
x**2*y**2
对数
将参数的幂作为系数提取出来,并将对数乘积分成对数和的和。
注意,这些仅在对数函数的参数具有适当假设(参数必须为正数,指数必须为实数)或者force
提示必须为 True 时才有效:
>>> from sympy import log, symbols
>>> log(x**2*y).expand(log=True)
log(x**2*y)
>>> log(x**2*y).expand(log=True, force=True)
2*log(x) + log(y)
>>> x, y = symbols('x,y', positive=True)
>>> log(x**2*y).expand(log=True)
2*log(x) + log(y)
Basic
此提示主要用于自定义子类以便默认情况下启用扩展。
这些提示默认情况下不运行:
复杂
将表达式分成实部和虚部。
>>> x, y = symbols('x,y')
>>> (x + y).expand(complex=True)
re(x) + re(y) + I*im(x) + I*im(y)
>>> cos(x).expand(complex=True)
-I*sin(re(x))*sinh(im(x)) + cos(re(x))*cosh(im(x))
注意,这只是对as_real_imag()
的包装。大多数希望重新定义_eval_expand_complex()
的对象应考虑重新定义as_real_imag()
。
函数
展开其他函数。
>>> from sympy import gamma
>>> gamma(x + 1).expand(func=True)
x*gamma(x)
三角
进行三角展开。
>>> cos(x + y).expand(trig=True)
-sin(x)*sin(y) + cos(x)*cos(y)
>>> sin(2*x).expand(trig=True)
2*sin(x)*cos(x)
注意 sin(n*x)
和 cos(n*x)
关于 sin(x)
和 cos(x)
的形式并不唯一,这是由于恒等式 (\sin²(x) + \cos²(x) = 1)。当前实现使用从切比雪夫多项式获得的形式,但这可能会改变。请参阅 这篇 MathWorld 文章 获取更多信息。
注意事项
-
您可以关闭不需要的方法:
>>> (exp(x + y)*(x + y)).expand() x*exp(x)*exp(y) + y*exp(x)*exp(y) >>> (exp(x + y)*(x + y)).expand(power_exp=False) x*exp(x + y) + y*exp(x + y) >>> (exp(x + y)*(x + y)).expand(mul=False) (x + y)*exp(x)*exp(y)
-
使用
deep=False
仅在顶层扩展:>>> exp(x + exp(x + y)).expand() exp(x)*exp(exp(x)*exp(y)) >>> exp(x + exp(x + y)).expand(deep=False) exp(x)*exp(exp(x + y))
-
提示以任意但一致的顺序应用(在当前实现中,它们按字母顺序应用,但 multinomial 在 mul 之前,但这可能会改变)。因此,某些提示可能会通过首先应用它们来阻止其他提示的扩展。例如,
mul
可能会分配乘法并阻止log
和power_base
扩展它们。此外,如果mul
在pymultinomial`, the expression might not be fully distributed. The solution is to use the various ``expand_hint
帮助函数之前应用,或者要使用hint=False
来精确控制哪些提示应用于此函数。以下是一些示例:>>> from sympy import expand, expand_mul, expand_power_base >>> x, y, z = symbols('x,y,z', positive=True) >>> expand(log(x*(y + z))) log(x) + log(y + z)
在这里,我们看到
log
在mul
之前被应用。要获取mul
的展开形式,可以使用以下任一方法:>>> expand_mul(log(x*(y + z))) log(x*y + x*z) >>> expand(log(x*(y + z)), log=False) log(x*y + x*z)
类似的情况也可能发生在
power_base
提示中:>>> expand((x*(y + z))**x) (x*y + x*z)**x
要获取
power_base
的展开形式,可以使用以下任一方法:>>> expand((x*(y + z))**x, mul=False) x**x*(y + z)**x >>> expand_power_base((x*(y + z))**x) x**x*(y + z)**x >>> expand((x + y)*y/x) y + y**2/x
可以针对有理表达式的部分进行目标化:
>>> expand((x + y)*y/x/(x + 1), frac=True) (x*y + y**2)/(x**2 + x) >>> expand((x + y)*y/x/(x + 1), numer=True) (x*y + y**2)/(x*(x + 1)) >>> expand((x + y)*y/x/(x + 1), denom=True) y*(x + y)/(x**2 + x)
-
modulus
元提示可用于在扩展后减少表达式的系数:>>> expand((3*x + 1)**2) 9*x**2 + 6*x + 1 >>> expand((3*x + 1)**2, modulus=5) 4*x**2 + x + 1
-
expand()
函数或.expand()
方法都可以使用。两者是等效的:>>> expand((x + 1)**2) x**2 + 2*x + 1 >>> ((x + 1)**2).expand() x**2 + 2*x + 1
Api
对象可以通过定义 _eval_expand_hint()
来定义其自己的扩展提示。该函数应采用以下形式:
def _eval_expand_hint(self, **hints):
# Only apply the method to the top-level expression
...
另请参阅下面的示例。对象应仅在特定对象适用于该提示时定义 _eval_expand_hint()
方法。在 Expr 中定义的通用 _eval_expand_hint()
方法将处理无操作的情况。
每个提示都应该负责扩展该提示。此外,扩展应该仅应用于顶层表达式。expand()
负责处理 deep=True
时发生的递归。
只有在您确信对象具有该方法时,才可以直接调用 _eval_expand_hint()
方法,否则可能会得到意外的结果 pyAttributeError``s. Note, again, that you do not need to recursively apply the hint to args of your object: this is handled automatically by ``expand()
。通常情况下,应完全避免使用 _eval_expand_hint()
。如果您想在另一个方法内应用特定的扩展,请使用公共的 expand()
函数、方法或 expand_hint()
函数。
为了使扩展正常工作,对象必须能够通过它们的参数进行重建,即 obj.func(*obj.args) == obj
必须成立。
扩展方法传递 **hints
,因此扩展提示可以使用“元提示”——控制如何应用不同扩展方法的提示。例如,force=True
提示会导致 expand(log=True)
忽略假设,这是一种元提示。deep
元提示仅由 expand()
处理,不会传递给 _eval_expand_hint()
方法。
请注意,扩展提示通常应该是执行某种“扩展”的方法。对于简单重写表达式的提示,请使用.rewrite() API。
示例
>>> from sympy import Expr, sympify
>>> class MyClass(Expr):
... def __new__(cls, *args):
... args = sympify(args)
... return Expr.__new__(cls, *args)
...
... def _eval_expand_double(self, *, force=False, **hints):
... '''
... Doubles the args of MyClass.
...
... If there more than four args, doubling is not performed,
... unless force=True is also used (False by default).
... '''
... if not force and len(self.args) > 4:
... return self
... return self.func(*(self.args + self.args))
...
>>> a = MyClass(1, 2, MyClass(3, 4))
>>> a
MyClass(1, 2, MyClass(3, 4))
>>> a.expand(double=True)
MyClass(1, 2, MyClass(3, 4, 3, 4), 1, 2, MyClass(3, 4, 3, 4))
>>> a.expand(double=True, deep=False)
MyClass(1, 2, MyClass(3, 4), 1, 2, MyClass(3, 4))
>>> b = MyClass(1, 2, 3, 4, 5)
>>> b.expand(double=True)
MyClass(1, 2, 3, 4, 5)
>>> b.expand(double=True, force=True)
MyClass(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
另请参阅
expand_log
,expand_mul
,expand_multinomial
,expand_complex
,expand_trig
,expand_power_base
,expand_power_exp
,expand_func
,sympy.simplify.hyperexpand.hyperexpand
class sympy.core.function.PoleError
sympy.core.function.count_ops(expr, visual=False)
返回 expr 中操作的表示(整数或表达式)。
参数:
expr:Expr
如果 expr 是可迭代的,则将返回项的操作计数的总和。
visual:bool,可选
如果
False
(默认),则返回可视化表达式的系数之和。如果True
,则显示每种操作类型的数量,每种核心类类型(或其虚拟等效)乘以其出现次数。
示例
>>> from sympy.abc import a, b, x, y
>>> from sympy import sin, count_ops
虽然没有 SUB 对象,减号被解释为否定或减法之一:
>>> (x - y).count_ops(visual=True)
SUB
>>> (-x).count_ops(visual=True)
NEG
在这里,有两个 Adds 和一个 Pow:
>>> (1 + a + b**2).count_ops(visual=True)
2*ADD + POW
在以下示例中,有一个 Add,Mul,Pow 和两个函数:
>>> (sin(x)*x + sin(x)**2).count_ops(visual=True)
ADD + MUL + POW + 2*SIN
总共为 5:
>>> (sin(x)*x + sin(x)**2).count_ops(visual=False)
5
注意,“你输入的内容”并非总是你得到的内容。表达式 1/x/y 被 sympy 翻译为 1/(x*y),因此它会给出 DIV 和 MUL,而不是两个 DIV:
>>> (1/x/y).count_ops(visual=True)
DIV + MUL
可视选项可用于展示不同形式表达式的操作差异。在此处,Horner 表示法与多项式的展开形式进行比较:
>>> eq=x*(1 + x*(2 + x*(3 + x)))
>>> count_ops(eq.expand(), visual=True) - count_ops(eq, visual=True)
-MUL + 3*POW
count_ops 函数还处理可迭代对象:
>>> count_ops([x, sin(x), None, True, x + 2], visual=False)
2
>>> count_ops([x, sin(x), None, True, x + 2], visual=True)
ADD + SIN
>>> count_ops({x: sin(x), x + 2: y + 1}, visual=True)
2*ADD + SIN
sympy.core.function.expand_mul(expr, deep=True)
包装器,仅使用 mul 提示的扩展。
示例
>>> from sympy import symbols, expand_mul, exp, log
>>> x, y = symbols('x,y', positive=True)
>>> expand_mul(exp(x+y)*(x+y)*log(x*y**2))
x*exp(x + y)*log(x*y**2) + y*exp(x + y)*log(x*y**2)
sympy.core.function.expand_log(expr, deep=True, force=False, factor=False)
包装器,仅使用 log 提示的扩展。有关更多信息,请参阅扩展 docstring。
示例
>>> from sympy import symbols, expand_log, exp, log
>>> x, y = symbols('x,y', positive=True)
>>> expand_log(exp(x+y)*(x+y)*log(x*y**2))
(x + y)*(log(x) + 2*log(y))*exp(x + y)
sympy.core.function.expand_func(expr, deep=True)
包装器,仅使用 func 提示的扩展。有关更多信息,请参阅扩展 docstring。
示例
>>> from sympy import expand_func, gamma
>>> from sympy.abc import x
>>> expand_func(gamma(x + 2))
x*(x + 1)*gamma(x)
sympy.core.function.expand_trig(expr, deep=True)
包装器,仅使用 trig 提示的扩展。有关更多信息,请参阅扩展 docstring。
示例
>>> from sympy import expand_trig, sin
>>> from sympy.abc import x, y
>>> expand_trig(sin(x+y)*(x+y))
(x + y)*(sin(x)*cos(y) + sin(y)*cos(x))
sympy.core.function.expand_complex(expr, deep=True)
包装器,仅使用 complex 提示的扩展。有关更多信息,请参阅扩展 docstring。
示例
>>> from sympy import expand_complex, exp, sqrt, I
>>> from sympy.abc import z
>>> expand_complex(exp(z))
I*exp(re(z))*sin(im(z)) + exp(re(z))*cos(im(z))
>>> expand_complex(sqrt(I))
sqrt(2)/2 + sqrt(2)*I/2
另请参阅
sympy.core.expr.Expr.as_real_imag
sympy.core.function.expand_multinomial(expr, deep=True)
包装器,仅使用多项式提示的扩展。有关更多信息,请参阅扩展 docstring。
示例
>>> from sympy import symbols, expand_multinomial, exp
>>> x, y = symbols('x y', positive=True)
>>> expand_multinomial((x + exp(x + 1))**2)
x**2 + 2*x*exp(x + 1) + exp(2*x + 2)
sympy.core.function.expand_power_exp(expr, deep=True)
包装器,仅使用 power_exp 提示。
更多信息请参见 expand 文档字符串。
示例
>>> from sympy import expand_power_exp, Symbol
>>> from sympy.abc import x, y
>>> expand_power_exp(3**(y + 2))
9*3**y
>>> expand_power_exp(x**(y + 2))
x**(y + 2)
如果 x = 0
,表达式的值取决于 y
的值;如果展开表达式,结果将为 0。因此,仅当 x != 0
时才进行展开:
>>> expand_power_exp(Symbol('x', zero=False)**(y + 2))
x**2*x**y
sympy.core.function.expand_power_base(expr, deep=True, force=False)
在仅使用 power_base 提示的情况下扩展的包装器。
将使一个以 Mul 为基数的幂展开(仅当关于幂的基数和指数的假设允许时),而不进行任何其他展开。
deep=False(默认为 True)仅适用于顶级表达式。
force=True(默认为 False)将导致展开忽略关于基数和指数的假设。当为 False 时,仅在基数为非负数或指数为整数时才会展开。
>>> from sympy.abc import x, y, z
>>> from sympy import expand_power_base, sin, cos, exp, Symbol
>>> (x*y)**2
x**2*y**2
>>> (2*x)**y
(2*x)**y
>>> expand_power_base(_)
2**y*x**y
>>> expand_power_base((x*y)**z)
(x*y)**z
>>> expand_power_base((x*y)**z, force=True)
x**z*y**z
>>> expand_power_base(sin((x*y)**z), deep=False)
sin((x*y)**z)
>>> expand_power_base(sin((x*y)**z), force=True)
sin(x**z*y**z)
>>> expand_power_base((2*sin(x))**y + (2*cos(x))**y)
2**y*sin(x)**y + 2**y*cos(x)**y
>>> expand_power_base((2*exp(y))**x)
2**x*exp(y)**x
>>> expand_power_base((2*cos(x))**y)
2**y*cos(x)**y
请注意,和式保持不变。如果这不是期望的行为,请将完整的 expand()
应用于表达式:
>>> expand_power_base(((x+y)*z)**2)
z**2*(x + y)**2
>>> (((x+y)*z)**2).expand()
x**2*z**2 + 2*x*y*z**2 + y**2*z**2
>>> expand_power_base((2*y)**(1+z))
2**(z + 1)*y**(z + 1)
>>> ((2*y)**(1+z)).expand()
2*2**z*y**(z + 1)
未展开的幂可以在 y != 0
时安全展开,否则可能会得到表达式的不同值:
>>> prev = _
如果我们指出 y
是正数,但在展开后将其替换为 0,则表达式变为 0:
>>> p = Symbol('p', positive=True)
>>> prev.subs(y, p).expand().subs(p, 0)
0
但是如果 z = -1
,表达式将不为零:
>>> prev.subs(y, 0).subs(z, -1)
1
另请参阅
expand
sympy.core.function.nfloat(expr, n=15, exponent=False, dkeys=False)
使 expr 中所有有理数成为浮点数,除了指数中的那些(除非将 exponents 标志设置为 True)和未定义函数中的那些。在处理字典时,请不要修改键,除非 dkeys=True
。
示例
>>> from sympy import nfloat, cos, pi, sqrt
>>> from sympy.abc import x, y
>>> nfloat(x**4 + x/2 + cos(pi/3) + 1 + sqrt(y))
x**4 + 0.5*x + sqrt(y) + 1.5
>>> nfloat(x**4 + sqrt(y), exponent=True)
x**4.0 + y**0.5
容器类型不被修改:
>>> type(nfloat((1, 2))) is tuple
True
``` ## evalf
```py
class sympy.core.evalf.EvalfMixin
添加 evalf 能力的混合类。
evalf(n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False)
将给定的公式评估到 n 位数的精度。
参数:
subs : 字典,可选
用于符号的数值替换,例如
subs={x:3, y:1+pi}
。替换必须以字典形式给出。
maxn : 整数,可选
允许最大临时工作精度为 maxn 位数。
chop : 布尔值或数字,可选
指定如何将子结果中微小的实部或虚部替换为精确的零。
当
True
时,chop 值默认为标准精度。否则,chop 值用于确定“小”的量级以进行切除。
>>> from sympy import N >>> x = 1e-4 >>> N(x, chop=True) 0.000100000000000000 >>> N(x, chop=1e-5) 0.000100000000000000 >>> N(x, chop=1e-4) 0
strict : 布尔值,可选
如果任何子结果未能在可用的最大精度下完全准确评估,则引发
PrecisionExhausted
。
quad : 字符串,可选
选择数值积分的算法。默认情况下,使用双曲正弦积分法。对于无限区间上的振荡积分,尝试
quad='osc'
。
verbose : 布尔值,可选
打印调试信息。
注意
当浮点数被天真地替换到表达式中时,精度误差可能会对结果产生不利影响。例如,将 1e16(一个浮点数)加到 1 时会截断为 1e16;如果随后减去 1e16,则结果将为 0。以下正是发生的情况:
>>> from sympy.abc import x, y, z
>>> values = {x: 1e16, y: 1, z: 1e16}
>>> (x + y - z).subs(values)
0
使用 evalf 的 subs 参数是评估此类表达式的准确方法:
>>> (x + y - z).evalf(subs=values)
1.00000000000000
n(n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False)
将给定的公式评估到 n 位数的精度。
参数:
subs : 字典,可选
替换符号的数值值,例如
subs={x:3, y:1+pi}
。替换必须作为字典给出。
maxn:int,可选
允许最大临时工作精度达到 maxn 位数。
chop:bool 或 number,可选
指定如何用精确的零替换子结果中微小的实部或虚部。
当
True
时,chop 值默认为标准精度。否则,将使用截断值来确定“小数”的量级。
>>> from sympy import N >>> x = 1e-4 >>> N(x, chop=True) 0.000100000000000000 >>> N(x, chop=1e-5) 0.000100000000000000 >>> N(x, chop=1e-4) 0
strict:bool,可选
如果任何子结果未能在给定的 maxprec 下完全精确计算,则抛出
PrecisionExhausted
。
quad:str,可选
选择数值积分的算法。默认情况下,使用 tanh-sinh 积分。对于在无穷区间上的振荡积分,尝试
quad='osc'
。
verbose:bool,可选
打印调试信息。
注意
当 Floats 被天真地替换到表达式中时,精度误差可能会对结果产生不利影响。例如,将 1e16(一个 Float)加到 1 中将截断为 1e16;如果然后减去 1e16,则结果将为 0。这正是以下情况发生的:
>>> from sympy.abc import x, y, z
>>> values = {x: 1e16, y: 1, z: 1e16}
>>> (x + y - z).subs(values)
0
对于 evalf 的子参数,使用此方法来准确评估这样的表达式:
>>> (x + y - z).evalf(subs=values)
1.00000000000000
class sympy.core.evalf.PrecisionExhausted
sympy.core.evalf.N(x, n=15, **options)
调用 x.evalf(n, **options)。
解释
.n()
和 N()
都等同于 .evalf()
;使用你喜欢的那个。另请参阅 .evalf()
的文档字符串,了解选项信息。
示例
>>> from sympy import Sum, oo, N
>>> from sympy.abc import k
>>> Sum(1/k**k, (k, 1, oo))
Sum(k**(-k), (k, 1, oo))
>>> N(_, 4)
1.291
``` ## containers
```py
class sympy.core.containers.Tuple(*args, **kwargs)
封装内置的 tuple 对象。
参数:
sympify:bool
若为
False
,则不在args
上调用sympify
。这可用于对已知元素为 SymPy 对象的非常大的 tuple 进行加速。
解释
Tuple 是 Basic 的子类,因此在 SymPy 框架中能很好地运行。包装后的 tuple 可作为 self.args 使用,但也可以使用 [:] 语法访问元素或切片。
示例
>>> from sympy import Tuple, symbols
>>> a, b, c, d = symbols('a b c d')
>>> Tuple(a, b, c)[1:]
(b, c)
>>> Tuple(a, b, c).subs(a, d)
(d, b, c)
index(value, start=None, stop=None)
搜索并返回值的第一个索引。
property kind
Tuple 实例的种类。
Tuple 的种类始终为 TupleKind
,但由元素数量和每个元素的种类参数化。
示例
>>> from sympy import Tuple, Matrix
>>> Tuple(1, 2).kind
TupleKind(NumberKind, NumberKind)
>>> Tuple(Matrix([1, 2]), 1).kind
TupleKind(MatrixKind(NumberKind), NumberKind)
>>> Tuple(1, 2).kind.element_kind
(NumberKind, NumberKind)
参见
sympy.matrices.kind.MatrixKind
, sympy.core.kind.NumberKind
tuple_count(value) → int
返回值的出现次数。
class sympy.core.containers.TupleKind(*args)
TupleKind 是 Kind 的子类,用于定义 Tuple
的种类。
TupleKind 的参数将是 Tuples 中所有参数的种类,例如
参数:
args:tuple(element_kind)
element_kind 是元素的种类。args 是元素种类的 tuple
示例
>>> from sympy import Tuple
>>> Tuple(1, 2).kind
TupleKind(NumberKind, NumberKind)
>>> Tuple(1, 2).kind.element_kind
(NumberKind, NumberKind)
参见
sympy.core.kind.NumberKind
, MatrixKind
, sympy.sets.sets.SetKind
class sympy.core.containers.Dict(*args)
封装了内置的 dict 对象。
解释
Dict
是 Basic
的子类,因此它在 SymPy 框架中表现良好。由于它是不可变的,可以包含在集合中,但其值必须在实例化时全部给定,并且不能后续更改。否则,其行为与 Python 的 dict 完全相同。
示例
>>> from sympy import Dict, Symbol
>>> D = Dict({1: 'one', 2: 'two'})
>>> for key in D:
... if key == 1:
... print('%s %s' % (key, D[key]))
1 one
参数被 sympify,所以 1 和 2 是整数,而值是符号。查询自动 sympify 参数,因此以下操作有效:
>>> 1 in D
True
>>> D.has(Symbol('one')) # searches keys and values
True
>>> 'one' in D # not in the keys
False
>>> D[1]
one
get(key, default=None)
如果键在字典中,则返回键的值。
items()
返回提供字典条目视图的类似集合的对象。
keys()
返回字典键的列表。
values()
返回字典值的列表。 ## exprtools
sympy.core.exprtools.gcd_terms(terms, isprimitive=False, clear=True, fraction=True)
计算 terms
的最大公约数并将它们放在一起。
参数:
terms : 表达式
可以是一个表达式或非 Basic 序列的表达式,这将被处理为一个求和项。
isprimitive : 布尔值,可选
如果
isprimitive
为 True,则 _gcd_terms 不会在项上运行原始方法。
clear : 布尔值,可选
它控制从 Add 表达式的分母中移除整数的操作。当为 True(默认)时,将清除所有数值分母;当为 False 时,仅当所有项的数值分母不为 1 时,才清除分母。
fraction : 布尔值,可选
当为 True(默认)时,将表达式置于通用分母之上。
示例
>>> from sympy import gcd_terms
>>> from sympy.abc import x, y
>>> gcd_terms((x + 1)**2*y + (x + 1)*y**2)
y*(x + 1)*(x + y + 1)
>>> gcd_terms(x/2 + 1)
(x + 2)/2
>>> gcd_terms(x/2 + 1, clear=False)
x/2 + 1
>>> gcd_terms(x/2 + y/2, clear=False)
(x + y)/2
>>> gcd_terms(x/2 + 1/x)
(x**2 + 2)/(2*x)
>>> gcd_terms(x/2 + 1/x, fraction=False)
(x + 2/x)/2
>>> gcd_terms(x/2 + 1/x, fraction=False, clear=False)
x/2 + 1/x
>>> gcd_terms(x/2/y + 1/x/y)
(x**2 + 2)/(2*x*y)
>>> gcd_terms(x/2/y + 1/x/y, clear=False)
(x**2/2 + 1)/(x*y)
>>> gcd_terms(x/2/y + 1/x/y, clear=False, fraction=False)
(x/2 + 1/x)/y
在这种情况下,clear
标志被忽略,因为返回的表达式是一个有理数表达式,而不是一个简单的求和。
另请参见
factor_terms
,sympy.polys.polytools.terms_gcd
sympy.core.exprtools.factor_terms(expr, radical=False, clear=False, fraction=False, sign=True)
从所有参数的项中去除公共因子,而不改变表达式的基本结构。不进行展开或简化(也不处理非交换元素)。
参数:
radical: 布尔值,可选
如果 radical=True,则所有项的常见根号将从表达式的任何 Add 子表达式中因式分解出来。
clear : 布尔值,可选
如果 clear=False(默认值),则不会从单个 Add 中分离系数,如果可以分布到一个或多个具有整数系数的项中。
fraction : 布尔值,可选
如果 fraction=True(默认为 False),则将为表达式构造一个通用分母。
sign : 布尔值,可选
如果 sign=True(默认值),即使唯一的共同因子是 -1,它也会从表达式中因式分解出来。
示例
>>> from sympy import factor_terms, Symbol
>>> from sympy.abc import x, y
>>> factor_terms(x + x*(2 + 4*y)**3)
x*(8*(2*y + 1)**3 + 1)
>>> A = Symbol('A', commutative=False)
>>> factor_terms(x*A + x*A + x*y*A)
x*(y*A + 2*A)
当 clear
为 False 时,如果 Add 表达式的所有项的系数都是分数,则仅从中因式分解出一个有理数:
>>> factor_terms(x/2 + 1, clear=False)
x/2 + 1
>>> factor_terms(x/2 + 1, clear=True)
(x + 2)/2
如果 -1 是唯一可以因式分解的内容,则 不 因式分解它,sign
标志必须为 False:
>>> factor_terms(-x - y)
-(x + y)
>>> factor_terms(-x - y, sign=False)
-x - y
>>> factor_terms(-2*x - 2*y, sign=False)
-2*(x + y)
参见
gcd_terms
,sympy.polys.polytools.terms_gcd
## 类型
class sympy.core.kind.Kind(*args)
种类的基类。
对象的种类表示实体所属的数学分类。函数和类应当通过其种类来识别和过滤参数。
每个对象的种类必须谨慎选择,以表明设计意图。根据其参数的种类,表达式可能有不同的种类。例如,Add
的参数必须具有共同的种类,因为加法是群操作符,而生成的Add()
也具有相同的种类。
为了性能,每种种类尽可能广泛,并且不基于集合理论。例如,NumberKind
不仅包括复数,还包括包含非严格数字S.Infinity
或S.NaN
的表达式。
种类可以作为参数具有参数。例如,MatrixKind()
可以用一个元素构造,该元素表示其元素的种类。
Kind
表现得像单例模式。相同的签名将返回相同的对象。
sympy.core.kind.NumberKind
NumberKind
的别名
sympy.core.kind.UndefinedKind
UndefinedKind
的别名
sympy.core.kind.BooleanKind
BooleanKind
的别名
排序
sympy.core.sorting.default_sort_key(item, order=None)
返回可用于排序的关键字。
关键字的结构如下:
(class_key, (len(args), args), exponent.sort_key(), coefficient)
当item
是 Basic 对象或符号化为 Basic 对象的对象(而不是字符串)时,此关键字由 Basic 对象的sort_key
例程提供。否则,此函数将生成关键字。
order
参数传递给sort_key
例程,并用于确定表达式中项的顺序。 (请参见下面的示例)order
选项包括:'lex','grlex','grevlex'和相同的反向值(例如'rev-lex')。默认的order
值为 None(即'lex')。
示例
>>> from sympy import S, I, default_sort_key, sin, cos, sqrt
>>> from sympy.core.function import UndefinedFunction
>>> from sympy.abc import x
获取对象关键字的等效方法如下:
>>> x.sort_key() == default_sort_key(x)
True
以下是生成的关键字的一些示例:
>>> default_sort_key(UndefinedFunction('f'))
((0, 0, 'UndefinedFunction'), (1, ('f',)), ((1, 0, 'Number'),
(0, ()), (), 1), 1)
>>> default_sort_key('1')
((0, 0, 'str'), (1, ('1',)), ((1, 0, 'Number'), (0, ()), (), 1), 1)
>>> default_sort_key(S.One)
((1, 0, 'Number'), (0, ()), (), 1)
>>> default_sort_key(2)
((1, 0, 'Number'), (0, ()), (), 2)
虽然sort_key
是 SymPy 对象专有的方法,但default_sort_key
将接受任何参数作为参数,因此作为排序关键字更加健壮。对于下面的例子,使用key=lambda i: i.sort_key()
会失败,因为 2 没有sort_key
方法;这就是为什么使用default_sort_key
。请注意,它还处理非字符串项(如整数)的符号化:
>>> a = [2, I, -I]
>>> sorted(a, key=default_sort_key)
[2, -I, I]
返回的关键字可用于函数中可以指定关键字的任何位置,例如排序、最小值、最大值等:
>>> a.sort(key=default_sort_key); a[0]
2
>>> min(a, key=default_sort_key)
2
注意事项
返回的关键字可用于按照平台通用的规范顺序获取项目。它并不直接用于对表达式列表进行排序:
>>> a, b = x, 1/x
由于a
只有 1 个项,其sort_key
值不受order
的影响:
>>> a.sort_key() == a.sort_key('rev-lex')
True
如果合并a
和b
,则关键字将不同,因为可以排序的项有所不同:
>>> eq = a + b
>>> eq.sort_key() == eq.sort_key('rev-lex')
False
>>> eq.as_ordered_terms()
[x, 1/x]
>>> eq.as_ordered_terms('rev-lex')
[1/x, x]
但由于每个项的关键字都独立于order
的值,因此当它们单独出现在列表中时,它们不会按不同的顺序排序:
>>> sorted(eq.args, key=default_sort_key)
[1/x, x]
>>> sorted(eq.args, key=lambda i: default_sort_key(i, order='rev-lex'))
[1/x, x]
使用这些关键字时获得的项的顺序是在一个乘积中作为因子时获得的顺序。
尽管它对于快速将表达式放入规范顺序很有用,但它不根据操作数量、变量的幂次和其他定义的复杂性对表达式进行排序:
>>> sorted([sin(x)*cos(x), sin(x)], key=default_sort_key)
[sin(x)*cos(x), sin(x)]
>>> sorted([x, x**2, sqrt(x), x**3], key=default_sort_key)
[sqrt(x), x, x**2, x**3]
另见
有序,sympy.core.expr.Expr.as_ordered_factors,sympy.core.expr.Expr.as_ordered_terms
sympy.core.sorting.ordered(seq, keys=None, default=True, warn=False)
返回一个序列的迭代器,其中键被保守地用于打破平局:如果应用一个键后没有平局,则不会计算其他键。
如果未提供键或给定键未解决所有平局(但仅当default
为 True 时),将应用两个默认键:_nodes
(将较小的表达式放在前面)和default_sort_key
(如果对象的sort_key
正确定义,则应解决任何平局)。此策略类似于Basic.compare
所做的排序,但不同之处在于ordered
从不基于对象名称做决定。
如果warn
为 True,则如果没有剩余的键来打破平局,则会引发错误。如果预期不应该有非相同项目之间的平局,则可以使用此功能。
示例
>>> from sympy import ordered, count_ops
>>> from sympy.abc import x, y
count_ops
不足以在此列表中打破平局,并且前两个项目以其原始顺序出现(即排序是稳定的):
>>> list(ordered([y + 2, x + 2, x**2 + y + 3],
... count_ops, default=False, warn=False))
...
[y + 2, x + 2, x**2 + y + 3]
default_sort_key
允许打破平局:
>>> list(ordered([y + 2, x + 2, x**2 + y + 3]))
...
[x + 2, y + 2, x**2 + y + 3]
在这里,序列按长度排序,然后按总和排序:
>>> seq, keys = [[[1, 2, 1], [0, 3, 1], [1, 1, 3], [2], [1]], [
... lambda x: len(x),
... lambda x: sum(x)]]
...
>>> list(ordered(seq, keys, default=False, warn=False))
[[1], [2], [1, 2, 1], [0, 3, 1], [1, 1, 3]]
如果warn
为 True,则如果没有足够的键来打破平局,则会引发错误:
>>> list(ordered(seq, keys, default=False, warn=True))
Traceback (most recent call last):
...
ValueError: not enough keys to break ties
注
装饰排序是希望特定项目比较的一种最快排序序列的方式之一:序列被装饰,根据装饰进行排序(例如将所有字母变成小写),然后取消装饰。如果想要打破具有相同装饰值项目的平局,则可以使用第二个键。但是如果计算第二个键很昂贵,那么使用两个键来装饰所有项目是低效的:只有具有相同第一个键值的项目才需要装饰。该函数仅在需要打破平局时连续应用键。通过生成迭代器,使用打破平局者被尽可能延迟使用。
当预期使用第一个键作为良好的哈希函数时,此函数最好用于案例;如果从键的应用中没有唯一的哈希,则不应该使用该键。但例外情况是,即使有许多碰撞,如果第一组较小并且不需要处理列表中的所有项,则不会浪费时间对不感兴趣的内容进行排序。例如,如果要在列表中查找最小值,并且有几个标准用于定义排序顺序,那么如果第一组候选人相对于正在处理的项目数较小,则此功能将快速返回结果。
随机
当您需要在 SymPy 库代码中使用随机数时,请从这里导入,以便为 SymPy 仅工作一个生成器。从这里导入应该与从 Python 的随机模块导入的行为相同。但这里仅包括当前在 SymPy 中使用的例程。要使用其他例程,请导入rng
并直接访问方法。例如,要捕获生成器的当前状态,请使用rng.getstate()
。
这里有意没有 Random 可供导入。如果要控制生成器的状态,请导入seed
并调用它,可以带参数也可以不带参数来设置状态。
示例
>>> from sympy.core.random import random, seed
>>> assert random() < 1
>>> seed(1); a = random()
>>> b = random()
>>> seed(1); c = random()
>>> assert a == c
>>> assert a != b # remote possibility this will fail
sympy.core.random.random_complex_number(a=2, b=-1, c=3, d=1, rational=False, tolerance=None)
返回一个随机复数。
为了减少命中分支切割或任何东西的机会,我们保证 b <= Im z <= d,a <= Re z <= c
当 rational 为 True 时,可以在指定的容差范围内获得对随机数的有理逼近。
sympy.core.random.verify_numerically(f, g, z=None, tol=1e-06, a=2, b=-1, c=3, d=1)
数值上测试在参数 z 处评估时 f 和 g 是否一致。
如果 z 为 None,则将测试所有符号。此例程不测试是否存在精度高于 15 位的浮点数,因此如果有,则由于舍入误差,您的结果可能不符合预期。
示例
>>> from sympy import sin, cos
>>> from sympy.abc import x
>>> from sympy.core.random import verify_numerically as tn
>>> tn(sin(x)**2 + cos(x)**2, 1, x)
True
sympy.core.random.test_derivative_numerically(f, z, tol=1e-06, a=2, b=-1, c=3, d=1)
数值上测试 f 对 z 的符号计算导数是否正确。
此例程不测试是否存在精度高于 15 位的浮点数,因此如果有,则由于舍入误差,您的结果可能不符合预期。
示例
>>> from sympy import sin
>>> from sympy.abc import x
>>> from sympy.core.random import test_derivative_numerically as td
>>> td(sin(x), x)
True
sympy.core.random._randrange(seed=None)
返回一个 randrange 生成器。
seed
可以
-
None - 返回随机种子生成器
-
int - 返回用 int 种子的生成器
-
list - 将返回的值按给定顺序从列表中取出;不修改提供的列表。
示例
>>> from sympy.core.random import _randrange
>>> rr = _randrange()
>>> rr(1000)
999
>>> rr = _randrange(3)
>>> rr(1000)
238
>>> rr = _randrange([0, 5, 1, 3, 4])
>>> rr(3), rr(3)
(0, 1)
sympy.core.random._randint(seed=None)
返回一个 randint 生成器。
seed
可以
-
None - 返回随机种子生成器
-
int - 返回用 int 种子的生成器
-
list - 将返回的值按给定顺序从列表中取出;不修改提供的列表。
示例
>>> from sympy.core.random import _randint
>>> ri = _randint()
>>> ri(1, 1000)
999
>>> ri = _randint(3)
>>> ri(1, 1000)
238
>>> ri = _randint([0, 5, 1, 2, 4])
>>> ri(1, 3), ri(1, 3)
(1, 2)
``` ## 遍历
```py
sympy.core.traversal.bottom_up(rv, F, atoms=False, nonbasic=False)
对表达式树中的所有表达式从底向上应用F
。如果atoms
为 True,则即使没有参数也应用F
;如果nonbasic
为 True,则尝试将F
应用于非基本对象。
sympy.core.traversal.postorder_traversal(node, keys=None)
对树进行后序遍历。
此生成器以后序方式递归地生成已访问的节点。也就是说,它通过深度优先方式下降以生成所有节点子节点的后序遍历,然后才生成节点本身。
参数:
node:SymPy 表达式
遍历表达式。
keys:(默认为 None)排序键
用于排序 Basic 对象的键。当为 None 时,处理 Basic 对象的 args 的顺序是任意的。如果定义了 key,则它将作为唯一的键传递给 ordered();如果
key
简单地为 True,则将使用 ordered 的默认键(节点计数和默认排序键)。
生成:
子树:SymPy 表达式
树中的所有子树。
示例
>>> from sympy import postorder_traversal
>>> from sympy.abc import w, x, y, z
节点按照遇到的顺序返回,除非提供了关键字;仅传递 key=True 将确保遍历是唯一的。
>>> list(postorder_traversal(w + (x + y)*z))
[z, y, x, x + y, z*(x + y), w, w + z*(x + y)]
>>> list(postorder_traversal(w + (x + y)*z, keys=True))
[w, z, x, y, x + y, z*(x + y), w + z*(x + y)]
sympy.core.traversal.preorder_traversal(node, keys=None)
对树进行先序遍历。
此迭代器以先序方式递归地生成已访问的节点。也就是说,它生成当前节点,然后以广度优先方式下降以生成所有节点子节点的先序遍历。
对于表达式,遍历的顺序取决于 .args 的顺序,在许多情况下可以是任意的。
参数:
node:SymPy 表达式
遍历表达式。
keys:(默认为 None)排序键
用于排序 Basic 对象的键。当为 None 时,处理 Basic 对象的 args 的顺序是任意的。如果定义了 key,则它将作为唯一的键传递给 ordered();如果
key
简单地为 True,则将使用 ordered 的默认键。
生成:
子树:SymPy 表达式
树中的所有子树。
示例
>>> from sympy import preorder_traversal, symbols
>>> x, y, z = symbols('x y z')
节点按照遇到的顺序返回,除非提供了关键字;仅传递 key=True 将确保遍历是唯一的。
>>> list(preorder_traversal((x + y)*z, keys=None))
[z*(x + y), z, x + y, y, x]
>>> list(preorder_traversal((x + y)*z, keys=True))
[z*(x + y), z, x + y, x, y]
sympy.core.traversal.use(expr, func, level=0, args=(), kwargs={})
使用 func
在给定级别转换 expr
。
示例
>>> from sympy import use, expand
>>> from sympy.abc import x, y
>>> f = (x + y)**2*x + 1
>>> use(f, expand, level=2)
x*(x**2 + 2*x*y + y**2) + 1
>>> expand(f)
x**3 + 2*x**2*y + x*y**2 + 1
sympy.core.traversal.walk(e, *target)
遍历给定类型的参数并返回遍历过的参数列表;不是指定类型的参数不会遍历。
示例
>>> from sympy.core.traversal import walk
>>> from sympy import Min, Max
>>> from sympy.abc import x, y, z
>>> list(walk(Min(x, Max(y, Min(1, z))), Min))
[Min(x, Max(y, Min(1, z)))]
>>> list(walk(Min(x, Max(y, Min(1, z))), Min, Max))
[Min(x, Max(y, Min(1, z))), Max(y, Min(1, z)), Min(1, z)]
参见
bottom_up