Opened 5 years ago
Last modified 2 years ago
#24456 needs_work enhancement
classes for the fields of complex and real numbers
Reported by:  Vincent Delecroix  Owned by:  

Priority:  major  Milestone:  sage8.2 
Component:  basic arithmetic  Keywords:  
Cc:  Ralf Stephan, Travis Scrimshaw, Eric Gourgoulhon, Michael Jung  Merged in:  
Authors:  Vincent Delecroix  Reviewers:  
Report Upstream:  N/A  Work issues:  merge conflict 
Branch:  u/rws/24456 (Commits, GitHub, GitLab)  Commit:  febfe35f9a4fd3c509e1ab4e94b9c30e77ab7359 
Dependencies:  #24464, #24465, #24483, #24457  Stopgaps: 
Description (last modified by )
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:
 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.
 As a Sage analogy to PEP 3141: it should provide a way to ask "is
x
a real number" or "isX
a substructure of the reals" or maybe "does parentX
represent the real numbers". Also, we should be able to ask "isx
an exact or approximate real number". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).
 As a class factory for all concrete real fields (e.g. the
create_RealField
function that is currently used for nonexact approximations).
Change History (56)
comment:1 Changed 5 years ago by
Cc:  Ralf Stephan added 

comment:2 Changed 5 years ago by
Cc:  Travis Scrimshaw added 

comment:4 Changed 5 years ago by
Authors:  → Vincent Delecroix 

Description:  modified (diff) 
comment:5 Changed 5 years ago by
Branch:  → u/vdelecroix/24456 

Commit:  → 78f677ed25ab323d9940a1b038213356aff70a45 
Status:  new → needs_review 
New commits:
78f677e  24456: class for the field of real numbers

comment:6 Changed 5 years ago by
Description:  modified (diff) 

comment:7 Changed 5 years ago by
Status:  needs_review → needs_work 

comment:8 Changed 5 years ago by
Commit:  78f677ed25ab323d9940a1b038213356aff70a45 → 62d2d219c661a375f86ed6fd7c4f90f782fdf11d 

Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:
62d2d21  24456: class for the field of real numbers

comment:9 Changed 5 years ago by
Status:  needs_work → needs_review 

comment:10 Changed 5 years ago by
Status:  needs_review → positive_review 

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".
comment:11 Changed 5 years ago by
Status:  positive_review → needs_review 

comment:12 followup: 13 Changed 5 years ago by
Thanks. I also had a question turning up while working on #24457. The code here does not support RealField(prec)
anymorethe init method only has self argument, is this intended? Since real_mpfr.RealField()
will be renamed should create_RealField(prec)
be used everywhere instead?
comment:13 Changed 5 years ago by
Replying to rws:
Thanks. I also had a question turning up while working on #24457. The code here does not support
RealField(prec)
anymorethe 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 shouldcreate_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
.
comment:14 Changed 5 years ago by
Some comments:
 I think the completion of
ZZ
should be in a separate ticket for better granularity.  Similarly for changing the output of
CompletionFunctor
to haveprec
.  Should be "field of real numbers".
 Why the check for façade sets in those tests? Are tests failing otherwise? I don't think they should be necessary...
 It would be nice if
RealField
could be a common ABC for all classes that model R, but that is not possible because it inherits fromSingleton
(IMO, is a shortcoming of that class, but that is a different issue).
comment:15 followup: 18 Changed 5 years ago by
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
.
comment:16 Changed 5 years ago by
Status:  needs_review → needs_work 

comment:17 Changed 5 years ago by
Summary:  class for the field of real number → class for the field of real numbers 

comment:18 Changed 5 years ago by
comment:19 Changed 5 years ago by
OK, I sort of see where this is going. But it doesn't explain why it is a Parent
.
comment:20 Changed 5 years ago by
Dependencies:  → #24464, #24465 

Description:  modified (diff) 
I am fine making it a CategoryObject
with category Fields().Infinite()
.
comment:21 followup: 22 Changed 5 years ago by
This is initialized as a facade parent, so it should not have an Element
class.
comment:22 followup: 23 Changed 5 years ago by
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?
comment:23 followups: 24 25 Changed 5 years ago by
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 likesage: R = RealField() # abstract real numbers sage: issubclass(RR, R) TrueIs 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)
comment:24 Changed 5 years ago by
Replying to vdelecroix:
This is the kind of purposes I want this class for.
Excellent! A big +1 from me.
comment:25 Changed 5 years ago by
Replying to vdelecroix:
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.
comment:26 Changed 5 years ago by
Cc:  Eric Gourgoulhon added 

comment:27 Changed 5 years ago by
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 3dimensional 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).
comment:28 followups: 31 33 35 Changed 5 years ago by
Sorry for being mute, i did not have time to write something when i put this ticket back on needsreview, 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 illnamed 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.
comment:29 followup: 30 Changed 5 years ago by
The depending ticket #24171 could work with numbers.*
as well, as the objects are used only internally.
comment:30 Changed 5 years ago by
comment:31 followup: 34 Changed 5 years ago by
Replying to 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 parentReal 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 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
 mathematical construction relying on an (abstract) field of real numbers (such as manifolds, see 27)
 querries like "is parent X is a model for real numbers" (see 22 and followup)
How do we ensure a smooth transition from the current illnamed
RR
and a genuineRR
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. Statusquo is not the way to go either.
comment:32 Changed 5 years ago by
Dependencies:  #24464, #24465 → #24464, #24465, #24483 

Description:  modified (diff) 
Summary:  class for the field of real numbers → classes for the fields of complex and real numbers 
comment:33 Changed 5 years ago by
Replying to 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).
comment:34 Changed 5 years ago by
Replying to vdelecroix:
sage: 0.1 in R FalseAs 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
.
comment:35 Changed 5 years ago by
Replying to 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.
comment:36 followup: 39 Changed 5 years ago by
Maybe we should start by thinking about possible use cases for this "real field":
 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.
 As a Sage analogy to PEP 3141: it should provide a way to ask "is
x
a real number" or "isX
a substructure of the reals" or maybe "does parentX
represent the real numbers". Note that Sage already has partial support for PEP 3141 but only for elements (not parents).
comment:37 Changed 5 years ago by
Dependencies:  #24464, #24465, #24483 → #24464, #24465, #24483, #24457 

comment:38 Changed 5 years ago by
Description:  modified (diff) 

comment:39 followups: 42 44 Changed 5 years ago by
Replying to jdemeyer:
Maybe we should start by thinking about possible use cases for this "real field":
 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.
 As a Sage analogy to PEP 3141: it should provide a way to ask "is
x
a real number" or "isX
a substructure of the reals" or maybe "does parentX
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 nonexact approximations. This is for coercion reasons: each exact subring coerces into all nonexact approximations. This is also why I claimed that 0.1 in R
should be False
.
Let me add
 As a way to check for
is x an exact real number?
andis x a nonexact real number?
. We should specify clearly thatisinstance(x, numbers.Real)
means exact real or nonexact real (I take that as given because bothissubclass(int, numbers.Real)
andissubclass(float, numbers.Real)
areTrue
).
 As a pointers to all real field implementations (exact subrings and nonexact 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 nonexact approximations).
comment:40 Changed 5 years ago by
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.
comment:41 Changed 5 years ago by
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.
comment:42 Changed 5 years ago by
Replying to vdelecroix:
This is also why I claimed that
0.1 in R
should beFalse
.
I still don't get this. Please elaborate...
comment:43 Changed 5 years ago by
Description:  modified (diff) 

comment:44 followup: 46 Changed 5 years ago by
Replying to vdelecroix:
 As a pointers to all real field implementations (exact subrings and nonexact 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 nonexact approximations).
What is the it in this last sentence?
comment:45 followup: 48 Changed 5 years ago by
Replying to jdemeyer:
Replying to vdelecroix:
This is also why I claimed that
0.1 in R
should beFalse
.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. Floatingpoint 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
.
comment:46 followup: 47 Changed 5 years ago by
Replying to jdemeyer:
Replying to vdelecroix:
 As a pointers to all real field implementations (exact subrings and nonexact 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 nonexact approximations).What is the it in this last sentence?
I meant the genuine real field that we are trying to design.
comment:47 Changed 5 years ago by
Description:  modified (diff) 

Replying to vdelecroix:
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 Floatingpoint field with 53 bits of precision
or maybe
sage: R = RealField() sage: R(prec=53, implementation="mpfr") Real Floatingpoint field with 53 bits of precision
comment:48 followup: 49 Changed 5 years ago by
Replying to vdelecroix:
For me
RealField
means the field of real numbers in the mathematical sense together with its exact operations+
,
,log
,exp
, etc. Floatingpoint 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 floatingpoint 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.
comment:49 Changed 5 years ago by
Replying to jdemeyer:
Replying to vdelecroix:
For me
RealField
means the field of real numbers in the mathematical sense together with its exact operations+
,
,log
,exp
, etc. Floatingpoint 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 floatingpoint 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.
comment:50 Changed 5 years ago by
Description:  modified (diff) 

comment:51 Changed 5 years ago by
Branch:  u/vdelecroix/24456 → u/rws/24456 

comment:52 Changed 5 years ago by
Commit:  62d2d219c661a375f86ed6fd7c4f90f782fdf11d → febfe35f9a4fd3c509e1ab4e94b9c30e77ab7359 

Status:  needs_work → needs_review 
Rebased on the dependency.
New commits:
875c231  24483: merge complex_number/complex_field into complex_mpfr

f3ed18c  24483: fix interpreters

14c9753  24483: fix imports and doctests

1fdb61c  Merge branch 'develop' into t/24483/24483

aefb4df  24483: fix import

febfe35  Merge branch 'u/vdelecroix/24456' of git://trac.sagemath.org/sage into tmp18

comment:53 Changed 4 years ago by
Status:  needs_review → needs_work 

Work issues:  → merge conflict 
Does not apply anymore.
comment:54 followup: 56 Changed 2 years ago by
I think, this is a splendid idea. What can be done to stress this forward? Can I help?
comment:55 Changed 2 years ago by
Cc:  Michael Jung added 

comment:56 Changed 2 years ago by
Replying to ghmjungmath:
I think, this is a splendid idea. What can be done to stress this forward? Can I help?
Indeed, it was a terrible design from the start. The main obstruction to change it is backward compatibility... You can work on any of #24483, #24489 and #24457 that are prerequisite for this ticket.
+1