I am currently working with Sympy 1.0 and Python 2.7, and my aim is to replace every numerical parameter in an expression with a symbol.
For example:
2 * x + 3 * y - 10 * z -> a * x + b * y - c * z
So far I used expression.atoms(Number) to obtain the list of numerical parameters, to later replace them either using .subs or by writing everything to string and using .replace. However, I am facing an issue with expressions such as:
expression = sympy.simpify("x - z")
Where -z is actually -1 * z if I analyze the expression as a tree...but -1 does not appear among the result of expression.atoms(Number), so I cannot replace it.
Even converting the expression to a string to then use .replace does not really help, as -1 * z is always written out as -z.
There is probably some solution that I overlooked, but so far I am stuck. Can you help me? Thank you in advance for your time.
In fact, it turns out I probably did a moronic error when I first tried to use .subs; as Patrick noted in the comments, .subs works perfectly in this case.
Related
This question already has answers here:
How can I solve equations in Python? [closed]
(5 answers)
Closed 2 years ago.
from sympy import *
import numpy as np
x= symbols('x')
gfg_exp = np.tan(x)-1/x
intr = solve(gfg_exp, x)
print("After Integration : {}".format(intr))
I've tried to solve equation with this code but it did not work.
----> 5 gfg_exp = np.tan(x)-1/x
TypeError: loop of ufunc does not support argument 0 of type Symbol which
has no callable tan method
I'm sure this is due to tan(x).
If this is a bad way, is there a good code to work on the equations in the specific interval by Python?
It would be nice to use numerical algorithms, but it would take too much time to get one by one, and it would be inconvenient to set the initial value separately.
You did not specify that you need an algebraic/analytical solution... Good, because I don't think there is one. Regarding #jakub's comment to implement as follows:
import sympy
x = sympy.symbols("x")
out = sympy.solve(sympy.tan(x) - 1 / x, x)
That could work, but actually yields the error No algorithms are implemented to solve equation tan(x) - 1/x.
However, note that:
tan(x)=1/x -> x = arctan(1/x)
And notice that the derivative of this expression with regards to x is -1/(1+x²) which in absolute value is always less than one, hence you can make fixed point iterations to get a numerical solution, such as:
import numpy as np
x = 1
tol = 1e-17
while np.abs(np.tan(x) - 1/x) > tol:
x = np.arctan(1/x)
print('x =', x)
print('Final error:', np.abs(np.tan(x) - 1/x))
This yields to me:
x = 0.7853981633974483
x = 0.9050225767665427
...
x = 0.8603335890193796
x = 0.8603335890193798
x = 0.8603335890193797
Final error: 0.0
Process finished with exit code 0
Note that I've used x = 1 as my initial guess, but you can always pick the middle of any of your intervals as an initial guess, as long as you don't start with 0, you may need to add an offset in the equation to handle the fact that the arctangent function yields only results in the [-pi, pi] interval.
If you are in the state of finding value of x , i can help you.
you need to give a user input or any variable to x. And there is a library called as math(python inbuild library you need to use it). The equation need to have the variable x in one side . So the equation would be x = tan(x) - 1 . It may work and to calculate tan you need to use math.tan(x) . But you need to assign the value of x the the code would work fine . But practically thinking tan(x) - 1 / x = 0 simply says the the answer for equation is 0. If tan(x) - 1 goes to other side x would be zero. I dont think you expect answer as 0 . So use, "x = math.tan(x) - 1" . Hope this works.
This question already has answers here:
Evaluating a mathematical expression in a string
(14 answers)
Closed 3 years ago.
Is there a way to solve math equations that are in string format?
For example, I have
x = 2
y = 3
equations_str = ('x+y', 'x-y')
and I want a function that will give
results = (5, -1)
I want to do this because I want to have the equations as titles of figures, so they need to be strings.
I'm aware that a similar question was asked for java, but I'm not familiar enough with java so translate it to python.
Thanks!
Look into eval() https://www.geeksforgeeks.org/eval-in-python/ You can write statements and execute them.
eval example (interactive shell):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
As Jam mentioned, you can do the following:
equations_str = (eval('x+y'), eval('x-y'))
The only way I can think of solving this problem is to take your equation, calculate it as a regular integer, and then convert it into a string using str(). Then you could put that result into an array before proceeding. The only thing is that this method won't work for large amounts, but if you only need a few, this should work. Hope this helps, Luke.
Try the sympify function of the sympy package. It lets you evaluate strings, but uses the eval function, so do not use it on unsanitized input.
Example:
>>> from sympy import sympify
>>> str_expr = "x**2 + 3*x - 1/2"
>>> expr = sympify(str_expr)
>>> expr
x**2 + 3*x - 1/2
>>> expr.subs(x, 2)
19/2
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.
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.