Skip to content

Commit a7382ff

Browse files
committed
Merge branch 'develop' into refactor/deprecate_from_yaml_toml_json
2 parents b3c6030 + 250ada5 commit a7382ff

12 files changed

Lines changed: 119 additions & 35 deletions

File tree

.github/workflows/basic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
matrix:
1818
os: [ubuntu-latest]
1919
mpi-version: [mpich]
20-
python-version: ["py310", "py311", "py312", "py313", "py314"]
20+
python-version: ["py311", "py312", "py313", "py314"]
2121
comms-type: [m, l]
2222
include:
2323
- os: macos-latest

.github/workflows/extra.yml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
matrix:
1212
os: [ubuntu-latest]
1313
mpi-version: [mpich]
14-
python-version: ["py310e", "py311e", "py312e", "py313e", "py314e"]
14+
python-version: ["py311e", "py312e", "py313e", "py314e"]
1515
comms-type: [m, l]
1616
include:
1717
- os: macos-latest
@@ -70,13 +70,6 @@ jobs:
7070
run: |
7171
pixi run -e ${{ matrix.python-version }} pip install gpcam==8.1.13
7272
73-
- name: Remove xopt tests on old python
74-
if: matrix.python-version == 'py310e'
75-
run: |
76-
rm ./libensemble/tests/regression_tests/test_xopt_EI_xopt_sim.py
77-
rm ./libensemble/tests/regression_tests/test_xopt_EI.py
78-
rm ./libensemble/tests/regression_tests/test_xopt_nelder_mead.py
79-
8073
- name: Remove test using octave, gpcam, globus-compute on Python 3.13
8174
if: matrix.python-version == 'py313e' || matrix.python-version == 'py314e'
8275
run: |

.pre-commit-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,8 @@ repos:
3232
additional_dependencies: [black==22.12.0]
3333
files: ^(.*\.py|.*\.rst)$
3434
args: [--line-length=120]
35+
36+
- repo: https://github.com/pre-commit/mirrors-mypy
37+
rev: v1.19.1
38+
hooks:
39+
- id: mypy

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 2
33
build:
44
os: "ubuntu-22.04"
55
tools:
6-
python: "3.10"
6+
python: "3.12"
77
commands:
88
# from https://docs.readthedocs.com/platform/stable/build-customization.html#support-git-lfs-large-file-storage
99
# Download and uncompress the binary

AGENTS.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Agent Contributor Guidelines and Information
2+
============================================
3+
4+
Read the ``README.rst`` for an overview of libEnsemble.
5+
6+
- libEnsemble uses a manager-worker architecture. Points are generated by a generator and sent to a worker, which runs a simulator.
7+
- The manager determines how and when points get passed to workers via an allocation function.
8+
- See ``libensemble/tests/regression_tests/test_1d_sampling.py`` for a simple example of the libEnsemble interface.
9+
10+
Repository Layout
11+
-----------------
12+
13+
- ``libensemble/`` - Source code.
14+
- ``/alloc_funcs`` - Allocation functions. Policies for passing work between the manager and workers.
15+
- ``/comms`` - Modules and abstractions for communication between the manager and workers.
16+
- ``/executors`` - An interface for launching executables, often simulations.
17+
- ``/gen_classes`` - Generators that adhere to the `gest-api` standard.
18+
Recommended over entries from ``/gen_funcs`` that perform similar functionality.
19+
- ``/gen_funcs`` - Generator functions. Modules for producing points for simulations.
20+
- ``/resources`` - Classes and functions for managing compute resources for MPI tasks, libensemble workers.
21+
- ``/sim_funcs`` - Simulator functions. Modules for running simulations or performing experiments.
22+
- ``/tests`` - Tests.
23+
- ``/functionality_tests`` - Primarily tests libEnsemble code only.
24+
- ``/regression_tests`` - Tests libEnsemble code with external code. Often more closely resembles actual use-cases.
25+
- ``/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.
29+
- ``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.
33+
- ``manager.py`` - Module for maintaining the history array and passing points between the workers.
34+
- ``message_numbers.py`` - Constants that represent states of the ensemble.
35+
- ``specs.py`` - Dataclasses for parameterizing the ensemble. Most importantly, contains ``LibeSpecs, SimSpecs, GenSpecs``.
36+
- ``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.
41+
- ``examples/`` - The ``*_funcs`` and ``calling_scripts`` directories contain symlinks to examples further in the source code.
42+
- ``/libE_submission_scripts`` - Example scripts for submitting libEnsemble jobs to HPC systems.
43+
- ``/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.
47+
48+
Information about Generators
49+
----------------------------
50+
51+
- Generators are functions or objects that produce points for simulations.
52+
- The History array is a NumPy structured array that stores points that have been generated and simulation results.
53+
Its fields match ``sim_specs/gen_specs["out"]`` or ``vocs`` attributes, plus additional reserved fields for metadata.
54+
- Prior to libEnsemble v1.6.0, generators were plain functions. They often ran in "persistent" mode, meaning they executed in a
55+
long-running loop, sending and receiving points to and from the manager until the ensemble was complete.
56+
- A ``gest-api`` or "standardized" generator is a class that at a minimum implements ``suggest`` and ``ingest`` methods, and is parameterized by a ``vocs``.
57+
- 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.
59+
- Generators are often used for simple sampling, optimization, calibration, uncertainty quantification, and other simulation-based tasks.
60+
61+
General Guidelines
62+
------------------
63+
64+
- If using classic ``sim_specs`` and ``gen_specs``, then ensure that ``sim_specs["out"]`` and ``gen_specs["in"]`` field names match, and vice-versa.
65+
- As-of libEnsemble v1.6.0, ``SimSpecs`` and ``GenSpecs`` can also be parameterized by a ``vocs`` object, imported from ``gest_api.vocs`` (NOT xopt.vocs).
66+
- ``VOCS`` contains variables, objectives, constraints, and other settings that define the problem.
67+
See ``libensemble/tests/regression_tests/test_xopt_EI.py`` for an example of how to use it.
68+
- An MPI distribution is not required for libEnsemble to run, but is required to use the ``MPIExecutor``. ``mpich`` is recommended.
69+
- New tests are heavily encouraged for new features, bug fixes, or integrations. See ``libensemble/tests/regression_tests`` for examples.
70+
- Never use destructive git commands unless explicitly requested.
71+
- Code is in the ``black`` style. This should be enforced by ``pre-commit``.
72+
- When writing new code, prefer the ``LibeSpecs``, ``SimSpecs``, and ``GenSpecs`` dataclasses over the classic ``sim_specs`` and ``gen_specs`` bare dictionaries.
73+
- Read ``CONTRIBUTING.md`` for more information.
74+
- The external ``libE-community-examples`` repository contains past use-cases, generators, and other examples.
75+
76+
Development Environment
77+
-----------------------
78+
79+
- ``pixi`` is the recommended environment manager for libEnsemble development. See ``pyproject.toml`` for the list
80+
of dependencies and the available testing environments.
81+
- Enter the development environment with ``pixi shell -e dev``. This environment contains the most common dependencies for development and testing.
82+
- For one-off commands, use ``pixi run -e dev``. This will run a single command in the development environment.
83+
- 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.
84+
- If committing, use ``pre-commit`` to ensure that code style and formatting are consistent. See ``.pre-commit-config.yaml`` for
85+
the configuration and ``pyproject.toml`` for other configuration.
86+
87+
Testing
88+
-------
89+
90+
- Run tests with the ``run-tests.py`` script: ``python libensemble/tests/run-tests.py``. See ``libensemble/tests/run-tests.py`` for usage information.
91+
- 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,
92+
for local development running individual tests is sufficient.
93+
- Individual unit tests can be run with ``pixi run -e dev pytest path/to/test_file``.
94+
- 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.
95+
- An "ensemble" or "workflow" directory may also be created, often containing per-simulation output directories

docs/advanced_installation.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ libEnsemble can be installed from ``pip``, ``uv``, ``Conda``, or ``Spack``.
66
libEnsemble requires the following dependencies, which are typically
77
automatically installed alongside libEnsemble:
88

9-
* Python_ ``>= 3.10``
9+
* Python_ ``>= 3.11``
1010
* NumPy_ ``>= 1.21``
1111
* psutil_ ``>= 5.9.4``
1212
* `pydantic`_ ``>= 2``
@@ -142,7 +142,7 @@ Further recommendations for selected HPC systems are given in the
142142

143143
**Hint**: When combining Spack and Conda, you can access your Conda Python and packages in your
144144
``~/.spack/packages.yaml`` while your Conda environment is activated, using ``CONDA_PREFIX``
145-
For example, if you have an activated Conda environment with Python 3.10 and SciPy installed:
145+
For example, if you have an activated Conda environment with Python 3.11 and SciPy installed:
146146

147147
.. code-block:: yaml
148148
@@ -155,12 +155,12 @@ Further recommendations for selected HPC systems are given in the
155155
py-numpy:
156156
externals:
157157
- spec: "py-numpy"
158-
prefix: $CONDA_PREFIX/lib/python3.10/site-packages/numpy
158+
prefix: $CONDA_PREFIX/lib/python3.11/site-packages/numpy
159159
buildable: False
160160
py-scipy:
161161
externals:
162162
- spec: "py-scipy"
163-
prefix: $CONDA_PREFIX/lib/python3.10/site-packages/scipy
163+
prefix: $CONDA_PREFIX/lib/python3.11/site-packages/scipy
164164
buildable: True
165165
166166
For more information on Spack builds and any particular considerations

docs/platforms/perlmutter.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Change the ``libE_specs`` in **run_libe_forces.py** as follows.
120120
# Persistent gen does not need resources
121121
ensemble.libE_specs = LibeSpecs(
122122
gen_on_manager=True,
123+
)
123124
124125
and run with::
125126

docs/platforms/summit.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Begin by loading the Python 3 Anaconda module::
2424

2525
You can now create and activate your own custom conda_ environment::
2626

27-
conda create --name myenv python=3.10
27+
conda create --name myenv python=3.11
2828
export PYTHONNOUSERSITE=1 # Make sure get python from conda env
2929
. activate myenv
3030

docs/tutorials/local_sine_tutorial.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ need to write a new allocation function.
2222

2323
.. code-block:: bash
2424
25-
python --version # This should be >= 3.10
25+
python --version # This should be >= 3.11
2626
2727
.. _Python: https://www.python.org/
2828

libensemble/utils/misc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from itertools import chain, groupby
66
from operator import itemgetter
7-
from typing import List
87

98
import numpy as np
109
import numpy.typing as npt
@@ -85,6 +84,7 @@ def _get_combinable_multidim_names(first: dict, new_dtype_names: list) -> list:
8584

8685
def _decide_dtype(name: str, entry, size: int) -> tuple:
8786
"""decide dtype of field, and size if needed"""
87+
output_type: str | type # str for numpy string type, type for python type
8888
if isinstance(entry, str): # use numpy style for string type
8989
output_type = "U" + str(len(entry) + 1)
9090
else:
@@ -115,7 +115,7 @@ def _pack_field(input_dict: dict, field_names: list) -> tuple:
115115
return tuple(input_dict[name] for name in field_names) if len(field_names) > 1 else input_dict[field_names[0]]
116116

117117

118-
def list_dicts_to_np(list_dicts: list, dtype: list = None, mapping: dict = {}) -> npt.NDArray:
118+
def list_dicts_to_np(list_dicts: list, dtype: list | None = None, mapping: dict = {}) -> npt.NDArray:
119119
"""Convert list of dicts to numpy structured array"""
120120
if list_dicts is None:
121121
return None
@@ -231,7 +231,7 @@ def map_numpy_array(array: npt.NDArray, mapping: dict = {}) -> npt.NDArray:
231231
return array
232232

233233
# Create new dtype with mapped fields
234-
new_fields = []
234+
new_fields: list[tuple] = []
235235

236236
# Track fields processed by mapping to avoid duplication
237237
mapped_source_fields = set()
@@ -275,7 +275,7 @@ def map_numpy_array(array: npt.NDArray, mapping: dict = {}) -> npt.NDArray:
275275
return mapped_array
276276

277277

278-
def np_to_list_dicts(array: npt.NDArray, mapping: dict = {}) -> List[dict]:
278+
def np_to_list_dicts(array: npt.NDArray, mapping: dict = {}) -> list[dict]:
279279
"""Convert numpy structured array to list of dicts"""
280280
out = []
281281

0 commit comments

Comments
 (0)