symengine.py icon indicating copy to clipboard operation
symengine.py copied to clipboard

Complex value support for Piecewise and comparison operators

Open nkanazawa1989 opened this issue 3 years ago • 7 comments

I want to lambdify the following piecewise function

import symengine as sym

amp, t, duration = sym.symbols("amp, t, duration")
expr = amp * sym.Piecewise((1, t < duration), (0, sym.true))
lamb = sym.lambdify([amp, t, duration], [expr])

lamb(0.1 + 0.1j, 10, 50)  # expected to return 0.1 + 0.1j

but here I assume amp is a complex number. This raises TypeError.

TypeError                                 Traceback (most recent call last)
<ipython-input-10-0c9e71176b96> in <module>
----> 1 lamb(0.1 + 0.1j, 10, 50)

symengine_wrapper.pyx in symengine.lib.symengine_wrapper._Lambdify.__call__()

TypeError: can't convert complex to float

Setting real=False to lambdify doesn't work because both Piecewise and LessThan operator are not defined in complex_double (maybe complex_mpc.cpp ?) in symengine. Is there any workaround to call lamb with a complex number?

nkanazawa1989 avatar Jun 07 '22 01:06 nkanazawa1989

SymPy's lambdify uses numpy.greater which compares complex doubles by ignoring the imaginary part so that with sympy, lamb(0.1 + 0.1j, 10, 50 + 0j) still gives the expected return. I don't think it's a good idea to ignore the imaginary part.

We can implement LessThan operators for complex_double when the the real parts of the numbers are zero. What do you think @certik, @symengine/push-access?

isuruf avatar Jun 07 '22 02:06 isuruf

What types for amp, t and duration does the lambdified function allow? Could perhaps typing information be provided to lambdify?

rikardn avatar Jun 07 '22 06:06 rikardn

It has to be all double or all complex<double>

isuruf avatar Jun 07 '22 06:06 isuruf

Ok, then there might at least exist some workaround. t < duration could be changed to abs(t - duration) > 0 perhaps and then lamb(0.1 + 0.1j, 10+0j, 50+0j).

rikardn avatar Jun 07 '22 06:06 rikardn

I assumed float or integer for t and duration, but it would be great complex is also acceptable. abs(t - duration) > 0 makes sense to me.

nkanazawa1989 avatar Jun 07 '22 07:06 nkanazawa1989

t < duration could be changed to abs(t - duration) > 0 perhaps and then lamb(0.1 + 0.1j, 10+0j, 50+0j).

Temporaries are also complex<double>. So, we'll be comparing 10 + 0j > 0 + 0j. To do that, we'll have to check that the real part of both temporaries are zero.

Btw, abs(t-duration)>0 doesn't make sense to me. May be you meant Re(t-duration)>0?

isuruf avatar Jun 07 '22 13:06 isuruf

Any other thoughts @symengine/push-access ?

isuruf avatar Jun 27 '22 16:06 isuruf