generic arithmetic in python and sage

55 views
Skip to first unread message

Gary Bunting

unread,
Apr 16, 2007, 12:11:16 PM4/16/07
to sage-support
I have been trying to use some of my python code in sage but
have been having problems, apparently because sage implements
generic arithmetic differently to python.

Here is a simple example:

class MyList(list):

def __rmul__(self, other):
return MyList([other*x for x in self])

Python:
>>> x = MyList([1,2,3])
>>> 10*x
[10, 20, 30]

Sage:

sage: x = MyList([1,2,3])
sage: 10*x
---------------------------------------------------------------------------
<type 'exceptions.TypeError'> Traceback (most recent call
last)

/home/gbunting/algebra/comp/python/sage/<ipython console> in
<module>()

/home/gbunting/algebra/comp/python/sage/element.pyx in
element.RingElement.__mul__()

/home/gbunting/algebra/comp/python/sage/element.pyx in
element.bin_op_c()

<type 'exceptions.TypeError'>: unsupported operand parent(s) for '*':
'Integer Ring' and '<class '__main__.MyList'>'


I have python code for that I use for experimenting with polynomials
and
differential operators and would like to use it from sage.

Cheers,
Gary

didier deshommes

unread,
Apr 16, 2007, 12:27:31 PM4/16/07
to sage-s...@googlegroups.com
On 4/16/07, Gary Bunting <gbun...@turing.une.edu.au> wrote:
>
> I have been trying to use some of my python code in sage but
> have been having problems, apparently because sage implements
> generic arithmetic differently to python.

Hi Gary,
The SAGE preparser is your problem. If you run the preparser on the
line you just typed, you'll notice that it is treated as
{{{
sage: preparse( 'MyList([1,2,3])')
'MyList([Integer(1),Integer(2),Integer(3)])'
}}}

So instead of working with normal int's, you're working with SAGE's.
If you want to work with normal int's you could:
* append an "r" ("r" stands for "raw") to each number (faster):
{{{
sage: x = MyList([1r,2r,3r])
sage: 10r*x
[10, 20, 30]
}}}

This is preparsed as:
{{{
sage: preparse(' MyList([1r,2r,3r])')
' MyList([1,2,3])'
}}}


* explicitly call the int() constructor on each number (slower):
{{{
sage: x = MyList([int(1),int(2),int(3)])

sage: int(10)*x
[10, 20, 30]
}}}

which is preparsed as:
{{{
sage: preparse(' MyList([int(1),int(2),int(3)])')
' MyList([int(Integer(1)),int(Integer(2)),int(Integer(3))])'
}}}


Hope that clarifies things for you,
didier

William Stein

unread,
Apr 16, 2007, 12:44:31 PM4/16/07
to sage-s...@googlegroups.com
On 4/16/07, Gary Bunting <gbun...@turing.une.edu.au> wrote:
>
> I have been trying to use some of my python code in sage but
> have been having problems, apparently because sage implements
> generic arithmetic differently to python.

SAGE implements its own integer class, which is better than
Python's in various ways. However, it has somewhat different
behavior. Your options (4 is the best but most complicated):

(1) Use Python integers instead of SAGE integers, at least
in an example like below. To make a Python integer literal,
just put r after it:


sage: x = MyList([1,2,3])

sage: 10r*x
[should work]
Alternatively, make the Python integer using int(10), though
that would be slower.

(2) It's possible we'll be able to come up with an extension to
how SAGE arithmetic works so thaty your example below works,
but you would have to wait a while.

(3) Use the SAGE libraries directly from Python. E.g.,
was@ubuntu:~$ sage -python
Python 2.5 (r25:51908, Feb 16 2007, 11:50:26)
[GCC 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from sage.all import *
>>> 2/3
0
>>> euler_phi(50)
20

(4) Make your class genuinely fit into the SAGE arithmetic
architecture. SAGE has a very sophisticated and thought
through "arithmetic architecture", which is much different
than Python's very naive (in the context of serious math)
approach. See the programming guide for more details.
The basic idea is that every element has a parent (container
ring of module) and there are canonical coercion rules.
Anyway, your example would be written this way (note that
you can't inherit from both ModuleElement and list):


{{{
from sage.structure.parent_base import ParentWithBase

class AllLists_class(ParentWithBase):
def __init__(self):
ParentWithBase.__init__(self, ZZ)

AllLists = AllLists_class()

class MyList(ModuleElement):
def __init__(self, v):
ModuleElement.__init__(self, AllLists)
self._list = list(v)

def _rmul_(self, other):
return MyList([other*x for x in self._list])

def _repr_(self):
return repr(self._list)
}}}

{{{
v = MyList([1,2,3])
}}}

{{{
2*v
///
[2, 4, 6]
}}}


--
William Stein
Associate Professor of Mathematics
University of Washington
http://www.williamstein.org

Reply all
Reply to author
Forward
0 new messages