用代数方法化简单个变量的一元或多元不等式

使用 SymPy 用代数方法化简单个变量的一元或多元不等式。例如,化简 \(x^2 < \pi\)\(x > 0\) 得到 \(0 < x < \sqrt{\pi}\).

注意

SymPy 目前只能化简不等式中的一个符号(变量)。

如果每个不等式只有一个符号,SymPy 可以化简包含多个符号的系统。

其他可选方案

  • 要化简不等式中的多个符号,请尝试 SciPy 的 linprog()

  • 要化简布尔表达式,请使用 as_set

示例

用代数方法化简单个变量的多元不等式

reduce_inequalities() 接受一个列表或元组,表示要化简成一个系统的多个不等式

>>> from sympy import symbols, reduce_inequalities, pi
>>> x = symbols('x')
>>> reduce_inequalities([x >= 0, x**2 <= pi], x)
(0 <= x) & (x <= sqrt(pi))

注意

虽然 solve() 目前实现了相同的功能(通过内部调用 reduce_inequalities()),但该功能可能会从 solve() 中弃用或删除。因此,我们建议使用 reduce_inequalities()

reduce_inequalities() 是最高级的不等式简化函数,它将在内部根据需要调用任何其他低级的 不等式简化函数

代数简化单个变量的单个不等式

如果您只有一个不等式,您可以选择不使用列表结构,只需将不等式作为表达式传递给 reduce_inequalities()

>>> from sympy import symbols, reduce_inequalities, pi
>>> x = symbols('x')
>>> reduce_inequalities(x**2 <= pi, x)
(x <= sqrt(pi)) & (-sqrt(pi) <= x)

指南

在函数调用中包含要简化的变量

我们建议您将要简化的变量作为 reduce_inequalities() 的第二个参数,以确保它针对所需变量进行简化。

代数简化不等式组

您可以创建不等式,然后将该组作为列表进行简化。

>>> from sympy import symbols, reduce_inequalities, pi
>>> x = symbols('x')
>>> reduce_inequalities([3*x >= 1, x**2 <= pi], x)
(1/3 <= x) & (x <= sqrt(pi))

使用结果

使用结果的一种常见方法是提取符号(变量)的边界。例如,对于解 \(0 < x < \sqrt{\pi}\),您可能想要提取 \(0\)\(\sqrt{\pi}\)

提取分解关系的列表

您可以使用关系原子将由 ^ (Or) 或 & (And) 连接的关系集分解为单个关系。使用 canonical 将对每个关系进行排序,以便符号位于左侧,因此您可以获取右侧的 rhs 来提取常量。

>>> from sympy import symbols, reduce_inequalities, pi
>>> from sympy.core.relational import Relational
>>> x = symbols('x')
>>> eq = reduce_inequalities([3*x >= 1, x**2 <= pi], x); eq
(1/3 <= x) & (x <= sqrt(pi))
>>> relations = [(i.lhs, i.rel_op, i.rhs) for i in [i.canonical for i in eq.atoms(Relational)]]
>>> relations_sorted = sorted(relations, key=lambda x: float(x[2])) # Sorting relations just to ensure consistent list order for docstring testing
>>> relations_sorted
[(x, '>=', 1/3), (x, '<=', sqrt(pi))]

提取关系元组

简化关系的 args(参数)是单个关系,因此您可以从 args 的左侧或右侧提取常量。

>>> from sympy import symbols, reduce_inequalities, pi
>>> x = symbols('x')
>>> eq = reduce_inequalities([3*x >= 1, x**2 <= pi], x); eq
(1/3 <= x) & (x <= sqrt(pi))
>>> eq.args
(1/3 <= x, x <= sqrt(pi))
>>> constants = []
>>> for arg in eq.args:
...     if arg.lhs == x:
...         constants.append(arg.rhs)
...     else:
...         constants.append(arg.lhs)
>>> constants
[1/3, sqrt(pi)]

使用 SymPy 进行不等式简化的局限性

SymPy 每个不等式只能针对一个感兴趣的符号进行简化

SymPy 目前只能针对给定不等式中的一个符号(变量)进行简化。

>>> from sympy import reduce_inequalities, symbols
>>> x, y = symbols("x y")
>>> reduce_inequalities([x + y > 1, y > 0], [x, y])
Traceback (most recent call last):
...
NotImplementedError: inequality has more than one symbol of interest.

您可以使用 SciPy 的 linprog() 来简化此不等式组。

如果每个不等式中只有一个感兴趣的符号,则 SymPy 可以针对多个符号简化不等式组。例如,以下不等式组有两个变量 \(x\)\(y\)。SymPy 可以针对 \(x\) 进行简化,并给出对 \(y\) 的约束。

>>> from sympy import reduce_inequalities, symbols
>>> x, y = symbols("x y")
>>> reduce_inequalities([x + y > 1, y > 0], x)
(0 < y) & (y < oo) & (x > 1 - y)

(ooInfinity。)

如果每个不等式只包含一个要简化的符号,则 SymPy 可以针对多个符号简化不等式集。

>>> from sympy import reduce_inequalities, symbols
>>> x, y = symbols("x y")
>>> x_y_reduced = reduce_inequalities([x > 1, y > 0], [x, y]); x_y_reduced
(0 < y) & (1 < x) & (x < oo) & (y < oo)

请注意,这除了分别简化不等式之外,不会提供任何数学见解。

>>> from sympy import And
>>> x_reduced = reduce_inequalities(x > 1, x); x_reduced
(1 < x) & (x < oo)
>>> y_reduced = reduce_inequalities(y > 0, y); y_reduced
(0 < y) & (y < oo)
>>> And(x_reduced, y_reduced) == x_y_reduced
True

因此,将此类不等式作为集合求解的好处可能是方便性。

SymPy 可求解的不等式类型的局限性

reduce_inequalities() 可以求解包含要简化的符号的幂或包含其他符号的但两者都不包含的系统不等式。

>>> from sympy import reduce_inequalities
>>> from sympy.abc import x, y
>>> reduce_inequalities([x ** 2 < 4, x > 0], x)
(0 < x) & (x < 2)
>>> reduce_inequalities([x < y, x > 0], x)
(0 < x) & (x < oo) & (x < y)
>>> reduce_inequalities([x ** 2 - y < 4, x > 0], x)
Traceback (most recent call last):
...
NotImplementedError: The inequality, -_y + x**2 - 4 < 0, cannot be solved using
solve_univariate_inequality.

并非所有结果都针对周期函数返回

针对三角不等式返回的结果在其周期区间内受到限制。 reduce_inequalities() 尝试仅返回足够的解,以便可以通过添加方程的 periodicity()(这里为 \(2\pi\))的整数倍数,从返回的解中生成所有(无限多个)解。

>>> from sympy import reduce_inequalities, cos
>>> from sympy.abc import x, y
>>> from sympy.calculus.util import periodicity
>>> reduce_inequalities([2*cos(x) < 1, x > 0], x)
(0 < x) & (x < oo) & (pi/3 < x) & (x < 5*pi/3)
>>> periodicity(2*cos(x), x)
2*pi

并非所有不等式组都可以简化

无法满足的不等式组

如果不等式组包含不兼容的条件,例如 \(x < 0\)\(x > \pi\),则 SymPy 将返回 False

>>> from sympy import symbols, reduce_inequalities, pi
>>> x = symbols('x')
>>> reduce_inequalities([x < 0, x > pi], x)
False

无法代数简化的不等式组

SymPy 可能会通过返回错误(例如 NotImplementedError)来反映您的不等式组没有可以用代数(符号)表示的解。

>>> from sympy import symbols, reduce_inequalities, cos
>>> x = symbols('x')
>>> reduce_inequalities([cos(x) - x > 0, x > 0], x)
Traceback (most recent call last):
...
NotImplementedError: The inequality, -x + cos(x) > 0, cannot be solved using solve_univariate_inequality.

因此,您可能需要使用 SciPy 的 linprog() 数值地简化不等式。

可以代数简化但 SymPy 无法简化的不等式

请参阅上面的 使用 SymPy 进行不等式简化的局限性

报告错误

如果您发现 diophantine() 存在错误,请在 SymPy 邮件列表 上发布该问题。在问题解决之前,您可以使用 需要考虑的替代方法 中列出的其他方法。