Skip to content

Commit cefcf2e

Browse files
authored
Merge pull request #1710 from Libensemble/refactor/rm_add_random_streams
Remove add_unique_random_streams and ensemble.add_random_streams. Mypy fixes.
2 parents 30142a2 + 089ea5e commit cefcf2e

125 files changed

Lines changed: 421 additions & 611 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ repos:
3737
rev: v1.19.1
3838
hooks:
3939
- id: mypy
40-
exclude: ^libensemble/utils/(launcher|loc_stack|runners|pydantic|output_directory)\.py$|^libensemble/tests/regression_tests/support\.py$|^libensemble/tests/functionality_tests/|^libensemble/tests/unit_tests/
40+
exclude: ^libensemble/utils/(launcher|loc_stack|runners|pydantic|output_directory)\.py$|libensemble/tests/(regression_tests|functionality_tests|unit_tests|scaling_tests)/.*

AGENTS.md

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,33 @@ Read the ``README.rst`` for an overview of libEnsemble.
77
- The manager determines how and when points get passed to workers via an allocation function.
88
- See ``libensemble/tests/regression_tests/test_1d_sampling.py`` for a simple example of the libEnsemble interface.
99

10-
Repository Layout
11-
-----------------
10+
Critical Repository Layout Information
11+
--------------------------------------
1212

1313
- ``libensemble/`` - Source code.
1414
- ``/alloc_funcs`` - Allocation functions. Policies for passing work between the manager and workers.
1515
- ``/comms`` - Modules and abstractions for communication between the manager and workers.
1616
- ``/executors`` - An interface for launching executables, often simulations.
1717
- ``/gen_classes`` - Generators that adhere to the `gest-api` standard.
1818
Recommended over entries from ``/gen_funcs`` that perform similar functionality.
19-
- ``/gen_funcs`` - Generator functions. Modules for producing points for simulations.
19+
- ``/gen_funcs`` - Generator functions. Modules for producing points for simulations. (Legacy)
2020
- ``/resources`` - Classes and functions for managing compute resources for MPI tasks, libensemble workers.
2121
- ``/sim_funcs`` - Simulator functions. Modules for running simulations or performing experiments.
2222
- ``/tests`` - Tests.
2323
- ``/functionality_tests`` - Primarily tests libEnsemble code only.
2424
- ``/regression_tests`` - Tests libEnsemble code with external code. Often more closely resembles actual use-cases.
2525
- ``/unit_tests`` - Tests for individual modules.
26-
- ``/tools`` - Tools. Misc functions and classes to ease development.
27-
- ``/utils`` - Utilities. Misc functions and classes used internally by multiple modules.
28-
- ``ensemble.py`` - The primary interface for parameterizing and running libEnsemble.
26+
- ``ensemble.py`` - The primary interface for parameterizing and running libEnsemble. The ``Ensemble`` class in this module wraps the lower-level ``libE`` function and automates argument parsing and state management.
2927
- ``generators.py`` - Base classes for generators that adhere to the `gest-api` standard.
30-
- ``history.py`` - Module for recording points that have been generated and simulation results. NumPy array.
31-
- ``libE.py`` - libE main file. Previous primary interface for parameterizing and running libEnsemble.
32-
- ``logger.py`` - Logging configuration.
28+
- ``history.py`` - Module for recording points that have been generated and simulation results. NumPy structured array.
29+
- ``libE.py`` - libE main file. Previous primary interface for parameterizing and running libEnsemble. The primary interface in ``ensemble.py`` wraps this function.
3330
- ``manager.py`` - Module for maintaining the history array and passing points between the workers.
3431
- ``message_numbers.py`` - Constants that represent states of the ensemble.
3532
- ``specs.py`` - Dataclasses for parameterizing the ensemble. Most importantly, contains ``LibeSpecs, SimSpecs, GenSpecs``.
3633
- ``worker.py`` - Module for running generators and simulators. Communicates with the manager.
37-
- ``version.py`` - Version file.
38-
39-
- ``.github/`` - GitHub actions. See ``.github/workflows/`` for the CI.
40-
- ``docs/`` - Documentation. Check here first for information before reading the source code.
4134
- ``examples/`` - The ``*_funcs`` and ``calling_scripts`` directories contain symlinks to examples further in the source code.
4235
- ``/libE_submission_scripts`` - Example scripts for submitting libEnsemble jobs to HPC systems.
4336
- ``/tutorials`` - Tutorials on how to use libEnsemble.
44-
- ``pyproject.toml`` - Project configuration file. Contains information about the project and its dependencies.
45-
46-
Other files in the root directory should be self-documenting.
4737

4838
Information about Generators
4939
----------------------------
@@ -55,8 +45,10 @@ Its fields match ``sim_specs/gen_specs["out"]`` or ``vocs`` attributes, plus add
5545
long-running loop, sending and receiving points to and from the manager until the ensemble was complete.
5646
- A ``gest-api`` or "standardized" generator is a class that at a minimum implements ``suggest`` and ``ingest`` methods, and is parameterized by a ``vocs``.
5747
- See ``libensemble/generators.py`` for more information about the ``gest-api`` standard.
58-
- If using a generator that adheres to the ``gest-api`` standard, or a classic persistent generator, use the ``start_only_persistent`` allocation function.
5948
- Generators are often used for simple sampling, optimization, calibration, uncertainty quantification, and other simulation-based tasks.
49+
- **Automatic Variable Mapping**: Subclasses of ``LibensembleGenerator`` (like ``UniformSample``) automatically map all ``VOCS`` variables to a single multi-dimensional ``"x"`` field in the History array if no explicit ``variables_mapping`` is provided.
50+
- **Mandatory Input Fields**: Even for simple generators that don't ingest data, ``gen_specs["in"]`` or ``gen_specs["persis_in"]`` must be defined if using an allocation function like ``only_persistent_gens`` that attempts to send rows. If these are empty, the manager will raise an ``AssertionError`` stating that no fields were requested to be sent.
51+
- **Default Allocator**: ``only_persistent_gens`` is the default allocator for standardized ``gest-api`` generators. It treats these generators as persistent entities that communicate throughout the run.
6052

6153
General Guidelines
6254
------------------
@@ -77,7 +69,7 @@ Development Environment
7769
-----------------------
7870

7971
- ``pixi`` is the recommended environment manager for libEnsemble development. See ``pyproject.toml`` for the list
80-
of dependencies and the available testing environments.
72+
of dependencies and the available testing environments. (Note: If ``pixi`` is not in your system path, it can often be found in ``/opt/homebrew/bin/pixi`` or ``/usr/local/bin/pixi``).
8173
- Enter the development environment with ``pixi shell -e dev``. This environment contains the most common dependencies for development and testing.
8274
- For one-off commands, use ``pixi run -e dev``. This will run a single command in the development environment.
8375
- If ``pixi`` is not available or not preferred by the user, ``pip install -e .`` can be used instead. Other dependencies may need to be installed manually.
@@ -87,9 +79,21 @@ the configuration and ``pyproject.toml`` for other configuration.
8779
Testing
8880
-------
8981

90-
- Run tests with the ``run-tests.py`` script: ``python libensemble/tests/run-tests.py``. See ``libensemble/tests/run-tests.py`` for usage information.
82+
- Run tests with the ``run_tests.py`` script: ``python libensemble/tests/run_tests.py``. See ``libensemble/tests/run_tests.py`` for usage information.
9183
- Some tests require third party software to be installed. When developing a feature or fixing a bug, since the entire test suite will be run on Github Actions,
9284
for local development running individual tests is sufficient.
9385
- Individual unit tests can be run with ``pixi run -e dev pytest path/to/test_file``.
9486
- A libEnsemble run typically outputs an ``ensemble.log`` and ``libE_stats.txt`` file in the working directory. Check these files for tracebacks or run statistics.
9587
- An "ensemble" or "workflow" directory may also be created, often containing per-simulation output directories
88+
89+
Modernizing Scripts for libEnsemble 2.0
90+
---------------------------------------
91+
92+
When modernizing existing libEnsemble scripts (functionality tests, regression tests, or user examples) for version 2.0, follow these steps:
93+
94+
- **Switch to `gest-api` Generators**: Replace legacy generator functions (from `libensemble.gen_funcs`) with standardized generator classes (from `libensemble.gen_classes` or other `gest-api` compatible sources).
95+
- **Use `VOCS` for Parameterization**: Standardized generators are parameterized by a `VOCS` object (from `gest_api.vocs`). Define variables and objectives within this object.
96+
- **Set `gen_specs["generator"]`**: Instead of `gen_f`, use the `generator` field in `GenSpecs` to pass the initialized generator class.
97+
- **Remove Explicit `AllocSpecs`**: In libEnsemble 2.0, `only_persistent_gens` is the default allocator. Scripts that previously used `give_sim_work_first` or other simple allocators can often remove `alloc_specs` entirely when switching to standardized generators.
98+
- **Generator Placement**: By default, generators run on the manager thread (Worker 0). This means all allocated workers are available for simulation tasks unless `gen_on_worker` is explicitly set to `True` in `libE_specs`.
99+
- **Mandatory Fields**: Ensure `gen_specs["in"]` or `gen_specs["persis_in"]` includes at least one field (e.g., `["sim_id"]`) if feedback is sent back to the generator, to satisfy the allocator's requirements.

README.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ and inference problems on the world's leading supercomputers such as Frontier, A
2222

2323
`Quickstart`_
2424

25-
**New:** libEnsemble nows supports the `gest-api`_ generator standard, and can run with
25+
**New:** libEnsemble nows supports the `gest-api`_ generator standard, and can run with
2626
Optimas and Xopt generators.
2727

2828
The |ScriptCreator| to generate customized scripts for running ensembles with your
@@ -81,7 +81,6 @@ and an exit condition. Run the following four-worker example via ``python this_f
8181
exit_criteria=exit_criteria,
8282
)
8383
84-
sampling.add_random_streams()
8584
sampling.run()
8685
8786
if sampling.is_manager:

docs/data_structures/persis_info.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ and from the corresponding workers. These are received in the ``persis_info``
1313
argument of user functions, and returned as the optional second return value.
1414

1515
A typical example is a random number generator stream to be used in consecutive
16-
calls to a generator (see
17-
:meth:`add_unique_random_streams()<tools.add_unique_random_streams>`)
16+
calls to a generator. Generators should initialize their own RNG using
17+
:meth:`get_rng()<tools.get_rng>`.
1818

1919
All other entries persist on the manager and can be updated in the calling script
2020
between ensemble invocations, or in the allocation function.

docs/tutorials/aposmm_tutorial.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function:
146146
from libensemble.libE import libE
147147
from libensemble.gen_funcs.persistent_aposmm import aposmm
148148
from libensemble.alloc_funcs.persistent_aposmm_alloc import persistent_aposmm_alloc
149-
from libensemble.tools import parse_args, add_unique_random_streams
149+
from libensemble.tools import parse_args
150150
151151
This allocation function starts a single Persistent APOSMM routine and provides
152152
``sim_f`` output for points requested by APOSMM. Points can be sampled points
@@ -241,7 +241,7 @@ random sampling seeding:
241241
:linenos:
242242
243243
exit_criteria = {"sim_max": 2000}
244-
persis_info = add_unique_random_streams({}, nworkers + 1)
244+
persis_info = {}
245245
246246
Finally, add statements to :doc:`initiate libEnsemble<../libe_module>`, and quickly
247247
check calculated minima:

examples/readme_notebook.ipynb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@
7676
" exit_criteria=exit_criteria,\n",
7777
" )\n",
7878
"\n",
79-
" sampling.add_random_streams()\n",
8079
" H, persis_info, flag = sampling.run()\n",
8180
"\n",
8281
" # Print first 10 lines of input/output values\n",

examples/tutorials/aposmm/aposmm_tutorial_notebook.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
"from libensemble.libE import libE\n",
115115
"from libensemble.gen_funcs.persistent_aposmm import aposmm\n",
116116
"from libensemble.alloc_funcs.persistent_aposmm_alloc import persistent_aposmm_alloc\n",
117-
"from libensemble.tools import parse_args, add_unique_random_streams"
117+
"from libensemble.tools import parse_args"
118118
]
119119
},
120120
{
@@ -235,7 +235,7 @@
235235
"metadata": {},
236236
"outputs": [],
237237
"source": [
238-
"persis_info = add_unique_random_streams({}, nworkers + 1)\n",
238+
"persis_info = {}\n",
239239
"\n",
240240
"H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, libE_specs)"
241241
]

examples/tutorials/aposmm/tutorial_aposmm.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from libensemble.alloc_funcs.persistent_aposmm_alloc import persistent_aposmm_alloc
66
from libensemble.gen_funcs.persistent_aposmm import aposmm
77
from libensemble.libE import libE
8-
from libensemble.tools import add_unique_random_streams, parse_args
8+
from libensemble.tools import parse_args
99

1010
libensemble.gen_funcs.rc.aposmm_optimizers = "scipy"
1111

@@ -42,8 +42,7 @@
4242
alloc_specs = {"alloc_f": persistent_aposmm_alloc}
4343

4444
exit_criteria = {"sim_max": 2000}
45-
persis_info = add_unique_random_streams({}, nworkers + 1)
4645

47-
H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, libE_specs)
46+
H, persis_info, flag = libE(sim_specs, gen_specs, exit_criteria, alloc_specs=alloc_specs, libE_specs=libE_specs)
4847
if is_manager:
4948
print("Minima:", H[np.where(H["local_min"])]["x"])

examples/tutorials/forces_with_executor/forces_tutorial_notebook.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,7 @@
312312
" gen_specs=gen_specs,\n",
313313
" sim_specs=sim_specs,\n",
314314
" exit_criteria=exit_criteria,\n",
315-
")\n",
316-
"\n",
317-
"# Seed random streams for each worker, particularly for gen_f\n",
318-
"ensemble.add_random_streams()"
315+
")\n"
319316
]
320317
},
321318
{
@@ -562,9 +559,6 @@
562559
" user={\"input_filename\": input_file, \"input_names\": [\"particles\"]},\n",
563560
")\n",
564561
"\n",
565-
"# To reset random number seed in the generator\n",
566-
"ensemble.add_random_streams()\n",
567-
"\n",
568562
"# Clean up any previous outputs and launch libEnsemble\n",
569563
"cleanup()\n",
570564
"H, persis_info, flag = ensemble.run()\n",

examples/tutorials/simple_sine/sine_tutorial_notebook.ipynb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@
186186
"\n",
187187
"# Initialize and run the ensemble.\n",
188188
"ensemble = Ensemble(sim_specs, gen_specs, exit_criteria, libE_specs)\n",
189-
"ensemble.add_random_streams() # setup the random streams unique to each worker\n",
190189
"H, persis_info, flag = ensemble.run() # start the ensemble. Blocks until completion."
191190
]
192191
},

0 commit comments

Comments
 (0)