Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List of inconsistency with sympy #400

Open
nkanazawa1989 opened this issue Apr 18, 2022 · 5 comments
Open

List of inconsistency with sympy #400

nkanazawa1989 opened this issue Apr 18, 2022 · 5 comments

Comments

@nkanazawa1989
Copy link

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).

@isuruf
Copy link
Member

isuruf commented Apr 18, 2022

  1. Easiest option here is to define ITE as a python function that returns a piecewise. Other option is to implement in C++
  2. sym.Lambdify works instead of sym.lambdify there. @bjodah I can't remember the details. Do you remember why?
  3. That's something we can fix here.
  4. Should be easy to implement __and__ at

@bjodah
Copy link
Contributor

bjodah commented Apr 18, 2022

I seem to recall ambiguities when broadcasting, but I'm not sure, perhaps it could be implemented without too much work.

@isuruf
Copy link
Member

isuruf commented Apr 18, 2022

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?

@nkanazawa1989
Copy link
Author

nkanazawa1989 commented Apr 19, 2022

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

@wshanks
Copy link

wshanks commented Apr 21, 2022

#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants