Skip to content

Overhall equality checks, to give better failure messages #57

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

Merged
merged 13 commits into from
Dec 14, 2020

Conversation

oxinabox
Copy link
Member

@oxinabox oxinabox commented Oct 5, 2020

I wanted to add accumulation checks,
but to do that

I felt it was good to refactor away from using isapprox as much as we do,
I am not entirely sure this PR is a great idea,
the accumulation stuff is easy enough to put in another PR, if we don't like the rest of it.

This PR is a great idea.
To deal with giving useful error messages an not things about thunks not being equal.
and getting rid of all the hacks with extern, collect, and isapprox.
effectively closes #7 as we will be able to delete isapprox on differentials with the next major release

src/iterator.jl Outdated
Comment on lines 46 to 50
# To make it a valid differential: needs at very least `zero` and `+`
Base.zero(::Type{<:TestIterator}) = Zero()
function Base.:+(iter1::TestIterator{T,IS,IE}, iter2::TestIterator{T,IS,IE}) where {T,IS,IE}
return TestIterator{T,IS,IE}(map(+, iter1, iter2))
end
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using this like a differential, without these being defined,
which ment that testing accumulation errored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm you're right. The idea with TestIterator is for it to behave like some generic iterator. For most iterators, we will not be able to define e.g. zero(::SomeIterator) without type piracy, so maybe the type of TestIterator's differential should not be TestIterator but instead a Composite?
But then again, I guess most iterators won't have isapprox defined on them, so we're already not super consistent here.

src/testers.jl Outdated
frule((Zero(), Δx), f, z; fkwargs...)[2],
check_equal(
frule((Zero(), real(Δx)), f, z; fkwargs...)[2]::Number,
frule((Zero(), Δx), f, z; fkwargs...)[2]::Number,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scalar rules shout return Numbers.
but maybe this should be moved out of this part of the test and be somewhere else
tested explictly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree that this should have an explicit isa Number test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can leave this for now, I have removed this from the test

@oxinabox
Copy link
Member Author

oxinabox commented Oct 5, 2020

I don't really love this PR. though I like it more than the code it replaces i think.
I might sit on if for a few days see if anyone else has good input

@oxinabox oxinabox requested review from mattBrzezinski, nickrobinson251 and sethaxen and removed request for sethaxen October 6, 2020 12:51
Copy link
Member

@sethaxen sethaxen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't followed the accumulation PR(s?), so take this review with that caveat. In general I like the introduction of more human-readable errors (can you actually add a test that check_equal produces human-readable errors for a case where isapprox would not have?), and I don't see a problem with the accumulation part (can you add a test for the testers for an accumulating function?)

src/iterator.jl Outdated
Comment on lines 46 to 50
# To make it a valid differential: needs at very least `zero` and `+`
Base.zero(::Type{<:TestIterator}) = Zero()
function Base.:+(iter1::TestIterator{T,IS,IE}, iter2::TestIterator{T,IS,IE}) where {T,IS,IE}
return TestIterator{T,IS,IE}(map(+, iter1, iter2))
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm you're right. The idea with TestIterator is for it to behave like some generic iterator. For most iterators, we will not be able to define e.g. zero(::SomeIterator) without type piracy, so maybe the type of TestIterator's differential should not be TestIterator but instead a Composite?
But then again, I guess most iterators won't have isapprox defined on them, so we're already not super consistent here.

src/testers.jl Outdated
frule((Zero(), Δx), f, z; fkwargs...)[2],
check_equal(
frule((Zero(), real(Δx)), f, z; fkwargs...)[2]::Number,
frule((Zero(), Δx), f, z; fkwargs...)[2]::Number,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree that this should have an explicit isa Number test.

@oxinabox oxinabox changed the title RFC: overhall equality checks and add accumulation checks RFC: overhall equality checks, to give better failure messages Dec 11, 2020
@oxinabox oxinabox changed the title RFC: overhall equality checks, to give better failure messages Overhall equality checks, to give better failure messages Dec 11, 2020
@oxinabox
Copy link
Member Author

I have come back to this because i an sick of bad messages around thunks
so it is rebased and has test now
@sethaxen can you rereview

Example change:

julia> oldcheck(log(-1.0 - im), k)
Test Failed at REPL[95]:1
  Expression: isapprox(actual, expected)
   Evaluated: isapprox(0.34657359027997264 - 2.356194490192345im, Thunk(var"#217#218"()))
ERROR: There was an error during testing

julia> check(log(-1.0 - im), k)
Test Failed at /Users/oxinabox/JuliaEnvs/ChainRulesWorld/ChainRulesTestUtils.jl/src/check_result.jl:18
  Expression: isapprox(actual, expected; kwargs...)
   Evaluated: isapprox(0.34657359027997264 - 2.356194490192345im, 0.34657359027997264 + 2.356194490192345im)
ERROR: There was an error during testing

@oxinabox oxinabox requested a review from sethaxen December 11, 2020 20:32
)
_, real_tangent = frule((Zero(), real(Δx)), f, z; fkwargs...)
_, embedded_tangent = frule((Zero(), Δx), f, z; fkwargs...)
_check_equal(real_tangent, embedded_tangent; isapprox_kwargs...)
end
end
if z isa Complex
Copy link
Member Author

@oxinabox oxinabox Dec 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to move the 4 sections of this function that happen only for complex out into 2 helper functions.
(one for forward on one for reverse)
but that should be a follow up PR as it will make this hard to read.

@nickrobinson251
Copy link
Contributor

Does this close #7? I think probably, but not sure because i've just given it a quick look.

Also does it make any difference to #56?

are shown on failures.
All keyword arguments are passed to `isapprox`.
"""
function _check_equal(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should export this, (and rename it)
for people who need to write special tests?
Might make it feel more safe to remove isapprox as there is a handy subsitution

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I think we're probably committed to maintaining some functionality of this form, I agree that we should export it.

oxinabox and others added 3 commits December 11, 2020 20:44
) where {T1,T2,IS,IE}
return isapprox(iter1.data, iter2.data; kwargs...)
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this is breaking, but I am pretty sure they are not used except in this package.
But I could keep them and move them to deprecated, do you think?

Co-authored-by: willtebbutt <wt0881@my.bristol.ac.uk>
@oxinabox
Copy link
Member Author

Does this close #7? I think probably, but not sure because i've just given it a quick look.

Yes, this closes #7 (technically would need to wait for next breaking change when isapprox on all the differnetials is deleted but its not used internally any more)

Also does it make any difference to #56?

#56 was actually closed by the follow up to this PR that was more minimal #59, but I forgot to close it

Co-authored-by: willtebbutt <wt0881@my.bristol.ac.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove automatic extern in isapprox?
4 participants