Reduce One or a System of Inequalities for a Single Variable Algebraically

Use SymPy to reduce one or a system of inequalities for a single variable algebraically. For example, reducing \(x^2 < \pi\), \(x > 0\) yields \(0 < x < \sqrt{\pi}\).

Note

SymPy can currently reduce for only one symbol (variable) in an inequality.

SymPy can reduce a system containing more than one symbol, if there is only one symbol per inequality.

Alternatives to Consider

  • To reduce for more than one symbol in an inequality, try SciPy’s linprog()

  • To reduce Boolean expressions, use as_set

Examples

Reducing a System of Inequalities for a Single Variable Algebraically

reduce_inequalities() accepts a list or tuple of inequalities to be reduced as a system:

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

Note

While solve() currently accomplishes the same thing (by calling reduce_inequalities() internally), that functionality may be deprecated or removed from solve(). We thus recommend using reduce_inequalities().

reduce_inequalities() is the top-level inequality-reducing function which will internally call any other lower-level inequality-reducing functions as needed.

Reducing One Inequality for a Single Variable Algebraically

If you have only one inequality, you can optionally exclude the list construct and simply pass reduce_inequalities() the inequality as an expression:

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

Guidance

Include the Variable to Be Reduced for in the Function Call

We recommend you include the variable to be reduced for as the second argument for reduce_inequalities() to ensure that it reduces for the desired variable.

Reduce a System of Inequalities Algebraically

You can create your inequalities, then reduce the system as a list:

>>> 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))

Use the Result

A common way to use the result is to extract the bounds for the symbol (variable). For example, for a solution of \(0 < x < \sqrt{\pi}\), you might want to extract \(0\) and \(\sqrt{\pi}\).

Extract a List of Decomposed Relations

You can decompose a set of relations which is joined by ^ (Or) or & (And) into individual relations using relational atoms. Using canonical will put order each relation so the symbol is on the left, so you can take the right-hand side rhs to extract the constants:

>>> 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))]

Extract a Tuple of Relations

The args (arguments) of reduced relations are the individual relations, so you can extract the constants from the left- or right-hand side of the 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)]

Limitations of Inequality Reduction Using SymPy

SymPy Can Reduce for Only One Symbol of Interest Per Inequality

SymPy can currently reduce for only one symbol (variable) of interest in a given inequality.

>>> 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.

You can use SciPy’s linprog() to reduce this system of inequalities.

SymPy can reduce for more than one symbol in a system, if there is only one symbol of interest per inequality. For example, the following system of inequalities has two variables, \(x\) and \(y\). SymPy can reduce for \(x\), and gives the constraints on \(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)

(oo is Infinity.)

If each inequality contains only one symbol to be reduced for, SymPy can reduce the set of inequalities for multiple symbols:

>>> 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)

Note that this provides no mathematical insight beyond reducing the inequalities separately:

>>> 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

so the benefit of solving such inequalities as a set maybe only convenience.

Limitations on Types of Inequalities That SymPy Can Solve

reduce_inequalities() can solve a system of inequalities involving a power of the symbol to be reduced for, or involving another symbol, but not both:

>>> 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.

Not All Results Are Returned for Periodic Functions

The results returned for trigonometric inequalities are restricted in its periodic interval. reduce_inequalities() tries to return just enough solutions so that all (infinitely many) solutions can generated from the returned solutions by adding integer multiples of the periodicity() of the equation, here \(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

Not All Systems of Inequalities Can Be Reduced

Systems of Inequalities Which Cannot Be Satisfied

If the system of inequalities has incompatible conditions, for example \(x < 0\) and \(x > \pi\), SymPy will return False:

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

Systems of Inequalities That Cannot Be Reduced Analytically

SymPy may reflect that your system of inequalities has no solutions that can be expressed algebraically (symbolically) by returning an error such as 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.

so you may have to reduce your inequalities numerically instead using SciPy’s linprog().

Inequalities Which Can Be Reduced Analytically, and SymPy Cannot Reduce

Refer to Limitations of Inequality Reduction Using SymPy above.

Report a Bug

If you find a bug with diophantine(), please post the problem on the SymPy mailing list. Until the issue is resolved, you can use a different method listed in Alternatives to Consider.