I have very ugly symbolic functions on which I would like to do some operations, then lambdify them. Among others, I need to take the derivative of the conjugate. My issue: the derivative and the conjugate work separately, but when I try to lambdify the derivative of the conjugate, it throws me the following error:
PrintMethodNotImplementedError: Unsupported by <class 'sympy.printing.numpy.SciPyPrinter'>: <class 'sympy.core.function.Derivative'>
Set the printer option 'strict' to False in order to generate partially printed code.
Details + working/not working examples
Here is the basic function:
import sympy as sp
a, b = sp.symbols('a b')
def myfunction(x,y):
return x + 1j * y
myfunctionval = myfunction(a,b)
myfunction_lam = sp.lambdify((a,b), myfunctionval)
print(myfunction_lam(1,2))
>> (1+2j)
Here is the conjugate:
def myfunctionConjugate(x,y):
return sp.conjugate(x + 1j * y)
myfunctionConjugateval = myfunctionConjugate(a,b)
myfunctionConjugate_lam = sp.lambdify((a,b), myfunctionConjugateval)
print(myfunctionConjugate_lam(1,2))
>> (1-2j)
Here is the derivative:
def myfunctionDerivative(x,y):
return sp.diff(x + 1j * y, x)
myfunctionDerivativeval = myfunctionDerivative(a,b)
myfunctionDerivative_lam = sp.lambdify((a,b), myfunctionDerivativeval)
print(myfunctionDerivative_lam(1,2))
>> 1
Here is the conjugate of the derivative, which works:
def myfunctionDerivativeConjugate(x,y):
return sp.conjugate(sp.diff(x + 1j * y,x))
myfunctionDerivativeConjugateval = myfunctionDerivativeConjugate(a,b)
myfunctionDerivativeConjugate_lam = sp.lambdify((a,b), myfunctionDerivativeConjugateval)
print(myfunctionDerivativeConjugate_lam(1,2))
>> 1
Here is the derivative of the conjugate, which DOESNT work:
def myfunctionConjugateDerivative(x,y):
return sp.diff(sp.conjugate(x + 1j * y),x)
myfunctionConjugateDerivativeval = myfunctionConjugateDerivative(a,b)
myfunctionConjugateDerivative_lam = sp.lambdify((a,b), myfunctionConjugateDerivativeval)
myfunctionConjugateDerivative_lam(1,2)
And throws me this error :
---------------------------------------------------------------------------
PrintMethodNotImplementedError Traceback (most recent call last)
/tmp/ipykernel_13914/1657192206.py in <module>
3
4 myfunctionConjugateDerivativeval = myfunctionConjugateDerivative(a,b)
----> 5 myfunctionConjugateDerivative_lam = sp.lambdify((a,b), myfunctionConjugateDerivativeval)
6 myfunctionConjugateDerivative_lam(1,2)
~/anaconda3/lib/python3.9/site-packages/sympy/utilities/lambdify.py in lambdify(args, expr, modules, printer, use_imps, dummify, cse, docstring_limit)
878 else:
879 cses, _expr = (), expr
--> 880 funcstr = funcprinter.doprint(funcname, iterable_args, _expr, cses=cses)
881
882 # Collect the module imports from the code printers.
~/anaconda3/lib/python3.9/site-packages/sympy/utilities/lambdify.py in doprint(self, funcname, args, expr, cses)
1169 funcbody.append('{} = {}'.format(self._exprrepr(s), self._exprrepr(e)))
1170
-> 1171 str_expr = _recursive_to_string(self._exprrepr, expr)
1172
1173 if '\n' in str_expr:
~/anaconda3/lib/python3.9/site-packages/sympy/utilities/lambdify.py in _recursive_to_string(doprint, arg)
964
965 if isinstance(arg, (Basic, MatrixBase)):
--> 966 return doprint(arg)
967 elif iterable(arg):
968 if isinstance(arg, list):
~/anaconda3/lib/python3.9/site-packages/sympy/printing/codeprinter.py in doprint(self, expr, assign_to)
170 self._number_symbols = set()
171
--> 172 lines = self._print(expr).splitlines()
173
174 # format the output
~/anaconda3/lib/python3.9/site-packages/sympy/printing/printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~/anaconda3/lib/python3.9/site-packages/sympy/printing/codeprinter.py in _print_not_supported(self, expr)
580 def _print_not_supported(self, expr):
581 if self._settings.get('strict', False):
--> 582 raise PrintMethodNotImplementedError("Unsupported by %s: %s" % (str(type(self)), str(type(expr))) + \
583 "\nSet the printer option 'strict' to False in order to generate partially printed code.")
584 try:
PrintMethodNotImplementedError: Unsupported by <class 'sympy.printing.numpy.SciPyPrinter'>: <class 'sympy.core.function.Derivative'>
Set the printer option 'strict' to False in order to generate partially printed code.
That occurs when you are trying to generate code (lambdify — the print
referred here is the printing of code) with some unsolved derivative in it (that is, once simplification and cse has done their job, there are still derivative in the result)
In your case, this occurs, because conjugate of a+ib
is conjugate(a) - 1.0*I*conjugate(b)
. And derivative of that (for example of conjugate of a) is not computable, without any information on a trajectory.
(It is different from "conjugate of derivative", because derivative of a+ib
is just 1, what ever a
trajectory. So, derivative is replaced by a very computable 1
, while dz¯/dz is not)
So, not saying that this is perfectly normal (it should raise another error that one that seems an internal one). But you asked for an impossible task.
But the more profound reason for that, is probably (I am surmising here) that you decided to explicitly make your functions parameters a+ib
, to explicitly represent real and imaginary parts. So, your intents, I guess, was that a
and b
are reals (and a+ib
is complex). So that conjugate(a+ib) is just (a-ib), and its derivative (with a) is also 1 (note that, if a+ib is a complex, and you compute derivative of f(a+ib) with respect to a, then, you fix a "trajectory" (you approach a+ib horizontally); so this is really not the same as computing derivative of f(z) with respect to z, or f(a+ib) with respect to a+ib. Which you are doing — I think involuntary, because not being aware that your a
and b
are also complex, with their own imaginary parts, as you wrote them).
So, said otherwise, if I surmise correctly, and your intents were to have a+ib
a complex made of a real part (a) and an imaginary part (b), then you should have said that.
Short solution if so: create your symbols with
a, b = sp.symbols('a b', real=True)
And then, everything works.
(again, I am not 100% sure this is you want, since it is then an easier problem. On another hand, without specifying that a and b are real, the problem is not just harder, but impossible)