sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.43k stars 478 forks source link

classes for the fields of complex and real numbers #24456

Open videlec opened 6 years ago

videlec commented 6 years ago

We create (mostly abstract) classes to model the set of complex and real numbers as sage.rings.complex_field.ComplexField and sage.rings.real_field.RealField.

See also task ticket #17713.

Use cases for this new "real field" object:

  1. As some placeholder object to denote the field of real numbers, for example as output of QQ.completion(oo), for domain/codomain of symbolic functions, in manifolds, etc. This implies that it should be a unique object.

  2. As a Sage analogy to PEP 3141: it should provide a way to ask "is x a real number" or "is X a substructure of the reals" or maybe "does parent X represent the real numbers". Also, we should be able to ask "is x an exact or approximate real number". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).

  3. As a class factory for all concrete real fields (e.g. the create_RealField function that is currently used for non-exact approximations).

Depends on #24464 Depends on #24465 Depends on #24483 Depends on #24457

CC: @rwst @tscrim @egourgoulhon @mjungmath

Component: basic arithmetic

Work Issues: merge conflict

Author: Vincent Delecroix

Branch/Commit: u/rws/24456 @ febfe35

Issue created by migration from https://trac.sagemath.org/ticket/24456

tscrim commented 6 years ago
comment:2

+1

videlec commented 6 years ago
comment:3

:-) pushing in a minute...

videlec commented 6 years ago

Author: Vincent Delecroix

videlec commented 6 years ago

Description changed:

--- 
+++ 
@@ -1 +1,9 @@
 We create a (mostly abstract) class to model the set of real numbers.
+
+We also fix
+
+```
+sage: ZZ.completion(oo, 53)
+Real Field with 53 bits of precision
+```
+as `ZZ` is complete (for the usual absolute value)!
videlec commented 6 years ago

Commit: 78f677e

videlec commented 6 years ago

New commits:

78f677e24456: class for the field of real numbers
videlec commented 6 years ago

Branch: u/vdelecroix/24456

videlec commented 6 years ago

Description changed:

--- 
+++ 
@@ -7,3 +7,7 @@
 Real Field with 53 bits of precision

as ZZ is complete (for the usual absolute value)! + +follow-ups: +- #24457: rename sage.rings.real_mpfr.RealField +- #24458: a useful real lazy field

7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 6 years ago

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:

62d2d2124456: class for the field of real numbers
7ed8c4ca-6d56-4ae9-953a-41e42b4ed313 commented 6 years ago

Changed commit from 78f677e to 62d2d21

rwst commented 6 years ago
comment:10

For me this looks fine (I can now create the object and use it in formal expressions) and patchbot is green. If you think this is not enough for a review then please set back to "needs review".

rwst commented 6 years ago
comment:12

Thanks. I also had a question turning up while working on #24457. The code here does not support RealField(prec) anymore---the init method only has self argument, is this intended? Since real_mpfr.RealField() will be renamed should create_RealField(prec) be used everywhere instead?

videlec commented 6 years ago
comment:13

Replying to @rwst:

Thanks. I also had a question turning up while working on #24457. The code here does not support RealField(prec) anymore---the init method only has self argument, is this intended?

It is intended: the field of real number is the field of real number (see e.g. wikipedia). The code provided in the branch u/vdelecroix/24456 is new, so it never used to support anything.

Since real_mpfr.RealField() will be renamed should create_RealField(prec) be used everywhere instead?

No. create_RealField is a convenience to handle options for the completion functor. There is no reason to use it directly.

The real_field.RealField in this branch has (almost) nothing to do with real_mpfr.RealField.

tscrim commented 6 years ago
comment:14

Some comments:

jdemeyer commented 6 years ago
comment:15

I don't quite understand the purpose of this new RealField. Maybe it would be good to elaborate on that.

Why is this thing a Parent? Given that it doesn't have Elements (in the Sage sense), it probably should be a CategoryObject and not a Parent.

rwst commented 6 years ago
comment:18

Replying to @jdemeyer:

I don't quite understand the purpose of this new RealField. Maybe it would be good to elaborate on that.

24171 depends on this.

jdemeyer commented 6 years ago
comment:19

OK, I sort of see where this is going. But it doesn't explain why it is a Parent.

videlec commented 6 years ago

Dependencies: #24464, #24465

videlec commented 6 years ago

Description changed:

--- 
+++ 
@@ -1,12 +1,4 @@
 We create a (mostly abstract) class to model the set of real numbers.
-
-We also fix
-
-```
-sage: ZZ.completion(oo, 53)
-Real Field with 53 bits of precision
-```
-as `ZZ` is complete (for the usual absolute value)!

 follow-ups:
 - #24457: rename `sage.rings.real_mpfr.RealField`
videlec commented 6 years ago
comment:20

I am fine making it a CategoryObject with category Fields().Infinite().

tscrim commented 6 years ago
comment:21

This is initialized as a facade parent, so it should not have an Element class.

jdemeyer commented 6 years ago
comment:22

Replying to @tscrim:

This is initialized as a facade parent

Why? As I said above, I don't see why this should be a Parent in the first place.

Also, it would be good to replace the coerce_map_from method by a real PEP 3119 check like

sage: R = RealField()  # abstract real numbers
sage: issubclass(RR, R)
True

Is that in line with what you have in mind?

videlec commented 6 years ago
comment:23

Replying to @jdemeyer:

Replying to @tscrim:

This is initialized as a facade parent

Why? As I said above, I don't see why this should be a Parent in the first place.

Also, it would be good to replace the coerce_map_from method by a real PEP 3119 check like

sage: R = RealField()  # abstract real numbers
sage: issubclass(RR, R)
True

Is that in line with what you have in mind?

This is the kind of purposes I want this class for. RealField() should know about all ways of modelling concretely real numbers in Sage (but how?) and it should be possible to query it about real number questions, like the example you mentioned (but how?). The main problem I have is how to handle the distinction between exact subrings (e.g. QQ) versus approximations (e.g. RDF).

Note that in your example we might also want to make the following works

sage: import numbers
sage: isinstance(RR.element_class, numbers.Real)
jdemeyer commented 6 years ago
comment:24

Replying to @videlec:

This is the kind of purposes I want this class for.

Excellent! A big +1 from me.

jdemeyer commented 6 years ago
comment:25

Replying to @videlec:

sage: import numbers
sage: isinstance(RR.element_class, numbers.Real)

This already works except for the fact that RR doesn't have an element_class attribute:

sage: import numbers
sage: isinstance(RR.an_element(), numbers.Real)
True

But I'd really like it to work on the parent since it's the parent which models the real numbers. Also, the coercion framework mostly works with parents, so this could be useful there too.

egourgoulhon commented 6 years ago
comment:27

It would be nice if this could serve as the base field for real manifolds. For the moment we have:

sage: M = Manifold(3, 'M', field='real'); M
3-dimensional differentiable manifold M
sage: M.base_field()
Real Field with 53 bits of precision
sage: M.base_field() is RR
True

which is a bit awkward, since all subsequent calculus on M has nothing to do with RR. Actually RR is used as a proxy for the field of real numbers, so it would be very nice to replace it by something closer to the actual field of real numbers, as the new RealField proposed here (as far as I understand).

edd8e884-f507-429a-b577-5d554626c0fe commented 6 years ago
comment:28

Sorry for being mute, i did not have time to write something when i put this ticket back on needs-review, but i did not want it to be merged that way. Blitzkrieg is not the way, there have been too much projects within Sage dying because of a lack of consensus, and i do not want the idea of a "genuine" real field to end like this.

Of course i am in favor of having such an abstraction and i am happy that some people support this as well, however when i promoted such an idea in various sage days, tutorials, discussions, tickets, it was clear from that experience that there was no consensus about that question, at all.

Hence, i think that a collectively approved decision on such subject should happen before code. For example, the proposed branch implies behaviors such as (random undocumented examples):

sage: R = QQ.completion(infinity, infinity) ; R
Real Field

sage: QQbar(sqrt(2)).parent()
Algebraic Field
sage: R(QQbar(sqrt(2))).parent()
Algebraic Real Field

sage: QQbar(sqrt(1)).parent()
Algebraic Field
sage: R(QQbar(sqrt(1))).parent()
Rational Field

sage: 0.1 in R
False

sage: R(RDF(0.1))
1/10

sage: R(pi)
ValueError: Can't coerce `pi` in any parent `Real Field` is a facade for

sage: R(ZZ(1)).parent()
Rational Field

Which behavior do we want for this ? Which interplay with existing representations of real numbers ? What are the implications in the whole Sage ? How do we ensure a smooth transition from the current ill-named RR and a genuine RR corresponding to the field of real numbers ? Since real numbers are everywhere, we should think about the consequences before being tied with wrong design and the imperative of backward compatibility.

All this to say that we need to have a plan with a boarder view, on which the community agrees.

Note that Ralf opened a ticket on that subject, and since ticket #17713 already has some debates on this subject and a similar purpose, let me suggest to continue the discussion there (so that we collect every input in a single place), and make it a task with appropriate subtickets once we reach a consensus.

rwst commented 6 years ago
comment:29

The depending ticket #24171 could work with numbers.* as well, as the objects are used only internally.

rwst commented 6 years ago
comment:30

Replying to @rwst:

The depending ticket #24171 could work with numbers.* as well, as the objects are used only internally.

Ah no, the numbers classes are abstract, sorry.

videlec commented 6 years ago
comment:31

Replying to @sagetrac-tmonteil:

For example, the proposed branch implies behaviors such as (random undocumented examples):

The current RealField as it is in the branch is a facade. Which means that it does not have any element of its own. The sets for which it is a facade are concrete subrings/subfields of the set of real numbers. In the current branch it is only QQ and AA. Beyond adding more subrings/subfields, I don't see how it could be otherwise.

All the examples you mention come from the way _element_constructor_ is designed for facade sets. For each set for which it is a facade the element constructor tries a conversion to this set. The behavior might be wrong, I am just explaining the mechanic.

sage: QQbar(sqrt(2)).parent() Algebraic Field sage: R(QQbar(sqrt(2))).parent() Algebraic Real Field

This is because AA(QQbar(sqrt(2))) is the first to succeed (QQ(QQbar(sqrt(2))) does not).

sage: QQbar(sqrt(1)).parent() Algebraic Field sage: R(QQbar(sqrt(1))).parent() Rational Field

This is because QQ(QQbar(sqrt(1))) does succeed.

sage: 0.1 in R False

As it should be!

sage: R(RDF(0.1)) 1/10

Because QQ(RDF(0.1)) works that way.

sage: R(pi) ValueError: Can't coerce pi in any parent Real Field is a facade for

Because there is not yet any subset of the real numbers handling pi. As soon as there is one, it should be added to the facades and the above will work.

sage: R(ZZ(1)).parent() Rational Field

This is because QQ(ZZ(1)) is the first to succeed (we might add ZZ to the list of facades).

Which behavior do we want for this?

For me, the current behavior of element construction is close to what it should be. To make things smoother, we might want to modify the QQbar -> QQ to a QQbar -> AA. This can be achieved by using a friend complex field on which we could call .real(). More precisely

def _element_constructor_(self, x):
    if parent(x) in self.facade_for():
        return x

    CC = ComplexField()   # the genuine one of course
    try:
        z = CC(x)
    except (ValueError,TypeError):
        pass
    else:
        if z.is_real():   # does not currently work for QQbar
            return z.real()

    raise ValueError("x not recognized as a real number")

Which interplay with existing representations of real numbers?

This is precisely the question in [comment:23] that you are not helping with by asking it again.

What are the implications in the whole Sage?

Just new features. To be able to do

How do we ensure a smooth transition from the current ill-named RR and a genuine RR corresponding to the field of real numbers?

This question is beyond the scope of this ticket. But see #24457.

Since real numbers are everywhere, we should think about the consequences before being tied with wrong design and the imperative of backward compatibility.

All this to say that we need to have a plan with a boarder view, on which the community agrees.

Note that Ralf opened a ticket on that subject, and since ticket #17713 already has some debates on this subject and a similar purpose, let me suggest to continue the discussion there (so that we collect every input in a single place), and make it a task with appropriate subtickets once we reach a consensus.

To balance, let me add that ticket #17713 was opened 3 years ago, contains three messages and no concrete proposal. It refers to another ticket #15944 that was untouched during 4 years. This ticket on the other hand, started with a concrete proposal and 4 people expressed their opinions. I am about to propose a new version taking into account all comments. We are also not likely to merge it soon as the discussion is going on.

Tickets are also dying because of absence of action. Status-quo is not the way to go either.

videlec commented 6 years ago

Description changed:

--- 
+++ 
@@ -1,5 +1,7 @@
-We create a (mostly abstract) class to model the set of real numbers.
+We create (mostly abstract) classes to model the set of complex and real numbers.

 follow-ups:
 - #24457: rename `sage.rings.real_mpfr.RealField`
 - #24458: a useful real lazy field
+
+See also task ticket #17713.
videlec commented 6 years ago

Changed dependencies from #24464, #24465 to #24464, #24465, #24483

jdemeyer commented 6 years ago
comment:33

Replying to @sagetrac-tmonteil:

sage: R(QQbar(sqrt(2))).parent()
Algebraic Real Field

sage: R(QQbar(sqrt(1))).parent()
Rational Field

sage: R(RDF(0.1))
1/10

sage: R(pi)
ValueError: Can't coerce `pi` in any parent `Real Field` is a facade for

sage: R(ZZ(1)).parent()
Rational Field

All of these could be fixed by simply not letting R be a Parent and disallowing R(anything). As I said in some comments above, I don't see why R should be a Parent (facade or not).

jdemeyer commented 6 years ago
comment:34

Replying to @videlec:

sage: 0.1 in R
False

As it should be!

If you think that 0.1 should not be contained in the field of real numbers, you'll need to justify that better. For me, it is obvious that 0.1 is a real number, such that 0.1 in R must be True.

jdemeyer commented 6 years ago
comment:35

Replying to @sagetrac-tmonteil:

Hence, i think that a collectively approved decision on such subject should happen before code.

+1

It is clear that people support the idea of having a true "real field" object in Sage. However, it is not clear at all what kind of object this should be and how it should be used.

jdemeyer commented 6 years ago
comment:36

Maybe we should start by thinking about possible use cases for this "real field":

  1. As some placeholder object to denote the field of real numbers, for example as output of QQ.completion(oo). This implies that it should be a unique object.

  2. As a Sage analogy to PEP 3141: it should provide a way to ask "is x a real number" or "is X a substructure of the reals" or maybe "does parent X represent the real numbers". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).

videlec commented 6 years ago

Changed dependencies from #24464, #24465, #24483 to #24464, #24465, #24483, #24457

videlec commented 6 years ago

Description changed:

--- 
+++ 
@@ -1,7 +1,3 @@
-We create (mostly abstract) classes to model the set of complex and real numbers.
-
-follow-ups:
-- #24457: rename `sage.rings.real_mpfr.RealField`
-- #24458: a useful real lazy field
+We create (mostly abstract) classes to model the set of complex and real numbers as `sage.rings.complex_field.ComplexField` and `sage.rings.real_field.RealField`.

 See also task ticket #17713.
videlec commented 6 years ago
comment:39

Replying to @jdemeyer:

Maybe we should start by thinking about possible use cases for this "real field":

  1. As some placeholder object to denote the field of real numbers, for example as output of QQ.completion(oo). This implies that it should be a unique object.

Agreed.

  1. As a Sage analogy to PEP 3141: it should provide a way to ask "is x a real number" or "is X a substructure of the reals" or maybe "does parent X represent the real numbers". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).

I want to be able distinguish between exact subrings and non-exact approximations. This is for coercion reasons: each exact subring coerces into all non-exact approximations. This is also why I claimed that 0.1 in R should be False.

Let me add

  1. As a way to check for is x an exact real number? and is x a non-exact real number?. We should specify clearly that isinstance(x, numbers.Real) means exact real or non-exact real (I take that as given because both issubclass(int, numbers.Real) and issubclass(float, numbers.Real) are True).

  2. As a pointers to all real field implementations (exact subrings and non-exact approximations). In particular it should contain a class factory for all concrete real fields (e.g. the create_RealField function that is currently used for non-exact approximations).

tscrim commented 6 years ago
comment:40

If you want to ask about exact reals, you should have a 2', where you have a subclass of generic all reals class for the exact reals.

videlec commented 6 years ago
comment:41

Concerning approximations (like floating point numbers), there are often the three special values NaN, +inf and -inf which are not real numbers (in the mathematical sense). For -inf and +inf one can still argue that they approximate very negative and very positive reals. But NaN is not an approximation of anything. This is one more argument for having RealField() to mean exact real numbers.

On the other hand, Python numbers.Real means both floating and exact. Having different semantic for RealField() and numbers.Real might be disturbing.

jdemeyer commented 6 years ago
comment:42

Replying to @videlec:

This is also why I claimed that 0.1 in R should be False.

I still don't get this. Please elaborate...

jdemeyer commented 6 years ago

Description changed:

--- 
+++ 
@@ -1,3 +1,11 @@
 We create (mostly abstract) classes to model the set of complex and real numbers as `sage.rings.complex_field.ComplexField` and `sage.rings.real_field.RealField`.

 See also task ticket #17713.
+
+Use cases for this new "real field" object:
+
+1. As some placeholder object to denote the field of real numbers, for example as output of `QQ.completion(oo)`. This implies that it should be a unique object.
+
+2. As a Sage analogy to [PEP 3141](https://www.python.org/dev/peps/pep-3141/): it should provide a way to ask "is `x` a real number" or "is `X` a substructure of the reals" or maybe "does parent `X` represent the real numbers". Also, we should be able to ask "is `x` an *exact* or *approximate* real number". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).
+
+3. As a pointers to all real field implementations (exact subrings and non-exact approximations). In particular it [what ???] should contain a class factory for all concrete real fields (e.g. the `create_RealField` function that is currently used for non-exact approximations).
jdemeyer commented 6 years ago
comment:44

Replying to @videlec:

  1. As a pointers to all real field implementations (exact subrings and non-exact approximations). In particular it should contain a class factory for all concrete real fields (e.g. the create_RealField function that is currently used for non-exact approximations).

What is the it in this last sentence?

videlec commented 6 years ago
comment:45

Replying to @jdemeyer:

Replying to @videlec:

This is also why I claimed that 0.1 in R should be False.

I still don't get this. Please elaborate...

For me RealField means the field of real numbers in the mathematical sense together with its exact operations +, -, log, exp, etc. Floating-point numbers do not respect exactness of operations and for me do not qualify as being real numbers. I agree that you can think of a floating point number in two ways. As an approximation of a real number "m ± 2-e" or as a diadic number "p 2-n". The latter is the actual datastructure but it is mostly useless to think of it this way when doing mathematics. This is moreover how it works in Sage: QQ coerces into RealField(prec) and not the contrary even though RealField(prec) is formally a subset of QQ.

videlec commented 6 years ago
comment:46

Replying to @jdemeyer:

Replying to @videlec:

  1. As a pointers to all real field implementations (exact subrings and non-exact approximations). In particular it should contain a class factory for all concrete real fields (e.g. the create_RealField function that is currently used for non-exact approximations).

What is the it in this last sentence?

I meant the genuine real field that we are trying to design.

jdemeyer commented 6 years ago
comment:47

Replying to @videlec:

I meant the genuine real field that we are trying to design.

OK, so what would it mean for a Python object (representing the real field) to "contain a class factory"? Do you want something like

sage: R = RealField()
sage: R.create(prec=53, implementation="mpfr")
Real Floating-point field with 53 bits of precision

or maybe

sage: R = RealField()
sage: R(prec=53, implementation="mpfr")
Real Floating-point field with 53 bits of precision
jdemeyer commented 6 years ago

Description changed:

--- 
+++ 
@@ -8,4 +8,4 @@

 2. As a Sage analogy to [PEP 3141](https://www.python.org/dev/peps/pep-3141/): it should provide a way to ask "is `x` a real number" or "is `X` a substructure of the reals" or maybe "does parent `X` represent the real numbers". Also, we should be able to ask "is `x` an *exact* or *approximate* real number". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).

-3. As a pointers to all real field implementations (exact subrings and non-exact approximations). In particular it [what ???] should contain a class factory for all concrete real fields (e.g. the `create_RealField` function that is currently used for non-exact approximations).
+3. As a class factory for all concrete real fields (e.g. the `create_RealField` function that is currently used for non-exact approximations).
jdemeyer commented 6 years ago
comment:48

Replying to @videlec:

For me RealField means the field of real numbers in the mathematical sense together with its exact operations +, -, log, exp, etc. Floating-point numbers do not respect exactness of operations and for me do not qualify as being real numbers.

That point of view is technically mathematically true but also completely useless. Clearly, the real floating-point field is meant to model the real numbers. For technical reasons, the operations are not exact. But that is an implementation detail and not a mathematical property. For practical purposes, it behaves as a field.

I do agree that it makes sense to differentiate between exact real fields and approximate real fields, but both are real fields.

videlec commented 6 years ago
comment:49

Replying to @jdemeyer:

Replying to @videlec:

For me RealField means the field of real numbers in the mathematical sense together with its exact operations +, -, log, exp, etc. Floating-point numbers do not respect exactness of operations and for me do not qualify as being real numbers.

That point of view is technically mathematically true but also completely useless. Clearly, the real floating-point field is meant to model the real numbers.

Indeed!

For technical reasons, the operations are not exact. But that is an implementation detail and not a mathematical property. For practical purposes, it behaves as a field.

It is not associative! Equality dramatically fails! This is not a detail.

I do agree that it makes sense to differentiate between exact real fields and approximate real fields, but both are real fields.

I also agree and IMHO, for consistency with numbers.Real, the genuine RealField should be both used for approximate (= projection) and exact (= subset). And this should be very clearly stated.