Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 307514e

Browse files
Jaquier Aurélien TristanTanguy Pierre Louis Damart
authored andcommitted
Added terminator to gracefully exit optimisation.
1 parent 60ac638 commit 307514e

File tree

5 files changed

+63
-6
lines changed

5 files changed

+63
-6
lines changed

bluepyopt/deapext/algorithms.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ def eaAlphaMuPlusLambdaCheckpoint(
9393
halloffame=None,
9494
cp_frequency=1,
9595
cp_filename=None,
96-
continue_cp=False):
96+
continue_cp=False,
97+
terminator=None):
9798
r"""This is the :math:`(~\alpha,\mu~,~\lambda)` evolutionary algorithm
9899
99100
Args:
@@ -108,6 +109,8 @@ def eaAlphaMuPlusLambdaCheckpoint(
108109
cp_frequency(int): generations between checkpoints
109110
cp_filename(string): path to checkpoint filename
110111
continue_cp(bool): whether to continue
112+
terminator (multiprocessing.Event): exit loop when is set.
113+
Not taken into account if None.
111114
"""
112115
<<<<<<< HEAD
113116

@@ -157,7 +160,9 @@ def eaAlphaMuPlusLambdaCheckpoint(
157160
# Begin the generational process
158161
gen = start_gen + 1
159162
stopping_params = {"gen": gen}
160-
while not(_check_stopping_criteria(stopping_criteria, stopping_params)):
163+
while utils.run_next_gen(
164+
not(_check_stopping_criteria(stopping_criteria, stopping_params)),
165+
terminator):
161166
offspring = _get_offspring(parents, toolbox, cxpb, mutpb)
162167

163168
population = parents + offspring

bluepyopt/deapext/optimisations.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ def run(self,
252252
continue_cp=False,
253253
cp_filename=None,
254254
cp_frequency=1,
255-
parent_population=None):
255+
parent_population=None,
256+
terminator=None):
256257
"""Run optimisation"""
257258
# Allow run function to override offspring_size
258259
# TODO probably in the future this should not be an object field
@@ -307,7 +308,8 @@ def run(self,
307308
halloffame=self.hof,
308309
cp_frequency=cp_frequency,
309310
continue_cp=continue_cp,
310-
cp_filename=cp_filename)
311+
cp_filename=cp_filename,
312+
terminator=terminator)
311313

312314
# Update hall of fame
313315
self.hof = hof

bluepyopt/deapext/optimisationsCMA.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,12 @@ def setup_deap(self):
233233
self.toolbox.register("map", self.map_function)
234234

235235
def run(
236-
self, max_ngen=0, cp_frequency=1, continue_cp=False, cp_filename=None
236+
self,
237+
max_ngen=0,
238+
cp_frequency=1,
239+
continue_cp=False,
240+
cp_filename=None,
241+
terminator=None,
237242
):
238243
""" Run the optimizer until a stopping criteria is met.
239244
@@ -242,6 +247,8 @@ def run(
242247
cp_frequency(int): generations between checkpoints
243248
continue_cp(bool): whether to continue
244249
cp_filename(string): path to checkpoint filename
250+
terminator (multiprocessing.Event): exit loop when is set.
251+
Not taken into account if None.
245252
"""
246253

247254
stats = self.get_stats()
@@ -288,7 +295,7 @@ def run(
288295
pop = CMA_es.get_population(self.to_space)
289296

290297
# Run until a termination criteria is met
291-
while CMA_es.active:
298+
while utils.run_next_gen(CMA_es.active, terminator):
292299
logger.info("Generation {}".format(gen))
293300

294301
# Generate the new populations

bluepyopt/deapext/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,10 @@ def uniform(lower_list, upper_list, dimensions):
137137
def reduce_method(meth):
138138
"""Overwrite reduce"""
139139
return (getattr, (meth.__self__, meth.__func__.__name__))
140+
141+
142+
def run_next_gen(criteria, terminator):
143+
"""Condition to stay inside the loop."""
144+
if terminator is None:
145+
return criteria
146+
return criteria and not terminator.is_set()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""bluepyopt.utils tests"""
2+
3+
import multiprocessing
4+
import time
5+
6+
import bluepyopt.deapext.utils as utils
7+
import nose.tools as nt
8+
9+
def flag(event):
10+
"""Send a multiprocessing event."""
11+
time.sleep(1)
12+
event.set()
13+
14+
def catch_event(event):
15+
"""Verify that run_next_gen changes when event is caught."""
16+
# None case
17+
nt.assert_true(utils.run_next_gen(True, None))
18+
19+
# event is not set case
20+
nt.assert_true(utils.run_next_gen(True, event))
21+
22+
# event is set by another process case
23+
time.sleep(2)
24+
nt.assert_equal(utils.run_next_gen(True, event), False)
25+
26+
def test_run_next_gen_condition():
27+
"""deapext.utils: Testing run_next_gen."""
28+
event = multiprocessing.Event()
29+
p1 = multiprocessing.Process(target=catch_event, args=(event,))
30+
p2 = multiprocessing.Process(target=flag, args=(event,))
31+
32+
p1.start()
33+
p2.start()
34+
35+
p1.join()
36+
p2.join()

0 commit comments

Comments
 (0)