Search code examples
pythonsympysymbolic-math

Find root of derivative of absolute value of complex number in sympy


In essence what I want to do is take the absolute value of a complex number that has a parameter both in real and imaginary parts and derive that in respect to that parameter. I then want to know for which value of that parameter the derivative is zero. So essentially I want to know Min/Max of the absolute value of a complex number with parameters.

I've encountered a problem in using sympy and don't quite know how to fix it/if its a problem at their end. Before I report it as bug I wanted to ask here. Ok so this is essentially what I want to do (the implementation is a bit more complex but the errors are the same)

0 import sympy
1 import mpmath
2 sympy.init_printing() # enable pretty printing
3 a,b = sympy.symbols("a,b") # a and b are symbols a and b
4 c = a+ 1j*b # complex number a+ib
5 d = sympy.Abs(c) # absolute value of c
6 e = d.diff(b,1) # derive d in respect to b one time
7 f = sympy.lambdify(b,e) # lambdify e with b as parameter
8 g = mpmath.findroot(f,0) # find root of f starting at 0

The error occurs in line 8 but because of f. Calling f with f(1) for example yields the same error. The error is:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <lambda>
NameError: name 'Derivative' is not defined

I got the whole thing working but only if I wrote methods for stuff like the absolute value myself and avoided using the sympy functions. So for example

d = (sympy.re(c)**2 + sympy.im(c)**2)**0.5

worked fine but

d = sympy.sqrt(sympy.re(c)**2 + sympy.im(c)**2)

gave me an Error. That Error was essentially the same one as the one I describe next but with Sqrt in place of the Add. It would be fine with me writing those methods myself but since the function is dynamically built at runtime(It's an electrical engineering toolbox) it's not a possibility to simply plug the stuff in; I have to rely on sympy.

I also got a Error that was something along the lines of:

Add doesn't contain Derivative Attribute.

which essentially meant that the complex number is an instance of the Add class of sympy and that doesn't have an differentiation method, but I can't get that to reproduce as of now.

Printing e.subs(a,5).subs(b,1) also shows that it doesn't substitute a and b inside the Derivative().

Sorry that some things are a bit vague, I originally troubleshot the whole thing yesterday and forgot to save the code. If the whole thing is not an Error in Sympy but rather a mistake on my part I sincerly apologise and would love to get pointed in the direction of how it's done properly.

The whole thing is run under Anaconda 5.1.0 and debugged/managed in Visual Studio. In case you're interested in my exact implementation the project is hosted at https://github.com/SV-97/iphipy

The interesting files are Systems.py and Main.py


Solution

  • This is what the lines 3-4 should have been

    a, b = sympy.symbols("a, b", real=True) # a and b are REAL symbols a and b
    c = a + I*b   
    

    By default, a and b are allowed to be complex numbers, which makes the computation of Abs(a+I*b) messy, and the differentiation of that with respect to b mathematically dubious.

    Also, 1j is a Python float, while I is a SymPy object; use the latter in symbolic expressions.

    Now e will be computed as b/sqrt(a**2 + b**2). But there is nothing that mpmath.findroot can do with this expression, given that it contains a symbol a, and mpmath.findroot is a numeric solver.

    sympy.solve(e, b) does return an answer, [0]. Of course you may need a numeric solver in more complicated situations; but then make sure that everything except for the variable(s) being solved for has a numeric value.