pythonsympy

How to force Sympy to simplify expressions that contain logarithms inside an exponential?


Consider the following MWE:

import sympy as sp
a,b = sp.symbols("a b", positive=True, real=True)
t = sp.symbols("t", real=True)
s = sp.symbols("s")
T = 1/(1+s*a)/(1+s*b)
y = sp.inverse_laplace_transform(T,s,t)
tmax = sp.solve(sp.diff(y,t),t)[0]
ymax = y.subs(t,tmax)
display(ymax.simplify())

This code gives the following output: Output in the console

How can I force Sympy to simplify this expression? Both the fraction and the sum can be decomposed easily, leaving a term in the form of exp(log(x)), which can be simplified to x.

Edit: Here is one example how the simplification of one exp() term could look like (the first one in this case): Partial solution


Solution

  • Notice the denominators in the arguments of the exponentials (which are different than you posted, but that is what I get):

    >>> from sympy import *
    ...your code...
    >>> e=ymax.atoms(exp);e
    [exp(-log((a/b)**(a*b))/(a**2 - a*b)), exp(-log((a/b)**(a*b))/(a*b - b**2))]
    

    If you assure SymPy that those are non-zero (and real), all can be well:

    >>> p,q = var('p q',nonzero=True) # nonzero=True implies real
    >>> reps = {a**2-a*b:p,a*b-b**2:q}; _reps = {v:k for k,v in reps.items()}
    >>> [i.subs(reps).simplify().subs(_reps) for i in e]
    [(b/a)**(a*b/(a**2 - a*b)), (b/a)**(a*b/(a*b - b**2))]
    

    Is that what you were hoping would happen to them? If so you can write a handler to be used with replace to target out the exp and make the denominator nonzero:

    def handler(x):
        assert isinstance(x, exp)
        e = x.args[0]
        n,d = e.as_numer_denom()
        if d.is_nonzero:
            return x.simplify()
        nz=Dummy(nonzero=True)
        return exp(n/nz).simplify().subs(nz,d)
    
    >>> ymax.replace(lambda x:isinstance(x,exp), handler)
    a*(b/a)**(a*b/(a**2 - a*b))*Heaviside(log((a/b)**(a*b))/(a - b))/(a**2 - a*b) - b*(b/a)**(a*b/(a*b - b**2))*Heaviside(log((a/b)**(a*b))/(a - b))/(a*b - b**2)