From 2a8512732dff55fd95aa9f8c613165ecd523267e Mon Sep 17 00:00:00 2001 From: jlnav Date: Tue, 14 Apr 2026 10:56:08 -0500 Subject: [PATCH 1/8] remove use_persis_return_sim plus mypy fixes --- docs/data_structures/libE_specs.rst | 3 - libensemble/manager.py | 2 - libensemble/specs.py | 3 - .../test_persistent_sim_uniform_sampling.py | 80 ------------------- libensemble/tools/tools.py | 7 +- 5 files changed, 3 insertions(+), 92 deletions(-) delete mode 100644 libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py diff --git a/docs/data_structures/libE_specs.rst b/docs/data_structures/libE_specs.rst index 1a31b41b8..963ac9cc1 100644 --- a/docs/data_structures/libE_specs.rst +++ b/docs/data_structures/libE_specs.rst @@ -212,9 +212,6 @@ libEnsemble is primarily customized by setting options within a ``LibeSpecs`` in **use_persis_return_gen** [bool] = ``False``: Adds persistent generator output fields to the History array on return. - **use_persis_return_sim** [bool] = ``False``: - Adds persistent simulator output fields to the History array on return. - **final_gen_send** [bool] = ``False``: Send final simulation results to persistent generators before shutdown. The results will be sent along with the ``PERSIS_STOP`` tag. diff --git a/libensemble/manager.py b/libensemble/manager.py index 389c3b6cb..3cb7cd591 100644 --- a/libensemble/manager.py +++ b/libensemble/manager.py @@ -491,8 +491,6 @@ def _update_state_on_worker_msg(self, persis_info: dict, D_recv: dict, w: int) - if calc_status is FINISHED_PERSISTENT_GEN_TAG and self.libE_specs.get("use_persis_return_gen", False): self._ensure_sim_id_in_persis_in(final_data) self.hist.update_history_x_in(w, final_data, self.W[w]["gen_started_time"]) - elif calc_status is FINISHED_PERSISTENT_SIM_TAG and self.libE_specs.get("use_persis_return_sim", False): - self.hist.update_history_f(D_recv, self.kill_canceled_sims) else: logger.info(_PERSIS_RETURN_WARNING) self.W[w]["persis_state"] = 0 diff --git a/libensemble/specs.py b/libensemble/specs.py index 08b02462b..41157f40e 100644 --- a/libensemble/specs.py +++ b/libensemble/specs.py @@ -601,9 +601,6 @@ class LibeSpecs(BaseModel): use_persis_return_gen: bool | None = False """ Adds persistent generator output fields to the History array on return. """ - use_persis_return_sim: bool | None = False - """ Adds persistent simulator output fields to the History array on return. """ - final_gen_send: bool | None = False """ Send final simulation results to persistent generators before shutdown. diff --git a/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py b/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py deleted file mode 100644 index af2a7ac07..000000000 --- a/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -Runs libEnsemble on the 6-hump camel problem. Documented here: - https://www.sfu.ca/~ssurjano/camel6.html - -Execute via one of the following commands (e.g. 3 workers): - mpiexec -np 4 python test_persistent_sim_uniform_sampling.py - python test_persistent_sim_uniform_sampling.py --nworkers 3 - python test_persistent_sim_uniform_sampling.py --nworkers 3 --comms tcp - -When running with the above command, the number of concurrent evaluations of -the objective function will be 2, as one of the three workers will be the -persistent generator. -""" - -# Do not change these lines - they are parsed by run-tests.sh -# TESTSUITE_COMMS: mpi local tcp -# TESTSUITE_NPROCS: 3 4 -# TESTSUITE_OS_SKIP: WIN - -import sys - -import numpy as np - -from libensemble.gen_funcs.persistent_sampling import persistent_uniform as gen_f - -# Import libEnsemble items for this test -from libensemble.libE import libE -from libensemble.sim_funcs.six_hump_camel import persistent_six_hump_camel as sim_f -from libensemble.tools import add_unique_random_streams, parse_args, save_libE_output - -# from libensemble import logger -# logger.set_level("DEBUG") - -# Main block is necessary only when using local comms with spawn start method (default on macOS and Windows). -if __name__ == "__main__": - nworkers, is_manager, libE_specs, _ = parse_args() - libE_specs["num_resource_sets"] = nworkers - 1 # Only matters if sims use resources. - - # Only used to test returning/overwriting a point at the end of the persistent sim. - libE_specs["use_persis_return_sim"] = True - - if nworkers < 2: - sys.exit("Cannot run with a persistent worker if only one worker -- aborting...") - - n = 2 - - sim_specs = { - "sim_f": sim_f, - "in": ["x"], - "user": {"replace_final_fields": True}, - "out": [("f", float), ("grad", float, n)], - } - - gen_specs = { - "gen_f": gen_f, - "in": [], - "persis_in": ["sim_id", "f", "grad"], - "out": [("x", float, (n,))], - "initial_batch_size": 5, - "alt_type": True, - "user": { - "lb": np.array([-3, -2]), - "ub": np.array([3, 2]), - }, - } - - persis_info = add_unique_random_streams({}, nworkers + 1) - - exit_criteria = {"sim_max": 40, "wallclock_max": 300} - - # Perform the run - H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, persis_info, libE_specs=libE_specs) - - if is_manager: - assert len(np.unique(H["gen_ended_time"])) == 8 - assert not any((H["f"] == 0)) - # Should overwrite the last value (in fact last (nworker-1) values) with f(1,1) = 3.23333333 - assert not np.isclose(H["f"][0], 3.23333333) - assert np.isclose(H["f"][-1], 3.23333333) - save_libE_output(H, persis_info, __file__, nworkers) diff --git a/libensemble/tools/tools.py b/libensemble/tools/tools.py index fdffff78d..e31ca7f50 100644 --- a/libensemble/tools/tools.py +++ b/libensemble/tools/tools.py @@ -72,7 +72,6 @@ + "not currently added to the manager's history to avoid possibly overwriting, but\n" + "will be added to the manager's history in a future release. If you want to\n" + "overwrite/append, you can set the libE_specs option ``use_persis_return_gen``\n" - + "or ``use_persis_return_sim``" "\n" + 79 * "*" + "\n\n" ) @@ -91,7 +90,7 @@ def save_libE_output( persis_info: dict, basename: str, nworkers: int, - dest_path: str = None, + dest_path: str | Path = "", mess: str = "Run completed", append_attrs: bool = True, ) -> str: @@ -141,7 +140,7 @@ def save_libE_output( Append run attributes to the base filename. """ - if dest_path is None: + if not dest_path: dest_path = Path.cwd() else: dest_path = Path(dest_path) @@ -252,7 +251,7 @@ def check_basename_file_exists(): check_file_exists = check_basename_file_exists if basename else check_exact_file_exists sleep_interval = 0.1 - total_wait_time = 0 + total_wait_time = 0.0 file_exists = False while total_wait_time < max_wait: if check_file_exists(): From 181906b6fd235249d62d324652d9902ad7806ea7 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 08:56:55 -0500 Subject: [PATCH 2/8] remove use_persis_return_gen. restore deleted test. restore update_history_f from persis_sim. remove message warning that fields will be appended in upcoming release --- docs/data_structures/libE_specs.rst | 3 - libensemble/gen_funcs/persistent_sampling.py | 1 - libensemble/manager.py | 8 +- libensemble/specs.py | 3 - .../test_persistent_sim_uniform_sampling.py | 75 +++++++++++++++++++ ...ersistent_uniform_sampling_running_mean.py | 2 - 6 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py diff --git a/docs/data_structures/libE_specs.rst b/docs/data_structures/libE_specs.rst index 963ac9cc1..7afe0c5bb 100644 --- a/docs/data_structures/libE_specs.rst +++ b/docs/data_structures/libE_specs.rst @@ -209,9 +209,6 @@ libEnsemble is primarily customized by setting options within a ``LibeSpecs`` in **H_file_prefix** str | None = ``"libE_history"`` Prefix for ``H`` filename. - **use_persis_return_gen** [bool] = ``False``: - Adds persistent generator output fields to the History array on return. - **final_gen_send** [bool] = ``False``: Send final simulation results to persistent generators before shutdown. The results will be sent along with the ``PERSIS_STOP`` tag. diff --git a/libensemble/gen_funcs/persistent_sampling.py b/libensemble/gen_funcs/persistent_sampling.py index 420ab8679..a12002e5c 100644 --- a/libensemble/gen_funcs/persistent_sampling.py +++ b/libensemble/gen_funcs/persistent_sampling.py @@ -121,7 +121,6 @@ def sample_corners_with_probability(corners, p, b): running_total[row["corner_id"]] += row["f"] # Having received a PERSIS_STOP, update f_est field for all points and return - # For manager to honor final H_o return, must have set libE_specs["use_persis_return_gen"] = True f_est = running_total / number_of_samples H_o = np.zeros(len(sent), dtype=[("sim_id", int), ("corner_id", int), ("f_est", float)]) for count, i in enumerate(sent): diff --git a/libensemble/manager.py b/libensemble/manager.py index 3cb7cd591..7995d2da9 100644 --- a/libensemble/manager.py +++ b/libensemble/manager.py @@ -34,7 +34,7 @@ ) from libensemble.resources.resources import Resources from libensemble.tools.fields_keys import protected_libE_fields -from libensemble.tools.tools import _PERSIS_RETURN_WARNING, _USER_CALC_DIR_WARNING +from libensemble.tools.tools import _USER_CALC_DIR_WARNING from libensemble.utils.misc import _WorkerIndexer, extract_H_ranges from libensemble.utils.output_directory import EnsembleDirectory from libensemble.utils.timer import Timer @@ -488,11 +488,11 @@ def _update_state_on_worker_msg(self, persis_info: dict, D_recv: dict, w: int) - if calc_status in [FINISHED_PERSISTENT_SIM_TAG, FINISHED_PERSISTENT_GEN_TAG]: final_data = D_recv.get("calc_out", None) if isinstance(final_data, np.ndarray): - if calc_status is FINISHED_PERSISTENT_GEN_TAG and self.libE_specs.get("use_persis_return_gen", False): + if calc_status is FINISHED_PERSISTENT_GEN_TAG: self._ensure_sim_id_in_persis_in(final_data) self.hist.update_history_x_in(w, final_data, self.W[w]["gen_started_time"]) - else: - logger.info(_PERSIS_RETURN_WARNING) + elif calc_status is FINISHED_PERSISTENT_SIM_TAG: + self.hist.update_history_f(D_recv, self.kill_canceled_sims) self.W[w]["persis_state"] = 0 if self.W[w]["active_recv"]: self.W[w]["active"] = 0 diff --git a/libensemble/specs.py b/libensemble/specs.py index 1b9d80a28..4ac858f5a 100644 --- a/libensemble/specs.py +++ b/libensemble/specs.py @@ -686,9 +686,6 @@ def set_calc_dirs_on_input_dir(self): ``manager_port``, ``authkey``, and ``workerID``. ``nworkers`` is specified normally. """ - use_persis_return_gen: bool | None = False - """ Adds persistent generator output fields to the History array on return. """ - final_gen_send: bool | None = False """ Send final simulation results to persistent generators before shutdown. diff --git a/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py b/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py new file mode 100644 index 000000000..8649614b9 --- /dev/null +++ b/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py @@ -0,0 +1,75 @@ +""" +Runs libEnsemble on the 6-hump camel problem. Documented here: + https://www.sfu.ca/~ssurjano/camel6.html + +Execute via one of the following commands (e.g. 3 workers): + mpiexec -np 4 python test_persistent_sim_uniform_sampling.py + python test_persistent_sim_uniform_sampling.py --nworkers 3 + python test_persistent_sim_uniform_sampling.py --nworkers 3 --comms tcp + +When running with the above command, the number of concurrent evaluations of +the objective function will be 2, as one of the three workers will be the +persistent generator. +""" + +# Do not change these lines - they are parsed by run-tests.sh +# TESTSUITE_COMMS: mpi local tcp +# TESTSUITE_NPROCS: 3 4 +# TESTSUITE_OS_SKIP: WIN + +import sys + +import numpy as np + +from libensemble.gen_funcs.persistent_sampling import persistent_uniform as gen_f + +# Import libEnsemble items for this test +from libensemble.libE import libE +from libensemble.sim_funcs.six_hump_camel import persistent_six_hump_camel as sim_f +from libensemble.tools import parse_args, save_libE_output + +# from libensemble import logger +# logger.set_level("DEBUG") + +# Main block is necessary only when using local comms with spawn start method (default on macOS and Windows). +if __name__ == "__main__": + nworkers, is_manager, libE_specs, _ = parse_args() + libE_specs["num_resource_sets"] = nworkers - 1 # Only matters if sims use resources. + + if nworkers < 2: + sys.exit("Cannot run with a persistent worker if only one worker -- aborting...") + + n = 2 + + sim_specs = { + "sim_f": sim_f, + "in": ["x"], + "user": {"replace_final_fields": True}, + "out": [("f", float), ("grad", float, n)], + } + + gen_specs = { + "gen_f": gen_f, + "in": [], + "persis_in": ["sim_id", "f", "grad"], + "out": [("x", float, (n,))], + "initial_batch_size": 5, + "alt_type": True, + "user": { + "lb": np.array([-3, -2]), + "ub": np.array([3, 2]), + }, + } + + exit_criteria = {"sim_max": 40, "wallclock_max": 300} + + # Perform the run + H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, libE_specs=libE_specs) + + if is_manager: + assert len(np.unique(H["gen_ended_time"])) == 8 + assert not any((H["f"] == 0)) + # Should overwrite the last value (in fact last (nworker-1) values) with f(1,1) = 3.23333333 + assert not np.isclose(H["f"][0], 3.23333333) + assert np.isclose(H["f"][-1], 3.23333333) + save_libE_output(H, persis_info, __file__, nworkers) diff --git a/libensemble/tests/functionality_tests/test_persistent_uniform_sampling_running_mean.py b/libensemble/tests/functionality_tests/test_persistent_uniform_sampling_running_mean.py index 103abcfa4..acd15d370 100644 --- a/libensemble/tests/functionality_tests/test_persistent_uniform_sampling_running_mean.py +++ b/libensemble/tests/functionality_tests/test_persistent_uniform_sampling_running_mean.py @@ -29,8 +29,6 @@ if __name__ == "__main__": nworkers, is_manager, libE_specs, _ = parse_args() - libE_specs["use_persis_return_gen"] = True - if nworkers < 2: sys.exit("Cannot run with a persistent worker if only one worker -- aborting...") From 65f05135d45fb736a4eddb380e854b1627efdfe1 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 09:04:55 -0500 Subject: [PATCH 3/8] cleanup some persis gens/sims to return None upon finishing except when explicitly updating after loop --- libensemble/gen_funcs/persistent_fd_param_finder.py | 2 +- libensemble/gen_funcs/uniform_or_localopt.py | 7 ++----- libensemble/sim_funcs/six_hump_camel.py | 6 ++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libensemble/gen_funcs/persistent_fd_param_finder.py b/libensemble/gen_funcs/persistent_fd_param_finder.py index d72f64537..2f45327a7 100644 --- a/libensemble/gen_funcs/persistent_fd_param_finder.py +++ b/libensemble/gen_funcs/persistent_fd_param_finder.py @@ -119,4 +119,4 @@ def fd_param_finder(H, persis_info, gen_specs, libE_info): tag, Work, calc_in = ps.send_recv(H0) persis_info["Fnoise"] = Fnoise - return H0, persis_info, FINISHED_PERSISTENT_GEN_TAG + return None, persis_info, FINISHED_PERSISTENT_GEN_TAG diff --git a/libensemble/gen_funcs/uniform_or_localopt.py b/libensemble/gen_funcs/uniform_or_localopt.py index fb7b2b89a..916443c85 100644 --- a/libensemble/gen_funcs/uniform_or_localopt.py +++ b/libensemble/gen_funcs/uniform_or_localopt.py @@ -25,9 +25,7 @@ def uniform_or_localopt(H, persis_info, gen_specs, libE_info): `test_uniform_sampling_then_persistent_localopt_runs.py `_ # noqa """ if libE_info.get("persistent"): - x_opt, persis_info_updates, tag_out = try_and_run_nlopt(H, gen_specs, libE_info) - H_o = [] - return H_o, persis_info_updates, tag_out + return try_and_run_nlopt(H, gen_specs, libE_info) else: rng = get_rng(gen_specs, libE_info) ub = gen_specs["user"]["ub"] @@ -109,10 +107,9 @@ def nlopt_obj_fun(x, grad): if exit_code > 0 and exit_code < 5: persis_info_updates["x_opt"] = x_opt except Exception: # Raised when manager sent PERSIS_STOP or STOP_TAG - x_opt = [] persis_info_updates = {} - return x_opt, persis_info_updates, FINISHED_PERSISTENT_GEN_TAG + return None, persis_info_updates, FINISHED_PERSISTENT_GEN_TAG def add_to_Out(H_o, x, i, ub, lb, local=False, active=False): diff --git a/libensemble/sim_funcs/six_hump_camel.py b/libensemble/sim_funcs/six_hump_camel.py index 8a49a0762..f453bf5bb 100644 --- a/libensemble/sim_funcs/six_hump_camel.py +++ b/libensemble/sim_funcs/six_hump_camel.py @@ -94,15 +94,13 @@ def persistent_six_hump_camel(H, persis_info, sim_specs, libE_info): tag, Work, calc_in = ps.send_recv(H_o) - final_return = None - # Overwrite final point - for testing only if sim_specs["user"].get("replace_final_fields", 0): calc_in = np.ones(1, dtype=[("x", float, (2,))]) H_o, persis_info = six_hump_camel(calc_in, persis_info, sim_specs, libE_info) - final_return = H_o + return H_o, persis_info, FINISHED_PERSISTENT_SIM_TAG - return final_return, persis_info, FINISHED_PERSISTENT_SIM_TAG + return None, persis_info, FINISHED_PERSISTENT_SIM_TAG def six_hump_camel_func(x): From 35741f4ec96c6419144a2d35e142224935e538e1 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 11:09:40 -0500 Subject: [PATCH 4/8] with APOSMM's returned H now completely respected, it may not have the latest status of the last few complete sims. So it's sim_ended count may not necessarily match sim_max --- .../tests/regression_tests/test_persistent_aposmm_scipy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libensemble/tests/regression_tests/test_persistent_aposmm_scipy.py b/libensemble/tests/regression_tests/test_persistent_aposmm_scipy.py index 111f73af1..6556a6c73 100644 --- a/libensemble/tests/regression_tests/test_persistent_aposmm_scipy.py +++ b/libensemble/tests/regression_tests/test_persistent_aposmm_scipy.py @@ -127,4 +127,4 @@ H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, alloc_specs=alloc_specs, libE_specs=libE_specs) if is_manager: - assert np.sum(H["sim_ended"]) >= exit_criteria["sim_max"], "Run didn't finish" + assert np.sum(H["sim_ended"]) >= exit_criteria["sim_max"] - 10, "Not enough runs finished" From 65358faed30aae1b96a6be967f05dbfd59739d14 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 11:41:51 -0500 Subject: [PATCH 5/8] last couple runs don't get their "f"s updated now with APOSMM's H_out getting respected --- .../test_persistent_aposmm_ibcdfo_manifold_sampling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libensemble/tests/regression_tests/test_persistent_aposmm_ibcdfo_manifold_sampling.py b/libensemble/tests/regression_tests/test_persistent_aposmm_ibcdfo_manifold_sampling.py index 0ac502cf6..8d90b523e 100644 --- a/libensemble/tests/regression_tests/test_persistent_aposmm_ibcdfo_manifold_sampling.py +++ b/libensemble/tests/regression_tests/test_persistent_aposmm_ibcdfo_manifold_sampling.py @@ -119,7 +119,7 @@ def synthetic_beamline_mapping(H, _, sim_specs): H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, alloc_specs=alloc_specs, libE_specs=libE_specs) if is_manager: - assert np.min(H["f"]) == 2.0, "The best is 2" + assert np.min(H["f"][H["f"] > 0]) == 2.0, "The best is 2" # nonzero assert persis_info[0].get("run_order"), "Run_order should have been given back" assert flag == 0 From 91d3624da8d885e502ad3ac68100524a3e2af570 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 13:47:49 -0500 Subject: [PATCH 6/8] remove use_persis_return_sim/gen warning --- libensemble/tools/tools.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/libensemble/tools/tools.py b/libensemble/tools/tools.py index 61e17864f..ea7e76a8c 100644 --- a/libensemble/tools/tools.py +++ b/libensemble/tools/tools.py @@ -62,19 +62,6 @@ + "\n\n" ) -# ==================== Warning that persistent return data is not used ========== - -_PERSIS_RETURN_WARNING = ( - "\n" - + 79 * "*" - + "\n" - + "A persistent worker has returned history data on shutdown. This data is\n" - + "not currently added to the manager's history to avoid possibly overwriting, but\n" - + "will be added to the manager's history in a future release. If you want to\n" - + "overwrite/append, you can set the libE_specs option ``use_persis_return_gen``\n" - "\n" + 79 * "*" + "\n\n" -) - def _get_shortname(basename): script_name = os.path.splitext(os.path.basename(basename))[0] From 4e5ada4d2cb3be3f64782b247d21b6a7d5d4eac8 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 29 Apr 2026 14:10:22 -0500 Subject: [PATCH 7/8] change dependabot to only check for updates monthly --- .github/dependabot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 21ca389e0..b3000567e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,7 +10,7 @@ updates: - package-ecosystem: github-actions directory: / schedule: - interval: weekly # Reduced frequency + interval: monthly # Reduced frequency target-branch: "develop" groups: actions-updates: @@ -20,7 +20,7 @@ updates: - package-ecosystem: pip directory: / schedule: - interval: weekly # Reduced frequency + interval: monthly # Reduced frequency target-branch: "develop" groups: python-updates: @@ -30,7 +30,7 @@ updates: - package-ecosystem: gitsubmodule directory: / schedule: - interval: weekly # Reduced frequency + interval: monthly # Reduced frequency target-branch: "develop" groups: submodule-updates: From f18029ee5fbac6994b7345ec6dac0e5779c8fd5e Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 30 Apr 2026 17:01:47 -0500 Subject: [PATCH 8/8] fix bug where final H getting returned from a gen overwrote "protected" fields. Noticed with test_persistent_aposmm_dfols not evaluating all "actual" sim-completed sims for any f below 3000 since the gen overwrote sim-ended --- libensemble/history.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/libensemble/history.py b/libensemble/history.py index aa16a4d77..80f848cca 100644 --- a/libensemble/history.py +++ b/libensemble/history.py @@ -68,15 +68,22 @@ def __init__( H[field][: len(H0)] = H0[field] if "sim_started" not in fields: - logger.manager_warning("Marking entries in H0 as having been 'sim_started' and 'sim_ended'") + logger.manager_warning( # type: ignore[attr-defined] + "Marking entries in H0 as having been " + "'sim_started' and 'sim_ended'" + ) + H["sim_started"][: len(H0)] = 1 H["sim_ended"][: len(H0)] = 1 elif "sim_ended" not in fields: - logger.manager_warning("Marking entries in H0 as having been 'sim_ended' if 'sim_started'") + logger.manager_warning( # type: ignore[attr-defined] + "Marking entries in H0 as having been " + "'sim_ended' if 'sim_started'" + ) + H["sim_ended"][: len(H0)] = H0["sim_started"] if "sim_id" not in fields: - logger.manager_warning("Assigning sim_ids to entries in H0") + logger.manager_warning("Assigning sim_ids to entries in H0") # type: ignore[attr-defined] + H["sim_id"][: len(H0)] = np.arange(0, len(H0)) else: H = np.zeros(L + len(H0), dtype=specs_dtype_list) @@ -130,8 +137,11 @@ def update_history_f(self, D: dict, kill_canceled_sims: bool = False) -> None: for j, ind in enumerate(new_inds): for field in fields: - if self.safe_mode: - assert field not in protected_libE_fields, "The field '" + field + "' is protected" + if field in protected_libE_fields: + if self.safe_mode: + assert False, "The field '" + field + "' is protected" + continue + if np.isscalar(returned_H[field][j]) or returned_H.dtype[field].hasobject: self.H[field][ind] = returned_H[field][j] else: @@ -194,9 +204,10 @@ def update_history_to_gen(self, q_inds: npt.NDArray): self.H["gen_informed"][ind] = True if self.using_H0 and not self.given_back_warned: - logger.manager_warning( - "Giving entries in H0 back to gen. Marking entries in H0 as 'gen_informed' if 'sim_ended'." + logger.manager_warning( # type: ignore[attr-defined] + "Giving entries in H0 back to gen. Marking entries in " + "H0 as 'gen_informed' if 'sim_ended'." ) + self.given_back_warned = True self.H["gen_informed_time"][q_inds] = t @@ -250,8 +261,11 @@ def update_history_x_in(self, gen_worker: int, D: npt.NDArray, gen_started_time: update_inds = D["sim_id"] for field in D.dtype.names: - if self.safe_mode: - assert field not in protected_libE_fields, "The field '" + field + "' is protected" + if field in protected_libE_fields: + if self.safe_mode: + assert False, "The field '" + field + "' is protected" + continue + self.H[field][update_inds] = D[field] first_gen_inds = update_inds[self.H["gen_ended_time"][update_inds] == 0]