Every input in the sympy-live shell is processed using int_to_Integer (converts Python int to sympy Integers) because this makes it much nicer. Not sure but maybe some of the example in the docs also assume this behaviour.
While trying to understand some bugs in sympy-live related to numpy-lambdification, I was able to isolate the following bug that appears to exist in sympy (1.1 and 1.1.1rc1).
To reproduce, pip install sympy numpy then run
import numpy
import sympy
sympy.init_session(auto_int_to_Integer=True)
print 'using sympy', sympy.__version__, 'and numpy', numpy.__version__
wait a second then run
x = sympy.symbols('x')
expr = sympy.sin(x)
f = sympy.lambdify(x, expr, "numpy")
a = 3
print( f(3) )
This results in
using sympy 1.1 and numpy 1.13.1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-a8c650daaf7d> in <module>()
3 f =sympy .lambdify (x ,expr ,"numpy")
4 a =Integer (3 )
----> 5 print (f (Integer (3 )))
/int_to_Int_lambdify_bug/venv/lib/python2.7/site-packages/sympy/utilities/lambdify.pyc in wrapper(*argsx, **kwargsx)
439 @wraps(funcarg)
440 def wrapper(*argsx, **kwargsx):
--> 441 return funcarg(*[namespace['asarray'](i) for i in argsx], **kwargsx)
442 return wrapper
443 func = array_wrap(func)
/int_to_Int_lambdify_bug/venv/lib/python2.7/site-packages/numpy/__init__.pyc in <lambda>(_Dummy_140)
AttributeError: 'Integer' object has no attribute 'sin'
I saw there is some work on lambdify-related work in 1.1.1 so I tried that too using
pip install git+git://github.com/sympy/[email protected]#egg=sympy
and running the same code as above produced
using sympy 1.1.1rc1 and numpy 1.13.1
In [2]: x = sympy.symbols('x')
...: expr = sympy.sin(x)
...: f = sympy.lambdify(x, expr, "numpy")
...: a = 3
...: print( f(3) )
...:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-a8c650daaf7d> in <module>()
3 f =sympy .lambdify (x ,expr ,"numpy")
4 a =Integer (3 )
----> 5 print (f (Integer (3 )))
/int_to_Int_lambdify_bug/venv/lib/python2.7/site-packages/sympy/utilities/lambdify.pyc in wrapper(*argsx, **kwargsx)
442 newargs = [asarray(i) if isinstance(i, integer_types + (float,
443 complex)) else i for i in argsx]
--> 444 return funcarg(*newargs, **kwargsx)
445 return wrapper
446 func = array_wrap(func)
/int_to_Int_lambdify_bug/venv/lib/python2.7/site-packages/numpy/__init__.pyc in <lambda>(_Dummy_140)
AttributeError: 'Integer' object has no attribute 'sin'
It's because SymPy objects do not work in NumPy functions, and auto_int_to_Integer causes the f(3) to become f(Integer(3)) (here, f is essentially the same as np.sin).
Probably the most correct fix would be to modify the int -> Integer translation so that it only applies to int/int division. In other words, instead of wrapping integer literals with Integer, replace int/int division with a call to Rational. That would avoid issues where ints are used in other scenarios where Integer doesn't work.
So instead of
>>> int_to_Integer('1.2 + 1/2 - 0x12 + a1')
'1.2 +Integer (1 )/Integer (2 )-Integer (0x12 )+a1 '
we'll have
>>> int_to_Integer('1.2 + 1/2 - 0x12 + a1')
'1.2 + Rational(5, 2) - 0x12 + a1 '
this makes a lot of sense...
The code looks quite readable, so I'll try to implement that.
Would this break anything else? I never used auto_int_to_Integer=True on the command line, and it seems like it's just a minor convnience so this API change shouldn't impact too many people.
The whole point of it is to avoid the gotcha of 1/2 = 0.5 instead of Rational(1, 2). Python ints don't lose any information for any other operation, so they can be used instead of Integer.
The code looks quite readable, so I'll try to implement that.
I would suggest you to use ast transformations instead, as I did in the diofant. See linked pr.
Wrapping integer divisions would fail, when integer operation is in dividend or divisor, e.g., 2**3/7 and (3+5)/7, which is more common cases.
@ylemkimon, good catch, more deep tests for arguments of ast.Div required in such cases.