2

If I use simplify() function in sympy, log((exp(x)+1)/exp(x)) does simplify to log(1+exp(-x)), however, as I read the doc, the simplify function is "can be unnecessarily slow", I tried other simplification methods, but non of them works, so I'm wondering how do I simplify ln((exp(x)+1)/exp(x)) to the form like this log(1+exp(-x)) without calling simplify().

  • Have you experienced the function being "unnecessarily slow" ? Simplification of mathematical functions is not a particularly easy task. I'd look at http://docs.sympy.org/dev/modules/simplify/simplify.html to help understand what the function does. – vielmetti Aug 10 '16 at 17:58
  • I think another problem is it's unpredictable because it choose the answer based on it's length. My job is to compare two equations, so I do need the result to be predictable, I'm trying to use functions in the simplify doc, but can't get any of them to work unless I use simplify() – Michael Yuxi Dong Aug 10 '16 at 18:57
  • The desired result arises immediately for me...I am using Sympy 1.0. – comer Aug 10 '16 at 20:19
  • I'm using 1.0 too and it only shows the desired result if I use simplify() function, but I don't really want to – Michael Yuxi Dong Aug 11 '16 at 02:50

2 Answers2

4

The exact function you want to use depends on the general form of the expressions you are dealing with. cancel apparently works, but perhaps only by accident. In general, cancel cancels common factors from a numerator and denominator, like cancel((x**2 - 1)/(x - 1)) -> x + 1. I think it is only working here because it represents the expression in terms of exp(-x). If it instead used exp(x), it wouldn't simplify, because (x + 1)/x doesn't have any common factors. This might be why you are seeing different results from cancel in different versions. See this issue for more information.

For this expression, I would use expand() (or the more targeted expand_mul). expand will distribute the denominator over the numerator, i.e., (exp(x) + 1)/exp(x) will become exp(x)/exp(x) + 1/exp(x). SymPy then automatically cancels exp(x)/exp(x) into 1 and converts 1/exp(x) into exp(-x) (they are internally both represented the same way).

In [1]: log((exp(x)+1)/exp(x)).expand()
Out[1]:
   ⎛     -x⎞
log⎝1 + ℯ  ⎠

There's a guide on some of the simplification functions in the tutorial.

asmeurer
  • 86,894
  • 26
  • 169
  • 240
3

You can more directly just use sympy.polys.polytools.cancel(), which is available as a method on your expression with .cancel().

>>> from sympy.abc import x
>>> from sympy import *
>>> my_expr = log((exp(x)+1)/exp(x))
>>> my_expr.cancel()
log(1 + exp(-x))

This is what is doing the work of simplifying your expression inside simplify().

A very naive benchmark:

>>> import timeit
>>> %timeit my_expr.simplify()
100 loops, best of 3: 7.78 ms per loop
>>> %timeit my_expr.cancel()
1000 loops, best of 3: 972 µs per loop

Edit: This isn't a stable solution, and I would advise that you take a look at asmeurer's answer where he suggests using expand().

Community
  • 1
  • 1
miradulo
  • 28,857
  • 6
  • 80
  • 93