Add new structures to Sage: Parent and Element

10 views
Skip to first unread message

Franco Saliola

unread,
Feb 12, 2008, 7:42:58 PM2/12/08
to sage-...@googlegroups.com
Hello.

I'm wondering if there is some documentation or a howto somewhere that
describes the process of adding new structures to Sage. For example,
we want to add poset functionality to Sage---Peter Jipsen and I began
working on this at Sage Days 7. So we created a Poset class that
inherits from ParentWithBase (because inheriting from Parent isn't
support if I want to have elements---something that should be fixed, I
guess), and a PosetElement class that inherits from the Element class.
If this is not correct, then someone should tell me now, and the
better way to do this.

Also, I have some technical questions.

1. Can someone describe to me how ParentWithBase works? Does each
instance of Element store the parent poset? I imagine this is not the
case as it would mean several copies of the Parent will be stored in
memory. So it's some kind of identifier for the poset?

2. My PosetElement class accepts two arguments: the Parent poset P and
a label for the poset element. The problem I am having here is that I
can create an instance of PosetElement with Parent poset P, but this
element won't belong to P (and it shouldn't). But then the parent
function returns P on this new element. Here is a psuedo-example:

sage: P = FinitePoset([0,1,2])
sage: y = PosetElement(P,3)
sage: parent(y) == P
True
sage: y in P
False

I'm probably messing something up with my class definitions. (I'm new
to OOProgramming and Sage.) I'm including a very basic implementation
of the classes below. Any suggestions?

Take care,
Franco

--

from sage.structure.element import Element

class FinitePoset(ParentWithBase):
def __init__(self,data=None):
Parent.__init__(self)
self.elements=[]
if not data is None:
for x in data:
self.elements.append(PosetElement(self,x))

def __contains__(self,x):
return x in self.elements

def list(self):
return self.elements

class PosetElement(Element):
def __init__(self,poset,label):
Element.__init__(self,poset)

--

David Roe

unread,
Feb 12, 2008, 10:50:33 PM2/12/08
to sage-...@googlegroups.com
So, these kinds of issues were the subject of the coercion project at SD7.  Robert Bradshaw, Mike Hansen, Bobby Moretti and I are currently in the process of changing a lot of the infrastructure behind parents, elements, etc.  If you want to help (or want to see our current progress) see the sprint page at http://wiki.sagemath.org/days7/coercion or contact one of us via e-mail.

Given that, I'll answer your questions, both as Sage exists now and as we see it existing in a few months.

I'm wondering if there is some documentation or a howto somewhere that
describes the process of adding new structures to Sage.
 
We're working on this.  See the wiki page I referenced above for the current progress.
 
For example,
we want to add poset functionality to Sage---Peter Jipsen and I began
working on this at Sage Days 7. So we created a Poset class that
inherits from ParentWithBase (because inheriting from Parent isn't
support if I want to have elements---something that should be fixed, I
guess),

Yup.  This will be one of the changes that we're making.  ParentWithBase and ParentWithGens are both disappearing, and both generator and base functionality is getting pushed up to CategoryObject (a superclass of parent) so that you can have objects with generators and bases but without elements.

For now you should probably inherit from ParentWithBase and have base = self.
 
and a PosetElement class that inherits from the Element class.

Yes, you should still be inheriting from Element.

If this is not correct, then someone should tell me now, and the
better way to do this.

Also, I have some technical questions.

1. Can someone describe to me how ParentWithBase works? Does each
instance of Element store the parent poset? I imagine this is not the
case as it would mean several copies of the Parent will be stored in
memory. So it's some kind of identifier for the poset?

This is the case, because elements need to know their parent.  Since Python objects are stored as pointers, this isn't a huge memory overhead.  But you can just treat it as storing the parent, and get access to it by calling self.parent().
 
2. My PosetElement class accepts two arguments: the Parent poset P and
a label for the poset element. The problem I am having here is that I
can create an instance of PosetElement with Parent poset P, but this
element won't belong to P (and it shouldn't). But then the parent
function returns P on this new element. Here is a psuedo-example:

sage: P = FinitePoset([0,1,2])
sage: y = PosetElement(P,3)
sage: parent(y) == P
True
sage: y in P
False
 
Your __init__ method on the element should check to see if the input it gets generates a valid element of the parent.  If it doesn't, raise a ValueError.

One generally doesn't expose the element class directly to the user.  Instead, the better behavior is to use the __call__ method on Parent and the write P(3).

I'm probably messing something up with my class definitions. (I'm new
to OOProgramming and Sage.) I'm including a very basic implementation
of the classes below. Any suggestions?

Take care,
Franco

--

from sage.structure.element import Element

class FinitePoset(ParentWithBase):
       def __init__(self,data=None):
               Parent.__init__(self)
               self.elements=[]
               if not data is None:
                       for x in data:
                               self.elements.append(PosetElement(self,x))
 
You can write "data is not None" if you want: Python has an "is not" operator.

       def __contains__(self,x):
               return x in self.elements

       def list(self):
               return self.elements

class PosetElement(Element):
       def __init__(self,poset,label):
               Element.__init__(self,poset)

This __init__ method should check that the label actually belongs to the parent.  You can have a parameter check, by default True, which is able to disable this checking.

Let me know if you have more questions.
And for those of you out there interested in coercion, I'll have my bundle posted as soon as I get a chance to tie off some loose ends.
David

Dan Drake

unread,
Feb 12, 2008, 11:51:37 PM2/12/08
to sage-...@googlegroups.com
On Tue, 12 Feb 2008 at 10:50PM -0500, David Roe wrote:
> So, these kinds of issues were the subject of the coercion project at
> SD7. Robert Bradshaw, Mike Hansen, Bobby Moretti and I are currently
> in the process of changing a lot of the infrastructure behind parents,
> elements, etc. If you want to help (or want to see our current
> progress) see the sprint page at
> http://wiki.sagemath.org/days7/coercion or contact one of us via
> e-mail.

This is something that interests me, although I don't know how much help
I can be. I'd like to add combinatorial classes for complete matchings
of [n] to Sage. Matchings are thought of in several different ways: as
set partitions with blocks of size 2, as fixed-point-free involutions
(permutations of order 2), and as matchings of the complete graph.

I would definitely like to mix these things, and add more. (In some
recent research, I found myself wanting to define a poset structure on
the edges of matchings.)

So I don't have any smart ideas, but perhaps this could be one data
point for how users want coercion/multiple inheritance to work.

Dan

--
--- Dan Drake <dr...@mathsci.kaist.ac.kr>
----- KAIST Department of Mathematical Sciences
------- http://math.kaist.ac.kr/~drake

signature.asc

Franco Saliola

unread,
Feb 13, 2008, 10:10:36 PM2/13/08
to sage-...@googlegroups.com
On Feb 12, 2008 10:50 PM, David Roe <roe...@gmail.com> wrote:

> So, these kinds of issues were the subject of the coercion project at SD7.

Yeah, I was at Sage Days 7, but I didn't realize that this is what
coercion is all about! I decided to not pay much attention to the
discussion and concentrate on understanding other aspects of Sage. (I
think it was a good decision, as I got to coercion in the end.

> Robert Bradshaw, Mike Hansen, Bobby Moretti and I are currently in the
> process of changing a lot of the infrastructure behind parents, elements,
> etc. If you want to help (or want to see our current progress) see the
> sprint page at http://wiki.sagemath.org/days7/coercion or contact one of us
> via e-mail.

Yes, I'd really like to help as I want to understand how Sage works.
I've taken a look at the sprint page and I see that there are quite a
few things on the todo list. I can start with some from the "little to
do" section and the progress from there. But can you explicitly tell
me what needs to be done?

> Given that, I'll answer your questions, both as Sage exists now and as we
> see it existing in a few months.

Thanks for your other answers.

> > I'm wondering if there is some documentation or a howto somewhere that
> > describes the process of adding new structures to Sage.
>
> We're working on this. See the wiki page I referenced above for the current
> progress.

Great. I think such a thing would be extremely helpful to a new user.

> Let me know if you have more questions.
> And for those of you out there interested in coercion, I'll have my bundle
> posted as soon as I get a chance to tie off some loose ends.

I look forward to this.

Take care,
Franco

--

Robert Bradshaw

unread,
Feb 14, 2008, 12:26:30 AM2/14/08
to sage-...@googlegroups.com
On Feb 13, 2008, at 7:10 PM, Franco Saliola wrote:

> On Feb 12, 2008 10:50 PM, David Roe <roe...@gmail.com> wrote:
>
>> So, these kinds of issues were the subject of the coercion project
>> at SD7.
>
> Yeah, I was at Sage Days 7, but I didn't realize that this is what
> coercion is all about! I decided to not pay much attention to the
> discussion and concentrate on understanding other aspects of Sage. (I

> think it was a good decision, as I got to coercion in the end.)

The core question of coercion is when I type "a+b" where a and b are
different types, where should the result live? To facilitate Sage
making rational inferences of this type, this is intimately tied to
the Parent/Element/Category discussion that occurred at Sage Days 7
and is the topic of this thread. Specifically, one (of many term)
questions we were trying to answer is how to make it easy for new
structures to hook into Sage's coercion model. We also plan to expand
the category-theoretic framework.

>> Robert Bradshaw, Mike Hansen, Bobby Moretti and I are currently in
>> the
>> process of changing a lot of the infrastructure behind parents,
>> elements,
>> etc. If you want to help (or want to see our current progress)
>> see the
>> sprint page at http://wiki.sagemath.org/days7/coercion or contact
>> one of us
>> via e-mail.
>
> Yes, I'd really like to help as I want to understand how Sage works.
> I've taken a look at the sprint page and I see that there are quite a
> few things on the todo list. I can start with some from the "little to
> do" section and the progress from there. But can you explicitly tell
> me what needs to be done?

We would gladly welcome your help--it is a daunting but very
parallelizeable task. Specifically, we're trying to make each parent
in Sage conform to the model on the wiki. At a bare minimum this
means for a parent X we have

X.__init__ calls the init function of its superclass, passing up
"element_class" which is to be called for new element creation. (This
is often the actual class itself, but may be a function instead).
X.__call__ should be removed, and the logic is placed into element_class
X._coerce_, X._coerce_impl, etc. are deprecated and should be
removed. There are two simple ways to implement this functionality:
1) implement X._has_coerce_map_from_(S) which returns True when
there is a natural coercion from S to X, and False otherwise.
2) call self._populate_coercion_lists_(coerce_list=
[list,of,parents,who,coerce,into,self])
One can implement both (1) and (2) if one wants. Option (2) is nice
because it automatically searches recursively.

The much to do/little to do distinction is quite fuzzy, and a very
bad indication of how easy it would be to jump into it. If I were
going to start, I would pick an easy parent in sage.modules (It's on
the much to do because there are a lot of specific module types, not
because of complexity.) Maybe I could do one module as an example.

To get started, you need to install the new Cython http://
sage.math.washington.edu/home/robertwb/cython/ (don't worry, it
passes sage -testall), and make a new branch and pull the latest
bundle (currently the real-complex one, though David Roe will have
one up soon hopefully too).

>> Given that, I'll answer your questions, both as Sage exists now
>> and as we
>> see it existing in a few months.
>
> Thanks for your other answers.
>
>>> I'm wondering if there is some documentation or a howto somewhere
>>> that
>>> describes the process of adding new structures to Sage.
>>
>> We're working on this. See the wiki page I referenced above for
>> the current
>> progress.
>
> Great. I think such a thing would be extremely helpful to a new user.

That's the hope. This will in some form be part of the programming
guide.

- Robert

root

unread,
Feb 14, 2008, 1:45:39 AM2/14/08
to sage-...@googlegroups.com, sage-...@googlegroups.com
>The core question of coercion is when I type "a+b" where a and b are
>different types, where should the result live? To facilitate Sage
>making rational inferences of this type, this is intimately tied to
>the Parent/Element/Category discussion that occurred at Sage Days 7
>and is the topic of this thread. Specifically, one (of many term)
>questions we were trying to answer is how to make it easy for new
>structures to hook into Sage's coercion model. We also plan to expand
>the category-theoretic framework.

This is one area where Axiom excels. You might want to look at the
way it is done in Axiom.

Tim

root

unread,
Feb 14, 2008, 1:50:49 AM2/14/08
to sage-...@googlegroups.com, sage-...@googlegroups.com
>The core question of coercion is when I type "a+b" where a and b are
>different types, where should the result live? To facilitate Sage
>making rational inferences of this type, this is intimately tied to
>the Parent/Element/Category discussion that occurred at Sage Days 7
>and is the topic of this thread. Specifically, one (of many term)
>questions we were trying to answer is how to make it easy for new
>structures to hook into Sage's coercion model. We also plan to expand
>the category-theoretic framework.

In fact, this raises the somewhat sensitive question of whether it
makes sense to implement most of the algorithms in python directly.
Wouldn't it be better to depend on the strength of the underlying
systems?

Tim

Robert Bradshaw

unread,
Feb 14, 2008, 12:52:06 AM2/14/08
to sage-...@googlegroups.com

Yes, in the EuclideanDomain category, a generic GCD algorithm would
be implemented that would be available to any member of this
category. But the integers, or Z[x], would override this gcd with a
more specific (and much faster) implementation.

- Robert

Reply all
Reply to author
Forward
0 new messages