TypeError: unhashable type 'numpy.ndarray' followed by SympifyError

Question:

I am following the steps on https://www.sympy.org/scipy-2017-codegen-tutorial/notebooks/22-lambdify.html in order to produce a plot of a surface. The example shown on the link works perfectly to me.

Now, the problem appears to me when trying to produce a plot of my own: I define my functions also making use of lambdify and, as far as I am concerned, following the same steps as in the link mentioned before. Here is my code:

import numpy as np
import plotly.graph_objects as go # for the surface
import sympy as sym

sym.init_printing()

## definition of the surface and its normal unitary field

u,v = sym.symbols('u v')                                                                                                           # we define the symbols
surface_expr = -sym.sqrt(1-u**2-v**2)                                                                                           # expresion for the surface
surface = sym.lambdify([u,v], surface_expr, modules = ['sympy'])                                                                       # symbolic surface

## plot the surface 

uplot = np.outer(np.linspace(-0.5, 0.5, 100), np.ones(100))                                                 # plotting mesh
vplot = uplot.T      
zplot = surface(uplot,vplot)                                                             # z value over the mesh

colorscale = 'oryel'                                                                     # color scale for the surface plot


fig = go.Figure()                                                                        # this creates the figure object
fig.add_surface(x=uplot, y=vplot, z=zplot, colorscale = colorscale)                      # we add a surfaceplot to it
fig.update_traces(showscale=False) 

When running this code, I get the following error:

TypeError                                 Traceback (most recent call last)
File ~/opt/anaconda3/lib/python3.9/site-packages/sympy/core/cache.py:70, in __cacheit.<locals>.func_wrapper.<locals>.wrapper(*args, **kwargs)
     69 try:
---> 70     retval = cfunc(*args, **kwargs)
     71 except TypeError as e:

TypeError: unhashable type: 'numpy.ndarray'

During handling of the above exception, another exception occurred:

SympifyError                              Traceback (most recent call last)
/Users/jzaragoza/PhD/Codes/offset_surface.ipynb Cell 4 in <cell line: 5>()
      3 uplot = np.outer(np.linspace(-0.5, 0.5, 100), np.ones(100))                                                 # plotting mesh
      4 vplot = uplot.T      
----> 5 zplot = surface(uplot,vplot)                                                             # z value over the mesh
      7 colorscale = 'oryel'                                                            # color scale for the surface plot
     10 fig = go.Figure()                                                               # this creates the figure object

File <lambdifygenerated-1>:2, in _lambdifygenerated(u, v)
      1 def _lambdifygenerated(u, v):
----> 2     return -sqrt(-u**2 - v**2 + 1)

File ~/opt/anaconda3/lib/python3.9/site-packages/sympy/functions/elementary/miscellaneous.py:154, in sqrt(arg, evaluate)
     70 """Returns the principal square root.
...
        0.5197939 ],
       [0.50999898, 0.51999796, 0.52979288, ..., 0.52979288, 0.51999796,
        0.50999898],
       [0.5       , 0.50999898, 0.5197939 , ..., 0.5197939 , 0.50999898,
        0.5       ]])

You can finde an image of the error here

Anyone knows why this happens and/or how to fix it and make it work? Thank you in advance!!!

PS: number lines in the error message do not match with the lines of code posted here since my actual code has more lines but they are not relevant for the question.

Asked By: juan zaragoza

||

Answers:

The problem is this line:

surface = sym.lambdify([u,v], surface_expr, modules = ['sympy']) 

here, you have created a lambda function that will be evaluated by SymPy. Then, with zplot = surface(uplot,vplot) you are passing in Numpy arrays, but SymPy doesn’t know what to do with them.

Instead, you should create a lambda function that will be evaluated with Numpy/Scipy:

surface = sym.lambdify([u,v], surface_expr) 

Now, everything will work as expected.

EDIT: if you want to create plots of symbolic expressions with Plotly, I suggest to take a look at this module, SymPy Plot Backends. Then, you can simply write:

from spb import *
plot3d(surface_expr, (u, -0.5, 0.5), (v, -0.5, 0.5), backend=PB, use_cm=True)
Answered By: Davide_sd