Trying to compute the following lines I'm getting a realy complex result.
from sympy import *
s = symbols("s")
t = symbols("t")
h = 1/(s**3 + s**2/5 + s)
inverse_laplace_transform(h,s,t)
The result is the following:
(-(I*exp(-t/10)*sin(3*sqrt(11)*t/10) - exp(-t/10)*cos(3*sqrt(11)*t/10))*gamma(-3*sqrt(11)*I/5)*gamma(-1/10 - 3*sqrt(11)*I/10)/(gamma(9/10 - 3*sqrt(11)*I/10)*gamma(1 - 3*sqrt(11)*I/5)) + (I*exp(-t/10)*sin(3*sqrt(11)*t/10) + exp(-t/10)*cos(3*sqrt(11)*t/10))*gamma(3*sqrt(11)*I/5)*gamma(-1/10 + 3*sqrt(11)*I/10)/(gamma(9/10 + 3*sqrt(11)*I/10)*gamma(1 + 3*sqrt(11)*I/5)) + gamma(1/10 - 3*sqrt(11)*I/10)*gamma(1/10 + 3*sqrt(11)*I/10)/(gamma(11/10 - 3*sqrt(11)*I/10)*gamma(11/10 + 3*sqrt(11)*I/10)))*Heaviside(t)
However the answer should be simpler, Wolframalpha proves it.
Is there any way to simplify this result?
I tried a bit with this one and the way I could find a simpler solution is using something like:
from sympy import *
s = symbols("s")
t = symbols("t", positive=True)
h = 1/(s**3 + s**2/5 + s)
inverse_laplace_transform(h,s,t).evalf().simplify()
Notice that I define t as a positive variable, otherwise the sympy function returns a large term followed by the Heaviaside function. The result still contains many gamma functions that I could not reduce to the expression returned by Wolfram. Using evalf() some of those are converted to their numeric value and then after simplification you get a expression similar like the one in Wolfram but with floating numbers.
Unfortunately this part of Sympy is not quite mature. I also tried with Maxima and the result is quite close to the one in Wolfram. So it seems that Wolfram is not doing anything really special there.
Related
I am trying to solve this ordinary linear differential equation of second order with SymPy and get an unexpected result.
import sympy as sym
k, t = sym.symbols('k, t')
s = sym.Function('s')
diff_eq = sym.Eq(s(t).diff(t, 2) + s(t) * k**2, 0) # everything fine here, when I print this I get what I expected.
solution_diff_eq = sym.dsolve(diff_eq, s(t))
print(solution_diff_eq)
Which prints
Eq(s(t), C1*exp(-I*k*t) + C2*exp(I*k*t))
However, the solution I expected is
Any ideas what I have done wrong?
The result prints as
Eq(s(t), C1*exp(-I*k*t) + C2*exp(I*k*t))
which is correct, as I is the imaginary unit. You might prefer the real form, but sympy was not notified of that and produced the most simple form as sum of exponential terms, especially as it is not clear if k is actually real.
If you make it explicit that k is a positive real number via
k = sym.Symbol('k', real=True, positive=True)
the solution is actually in real form, as you were expecting
Eq(s(t), C1*sin(k*t) + C2*cos(k*t))
I have a function whose roots I'd like to find. So far, even Mathematica was inable of finding the roots analytically, so numerically is fine (but please, I'd be happy to be surprised on this matter).
The examples in the documentation all refer to "real" functions, lambda functions, and don't address this issue sufficiently (or I'm just too slow to understand). Here's a simple use case:
from sympy import *
p, r, c, y, lam, f = symbols('p r c y lambda f')
priceCDF = (c*lam*p + c*r - lam*p*r - p*r + r*(c - p)*LambertW(-exp((-c*lam*p - c*r + lam*p*r + lam*r*(c - p) + p*r)/(r*(c - p))), -1))/(lam*r*(c - p))
priceCDFplot = priceCDF.subs(r, 2).subs(c, 0.5).subs(lam, 1)
mpmath.findroot(priceCDFplot, 0.8)
which gives me TypeError: 'Mul' object is not callable. What am I wrong, how do I numerically find the root -- and how could I find it analyitcally?
If you want to use mpmath.findroot, you'll need to convert the SymPy expression to a mpmath expression. The easiest way to do this is with lambdify(p, priceCDF, 'mpmath') (I'm assuming p is the variable you want to solve for).
Another solution would be to use sympy.nsolve, which works directly on SymPy expressions.
I am using IPython (Anaconda distribution) with the sympy symbolic maths library.
I have the following expression:
t⋅(h + l)
───────────────────────
l⋅(h + l⋅sin(θ))⋅cos(θ)
I would like to rearrange this to get it in terms of (h/l) and (t/l):
(t/l)⋅((h/l)+1)
─────────────────────
((h/l)+sin(θ))⋅cos(θ)
This is quite easy to do by hand; just divide both sides of the fraction by l and rearrange.
So far I have had no luck with sympy's built in functions.
I have tried using expand followed by collect(expr,h/l), but it doesn't change the expression. I suspect this doesn't work because there are no h/l terms for it to collect in the first place.
How do I get sympy to do this?
Python code for the first expression to save you time:
t*(h + l)/(l*(h + l*sin(theta))*cos(theta))
Building on strubbly's idea:
In [2]: expr = t *(h +l )/(l *(h +l *sin (theta ))*cos (theta ))
In [3]: expr
Out[3]:
t*(h + l)
-------------------------------
l*(h + l*sin(theta))*cos(theta)
In [4]: repl1 = [x-h/l, y-t/l]
In [7]: repl2 = solve(repl1, t, l)
In [8]: repl2
Out[8]:
h h*y
{l: -, t: ---}
x x
In [9]: simplify(expr.subs(repl2)).subs({x: h/l, y: t/l})
Out[9]:
/h \
t*|- + 1|
\l /
-----------------------------
/h \
l*|- + sin(theta)|*cos(theta)
\l /
That is, introduce two variables x and y to replace h/l and t/l (In[4]), invert the equalities in order to get the replacement dictionary (In[7]). Replace, simplify (to get rid of the l), then substitute back the original values for x and y. One variable gets still simplified away.
One should tell .subs( ... ) not to evaluate the expression after substitution. I don't know whether that's currently supported.
So I used x = h/l and y = t/l and substituted. Then simplified. This gave me
x*(y + 1)/((y + sin(theta))*cos(theta))
Which I think is what you want. I can't see how to simplify "with respect to" h/l but this works...
Unless you glom the ratios together, the leading fraction will split across the division line. There are two ways to glom: with an UnevaluatedExpr and with "symbol trickery". First the UnevaluatedExpr:
>>> from sympy import UnevaluatedExpr as UE
>>> eq
t*(h + l)*cos(th)/(l*(h + l*sin(th)))
>>> factor_terms(_.subs(t, UE(t/l)*l).subs(h, UE(h/l)*l))
cos(th)*(sin(th) + h/l)**(-1)*(1 + h/l)*(t/l)
Notice how the order is not as you hoped. So now replace that UE with a symbol that looks like a UE:
>>> _.replace(lambda x: isinstance(x, UE), lambda x: Symbol(str(x)))
t/l*(h/l + 1)*cos(th)/(h/l + sin(th))
So that look like you wanted. The t/l and h/l are actually symbols with a complex name. (You can even use latex for the symbol names.)
I dont really know if you can uses regex, but if you can, you can use re.sub to replace all instances of h with (h/1). or if the expression is a string, you can use str.replace to do the same thing.
I am looking for a way to do a plus/minus operation in python 2 or 3. I do not know the command or operator, and I cannot find a command or operator to do this.
Am I missing something?
If you are looking to print the ± symbol, just use:
print(u"\u00B1")
Another possibility: uncertainties is a module for doing calculations with error tolerances, ie
(2.1 +/- 0.05) + (0.6 +/- 0.05) # => (2.7 +/- 0.1)
which would be written as
from uncertainties import ufloat
ufloat(2.1, 0.05) + ufloat(0.6, 0.05)
Edit: I was getting some odd results, and after a bit more playing with this I figured out why: the specified error is not a tolerance (hard additive limits as in engineering blueprints) but a standard-deviation value - which is why the above calculation results in
ufloat(2.7, 0.07071) # not 0.1 as I expected!
If you happen to be using matplotlib, you can print mathematical expressions similar as one would with Latex. For the +/- symbol, you would use:
print( r"value $\pm$ error" )
Where the r converts the string to a raw format and the $-signs are around the part of the string that is a mathematical equation. Any words that are in this part will be in a different font and will have no whitespace between them unless explicitly noted with the correct code. This can be found on the relavent page of the matplotlib documentation.
Sorry if this is too niche, but I stumbeled across this question trying to find this very answer.
Instead of computing expressions like
s1 = sqrt((125 + 10 * sqrt(19)) / 366)
s2 = sqrt((125 - 10 * sqrt(19)) / 366)
you could use
import numpy as np
pm = np.array([+1, -1])
s1, s2 = sqrt((125 + pm * 10 * sqrt(19)) / 366)
I think you want that for an equation like this;
Well there is no operator for that unless you don't use SymPy, only you can do is make an if statement and find each multiplier.
There is no such object in SymPy yet (as you saw, there is an issue suggesting one https://github.com/sympy/sympy/issues/5305). It's not hard to emulate, though. Just create a Symbol, and swap it out with +1 and -1 separately at the end. Like
pm = Symbol(u'±') # The u is not needed in Python 3. I used ± just for pretty printing purposes. It has no special meaning.
expr = 1 + pm*x # Or whatever
# Do some stuff
exprpos = expr.subs(pm, 1)
exprneg = expr.subs(pm, -1)
You could also just keep track of two equations from the start.
Instead of computing expressions like
s1 = sqrt((125.0 + 10.0*sqrt(19)) / 366.0)
s2 = sqrt((125.0 - 10.0*sqrt(19)) / 366.0)
you could use
r = 10.0*sqrt(19)
s1, s2 = (sqrt((125.0 + i) / 366.0) for i in (r, -r))
This is based on Nico's answer, but using a generator expression instead of NumPy
A plus/minus tolerance test can be done using a difference and absolute against the tolerance you wish to test for. Something like:
tst_data = Number you wish to test
norm = Target number
tolerance = Whatever the allowed tolerance is.
if abs(tst_data - norm) <= tolerance:
do stuff
Using the abs function allows the test to return a +/- within tolerance as True
I'm using Sympy's sympify function to simplify 2 expressions so I can compare them for equality.
For example:
expr1 = sympify("(2 * x) + (x + 10)")
expr2 = sympify("(x + 10) + (x * 2)")
if expr1 == expr2:
print "Congrats those are essentially the same!"
However when using the form 2x as apposed to x*2 i get a parse exception eg:
expr1 = sympify("2x + (x + 10)")
Is there any way I can get sympy to understand the 2x form ?
If not, is there any other library that will allow this form ?
Well, you could modify the sympy lexer (or parser / grammar / whatever).
You could also wrap it with a function that transformed your input strings for you, using something like this:
>>> import re
>>> expr = '2x + 1'
>>> re.sub(r"(\d+)(\w+)", r"(\1 * \2)", expr)
'(2 * x) + 1'
But ask yourself why this notation isn't there to begin with.
For example, all of these are valid python, and though it's been a long while since I messed with sympy, I bet they mean something besides multiplication in sympy too:
0x32 # hex for 50
5e-3 # 0.005
2j # 2 * sqrt(-1) (so that one *is* multiplication, but by 1j, not j!)
15L # 15 (L used to represent long integers in python)
And what does x2 mean? Is it a variable named x2 or does it mean (x * 2). I purposely left this case out of the regular expression above because it's so ambiguous.
The development version of SymPy has the ability to parse such expressions. See http://docs.sympy.org/dev/modules/parsing#sympy.parsing.sympy_parser.implicit_multiplication_application. It is still not enabled by default in sympify, because sympify only does very basic extensions to the Python syntax (i.e., wrapping of numeric literals and undefined names, and converting ^ to **). But there is an example there that shows how to use it.
Note that this currently also applies implicit function application as well. Probably the two functionalities should be split up.
EDIT: Those functions are being split up in a pull request.