-
-
Notifications
You must be signed in to change notification settings - Fork 120
simplify internal_itp #1127
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
simplify internal_itp #1127
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,12 +20,11 @@ end | |
simpler dependencies. | ||
""" | ||
struct InternalITP | ||
k1::Float64 | ||
k2::Float64 | ||
scaled_k1::Float64 | ||
n0::Int | ||
end | ||
|
||
InternalITP() = InternalITP(0.007, 1.5, 10) | ||
InternalITP() = InternalITP(0.2, 10) | ||
|
||
function SciMLBase.solve(prob::IntervalNonlinearProblem{IP, Tuple{T, T}}, alg::InternalITP, | ||
args...; | ||
|
@@ -36,78 +35,58 @@ function SciMLBase.solve(prob::IntervalNonlinearProblem{IP, Tuple{T, T}}, alg::I | |
ϵ = eps(T) | ||
if iszero(fl) | ||
return SciMLBase.build_solution(prob, alg, left, fl; | ||
retcode = ReturnCode.ExactSolutionLeft, left = left, | ||
right = right) | ||
retcode = ReturnCode.ExactSolutionLeft, left, right) | ||
elseif iszero(fr) | ||
return SciMLBase.build_solution(prob, alg, right, fr; | ||
retcode = ReturnCode.ExactSolutionRight, left = left, | ||
right = right) | ||
retcode = ReturnCode.ExactSolutionRight, left, right) | ||
end | ||
#defining variables/cache | ||
k1 = T(alg.k1) | ||
k2 = T(alg.k2) | ||
span = abs(right - left) | ||
k1 = T(alg.scaled_k1)/span | ||
n0 = T(alg.n0) | ||
n_h = ceil(log2(abs(right - left) / (2 * ϵ))) | ||
mid = (left + right) / 2 | ||
x_f = (fr * left - fl * right) / (fr - fl) | ||
xt = left | ||
xp = left | ||
r = zero(left) #minmax radius | ||
δ = zero(left) # truncation error | ||
σ = 1.0 | ||
ϵ_s = ϵ * 2^(n_h + n0) | ||
i = 0 #iteration | ||
while i <= maxiters | ||
#mid = (left + right) / 2 | ||
n_h = exponent(span / (2 * ϵ)) | ||
ϵ_s = ϵ * exp2(n_h + n0) | ||
T0 = zero(fl) | ||
|
||
i = 1 | ||
while i ≤ maxiters | ||
stats.nsteps += 1 | ||
span = abs(right - left) | ||
mid = (left + right) / 2 | ||
r = ϵ_s - (span / 2) | ||
δ = k1 * (span^k2) | ||
|
||
## Interpolation step ## | ||
x_f = left + (right - left) * (fl / (fl - fr)) | ||
x_f = left + span * (fl / (fl - fr)) # Interpolation Step | ||
|
||
## Truncation step ## | ||
σ = sign(mid - x_f) | ||
if δ <= abs(mid - x_f) | ||
xt = x_f + (σ * δ) | ||
else | ||
xt = mid | ||
end | ||
δ = max(k1 * span^2, eps(x_f)) | ||
diff = mid - x_f | ||
|
||
## Projection step ## | ||
if abs(xt - mid) <= r | ||
xp = xt | ||
else | ||
xp = mid - (σ * r) | ||
end | ||
xt = ifelse(δ ≤ abs(diff), x_f + copysign(δ, diff), mid) # Truncation Step | ||
|
||
## Update ## | ||
tmin, tmax = minmax(left, right) | ||
xp >= tmax && (xp = prevfloat(tmax)) | ||
xp <= tmin && (xp = nextfloat(tmin)) | ||
xp = ifelse(abs(xt - mid) ≤ r, xt, mid - copysign(r, diff)) # Projection Step | ||
if span < 2ϵ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch. This was based on SciML/NonlinearSolve.jl#548 where we have an abstol. I think this branch can just be deleted. |
||
return SciMLBase.build_solution( | ||
prob, alg, xt, f(xt); retcode = ReturnCode.Success, left, right | ||
) | ||
end | ||
yp = f(xp) | ||
stats.nf += 1 | ||
yps = yp * sign(fr) | ||
if yps > 0 | ||
right = xp | ||
fr = yp | ||
elseif yps < 0 | ||
left = xp | ||
fl = yp | ||
if yps > T0 | ||
right, fr = xp, yp | ||
elseif yps < T0 | ||
left, fl = xp, yp | ||
else | ||
left = prevfloat_tdir(xp, prob.tspan...) | ||
right = xp | ||
return SciMLBase.build_solution(prob, alg, left, f(left); | ||
retcode = ReturnCode.Success, left = left, | ||
right = right) | ||
return SciMLBase.build_solution( | ||
prob, alg, xp, yps; retcode = ReturnCode.Success, left, right | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another question: here we're no longer contracting the left - right interval for the solution object, does this change behavior in any case? I'm investigating a small outcome variation in a test in some internal code of ours that opts into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's definitely possible that this changes behavior slightly. It's very unclear why the previous code thought that this was trying to do. Specifically, this case only is hit if the function hits exactly 0 (i.e. it will not hit this even if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that makes sense; my concern is that while the actual crossing ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess another connected question (that is probably not very relevant practically except for sorting simultaneous events) is what should happen if there are multiple zeros in a row (e.g. for a sequence of adjacent floats for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upon further testing it appears that setting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upon further testing it appears that setting |
||
) | ||
end | ||
|
||
i += 1 | ||
mid = (left + right) / 2 | ||
ϵ_s /= 2 | ||
|
||
if nextfloat_tdir(left, prob.tspan...) == right | ||
return SciMLBase.build_solution(prob, alg, left, fl; | ||
retcode = ReturnCode.FloatingPointLimit, left = left, | ||
right = right) | ||
if nextfloat_tdir(left, left, right) == right | ||
return SciMLBase.build_solution( | ||
prob, alg, right, fr; retcode = ReturnCode.FloatingPointLimit, left, right | ||
) | ||
end | ||
end | ||
return SciMLBase.build_solution(prob, alg, left, fl; retcode = ReturnCode.MaxIters, | ||
|
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.
do you know if the lack of scaling based on
span
was intentional here? The NonlinearSolveBase verison already had it.