按类型求解输出

solve() 函数的输出可能看起来很笨拙,因为它似乎任意地返回六种不同类型的输出(除了抛出错误)。出现这种情况的原因是历史性的,并且偏向于人机交互而不是程序化使用。输出的类型将取决于方程的类型(以及它们是如何输入的)以及提供的符号的数量(以及它们是如何提供的)。

>>> from sympy import sqrt, exp, solve, Symbol, Eq
>>> from sympy.abc import x, y, z, a, b

solve() 函数尝试找到尽可能多的符号的所有值,这些值将使给定的每个表达式都等于零。可以使用 dictset 关键字控制输出格式。

>>> solve(x - 1, dict=True)
[{x: 1}]
>>> solve([x**2 - y, x + y - 6], set=True)
([x, y], {(-3, 9), (2, 4)})

以下讨论解释了在不使用这些关键字时获得的输出。

空列表

当没有解时,将返回一个空列表。

>>> solve(sqrt(x) + 1)  # or solve(sqrt(x) + 1, dict=True)
[]
>>> solve(sqrt(x) + 1, set=True)
([x], set())

值列表

当要求解的符号在上下文中是明确的时,会给出值列表,因为 a) 方程是单变量的,或者 b) 指定了单个符号作为关注对象。

>>> solve(x**2 - 4)
[-2, 2]
>>> solve(x - y - 1, x)
[y + 1]

单个字典

当方程作为列表传递且所有方程在给定的符号中都是线性的时,结果将是一个包含键为符号、值为这些符号解的单个字典。注意:如果给定符号存在一个不定系数解,则会为单个方程(不作为列表传递)自动生成这样的系统。如果这不是预期的,则将表达式作为列表传递。

>>> solve([x + y - 2, x - y + 2], x, y)
{x: 0, y: 2}
>>> eq = a*x - 2*x + b - 5
>>> solve(eq, {a, b})  # undetermined coefficients
{a: 2, b: 5}
>>> solve([eq], {a, b})  # algebraic
{a: -b/x + (2*x + 5)/x}

元组列表

列表中的每个元组都提供了解决方案,按照符号给出的顺序排列。当以下情况发生时,将使用此格式:a) 方程式列表包含至少一个非线性方程式,或者 b) 符号列表按照明确定义的顺序给出。(当使用标志 set=True 时,返回的集合中的元组也使用这种格式。)

>>> solve(x - 1, x, y)  # more than one symbol
[(1, y)]
>>> solve([x**2], x)  # list with nonlinear equation
[(0,)]
>>> solve([x**2 - 1], x)
[(-1,), (1,)]
>>> solve([x**2 - y, x - 3], x, y)  # nonlinear and multiple symbols
[(3, 9)]

字典列表

当表达式不是单变量,或者列表中存在非线性表达式,并且符号的顺序由于以下原因而不明确时,将返回字典列表:a) 没有传递符号,或者 b) 符号作为集合传递。(使用 dict=True 时,也会选择这种格式。)

>>> solve(x - y)
[{x: y}]
>>> solve([exp(x) - 1, x*(x - 1)])
[{x: 0}]
>>> system = [x + y - z, x**2 - y + z, exp(z) + 1/x + 1/y - 2]
>>> sol = solve(system[:2]); sol
[{x: -1, y: z + 1}, {x: 0, y: z}]

字典只包含与键不同的值。在上面的最后一个例子中,字典中没有 z 的键,因为只有三个方程式中的两个不足以确定它的值。然而,这些解可以用来从第三个方程式中消去这些变量,从而得到一个单个变量的关系式,这个关系式可以(可能通过数值方法)求解,从而获得完整的解,而只需要猜测一个值,而不是三个值。

>>> from sympy import nsolve
>>> [system[-1].subs(s) for s in sol]
[exp(z) - 3 + 1/(z + 1), exp(z) + zoo + 1/z]
>>> z_eq = _[0]
>>> zsol = nsolve(z_eq, 1); zsol
0.906425478894557
>>> sol0 = {k: v.subs(z, zsol) for k, v in sol[0].items()}
>>> sol0[z] = zsol; sol0
{x: -1, y: 1.90642547889456, z: 0.906425478894557}

布尔或关系

当给定一个除了 Equality 之外的关系表达式作为表达式求解时,将返回一个布尔表达式。可能会返回单个 \(Equality\) 或更复杂的关系表达式。在这里使用 solve() 等效于将方程式集和符号传递给 reduce_inequalities()(并且忽略 dictsetcheck 标志)。

>>> solve([x**2 > 4, x > 0])
(2 < x) & (x < oo)
>>> from sympy import Unequality as Ne
>>> solve([x**2 - 4, Ne(x, -2)])
Eq(x, 2)

任何返回的 \(Equality\) 可以转换为字典

>>> {_.lhs: _.rhs}
{x: 2}