Skip to content

Commit

Permalink
added time_limit for univariate optimization (#1092)
Browse files Browse the repository at this point in the history
* added time_limit for univariate optimization

* time_limit tests for univariate solvers
  • Loading branch information
christianhauschel authored Apr 29, 2024
1 parent 01b9391 commit cf5d08f
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,8 @@ abs_tol(r::UnivariateOptimizationResults) = r.abs_tol
time_limit(r::MultivariateOptimizationResults) = r.time_limit
time_run( r::MultivariateOptimizationResults) = r.time_run

time_limit(r::UnivariateOptimizationResults) = r.time_limit
time_run( r::UnivariateOptimizationResults) = r.time_run

time_limit(r::OptimizationResults) = error("time_limit is not implemented for $(summary(r)).")
time_run( r::OptimizationResults) = error("time_run is not implemented for $(summary(r)).")
9 changes: 9 additions & 0 deletions src/univariate/printing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ function Base.show(io::IO, t::OptimizationState{<:Real, GoldenSection})
end

function Base.show(io::IO, r::UnivariateOptimizationResults)

status_string = ""
if time_run(r) > time_limit(r)
status_string *= "failure (exceeded time limit of $(time_limit(r)))"
else
status_string = "success"
end

@printf io "Results of Optimization Algorithm\n"
@printf io " * Status: %s\n" status_string
@printf io " * Algorithm: %s\n" summary(r)
@printf io " * Search Interval: [%f, %f]\n" lower_bound(r) upper_bound(r)
@printf io " * Minimizer: %e\n" minimizer(r)
Expand Down
13 changes: 9 additions & 4 deletions src/univariate/solvers/brent.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ function optimize(
rel_tol::T = sqrt(eps(T)),
abs_tol::T = eps(T),
iterations::Integer = 1_000,
time_limit::Float64 = Inf,
store_trace::Bool = false,
show_trace::Bool = false,
show_warnings::Bool = true,
callback = nothing,
show_every = 1,
extended_trace::Bool = false) where T <: AbstractFloat
t0 = time()
options = (store_trace=store_trace, show_trace=show_trace, show_warnings=show_warnings, show_every=show_every, callback=callback)
options = (store_trace=store_trace, show_trace=show_trace, show_warnings=show_warnings, show_every=show_every, callback=callback, time_limit=time_limit)
if x_lower > x_upper
error("x_lower must be less than x_upper")
end
Expand Down Expand Up @@ -73,8 +74,8 @@ function optimize(
new_minimum=new_minimum)
stopped_by_callback = trace!(tr, nothing, state, iteration, mo, options, time()-t0)
end

while iteration < iterations && !stopped_by_callback
_time = time() - t0
while iteration < iterations && !stopped_by_callback && _time < time_limit

p = zero(T)
q = zero(T)
Expand Down Expand Up @@ -170,6 +171,7 @@ function optimize(
new_minimum=new_minimum)
stopped_by_callback = trace!(tr, nothing, state, iteration, mo, options, time()-t0)
end
_time = time() - t0
end

return UnivariateOptimizationResults(mo,
Expand All @@ -183,7 +185,10 @@ function optimize(
rel_tol,
abs_tol,
tr,
f_calls)
f_calls,
time_limit,
_time,
)
end


Expand Down
12 changes: 9 additions & 3 deletions src/univariate/solvers/golden_section.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function optimize(f, x_lower::T, x_upper::T,
rel_tol::T = sqrt(eps(T)),
abs_tol::T = eps(T),
iterations::Integer = 1_000,
time_limit::Float64 = Inf,
store_trace::Bool = false,
show_trace::Bool = false,
show_warnings::Bool = true,
Expand All @@ -34,7 +35,7 @@ function optimize(f, x_lower::T, x_upper::T,
error("x_lower must be less than x_upper")
end
t0 = time()
options = (store_trace=store_trace, show_trace=show_trace, show_warnings=show_warnings, show_every=show_every, callback=callback)
options = (store_trace=store_trace, show_trace=show_trace, show_warnings=show_warnings, show_every=show_every, callback=callback, time_limit=time_limit)
# Save for later
initial_lower = x_lower
initial_upper = x_upper
Expand Down Expand Up @@ -63,7 +64,9 @@ function optimize(f, x_lower::T, x_upper::T,
stopped_by_callback = trace!(tr, nothing, state, iteration, mo, options, time()-t0)
end

while iteration < iterations && !stopped_by_callback
_time = time() - t0

while iteration < iterations && !stopped_by_callback && _time < time_limit

x_tol = rel_tol * abs(new_minimizer) + abs_tol

Expand Down Expand Up @@ -113,6 +116,7 @@ function optimize(f, x_lower::T, x_upper::T,
new_minimum=new_minimum)
stopped_by_callback = trace!(tr, nothing, state, iteration, mo, options, time()-t0)
end
_time = time() - t0
end

return UnivariateOptimizationResults(mo,
Expand All @@ -126,7 +130,9 @@ function optimize(f, x_lower::T, x_upper::T,
rel_tol,
abs_tol,
tr,
f_calls)
f_calls,
time_limit,
_time)
end


Expand Down
2 changes: 2 additions & 0 deletions src/univariate/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ mutable struct UnivariateOptimizationResults{Tb,Tt,Tf, Tx,M,O<:UnivariateOptimiz
abs_tol::Tt
trace::OptimizationTrace{M}
f_calls::Int
time_limit::Float64
time_run::Float64
end
8 changes: 8 additions & 0 deletions test/univariate/solvers/brent.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,13 @@
@test Optim.converged(result)
@test Optim.minimum(result) == -1.0

## time limit
function slow_obj(x)
sleep(0.05)
return sin(x)
end
result = optimize(x -> slow_obj(x), 0, 2π, Brent(); time_limit=0.01)
@test result.f_calls == 1

result = Optim.optimize(x->sin(x), 0, 2π, Optim.Brent(); abs_tol=1e-4, store_trace=false, show_trace=true, iterations=2)
end
8 changes: 8 additions & 0 deletions test/univariate/solvers/golden_section.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@
@test Optim.minimum(result) == 2.0
@test_throws ErrorException optimize(identity, 2.0, 1.0, GoldenSection())

## time limit
function slow_obj(x)
sleep(0.05)
return sin(x)
end
result = optimize(x -> slow_obj(x), 0, 2π, GoldenSection(); time_limit=0.01)
@test result.f_calls == 1

result = Optim.optimize(x->sin(x), 0, 2π, Optim.GoldenSection(); abs_tol=1e-4, store_trace=false, show_trace=true, iterations=2)
end

0 comments on commit cf5d08f

Please sign in to comment.