Opened 11 years ago

Last modified 8 years ago

#12269 new enhancement

coercion and conversion for absolute_field

Reported by: mstreng Owned by: davidloeffler
Priority: major Milestone: sage-6.4
Component: number fields Keywords: coercion conversion absolute_field number field structure relative absolute
Cc: jdemeyer, SimonKing, daniels Merged in:
Authors: Reviewers:
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by mstreng)

sage: x = var('x')
sage: K1.<a1> = CyclotomicField(11)
sage: K2.<a2> = K1.extension(x^2 - 3)
sage: K3.<a3> = K2.extension(x^2 + 1) # Let's make a big relative number field
sage: t=a1+6*a2+a3*a1                 # with a complicated element.
sage: L = K3.absolute_field('b')
sage: L(t)
# The code at #11869 takes 12 seconds to compute roots of a
# polynomial, and then doesn't use them.
# TypeError: No compatible natural embeddings found for Number Field in b with .... and Complex Lazy Field
sage: L.structure()                   # However, the correct conversion map is available and works almost instantly
#(Isomorphism map:... , Isomorphism map: ...)
sage: L.structure()[1](t)
# big output
sage: L.gen() + t                     # It would be good if one of the structure maps is a coercion, but they aren't at the moment
# TypeError: unsupported operand parent(s) for '+': ....
sage: K3(L.gen())                     # There are similar problems in the other direction
# TypeError: Cannot coerce element into this number field
sage: L.structure()[0](L.gen())       # for which the structure maps also work.
# a3 - a2 + a1

So this ticket is meant to:

  • make both structure maps into conversions
  • maybe make one or both of the structure maps into a coercion

Speeding up #11869 is not really related and is #12270.

Attachments (1)

11800-indicator.patch (2.4 KB) - added by mstreng 11 years ago.
shows where long calculations are done in #11869

Download all attachments as: .zip

Change History (24)

comment:1 Changed 11 years ago by mstreng

  • Description modified (diff)

comment:2 Changed 11 years ago by mstreng

  • Description modified (diff)

Sorry, I'm messing up the patch numbers. I mean #11869 everywhere.

Changed 11 years ago by mstreng

shows where long calculations are done in #11869

comment:3 Changed 11 years ago by mstreng

  • Description modified (diff)

comment:4 Changed 11 years ago by mstreng

See also #12271 (which is the same, but for relativize)

comment:5 follow-up: Changed 11 years ago by jdemeyer

I believe a solution similar to #11876 is in order: make absolute_field store an embedding (in this case an isomorphism) to the starting field.

comment:6 in reply to: ↑ 5 Changed 11 years ago by mstreng

  • Cc SimonKing added

Replying to jdemeyer:

I believe a solution similar to #11876 is in order: make absolute_field store an embedding (in this case an isomorphism) to the starting field.

That would fix it, but I don't think it would be very fast, as it would still use .roots() / #11869.

Wouldn't it be better to use the category/coercion framework here? I suppose all that is needed it to store the .structure() homomorphisms in the appropriate place (wherever that is, cc: Simon) as conversion maps. The structure homomorphisms are computed already, and using them is very fast.

Still, inheriting embeddings as in #11876 is certainly useful, so I think it is best to do both.

comment:7 follow-up: Changed 11 years ago by mstreng

The map absolute_field().structure()[1] (from relative to absolute) cannot be a *coercion*, because it would lead to non-commuting diagrams of coercions. In sage-4.8.alpha4:

sage: K.<a> = NumberField(x^2-2, embedding=-1)
sage: L.<b> = NumberField(x^2-2, embedding=1)
sage: xK = K['x'].gen()
sage: xL = L['x'].gen()
sage: M.<c> = NumberField(xK^2-3)
sage: N.<d> = NumberField(xL^2-3)
sage: O = M.absolute_field('e')
sage: P = N.absolute_field('e')
sage: b_in_a = K(0)+b
sage: map1 = O.structure()[1]
sage: map2 = P.structure()[1]
sage: b_in_a in map1.domain()
# True
sage: b in map2.domain()
# True
sage: map1(b_in_a) - map2(b)
# e^3 - 9*e, which is non-zero, so the diagrams don't commute!

Fast *conversions* in both directions would be very useful though. And maybe coercion from absolute to relative?

comment:8 follow-up: Changed 11 years ago by SimonKing

Sorry, I did not answer Marco's question yet.

Is it the case that the map is already known at initialisation time? Then, you could use (depending on whether you want a conversion or a coercion or an action) sage.structure.parent.Parent.register_conversion(...) or ...register_coercion(...) or ...register_action(...). But note that it might be tricky to find the right moment for using these methods: They raise an error if the coercion framework was used before invoking the methods.

If the maps are not available at initialisation time (or if otherwise initialisation takes too much time), you could implement either _convert_map_from_ or _coerce_map_from_ -- see the documentation of both methods in sage.structure.parent.Parent for the expected return values. The advantage is that the map would only be constructed when needed.

Concerning "coercion or conversion between relative and absolute number fields", I think there has been at least one thread on sage-nt and also a trac ticket devoted to that subject.

comment:9 in reply to: ↑ 8 Changed 11 years ago by mstreng

  • Type changed from defect to enhancement

Replying to SimonKing:

Sorry, I did not answer Marco's question yet.

No problem, it wasn't a very direct question.

Is it the case that the map is already known at initialisation time?

Don't know, I'll have to dig through the code some more.

Concerning "coercion or conversion between relative and absolute number fields", I think there has been at least one thread on sage-nt and also a trac ticket devoted to that subject.

Thanks, I don't know that ticket/thread. I have found

The first two are about coercions between number fields, but don't say anything about relative versus absolute. The third is about conversions, again no relative versus absolute.

I also did another search on trac, and could only find the tickets I created last week: #12269 (this ticket) and #12271 (same, but for relativize).

comment:10 in reply to: ↑ 7 Changed 11 years ago by mstreng

  • Description modified (diff)

Replying to mstreng:

structure()[1] cannot be a coercion, because it would lead to non-commuting diagrams of coercions.

Actually, maybe it is the coercion between O to P that shouldn't be there! All of the following maps are natural O <--> M <-- K <--> L --> N <--> P and a map between O and P sending generator to generator does not commute with the abovementioned natural maps.

Some more about O and P:

sage: O
Number Field in e with defining polynomial x^4 - 10*x^2 + 1
sage: P
Number Field in e with defining polynomial x^4 - 10*x^2 + 1
sage: O is P
False
sage: O == P
True
sage: RR(O.structure()[1].domain().base_field().gen())
-1.41421356237309
sage: RR(P.structure()[1].domain().base_field().gen())
1.41421356237309

O and P are really different, I don't understand True for "==" here. Is that a bug?

sage: K is L
False
sage: K == L
False

comment:11 follow-up: Changed 11 years ago by lftabera

Hi, I agree that the error here is that O and P should not be given a coercion. Note that the code above does not work if P is given another generator name. On this example I would not expect a canonical isomorphism from O to P.

comment:12 follow-up: Changed 11 years ago by lftabera

Forcing coercions exposes other errors in the coercion model:

K = NumberField([x^2-2, x^2-3], 'a,b')
M = K.absolute_field('c')
M_to_K, K_to_M = M.structure()
M.register_coercion(K_to_M)
K.register_coercion(M_to_K)
M.coerce_map_from(QQ)
...
UnboundLocalError: local variable 'connecting' referenced before assignment

comment:13 in reply to: ↑ 12 ; follow-up: Changed 11 years ago by SimonKing

Replying to lftabera:

Forcing coercions exposes other errors in the coercion model:

Right. And here it is (in sage.structure.parent, lines 2300-2303):

                connection = None
                if EltPair(mor._domain, S, "coerce") not in _coerce_test_dict:
                    connecting = mor._domain.coerce_map_from(S)
                if connecting is not None:

So, apparently someone intended to write "connecting = None", but wrote "connection = None". Can you try whether writing "connecting = None" fixes the problem?

K = NumberField([x^2-2, x^2-3], 'a,b')
M = K.absolute_field('c')
M_to_K, K_to_M = M.structure()
M.register_coercion(K_to_M)
K.register_coercion(M_to_K)
M.coerce_map_from(QQ)
...
UnboundLocalError: local variable 'connecting' referenced before assignment

comment:14 in reply to: ↑ 11 Changed 11 years ago by mstreng

Replying to lftabera:

Hi, I agree that the error here is that O and P should not be given a coercion. Note that the code above does not work if P is given another generator name. On this example I would not expect a canonical isomorphism from O to P.

This can be fixed by making O == P be False by letting O.__cmp__(P) compare structure maps.

comment:15 in reply to: ↑ 13 ; follow-ups: Changed 11 years ago by lftabera

Replying to SimonKing:

Replying to lftabera:

Forcing coercions exposes other errors in the coercion model:

Right. And here it is (in sage.structure.parent, lines 2300-2303):

                connection = None
                if EltPair(mor._domain, S, "coerce") not in _coerce_test_dict:
                    connecting = mor._domain.coerce_map_from(S)
                if connecting is not None:

So, apparently someone intended to write "connecting = None", but wrote "connection = None". Can you try whether writing "connecting = None" fixes the problem?

Yes, this solves the problem. I guess that this fix should go to a new ticket.

comment:16 in reply to: ↑ 15 Changed 11 years ago by SimonKing

Replying to lftabera:

Yes, this solves the problem. I guess that this fix should go to a new ticket.

OK, but I couldn't do it right now. I am in quite a mess with my good old group cohomology spkg, which wouldn't work in the latest Sage version for at least three independent reasons.

comment:17 in reply to: ↑ 15 Changed 11 years ago by mstreng

Replying to lftabera:

Yes, this solves the problem. I guess that this fix should go to a new ticket.

Yes, that makes sense. It is a bugfix of 2 characters, so doesn't have to wait for all of #12269 to be fixed.

comment:18 Changed 10 years ago by lftabera

For the typo in parent.pyx I have added a patch in #12990

comment:19 Changed 10 years ago by daniels

  • Cc daniels added

comment:20 Changed 9 years ago by jdemeyer

  • Milestone changed from sage-5.11 to sage-5.12

comment:21 Changed 9 years ago by vbraun_spam

  • Milestone changed from sage-6.1 to sage-6.2

comment:22 Changed 8 years ago by vbraun_spam

  • Milestone changed from sage-6.2 to sage-6.3

comment:23 Changed 8 years ago by vbraun_spam

  • Milestone changed from sage-6.3 to sage-6.4
Note: See TracTickets for help on using tickets.