Registering NumberField as numbers.Number

58 views
Skip to first unread message

jonatha...@googlemail.com

unread,
Jul 15, 2021, 6:38:59 AM7/15/21
to sage-devel
Hi, I was looking into typing a bit and realized that our number field elements are not registered as numbers. So the following will not evaluate to true:

sage: import numbers
sage: K.<a> = QuadraticField(2)
sage: isinstance(a, numbers.Number)

Is there a reason, we do not register number fields in `rings/numbers_abc.py`? Can I just change this?

E.g. I want to specify an iterable over numbers via `Iterable[numbers.Number]`, which would not include our number field elements currently.

Jonathan

Vincent Delecroix

unread,
Jul 15, 2021, 10:01:34 AM7/15/21
to sage-...@googlegroups.com
I don't think there is any deep reason. Sage started much before the
existence of the numbers Python module.

Note that the concept of "Number" is not clearly stated in the library.
Does it include finite fields? padics? polynomials (these can be seen
as infinitesimal deformation of scalars)?

Vincent

Nils Bruin

unread,
Jul 15, 2021, 12:06:10 PM7/15/21
to sage-devel
Taking a quick look at the relevant PEP https://www.python.org/dev/peps/pep-3141/ or the documentation https://docs.python.org/3/library/numbers.html#module-numbers (the PEP has considerably more detail), I get the impression that our Integer and Rational type could be incorporated in the hierarchy without problem, and possibly some benefit. We should just check it doesn't cause some inadvertent speed regression, and we should check that we're actually fully adhering to the contract API. Our real and complex numbers may well fit too. I'm not so sure p-adic would fit. I think incorporating them would make the tower hierarchy into a tree.  Same for number field elements (they would be exact, but you can't tell from the types whether they're real or complex).

It looks like Integer, Rational, RealNumber, ComplexNumber already are"Number"s.

From what I understand, an interesting feature of type annotations would be efficiency improvements. I have trouble seeing how something as general as "Number"s would lead to that. So before people start putting effort in extending the Number hierarchy with sage types, it's probably good to have some examples where it produces a tangible benefit.

Nils Bruin

unread,
Jul 15, 2021, 12:13:03 PM7/15/21
to sage-devel
Following up: while sage's "RationalNumber" is indeed a numbers.Rational according to "isinstance", it does not actually adhere to the stated API: "numerator" and "denominator" are supposed to be properties, but in sage they are methods. So even in places where we are trying to fit into "Number" we are already failing. Changing the way that "numerator" and "denominator" behave would break a *LOT* of sage code. I don't think we can do it.

William Stein

unread,
Jul 15, 2021, 2:06:09 PM7/15/21
to sage-devel
On Thu, Jul 15, 2021 at 9:13 AM Nils Bruin <nbr...@sfu.ca> wrote:
>
> Following up: while sage's "RationalNumber" is indeed a numbers.Rational according to "isinstance", it does not actually adhere to the stated API: "numerator" and "denominator" are supposed to be properties, but in sage they are methods. So even in places where we are trying to fit into "Number" we are already failing. Changing the way that "numerator" and "denominator" behave would break a *LOT* of sage code.

> I don't think we can do it.

Dumb question, but right now:

sage: n = 5
sage: n()
TypeError: 'sage.rings.integer.Integer' object is not callable

If we changed __call__ for integers to just return self, then maybe we
would have

sage: n = 5
sage: n()
5

and this would mean that if we implemented numerator and denominator
as properties, then

sage: a = 2/3
sage: a.numerator
2
sage: a.numerator()
2

would just work. Am I missing something?

It's 100% my fault that numerator and denominator are function calls
instead of properties. Here's why I made that choice, both for
rational numbers and for a lot of other things. The reason is that I
watched lots of grad students struggling to use Sage/Python around
2006 (e.g., at Arizona Winter School, in classes, etc.), and having
two different concepts -- methods *and* attributes -- with no easy way
to know which is which, just made things much more difficult for
people. People would do things like:

sage: A = matrix(...)
sage: A.det
<built-in method det of
sage.matrix.matrix_integer_dense.Matrix_integer_dense object at
0x7f7fca0c2ca0>

and be like "WTF?", and I would explain "A.det is a function. You
have to call it.", and they woud then do

sage: A.det()
number

and think "OK, sage makes sense." If basically at random half of the
things listed in tab completion needed parens after them and half
didn't, that would confuse the hell out of my poor potential users.
And with Sage there is really no clear way to decide whether or not
something should be a property or a method, since it's really a
function of "how hard is it to compute? are there different inputs to
computing it?" The answer to the second question is unknown when you
write the thing, e.g., an input could be the algorithm or whether
proof is True. The thing that really convinced me was that
"A.det?" would give help on a number (not the det function) in IPython
back then at least -- well definitely "help(A.det)" would "not work"
at all in a helpful way.

Please keep in mind that I made this choice over 15 years ago when
Sage had only a few users, and it would today have no users if I
hadn't made many design choices based on "what will confuse new users
less in 2005"...

-- William


--
William (http://wstein.org)

Vincent Delecroix

unread,
Jul 15, 2021, 2:14:07 PM7/15/21
to sage-...@googlegroups.com

William Stein

unread,
Jul 15, 2021, 3:12:02 PM7/15/21
to sage-devel
On Thu, Jul 15, 2021 at 11:05 AM William Stein <wst...@gmail.com> wrote:
>
> On Thu, Jul 15, 2021 at 9:13 AM Nils Bruin <nbr...@sfu.ca> wrote:
> >
> > Following up: while sage's "RationalNumber" is indeed a numbers.Rational according to "isinstance", it does not actually adhere to the stated API: "numerator" and "denominator" are supposed to be properties, but in sage they are methods. So even in places where we are trying to fit into "Number" we are already failing. Changing the way that "numerator" and "denominator" behave would break a *LOT* of sage code.
>
> > I don't think we can do it.
>
> Dumb question, but right now:

In particular, thanks to Vincent Delecroix for pointing out that the
answer is here

https://trac.sagemath.org/ticket/28234#comment:7

In particular, @mcbell implemented exactly this for Sage over two
years ago, and there is extensive discussion there about what happens.
It's pretty crazy, e.g., "This now makes [instances of] the Sage
Integer class callable and it appears that there are doctest that
determine whether an object is an integer or not by testing whether it
is callable!"

William
--
William (http://wstein.org)

TB

unread,
Jul 15, 2021, 5:58:45 PM7/15/21
to sage-...@googlegroups.com
On 15/07/2021 22:11, William Stein wrote:
> On Thu, Jul 15, 2021 at 11:05 AM William Stein <wst...@gmail.com> wrote:
>>
>> On Thu, Jul 15, 2021 at 9:13 AM Nils Bruin <nbr...@sfu.ca> wrote:
>>>
>>> Following up: while sage's "RationalNumber" is indeed a numbers.Rational according to "isinstance", it does not actually adhere to the stated API: "numerator" and "denominator" are supposed to be properties, but in sage they are methods. So even in places where we are trying to fit into "Number" we are already failing. Changing the way that "numerator" and "denominator" behave would break a *LOT* of sage code.
>>
For one more attempt by Jeroen Demeyer at solving this issue, please see
https://discuss.python.org/t/pep-3141-ratio-instead-of-numerator-denominator/2037
I find the history of this topic quiet interesting.

Using methods for all public API of Sage still seems to me as the better
choice. The reasons given above for this (no need to guess if
parentheses are required and the expectation that properties are very
efficient) are still relevant today.

In addition, it is possible that in the future numerator/denominator
might get new arguments (e.g. reduce, canonicalize, or normalize as in
SR). One more reason is that the numerator/denominator methods are used
for more complicated mathematical objects in Sage, where calling them
with arguments is sensible. In the python-ideas discussion Vincent
Delecroix mentions that also real and imag methods/properties have the
same problem, like calling `1j.real` in Sage compared to Python.

Regards,
TB

jonatha...@googlemail.com

unread,
Jul 16, 2021, 4:04:33 AM7/16/21
to sage-devel
Thanks for the answers.

I didn't realize this whole issue was this involved. It's certainly interesting.

For now I think there is nothing wrong with registering `NumberFieldElement` as `numbers.Numbers`, see https://trac.sagemath.org/ticket/32206.

Jonathan
Reply all
Reply to author
Forward
0 new messages