coercion question

0 views
Skip to first unread message

John H Palmieri

unread,
Jul 4, 2008, 10:12:37 AM7/4/08
to sage-support
I'm running into a coercion problem. I'm trying to define a class
SteenrodAlgebra (based on the Algebra class); there should be one
Steenrod algebra for each prime number p, and it is an algebra over
GF(p). For example, you can do

sage: A5 = SteenrodAlgebra(5)
sage: A7 = SteenrodAlgebra(7)

I have coercion working properly for addition, but not multiplication,
and I really don't know why. One way to define elements is to use a
method called "P":

sage: v = A5.P(1,2,3)
sage: w = A7.P(4,5)

The identity element of the Steenrod algebra is called P(0), and I
have a _coerce_impl method which seems to work: it seems to coerce a
scalar into the appropriate scalar multiple of P(0):

sage: 3 + v
3 P(0) + P(1,2,3)
sage: 11 + w # addition here is mod 7
4 P(0) + P(4,5)

Multiplication is broken, though:

sage: 3 * v # this works
3 P(1,2,3)
sage: 11 * w

gives me a traceback, and it appears that the problem is that Sage is
testing whether A5.gen(0) is equal to A7.gen(0). Why is A7.gen(0)
involved? I mean, w is in A7, but why is Sage interested in its 0th
generator? And why is A5.gen(0) involved in this at all, when I'm
trying to multiply an element of A7 by an integer (which should coerce
to an element of GF(7), and then into A7)? If I interchange the order
of evaluation here, doing 11 * w before 3 * v, then 11 * w works,
while 3 * v gives the error. By putting in some print statements in
various places, I can see that even when 3 * v works, it is still
calling A5.gen(0) the first time it is called; subsequent times, it
doesn't call this. (Is Sage caching information about generators
somewhere, and is that perhaps causing problems, because I've done
something wrong and not distinguished sufficiently between Steenrod
algebras at different primes?)

So I'm very confused. Any ideas what I should look at to try to fix
this?

Robert Bradshaw

unread,
Jul 4, 2008, 1:25:55 PM7/4/08
to sage-s...@googlegroups.com
On Jul 4, 2008, at 7:12 AM, John H Palmieri wrote:

> I'm running into a coercion problem. I'm trying to define a class
> SteenrodAlgebra (based on the Algebra class); there should be one
> Steenrod algebra for each prime number p, and it is an algebra over
> GF(p). For example, you can do
>
> sage: A5 = SteenrodAlgebra(5)
> sage: A7 = SteenrodAlgebra(7)

I just tried these lines, where do I import SteenrodAlgebra from? (Or
is it not in standard Sage yet?)

Yes, Sage caches some information so it doesn't have to do the logic
anew on each arithmetic operation. One thing to check is if A5 == A7
succeeds. If you could post the traceback I could see if anything
stands out to me.

- Robert

John H Palmieri

unread,
Jul 4, 2008, 1:44:20 PM7/4/08
to sage-support


On Jul 4, 10:25 am, Robert Bradshaw <rober...@math.washington.edu>
wrote:
> On Jul 4, 2008, at 7:12 AM, John H Palmieri wrote:
>
> > I'm running into a coercion problem.  I'm trying to define a class
> > SteenrodAlgebra (based on the Algebra class); there should be one
> > Steenrod algebra for each prime number p, and it is an algebra over
> > GF(p).  For example, you can do
>
> > sage: A5 = SteenrodAlgebra(5)
> > sage: A7 = SteenrodAlgebra(7)
>
> I just tried these lines, where do I import SteenrodAlgebra from? (Or  
> is it not in standard Sage yet?)

It's not in standard Sage yet. I've put some sample source code here:

<http://faculty.washington.edu/jpalmier/test.py>

which seems to exhibit the behavior I'm talking about.
Here's an example.

sage: A5 = SteenrodAlgebra(5); A7 = SteenrodAlgebra(7)
sage: A5 == A7
False
sage: v = A5.P(2)
sage: w = A7.P(2,1)
sage: 2 * v
2 P(2)
sage: 3 * w
---------------------------------------------------------------------------
TypeError Traceback (most recent call
last)

/Users/palmieri/<ipython console> in <module>()

/Users/palmieri/element.pyx in
sage.structure.element.RingElement.__mul__ (sage/structure/element.c:
8545)()

/Users/palmieri/coerce.pyx in
sage.structure.coerce.CoercionModel_cache_maps.bin_op_c (sage/
structure/coerce.c:5039)()

/Users/palmieri/coerce.pyx in
sage.structure.coerce.CoercionModel_cache_maps.get_action_c (sage/
structure/coerce.c:7864)()

/Users/palmieri/coerce.pyx in
sage.structure.coerce.CoercionModel_cache_maps.discover_action_c (sage/
structure/coerce.c:8522)()

/Users/palmieri/parent.pyx in
sage.structure.parent.Parent.get_action_c (sage/structure/parent.c:
1843)()

/Users/palmieri/parent.pyx in
sage.structure.parent.Parent.get_action_impl (sage/structure/parent.c:
2005)()

/Users/palmieri/parent.pyx in
sage.structure.parent.Parent.get_action_c_impl (sage/structure/
parent.c:2672)()

/Users/palmieri/parent.pyx in sage.structure.parent._register_pair
(sage/structure/parent.c:6360)()

/Users/palmieri/parent.pyx in sage.structure.parent.EltPair.__eq__
(sage/structure/parent.c:6183)()

/Applications/sage/local/lib/python2.5/site-packages/sage/algebras/
steenrod_algebra.py in __eq__(self, other)
1528 Two elements are equal if their difference is zero.
1529 """
-> 1530 difference = self - other
1531 return len(difference._raw['milnor']) == 0
1532

/Users/palmieri/element.pyx in
sage.structure.element.ModuleElement.__sub__ (sage/structure/element.c:
5421)()

/Users/palmieri/coerce.pyx in
sage.structure.coerce.CoercionModel_cache_maps.bin_op_c (sage/
structure/coerce.c:5338)()

TypeError: unsupported operand parent(s) for '-': 'mod 7 Steenrod
algebra' and 'mod 5 Steenrod algebra'



>
> - Robert

Robert Bradshaw

unread,
Jul 4, 2008, 1:53:05 PM7/4/08
to sage-s...@googlegroups.com

Ah, it looks like your __eq__ method is assuming that self and other
are elements of the steenrod algebra. There are two solutions to this:

1) Use __cmp__ which (in Sage) will ensure that self and other have
the same parent before it's called
2) Fix your __eq__ (and any other comparison methods you might have)
to make sure self-other makes sense (or, as a quick fix, catch the
type error here).

- Robert


John H Palmieri

unread,
Jul 4, 2008, 4:52:17 PM7/4/08
to sage-support


On Jul 4, 10:53 am, Robert Bradshaw <rober...@math.washington.edu>
wrote:
I still don't understand two things: why the gen method is being used,
and why if I multiply an element of SteenrodAlgebra(7) by 3, somehow
elements of SteenrodAlgebra(5) are getting involved.

> - Robert

Robert Bradshaw

unread,
Jul 5, 2008, 1:08:00 PM7/5/08
to sage-s...@googlegroups.com

I'm not seeing where the gen method is being used--it's probably to
get a "generic" element to see if multiplication is a viable option.
As for elements of SteenrodAlgebra(7) and SteenrodAlgebra(5) getting
compared, that's because it's looking up something in a (global-ish)
lookup table that happens to have SteenrodAlgebra(5) in it as well.
Obviously equality here should return False.

- Robert

John H Palmieri

unread,
Jul 5, 2008, 3:42:43 PM7/5/08
to sage-support


On Jul 5, 10:08 am, Robert Bradshaw <rober...@math.washington.edu>
So, for example, for the definition of the __eq__ method for
SteenrodAlgebraElement, replacing

difference = self - other
return len(difference._raw['milnor']) == 0

with

if self.parent() == other.parent():
difference = self - other
return len(difference._raw['milnor']) == 0
else:
return False

would be good enough? (That is, assuming I've defined a reasonable
__eq__ method for the parents, the SteenrodAlgebra class.)

> - Robert

John H Palmieri

unread,
Jul 5, 2008, 3:50:59 PM7/5/08
to sage-support


On Jul 5, 10:08 am, Robert Bradshaw <rober...@math.washington.edu>
It's not apparent where it's used from the traceback, but if I put in
some print statements, e.g., print "gen" at the start of the gen
method, and similarly for _coerce_impl, and for _init_ and _mul_ for
the element class, then when I evaluate 3 * A5.P(2,1,4), gen gets used
before anything else. There is a call to gen(0) in the method
_an_element_c_impl for Parent in parent.pyx; maybe that's where it's
coming from. But mathematically, I still don't understand it...

Robert Bradshaw

unread,
Jul 5, 2008, 8:44:42 PM7/5/08
to sage-s...@googlegroups.com

Here is what happens. When it's trying to figure out how to do
arithmetic between to sets, say ZZ and A5, it wants to know if ZZ
acts on A5 (or, conversely, if A5 acts on ZZ). To do this it needs to
get elements of A5 and ZZ to see if they have _rmul_ and/or _lmul_
methods, so it calls _an_element_c_impl whose generic code tries
calling gen. (Note, this is in the current model, names have changed
a bit, but the general idea is still there). This only happens once,
from then on the action (or non-existence of the action) is cached
for lookup every time two elements of that kind are encountered.

There is much more documentation and introspection in the new model,
so hopefully things will be a lot less confusing.

- Robert

Robert Bradshaw

unread,
Jul 5, 2008, 8:48:17 PM7/5/08
to sage-s...@googlegroups.com

Yes, though that will mean something like A5.P(2) - A5.P(2) == 0 will
return False. This is why you are better off using _cmp_ instead of
__eq__, __ne__, __le__, __gt__, ... (also, the latter are deprecated
in Python). The _cmp_ method will always be called with two things of
the same parent, invoking coercion if necessary.

- Robert


John H Palmieri

unread,
Jul 5, 2008, 10:16:28 PM7/5/08
to sage-support


On Jul 5, 5:48 pm, Robert Bradshaw <rober...@math.washington.edu>
wrote:
I think I understand this, but I have one more problem. I think you're
saying that I'm supposed to get rid of __eq__ and define __cmp__
instead, with no error checking -- assume that the two arguments have
the same parent. I have done this, and __cmp__ just checks whether
the difference x-y is the zero element of the algebra.

Now I get the following, which is good:

sage: A5.P(2) == A7.P(2)
False
sage: A5.P(2) - A5.P(2) == 0
True
sage: 2 * A5.P(2)
2 P(2)
sage: 10 * A7.P(2) # working mod 7
3 P(2)

On the other hand,

sage: cmp(A5.P(2), A7.P(2))

gives an error message: "unsupported operand parent(s) for '-': 'mod 5
Steenrod algebra' and 'mod 7 Steenrod algebra' "

(Same thing happens with 'A5.P(2).__cmp__(A7.P(2))', but cmp(A5(3),
3) returns 0, as it should.)

Why doesn't cmp() work, or is this what's supposed to happen? (I can
add type-checking to the definition of __cmp__, in which case the
above command returns -1, but it sounded like you were saying that I
shouldn't have to.)

Thanks for taking the time to answer all of my silly questions, by the
way. I think this might be the last one for now.

John

> - Robert

Robert Bradshaw

unread,
Jul 5, 2008, 11:39:53 PM7/5/08
to sage-s...@googlegroups.com

What does A5 == A7 give you? Can you do A5.P(2) == A7.P(2)? I'm not
sure exactly what's going on here, but as long as the above is
working well enough for now it's probably worth holding off debugging
too much until the new coercion is in place (which is more likely
than not to resolve this).

- Robert

John H Palmieri

unread,
Jul 6, 2008, 1:00:45 AM7/6/08
to sage-support


On Jul 5, 8:39 pm, Robert Bradshaw <rober...@math.washington.edu>
wrote:
Both of those things, A5 == A7 and A5.P(2) == A7.P(2), return False.
So I'll leave it as is. Thanks.

>
> - Robert
Reply all
Reply to author
Forward
0 new messages