diff --git a/.github/workflows/basic.yml b/.github/workflows/basic.yml index c18f5386c..a4ea568d0 100644 --- a/.github/workflows/basic.yml +++ b/.github/workflows/basic.yml @@ -9,93 +9,93 @@ on: - synchronize jobs: - test-libE: - if: '! github.event.pull_request.draft' - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - mpi-version: [mpich] - python-version: ["py311", "py312", "py313", "py314"] - comms-type: [m, l] - include: - - os: macos-latest - python-version: "py311" - mpi-version: mpich - comms-type: m - - os: macos-latest - python-version: "py311" - mpi-version: mpich - comms-type: l - + test-libE: + if: "! github.event.pull_request.draft" + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + mpi-version: [mpich] + python-version: ["py311", "py312", "py313", "py314"] + comms-type: [m, l] + include: + - os: macos-latest + python-version: "py311" + mpi-version: mpich + comms-type: m + - os: macos-latest + python-version: "py311" + mpi-version: mpich + comms-type: l + + env: + HYDRA_LAUNCHER: "fork" + TERM: xterm-256color + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v6 + with: + lfs: true + + - name: Checkout lockfile + run: git lfs checkout + + - uses: prefix-dev/setup-pixi@v0.9.6 + with: + pixi-version: v0.68.1 + frozen: true + environments: ${{ matrix.python-version }} + activate-environment: ${{ matrix.python-version }} + + - name: Install minq + run: | + pixi run -e ${{ matrix.python-version }} ./install/install_minq.sh + + - name: Install libEnsemble, test flake8 + run: | + pip install -e . + flake8 libensemble + + - name: Install mypy + run: pip install mypy + + - name: Run mypy (limited scope) + run: mypy + + - name: Remove various tests on newer pythons + if: matrix.python-version == 'py311' || matrix.python-version == 'py312' || matrix.python-version == 'py313' || matrix.python-version == 'py314' + run: | + rm ./libensemble/tests/functionality_tests/test_local_sine_tutorial*.py # matplotlib errors on py312 + + - name: Run simple tests, Ubuntu + if: matrix.os == 'ubuntu-latest' + run: | + ./libensemble/tests/run_tests.py -A "-W error" -${{ matrix.comms-type }} + + - name: Run simple tests, macOS + if: matrix.os == 'macos-latest' + run: | + pixi run -e ${{ matrix.python-version }} ./libensemble/tests/run_tests.py -A "-W error" -${{ matrix.comms-type }} + + - name: Merge coverage + run: | + mv libensemble/tests/.cov* . + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v6 env: - HYDRA_LAUNCHER: "fork" - TERM: xterm-256color - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - defaults: - run: - shell: bash -l {0} - - steps: - - uses: actions/checkout@v6 - with: - lfs: true - - - name: Checkout lockfile - run: git lfs checkout - - - uses: prefix-dev/setup-pixi@v0.9.5 - with: - pixi-version: v0.55.0 - frozen: true - environments: ${{ matrix.python-version }} - activate-environment: ${{ matrix.python-version }} - - - name: Install minq - run: | - pixi run -e ${{ matrix.python-version }} ./install/install_minq.sh - - - name: Install libEnsemble, test flake8 - run: | - pip install -e . - flake8 libensemble - - - name: Install mypy - run: pip install mypy - - - name: Run mypy (limited scope) - run: mypy - - - name: Remove various tests on newer pythons - if: matrix.python-version == 'py311' || matrix.python-version == 'py312' || matrix.python-version == 'py313' || matrix.python-version == 'py314' - run: | - rm ./libensemble/tests/functionality_tests/test_local_sine_tutorial*.py # matplotlib errors on py312 - - - name: Run simple tests, Ubuntu - if: matrix.os == 'ubuntu-latest' - run: | - ./libensemble/tests/run_tests.py -A "-W error" -${{ matrix.comms-type }} - - - name: Run simple tests, macOS - if: matrix.os == 'macos-latest' - run: | - pixi run -e ${{ matrix.python-version }} ./libensemble/tests/run_tests.py -A "-W error" -${{ matrix.comms-type }} - - - name: Merge coverage - run: | - mv libensemble/tests/.cov* . - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v6 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - spellcheck: - name: Spellcheck release branch - if: contains(github.base_ref, 'develop') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.46.2 + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + spellcheck: + name: Spellcheck release branch + if: contains(github.base_ref, 'develop') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: crate-ci/typos@v1.46.2 diff --git a/.github/workflows/extra.yml b/.github/workflows/extra.yml index 8f9a27162..bd4cc601d 100644 --- a/.github/workflows/extra.yml +++ b/.github/workflows/extra.yml @@ -4,111 +4,111 @@ on: workflow_dispatch: jobs: - test-libE: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - mpi-version: [mpich] - python-version: ["py311e", "py312e", "py313e", "py314e"] - comms-type: [m, l] - include: - - os: macos-latest - python-version: "py312e" - mpi-version: mpich - comms-type: m - - os: macos-latest - python-version: "py312e" - mpi-version: mpich - comms-type: l - - os: ubuntu-latest - python-version: "py312e" - mpi-version: mpich - comms-type: t - - os: ubuntu-latest - mpi-version: openmpi - python-version: "py312e" - comms-type: l - + test-libE: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + mpi-version: [mpich] + python-version: ["py311e", "py312e", "py313e", "py314e"] + comms-type: [m, l] + include: + - os: macos-latest + python-version: "py312e" + mpi-version: mpich + comms-type: m + - os: macos-latest + python-version: "py312e" + mpi-version: mpich + comms-type: l + - os: ubuntu-latest + python-version: "py312e" + mpi-version: mpich + comms-type: t + - os: ubuntu-latest + mpi-version: openmpi + python-version: "py312e" + comms-type: l + + env: + HYDRA_LAUNCHER: "fork" + TERM: xterm-256color + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v6 + with: + lfs: true + + - name: Checkout lockfile + run: git lfs checkout + + - uses: prefix-dev/setup-pixi@v0.9.6 + with: + pixi-version: v0.68.1 + cache: true + frozen: true + environments: ${{ matrix.python-version }} + activate-environment: ${{ matrix.python-version }} + + - name: Install other testing dependencies + run: | + pixi run -e ${{ matrix.python-version }} install/install_minq.sh + + - name: Install libEnsemble, flake8, lock environment + run: | + pip install -e . + flake8 libensemble + + - name: Install gpcam + if: matrix.python-version != 'py313e' && matrix.python-version != 'py314e' + run: | + pixi run -e ${{ matrix.python-version }} pip install gpcam==8.1.13 + + - name: Remove test using octave, gpcam, globus-compute on Python 3.13 + if: matrix.python-version == 'py313e' || matrix.python-version == 'py314e' + run: | + rm ./libensemble/tests/unit_tests/test_ufunc_runners.py # needs globus-compute + rm ./libensemble/tests/regression_tests/test_gpCAM.py # needs gpcam, which doesn't build on 3.13 + rm ./libensemble/tests/regression_tests/test_asktell_gpCAM.py # needs gpcam, which doesn't build on 3.13 + rm ./libensemble/tests/regression_tests/test_persistent_gp_multitask_ax.py # needs ax-platform, which doesn't yet support 3.14 + rm ./libensemble/tests/regression_tests/test_optimas_ax_mf.py # needs ax-platform, which doesn't yet support 3.14 + rm ./libensemble/tests/regression_tests/test_optimas_ax_sf.py # needs ax-platform, which doesn't yet support 3.14 + + - name: Start Redis + if: matrix.os == 'ubuntu-latest' + uses: supercharge/redis-github-action@v2 + with: + redis-version: 7 + + - name: Run extensive tests, Ubuntu + if: matrix.os == 'ubuntu-latest' + run: | + ./libensemble/tests/run_tests.py -e -${{ matrix.comms-type }} + + - name: Run extensive tests, macOS + if: matrix.os == 'macos-latest' + run: | + pixi run -e ${{ matrix.python-version }} ./libensemble/tests/run_tests.py -e -${{ matrix.comms-type }} + + - name: Merge coverage + run: | + mv libensemble/tests/.cov* . + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v6 env: - HYDRA_LAUNCHER: 'fork' - TERM: xterm-256color - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - defaults: - run: - shell: bash -l {0} - - steps: - - uses: actions/checkout@v6 - with: - lfs: true - - - name: Checkout lockfile - run: git lfs checkout - - - uses: prefix-dev/setup-pixi@v0.9.5 - with: - pixi-version: v0.55.0 - cache: true - frozen: true - environments: ${{ matrix.python-version }} - activate-environment: ${{ matrix.python-version }} - - - name: Install other testing dependencies - run: | - pixi run -e ${{ matrix.python-version }} install/install_minq.sh - - - name: Install libEnsemble, flake8, lock environment - run: | - pip install -e . - flake8 libensemble - - - name: Install gpcam - if: matrix.python-version != 'py313e' && matrix.python-version != 'py314e' - run: | - pixi run -e ${{ matrix.python-version }} pip install gpcam==8.1.13 - - - name: Remove test using octave, gpcam, globus-compute on Python 3.13 - if: matrix.python-version == 'py313e' || matrix.python-version == 'py314e' - run: | - rm ./libensemble/tests/unit_tests/test_ufunc_runners.py # needs globus-compute - rm ./libensemble/tests/regression_tests/test_gpCAM.py # needs gpcam, which doesn't build on 3.13 - rm ./libensemble/tests/regression_tests/test_asktell_gpCAM.py # needs gpcam, which doesn't build on 3.13 - rm ./libensemble/tests/regression_tests/test_persistent_gp_multitask_ax.py # needs ax-platform, which doesn't yet support 3.14 - rm ./libensemble/tests/regression_tests/test_optimas_ax_mf.py # needs ax-platform, which doesn't yet support 3.14 - rm ./libensemble/tests/regression_tests/test_optimas_ax_sf.py # needs ax-platform, which doesn't yet support 3.14 - - - name: Start Redis - if: matrix.os == 'ubuntu-latest' - uses: supercharge/redis-github-action@v2 - with: - redis-version: 7 - - - name: Run extensive tests, Ubuntu - if: matrix.os == 'ubuntu-latest' - run: | - ./libensemble/tests/run_tests.py -e -${{ matrix.comms-type }} - - - name: Run extensive tests, macOS - if: matrix.os == 'macos-latest' - run: | - pixi run -e ${{ matrix.python-version }} ./libensemble/tests/run_tests.py -e -${{ matrix.comms-type }} - - - name: Merge coverage - run: | - mv libensemble/tests/.cov* . - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v6 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - spellcheck: - name: Spellcheck release branch - if: contains(github.base_ref, 'develop') - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: crate-ci/typos@v1.46.2 + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + spellcheck: + name: Spellcheck release branch + if: contains(github.base_ref, 'develop') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: crate-ci/typos@v1.46.2 diff --git a/libensemble/tests/regression_tests/test_asktell_aposmm_nlopt.py b/libensemble/tests/regression_tests/test_asktell_aposmm_nlopt.py index bbc2c89d1..390582143 100644 --- a/libensemble/tests/regression_tests/test_asktell_aposmm_nlopt.py +++ b/libensemble/tests/regression_tests/test_asktell_aposmm_nlopt.py @@ -20,8 +20,6 @@ import numpy as np import libensemble.gen_funcs -from libensemble.executors.mpi_executor import MPIExecutor -from libensemble.sim_funcs import six_hump_camel # Import libEnsemble items for this test @@ -32,7 +30,6 @@ from libensemble import Ensemble from libensemble.gen_classes import APOSMM -from libensemble.manager import LoggedException from libensemble.specs import ExitCriteria, GenSpecs, SimSpecs from libensemble.tests.regression_tests.support import six_hump_camel_minima as minima @@ -53,75 +50,50 @@ def six_hump_camel_func(x): # Main block is necessary only when using local comms with spawn start method (default on macOS and Windows). if __name__ == "__main__": - for run in range(3): - - workflow = Ensemble(parse_args=True) - - if workflow.is_manager: - start_time = time() - - n = 2 - - vocs = VOCS( - variables={"core": [-3, 3], "edge": [-2, 2], "core_on_cube": [-3, 3], "edge_on_cube": [-2, 2]}, - objectives={"energy": "MINIMIZE"}, - ) - - aposmm = APOSMM( - vocs, - max_active_runs=workflow.nworkers, # should this match nworkers always? practically? - variables_mapping={"x": ["core", "edge"], "x_on_cube": ["core_on_cube", "edge_on_cube"], "f": ["energy"]}, - initial_sample_size=100, - sample_points=minima, - localopt_method="LN_BOBYQA", - rk_const=0.5 * ((gamma(1 + (n / 2)) * 5) ** (1 / n)) / sqrt(pi), - xtol_abs=1e-6, - ftol_abs=1e-6, - ) - - workflow.gen_specs = GenSpecs( - generator=aposmm, - vocs=vocs, - batch_size=5, - initial_batch_size=10, - ) - - if run == 0: - workflow.sim_specs = SimSpecs(simulator=six_hump_camel_func, vocs=vocs) - workflow.exit_criteria = ExitCriteria(sim_max=2000, wallclock_max=600) - elif run == 1: - workflow.persis_info["num_gens_started"] = 0 - sim_app2 = six_hump_camel.__file__ - exctr = MPIExecutor() - exctr.register_app(full_path=sim_app2, app_name="six_hump_camel", calc_type="sim") # Named app - workflow.sim_specs = SimSpecs(simulator=six_hump_camel_func, vocs=vocs) - workflow.exit_criteria = ExitCriteria(sim_max=200, wallclock_max=600) - elif run == 2: - workflow.persis_info["num_gens_started"] = 0 - workflow.sim_specs = SimSpecs( - sim_f=six_hump_camel_func, vocs=vocs - ) # wrong parameter, but check we get error message - workflow.exit_criteria = ExitCriteria(sim_max=200, wallclock_max=600) - workflow.libE_specs.abort_on_exception = False - - try: - H, _, _ = workflow.run() - except Exception as e: - if run == 2: - assert isinstance(e, LoggedException) - aposmm.finalize() - print("Passed", flush=True) - else: - raise e - - # Perform the run - if workflow.is_manager and run == 0: - print("[Manager]:", H[np.where(H["local_min"])]["x"]) - print("[Manager]: Time taken =", time() - start_time, flush=True) - - tol = 1e-5 - for m in minima: - # The minima are known on this test problem. - # We use their values to test APOSMM has identified all minima - print(np.min(np.sum((H[H["local_min"]]["x"] - m) ** 2, 1)), flush=True) - assert np.min(np.sum((H[H["local_min"]]["x"] - m) ** 2, 1)) < tol + workflow = Ensemble(parse_args=True) + + if workflow.is_manager: + start_time = time() + + n = 2 + + vocs = VOCS( + variables={"core": [-3, 3], "edge": [-2, 2], "core_on_cube": [0, 1], "edge_on_cube": [0, 1]}, + objectives={"energy": "MINIMIZE"}, + ) + + aposmm = APOSMM( + vocs, + max_active_runs=max(1, workflow.nworkers - 1), + variables_mapping={"x": ["core", "edge"], "x_on_cube": ["core_on_cube", "edge_on_cube"], "f": ["energy"]}, + initial_sample_size=100, + sample_points=np.round(minima, 1), + localopt_method="LN_BOBYQA", + rk_const=0.5 * ((gamma(1 + (n / 2)) * 5) ** (1 / n)) / sqrt(pi), + xtol_abs=1e-6, + ftol_abs=1e-6, + ) + + workflow.gen_specs = GenSpecs( + generator=aposmm, + vocs=vocs, + batch_size=5, + initial_batch_size=10, + ) + + workflow.sim_specs = SimSpecs(simulator=six_hump_camel_func, vocs=vocs) + workflow.exit_criteria = ExitCriteria(sim_max=2000, wallclock_max=600) + + # Perform the run + H, _, _ = workflow.run() + + if workflow.is_manager: + print("[Manager]:", H[np.where(H["local_min"])]["x"]) + print("[Manager]: Time taken =", time() - start_time, flush=True) + + tol = 1e-5 + for m in minima: + # The minima are known on this test problem. + # We use their values to test APOSMM has identified all minima + print(np.min(np.sum((H[H["local_min"]]["x"] - m) ** 2, 1)), flush=True) + assert np.min(np.sum((H[H["local_min"]]["x"] - m) ** 2, 1)) < tol diff --git a/libensemble/tests/unit_tests/test_persistent_aposmm.py b/libensemble/tests/unit_tests/test_persistent_aposmm.py index abcccb37b..900bfe070 100644 --- a/libensemble/tests/unit_tests/test_persistent_aposmm.py +++ b/libensemble/tests/unit_tests/test_persistent_aposmm.py @@ -373,6 +373,15 @@ def test_asktell_errors(): pytest.fail("Should've failed on consecutive setup") my_APOSMM.finalize() + from libensemble.utils.runners import Runner + + def gest_style_sim(_): + return {"energy": 0.0} + + runner = Runner({"sim_f": gest_style_sim}) + with pytest.raises(AttributeError, match="SimSpecs.simulator"): + runner.run(np.zeros(1), {"persis_info": {}, "libE_info": {}}) + @pytest.mark.extra def test_asktell_ingest_first():