On 8/11/07, Ondrej Certik <[EMAIL PROTECTED]> wrote: > > This is already fixed in the svn for some time, see the relevant issue > for details: > > http://code.google.com/p/sympy/issues/detail?id=247 > > when we release the 0.5.0 soon, it will be included. > > Note: all released versions use the old core, which was slow. The svn > version uses a new core, that is very fast, but it was a lot of work > to fix everything so that everything that used to work still works. > There are still some minor issues, that's why we didn't release for a > long time.
OK, I'll check it out. I'm looking forward to the new release. > > Some reasons this sort of minimal preparsing is done in SAGE include: > > 1. As soon as integers get at all large (bigger than three machine words, > > say), SAGE's GMP-based integer type is much faster than Python's builtin > > arbitrary precision integer type. > > Definitely, neither SAGE or SymPy should use Python ints (or floats), > because they are slow. In sympy/numerics (svn version), we have a > faster implementation of floats (in pure Python) that are much faster > than Python's Decimal, but it's not yet integrated in the core. SAGE uses mpfr for arbitrary precision reals and GMP for arbitrary precision integers and rationals. This is -- of course -- not the way to go for sympy, because of its design goals. Perhaps whatever you're doing with arbitrary precision reals might make it back into standard Python someday. > > 2. We want the following to behave different than in Python, to avoid > > lots > > of confusion to mathematicians: > > sage: 1/3 > > 1/3 > > sage: 2^3 > > 8 > > versus > > >>> 1/3 > > 0 > > >>> 2^3 > > 1 > > This paragraph is just my own opinion: > > For me, this is more confusing. The power of Python is, that it is a > standardised language that one can learn on many places on the web. [...] My only remark is that the vast majority of SAGE users prefer having the mild preparsing as a convenience. Those that don't certainly don't have to use it. There are numerous ways to turn off using the preparser, Some other remarks: (1) The preparser is essentially irrelevant to most of the SAGE Python library, since that library is implemented in 100% standard Python (and Cython), (2) If one creates a file foo.sage that contains code meant to run through the preparser, then run it, e.g., by typing "sage foo.sage", then a file foo.py is created, which contains the preparsed version of foo.sage, which can then safely be used as standard Python code. > It's a great language, but it has some drawbacks (your examples > above). However, those drawbacks are well-known. By preparsing, you > are in fact creating a new language incompatible with Python and thus > it is very confusing. (I am not against sending a patch to python-dev They are well known to Python programers, not to most users of SAGE (in my experience most first-time SAGE users have never touched Python before). For Sympy, on the other hand, the target audience is Python programmers, so again for them preparsing probably isn't relevant. > Imagine for example that I write some code using 1/3, or 2^3 > (expecting 1/3 and 8 respectively), then I will not be able to run it > in Python and thus will get stuck in SAGE environment, which is (I > think) bad. It is always very easy in SAGE to go from what you would type in SAGE to what you would type in the standard Python environment, as I mentioned above. Also, at the command line in SAGE you can type preparse('...') and the input string is preparsed and the preparsed version is displayed: sage: preparse('2^3') 'Integer(2)**Integer(3)' If SAGE users had to type sage: Integer(2) ** Integer(3) Just to compute 8 using SAGE integers, the experience of using SAGE would simply by far too cumbersome. >So for SymPy, preparsing is unacceptable, for SAGE, since > it wants to be an environment and replacement for Maple/Mathematica, > maybe it makes sense, but still it is confusing to me. Sympy is a library, so preparsing doesn't make sense. SAGE is both a library and an environment, and preparsing is something that happens only for the SAGE environment, not the library. > > This brings me to the example above. The SAGE Integer type > > is not a builtin Python numeric type, and it doesn't derive from > > Sympy's "basic" class. Thus Sympy just gives up on it for > > arithmetic. This is very bad for me. Would you consider, e.g., > > Agree, we already fixed that. If it flies like a duck and looks like a > duck, it's a duck. So if it behaves like an Int..., it's an Int. > > > calling a method to convert an arbitrary object to a Sympy object > > instead of giving up with an error. For example, before raising > > ValueError here: > > 528 if not isinstance(a,Basic): > > --> 529 raise ValueError("%s must be a subclass of > > basic" % str(a)) > > 530 return a > > > > you could instead check for an _sympy_ method, and if it is > > there call that. Then I could add a method like this to my Integer > > class (and likewise for many other SAGE classes), and SAGE and > > Sympy would then work well together again: > > > > def _sympy_(self): > > return something sympy is happy to work with. > > _sympy_ could be implemented in SAGE to return SymPy expression, the > same way like _maxima_ works. But as I said above, the general Python > philosophy is not to check for int, but rather try to use it like int. > Thus what we do, is that we try to convert the expression to string > (which both Python and SAGE ints can do) and then we parse the string > to SymPy expression. I do not like that as the only choice. Some issues: (1) String conversions can be very slow. Already converting a number with just over 100000 digits in Python to a string and back takes a very long time: In [1]: a = 13 ** 100000 In [2]: time b=eval(str(a)) CPU times: user 5.61 s, sys: 0.04 s, total: 5.65 s Wall time: 8.27 In [3]: len(str(a)) Out[3]: 111395 For comparison, converting the same SAGE integer to a Python integer is quite fast: In [1]: from sage.all import Integer In [2]: a = Integer(13) ** Integer(100000) In [3]: time b = int(a) CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.00 In [4]: time c = Integer(b) CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s Wall time: 0.00 It would be much better if you only use strings after checking for a _sympy_ method. (2) What about rational numbers or expressions that involve rationals? E.g., In [11]: from sage.all import Rational In [12]: a = Rational( (1, 3) ) In [13]: a Out[13]: 1/3 In [14]: eval(str(a)) Out[14]: 0 Using strings and eval'ing in Sympy will result in seriously incorrect results, because you don't use any sort of preparsing, and SAGE prints the rational number 1/3 as "1/3", which is reasonable for SAGE. If there were the possibility of a _sympy_ method to do the convertion, I could implement it to return In [17]: sympy.Rational(1,3) Out[17]: 1/3 Ahh, notice that even sympy's own rationals will break under the str --> eval conversion procedure. So, in fact, I would prefer that you do not have the string conversions at all. Best would be to raise an error and offer the user the chance to define _sympy_. The problem is that if a user defines some sort of objects that print with something like "1/3" in them, and you eval their string representation, a subtle bug will result. In SAGE, there are cases where evaling the print representation is the default way to do conversions -- but we always eval after preparsing, so it generally works with other CAS's. > However, for more general conversion of complex expressions, the > _sympy_() method is probably needed. > > > The same approach could also work for symbolic calculus expressions -- in > > SAGE > > one can input very complicated formal symbolic expressions, and if they had > > a _sympy_ method, it would be easy to use them with Sympy functions. > > > > What do you think? > > Sounds good. Also we can implement something in SymPy to help > converting back from SymPy to SAGE. For example _sage_ method, that > would return a SAGE expression (it would try to import SAGE at runtime > in the method _sage_, so that SymPy is not depending on anything else > besides Python). A way to deal with this might be for me to create a SAGE parent object (SympyRing) that contains all Sympy expressions, and a SAGE extension class whose elements are a pointer to an instance of that parent object and a pointer to an actual sympy expression. This will, of course, still require the existence of an _sage_ method like you suggest above. It might make sense to wait on this for a while. > Or maybe, since both SAGE and SymPy should be able to parse strings, > the _sympy_ and _sage_ methods can just return a string, and then it > will get parsed. That is probably the easiest and most clean solution > (maybe not the fastest). I would like to avoid this if possible. William --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/ -~----------~----~----~----~------~----~------~--~---