-
Notifications
You must be signed in to change notification settings - Fork 12
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
A confusing bug #151
Comments
That's... weird. I can reproduce it locally. |
I'm not sure what causes the error: there mat be some random element to working with a Still, I'd like to chase the original error, because different types arise in intermediate steps, whereas the input types are all the same. It's likely that hashes of domains which are equal are different, but a real clash is very unlikely. More likely this is a bug somewhere. |
another case: |
So the culprit of the error is this function. The error indeed goes away with a different implementation of the same logic, like this one: function setdiffdomain1(d1::UnionDomain, d2)
if d2 ∈ components(d1)
uniondomain(filter(x->x!=d2, components(d1))...)
else
UnionDomain(setdiffdomain.(components(d1), Ref(d2)))
end
end This might not be the best implementation if the components of the union object are a vector (because of the splatting). Looking at this code now, I would not write these routines again (the specialization of I say that because you're working on unions of intervals. Please just ignore whatever DomainSets does and make your own implementation, it does not matter that it's different from what happens here. It is probably easier to reason about (predictable) optimizations when working solely with intervals. (For the record, I know your example is cooked up, but the rule in the code is that |
Thanks for reporting, this is fun. I went digging into the internals of dictionaries. The difference between the (empty) open intervals happens at this line in dict.jl in base. It appears normal for there to be a difference here and it is not usually a problem. However, a few lines down the test for equality succeeds, in spite of the hashes of the EmptySpace and the open interval being different, because the open interval is equal to an empty interval. Thus, the outcome is different for different open intervals, even though all the types are the same. Conclusion: the problem is that This is a good catch! I've been wondering about the consequences of not respecting equavalence of equality and hashes. Unfortunately, this problem is hard to fix. It may be doable for intervals, but it will be a lot harder for domains. I am not 100% sure of my explanation because I do not understand the internals of dictionaries. |
Here is an example of the problem with I am creating a dictionary with a single object. I create a long vector of elements equal to that one object, but with a different hash. (The hash is different because julia> struct MyType
a
end
julia> Base.isequal(d1::MyType, d2::MyType) = true
julia> objects = [MyType(rand()) for i in 1:10000];
julia> d = Dict(MyType(2.0) => nothing)
Dict{MyType, Nothing} with 1 entry:
MyType(2.0) => nothing
julia> sum(haskey(d, objects[i]) for i in 1:length(objects))
5 The correct answer here would be yes 10000 times. |
Thanks for the investigation! The issue is not cooked up. It happens when I test the union of intervals. The way I check the correctness is to setdiff every component from the union and check if the final result is empty. A case that looks more common: |
Fixed by #152, could you confirm that? |
My tests are passing. |
The text was updated successfully, but these errors were encountered: