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: diff --git a/docs/data_structures/libE_specs.rst b/docs/data_structures/libE_specs.rst index 1a31b41b8..7afe0c5bb 100644 --- a/docs/data_structures/libE_specs.rst +++ b/docs/data_structures/libE_specs.rst @@ -209,12 +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. - - **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/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/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/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/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] diff --git a/libensemble/manager.py b/libensemble/manager.py index 389c3b6cb..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,13 +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"]) - elif calc_status is FINISHED_PERSISTENT_SIM_TAG and self.libE_specs.get("use_persis_return_sim", False): + elif calc_status is FINISHED_PERSISTENT_SIM_TAG: self.hist.update_history_f(D_recv, self.kill_canceled_sims) - else: - logger.info(_PERSIS_RETURN_WARNING) self.W[w]["persis_state"] = 0 if self.W[w]["active_recv"]: self.W[w]["active"] = 0 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): diff --git a/libensemble/specs.py b/libensemble/specs.py index 6b405728f..4ac858f5a 100644 --- a/libensemble/specs.py +++ b/libensemble/specs.py @@ -686,12 +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. """ - - 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 index adc49a707..8649614b9 100644 --- a/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py +++ b/libensemble/tests/functionality_tests/test_persistent_sim_uniform_sampling.py @@ -36,9 +36,6 @@ 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...") 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...") 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 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" diff --git a/libensemble/tools/tools.py b/libensemble/tools/tools.py index 4caa40873..ea7e76a8c 100644 --- a/libensemble/tools/tools.py +++ b/libensemble/tools/tools.py @@ -62,20 +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" - + "or ``use_persis_return_sim``" - "\n" + 79 * "*" + "\n\n" -) - def _get_shortname(basename): script_name = os.path.splitext(os.path.basename(basename))[0]