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
Related
I am attempting to create a loop that will evaluate a function at discrete values. Normally this will be okay, however, this is proving to be difficult as my function is conditional (it has an adittional piecewise function which is dependent on the main variable.) This is an attempt I made below;
import math
import numpy as np
for i in np.arange(4000,8000,1000):
def f(λ,a,u,o1,o2):
o = o1 if (λ <= u) else o2
return a*math.exp((λ-u)^2/(-2*o^2))
print(f(i,1.056,5998,379,310))
I expected the code to evaluate the function at i=4000, then i=5000 etc. The output I recieve is as follows;
TypeError: ufunc 'bitwise_xor' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
I can't seem to find any specific examples for implementing a conditional function like this. Another attempt was made without a loop but I ran into value errors where I believe I was evaluating arrays as if they were one variable.
I wish to integrate and plot sums of the function later. Will I run into any issues with an approach involving a loop?
Python uses ** for exponentiation. ^ is bitwise xor.
Assuming your function is correct apart from the power operator **, a possible implementation with numpy would look like this
# import math # does not work well with numpy
import numpy as np
def f(l,a,u,o1,o2): # change 'λ' to 'l' (it's easier to type)
o = np.where(l <= u, o1, o2) # vectorize piecewise definition
return a*np.exp((l-u)**2/(-2*o**2)) # change '^' to '**' operator, use np.exp
x = np.arange(4000,8000,1000) # define value range
print(f(x,1.056,5998,379,310)) # call your function one time with entire range
Output
[9.74560013e-07 3.29586202e-02 1.05597802e+00 5.68878883e-03]
To reuse your function you can change it into a parameterized version
import numpy as np
def f(a,u,o1,o2):
return lambda x: a*np.exp((x-u)**2/(-2*np.where(x <= u, o1, o2)**2))
x = np.arange(4000,8000,1000)
f_p = f(1.056,5998,379,310) # parameterize your function
print(f_p(x)) # call the parameterized function with your value range
Output
[9.74560013e-07 3.29586202e-02 1.05597802e+00 5.68878883e-03]
import math
import numpy as np
def f(λ,a,u,o1,o2):
o = o1 if (λ <= u) else o2
return a*math.exp((λ-u)^2/(-2*o^2))
for i in np.arange(4000,8000,1000):
print(f(i,1.056,5998,379,310))
Try this code. This will work
I have created a function which, given ranges of coefficients, constructs polynomials with such coefficients and outputs a list of all their roots. However, Numba doesn't like it. It's like this:
import math
import numpy as np
import itertools
from numba import jit
from sympy.solvers import solve
from sympy import Symbol
from sympy import Poly
#jit
def polyn(ranges=[[-20,20],[-20,20],[-20,20],[-20,20]],step=4):
l = []
x = Symbol('x')
rangl = [np.linspace(i[0],i[1],math.floor((i[1]-i[0])/step)) for i in ranges]
coeffl = iter(itertools.product(*rangl))
leng = 1
for i in rangl:
leng *= len(i)
for i in range(0, leng):
a = solve(Poly(list(next(coeffl)),x),x)
for j in a:
l.append(j)
return np.array(l)
When I try to run this, it outputs a cryptic:
AssertionError: Failed at object (object mode frontend)
which I do not understand... Can anyone help?
There are a number of things in your code which Numba can't cope with currently. The first is the list comprehension where you build rangl:
[np.linspace(i[0],i[1],math.floor((i[1]-i[0])/step)) for i in ranges]
You should replace this with a NumPy solution like:
rangl = np.empty((len(ranges), step))
for i in ranges:
rangl[i] = np.linspace(i[0],i[1],math.floor((i[1]-i[0])/step))
The second thing Numba can't cope with is itertools.product. You can replace that with NumPy and a for loop as well.
In general, try to reduce your code by commenting out the lower part of it until you get Numba to accept it, then work from the top down and see which parts it can't compile. Be methodical, go step by step, and try to stick to simple constructs like simple for loops and arrays.
I'm using the package numddifftools to calculate the hessians of a multidimensional function (from R^n to R^n). While changing the code to use numpy arrays instead of lists, I discovered that doing so broke the code. Specifically:
import numpy as np
import numdifftools as nd
def function(x):
out = np.zeros(2)
out[0] = x[0] - x[1]**2/2.0
return float(out[0])
tempHessian = nd.Hessian(function, method='complex')
tempHessian([0.4,0.4])
Produces the error:
...\Continuum\Anaconda3\lib\site-packages\ipykernel_launcher.py:8: ComplexWarning: Casting complex values to real discards the imaginary part
and gives a zero hessian.
However, this one works fine:
import numpy as np
import numdifftools as nd
def function(x):
return x[0] - x[1]**2/2.0
tempHessian = nd.Hessian(function, method='complex')
tempHessian([0.4,0.4])
Any ideas what could be the problem? Thanks!
When out is created like this:
out = np.zeros(2)
it has type numpy.float64. You can't assign a complex value to such an array. Depending on which version of numpy that you are using, you'll get a warning or an error.
The complex step method for numerical differentiation requires that your function works with complex values. Forcing out to be numpy.float64 breaks that method. Converting the return value to floating point with float(out[0]) also breaks the method.
You can try something like this:
def function(x):
out = np.zeros(2, dtype=x.dtype)
out[0] = x[0] - x[1]**2/2.0
return out[0]
This creates out with the same data type as x. So if x is complex, the return value is also complex, as required by the complex step method.
(Of course, we don't know why you create out to have size 2, when only the first element is used. Presumably this is a simplification of the actual code that you are working with.)
I am trying to do symbolical calculations (derivatives mostly) on time-indexed variables using sympy.
Using indexed symbols like r[t] below produces an error:
from sympy import *
t = Idx('t',10)
r = IndexedBase('r')
diff(r[t],r[t])
diff(r,r)
ValueError:
Can't differentiate wrt the variable: r[t], 1
Could the reason be that something went wrong here:
In [15]: r[t].indices
Out[15]: (t,)
The comma after the index t looks suspicious to me, but I have no idea what went wrong.
Does anyone know how to do this in sympy?
You can differentiate wrt symbols, functions and derivatives. Will this work:
>>> t = Idx('t',10)
>>> r=Function('r')
>>> r(t).diff(r(t))
1
>>> var('t')
t
>>> r(t).diff(t)
Derivative(r(t), t)
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.