-
Notifications
You must be signed in to change notification settings - Fork 146
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
Change ==
to ignore measure-zero branches
#481
Conversation
Edit: Locally tests pass on 1.5 and on 1.0. Initially 1.5 passed on CI. Now 1.0 and 1.5 fail on CI, at the same line, seemingly relevant. The tests here are pretty messy to work with; I'm happy to have another go but won't bother if there's no interest. |
I also think this makes sense. I am a little bit worried about the implications it will have though, perhaps there isn't a better way than to go ahead and try. Would it be considered a bugfix or a breaking change? @jrevels, any thoughts here? |
Codecov Report
@@ Coverage Diff @@
## master #481 +/- ##
==========================================
- Coverage 86.71% 86.33% -0.38%
==========================================
Files 9 9
Lines 903 900 -3
==========================================
- Hits 783 777 -6
- Misses 120 123 +3
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
Here's something this PR breaks: julia> ForwardDiff.gradient(x -> sum(abs2, unique(x)), [1,2,1,2,3]) |> println
[2, 4, 0, 0, 6] # before
[2, 4, 2, 4, 6] # after
julia> hash(ForwardDiff.Dual(1,0)) === hash(ForwardDiff.Dual(1,2,3))
true # unchanged Maybe there is some way to avoid this? Or maybe that's not the wrong answer, if all parameters are infinitesimally perturbed? julia> using FiniteDifferences
julia> grad(central_fdm(5, 1), x -> sum(abs2, unique(x)), Float32[1,2,1,2,3])
(Float32[1.9998622, 4.0002246, 1.9998622, 4.0002246, 6.000003],) |
Chiming in here, this patch solved this issue for me that involved sparse arrays. I would offer to help, but unfortunately I just don't know enough about auto diff :/ |
5f4bf0f
to
3177617
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I fixed the tests at last.
Project.toml
Outdated
version = "0.10.26" | ||
version = "0.11.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What version should this be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If in doubt, would it be safer to just bump the version (as if breaking)? Are there any downsides to doing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The downside is that 290 packages will all have to update their bounds:
https://juliahub.com/ui/Packages/ForwardDiff/k0ETY/0.10.28?page=2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is done, it should be 1.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it would also be good to enable nan safe mode by default.
SEED = trunc(Int, time()) | ||
println("##### Random.seed!($SEED), on VERSION == $VERSION") | ||
Random.seed!(SEED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously it tested with a random global seed.
What was confusing is that sometimes this gives PRIMAL == PRIMAL2 (for integers), and sometimes not. It would be clearer to deliberately test both cases. But, for now, I just made it print the seed used, so that you can lock it to debug locally.
Fixing the seed completely would test only one case per version of Julia.
Latest commit proposes to make this a bugfix, since apparently it's what the authors of all the above issues expected, and making a breaking release sounds like it'll take another year.
|
Hi there, will this make it into master before 1.0? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change is reasonable.
Should some of the unary definitions be changed as well? In particular I am thinking about isinteger
which is contained in UNARY_PREDICATES
and hence leads to the definiton
isinteger(d::Dual) = isinteger(value(d))
However, that means that not every dual d
with isinteger(d)
can be converted to an Integer
since we error if not all(iszero, partials(d))
:
Lines 365 to 368 in 78c73af
@inline function Base.Integer(d::Dual) | |
all(iszero, partials(d)) || throw(InexactError(:Integer, Integer, d)) | |
Integer(value(d)) | |
end |
I think the error is consistent with the modified definition of
==
in this PR since I guess we want d == Integer(d)
whenever Integer(d)
is defined/allowed. Hence probably isinteger
should be changed?
The integer complaint is this, which is unchanged by this PR: julia> using ForwardDiff: Dual
julia> isinteger(Dual(1.0, 0.2)) # is this wrong?
true
julia> convert(Int, Dual(1.0, 0.2))
ERROR: InexactError: Int(Int64, Dual{Nothing}(1.0,0.2))
julia> convert(Int, Dual(3.0, 0.0))
3 I'm not too sure what the right policy is here, has this ever come up in the wild? I don't think we should make quick arguments from apparent consistency. And I don't want to add anything more to this PR. |
I'm sorry, I think my comment was a bit unclear. The main reason for why I think one should consider changing
Initially I was worried that these additional changes would be too far-fetched or possibly breaking. Only then I noticed the existing inconsistency with |
Thanks! Test failures on master appear to be small changes in random numbers? This (copied from CI logs) would pass with slightly larger tolerance:
Not clear why. CI ran this PR on 1.8 this morning, and it passed. |
Replace evaluations of log(1+x) with log1p(x). In the code this occurs twice. In the old version, trickery in the first branch catched the case when 1+x == 1 with a test if w==0. We had this discussion before, the trick came from JuliaDiff/ForwardDiff.jl#481 This does not work anymore with JuliaDiff/ForwardDiff.jl#481 This PR (unfortunately) is now in v0.10.33 of ForwardDiff.jl. There is a discussion going on that this should have been 0.11, i.e. marked as a breaking change. It did break Example 103, the PR fixes this.
This changes the meaning of
==
for dual numbers, to demand that both real andimaginarydual parts match.Fixes #197, fixes #407. Edit -- also closes #490, closes #506, closes #536, closes #542, closes #551. Also closes #676, closes #677.
See #480 for too-long discussion of why I think this makes sense. And comments on functions like
>
, which this PR does not alter.