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/
-~----------~----~----~----~------~----~------~--~---

Reply via email to