I'm digging into SymPy's code generation capabilities and am struggling with a few basic things. Ironically, of all the languages that SymPy supports for code generation, the documentation for python code generation seems to be the most minimal/lacking. I would like to use numpy as np as the default for all math functions in the code conversion but am struggling. Looking at the source code (since it is not documented), it looks like you can input a settings dict that has a user_functions field which maps SymPy functions to custom functions. I have a basic example below:
import sympy as sp
from sympy.printing.pycode import PythonCodePrinter
class MyPrinter(PythonCodePrinter):
def __init__(self):
super().__init__({'user_functions':{'cos':'np.cos', 'sin':'np.sin', 'sqrt':'np.sqrt'}})
x = sp.symbols('x')
expr = sp.sqrt(x) + sp.cos(x)
mpr = MyPrinter()
mpr.doprint(expr)
This produces the following output:
'math.sqrt(x) + np.cos(x)'
You can see that the mapping worked correctly for cos but not for sqrt.
- Why am I getting this behavior?
- Is there a better way to do this than to manually specify numpy funcs for every function I want to use?
There exists a
sympy.printing.numpy.NumPyPrinterclass that usesnumpyfunctions instead ofmathfunctions. The docstring for its__init__says:but the method doesn't take a
moduleargument. Moreover, the name of the module is hardcoded asnumpyin the source code. Also, the lines that define the known functions and constants in the numpy module use a hardcoded'numpy.'to create the values for the_kcand_kfdictionaries, although there exist separate classesCuPyPrinterandJAXPrinterthat define their own_module,_kf, and_kcvariablesIMO the simplest way would be to extend the
NumPyPrinterclass so that it takes amoduleargument and uses it to create its_kfand_kcdictionaries, which are then used by the original__init__to create theknown_functionsandknown_constantsdictionaries:Now, using this printer to print your expression gives the expected output:
np.sqrt(x) + np.cos(x)