Corram
Corram

Reputation: 305

Plotting sympy.Max yields TypeError

I am trying to generate a 3-dimensional plot for a function involving sympy.Max, but I am getting a type-error. Minimum example:

import sympy

u, v = sympy.symbols("u v", positive=True)
f = sympy.Max(0, u*v - 0.5)
my_plot = sympy.plotting.plot3d(f, (u, 0, 1), (v, 0, 1), show=False, legend=True)
my_plot.show()

The code runs fine if I remove the -0.5 for example, so it really seems to be about taking the maximum. Any ideas how to fix this?

Full stack trace:

Traceback (most recent call last):
  File "/Users/marcusrockel/Documents/projects/copulas_in_systemic_risk/venv/lib/python3.9/site-packages/sympy/plotting/experimental_lambdify.py", line 131, in __call__
    results = self.vector_func(*temp_args)
  File "/Users/marcusrockel/Documents/projects/copulas_in_systemic_risk/venv/lib/python3.9/site-packages/sympy/plotting/experimental_lambdify.py", line 272, in __call__
    return self.lambda_func(*args, **kwargs)
  File "<string>", line 1, in <lambda>
  File "<__array_function__ internals>", line 180, in amax
  File "/Users/marcusrockel/Documents/projects/copulas_in_systemic_risk/venv/lib/python3.9/site-packages/numpy/core/fromnumeric.py", line 2793, in amax
    return _wrapreduction(a, np.maximum, 'max', axis, None, out,
  File "/Users/marcusrockel/Documents/projects/copulas_in_systemic_risk/venv/lib/python3.9/site-packages/numpy/core/fromnumeric.py", line 86, in _wrapreduction
    return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
TypeError: only integer scalar arrays can be converted to a scalar index

I am using Python 3.9 and sympy 1.11.1.

Upvotes: 0

Views: 75

Answers (1)

Davide_sd
Davide_sd

Reputation: 13185

That's unfortunate: it is a limitation of the current plotting module, which is using experimental_lambdify which is quite old.

Two solutions:

  1. you lambdify your expression, and manually plot it with matplotlib.
from sympy import *
import numpy as np
import matplotlib.pyplot as plt

u, v = symbols("u v", positive=True)
expr = Max(0, u*v - 0.5)
f = np.vectorize(lambdify([u, v], expr))
uu, vv = np.mgrid[0:1:50j, 0:1:50j]
zz = f(uu, vv)

fig = plt.figure()
ax = fig.add_subplot(projection="3d")
ax.plot_surface(uu, vv, zz)
ax.set_xlabel("u")
ax.set_ylabel("v")
plt.show()

enter image description here

  1. take a look at this plotting module, which uses lambdify and it is able to plot it:
from sympy import *
from spb import *
u, v = symbols("u v", positive=True)
expr = Max(0, u*v - 0.5)
plot3d(expr, (u, 0, 1), (v, 0, 1))

Upvotes: 1

Related Questions