Opened 4 years ago
Last modified 18 months ago
#18036 new defect
I.parent() should not be the symbolic ring
Reported by:  vdelecroix  Owned by:  

Priority:  major  Milestone:  sage6.6 
Component:  number fields  Keywords:  
Cc:  wuthrich, jdemeyer, mmezzarobba, behackl, rws  Merged in:  
Authors:  Reviewers:  
Report Upstream:  N/A  Work issues:  
Branch:  public/18036 (Commits)  Commit:  d7fab0b6a8628301543ed7bfae70380e1d6fa714 
Dependencies:  Stopgaps: 
Description (last modified by )
As suggested in #7545, I
(so that I^2 = 1
) should be defined directly as the generator of QuadraticField(1)
and not wrapped into a symbolic expression.
Currently, I
is defined in sage/symbolic/pynac.pyx
within the function init_pynac_I
.
Change History (37)
comment:1 followups: ↓ 2 ↓ 4 Changed 4 years ago by
comment:2 in reply to: ↑ 1 ; followup: ↓ 5 Changed 4 years ago by
Replying to nbruin:
I'm not so sure it should. Which quadratic field is the appropriate one? There are many, distinguishable by the name of their generator (that would be 'I') for this one, but also by their specified embeddings, and it's not clear which one to choose.
I also thought of this in the train... and I do not see much possible choices. I found two rather natural choices for the adoption of I
:
 the ring of integers
Z[sqrt(1)]
with its natural embedding inQQbar
QQbar
itself
Is there an argument for doing this? Ticket #17860 referenced in the description makes no mention of it. I'd imagine there might be evaluation reasons that might make it attractive. Perhaps those also give an indication of which quadratic field would be the appropriate one.
Some reasons (in favor of the first choice):
I + 1.0
and1.0 * I
should be complex numbersfactor((I+3))
should be the factorization over the Gaussian integers (i.e.(I) * (I + 1) * (2*I + 1)
)abs(I)
should be the integer1
Vincent
comment:3 Changed 4 years ago by
I
should be an element of QuadraticField(1, 'I', embedding=CC.gen(), latex_name='i')
, which is what it currently is (see src/sage/symbolic/pynac.pyx
).
comment:4 in reply to: ↑ 1 Changed 4 years ago by
Replying to nbruin:
Is there an argument for doing this?
In short: the same reason that 1
is not symbolic. When doing basic arithmetic with I
, there is no need for a symbolic I
. Whenever something symbolic is needed, coercion will make it symbolic.
comment:5 in reply to: ↑ 2 Changed 4 years ago by
Replying to vdelecroix:
I found two rather natural choices for the adoption of
I
:
 the ring of integers
Z[sqrt(1)]
with its natural embedding inQQbar
The ring ZZ[sqrt(1)]
definitely looks like the most natural choice to me, since admits a canonical homomorphism to any other ring with a distinguished square root of 1.
As for the distinguished embedding, is there a specific reason for choosing QQbar
? A more minimal choice would be to fix an embedding into a UniversalCyclotomicField
; then we would have coercion maps ZZ[I]
> UniversalCyclotomicField(zeta)
> QQbar
> CC
. (Maybe this makes finding common parents slightly harder, though.)
comment:6 Changed 4 years ago by
 Description modified (diff)
Thank you all for working on this  this kind of thing has been on the radar for years but after Burcin left daytoday operations around here there hasn't been the combination of energy and knowhow to do this "correctly", whatever that might mean. Just keep in mind it would be nice for I in SR
to be true, though I'm sure it will be since 1 in SR
already is True
. I do like the idea of abs(I)
being an Integer
and not a symbolic expression.
comment:7 Changed 4 years ago by
 Cc mmezzarobba added
comment:8 Changed 4 years ago by
Proof of concept to see what would break: u/mmezzarobba/18036QQi
(I'm using a number field element for now, not an order element, but switching shouldn't be hard). Still needs quite a bit of work, but all tests should pass (I didn't run them all with the last version of the code). Any comment or improvement welcome!
In particular:
 Are there behavior changes that you think are not acceptable, or not acceptable without a deprecation?
 I'm not happy with the changes to
sage.geometry.hyperbolic_space
(which apparently relied on operations involvingI
triggering coercions toSR
), but I don't understand the code well enough to do better.
Tangentially related: now may be a good time to deprecate (or remove directly?) the bogus coercion from SR
to QQbar
.
comment:9 Changed 4 years ago by
comment:10 followup: ↓ 11 Changed 4 years ago by
Very nice that it worked!
I do not quite understand why you need the creation of a new class of NumberFieldQQi
... is that only for the special method you need in the element class?
For embedding in QQbar I guess that what should be fixed is embedding of number fields. In the ideal world, you would declare:
QQi = NumberField(x**2 + 1, 'I', embedding=QQbar.gen())
But then, there might be an infinite loop with the definition of I
in QQbar
. I had the same sort of troubles when refining default embedding from lazy field to AA/QQbar
.
Vincent
comment:11 in reply to: ↑ 10 ; followup: ↓ 12 Changed 4 years ago by
Replying to vdelecroix:
I do not quite understand why you need the creation of a new class of
NumberFieldQQi
... is that only for the special method you need in the element class?
I don't remember, it could be that the reason no longer exists due to later changes.
For embedding in QQbar I guess that what should be fixed is embedding of number fields. In the ideal world, you would declare:
QQi = NumberField(x**2 + 1, 'I', embedding=QQbar.gen())
Yes, the idea is to switch to an embedding into QQbar when other number fields do.
comment:12 in reply to: ↑ 11 ; followup: ↓ 13 Changed 4 years ago by
Replying to mmezzarobba:
Replying to vdelecroix:
I do not quite understand why you need the creation of a new class of
NumberFieldQQi
... is that only for the special method you need in the element class?I don't remember, it could be that the reason no longer exists due to later changes.
One reason was that having separate classes makes it easy to test if we are in the special case of QQ[i] using isinstance
. In the case of the parent class, this is convenient when specifying coercions, for instance.
comment:13 in reply to: ↑ 12 ; followup: ↓ 14 Changed 4 years ago by
Replying to mmezzarobba:
Replying to mmezzarobba:
Replying to vdelecroix:
I do not quite understand why you need the creation of a new class of
NumberFieldQQi
... is that only for the special method you need in the element class?I don't remember, it could be that the reason no longer exists due to later changes.
One reason was that having separate classes makes it easy to test if we are in the special case of QQ[i] using
isinstance
. In the case of the parent class, this is convenient when specifying coercions, for instance.
Anyway this will be instantiated at startup so why not keeping one instance QQi
in sage.rings.number_field.number_field
? (like we have for ZZ
, QQ
, etc). Then you can test identity when testing coercions.
comment:14 in reply to: ↑ 13 ; followup: ↓ 16 Changed 4 years ago by
Replying to vdelecroix:
Anyway this will be instantiated at startup so why not keeping one instance
QQi
insage.rings.number_field.number_field
? (like we have forZZ
,
If I remember right, currently, just adding QQi = ...()
in the module currently doesn't work due to import order constraints. For now I just kept the creation of QQ[i] happening at the same time as it used to. But that's certainly something we should try to improve after this first draft.
Then you can test identity when testing coercions.
Yes. Having a separate class would also be natural if we want I.parent()
to display something less frightening than “Number Field in I
with defining polynomial x^2 + 1
”, and more generally to implement features specific to QQ[i]. But I can't really think of anything that makes sense for this field and not for embedded quadratic number fields in general, so perhaps it is better to encourage people to always implement a more general version?
A related question is whether QQi is NumberField(x^2+1, 'I', embedding=CC.0)
should be true, or if there should be two separate parents.
What do you think?
comment:15 Changed 4 years ago by
 Summary changed from I should not be symbolic to I.parent() should not be the symbolic ring
comment:16 in reply to: ↑ 14 ; followup: ↓ 17 Changed 4 years ago by
Replying to mmezzarobba:
Replying to vdelecroix:
Anyway this will be instantiated at startup so why not keeping one instance
QQi
insage.rings.number_field.number_field
? (like we have forZZ
,If I remember right, currently, just adding
QQi = ...()
in the module currently doesn't work due to import order constraints. For now I just kept the creation of QQ[i] happening at the same time as it used to. But that's certainly something we should try to improve after this first draft.
Here we can probably cheat with
_QQi = None def NumberFieldQQi(): if _QQi is None: # build it once for all ... return _QQi
Then you can test identity when testing coercions.
Yes. Having a separate class would also be natural if we want
I.parent()
to display something less frightening than “Number Field inI
with defining polynomialx^2 + 1
”, and more generally to implement features specific to QQ[i]. But I can't really think of anything that makes sense for this field and not for embedded quadratic number fields in general, so perhaps it is better to encourage people to always implement a more general version?
Yes! Having a custom representation should be done in the main class. It is already possible:
sage: K = QuadraticField(2) sage: K.rename('It's me') sage: K It's me sage: K.rename(None) sage: K Number Field in a with defining polynomial x^2  2
A related question is whether
QQi is NumberField(x^2+1, 'I', embedding=CC.0)
should be true, or if there should be two separate parents.What do you think?
More generally, do we want unique representation for (absolute) number fields? I would tend to say yes. And the natural keys would be:
 the polynomial
 the variable name (not of the polynomial!)
 the embedding
Vincent
comment:17 in reply to: ↑ 16 ; followup: ↓ 18 Changed 4 years ago by
Replying to vdelecroix:
Yes! Having a custom representation should be done in the main class. It is already possible:
If all we want is a different string representation, yes, perhaps it makes sense to use rename()
...
A related question is whether
QQi is NumberField(x^2+1, 'I', embedding=CC.0)
should be true, or if there should be two separate parents.What do you think?
More generally, do we want unique representation for (absolute) number fields?
I think everyone agrees that absolute number fields should have unique representation. My question was whether Q[i] should be an absolute number field in this sense, or if it should be a “special” object such that people could work with both Q[i]asasubsetofcomplexnumbers and Q[i]asanumber field, possibly at the same time. I'd prefer a single object as well, but I am sure I have missed some of the implications, so if anyone has arguments in favor of the other option, I would be interested in hearing them.
comment:18 in reply to: ↑ 17 ; followup: ↓ 20 Changed 4 years ago by
Replying to mmezzarobba:
A related question is whether
QQi is NumberField(x^2+1, 'I', embedding=CC.0)
should be true, or if there should be two separate parents.What do you think?
More generally, do we want unique representation for (absolute) number fields?
I think everyone agrees that absolute number fields should have unique representation. My question was whether Q[i] should be an absolute number field in this sense, or if it should be a “special” object such that people could work with both Q[i]asasubsetofcomplexnumbers and Q[i]asanumber field, possibly at the same time. I'd prefer a single object as well, but I am sure I have missed some of the implications, so if anyone has arguments in favor of the other option, I would be interested in hearing them.
I would be interested in working with any number field seeing them as a subfield of the real or complex numbers! Not only QQi
and it makes sense to ask whether we need a dedicated class for that. For both parent and elements.
Note that it is already partly possible to play with element of number fields as real numbers (especially with quadratic fields)
sage: K.<sqrt2> = QuadraticField(2) sage: 1 < sqrt2 < 3/2 True sage: sqrt2.n() 1.41421356237310 sage: sqrt2 + CC(0,1) 1.41421356237310 + 1.00000000000000*I sage: sage: cos(sqrt2) cos(sqrt(2)) sage: sqrt2.continued_fraction() [1; (2)*]
About having methods .cos()
, .sin()
, .exp()
, it is already something which I found dangerous with integers for which the method .sqrt()
might return an answer with a different parent
sage: 4.sqrt() # answer is a Sage integer 2 sage: 2.sqrt() # answer is symbolic sqrt(2)
Which is very different from
sage: R.<x> = ZZ[] sage: ((x+1)**2 * (x2)**4).sqrt() x^3  3*x^2 + 4 sage: R(2).sqrt() Traceback (most recent call last): ... TypeError: Polynomial is not a square. You must specify the name of the square root when using the default extend = True
At the time Sage would support embedding of number fields into padic fields, I think it might be worse to have that dedicated class! But in the meantime, I have no strong opinion.
Vincent
comment:19 Changed 4 years ago by
comment:20 in reply to: ↑ 18 Changed 4 years ago by
Replying to vdelecroix:
About having methods
.cos()
,.sin()
,.exp()
, it is already something which I found dangerous with integers
Still, if we ever want this new nonsymbolic I
to behave like to old symbolic I
, we would need to support things like that:
********************************************************************** File "src/sage/symbolic/expression.pyx", line 7901, in sage.symbolic.expression.Expression.log Failed example: I.log() Exception raised: Traceback (most recent call last): File "/usr/local/src/sagegit/local/lib/python2.7/sitepackages/sage/doctest/forker.py", line 496, in _run self.compile_and_execute(example, compiler, test.globs) File "/usr/local/src/sagegit/local/lib/python2.7/sitepackages/sage/doctest/forker.py", line 858, in compile_and_execute exec(compiled, globs) File "<doctest sage.symbolic.expression.Expression.log[11]>", line 1, in <module> I.log() File "sage/structure/element.pyx", line 420, in sage.structure.element.Element.__getattr__ (build/cythonized/sage/structure/element.c:4676) return getattr_from_other_class(self, P._abstract_element_class, name) File "sage/structure/misc.pyx", line 259, in sage.structure.misc.getattr_from_other_class (build/cythonized/sage/structure/misc.c:1772) raise dummy_attribute_error AttributeError: 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic' object has no attribute 'log' **********************************************************************
comment:21 Changed 4 years ago by
 Branch set to u/jdemeyer/i_parent___should_not_be_the_symbolic_ring
comment:22 Changed 3 years ago by
 Cc behackl added
 Commit set to 2f5a5198849c5b96bc2733e1e5853dc1b23f1cf9
New commits:
2f5a519  parent(I) should be a number field

comment:23 Changed 3 years ago by
 Cc rws added
comment:24 followups: ↓ 25 ↓ 26 Changed 3 years ago by
Hi! I'd like to revive this discussion a bit because we're getting a doctest failure at https://github.com/pynac/pynac/pull/162 which would probably be fixed along the lines of this ticket.
For starters, I had a look at the current branch and some of the resulting doctest failures; this should roughly resemble the tasks that are still to be done:
sage t warnlong 54.2 src/sage/symbolic/constants.py # 3 doctests failed
;
sage t warnlong 54.2 src/sage/symbolic/pynac.pyx # 3 doctests failed
:
duplicate doctests. not sure how to fix (maybe switch to I_symbolic?). and which to remove.
sage t warnlong 54.2 src/sage/symbolic/relation.py # 3 doctests failed
:
Doctests can be fixed directly.
sage t warnlong 54.2 src/sage/symbolic/expression_conversions.py # 2 doctests failed
probably I_symbolic is needed?
sage t warnlong 54.2 src/sage/symbolic/expression.pyx # 14 doctests failed
 arithmetic with
oo
is broken (4 doctests) 
_is_registered_constant_
> remove doctest? I_symbolic? 
is_numeric
/is_constant
missing (I_symbolic?) 
imag_part
/real_part
should be an alias ofimag
/real
(3 doctests) 
I.log
not implemented (3 doctests) rectform
: either converse to SR or multiply with I_symbolic.
 arithmetic with
sage t warnlong 54.2 src/sage/rings/infinity.py # 2 doctests failed
arithmetic with
oo
is broken.
sage t warnlong 54.2 src/sage/rings/complex_mpc.pyx # 8 doctests failed
andsage t warnlong 54.2 src/sage/rings/complex_arb.pyx # 7 doctests failed
 coercion errors:
ValueError: Cannot coerce algebraic number with nonzero imaginary part to algebraic real
 precision regressions.
 coercion errors:
sage t warnlong 54.2 src/sage/rings/qqbar.py # 6 doctests failed
common parent issue:
TypeError: unsupported operand parent(s) for '+': 'Algebraic Field' and 'Number Field in I with defining polynomial x^2 + 1'
sage t warnlong 54.2 src/sage/rings/number_field/number_field_element_quadratic.pyx # 1 doctest failed
common parent issue:
TypeError: unsupported operand parent(s) for '*': 'Number Field in I with defining polynomial x^2 + 1' and 'Number Field in sqrt3 with defining polynomial x^2  3'
sage t warnlong 54.2 src/sage/rings/polynomial/polynomial_rational_flint.pyx # 1 doctest failed
false error is raised
sage t warnlong 54.2 src/sage/rings/polynomial/cyclotomic.pyx # 2 doctests failed
both can be fixed directly.
 Stuff in
sage/geometry/hyperbolic_space/hyperbolic_*.py
breaks down:sage t warnlong 51.1 src/sage/geometry/hyperbolic_space/hyperbolic_point.py # 1 doctest failed
sage t warnlong 51.1 src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py # 4 doctests failed
sage t warnlong 51.1 src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py # 1 doctest failed
sage t warnlong 51.1 src/sage/geometry/hyperbolic_space/hyperbolic_model.py # 2 doctests failed
Not sure about these errors, some seem to be coercion related, others are just
TypeError: 'sage.rings.complex_number.ComplexNumber' object is not callable
maybe that goes away along the way.
These are certainly not all failures, but they should give an idea of what breaks down. The biggest issue seems to be coercion...
comment:25 in reply to: ↑ 24 Changed 3 years ago by
comment:26 in reply to: ↑ 24 Changed 3 years ago by
Replying to behackl:
sage t warnlong 54.2 src/sage/rings/infinity.py # 2 doctests failed
arithmetic with
oo
is broken.
It's just missing coercion of number field elements into the infinity ring. It would give a SignError
anyway.
comment:27 followup: ↓ 28 Changed 3 years ago by
Would
A = GaussianIntegers() A(1+I)
work with this branch?
comment:28 in reply to: ↑ 27 Changed 3 years ago by
Replying to kcrisman:
sage: A = GaussianIntegers() sage: A(1+I) I + 1 sage: type(_) <type 'sage.rings.number_field.number_field_element_quadratic.OrderElement_quadratic'>
comment:29 Changed 3 years ago by
Thanks! That is definitely a motivation for me to review this next week ... any sense on whether the various doctest failures are "real", as opposed to just fixes like comment:26?
comment:30 Changed 3 years ago by
What's a "real" doctest failure? Some features of SR
simply are not supported for number field elements.
comment:31 followups: ↓ 32 ↓ 33 Changed 3 years ago by
So, we must have two different I
s.
This interface duplication creates a similar problems to the one with pos.char. elements (either ring elements or symbolic Mod
). I think what's most understandable to the user would be a switch that prevents mixing and whose value is clearly visible on startup like symbolic I mode is ON
. I know this goes against the no globals rules but I predict no one will accept having to input symbolic_I
, and we will get hell for that.
comment:32 in reply to: ↑ 31 Changed 3 years ago by
Replying to rws:
So, we must have two different
I
s.
I've lost track what the exact issues are that lead to that conclusion, but I would definitely prefer if we don't do that. I think we can avoid it for the following reason:
Sage itself needs *many* different I's. For one thing, every ComplexField(b)
needs its own. We'd like coercion to take care of creating the many different I's. I guess we're now finding it's difficult to find a parent that coerces into sufficiently many complex parents.
If that is the case, perhaps we should solve the problem by just having a LiteralI
, just as we have RealLiteral
to avoid the precision coercion problems that arise with floats. The advantage is that its coercion properties can be tailored exactly to what we need (within the bounds of what coercion can handle in the first place)
It doesn't surprise me that I is problematic that way. It is, after all, an object that represents multiple values.
comment:33 in reply to: ↑ 31 ; followup: ↓ 34 Changed 3 years ago by
Replying to rws:
So, we must have two different
I
s.
We really should not do that. Ideally, I
should be some number field element but which allows the appropriate symbolic operations.
comment:34 in reply to: ↑ 33 Changed 3 years ago by
Replying to jdemeyer:
Ideally,
I
should be some number field element but which allows the appropriate symbolic operations.
Well, if the operation's name is a registered function , convert to symbolic, apply, convert back?
comment:35 Changed 3 years ago by
See also #22208.
comment:36 Changed 3 years ago by
 Branch changed from u/jdemeyer/i_parent___should_not_be_the_symbolic_ring to public/18036
comment:37 Changed 18 months ago by
 Commit changed from 2f5a5198849c5b96bc2733e1e5853dc1b23f1cf9 to d7fab0b6a8628301543ed7bfae70380e1d6fa714
Branch pushed to git repo; I updated commit sha1. New commits:
d7fab0b  Merge branch 'develop' into t/18036/public/18036

I'm not so sure it should. Which quadratic field is the appropriate one? There are many, distinguishable by the name of their generator (that would be 'I') for this one, but also by their specified embeddings, and it's not clear which one to choose.
Is there an argument for doing this? Ticket #17860 referenced in the description makes no mention of it. I'd imagine there might be evaluation reasons that might make it attractive. Perhaps those also give an indication of which quadratic field would be the appropriate one.