On Nov 26, 2007 5:15 AM, William Stein <[EMAIL PROTECTED]> wrote: > > On Nov 25, 2007 6:33 PM, David Roe <[EMAIL PROTECTED]> wrote: > > Addition not commuting there bothers me. I can see why it's happening: a > > SymPy object doesn't call into the coercion system. One possible solution > > is to have coercion map sage objects into sympy, so both s+o and o+s (in > > line 134 and 135 of test_sympy.py) would be SymPy objects. Is SymPy and the > > SymbolicRing canonically isomorphic? Can every SymbolicRing element be cast > > into SymPy? > > I don't think so, since probably sage/maxima have special functions > sympy doesn't. And even if it could be, the functions provided by > SymPy are different > than the ones provided by SymbolicRing. > > If sympy('x') + x and x + sympy('x') are totally different in Sage I > will be unhappy about > that. Either the result has to always be in SymPy or always in Sage > or we have to get > an error and request that the user explicitly do a coercion. > > We have to decide on a canonical map in exactly one direction, and I prefer > > SymPy ---> SymbolicRing, > > just because SymbolicRing is more native in Sage, and probably could be > improved > so it would support any SymPy expression (yes -- I know this isn't > true now, unfortunately).
David Roe: > I would prefer that direction too. In order to make that happen, the SymPy > __add__ function has to recognize a sage element and call its __add__ method > instead. This sounds like it should be doable. I am not sure it's a clean solution. Ideally, neither SAGE nor SymPy should know about each other - of course both of them need to implement the _sage_ and _sympy_ methods (that of course need to know about the other), but that should be it. Then you could plug any other library in SAGE, not just SymPy and it will work. If you look at the patch above: 373 elif isinstance(x, sympy.Basic): 374 #elif hasattr(x, "_sage_"): 375 # if "x" implements the _sage_() method, let's use it to convert 376 # the expression to a SAGE expression (for example SymPy provides 377 # _sage_() methods, some other libraries can too) 378 # 379 # unfortunately, the hasattr() above doesn't work (infinite 380 # recursion), so we check for SymPy directly. 381 382 return self(x._sage_()) It should work just by checking for the _sage_ method, not trying if it is a SymPy object. Currently it doesn't, I get an infinite recursion, so it's commented out (but I consider this a bug). as to sympy('x') + SR(x) and SR(x) + sympy('x'): it can be more complicated, like this: SR(x) + SR(y) + sympy(x) and sympy(x)+sympy(y)+SR(x) so you propose, that whenever there is some SAGE expression inside the sympy expression, the result should be a SAGE expression? That seems reasonable, but how about this: sympy.sin(SR(x)) should it be a SAGE expression? How about sympy functions that are not in SAGE/Maxima? This assumes that anything in SymPy can be converted to SAGE, but that's not true, for example the real spherical harmonics (there only seem to be complex harmonics in Maxima [1]), lucas numbers, harmonic numbers, dirichlet eta function and any other function, that the user creates himself, see [2] how to do it - he just provides a simple class and then it works inside the SymPy calculus natively. So I think the user would like to accept SAGE expression inside his class and use it (if sympy supports all the functions that are in the SAGE expression). With the current behaviour, this will be possible. One option would be to leave the current behaviour but redefine commutative operations in SymPy to return SAGE expression if possible, but I don't think it's a very clean solution either. BTW, this can be done for example by patching the SymPy classes on the fly, or by some other technique, so definitely there are technical means how to do it. So I think for now, we should just convert to that expression, that started the statement. i.e sympy(x)+SR(x) will convert to sympy and SR(x)+sympy(x) will convert to SAGE. The user can always use SR() and sympify() to convert to SAGE/SymPy explicitely. So we start with the current behavior, which is imho a progress from the old behavior, and then improve it iteratively. > Now that I read through #1189 patch, I'm uncomfortable with > > return _verify_canonical_coercion_c(x,y) > > The function _verify_canonical_coercion_c is supposed to be like > > assert(parent(x) is parent(y)) > > it's *never* supposed to be called when the parents are different -- if it is, > that means there is a bug. However, you're using it to test whether the > parents are different, and if so do some other behavior (i.e., eventually > raise > a TypeError). So that makes me nervous. It would be better to just > directly do a call to the have_same_parent function, like in the > implementation > of _verify_canonical_coercion_c in coerce.pxi. > > In summary, the way the code is written now will work fine now, but seems > a little abusive. I think that code is just asking for troubles, but I didn't know how to do it better. So you propose to do just this? 330 if PY_TYPE_CHECK(xp, type) or PY_TYPE_CHECK(yp, type): 331 if hasattr(x, "_sage_") and hasattr(y, "_sage_") and have_same_parent(x,y) : 332 x = x._sage_() 333 y = y._sage_() 335 return _verify_canonical_coercion_c(x,y) (The exception TypeError will be raised just a line later.) Ondrej [1] http://maxima.sourceforge.net/docs/manual/en/maxima_65.html [2] http://code.google.com/p/sympy/wiki/SymPySvn --~--~---------~--~----~------------~-------~--~----~ 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/ -~----------~----~----~----~------~----~------~--~---