Opened 7 months ago
Closed 7 months ago
#30266 closed enhancement (fixed)
Immutability for scalar fields
Reported by:  ghmjungmath  Owned by:  

Priority:  major  Milestone:  sage9.2 
Component:  manifolds  Keywords:  immutability 
Cc:  egourgoulhon, tscrim, mkoeppe  Merged in:  
Authors:  Michael Jung  Reviewers:  Matthias Koeppe 
Report Upstream:  N/A  Work issues:  
Branch:  1912193 (Commits, GitHub, GitLab)  Commit:  1912193c1c40222a7ce606e318fb1c5d5126cca4 
Dependencies:  #30181  Stopgaps: 
Description (last modified by )
This ticket adds the immutability and hashability for scalar fields.
See #30261.
Change History (45)
comment:1 Changed 7 months ago by
 Branch set to u/ghmjungmath/immutability_for_scalar_fields
comment:2 Changed 7 months ago by
 Cc egourgoulhon tscrim mkoeppe added
 Commit set to aebadedd85d782e004a626f207df5422fee5a9ab
 Component changed from PLEASE CHANGE to manifolds
 Description modified (diff)
 Keywords immutability added
 Status changed from new to needs_review
 Summary changed from immutability for scalar fields to Immutability for scalar fields
 Type changed from PLEASE CHANGE to enhancement
comment:3 Changed 7 months ago by
 Dependencies set to #30181
comment:4 Changed 7 months ago by
Is the hash input okay? Or should it be something more unique?
comment:5 followup: ↓ 6 Changed 7 months ago by
Given that ScalarField_repr_
does not print any contents, this hash does not seem to be useful to distinguish nonequal elements. This will degrade the performance of sets to that of lists.
More importantly, it must be ensured that f == g
implies hash(f) == hash(g)
. Because equality does not take names into account but repr
does, this is currently not satisfied.
comment:6 in reply to: ↑ 5 ; followups: ↓ 7 ↓ 9 Changed 7 months ago by
Replying to mkoeppe:
Given that
ScalarField_repr_
does not print any contents, this hash does not seem to be useful to distinguish nonequal elements. This will degrade the performance of sets to that of lists.More importantly, it must be ensured that
f == g
implieshash(f) == hash(g)
. Because equality does not take names into account butrepr
does, this is currently not satisfied.
I just copied the ideas from the elsewhere in the Sage code. This means that most hash
functions are implemented wrong.
Are you sure it is not f is g
implies hash(f) == hash(g)
? f == g
implies hash(f) == hash(g)
is barely possible in cases where coercions apply, isn't it?
comment:7 in reply to: ↑ 6 ; followup: ↓ 8 Changed 7 months ago by
Replying to ghmjungmath:
Are you sure it is not
f is g
implieshash(f) == hash(g)
?
This implication is trivially true.
comment:8 in reply to: ↑ 7 Changed 7 months ago by
Replying to mkoeppe:
Replying to ghmjungmath:
Are you sure it is not
f is g
implieshash(f) == hash(g)
?This implication is trivially true.
Oh, yes, this is obviously right. >.< :D
comment:9 in reply to: ↑ 6 Changed 7 months ago by
Replying to ghmjungmath:
Replying to mkoeppe:
Given that
ScalarField_repr_
does not print any contents, this hash does not seem to be useful to distinguish nonequal elements. This will degrade the performance of sets to that of lists.More importantly, it must be ensured that
f == g
implieshash(f) == hash(g)
. Because equality does not take names into account butrepr
does, this is currently not satisfied.I just copied the ideas from the elsewhere in the Sage code. This means that most
hash
functions are implemented wrong.
Ah yes, I see, apparently that were cases where the string representation cannot be changed. Due to the fact that we allow restrictions as coercion, hash(self._manifold)
seem to be the only choice.
I will add a related doctest for this particular case.
Thank you.
comment:10 Changed 7 months ago by
 Commit changed from aebadedd85d782e004a626f207df5422fee5a9ab to 5c7fd6e1933dd09daab91eda15df09572148413b
Branch pushed to git repo; I updated commit sha1. New commits:
5c7fd6e  Trac #30266: immutability of restrictions + hash function improved

comment:11 Changed 7 months ago by
This should be better.
comment:12 Changed 7 months ago by
Is that hash
function okay? I have added a short f == g
implies hash(f) == hash(g)
test.
Patchbot is green, btw.
comment:13 Changed 7 months ago by
 Dependencies changed from #30181 to #30181, #30116
Since #30116, scalar fields can be compared on common domains. I added the check of the hash condition in the doctest for this particular comparison.
comment:14 Changed 7 months ago by
 Commit changed from 5c7fd6e1933dd09daab91eda15df09572148413b to 8ca8b754a246ebad775b7db7310e4996f086687a
Branch pushed to git repo; I updated commit sha1. Last 10 new commits:
22e2961  Trac #30116: Merge branch 'develop' into replace_eq_by_richcmp_tensorfield

11c9d35  Trac #30116: invoke super method by using super() + replacing __eq__ in most files

a59c71a  Trac #30267: coercion via restriction added

3e2b28c  Trac #30267: coercion via restriction added

f640f21  Trac #30116: Merge branch 't/30267/coercion_via_restriction_of_chart_functions' into t/30116/test_comparison_tensorfield

4bcd2ee  Trac #30267: coercion via restriction added

89906e2  Trac #30116: Merge branch 'coercion_via_restriction_of_chart_functions' into t/30116/test_comparison_tensorfield

a9d652f  Trac #30116: documentation adapted

055d226  Trac #30266: Merge branch 't/30116/test_comparison_tensorfield' into t/30266/immutability_for_scalar_fields

8ca8b75  Trac #30266: hash compatibility check wrt #30116

comment:15 Changed 7 months ago by
 Commit changed from 8ca8b754a246ebad775b7db7310e4996f086687a to 0bf9f36d692396f8aa2b32a529532c2e4e48511e
Branch pushed to git repo; I updated commit sha1. New commits:
0bf9f36  Trac #30266: Merge branch 'develop' into t/30266/immutability_for_scalar_fields

comment:16 Changed 7 months ago by
Patchbot is green.
comment:17 followup: ↓ 18 Changed 7 months ago by
I believe for _richcmp_
you also have self is not other
, but you should double check this.
comment:18 in reply to: ↑ 17 ; followup: ↓ 19 Changed 7 months ago by
comment:19 in reply to: ↑ 18 Changed 7 months ago by
Replying to ghmjungmath:
Replying to tscrim:
I believe for
_richcmp_
you also haveself is not other
, but you should double check this.In #30116, I used
if self is other:
instead. Is that what you mean?
Ah, I missed it there. Yes, I mean that, and I think it is unnecessary because the coercion framework through __eq__
handles that case. However, I don't trust myself here, so it is worth checking.
comment:20 followup: ↓ 22 Changed 7 months ago by
I changed the whole _richcmp_
to return False
and tried f == f
. It returned False
. So, no prior instance check here. For fun, I did the same with the opposite: no prior check there, too.
comment:21 Changed 7 months ago by
 Commit changed from 0bf9f36d692396f8aa2b32a529532c2e4e48511e to a5f6a19d0b492cbe2b73daf74e1a6b3a98667055
Branch pushed to git repo; I updated commit sha1. New commits:
a5f6a19  Trac 30266: hash function slightly improved

comment:22 in reply to: ↑ 20 Changed 7 months ago by
Replying to ghmjungmath:
I changed the whole
_richcmp_
toreturn False
and triedf == f
. It returnedFalse
. So, no prior instance check here. For fun, I did the same with the opposite: no prior check there, too.
Thank you for checking. :)
comment:23 Changed 7 months ago by
Unfortunately I am too busy right now to do the review. I can probably do it next week, but if someone else wants to step up and do it, please go ahead.
comment:24 Changed 7 months ago by
One question btw: must 1 == f
also imply hash(1) == hash(f)
. The former can be fulfilled due to the coercion framework, the latter is rather difficult since both have different types. Is it enough for this condition to be fulfilled for objects of the same type?
comment:25 Changed 7 months ago by
For the ring of integers modulo some number, this behavior is not satisfied:
sage: 3 == GF(2)(3) True sage: hash(3) == hash(GF(2)(3)) False
comment:26 followup: ↓ 27 Changed 7 months ago by
Ensuring that this implication holds across coercion is very difficult, and it is done in Sage on a "best effort" basis  such as for QQ as the fraction field of ZZ.
The rule of thumb is that if we form sets, they should be of elements of the same parent so that no coercion is involved. Likewise for the keys of dictionaries.
comment:27 in reply to: ↑ 26 Changed 7 months ago by
Replying to mkoeppe:
Ensuring that this implication holds across coercion is very difficult, and it is done in Sage on a "best effort" basis  such as for QQ as the fraction field of ZZ.
The rule of thumb is that if we form sets, they should be of elements of the same parent so that no coercion is involved. Likewise for the keys of dictionaries.
Since the restriction is set as a coercion, and they live in different sets, maybe we should make the hash more unique? Namely:
 return hash((type(self).__name__, self._manifold)) + return hash((type(self).__name__, self._domain))
If that is what we want, I will, of course, adapt the doctest section.
comment:28 followup: ↓ 29 Changed 7 months ago by
I haven't followed the discussion regarding restriction and equality, so I would need more context here.
comment:29 in reply to: ↑ 28 Changed 7 months ago by
Replying to mkoeppe:
I haven't followed the discussion regarding restriction and equality, so I would need more context here.
Sorry, sure. See #30116 for the discussion.
Manifolds allows coercions from scalar fields on M
to scalar fields on U
, where U
is a subset of M
, i.e. a restriction. Since #30116, the equality check compares scalar fields on a common subset and returns True
if they are the same on that domain. Nevertheless, both scalar fields on different domains are still distinct objects defined in distinct sets.
comment:30 followup: ↓ 31 Changed 7 months ago by
You probably discussed this on that ticket, but this kind of "equality" relation is not transitive without strong assumptions such as analyticity and connectedness, is it?
comment:31 in reply to: ↑ 30 Changed 7 months ago by
Replying to mkoeppe:
You probably discussed this on that ticket, but this kind of "equality" relation is not transitive without strong assumptions such as analyticity and connectedness, is it?
Actually, we didn't. But that is a crucial point! Without analyticity, which is not necessarily given, the transitivity is definitely violated.
However, coercible objects have to be comparable, right?
comment:32 followup: ↓ 33 Changed 7 months ago by
In general I don't think you should feel obligated to use the coercion framework for comparisons just because you use it for arithmetic. It's just a tool.
comment:33 in reply to: ↑ 32 Changed 7 months ago by
Replying to mkoeppe:
In general I don't think you should feel obligated to use the coercion framework for comparisons just because you use it for arithmetic. It's just a tool.
Probably you're right. The documentation, however, is not very explicit on that. I changed the ticket above to "needs info" and left a question. Perhaps you can take a short look?
comment:34 Changed 7 months ago by
I just want to mention that your contributions are always very beneficial. Thank you very much! :)
comment:35 followup: ↓ 36 Changed 7 months ago by
But soon I'll start bothering you with lots of naive questions about differential geometry... ;)
comment:36 in reply to: ↑ 35 Changed 7 months ago by
Replying to mkoeppe:
But soon I'll start bothering you with lots of naive questions about differential geometry... ;)
That's only fair. ;)
comment:37 Changed 7 months ago by
I will remove the dependence from #30116 again.
comment:38 Changed 7 months ago by
 Commit changed from a5f6a19d0b492cbe2b73daf74e1a6b3a98667055 to 37b004279233b59c9044e82fb1578a3025beb258
Branch pushed to git repo; I updated commit sha1. New commits:
37b0042  Trac #30266: remove dependency of #30116

comment:39 Changed 7 months ago by
 Commit changed from 37b004279233b59c9044e82fb1578a3025beb258 to 2f72e19ef4e48b1dd886a3b7ec3488e0e95b284e
Branch pushed to git repo; I updated commit sha1. New commits:
2f72e19  Trac #30266: if statement missing

comment:40 Changed 7 months ago by
 Commit changed from 2f72e19ef4e48b1dd886a3b7ec3488e0e95b284e to 793c162342e961c60ddc3ba704a59934d921c47d
Branch pushed to git repo; I updated commit sha1. This was a forced push. New commits:
793c162  Trac #30266: hash function improved

comment:41 Changed 7 months ago by
 Dependencies changed from #30181, #30116 to #30181
Here we go. Let's see what our friend the patchbot says...
comment:42 Changed 7 months ago by
 Commit changed from 793c162342e961c60ddc3ba704a59934d921c47d to 1912193c1c40222a7ce606e318fb1c5d5126cca4
Branch pushed to git repo; I updated commit sha1. New commits:
1912193  Trac #30266: doctest improved

comment:43 Changed 7 months ago by
Patchbot is satisfied.
comment:44 Changed 7 months ago by
 Reviewers set to Matthias Koeppe
 Status changed from needs_review to positive_review
comment:45 Changed 7 months ago by
 Branch changed from u/ghmjungmath/immutability_for_scalar_fields to 1912193c1c40222a7ce606e318fb1c5d5126cca4
 Resolution set to fixed
 Status changed from positive_review to closed
New commits:
FreeModuleTensor, Vector: Subclass a new class ModuleElementWithMutability
sage.tensor.modules: Make all zero() and one() elements immutable
FreeModuleTensor: Replace special casing of the immutable zero by is_immutable
ModuleElementWithMutability.is_immutable, is_mutable: Change def to cpdef
Trac #30266: make scalarfields immutable