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:
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):
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)