-
Notifications
You must be signed in to change notification settings - Fork 25
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
Reenable and fix example 5.5 from Smiley et al. #153
Conversation
fix for #86 |
unfortunately, the example takes to long to solve and some CI tests time out. So we might have to create a faster test for CI |
implements the idea described in JuliaArrays/StaticArrays.jl#450 |
src/contractors.jl
Outdated
J = jacobian(X) | ||
|
||
if contains_zero(det(J)) |
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.
Isn't this very expensive? This should basically come out of the \
or LU factorization.
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 cant imagine the determinant is as expensive as LU - its just a fixed number of multiplicaitons and additions without any memory allocations
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.
As far as I understand, the determinant does exactly an LU decomposition.
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.
(ah, maybe not if this is for small StaticArrays?)
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.
The fact that this check is even necessary is disturbing as we overload \
for intervals with custom methods in
https://github.com/JuliaIntervals/IntervalRootFinding.jl/blob/master/src/linear_eq.jl
Either something is broken there or somehow the wrong method is picked.
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 line 165 needs to have StaticVector instead of StaticArray?
We should definitely test if this is actually getting called.
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 makes more sense to call gaussian_elimination explicitely (instead of the \
operator) to make sure and obvious that no external algorithm should be called here
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 fact that this check is even necessary is disturbing as we overload
\
for intervals with custom methods inhttps://github.com/JuliaIntervals/IntervalRootFinding.jl/blob/master/src/linear_eq.jl
Either something is broken there or somehow the wrong method is picked.
I can confirm that the internal method is not getting called – in fact it is broken for StaticArrays. And fixing the Array / Vector mixup is not sufficient either…
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.
Are we just not actually importing \ from Base?
Ok, given that there apparently is no way to test whether LU decomposition will work, I dont see a solution. The fundamental problem remains that IntervalArithmetic tolerates silent failures in external algorithms. I spent a few hours generalizing (and cleaning up) IntervalRootFinding to support NumberIntervals and then the solution is easy: function 𝒩(f::Function, jacobian::Function, X::AbstractVector{T}, α) where T # multidimensional Newton operator
m = T.(mid.(X, α))
J = jacobian(X)
try
return convert(typeof(X), m .- (J \ f(m)))
catch
return X .± Inf
end
end I've tested it: The exception is triggered (disturbingly often) and eventually all roots in Smiley 5.5 are discovered. |
ok, this version uses the internal algorithm and finally finds all the roots for Smiley 5.5 |
623fff3
to
39994d9
Compare
not sure I trust the internal solver – for the matrix discussed above, it basically just returns this hard-coded value from IntervalRootFinding.jl/src/linear_eq.jl Line 90 in 80328b4
|
It's also breaking the Julia naming convention – this function is marked as mutating but it doesn't IntervalRootFinding.jl/src/linear_eq.jl Line 102 in 80328b4
|
- fix type signature for ldiv operator - use similar instead of copy to get mutable arrays - remove arbitrary interval restriction
cleaned up the commit log a bit. this PR contains a few more changes than strictly necessary, lmk if I should separate them into other PRs |
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.
Many thanks for fixing this and sorry for the long delay.
I added a couple of comments but other than that LGTM!
test/roots.jl
Outdated
@@ -62,7 +62,7 @@ end | |||
|
|||
# Bisection | |||
rts = roots(f, X, Bisection, 1e-3) | |||
@test length(rts) == 4 |
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 do get 4 boxes here (even though there are only 2 roots).
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.
Yes, it gives an incorrect answer. Marking it as @test_broken
makes transparent that Bisection
is unreliable and probably should never be used in practise. In addition, it will notify us if Bisection
ever starts to give the correct result here. (I admit, this is not really related to the topic of this PR–I think I just noticed this inconsistency while I was working on it.)
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 see what you mean, but I don't agree that the result is unreliable. It is reliably giving you a set of boxes that are guaranteed to contain all of the roots in the original box, and correctly telling you that it is unable to guarantee whether or not there are actually roots there.
The test is testing what the function returns, not what we would like it to ideally return ;)
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.
Ok, that makes sense. But testing for the result 4 seems overly specific if any number above 2 would acceptable. Maybe it would be better to test that the exact solutions are contained in whatever boxes are returned? I've created a separate PR #156 for that.
A = similar(A) | ||
b = similar(b) | ||
A .= _A | ||
b .= _b |
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.
Is this different / better than _A = A; A = copy(_A)
?
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 I recall correctly, calling similar()
on a StaticArray
gives a MutableArray
which is required for the setindex!()
calls below.
Thanks a lot! |
No description provided.