I am new to python and I am trying to find Christoffel symbols of a Riemannian metric on a surface but I got this error: TypeError: can't convert expression to float . For simplicity, I wrote another code with exactly the same error ( my fundamental code is very long and not readable so I tried this example code to understand my fault ). Here is my example code:
from sympy import *
import numpy as np
coor = symbols('x y')
x = [coor[0] ** 2, coor[1]]
christoffels = np.zeros((2,2))
for i in range(2):
for j in range(2):
christoffels[i][j] = x[i] * x[j]
print(christoffels)
Could you please tell me what is going wrong?
There are multiple problems with the assignment:
christoffels[i][j] = x[i] * x[j]
On the right-hand, we have symbols
and on the left-hand, there is NumPy floats array cell.
Therefore Python had difficulties to convert the symbols
to a float.
TypeError: can't convert expression to float
Let's fix it by defining the matrix as sympy
matrix :
from sympy import *
import numpy as np
coor = symbols('x y')
x = [coor[0] ** 2, coor[1]]
# Create sympy array
christoffels = zeros(2,2)
for i in range(2):
for j in range(2):
# Now assignment works
# NOTE: In sympy location denoted as [i, j] and not [i][j]
christoffels[i, j] = x[i] * x[j]
# Matrix([[x**4, x**2*y], [x**2*y, y**2]])
print(christoffels)
In an isympy
session (where x
, y
are already defined)
In [1]: coor = symbols('x y')
In [2]: coor
Out[2]: (x, y)
coor
is a tuple
In [3]: xx = [coor[0]**2, coor[1]]
In [4]: xx
Out[4]:
⎡ 2 ⎤
⎣x , y⎦
xx
is a list containing 2 sympy objects.
If we make an object dtype array, we can assign sympy elements:
In [5]: xy = np.empty((2,2),object)
In [6]: for i in range(2):
...: for j in range(2):
...: xy[i,j] = xx[i]*xx[j]
...:
In [7]: xy
Out[7]:
array([[x**4, x**2*y],
[x**2*y, y**2]], dtype=object)
Or a list comprehension way of creating the same
In [8]: [[i*j for j in xx] for i in xx]
Out[8]:
⎡⎡ 4 2 ⎤ ⎡ 2 2⎤⎤
⎣⎣x , x ⋅y⎦, ⎣x ⋅y, y ⎦⎦
As nested list and then array as before:
In [9]: np.array(_)
Out[9]:
array([[x**4, x**2*y],
[x**2*y, y**2]], dtype=object)
Object dtype arrays come up often on SO questions, but usually when creating 'ragged' arrays. They don't have the speed or computing power of numeric dtype arrays.
Some basic math does work with object dtype arrays, as long as the elements themselves implement the right methods (such as addition)
In [10]: xy.sum(axis=1)
Out[10]: array([x**4 + x**2*y, x**2*y + y**2], dtype=object)
In [11]: np.exp(xy)
...
TypeError: loop of ufunc does not support argument 0 of type Pow which has no callable exp method
(no one implements a exp
method.)
sympy
runs in python
, so basic python structures like tuples and lists are natural. The interaction with numpy
is hit-or-miss, and never as fast as the pure numeric arrays. sympy's
own matrix/array imports usually will give you more power, but require more study.
The sympy.Matrix
object given in the other answer:
In [20]: zz = zeros(2,2)
In [21]: for i in range(2):
...: for j in range(2):
...: zz[i,j] = xx[i]*xx[j]
...:
In [22]: zz
Out[22]:
⎡ 4 2 ⎤
⎢ x x ⋅y⎥
⎢ ⎥
⎢ 2 2 ⎥
⎣x ⋅y y ⎦
Can also be constructed from the nested list:
In [23]: Matrix(Out[8])
Out[23]:
⎡ 4 2 ⎤
⎢ x x ⋅y⎥
⎢ ⎥
⎢ 2 2 ⎥
⎣x ⋅y y ⎦
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.