5

In Sympy it is possible to define constraints on what values a symbol may take

x = symbols('x', real=True)

Is it possible to say that a symbol should take values only in a certain range, say -1 < x < 1? The reason why I am interested in this is because I am trying to get sympy to automatically simplify expressions like the one below

expr = sqrt(1+x) * sqrt((1-x)*(1+x)) / sqrt(1-x)

Running simplify(expr) yields no simplification, whereas when -1<x<1 the simplified result should be 1+x. How do I get sympy to simplify expressions like the one above?

D R
  • 21,936
  • 38
  • 112
  • 149
  • 4
    You may declare Q.positive(x+1) & Q.positive(x-1) with the new style assumptions. Unfortunately the new assumptions are not yet linked to the inference rules, so they are quite useless for now. Also notice that simplify ignores assumptions in this case, because it would be otherwise too slow. – Francesco Bonazzi Oct 09 '15 at 02:28

2 Answers2

2

Although a single symbol can't hold that assumption, an expression can. Let's define an expression that has the desired range:

>>> p = Symbol('p', positive=True)
>>> neg1to1 = (p - 1)/(p + 1)

Now replace x with that value and simplify

>>> asp = expr.subs(x, neg1to1).simplify(); asp
2*p/(p + 1)

Now restore x from the relationship between it and neg1to1:

>>> p_as_x = solve(neg1to1 - x, p)[0]
>>> asp.subs(p, p_as_x).simplify()
x + 1

You could turn this into a function to allow for any range for x:

>>> def simplify_assuming_range(expr, x, lo, hi):
...      from sympy import Dummy, solve
...      p = Dummy(positive=True)
...      xr = (p - 1)/(p + 1)*(hi - lo) + lo
...      rx = solve(xr - x, p)[0]
...      return expr.subs(x, xr).simplify().subs(p, rx).simplify()
... 
>>> simplify_assuming_range(expr,x,-1,1)
x + 1
smichr
  • 16,948
  • 2
  • 27
  • 34
0

Using targeted expansion with force can help:

>>> expand(expr, power=True, force=True, mul=False)
x + 1

The expand docstring will tell about each of those options.

smichr
  • 16,948
  • 2
  • 27
  • 34