1
$\begingroup$

I am trying to define in sympy an inequality inecuacion = "19 < -25*x - 1 <= 37" so that I can print the solution set on a graph. When I print with a single value, i.e. like this: 2*x-4 < 0, it can be evaluated, but when it is 19 < -25*x - 1 <= 37, I get the error:

raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational

Fragment of my code:

  inecuacion = "19 < -25*x - 1 <= 37"
  ineq = parse_expr(inecuacion)
  interval = solveset(ineq, domain=S.Reals)

  plot_interval(title=latex(ineq, mode="inline"),  
                start=interval.start, end=interval.end, 
                start_open=interval.left_open, end_open=interval.right_open,
                x_axis=(-10, 10),
                color="#073065")

How can I make it so that sympy can interpret this kind of inequality 19 < -25*x - 1 <= 37? Tanks very much. Regards

$\endgroup$
4
  • $\begingroup$ If parse_expr() parses Python, then this certainly isn’t legal Python. You need something like a<b and b<c for what mathematicians would write $a<b<c.$ $\endgroup$ Commented Jan 25, 2022 at 3:09
  • $\begingroup$ Need a poly()? $\endgroup$ Commented Jan 25, 2022 at 3:11
  • $\begingroup$ So, how I can do it? $\endgroup$ Commented Jan 25, 2022 at 3:57
  • $\begingroup$ I try this: from sympy.solvers.inequalities import solve_poly_inequalities from sympy.polys import Poly from sympy.abc import x a= solve_poly_inequalities((( Poly(3*x + 29 - 17), "<"), ( Poly(3*x - 17 - 22), ">"))) $\endgroup$ Commented Jan 25, 2022 at 3:58

1 Answer 1

0
$\begingroup$

I posted the original question on StackOverflow in Spanish, it was answered by Abulafia, I leave the link if you want more details. ¿Cómo puedo evaluar una inecuación con dos desigualdades en python?

You can use a regular expression to "split" your double inequality into two separate inequalities, like so (explanations later):

import re
ineq = "20 < 3*x + 5 < 26"

parts = re.split(r"([<>]=?)", ineq)
eq1= "".join(parts[:3])
eq2 = "".join(parts[-3:])
print(eq1)
print(eq2)

As you can see, the trick is the regular expression ([<>]=?) which means the following:

  • The parentheses, we are going to create a capturing group. That will cause re.split() to not only return the resulting "chunks", but also return the "separators" between the chunks (which are the inequality signs of the inequalities).
  • The brackets [<>] which can appear either < or >
  • The equal with a question mark =? which can optionally appear with an equal sign (so that it admits >= and <= as a separator)

The result of re.split() is going to be a list with five chunks, as long as your input string has a pair of inequality comparers. The first chunk would be in this example the "20 ". The next chunk would be the first separator ("<" in the example) the next chunk would be " 3*x +5"in this case. The next would be the second separator, again"<"in this example, and the fourth and last chunk would be"26"`.

The following .join() joins the appropriate pieces together to form two expressions (inequalities). One with the first three pieces, another with the last three. The result on eq1 and eq2 is:

20 < 3*x + 5
 3*x + 5 < 26

Once we have it separated in this way, we can use sympy to solve the two inequalities, for example like this:

from sympy import solve, S
ineq = [S(eq) for eq in (eq1, eq2)]
intervals = solve(ineq, domain=S.Reals)

The solution found by sympy is an And operation between two intervals and it shows it like this:

(5 < x) & (x < 7)

If you want to reduce it to "a single interval" (which in this example would be (5,7)) so that you can plot it with the technique explained [in this other answer](https://en.stackoverflow.com/a /510763/7123) you could calculate the intersection of these two intervals with the interval (-infinity, +infinity), for example like this:

from sympy import Interval, solveset

solution = Interval(float("-inf"), float("+inf"))
for interval in intervals.args:
  interval = solveset(interval, domain=S.Reals)
  solution &= interval

As you can see, we start by creating the infinite interval, and then we iterate through intervals.args (which are each of the inequalities previously obtained with solve()), to resolve the inequalities posed by each of them, and so on. have intervals whose intersection with solution we compute with the &= operator.

The result in solution is an interval, namely (5, 7) in this case, which you can already plot with the above solution.

Note: This solution is not quite general, depending on the input inequality it may be that in the end you will not be able to obtain a single interval-solution, but two if solve() generates two disjoint inequalities.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .