38 views

Skip to first unread message

Jun 7, 2011, 3:25:53 PM6/7/11

to sage-...@googlegroups.com

In sage/structure/parent_base.pyx there is a function

"check_old_coerce" with the following definition:

"check_old_coerce" with the following definition:

cdef inline check_old_coerce(parent.Parent p):

if p._element_constructor is not None:

raise RuntimeError, "%s still using old coercion framework" % p

This function is called from a few methods in class ParentWithBase

(e.g. from _richcmp, from _coerce_c_impl, and from base_extend).

In my class (which inherits from ParentWithBase) I've defined

_element_constructor_ instead, but the init for ParentWithBase insist

on copying this method onto _element_constructor -- thus the

"check_old_coerce" function always fails... It's impossible to

avoid!!!

What is the base class that one is supposed to use instead of ParentWithBase?

The only reference for the coercion model that I was able to find is

http://www.sagemath.org/doc/reference/coercion.html#example, which

even shows an example, but the example inherits from Ring, which

ultimately inherits from ParentWithBase anyway.

Gonzalo

Jun 7, 2011, 4:18:21 PM6/7/11

to sage-devel

Hi Gonzalo,

On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

> What is the base class that one is supposed to use instead of ParentWithBase?

I think it is Parent. The Parent.__init__ accepts an argument base.

Here is a small example:

from sage.structure.parent import Parent

from sage.structure.element import Element

class MyElement(Element):

def __init__(self,n,parent):

Element.__init__(self,parent)

self.n = n

def _repr_(self):

return repr(self.n)

class MyParent(Parent):

Element = MyElement

def __init__(self,B):

from sage.all import Sets

Parent.__init__(self,base=B, category=Sets())

def _repr_(self):

return "Parent over %s"%self.base()

And if you attach that code, then you can do

sage: P = MyParent(QQ)

sage: P

Parent over Rational Field

sage: P.base()

Rational Field

As you see, the base() method exists and works correctly.

As for element constructor, in my minimal example I just provide a

class as an attribute called "Element" to the parent class. Then, an

element constructor is correctly inferred (that's one reason to

initialise the category of the parent):

sage: P(3)

3

sage: type(_)

<class '__main__.MyParent_with_category.element_class'>

sage: isinstance(P(3),MyElement)

True

sage: P._element_constructor_??

Type: instancemethod

...

def _element_constructor_from_element_class(self, *args,

**keywords):

"""

The default constructor for elements of this parent

I hope that answers your question.

Best regards,

Simon

On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

> What is the base class that one is supposed to use instead of ParentWithBase?

Here is a small example:

from sage.structure.parent import Parent

from sage.structure.element import Element

class MyElement(Element):

def __init__(self,n,parent):

Element.__init__(self,parent)

self.n = n

def _repr_(self):

return repr(self.n)

class MyParent(Parent):

Element = MyElement

def __init__(self,B):

from sage.all import Sets

Parent.__init__(self,base=B, category=Sets())

def _repr_(self):

return "Parent over %s"%self.base()

And if you attach that code, then you can do

sage: P = MyParent(QQ)

sage: P

Parent over Rational Field

sage: P.base()

Rational Field

As you see, the base() method exists and works correctly.

As for element constructor, in my minimal example I just provide a

class as an attribute called "Element" to the parent class. Then, an

element constructor is correctly inferred (that's one reason to

initialise the category of the parent):

sage: P(3)

3

sage: type(_)

<class '__main__.MyParent_with_category.element_class'>

sage: isinstance(P(3),MyElement)

True

sage: P._element_constructor_??

Type: instancemethod

...

def _element_constructor_from_element_class(self, *args,

**keywords):

"""

The default constructor for elements of this parent

I hope that answers your question.

Best regards,

Simon

Jun 7, 2011, 4:18:08 PM6/7/11

to sage-...@googlegroups.com

On Tue, Jun 7, 2011 at 12:25 PM, Gonzalo Tornaria

<torn...@math.utexas.edu> wrote:

> In sage/structure/parent_base.pyx there is a function

> "check_old_coerce" with the following definition:

>

> cdef inline check_old_coerce(parent.Parent p):

> if p._element_constructor is not None:

> raise RuntimeError, "%s still using old coercion framework" % p

>

>

> This function is called from a few methods in class ParentWithBase

> (e.g. from _richcmp, from _coerce_c_impl, and from base_extend).

>

> In my class (which inherits from ParentWithBase) I've defined

> _element_constructor_ instead, but the init for ParentWithBase insist

> on copying this method onto _element_constructor -- thus the

> "check_old_coerce" function always fails... It's impossible to

> avoid!!!

>

> What is the base class that one is supposed to use instead of ParentWithBase?

<torn...@math.utexas.edu> wrote:

> In sage/structure/parent_base.pyx there is a function

> "check_old_coerce" with the following definition:

>

> cdef inline check_old_coerce(parent.Parent p):

> if p._element_constructor is not None:

> raise RuntimeError, "%s still using old coercion framework" % p

>

>

> This function is called from a few methods in class ParentWithBase

> (e.g. from _richcmp, from _coerce_c_impl, and from base_extend).

>

> In my class (which inherits from ParentWithBase) I've defined

> _element_constructor_ instead, but the init for ParentWithBase insist

> on copying this method onto _element_constructor -- thus the

> "check_old_coerce" function always fails... It's impossible to

> avoid!!!

>

> What is the base class that one is supposed to use instead of ParentWithBase?

Just Parent, if one can.

> The only reference for the coercion model that I was able to find is

> http://www.sagemath.org/doc/reference/coercion.html#example, which

> even shows an example, but the example inherits from Ring, which

> ultimately inherits from ParentWithBase anyway.

What this is really telling you is that you're using an old coercon

method from a class that's trying to do new-style coercion. (I was

hoping to have all this ripped out years ago, but it lingers on...)

In particular, _coerce_c_impl should never be called, nor should

_richcmp or the generic base_extend. A full traceback would help see

what the problem is.

- Robert

Jun 7, 2011, 4:20:55 PM6/7/11

to sage-devel

PS:

On 7 Jun., 22:18, Simon King <simon.k...@uni-jena.de> wrote:

> As for element constructor, in my minimal example I just provide a

> class as an attribute called "Element" to the parent class. Then, an

> element constructor is correctly inferred (that's one reason to

> initialise the category of the parent):

To avoid misunderstanding: I did not intend to imply that the element

constructor *has* to be provided in that way. You could as well

implement your own _element_constructor_, and it should work.

On 7 Jun., 22:18, Simon King <simon.k...@uni-jena.de> wrote:

> As for element constructor, in my minimal example I just provide a

> class as an attribute called "Element" to the parent class. Then, an

> element constructor is correctly inferred (that's one reason to

> initialise the category of the parent):

constructor *has* to be provided in that way. You could as well

implement your own _element_constructor_, and it should work.

Jun 7, 2011, 8:14:32 PM6/7/11

to sage-...@googlegroups.com

On Tue, Jun 7, 2011 at 5:18 PM, Simon King <simon...@uni-jena.de> wrote:

> Hi Gonzalo,

>

> On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

>> What is the base class that one is supposed to use instead of ParentWithBase?

>

> I think it is Parent. The Parent.__init__ accepts an argument base.

>

> Here is a small example:

> Hi Gonzalo,

>

> On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

>> What is the base class that one is supposed to use instead of ParentWithBase?

>

> I think it is Parent. The Parent.__init__ accepts an argument base.

>

> Here is a small example:

Thanks for the example. I'll try it.

One caveat, though. The standard "Ring" and "Algebra" parents both

inherit from the ParentWithBase. Am I allowed to mix an element class

derived from AlgebraElements with a parent class derived from Parent?

Also, is it my impression or this model seems to require a lot of

boilerplate if I wanted to implement it fully (with categories,

functors, etc)?

Gonzalo

Jun 8, 2011, 1:04:21 AM6/8/11

to sage-...@googlegroups.com

On Tue, Jun 7, 2011 at 5:14 PM, Gonzalo Tornaria

<torn...@math.utexas.edu> wrote:

> On Tue, Jun 7, 2011 at 5:18 PM, Simon King <simon...@uni-jena.de> wrote:

>> Hi Gonzalo,

>>

>> On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

>>> What is the base class that one is supposed to use instead of ParentWithBase?

>>

>> I think it is Parent. The Parent.__init__ accepts an argument base.

>>

>> Here is a small example:

>

> Thanks for the example. I'll try it.

>

> One caveat, though. The standard "Ring" and "Algebra" parents both

> inherit from the ParentWithBase. Am I allowed to mix an element class

> derived from AlgebraElements with a parent class derived from Parent?

<torn...@math.utexas.edu> wrote:

> On Tue, Jun 7, 2011 at 5:18 PM, Simon King <simon...@uni-jena.de> wrote:

>> Hi Gonzalo,

>>

>> On 7 Jun., 21:25, Gonzalo Tornaria <torna...@math.utexas.edu> wrote:

>>> What is the base class that one is supposed to use instead of ParentWithBase?

>>

>> I think it is Parent. The Parent.__init__ accepts an argument base.

>>

>> Here is a small example:

>

> Thanks for the example. I'll try it.

>

> One caveat, though. The standard "Ring" and "Algebra" parents both

> inherit from the ParentWithBase. Am I allowed to mix an element class

> derived from AlgebraElements with a parent class derived from Parent?

I can't say for sure that there aren't any hidden assumptions, but I

don't think the Parent's class hierarchy constrains the Element's.

> Also, is it my impression or this model seems to require a lot of

> boilerplate if I wanted to implement it fully (with categories,

> functors, etc)?

I've tried to limit the amount of boilerplate one needs to write. For

example, if a category is not given, it will guess one for you (often

Sets). You simply have to declare that a coercion exists and it will

create the Morphisms for you. You've read

http://www.sagemath.org/doc/reference/coercion.html I presume? Not

much, but probably the best we have.

- Robert

Jun 8, 2011, 4:38:49 AM6/8/11

to sage-devel

Hi Gonzalo,

On 8 Jun., 07:04, Robert Bradshaw <rober...@math.washington.edu>

wrote:

any special assumption on their parents.

> > Also, is it my impression or this model seems to require a lot of

> > boilerplate if I wanted to implement it fully (with categories,

> > functors, etc)?

I didn't mention functors, although I love the stuff in

sage.categories.pushout :))

The full "boilerplate", if you want to do all of coercion model and

category framework, should roughly be as described below.

Let MyParent be the parent class and MyElement a class for the

elements of a MyParent instance. Let P and E denote instances of

MyParent and MyElement, respectively.

I start with a summary of the steps, telling how important and how

difficult they usually are, IMO:

0. Classes to inherit from: Easy, HAS to be done.

1. "Magic" Python methods: Mainly easy, you just need to write _repr_

instead of __repr__, etc. __cmp__ may be a bit more tricky.

2.a) Category for parents. Mainly easy: Just choose a category and

initialise your parent with it. Should/Has to be done.

2.b) Category for elements: Mainly easy. Just do

Should be done, if you use Python or wait until #11115 is merged.

You may be required to provide certain element or parent methods, but

that depends on the category you chose.

3. Basic coercion. Can range from "nothing to do at all" to "tedious".

It is a must-have!

3.a) Conversion: 2.b) may actually be sufficient for it, otherwise

implement _element_constructor_

3.b) Coercion maps: Done with implementing one method, namely

_coerce_map_from_.

4. Not-so-basic coercion with functors. Tricky, can be seen as cherry

on the cake (so, not necessary but sometimes nice to have).

Here are the gory details.

0. Classes to inherit from

MyParent should inherit from sage.structure.parent.Parent and

MyElement from sage.structure.element.Element, or of course from a sub-

class.

1. "Magic" Python methods

Do not use __repr__, __add__, __mul__ etc with double underscore, but

with single underscore (_repr_, _add_,_mul_). The double underscore

methods are inherited, and the generic code should not be overridden

since it provides coercion. The case of __cmp__ is a bit more

complicated -- please read the comments in the vicinity of

sage.structure.parent.Parent.__cmp__.

2. Category framework

2.a) Initialisation of the parent class

In MyParent.__init__, you should construct a category (or pass it as

an argument to __init__), and you should call

Parent.__init__(self,...,category=your_category). That is usually a

small amount of work, since probably you will find an existing

category that suites your needs --- Sets(), Algebras(basering),

Rngs(), Rings(), etc.

NOTE: If MyParent is written in Python, then you will find that its

instances belong to a class MyParent_with_category -- that is a

subclass of MyParent that is automatically obtained by adding stuff

from the category framework

2.b) Initialisation of the element class

The class MyParent should have an attribute called `Element`, and its

value should be MyElement. The background is that the attribute

Element is automatically mixed with stuff from the category and turned

into a new class available as P.element_class (where P is an instance

of MyParent). Note that this only works if MyParent is written in

Python --- or you may apply #11115, because then it also works with

Cython.

2.c) Required abstract methods

Some categories require that you implement certain methods for

MyParent or MyElement, such as lift() if your parent is a quotient.

2.d) Make the test suites work

You are supposed to provide doc tests of the form TestSuite(P).run().

To make them work, you may need to implement further things, like

MyParent._an_element_. The error messages of TestSuite may tell you

what is missing. But you may actually be lucky, sometimes there are

generic methods that do the job for you.

3. Coercion - the basics

3.a) Element conversion

Note that this is CONVERSION. So, the aim is that P(bla) returns an

element of P to the given argument bla -- but it is not necessarily

the case that there is a coercion map from parent(bla) to P.

3.a).(i) The default

It may be enough to do *nothing* at all: You provided MyParent.Element

= MyElement in step 2.b), and the default is that P(bla) returns

P.element_class(bla), and that will use the initialisation from

MyElement like MyElement(P,bla). So, if MyElement.__init__ is able to

understand anything convertible to P then you can rely on the default!

3.b).(ii) _element_constructor_

If you want to keep MyElement.__init__ simple, then you should provide

MyParent with a method _element_constructor_. It should transform

given arguments to something you can use to initialise MyElement. BUT

NOTE: You should NOT return MyElement(P,...)!! Instead, return

P.element_class(P,...)!

3.c) Coercion maps

A coercion of "bla" into P is more than just a conversion P(bla),

because in a coercion you must have a structure preserving map from

the parent of bla to P. Think of the integers: You can convert 1.0

into ZZ, but there is no coercion from RR (the parent of 1.0) to ZZ.

You should provide MyParent with a method _coerce_map_from_.

Requirements: If there is a coercion from a parent S to P, then

P._coerce_map_from_(S) should either return True or an actual map from

S to P.

(i) If it returns a map f, then an element e of S is coerced into

the element f(e) of P

(ii) If it just returns True, then P.coerce_map_from(S) will

automatically create a map for you. Coercion of an element e of S into

P boils down to calling P._element_constructor_(e).

4. Coercion -- the advanced stuff.

This step is needed if you want to do arithmetic with elements from P

and elements from S, where neither S coerces into P nor P coerces into

S. A typical example is P=ZZ[x] and S=QQ. The result of an arithmetic

operation between S and P lives in QQ[x], hence, neither in S nor in

P.

4.a) The construction of P

It is assumed that you can construct P out of a simpler parent by

means of a construction that is supposed to be functorial (e.g., the

construction of "forming a polynomial ring with variable x" transforms

*any* ring R into a ring R[x], and any map from R to S yields a map

from R[x] to S[x]).

Then, you should provide MyParent with a method construction(), that

returns a pair F,R, where F is a so-called construction functor, and

F(R) == P.

4.b) The construction functor F

See the examples in sage.categories.pushout. Basically, you need to

implement a class MyFunctor inherited from

sage.categories.pushout.ConstructionFunctor, and provide it with a

method _apply_functor

4.c) Pushout of functors

Assume that F1 is an instance of MyFunctor and F2 is any other

construction functor, and assume that there is neither a coercion from

F1(R) to F2(R) nor from F2(R) to F1(R). Assume further that you can

think of a "canonical" parent S that can be obtained from R, such that

both F1(R) and F2(R) coerce into S. Then, F1.pushout(F2) should return

a functor F3 such that S==F3(R).

Example from above: F1 is the fraction field constructor, F2 is the

polynomial ring constructor with variable x, and R is ZZ. Then,

F1(R)==QQ and F2(R)==ZZ[x] . You want S = QQ[x], hence, F3 = F2(F1),

such that S==F3(R)=F2(F1(R)).

Fortunately, this can be achieved very easily, using the default

method pushout() of ConstructionFunctor. You just provide MyFunctor

with an attribute "rank". If F1.rank is smaller than F2.rank then F3

will be "first F1, then F2". Example:

sage: R = ZZ

sage: F1 = QQ.construction()[0]

sage: F2 = R['x'].construction()[0]

sage: F1

FractionField

sage: F2

Poly[x]

sage: F1.rank

5

sage: F2.rank

9

sage: F1.pushout(F2)

Poly[x](FractionField(...))

sage: F2.pushout(F1)

Poly[x](FractionField(...))

4.d) Merging functors

This is when functors F1 and F2 are of the same rank.

It may be that your parent comes in different implementations. For

example, ZZ[x] can be in a dense or sparse implementation, based on

NTL or FLINT. The construction functor should know about these

details. And then, MyFunctor should be provided with a method merge()

with the following properties: If F1 and F2 are two construction

functors of the same rank, such that F1(R) and F2(R) are isomorphic

objects in different implementation for ANY R, then F1.merge(F2)

should return a functor F3 such that F3(R) is isomophic to F1(R) and

F2(R) and there is a coercion from both F1(R) and F2(R) to F3(R).

Otherwise, None should be returned.

Example: If F1 returns dense 3x3 matrix spaces and F2 returns sparse

3x3 matrix spaces, and you decide that dense is the default, then

F1.merge(F2) should return F1.

sage: MD = MatrixSpace(QQ,3,3,sparse=False)

sage: MS = MatrixSpace(QQ,3,3,sparse=True)

sage: FD,_=MD.construction()

sage: FS,_=MS.construction()

sage: FD.rank

10

sage: FS.rank

10

sage: FD.is_sparse

False

sage: FS.is_sparse

True

sage: FD.merge(FS).is_sparse

False

sage: FS.merge(FD).is_sparse

False

So, if you want the full programme then it's much to do. But often,

well-chosen parts of it are sufficient.

Best regards,

Simon

On 8 Jun., 07:04, Robert Bradshaw <rober...@math.washington.edu>

wrote:

> > One caveat, though. The standard "Ring" and "Algebra" parents both

> > inherit from the ParentWithBase. Am I allowed to mix an element class

> > derived from AlgebraElements with a parent class derived from Parent?

>

> I can't say for sure that there aren't any hidden assumptions, but I

> don't think the Parent's class hierarchy constrains the Element's.

I agree with Robert. As much as I understand, ring elements do not do
> > inherit from the ParentWithBase. Am I allowed to mix an element class

> > derived from AlgebraElements with a parent class derived from Parent?

>

> I can't say for sure that there aren't any hidden assumptions, but I

> don't think the Parent's class hierarchy constrains the Element's.

any special assumption on their parents.

> > Also, is it my impression or this model seems to require a lot of

> > boilerplate if I wanted to implement it fully (with categories,

> > functors, etc)?

sage.categories.pushout :))

The full "boilerplate", if you want to do all of coercion model and

category framework, should roughly be as described below.

Let MyParent be the parent class and MyElement a class for the

elements of a MyParent instance. Let P and E denote instances of

MyParent and MyElement, respectively.

I start with a summary of the steps, telling how important and how

difficult they usually are, IMO:

0. Classes to inherit from: Easy, HAS to be done.

1. "Magic" Python methods: Mainly easy, you just need to write _repr_

instead of __repr__, etc. __cmp__ may be a bit more tricky.

2.a) Category for parents. Mainly easy: Just choose a category and

initialise your parent with it. Should/Has to be done.

2.b) Category for elements: Mainly easy. Just do

class MyParent(Parent):

Element = MyElement

def __init__...
Element = MyElement

Should be done, if you use Python or wait until #11115 is merged.

You may be required to provide certain element or parent methods, but

that depends on the category you chose.

3. Basic coercion. Can range from "nothing to do at all" to "tedious".

It is a must-have!

3.a) Conversion: 2.b) may actually be sufficient for it, otherwise

implement _element_constructor_

3.b) Coercion maps: Done with implementing one method, namely

_coerce_map_from_.

4. Not-so-basic coercion with functors. Tricky, can be seen as cherry

on the cake (so, not necessary but sometimes nice to have).

Here are the gory details.

0. Classes to inherit from

MyParent should inherit from sage.structure.parent.Parent and

MyElement from sage.structure.element.Element, or of course from a sub-

class.

1. "Magic" Python methods

Do not use __repr__, __add__, __mul__ etc with double underscore, but

with single underscore (_repr_, _add_,_mul_). The double underscore

methods are inherited, and the generic code should not be overridden

since it provides coercion. The case of __cmp__ is a bit more

complicated -- please read the comments in the vicinity of

sage.structure.parent.Parent.__cmp__.

2. Category framework

2.a) Initialisation of the parent class

In MyParent.__init__, you should construct a category (or pass it as

an argument to __init__), and you should call

Parent.__init__(self,...,category=your_category). That is usually a

small amount of work, since probably you will find an existing

category that suites your needs --- Sets(), Algebras(basering),

Rngs(), Rings(), etc.

NOTE: If MyParent is written in Python, then you will find that its

instances belong to a class MyParent_with_category -- that is a

subclass of MyParent that is automatically obtained by adding stuff

from the category framework

2.b) Initialisation of the element class

The class MyParent should have an attribute called `Element`, and its

value should be MyElement. The background is that the attribute

Element is automatically mixed with stuff from the category and turned

into a new class available as P.element_class (where P is an instance

of MyParent). Note that this only works if MyParent is written in

Python --- or you may apply #11115, because then it also works with

Cython.

2.c) Required abstract methods

Some categories require that you implement certain methods for

MyParent or MyElement, such as lift() if your parent is a quotient.

2.d) Make the test suites work

You are supposed to provide doc tests of the form TestSuite(P).run().

To make them work, you may need to implement further things, like

MyParent._an_element_. The error messages of TestSuite may tell you

what is missing. But you may actually be lucky, sometimes there are

generic methods that do the job for you.

3. Coercion - the basics

3.a) Element conversion

Note that this is CONVERSION. So, the aim is that P(bla) returns an

element of P to the given argument bla -- but it is not necessarily

the case that there is a coercion map from parent(bla) to P.

3.a).(i) The default

It may be enough to do *nothing* at all: You provided MyParent.Element

= MyElement in step 2.b), and the default is that P(bla) returns

P.element_class(bla), and that will use the initialisation from

MyElement like MyElement(P,bla). So, if MyElement.__init__ is able to

understand anything convertible to P then you can rely on the default!

3.b).(ii) _element_constructor_

If you want to keep MyElement.__init__ simple, then you should provide

MyParent with a method _element_constructor_. It should transform

given arguments to something you can use to initialise MyElement. BUT

NOTE: You should NOT return MyElement(P,...)!! Instead, return

P.element_class(P,...)!

3.c) Coercion maps

A coercion of "bla" into P is more than just a conversion P(bla),

because in a coercion you must have a structure preserving map from

the parent of bla to P. Think of the integers: You can convert 1.0

into ZZ, but there is no coercion from RR (the parent of 1.0) to ZZ.

You should provide MyParent with a method _coerce_map_from_.

Requirements: If there is a coercion from a parent S to P, then

P._coerce_map_from_(S) should either return True or an actual map from

S to P.

(i) If it returns a map f, then an element e of S is coerced into

the element f(e) of P

(ii) If it just returns True, then P.coerce_map_from(S) will

automatically create a map for you. Coercion of an element e of S into

P boils down to calling P._element_constructor_(e).

4. Coercion -- the advanced stuff.

This step is needed if you want to do arithmetic with elements from P

and elements from S, where neither S coerces into P nor P coerces into

S. A typical example is P=ZZ[x] and S=QQ. The result of an arithmetic

operation between S and P lives in QQ[x], hence, neither in S nor in

P.

4.a) The construction of P

It is assumed that you can construct P out of a simpler parent by

means of a construction that is supposed to be functorial (e.g., the

construction of "forming a polynomial ring with variable x" transforms

*any* ring R into a ring R[x], and any map from R to S yields a map

from R[x] to S[x]).

Then, you should provide MyParent with a method construction(), that

returns a pair F,R, where F is a so-called construction functor, and

F(R) == P.

4.b) The construction functor F

See the examples in sage.categories.pushout. Basically, you need to

implement a class MyFunctor inherited from

sage.categories.pushout.ConstructionFunctor, and provide it with a

method _apply_functor

4.c) Pushout of functors

Assume that F1 is an instance of MyFunctor and F2 is any other

construction functor, and assume that there is neither a coercion from

F1(R) to F2(R) nor from F2(R) to F1(R). Assume further that you can

think of a "canonical" parent S that can be obtained from R, such that

both F1(R) and F2(R) coerce into S. Then, F1.pushout(F2) should return

a functor F3 such that S==F3(R).

Example from above: F1 is the fraction field constructor, F2 is the

polynomial ring constructor with variable x, and R is ZZ. Then,

F1(R)==QQ and F2(R)==ZZ[x] . You want S = QQ[x], hence, F3 = F2(F1),

such that S==F3(R)=F2(F1(R)).

Fortunately, this can be achieved very easily, using the default

method pushout() of ConstructionFunctor. You just provide MyFunctor

with an attribute "rank". If F1.rank is smaller than F2.rank then F3

will be "first F1, then F2". Example:

sage: R = ZZ

sage: F1 = QQ.construction()[0]

sage: F2 = R['x'].construction()[0]

sage: F1

FractionField

sage: F2

Poly[x]

sage: F1.rank

5

sage: F2.rank

9

sage: F1.pushout(F2)

Poly[x](FractionField(...))

sage: F2.pushout(F1)

Poly[x](FractionField(...))

4.d) Merging functors

This is when functors F1 and F2 are of the same rank.

It may be that your parent comes in different implementations. For

example, ZZ[x] can be in a dense or sparse implementation, based on

NTL or FLINT. The construction functor should know about these

details. And then, MyFunctor should be provided with a method merge()

with the following properties: If F1 and F2 are two construction

functors of the same rank, such that F1(R) and F2(R) are isomorphic

objects in different implementation for ANY R, then F1.merge(F2)

should return a functor F3 such that F3(R) is isomophic to F1(R) and

F2(R) and there is a coercion from both F1(R) and F2(R) to F3(R).

Otherwise, None should be returned.

Example: If F1 returns dense 3x3 matrix spaces and F2 returns sparse

3x3 matrix spaces, and you decide that dense is the default, then

F1.merge(F2) should return F1.

sage: MD = MatrixSpace(QQ,3,3,sparse=False)

sage: MS = MatrixSpace(QQ,3,3,sparse=True)

sage: FD,_=MD.construction()

sage: FS,_=MS.construction()

sage: FD.rank

10

sage: FS.rank

10

sage: FD.is_sparse

False

sage: FS.is_sparse

True

sage: FD.merge(FS).is_sparse

False

sage: FS.merge(FD).is_sparse

False

So, if you want the full programme then it's much to do. But often,

well-chosen parts of it are sufficient.

Best regards,

Simon

Jun 8, 2011, 8:04:02 AM6/8/11

to sage-...@googlegroups.com

On 6/8/11 3:38 AM, Simon King wrote:

> Hi Gonzalo,

>

> On 8 Jun., 07:04, Robert Bradshaw<rober...@math.washington.edu>

> wrote:

>>> One caveat, though. The standard "Ring" and "Algebra" parents both

>>> inherit from the ParentWithBase. Am I allowed to mix an element class

>>> derived from AlgebraElements with a parent class derived from Parent?

>>

>> I can't say for sure that there aren't any hidden assumptions, but I

>> don't think the Parent's class hierarchy constrains the Element's.

>

> I agree with Robert. As much as I understand, ring elements do not do

> any special assumption on their parents.

>

>>> Also, is it my impression or this model seems to require a lot of

>>> boilerplate if I wanted to implement it fully (with categories,

>>> functors, etc)?

>

> I didn't mention functors, although I love the stuff in

> sage.categories.pushout :))

>

> The full "boilerplate", if you want to do all of coercion model and

> category framework, should roughly be as described below.

> Hi Gonzalo,

>

> On 8 Jun., 07:04, Robert Bradshaw<rober...@math.washington.edu>

> wrote:

>>> One caveat, though. The standard "Ring" and "Algebra" parents both

>>> inherit from the ParentWithBase. Am I allowed to mix an element class

>>> derived from AlgebraElements with a parent class derived from Parent?

>>

>> I can't say for sure that there aren't any hidden assumptions, but I

>> don't think the Parent's class hierarchy constrains the Element's.

>

> I agree with Robert. As much as I understand, ring elements do not do

> any special assumption on their parents.

>

>>> Also, is it my impression or this model seems to require a lot of

>>> boilerplate if I wanted to implement it fully (with categories,

>>> functors, etc)?

>

> I didn't mention functors, although I love the stuff in

> sage.categories.pushout :))

>

> The full "boilerplate", if you want to do all of coercion model and

> category framework, should roughly be as described below.

This is great stuff! Have you considered contributing this to the docs?

Jason

Jun 8, 2011, 8:26:00 AM6/8/11

to sage-devel

Hi Jason,

On 8 Jun., 14:04, Jason Grout <jason-s...@creativetrax.com> wrote:

> This is great stuff! Have you considered contributing this to the docs?

Thanks!

Yes, why not? I guess it should be considered an extension of

http://www.sagemath.org/doc/reference/coercion.html. So I'll start to

work on that text.

Cheers,

Simon

On 8 Jun., 14:04, Jason Grout <jason-s...@creativetrax.com> wrote:

> This is great stuff! Have you considered contributing this to the docs?

Yes, why not? I guess it should be considered an extension of

http://www.sagemath.org/doc/reference/coercion.html. So I'll start to

work on that text.

Cheers,

Simon

Jun 8, 2011, 8:31:21 AM6/8/11

to sage-devel

On 8 Jun., 14:26, Simon King <simon.k...@uni-jena.de> wrote:

> Yes, why not? I guess it should be considered an extension ofhttp://www.sagemath.org/doc/reference/coercion.html. So I'll start to

> work on that text.

Or perhaps it should be in the "Sage constructions" or in a "Thematic

tutorial", rather than in the reference manual?

What do you think suits best?

> Yes, why not? I guess it should be considered an extension ofhttp://www.sagemath.org/doc/reference/coercion.html. So I'll start to

> work on that text.

Or perhaps it should be in the "Sage constructions" or in a "Thematic

tutorial", rather than in the reference manual?

What do you think suits best?

Jun 8, 2011, 8:41:42 AM6/8/11

to sage-...@googlegroups.com

I'd rather have a one-stop place for coercion documentation, so I'd

rather have it in the coercion section of the reference manual. It

might be good to put pointers in the other places for "A short guide to

implementing coercion" in the reference.

Jason

Jun 8, 2011, 10:14:59 AM6/8/11

to sage-devel

Hi Jason,

On 8 Jun., 14:41, Jason Grout <jason-s...@creativetrax.com> wrote:

> I'd rather have a one-stop place for coercion documentation, so I'd

> rather have it in the coercion section of the reference manual. It

> might be good to put pointers in the other places for "A short guide to

> implementing coercion" in the reference.

I really wonder if it makes sense to fit a text on the implementation

of parents and elements with coercion and category *into the reference

manual*? I doubt that the result could be called a one-step place.

The point is that the reference manual seems mainly structured

according to the modules of Sage. Note that http://www.sagemath.org/doc/reference/coercion.html

already slightly violates that rule, because it provides a common text

for at least three modules of Sage, namely sage.structure.coerce,

sage.structure.coerce_actions and sage.structure.coerce_maps

In addition to that, the text that I'm writing will relate with

sage.structure.parent, sage.structure.element, and

sage.categories.pushout.

I believe that a text using stuff from at least 6 modules would not

fit to the idea of a reference manual.

Therefore: Why not have a new thematic tutorial called "How to

implement basic algebraic structures in Sage", with sub-sections on

base classes, categories and coercion?

It would of course be related with various modules of Sage, and there

should be pointers from each of these modules to the new thematic

tutorial -- so that it would be easy to find. Is that what you would

call a one-step place?

Cheers,

Simon

On 8 Jun., 14:41, Jason Grout <jason-s...@creativetrax.com> wrote:

> I'd rather have a one-stop place for coercion documentation, so I'd

> rather have it in the coercion section of the reference manual. It

> might be good to put pointers in the other places for "A short guide to

> implementing coercion" in the reference.

of parents and elements with coercion and category *into the reference

manual*? I doubt that the result could be called a one-step place.

The point is that the reference manual seems mainly structured

according to the modules of Sage. Note that http://www.sagemath.org/doc/reference/coercion.html

already slightly violates that rule, because it provides a common text

for at least three modules of Sage, namely sage.structure.coerce,

sage.structure.coerce_actions and sage.structure.coerce_maps

In addition to that, the text that I'm writing will relate with

sage.structure.parent, sage.structure.element, and

sage.categories.pushout.

I believe that a text using stuff from at least 6 modules would not

fit to the idea of a reference manual.

Therefore: Why not have a new thematic tutorial called "How to

implement basic algebraic structures in Sage", with sub-sections on

base classes, categories and coercion?

It would of course be related with various modules of Sage, and there

should be pointers from each of these modules to the new thematic

tutorial -- so that it would be easy to find. Is that what you would

call a one-step place?

Cheers,

Simon

Jun 8, 2011, 10:32:22 AM6/8/11

to sage-...@googlegroups.com

+1 (or +100000000), especially if Simon is volunteering to write it!

The docstrings & hence ref manual can refer to it.

John

>

> Cheers,

> Simon

>

> --

> To post to this group, send an email to sage-...@googlegroups.com

> To unsubscribe from this group, send an email to sage-devel+...@googlegroups.com

> For more options, visit this group at http://groups.google.com/group/sage-devel

> URL: http://www.sagemath.org

>

Jun 8, 2011, 11:06:26 AM6/8/11

to sage-...@googlegroups.com

On 6/8/11 9:14 AM, Simon King wrote:

> Therefore: Why not have a new thematic tutorial called "How to

> implement basic algebraic structures in Sage", with sub-sections on

> base classes, categories and coercion?

> It would of course be related with various modules of Sage, and there

> should be pointers from each of these modules to the new thematic

> tutorial -- so that it would be easy to find. Is that what you would

> call a one-step place?

> Therefore: Why not have a new thematic tutorial called "How to

> implement basic algebraic structures in Sage", with sub-sections on

> base classes, categories and coercion?

> It would of course be related with various modules of Sage, and there

> should be pointers from each of these modules to the new thematic

> tutorial -- so that it would be easy to find. Is that what you would

> call a one-step place?

Sounds great!

Jason

Jun 8, 2011, 2:18:13 PM6/8/11

to sage-...@googlegroups.com

Sounds like you want to add a section to the developer's guide (http://sagemath.org/doc/developer)? A good introduction into parent/elements and categories is really missing there.

Jun 8, 2011, 2:40:29 PM6/8/11

to sage-devel

Hi Volker,

On 8 Jun., 20:18, Volker Braun <vbraun.n...@gmail.com> wrote:

> Sounds like you want to add a section to the developer's guide

> (http://sagemath.org/doc/developer)?

I guess it depends on the size. If the size is moderate then it could

become a subsection of http://www.sagemath.org/doc/developer/writing_code.html,

if it is too large then it should be a thematic tutorial.

Cheers,

Simon

On 8 Jun., 20:18, Volker Braun <vbraun.n...@gmail.com> wrote:

> Sounds like you want to add a section to the developer's guide

> (http://sagemath.org/doc/developer)?

become a subsection of http://www.sagemath.org/doc/developer/writing_code.html,

if it is too large then it should be a thematic tutorial.

Cheers,

Simon

Jun 9, 2011, 4:47:36 AM6/9/11

to sage-...@googlegroups.com

Hi Simon,

I am one of those who eagerly hope the thematic tutorial to be written and maintained by the core developers of Sage. The article should explain on parents, elements, categories, coercion, morphisms, homsets, and the canonical way to program an algebraic structure on the basic concepts. I think a great amount of time of developers is wasted in learning the concepts in a harsh way, that is, by reading the source codes.

Kwankyu

I am one of those who eagerly hope the thematic tutorial to be written and maintained by the core developers of Sage. The article should explain on parents, elements, categories, coercion, morphisms, homsets, and the canonical way to program an algebraic structure on the basic concepts. I think a great amount of time of developers is wasted in learning the concepts in a harsh way, that is, by reading the source codes.

Kwankyu

Jun 10, 2011, 5:29:04 PM6/10/11

to sage-...@googlegroups.com

Dear Simon, dear all,

+1 on Simon extending his notes to a full tutorial!

Note that we also have quite some tutorial material on development on

the Sage-Combinat queue, and should go into Sage at some point. We

should think about their respective perimeter. In any cases, please

feel free to recycle any part of them!

Thematic tutorial Index:

http://combinat.sagemath.org/doc/thematic_tutorials/index.html

Tutorial: Implementing Algebraic Structures

http://combinat.sagemath.org/doc/thematic_tutorials/tutorial-implementing-algebraic-structures.html

Elements, parents, and categories in Sage: a (draft of) primer (this document is for the most part already in Sage)

http://combinat.sagemath.org/doc/reference/sage/categories/primer.html

Implementing a new parent: a (draft of) tutorial

http://combinat.sagemath.org/doc/reference/sage/categories/tutorial.html

A note: an advantage of putting documentation in the reference manual,

and more precisely directly within the source, is that you can access

it from the command line with e.g.:

sage.categories.tutorial?

and also easily link to it from other spots in the reference manual

with e.g. see :mod:`sage.categories.tutorial`.

Cheers,

Nicolas

--

Nicolas M. Thi�ry "Isil" <nth...@users.sf.net>

http://Nicolas.Thiery.name/

Jun 11, 2011, 2:54:20 AM6/11/11

to sage-devel

Hi All,

On 10 Jun., 23:29, "Nicolas M. Thiery" <Nicolas.Thi...@u-psud.fr>

wrote:

tutorials yet? Is a review missing?

If the problem is about reviews, I suggest to use a similar procedure

for tutorials than for spkgs: There could be tutorials marked

"experimental", or maybe "preliminary" is a better word.

By a preliminary tutorial, I mean one that is not fully reviewed, but

one trusts that the author is expert enough to not write complete

nonsense, and thus makes it publicly available.

The table of contents at http://sagemath.org/doc/thematic_tutorials/index.html

would link to all tutorials, but the link to a preliminary tutorial

would be marked by a (red?) label. In that way, the users can already

benefit from the texts, but know that things may change over time.

Perhaps there could be finer labels, such as "draft". A tutorial would

be "preliminary" if it seems complete but potetially not final, and

"draft" if the author admits that it is incomplete but will not have

time to finish it in the near future.

In that way, all the tutorials from the sage.combinat branch could be

exposed to people *soon*.

Concerning the documents Nicolas pointed at:

Of course some of the subjects overlap with what I am about to write.

But my didactical approach is very different from these documents, to

the extent that there will be no overlap of the actual content of our

documents. Hence, I would not see a problem to eventually have

(preliminary) pointers in http://sagemath.org/doc/thematic_tutorials/index.html

to both the documents in the combinat branch and my to-be-finished

worksheet/text.

But let me finish things first...

Cheers,

Simon

On 10 Jun., 23:29, "Nicolas M. Thiery" <Nicolas.Thi...@u-psud.fr>

wrote:

> Note that we also have quite some tutorial material on development on

> the Sage-Combinat queue, and should go into Sage at some point.

Better sooner than later, I'd say. Why is it not in the thematic
> the Sage-Combinat queue, and should go into Sage at some point.

tutorials yet? Is a review missing?

If the problem is about reviews, I suggest to use a similar procedure

for tutorials than for spkgs: There could be tutorials marked

"experimental", or maybe "preliminary" is a better word.

By a preliminary tutorial, I mean one that is not fully reviewed, but

one trusts that the author is expert enough to not write complete

nonsense, and thus makes it publicly available.

The table of contents at http://sagemath.org/doc/thematic_tutorials/index.html

would link to all tutorials, but the link to a preliminary tutorial

would be marked by a (red?) label. In that way, the users can already

benefit from the texts, but know that things may change over time.

Perhaps there could be finer labels, such as "draft". A tutorial would

be "preliminary" if it seems complete but potetially not final, and

"draft" if the author admits that it is incomplete but will not have

time to finish it in the near future.

In that way, all the tutorials from the sage.combinat branch could be

exposed to people *soon*.

Concerning the documents Nicolas pointed at:

Of course some of the subjects overlap with what I am about to write.

But my didactical approach is very different from these documents, to

the extent that there will be no overlap of the actual content of our

documents. Hence, I would not see a problem to eventually have

(preliminary) pointers in http://sagemath.org/doc/thematic_tutorials/index.html

to both the documents in the combinat branch and my to-be-finished

worksheet/text.

But let me finish things first...

Cheers,

Simon

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu