List of inconsistency with sympy
I found several syntactic inconsistency with SymPy. Sorry I was bit lazy to write separate issues.
- symengine 0.9.2
- macOS Monterey 12.3.1 (Intel)
1. Missing ITE syntax
(In sympy)
from sympy import ITE
It works.
(In symengine)
from symengine import ITE
ImportError: cannot import name 'ITE' from 'symengine'
Alternative solution
Use Piecewise, e.g.
if flag1 is True:
return 1
else:
return 2
can be translated into
symengine.Piecewise((1, flag1 == symengine.true), (2, symengine.true))
however
sympy.ITE(flag1, 1, 2)
looks more intuitive to me.
2. Lambdify with a single function
(In sympy)
import sympy as sym
t, a, b = sym.symbols("t, a, b")
f = a * t + b
lamb_f = sym.lambdify([t, a, b], f)
It works
(In symengine)
import symengine as sym
t, a, b = sym.symbols("t, a, b")
f = a * t + b
lamb_f = sym.lambdify([t, a, b], f)
TypeError: Value after * must be an iterable, not Add
Alternative solution
Call lamdify with sym.lambdify([t, a, b], [f]), but this looks bit cumbersome (and result is always a list).
3. Evaluate lambda function with inhomogeneous-shape arguments
(In sympy)
import numpy as np
import sympy as sym
t, a, b = sym.symbols("t, a, b")
f = a * t + b
lamb_f = sym.lambdify([t, a, b], f)
t = np.linspace(0, 1, 10)
lamb_f(t, 1, 0.2)
array([0.2 , 0.31111111, 0.42222222, 0.53333333, 0.64444444, 0.75555556, 0.86666667, 0.97777778, 1.08888889, 1.2 ])
(In symengine)
import numpy as np
import symengine as sym
t, a, b = sym.symbols("t, a, b")
f = a * t + b
lamb_f = sym.lambdify([t, a, b], [f])
t = np.linspace(0, 1, 10)
lamb_f(t, 1, 0.2)
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part.
Alternative solution
No. We need to repeatedly call lamb_f which is heavy overhead with python (probably I just don't know another solution).
4. Inconsistent logical operation
(In sympy)
import sympy as sym
a = sym.Symbol("a")
expr = (0 < a) & (a < 1)
It works (preferably we should be able to write 0 < a < 1 in sympy but this raises TypeError: cannot determine truth value of Relational, anyways this is not the issue for symengine).
(In symengine)
import symengine as sym
a = sym.Symbol("a")
expr = (0 < a) & (a < 1)
expr
TypeError: unsupported operand type(s) for &: 'StrictLessThan' and 'StrictLessThan'
Alternative solution
Interestingly, if we write
import symengine as sym
a = sym.Symbol("a")
expr = 0 < a < 1
this omits the first condition, i.e. a < 1. This returns unexpected value when a is negative value.
expr.subs(a, -1)
True
This should be False. Likely it's a bug. It returns the same expression when I write (0 < a) and (a < 1).
- Easiest option here is to define
ITEas a python function that returns a piecewise. Other option is to implement in C++ sym.Lambdifyworks instead ofsym.lambdifythere. @bjodah I can't remember the details. Do you remember why?- That's something we can fix here.
- Should be easy to implement
__and__at https://github.com/symengine/symengine.py/blob/2ae44220caf26ea529463304d6364a1b741bd503/symengine/lib/symengine_wrapper.pyx#L1525
I seem to recall ambiguities when broadcasting, but I'm not sure, perhaps it could be implemented without too much work.
expr = (0 < a) & (a < 1)
& is a bitwise operator and and is the logical operator. However, there's no way to override and in python.
Therefore sympy uses & which I think is a mistake.
Can you use sym.And(0< a, a < 1) which is unambiguous?
Thanks @isuruf I confirmed sym.And is sympy compatible. Seems like this is correct syntax.
import sympy as sym
a = sym.Symbol("a")
expr = sym.And(a < 1, 0 < a)
expr.subs(a, -1)
False
import symengine as sym
a = sym.Symbol("a")
expr = sym.And(a < 1, 0 < a)
expr.subs(a, -1)
False
https://github.com/symengine/symengine.py/issues/396 was another inconsistency along the lines of item 2. I closed that one after isuruf showed the syntax that worked. I wasn't sure how faithfully symengine is supposed to mirror the sympy API.