-
Notifications
You must be signed in to change notification settings - Fork 24
/
start_only_persistent.py
68 lines (55 loc) · 3.32 KB
/
start_only_persistent.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import numpy as np
from libensemble.tools.alloc_support import avail_worker_ids, sim_work, gen_work, count_persis_gens
def only_persistent_gens(W, H, sim_specs, gen_specs, alloc_specs, persis_info):
"""
This allocation function will give simulation work if possible, but
otherwise start up to 1 persistent generator. If all points requested by
the persistent generator have been returned from the simulation evaluation,
then this information is given back to the persistent generator.
.. seealso::
`test_persistent_uniform_sampling.py <https://github.com/Libensemble/libensemble/blob/develop/libensemble/tests/regression_tests/test_persistent_uniform_sampling.py>`_ # noqa
`test_persistent_uniform_sampling_async.py <https://github.com/Libensemble/libensemble/blob/develop/libensemble/tests/regression_tests/test_persistent_uniform_sampling_async.py>`_ # noqa
"""
Work = {}
gen_count = count_persis_gens(W)
if persis_info.get('gen_started') and gen_count == 0:
# The one persistent worker is done. Exiting
return Work, persis_info, 1
for i in avail_worker_ids(W, persistent=True):
if gen_specs['user'].get('async', False):
# If i is in persistent mode, asynchronous behavior is desired, and
# *any* of its calculated values have returned, give them back to i.
# Otherwise, give nothing to i
returned_but_not_given = np.logical_and.reduce((H['returned'], ~H['given_back'], H['gen_worker'] == i))
if np.any(returned_but_not_given):
inds_to_give = np.where(returned_but_not_given)[0]
gen_work(Work, i,
sim_specs['in'] + [n[0] for n in sim_specs['out']] + [('sim_id')],
np.atleast_1d(inds_to_give), persis_info[i], persistent=True)
H['given_back'][inds_to_give] = True
else:
# If i is in persistent mode, batch behavior is desired, and
# *all* of its calculated values have returned, give them back to i.
# Otherwise, give nothing to i
gen_inds = (H['gen_worker'] == i)
if np.all(H['returned'][gen_inds]):
last_time_gen_gave_batch = np.max(H['gen_time'][gen_inds])
inds_to_give = H['sim_id'][gen_inds][H['gen_time'][gen_inds] == last_time_gen_gave_batch]
gen_work(Work, i,
sim_specs['in'] + [n[0] for n in sim_specs['out']] + [('sim_id')],
np.atleast_1d(inds_to_give), persis_info[i], persistent=True)
H['given_back'][inds_to_give] = True
task_avail = ~H['given']
for i in avail_worker_ids(W, persistent=False):
if np.any(task_avail):
# perform sim evaluations (if they exist in History).
sim_ids_to_send = np.nonzero(task_avail)[0][0] # oldest point
sim_work(Work, i, sim_specs['in'], np.atleast_1d(sim_ids_to_send), persis_info[i])
task_avail[sim_ids_to_send] = False
elif gen_count == 0:
# Finally, call a persistent generator as there is nothing else to do.
gen_count += 1
gen_work(Work, i, gen_specs['in'], range(len(H)), persis_info[i],
persistent=True)
persis_info['gen_started'] = True
return Work, persis_info, 0