Skip to content

Commit 24decec

Browse files
authored
Add support for interrupting during the solve loops (#140)
1 parent 244083f commit 24decec

11 files changed

+67
-38
lines changed

ext/MultiObjectiveAlgorithmsPolyhedraExt.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ function MOA.minimize_multiobjective!(
101101
H = _halfspaces(IPS)
102102
count = 0
103103
while !isempty(H)
104-
if MOA._time_limit_exceeded(model, start_time)
105-
status = MOI.TIME_LIMIT
104+
ret = MOA._check_premature_termination(model, start_time)
105+
if ret !== nothing
106+
status = ret
106107
break
107108
end
108109
count += 1

src/MultiObjectiveAlgorithms.jl

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,6 @@ function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, ::Nothing)
185185
return
186186
end
187187

188-
function _time_limit_exceeded(model::Optimizer, start_time::Float64)
189-
time_limit = MOI.get(model, MOI.TimeLimitSec())
190-
if time_limit === nothing
191-
return false
192-
end
193-
time_remaining = time_limit - (time() - start_time)
194-
if time_remaining <= 0
195-
return true
196-
end
197-
if MOI.supports(model.inner, MOI.TimeLimitSec())
198-
MOI.set(model.inner, MOI.TimeLimitSec(), time_remaining)
199-
end
200-
return false
201-
end
202-
203188
### SolveTimeSec
204189

205190
function MOI.get(model::Optimizer, ::MOI.SolveTimeSec)
@@ -604,7 +589,7 @@ end
604589

605590
function _compute_ideal_point(model::Optimizer, start_time)
606591
for (i, f) in enumerate(MOI.Utilities.eachscalar(model.f))
607-
if _time_limit_exceeded(model, start_time)
592+
if _check_premature_termination(model, start_time) !== nothing
608593
return
609594
end
610595
if !isnan(model.ideal_point[i])
@@ -644,7 +629,39 @@ function optimize_multiobjective!(
644629
return minimize_multiobjective!(algorithm, model)
645630
end
646631

632+
function _check_interrupt(f)
633+
try
634+
return reenable_sigint(f)
635+
catch ex
636+
if !(ex isa InterruptException)
637+
rethrow(ex)
638+
end
639+
return MOI.INTERRUPTED
640+
end
641+
end
642+
643+
function _check_premature_termination(model::Optimizer, start_time::Float64)
644+
return _check_interrupt() do
645+
time_limit = MOI.get(model, MOI.TimeLimitSec())
646+
if time_limit !== nothing
647+
time_remaining = time_limit - (time() - start_time)
648+
if time_remaining <= 0
649+
return MOI.TIME_LIMIT
650+
end
651+
if MOI.supports(model.inner, MOI.TimeLimitSec())
652+
MOI.set(model.inner, MOI.TimeLimitSec(), time_remaining)
653+
end
654+
end
655+
return
656+
end
657+
end
658+
647659
function MOI.optimize!(model::Optimizer)
660+
disable_sigint(() -> _optimize!(model))
661+
return
662+
end
663+
664+
function _optimize!(model::Optimizer)
648665
start_time = time()
649666
empty!(model.solutions)
650667
model.termination_status = MOI.OPTIMIZE_NOT_CALLED

src/algorithms/Chalmet.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ function minimize_multiobjective!(algorithm::Chalmet, model::Optimizer)
101101
push!(Q, (1, 2))
102102
t = 3
103103
while !isempty(Q)
104-
if _time_limit_exceeded(model, start_time)
105-
return MOI.TIME_LIMIT, solutions
104+
if (ret = _check_premature_termination(model, start_time)) !== nothing
105+
return ret, solutions
106106
end
107107
r, s = pop!(Q)
108108
yr, ys = solutions[r].y, solutions[s].y

src/algorithms/Dichotomy.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,16 @@ function optimize_multiobjective!(algorithm::Dichotomy, model::Optimizer)
7777
error("Only scalar or bi-objective problems supported.")
7878
end
7979
if MOI.output_dimension(model.f) == 1
80-
if _time_limit_exceeded(model, start_time)
81-
return MOI.TIME_LIMIT, nothing
80+
if (ret = _check_premature_termination(model, start_time)) !== nothing
81+
return ret, nothing
8282
end
8383
status, solution = _solve_weighted_sum(model, algorithm, [1.0])
8484
return status, [solution]
8585
end
8686
solutions = Dict{Float64,SolutionPoint}()
8787
for (i, w) in (1 => 1.0, 2 => 0.0)
88-
if _time_limit_exceeded(model, start_time)
89-
return MOI.TIME_LIMIT, nothing
88+
if (ret = _check_premature_termination(model, start_time)) !== nothing
89+
return ret, nothing
9090
end
9191
status, solution = _solve_weighted_sum(model, algorithm, [w, 1.0 - w])
9292
if !_is_scalar_status_optimal(status)
@@ -103,8 +103,8 @@ function optimize_multiobjective!(algorithm::Dichotomy, model::Optimizer)
103103
limit = MOI.get(algorithm, SolutionLimit())
104104
status = MOI.OPTIMAL
105105
while length(queue) > 0 && length(solutions) < limit
106-
if _time_limit_exceeded(model, start_time)
107-
status = MOI.TIME_LIMIT
106+
if (ret = _check_premature_termination(model, start_time)) !== nothing
107+
status = ret
108108
break
109109
end
110110
(a, b) = popfirst!(queue)

src/algorithms/DominguezRios.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ function minimize_multiobjective!(algorithm::DominguezRios, model::Optimizer)
183183
k = 0
184184
status = MOI.OPTIMAL
185185
while any(!isempty(l) for l in L)
186-
if _time_limit_exceeded(model, start_time)
187-
status = MOI.TIME_LIMIT
186+
if (ret = _check_premature_termination(model, start_time)) !== nothing
187+
status = ret
188188
break
189189
end
190190
i, k = _select_next_box(L, k)

src/algorithms/EpsilonConstraint.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ function minimize_multiobjective!(
111111
bound -= constant
112112
status = MOI.OPTIMAL
113113
for _ in 3:n_points
114-
if _time_limit_exceeded(model, start_time)
115-
status = MOI.TIME_LIMIT
114+
if (ret = _check_premature_termination(model, start_time)) !== nothing
115+
status = ret
116116
break
117117
end
118118
MOI.set(model, MOI.ConstraintSet(), ci, MOI.LessThan{Float64}(bound))

src/algorithms/KirlikSayin.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ function minimize_multiobjective!(algorithm::KirlikSayin, model::Optimizer)
117117
L = [_Rectangle(_project(yI, k), _project(yN, k))]
118118
status = MOI.OPTIMAL
119119
while !isempty(L)
120-
if _time_limit_exceeded(model, start_time)
121-
return MOI.TIME_LIMIT, solutions
120+
if (ret = _check_premature_termination(model, start_time)) !== nothing
121+
status = ret
122+
break
122123
end
123124
max_volume_index = argmax([_volume(Rᵢ, _project(yI, k)) for Rᵢ in L])
124125
uᵢ = L[max_volume_index].u

src/algorithms/Lexicographic.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ function _solve_in_sequence(
124124
solution = SolutionPoint[]
125125
status = MOI.OPTIMAL
126126
for i in sequence
127-
if _time_limit_exceeded(model, start_time)
128-
status = MOI.TIME_LIMIT
127+
if (ret = _check_premature_termination(model, start_time)) !== nothing
128+
status = ret
129129
break
130130
end
131131
f = scalars[i]

src/algorithms/RandomWeighting.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ function optimize_multiobjective!(algorithm::RandomWeighting, model::Optimizer)
6060
# * then the outer loop goes again
6161
while length(solutions) < MOI.get(algorithm, SolutionLimit())
6262
while length(solutions) < MOI.get(algorithm, SolutionLimit())
63-
if _time_limit_exceeded(model, start_time)
64-
return MOI.TIME_LIMIT, filter_nondominated(sense, solutions)
63+
ret = _check_premature_termination(model, start_time)
64+
if ret !== nothing
65+
return ret, filter_nondominated(sense, solutions)
6566
end
6667
weights = rand(P)
6768
f = _scalarise(model.f, weights)

src/algorithms/TambyVanderpooten.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ function minimize_multiobjective!(
123123
U_N[yN] = [[_get_child(yN, yI, k)] for k in 1:n]
124124
status = MOI.OPTIMAL
125125
while !isempty(U_N)
126-
if _time_limit_exceeded(model, start_time)
127-
status = MOI.TIME_LIMIT
126+
if (ret = _check_premature_termination(model, start_time)) !== nothing
127+
status = ret
128128
break
129129
end
130130
k, u = _select_search_zone(U_N, yI, yN)

0 commit comments

Comments
 (0)