input a symbolic function in a python code - python

I was just wondering if there is a method to input a symbolic function in a python code?
like in my code I have:
from sympy import *
import numpy as np
import math
myfunction = input("enter your function \n")
l = Symbol('l')
print myfunction(l**2).diff(l)
If I put cos, sin or exp, as an input then I have an output of: -2*l*sin(l**2)
What If I want to make the input function more general, say a polynomial or a complex function, or maybe a function of combined cos, sin and exp ???

As a syntax, sin + cos simply isn't going to work very well. The simplest way to get the general case to work is to give sympy an expression to evaluate. We can let sympify do the hard work of turning a string into a sympy object:
>>> s = raw_input("enter a formula: ")
enter a formula: sin(x) + x**3
>>> s
'sin(x) + x**3'
>>> f = sympy.sympify(s)
>>> f
x**3 + sin(x)
After which we can substitute and evaluate:
>>> f.subs({'x': 2})
sin(2) + 8
>>> f.subs({'x': 2}).evalf()
8.90929742682568
See also my answer here for some other tricks you can pull with a bit of work:
>>> f = definition_to_function("f(x) = sin(x) + x**3")
>>> f(3)
27.14112000805987

If you need good support for symbolic funcions, you should consider using sage.
It is a preprocessor for python, with lots of math support including symbolic functions. Sage code can be intermixed with normal python-code.
The package is quite big, but I have good experiences with it. It is free and open-source.

Related

How to solve implementation problem in sympy

I need to solve an equation, but spider returns me this error:
import sympy as sym
import sympy as sympy
Re=100
Epsilon=0.00000075
D=0.01
f=symbols('f')
eq=(((1/(-2* sympy.log((Epsilon/D/ 3.7)+( 2.51 / (Re*(f**0.5))), 10)))**2 -f),0)
sym.solve((eq), (f))
print(f)
NotImplementedError: could not solve -4*f*log(202702702702703/10000000000000000000 + 251/(10000*sqrt(f)))**2 + log(10)**2
The solve function is for finding analytic solutions but that isn't possible for your equation (not all equations have analytic solutions):
In [11]: eq[0]
Out[11]:
2
log (10)
-f + ──────────────────────────────────────────
2⎛ -0.5 ⎞
4⋅log ⎝0.0251⋅f + 2.02702702702703e-5⎠
You can find a numeric solution with nsolve:
In [12]: sym.nsolve(eq[0], f, 0.1)
Out[12]: 0.169438052045717
https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.nsolve
This can be represented in terms of the LambertW function, but it needs some help. SymPy doesn't recognize the inverted sqrt(f) in the log. If you replace that with 1/y and solve for y and transform the solutions for y back to f you can get a symbolic solution.
It's easier in this case to let SymPy work with symbols instead of Floats and substitute the values later. Your equation looks like this:
>>> from sympy import a,b,c
>>> seq = a**2/log(b/sqrt(f) + c)**2 - f
>>> reps = {a:log(10)/2, c:Epsilon/D/3.7, b:2.51/Re}
Replace that sqrt(f) with 1/y
>>> ysol = solve(seq.xreplace(sqrt(f), 1/y), y)
Calculate the corresponding solutions for f:
>>> fsol = [((1/i)**2) for i in ysol]
Substitute in your values -- or any values that you are interested in:
>>> [i.xreplace(reps).n(3) for i in fsol]
[0.00771 - 0.107*I, 0.169]
Testing in the original shows that the second solution is valid
>>> [eq.subs(f,i).n() for i in _]
[0.148289010493944 + 0.206688429851791*I, 6.05179945288758e-6]
So your symbolic solution is
>>> fsol[1]
(-c/b + LambertW(a*exp(a*c/b)/b)/a)**(-2)
The nice thing about this form is that you can substitute any values of a,b,c and get the corresponding value of f. Whether this is faster than using nsolve, you will have to see.

I am writing a program that accepts user input in order to differentiate a function

In order to find the maximums and minimums of a function, I am writing a program that accepts a polynomial imputed from the user and finds where the derivative = 0.
from sympy import Symbol, Derivative
from sympy import symbols, Eq, solve
import sympy as sy
import numpy as np
import math
x= Symbol('x', real = True)
function= x**4 +7*x**2 +8
deriv= Derivative(function, x)
yprime = deriv.doit()
y = symbols('x')
eq1 = Eq(yprime,0)
sol = solve(eq1, )
The only reason that the code above is able to take the derivative and find solutions is because the coefficients and exponents are integers. If I ask for user input {e.g., function = input("What is your function: ")}, then the whole thing will become a string and SymPy can not take the derivative.
Is it possible to turn the coefficients and exponents into integers and leave the rest of the function as a string so that I can take the derivative?
If your equation can be arbitrarily complicated, you might want to use eval to parse it from Python syntax. Now, eval is generally unsafe to use on untrusted user input, but a user replying to an input() prompt is probably trusted (since they're usually sitting at the computer running the code).
So one option is:
function = eval(input("What is your function: "))
If placed just below the definition of x, it will allow that variable to be used in the equation. You could also provide a namespace for eval to use, rather than letting it use your function's local namespace (e.g. function = eval(input(...), {'x': Symbol('x', real=True)})).
If your problem space is more limited, and you only need to handle equations that are polynomials with integer coefficients, then you could write your own logic to input the equation in a much more simplified form. For instance, you could loop, asking for the coefficients in order (probably from the lowest exponent to the highest). Try something like this:
import itertools
from sympy import Symbol
x = Symbol('x', real = True)
function = 0
for exponent in itertools.count():
coef = input(f"Enter coefficient for x**{exponent} (or give an empty value to be done): ")
if not coef:
break
function += int(coef) * x**exponent
print("Polynomial so far:", function)
For the example equation in your question, you'd enter 8, 0, 7, 0, 1 and finally an empty input.
The better thing to do is to turn your string into a SymPy expression. As long as the user uses SymPy/python syntax, sympyify will convert it for you:
>>> from sympy import sympify, solve
>>> user='3*x**2-1'
>>> eq = sympify(user)
>>> x = eq.free_symbols.pop() # assuming there is 1 symbol
>>> solve(eq.diff(x))
[0]

Can Sympy identify functions in expressions, if fuctions are defined?

I've seen that Sympy has a sympy.Function feature, but can't find an answer to the following in the documentation.
Is it possible to find custom functions in expressions and use the function definition to simplify them.
As a very simple example, I define the function: f(x) = 2 * exp(x).
Now let's say I have some Sympy expression: 6 * exp(y + z)
Is it possible to tell Sympy to simplify this expression to give a result in terms of the function f.... i.e. so the output from Sympy is: 3 * f(x).
I've found that using .subs() works for simple substitution of variables, but this doesn't seem to work for functions that contain symbols as arguments, as above.
Thanks.
I think what you want to do is not supported by Sympy at the moment (see for instance this stackoverflow question). Nevertheless, something very close can be done with this code:
from sympy import symbols, exp
x, f = symbols('x, f')
expr = 6 * exp(x)
f_func = 2 * exp(x)
print(expr.subs({f_func: f}))
# 3 * f
In the above code I have assumed that the expression you wanted to simplify (expr in the code) was a function of x.

Trigonometric identities with Python and Sympy, tan(A/2) = (sin A )/(1 + cos A)

I'm not sure how to get Sympy to perform / simplify these types of identities?
It does things like sin(a + b), but doesn't seem to do others (like the one in the title)
One approach is to try various combinations of simplification functions/methods such as rewrite and simplify. For example, the following gives the result you want:
import sympy as sp
x = sp.var('x', real = True)
f = sp.tan(x/2)
sp.re(f.rewrite(sp.exp).simplify().rewrite(sp.sin)).simplify()
sin(x)/(cos(x) + 1)

Converting expression involving tranpose of vector to numerical function with lambdify

I have written a script in python that uses sympy to compute a couple of vector/matrix formulas. However, when I try to convert those to functions that I can evaluate with sympy.lambdify, I get a
SyntaxError : EOL while scanning string literal
Here's some code with the same error, so that you can see what I mean.
import sympy
x = sympy.MatrixSymbol('x',3,1)
f = sympy.lambdify(x, x.T*x)
So, the syntax error has to do with the expression "x'.dot(x)" and the conversion of ".T" to '.
How can I work around this to correctly define f from the above lambdify?
Found a work around, although not the cleanest looking solution... but it works.
Use the implemented_function() method from sympy to define your function. Read full documentation here: http://docs.sympy.org/latest/modules/utilities/lambdify.html
Here is the code:
import sympy
import numpy as np
from sympy.utilities.lambdify import implemented_function
x = sympy.MatrixSymbol('x',3,1)
f = implemented_function(sympy.Function('f'), lambda x: x.T*x)
lam_f= sympy.lambdify(x, f(x))
Hope this solves your problem :)
It has been solved in sympy version >= 1.1
Edit:
Example
when u define this
x = sympy.MatrixSymbol('x',3,1)
you are creating a matrix,
you can check its indexing and shape using
print(sympy.Matrix(x))
Now that you want to multiply Transpose of x to x, you will have to give x a matrix of same shape that you have defined before
here try this:
from sympy import MatrixSymbol, lambdify, Matrix
x = MatrixSymbol('x', 3, 1)
f = lambdify(x, x.T*x)
a = Matrix([[1], [2], [3]])
print(f(a))
you can check this link out to understand lambdify better:
http://docs.sympy.org/latest/modules/utilities/lambdify.html

Categories