-
-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement hash for AffineScalarFunc #219
base: master
Are you sure you want to change the base?
Conversation
Last but not least, the |
I think, that is not the case, it is correct that #218 originates from #189, but it is about a different topic. Sure, if the Please let me know if I misunderstand something. |
Sorry @NelDav for not opening an issue to discuss further. I had wanted to, but I had not partly because discussion continued on in a few different GitHub Discussions in this repo like #218 and also just because I did not have time. I had suggested moving discussion to your fork because I thought the feedback in #189 was that it was too verbose and we should get alignment before reopening a clean PR. Here is my current understanding:
Personally, I prefer the latter option, but my impression is that the other maintainers have more reservations about treating |
Yes, @NelDav, the title of that discussion is about |
Yes, sorry if I have been the hold-up here. I think the various discussions here also get into the issue of what should "ideal behavior" be, and we want to do going forward, not so much about "let's fix a bug right now". I am OK with merging this, and then working to get 3.2.0 ready. That is, the more philosophical discussion for version 4.0. But, unable to resist, I would respond to @wshanks:
I think my preference would be:
But, again, that is for a future version. |
I totally agree with that. That's what I wanted to say before, but I did not find such nice words as you did.
Personally, I like this idea for the future version. It sounds like a clean solution. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #219 +/- ##
==========================================
- Coverage 95.59% 95.41% -0.18%
==========================================
Files 12 12
Lines 1905 1943 +38
==========================================
+ Hits 1821 1854 +33
- Misses 84 89 +5 ☔ View full report in Codecov by Sentry. |
See this PR on my fork where I implement a solution that allows It begins with the Next is the Finally is the *Basically I wanted a few conveniences in the API. I wanted users to be able to pass any kind of number, int, decimal, float, etc. in for the |
It is more than a week now, that I closed #189 and asked to continue discussion inside the issues of my Fork.
Nobody opened an issue. Because of that, I think that there are no further discrepancies between @wshanks, @MichaelTiemannOSC and me.
So, I want to try again and merge this changes :)
In the current master branch, there is no
__hash__
function forAffineScalarFunc
but forVariable
:Basics about hashes
If we just need a hash for
Variable
, this would be sufficient, but it is possible to makeAffineScalarFunc
hashable and I think we should provide a__hash__
function forAffineScalarFunc
objects as well.First, let us take a deeper look into python glossary about the term
hashable
.It describes to requirements:
From this requirement, it follows that the hash must be independent from the state of the object, because otherwise the hash could change during lifetime. That means, that we can only use immutable properties of the object, to calculate the hash.
If we use the same properties, that are used to determine equality, to calculate the hash, this requirement is fulfilled.
Hashes in the uncertainties package
Let us now check how
AffinceScalarFunc
behaves in the uncertainties package.Equality of two
AffineScalarFunc
objects is relatively complicate and I do not really want to step into details here.Currently there is another issue discussing that in more detail.
However, if we use the
_linear_part
property and the_nominal_value
property, we are able to calculate a hash, that compares equal, if twoAffineScalarFunc
objects compare equal.But there is still a problem, the hash equality must also be guaranteed, for comparisons, where a
AffineScalarFunc
object and aVariable
object are equal.Because of that, we cannot keep the original implementation of
__hash__
inside theVariable
object.Instead, we need to use the same calculation for
Variable::__hash_
as we use forAffineScalarFunc;:__hash__
.Normally, removing the
__hash__
function fromVariable
would do the trick, sinceAffineScalarFunc
is the base class ofVariable
.However, there one problem.
But before I explain this problem, let us check if the implementation of
AffineScalarFunc::__hash__
fulfills the first requirement ofhashable
.We note, that the
AffienScalarFunc
objects are mutable, which might be problem.But fortunately, the expanded version of
_linear_part
, as well as the_nominal_value
are immutable.Because of that, also the hash is immutable and cannot change during the entire lifetime.
Now let us step into the reason, why we need to use a slightly different implementation of
__hash__
forVariable
.The
Variable
object has a self reference inside the_linear_part
.This is a problem, when unpickling a
Variable
object. The reason for that is, that the pickle will first generate theLinearCombination
object, before it generate theVariable
object. While doing so, it tries to calculate the hash from the self reference. But theVariable
object does not exist and the calculation will fail.For the same reason, the
__getstate__
and__setstate__
function must be implemented.In the end, I want to thank everybody, who contributed to this PR.