Rational function factor cancellation in simplify

63 views
Skip to first unread message

EKW

unread,
Oct 17, 2017, 8:08:32 PM10/17/17
to sympy
>>> from sympy import *
>>> x = Symbol('x')
>>> p = (x**2 + x) / ((x - 1)*(x + 1))
>>> print(p)
(x**2 + x)/((x - 1)*(x + 1))
>>> p = simplify(p)
>>> print(p)
x/(x - 1)

This simplification is only valid for x != -1, and I haven't specified any restrictions on the range of x. Was this done on purpose, and if so why?

Kalevi Suominen

unread,
Oct 18, 2017, 6:28:02 AM10/18/17
to sympy

Defining x as a Symbol makes it different from any number.


>>> from sympy import *
>>> x = Symbol('x')
>>> x != -1
True

It is possible to substitute a number for x, but then then the expression will also be different.

Kalevi Suominen

Aaron Meurer

unread,
Oct 18, 2017, 3:23:48 PM10/18/17
to sy...@googlegroups.com
Cancellation of removable singularities is useful enough that it's
included in the default simplify() heuristics. Without it, it would be
quite annoying to most use cases. It's also not uncommon that in the
process of creating an expression a removable singularity is created,
through multiplying and dividing by some term.

Some functions are more careful about this. For instance, solve((x**2
+ x)/((x - 1)*(x + 1)), x) returns [0], not [-1, 0].

But also be aware that, for instance, x/x always automatically reduces
to 1. This is due to the way the internal representation works in
SymPy. a/b is treated like a*b**-1, and exponents on terms with common
bases always combine automatically.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/c8ec5e5d-56db-45cd-9ec5-013d7074cac8%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Richard Fateman

unread,
Oct 19, 2017, 8:18:59 PM10/19/17
to sympy
Another way of explaining this is to say that sympy (and all its
competitors) implement arithmetic in a field of fractions, in
which that cancellation is valid.  The perspective of
abstract algebra provides a computational framework for
polynomials and rational functions.  See for example
https://en.wikipedia.org/wiki/Field_of_fractions

Just because we were told to never divide by zero
doesn't mean something like it is illegal in some other context.

You might argue  ...  but but  I don't even know what
a Field of Fractions is!   

And yet, you've (and sympy) have been using it...

Also, Aaron's point below is another, somewhat different
explanation, which is an argument from analysis, heuristically,
rather than algebra, formally.
RJF

Richard Fateman

unread,
Oct 19, 2017, 8:31:49 PM10/19/17
to sympy
apologies for apparently responding to myself.  This link may provide a
useful, if somewhat long-winded explanation.


EKW

unread,
Oct 23, 2017, 2:17:39 AM10/23/17
to sympy
And I guess there's a similar rational for simplifying asin(sin(x)) to x? This one seems harder to justify since, for example, asin(sin(10)) is -0.575222039230620 which is obviously not equal to 10.

Aaron Meurer

unread,
Oct 23, 2017, 2:40:06 AM10/23/17
to sy...@googlegroups.com
I'm not really sure why simplify() simplifies asin(sin(x)) to x. I
agree that's more problematic. By default, it remains unevaluated. We
should look into it, and perhaps consider removing that behavior.

It's definitely a different thing. When you convert (x**2 + x)/x to x
+ 1, you expand the domain (by a single point, x=0). But when you
convert asin(sin(x)) to x, that restricts the domain (to [-pi/2,
pi/2], at least for real x).

Typically in SymPy forcibly restricting the domain of a variable
requires some kind of force=True flag. For instance, logcombine(log(x)
+ log(y)) requires force=True for the default assumptions on x and y
to give log(x*y), since it's only valid for certain x and y (e.g., if
they are both positive).

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/52a88afc-3429-428a-ad33-2130b0fc1025%40googlegroups.com.

Richard Fateman

unread,
Oct 24, 2017, 3:42:39 AM10/24/17
to sympy
What is the rationale  (not rational :)  ) for simplifying asin(sin(x)) to x ?

I suppose one rationale is that you haven't really looked at the consequence
and therefore think it is a good idea.  But it is a bad idea.
Also log(exp(x)) --> x  is a bad idea.  The reason is,  asin and log are
multi-valued and if you (or the simplifier) chooses a particular value,
behind the scenes, in the middle of a computation, and it is the wrong
one, then the answer comes out wrong.  It's this kind of design that
makes it possible to get a CAS to prove 0=1, or any other false
proposition, using "puzzles"

Actually, choosing the "wrong" sqrt gets you a quick proof, without
even using log or asin.

Now what if you say  x is in  (-pi, pi] What can you
say about asin(sin(x))?  Well, it depends on whether you want to
be mathematically correct, or not.  choose x=0, for example.
sin(x) is also 0.  No argument.,
asin(0) is ... what?   it is any  angle whose sine is 0.  That includes
n*pi for any integer n.  But But  ... what if we assume x is in that
interval??
It DOESN'T MATTER.   asin(0) is still multi-valued,

If you wanted to say that this particular answer from this particular
asin()  was in (-pi,pi],  then you might run with that.   But that
means that

    asin(sin(x+pi))  will come out as x.   And in particular,
    asin(sin(y))=y is sometimes FALSE,    with y=x+pi,  
    asin(sin(y))= y-pi.

Now all of this is based on the hypothesis that you would
try to have sympy produce the correct answer, as opposed
to the answer that seems "obvious to even a high school student".

Other computer algebra systems may or may not do the right
thing.  I just tried Maxima and Mathematica 
 -- asin(sin(x)) remains.  sin(asin(x)) is x,
which is correct.    asin(sin(0))  is simplified to 0. yech.

 It's a problem if you have no convenient way of dealing with
sets like {n*pi | n in integers}  throughout your system. (
those systems can represent such things, but I expect
will not treat them as first class objects.)  Sympy can do
the same thing, do worse, or do better.  Doing better
is difficult, I think.
Reply all
Reply to author
Forward
0 new messages