简体   繁体   中英

Getting the error: can't convert expression to float

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM