Skip to content
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

rework to save bracket #173

Merged
merged 5 commits into from
Feb 28, 2020
Merged

rework to save bracket #173

merged 5 commits into from
Feb 28, 2020

Conversation

jverzani
Copy link
Member

@jverzani jverzani commented Feb 8, 2020

Introduces find_bracket to return a tuple containing a zero, an enclosing bracket, and a flat indicating if the value is an exact zero.

To do so, required adding a field in the struct to store the approximate zero instead of reusing xn1, which contains one part of the bracket.

@ChrisRackauckas
Copy link
Member

@kanav99

@jverzani
Copy link
Member Author

@kanav99

Should I merge this? I certainly can, but wanted to make sure the interface is sufficient before doing so.

@kanav99
Copy link

kanav99 commented Feb 20, 2020

Sorry @jverzani this one slipped my mind. We have developed a workaround for the time being which seems to be stable. What we did right now is instead of solving for θ (which is in [0,1]) we solve for 1-θ. Thus we get an upper limit for 1-θ i.e. lower limit of θ. But this can only be done using Bisection.

If this PR makes sure that xn0 is just less than the root and xn1 is just greater than the root then this works for us!

@jverzani
Copy link
Member Author

There are two possibilities due to the stopping rules employed: one with a bracket satisfying the condition or one where the algorithm terminates with an exact zero is found. In the latter case, the bracket may not satisfy the above. The return value includes a flag to determine which occurred. Is that a satisfactory design for you?

@kanav99
Copy link

kanav99 commented Feb 22, 2020

I think that works for us. If we do prevfloat(root) in case of exact solution, we will get the previous sign right?

@jverzani
Copy link
Member Author

No, that's the worry. For example, you might see this:

julia> f(x) =  (x+1)*x^2
f (generic function with 1 method)

julia> Roots.find_bracket(f, (-2, 2))
(xstar = 0.0, bracket = (0.0, 2.0), exact = true)

Here, the first step is to consider the midpoint 0.0 which is an exact zero. But at zero, there is no sign change.

@kanav99
Copy link

kanav99 commented Feb 22, 2020

I don't think that would be issue, isn't it @ChrisRackauckas ? This issue is not because of floating point error or inconsistent lower or upper limit but a property of the function. If Chris agrees too, this interface is good enough for us.

@ChrisRackauckas
Copy link
Member

The true problem is that f(x) = 1e-12 and then f(prevfloat(x)) = 1e-12 still because of precision stuff, so f(prevfloat(prevfloat(x)) = -1e-12 is what we really needed. So we need the bracket and can just take the left, and that would solve it. The issue is that we've been having to assume the bracket right prevfloat once is equal to the left, which isn't always true. If we have a left bracket that always works, 👍

@jverzani
Copy link
Member Author

Hi @ChrisRackauckas and @kanav99 . After your comments, I squeezed the tolerances for the Alefeld-Potra-Shi cases and the following is satisfied for the test cases: if l is the return value from find_bracket then either:

  • l.exact is true (in which case the bracket may be quite large, as the algorithm can terminate early)

  • abs(l.bracket[2] - l.bracket[1]) <= 2eps(maximum(abs.(l.bracket))). For BisectionExact, this bound is smaller (the bracket consists of adjacent floting point values), but this isn't the case for the faster A42 method.

In the latter case, l.xstar can be any of the 4 possible values in the bracket, so starting at l.xstar, you might need to step back 3 floats to get the sign change.

Hopefully that will suit for your use case.

@ChrisRackauckas
Copy link
Member

In the latter case, l.xstar can be any of the 4 possible values in the bracket, so starting at l.xstar, you might need to step back 3 floats to get the sign change.

Yeah, having a known fact that it's at most 4 steps fixes this! Before we just put to run it like 5 steps otherwise through an error, so the larger tolerance likely was why ewe hit the error.

@jverzani jverzani merged commit a6dc315 into JuliaMath:master Feb 28, 2020
@jverzani jverzani deleted the issue_170 branch February 28, 2020 17:12
@kanav99
Copy link

kanav99 commented Mar 13, 2020

@jverzani In case of exact = false what is the suggested root? I @showed a result of the find_bracket function and output was:

(xstar = 0.9746722903038366, bracket = (0.9746722903038367, 0.9746722903038368), exact = false)

Note that xstar < bracket[1] < bracket[2]. Is this expected behaviour?

@jverzani
Copy link
Member Author

Well, that isn't expected. Do you have the function available that I can look at?

@kanav99
Copy link

kanav99 commented Mar 13, 2020

It is a private code someone sent me. I don't think I can send that to you. I will try to make a MWE

@jverzani
Copy link
Member Author

jverzani commented Mar 13, 2020 via email

@jverzani
Copy link
Member Author

jverzani commented Mar 21, 2020 via email

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.

None yet

3 participants