Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions ext/MultiObjectiveAlgorithmsPolyhedraExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ function MOA.minimize_multiobjective!(
H = _halfspaces(IPS)
count = 0
while !isempty(H)
if MOA._time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
ret = MOA._check_premature_termination(model, start_time)
if ret !== nothing
status = ret
break
end
count += 1
Expand Down
49 changes: 33 additions & 16 deletions src/MultiObjectiveAlgorithms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,21 +185,6 @@ function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, ::Nothing)
return
end

function _time_limit_exceeded(model::Optimizer, start_time::Float64)
time_limit = MOI.get(model, MOI.TimeLimitSec())
if time_limit === nothing
return false
end
time_remaining = time_limit - (time() - start_time)
if time_remaining <= 0
return true
end
if MOI.supports(model.inner, MOI.TimeLimitSec())
MOI.set(model.inner, MOI.TimeLimitSec(), time_remaining)
end
return false
end

### SolveTimeSec

function MOI.get(model::Optimizer, ::MOI.SolveTimeSec)
Expand Down Expand Up @@ -604,7 +589,7 @@ end

function _compute_ideal_point(model::Optimizer, start_time)
for (i, f) in enumerate(MOI.Utilities.eachscalar(model.f))
if _time_limit_exceeded(model, start_time)
if _check_premature_termination(model, start_time) !== nothing
return
end
if !isnan(model.ideal_point[i])
Expand Down Expand Up @@ -644,7 +629,39 @@ function optimize_multiobjective!(
return minimize_multiobjective!(algorithm, model)
end

function _check_interrupt(f)
try
return reenable_sigint(f)
catch ex
if !(ex isa InterruptException)
rethrow(ex)
end
return MOI.INTERRUPTED
end
end

function _check_premature_termination(model::Optimizer, start_time::Float64)
return _check_interrupt() do
time_limit = MOI.get(model, MOI.TimeLimitSec())
if time_limit !== nothing
time_remaining = time_limit - (time() - start_time)
if time_remaining <= 0
return MOI.TIME_LIMIT
end
if MOI.supports(model.inner, MOI.TimeLimitSec())
MOI.set(model.inner, MOI.TimeLimitSec(), time_remaining)
end
end
return
end
end

function MOI.optimize!(model::Optimizer)
disable_sigint(() -> _optimize!(model))
return
end

function _optimize!(model::Optimizer)
start_time = time()
empty!(model.solutions)
model.termination_status = MOI.OPTIMIZE_NOT_CALLED
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/Chalmet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ function minimize_multiobjective!(algorithm::Chalmet, model::Optimizer)
push!(Q, (1, 2))
t = 3
while !isempty(Q)
if _time_limit_exceeded(model, start_time)
return MOI.TIME_LIMIT, solutions
if (ret = _check_premature_termination(model, start_time)) !== nothing
return ret, solutions
end
r, s = pop!(Q)
yr, ys = solutions[r].y, solutions[s].y
Expand Down
12 changes: 6 additions & 6 deletions src/algorithms/Dichotomy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,16 @@ function optimize_multiobjective!(algorithm::Dichotomy, model::Optimizer)
error("Only scalar or bi-objective problems supported.")
end
if MOI.output_dimension(model.f) == 1
if _time_limit_exceeded(model, start_time)
return MOI.TIME_LIMIT, nothing
if (ret = _check_premature_termination(model, start_time)) !== nothing
return ret, nothing
end
status, solution = _solve_weighted_sum(model, algorithm, [1.0])
return status, [solution]
end
solutions = Dict{Float64,SolutionPoint}()
for (i, w) in (1 => 1.0, 2 => 0.0)
if _time_limit_exceeded(model, start_time)
return MOI.TIME_LIMIT, nothing
if (ret = _check_premature_termination(model, start_time)) !== nothing
return ret, nothing
end
status, solution = _solve_weighted_sum(model, algorithm, [w, 1.0 - w])
if !_is_scalar_status_optimal(status)
Expand All @@ -103,8 +103,8 @@ function optimize_multiobjective!(algorithm::Dichotomy, model::Optimizer)
limit = MOI.get(algorithm, SolutionLimit())
status = MOI.OPTIMAL
while length(queue) > 0 && length(solutions) < limit
if _time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
(a, b) = popfirst!(queue)
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/DominguezRios.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ function minimize_multiobjective!(algorithm::DominguezRios, model::Optimizer)
k = 0
status = MOI.OPTIMAL
while any(!isempty(l) for l in L)
if _time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
i, k = _select_next_box(L, k)
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/EpsilonConstraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ function minimize_multiobjective!(
bound -= constant
status = MOI.OPTIMAL
for _ in 3:n_points
if _time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
MOI.set(model, MOI.ConstraintSet(), ci, MOI.LessThan{Float64}(bound))
Expand Down
5 changes: 3 additions & 2 deletions src/algorithms/KirlikSayin.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ function minimize_multiobjective!(algorithm::KirlikSayin, model::Optimizer)
L = [_Rectangle(_project(yI, k), _project(yN, k))]
status = MOI.OPTIMAL
while !isempty(L)
if _time_limit_exceeded(model, start_time)
return MOI.TIME_LIMIT, solutions
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
max_volume_index = argmax([_volume(Rᵢ, _project(yI, k)) for Rᵢ in L])
uᵢ = L[max_volume_index].u
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/Lexicographic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ function _solve_in_sequence(
solution = SolutionPoint[]
status = MOI.OPTIMAL
for i in sequence
if _time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
f = scalars[i]
Expand Down
5 changes: 3 additions & 2 deletions src/algorithms/RandomWeighting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ function optimize_multiobjective!(algorithm::RandomWeighting, model::Optimizer)
# * then the outer loop goes again
while length(solutions) < MOI.get(algorithm, SolutionLimit())
while length(solutions) < MOI.get(algorithm, SolutionLimit())
if _time_limit_exceeded(model, start_time)
return MOI.TIME_LIMIT, filter_nondominated(sense, solutions)
ret = _check_premature_termination(model, start_time)
if ret !== nothing
return ret, filter_nondominated(sense, solutions)
end
weights = rand(P)
f = _scalarise(model.f, weights)
Expand Down
4 changes: 2 additions & 2 deletions src/algorithms/TambyVanderpooten.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ function minimize_multiobjective!(
U_N[yN] = [[_get_child(yN, yI, k)] for k in 1:n]
status = MOI.OPTIMAL
while !isempty(U_N)
if _time_limit_exceeded(model, start_time)
status = MOI.TIME_LIMIT
if (ret = _check_premature_termination(model, start_time)) !== nothing
status = ret
break
end
k, u = _select_search_zone(U_N, yI, yN)
Expand Down
9 changes: 9 additions & 0 deletions test/test_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,15 @@ function test_SubproblemCount()
return
end

function test_check_interrupt()
function _test_check_interrupt(err)
return disable_sigint(() -> MOA._check_interrupt(() -> throw(err)))
end
@test _test_check_interrupt(InterruptException()) == MOI.INTERRUPTED
@test_throws ArgumentError("") _test_check_interrupt(ArgumentError(""))
return
end

end # module

TestModel.run_tests()
Loading