xopt 3.2.2__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xopt-3.2.2/xopt.egg-info → xopt-3.3.0}/PKG-INFO +4 -3
- {xopt-3.2.2 → xopt-3.3.0}/README.md +3 -2
- {xopt-3.2.2 → xopt-3.3.0}/docs/algorithms.md +2 -1
- xopt-3.3.0/docs/api/generators/sequential/scipy.md +80 -0
- xopt-3.3.0/docs/api/stopping_conditions.md +33 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/index.md +4 -3
- {xopt-3.2.2 → xopt-3.3.0}/mkdocs.yml +3 -1
- {xopt-3.2.2 → xopt-3.3.0}/pyproject.toml +2 -1
- {xopt-3.2.2 → xopt-3.3.0}/xopt/_version.py +3 -3
- {xopt-3.2.2 → xopt-3.3.0}/xopt/asynchronous.py +7 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/base.py +5 -2
- xopt-3.3.0/xopt/entrypoint/__init__.py +1 -0
- xopt-3.3.0/xopt/entrypoint/mpi.py +172 -0
- xopt-3.2.2/xopt/entrypoint.py → xopt-3.3.0/xopt/entrypoint/multiprocessing.py +11 -119
- xopt-3.3.0/xopt/entrypoint/utils.py +136 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/__init__.py +5 -1
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bayesian_generator.py +4 -3
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/utils.py +12 -135
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/visualize.py +15 -22
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/sequential/__init__.py +2 -0
- xopt-3.3.0/xopt/generators/sequential/scipy.py +536 -0
- xopt-3.3.0/xopt/mpi/run.py +6 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/stopping_conditions.py +37 -0
- xopt-3.3.0/xopt/tests/generators/bayesian/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_utils.py +37 -158
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_visualize.py +26 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/ga/test_nsga2.py +36 -1
- xopt-3.3.0/xopt/tests/generators/sequential/test_scipy.py +727 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/sequential/test_serialization.py +11 -2
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_asynch_xopt.py +45 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_entrypoint.py +99 -10
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_stopping_condition.py +157 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_utils.py +7 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/utils.py +7 -5
- {xopt-3.2.2 → xopt-3.3.0/xopt.egg-info}/PKG-INFO +4 -3
- {xopt-3.2.2 → xopt-3.3.0}/xopt.egg-info/SOURCES.txt +7 -2
- xopt-3.3.0/xopt.egg-info/entry_points.txt +3 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt.egg-info/scm_file_list.json +7 -2
- xopt-3.3.0/xopt.egg-info/scm_version.json +8 -0
- xopt-3.2.2/docs/api/stopping_conditions.md +0 -3
- xopt-3.2.2/xopt/generators/scipy/__init__.py +0 -4
- xopt-3.2.2/xopt/mpi/run.py +0 -98
- xopt-3.2.2/xopt/tests/test_mpi.py +0 -100
- xopt-3.2.2/xopt.egg-info/entry_points.txt +0 -2
- xopt-3.2.2/xopt.egg-info/scm_version.json +0 -8
- {xopt-3.2.2 → xopt-3.3.0}/.pre-commit-config.yaml +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/LICENSE +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/MANIFEST.in +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/benchmarks/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/benchmarks/test_mo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/benchmarks/test_neldermead.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/benchmarks/test_ucb.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/codecov.yml +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/evaluator.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bax/acquisition_functions.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bax/algorithms.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bax/bax_generator.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bax/visualize.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bayesian_exploration.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/bayesian_generator.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/expected_improvement.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/mggpo.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/mobo.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/models/base_model_constructor.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/models/standard_model_constructor.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/models/time_dependent_model_constructor.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/multi_fidelity.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/time_dependent.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/turbo.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/upper_confidence_bound.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/bayesian/utils.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/deduplicated.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/ga/cnsga.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/ga/deap_creator.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/ga/deap_fitness_with_constraints.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/ga/nsga2.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/ga/operators.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/random.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/sequential/extremumseeking.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/sequential/neldermead.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/sequential/rcds.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/sequential/sequential_generator.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators/utils.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/generators.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/numerical_optimizer.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/utils.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/vocs.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/api/xopt.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/assets/Xopt-logo.png +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/assets/xopt_overview.pdf +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/hooks/zip_generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/installation.md +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/overrides/main.html +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/docs/stylesheets/extra.css +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/environment.yml +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/scripts/execute_notebooks.bash +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/scripts/run_benchmarks.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/scripts/run_examples.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/scripts/run_tests.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/setup.cfg +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/errors.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/evaluator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/base_model.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bax/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bax/acquisition.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bax/algorithms.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bax/visualize.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bax_generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/bayesian_exploration.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/constrained_acquisition.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/hessian_kernel.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/heteroskedastic.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/log_acquisition_function.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/custom_botorch/multi_fidelity.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/expected_improvement.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/mggpo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/mobo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/models/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/models/approximate.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/models/prior_mean.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/models/standard.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/models/time_dependent.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/multi_fidelity.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/objectives.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/time_dependent.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/turbo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/bayesian/upper_confidence_bound.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/checkpoints.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/deduplicated.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/base.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/cnsga.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/deap_creator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/deap_fitness_with_constraints.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/nsga2.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/ga/operators.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/random.py +0 -0
- {xopt-3.2.2/xopt/mpi → xopt-3.3.0/xopt/generators/scipy}/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/scipy/latin_hypercube.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/sequential/extremumseeking.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/sequential/neldermead.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/sequential/rcds.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/sequential/sequential_generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/generators/utils.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/log.py +0 -0
- {xopt-3.2.2/xopt/resources → xopt-3.3.0/xopt/mpi}/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/numerical_optimizer.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/pydantic.py +0 -0
- {xopt-3.2.2/xopt/resources/test_functions → xopt-3.3.0/xopt/resources}/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_framework.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_functions/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_functions/generators.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_functions/models.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_profiler.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/bench_runner.py +0 -0
- {xopt-3.2.2/xopt/tests → xopt-3.3.0/xopt/resources/test_functions}/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/ackley_20.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/haverly_pooling.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/modified_tnk.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/multi_objective.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/problem.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/rosenbrock.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/sinusoid_1d.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/tnk.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/test_functions/zdt.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/resources/testing.py +0 -0
- {xopt-3.2.2/xopt/tests/generators → xopt-3.3.0/xopt/tests}/__init__.py +0 -0
- {xopt-3.2.2/xopt/tests/generators/bayesian → xopt-3.3.0/xopt/tests/generators}/__init__.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/conftest.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_bax.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_bax_visualize.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_bayesian_exploration.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_bayesian_generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_constraints.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_contextual_bo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_custom_model.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_discrete_integration.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_expected_improvement.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_hessian_kernel.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_high_level.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_mggpo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_mobo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_model_constructor.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_multi_fidelity.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_objectives.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_time_dependent_bo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_turbo.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/bayesian/test_upper_confidence_bound.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/external/test_aposmm.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/ga/test_base.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/ga/test_cnsga.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/ga/test_deap_creator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/sequential/test_extremum_seeking.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/sequential/test_neldermead.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/sequential/test_rcds.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/sequential/test_sequential.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_checkpoints.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_deduplicated.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_latin_hypercube.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_operators.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_random.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/generators/test_utils.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_evaluator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_generator.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_io.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_log.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_numerical_optimizer.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_perf.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_pydantic.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_resources.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_vocs.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/tests/test_xopt.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt/vocs.py +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt.egg-info/dependency_links.txt +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt.egg-info/requires.txt +0 -0
- {xopt-3.2.2 → xopt-3.3.0}/xopt.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xopt
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Flexible optimization of arbitrary problems in Python.
|
|
5
5
|
Author: Christopher Mayes, Ryan Roussel, Nikita Kuklev, Christopher Pierce, Sara Miskovich
|
|
6
6
|
License: Apache License
|
|
@@ -305,11 +305,12 @@ Currenty **Xopt** provides:
|
|
|
305
305
|
- `extremum_seeking` Extremum seeking time-dependent optimization
|
|
306
306
|
- `rcds` Robust Conjugate Direction Search (RCDS)
|
|
307
307
|
- `neldermead` Nelder-Mead Simplex
|
|
308
|
+
- `scipy` Scipy-based optimization algorithms (Powell, L-BFGS-B, etc.)
|
|
308
309
|
- Sampling algorithms:
|
|
309
310
|
- `random` Uniform random sampling
|
|
310
311
|
- Convenient YAML/JSON based input format
|
|
311
312
|
- Driver programs:
|
|
312
|
-
- `xopt
|
|
313
|
+
- `xopt-mpirun` Parallel MPI execution using this input format
|
|
313
314
|
|
|
314
315
|
Xopt does **not** provide:
|
|
315
316
|
- your custom simulation or experimental measurement via an `evaluate` function.
|
|
@@ -428,7 +429,7 @@ Using MPI
|
|
|
428
429
|
===============
|
|
429
430
|
Example MPI run, with `xopt.yaml` as the only user-defined file:
|
|
430
431
|
```b
|
|
431
|
-
mpirun -n 64
|
|
432
|
+
mpirun -n 64 xopt-mpirun xopt.yaml
|
|
432
433
|
```
|
|
433
434
|
|
|
434
435
|
|
|
@@ -53,11 +53,12 @@ Currenty **Xopt** provides:
|
|
|
53
53
|
- `extremum_seeking` Extremum seeking time-dependent optimization
|
|
54
54
|
- `rcds` Robust Conjugate Direction Search (RCDS)
|
|
55
55
|
- `neldermead` Nelder-Mead Simplex
|
|
56
|
+
- `scipy` Scipy-based optimization algorithms (Powell, L-BFGS-B, etc.)
|
|
56
57
|
- Sampling algorithms:
|
|
57
58
|
- `random` Uniform random sampling
|
|
58
59
|
- Convenient YAML/JSON based input format
|
|
59
60
|
- Driver programs:
|
|
60
|
-
- `xopt
|
|
61
|
+
- `xopt-mpirun` Parallel MPI execution using this input format
|
|
61
62
|
|
|
62
63
|
Xopt does **not** provide:
|
|
63
64
|
- your custom simulation or experimental measurement via an `evaluate` function.
|
|
@@ -176,7 +177,7 @@ Using MPI
|
|
|
176
177
|
===============
|
|
177
178
|
Example MPI run, with `xopt.yaml` as the only user-defined file:
|
|
178
179
|
```b
|
|
179
|
-
mpirun -n 64
|
|
180
|
+
mpirun -n 64 xopt-mpirun xopt.yaml
|
|
180
181
|
```
|
|
181
182
|
|
|
182
183
|
|
|
@@ -65,7 +65,8 @@ Scipy Generators
|
|
|
65
65
|
These generators serve as wrappers for algorithms implemented in scipy.
|
|
66
66
|
|
|
67
67
|
- [`NelderMeadGenerator`](examples/sequential/neldermead.ipynb): implements Nelder-Mead (simplex) optimization.
|
|
68
|
-
- [`
|
|
68
|
+
- [`ScipyGenerator`](examples/sequential/scipy.ipynb): generic wrapper around `scipy.optimize.minimize` methods.
|
|
69
|
+
- [`LatinHypercubeGenerator`](examples/other/latin_hypercube.ipynb): performs latin hypercube sampling of the evaluation function.
|
|
69
70
|
|
|
70
71
|
RCDS Generators
|
|
71
72
|
===
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Scipy Minimize Generator
|
|
2
|
+
|
|
3
|
+
`ScipyGenerator` exposes scipy's `optimize.minimize` methods through Xopt's sequential ingest/suggest interface.
|
|
4
|
+
|
|
5
|
+
## Integration Model
|
|
6
|
+
|
|
7
|
+
Xopt evaluates objective functions externally, one point at a time. `scipy.optimize.minimize` expects an in-process callable objective. `ScipyGenerator` bridges this mismatch by running one persistent scipy session in a worker thread:
|
|
8
|
+
|
|
9
|
+
1. A cache is built from prior evaluations (`data`) keyed by rounded variable values.
|
|
10
|
+
2. A single `minimize` call starts in a background thread.
|
|
11
|
+
3. The objective callback first checks the cache.
|
|
12
|
+
4. For an uncached point, that point is pushed to Xopt via a request queue.
|
|
13
|
+
5. Xopt evaluates the point externally and calls `add_data`.
|
|
14
|
+
6. The objective value is sent back through a response queue, and the same scipy run continues from in-memory state.
|
|
15
|
+
|
|
16
|
+
Only the first `add_data` call answering a pending request sends a response to
|
|
17
|
+
scipy. Repeated submissions of the same candidate remain in the data history,
|
|
18
|
+
but cannot answer a later request. Values are also cached under the requested
|
|
19
|
+
coordinates, so small readback differences accepted by sequential point
|
|
20
|
+
validation do not cause cache misses after a session restart.
|
|
21
|
+
|
|
22
|
+
## Performance Notes
|
|
23
|
+
|
|
24
|
+
- Cache reconstruction is O(N) when a session starts or data is reloaded.
|
|
25
|
+
- The active scipy run is maintained between `step` calls; `minimize` is not restarted each step.
|
|
26
|
+
- Keys are rounded to 12 decimals before cache lookup to reduce floating-point key mismatch issues.
|
|
27
|
+
|
|
28
|
+
## Supported Methods
|
|
29
|
+
|
|
30
|
+
`method` is validated against bounded scipy methods supported by this wrapper:
|
|
31
|
+
|
|
32
|
+
- `Nelder-Mead`
|
|
33
|
+
- `Powell`
|
|
34
|
+
- `L-BFGS-B`
|
|
35
|
+
- `TNC`
|
|
36
|
+
- `SLSQP`
|
|
37
|
+
- `trust-constr`
|
|
38
|
+
- `COBYLA`
|
|
39
|
+
- `COBYQA`
|
|
40
|
+
|
|
41
|
+
Invalid or empty method names fail validation.
|
|
42
|
+
|
|
43
|
+
## Session Lifecycle and Errors
|
|
44
|
+
|
|
45
|
+
- `reset()` stops the active worker session and clears the result and completion state.
|
|
46
|
+
- `set_data(...)` stops any active session, clears completion state, reloads data, and rebuilds the cache.
|
|
47
|
+
- Each worker retains its own stop event, queues, and cache. Shutdown waits up to two seconds and warns if the worker is still running in scipy; that worker cannot consume responses or publish requests, results, or errors into a subsequent session.
|
|
48
|
+
- `result` exposes scipy's `OptimizeResult` after termination, including `success`, `message`, and solver-specific fields such as `nit`. It is `None` before termination.
|
|
49
|
+
- `is_done` is true once scipy terminates, including unsuccessful termination (for example, reaching an iteration limit). Check `result.success` to distinguish successful convergence.
|
|
50
|
+
- Once terminated, later `generate()` calls do not restart scipy or rebuild the cache. For compatibility, they still return the latest known data row, with a `RuntimeWarning` emitted once per session on this fallback path. Further explicit `Xopt.step()` calls will re-evaluate and append this duplicate; stop stepping when `generator.is_done` is true.
|
|
51
|
+
- Common scipy `ValueError` messages are remapped to clearer runtime errors (for example unsupported solver availability or bound handling).
|
|
52
|
+
|
|
53
|
+
## State Restoration
|
|
54
|
+
|
|
55
|
+
For model-level roundtrips, use pydantic serialization:
|
|
56
|
+
|
|
57
|
+
- `model_dump()`
|
|
58
|
+
- `model_validate(...)`
|
|
59
|
+
|
|
60
|
+
Then restore the evaluation history with `set_data(...)` so the cache and last outcome are reconstructed before continuing optimization.
|
|
61
|
+
|
|
62
|
+
The class also defines `__getstate__` and `__setstate__` for explicit state handling of non-picklable runtime thread objects.
|
|
63
|
+
Pickling does not stop the original worker. Pickle and deep-copy roundtrips retain
|
|
64
|
+
completed results and the completion latch without sharing runtime thread objects;
|
|
65
|
+
model-level roundtrips restart from the restored evaluation history instead.
|
|
66
|
+
Requested-coordinate cache entries are retained through `reset()`, pickle, and
|
|
67
|
+
deep-copy roundtrips. Replacing the dataset with `set_data(...)` clears these
|
|
68
|
+
entries; model-level roundtrips rebuild from observed coordinates in the restored
|
|
69
|
+
history.
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
Typical fields:
|
|
74
|
+
|
|
75
|
+
- `method`: scipy minimization method name, e.g. `Powell`, `Nelder-Mead`, `L-BFGS-B`.
|
|
76
|
+
- `initial_point`: optional starting point dictionary.
|
|
77
|
+
- `tol`, `options`: passed directly to `scipy.optimize.minimize`.
|
|
78
|
+
- `scipy_kwargs`: additional keyword arguments forwarded to scipy.
|
|
79
|
+
|
|
80
|
+
::: xopt.generators.sequential.scipy
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Stopping Conditions
|
|
2
|
+
|
|
3
|
+
## Maximum elapsed time
|
|
4
|
+
|
|
5
|
+
Use `MaxTimeCondition` to stop after a positive, finite number of wall-clock
|
|
6
|
+
seconds:
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from xopt.stopping_conditions import MaxTimeCondition
|
|
10
|
+
|
|
11
|
+
X.stopping_condition = MaxTimeCondition(max_time=60.0)
|
|
12
|
+
X.run()
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The timer starts when `should_stop()` is first called, normally at the start of
|
|
16
|
+
`run()`, and uses a monotonic clock. Time before that first check is not counted.
|
|
17
|
+
Conditions are checked between optimization steps, so an
|
|
18
|
+
in-progress evaluation is allowed to finish and the time limit may be exceeded.
|
|
19
|
+
The condition also works without evaluation data and can be nested inside a
|
|
20
|
+
`CompositeCondition`.
|
|
21
|
+
|
|
22
|
+
For YAML configuration:
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
stopping_condition:
|
|
26
|
+
name: MaxTimeCondition
|
|
27
|
+
max_time: 60.0
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Only the time limit is serialized. Loading a saved configuration resets the
|
|
31
|
+
timer; the full time budget starts at the first check.
|
|
32
|
+
|
|
33
|
+
::: xopt.stopping_conditions
|
|
@@ -42,12 +42,13 @@ Currenty **Xopt** provides:
|
|
|
42
42
|
- [`extremum_seeking`](examples/sequential/extremum_seeking.ipynb) Extremum seeking time-dependent optimization
|
|
43
43
|
- [`rcds`](examples/sequential/rcds.ipynb) Robust Conjugate Direction Search (RCDS)
|
|
44
44
|
- [`neldermead`](examples/sequential/neldermead.ipynb) Nelder-Mead Simplex
|
|
45
|
+
- [`scipy`](examples/sequential/scipy.ipynb) Scipy-based optimization algorithms (Powell, L-BFGS-B, etc.)
|
|
45
46
|
- Sampling algorithms:
|
|
46
47
|
- `random` Uniform random sampling
|
|
47
48
|
- Convenient YAML/JSON based input format
|
|
48
49
|
- Driver programs:
|
|
49
|
-
- [`xopt-run`](examples/basic/xopt_cli.md) Run Xopt from the command line using a YAML config file
|
|
50
|
-
- `xopt.
|
|
50
|
+
- [`xopt-run`](examples/basic/xopt_cli.md#xopt-run-usage) Run Xopt from the command line using a YAML config file
|
|
51
|
+
- [`xopt-mpirun`](examples/basic/xopt_cli.md#xopt-mpirun-usage) Parallel MPI execution using this input format
|
|
51
52
|
|
|
52
53
|
**Xopt** does **not** provide:
|
|
53
54
|
- your custom simulation via an `evaluate` function.
|
|
@@ -151,7 +152,7 @@ Using MPI
|
|
|
151
152
|
===============
|
|
152
153
|
Example MPI run, with `xopt.yaml` as the only user-defined file:
|
|
153
154
|
```b
|
|
154
|
-
mpirun -n 64
|
|
155
|
+
mpirun -n 64 xopt-mpirun xopt.yaml
|
|
155
156
|
```
|
|
156
157
|
|
|
157
158
|
|
|
@@ -63,11 +63,12 @@ nav:
|
|
|
63
63
|
- Genetic operators: examples/ga/nsga2/genetic_operators.ipynb
|
|
64
64
|
|
|
65
65
|
- Sequential:
|
|
66
|
+
- Scipy Minimize: examples/sequential/scipy.ipynb
|
|
66
67
|
- Nelder-Mead: examples/sequential/neldermead.ipynb
|
|
67
68
|
- Extremum seeking: examples/sequential/extremum_seeking.ipynb
|
|
68
69
|
- RCDS: examples/sequential/rcds.ipynb
|
|
69
70
|
- Other:
|
|
70
|
-
- Latin Hypercube: examples/
|
|
71
|
+
- Latin Hypercube: examples/other/latin_hypercube.ipynb
|
|
71
72
|
- Developer:
|
|
72
73
|
- Benchmarking & Profiling: examples/developer/benchmarking.md
|
|
73
74
|
|
|
@@ -105,6 +106,7 @@ nav:
|
|
|
105
106
|
- Genetic Operators: api/generators/ga/operators.md
|
|
106
107
|
- Sequential generators:
|
|
107
108
|
- Sequential Base Class: api/generators/sequential/sequential_generator.md
|
|
109
|
+
- Scipy Minimize: api/generators/sequential/scipy.md
|
|
108
110
|
- RCDS: api/generators/sequential/rcds.md
|
|
109
111
|
- Extremum Seeking: api/generators/sequential/extremumseeking.md
|
|
110
112
|
- Nelder-Mead: api/generators/sequential/neldermead.md
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '3.
|
|
22
|
-
__version_tuple__ = version_tuple = (3,
|
|
21
|
+
__version__ = version = '3.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 3, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gf13d21cd6'
|
|
@@ -159,6 +159,13 @@ class AsynchronousXopt(Xopt):
|
|
|
159
159
|
|
|
160
160
|
self.add_data(new_data)
|
|
161
161
|
|
|
162
|
+
# dump to file(s) if specified
|
|
163
|
+
if len(new_data):
|
|
164
|
+
if self.xopt_dump_file is not None:
|
|
165
|
+
self.dump()
|
|
166
|
+
if self.data_dump_file is not None:
|
|
167
|
+
self.dump_data()
|
|
168
|
+
|
|
162
169
|
# Cleanup
|
|
163
170
|
self._input_data.drop(index, inplace=True)
|
|
164
171
|
|
|
@@ -391,8 +391,8 @@ class Xopt(XoptBaseModel):
|
|
|
391
391
|
while True:
|
|
392
392
|
# Check custom stopping condition
|
|
393
393
|
if self.stopping_condition is not None:
|
|
394
|
-
if self.
|
|
395
|
-
self.data, self.vocs
|
|
394
|
+
if self.stopping_condition.should_stop(
|
|
395
|
+
self.data if self.data is not None else pd.DataFrame(), self.vocs
|
|
396
396
|
):
|
|
397
397
|
logger.info("Xopt is done. Stopping condition met.")
|
|
398
398
|
break
|
|
@@ -539,6 +539,9 @@ class Xopt(XoptBaseModel):
|
|
|
539
539
|
except DataError as exc:
|
|
540
540
|
if self.strict:
|
|
541
541
|
raise exc
|
|
542
|
+
warnings.warn(
|
|
543
|
+
f"Generator rejected {len(new_data)} new data point(s) (strict=False): {exc}"
|
|
544
|
+
)
|
|
542
545
|
|
|
543
546
|
def reset_data(self):
|
|
544
547
|
"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__all__ = []
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from mpi4py import MPI
|
|
2
|
+
from mpi4py.futures import MPICommExecutor
|
|
3
|
+
import argparse
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import sys
|
|
8
|
+
import yaml
|
|
9
|
+
|
|
10
|
+
from xopt import AsynchronousXopt
|
|
11
|
+
from xopt.base import Xopt
|
|
12
|
+
from xopt.entrypoint.utils import (
|
|
13
|
+
merge_dicts,
|
|
14
|
+
normalize_initial_data,
|
|
15
|
+
override_to_dict,
|
|
16
|
+
setup_import_paths,
|
|
17
|
+
)
|
|
18
|
+
from xopt.log import set_handler_with_logger
|
|
19
|
+
from xopt.pydantic import remove_none_values
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
comm = MPI.COMM_WORLD
|
|
23
|
+
mpi_rank = comm.Get_rank()
|
|
24
|
+
mpi_size = comm.Get_size()
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger("xopt")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def run_mpi(
|
|
30
|
+
config,
|
|
31
|
+
verbosity=None,
|
|
32
|
+
asynchronous=True,
|
|
33
|
+
logfile=None,
|
|
34
|
+
python_path=None,
|
|
35
|
+
initial_data=None,
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Xopt MPI driver
|
|
39
|
+
|
|
40
|
+
Basic usage:
|
|
41
|
+
|
|
42
|
+
mpirun -n 4 xopt-mpirun xopt.yaml
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
config : dict
|
|
47
|
+
Xopt configuration.
|
|
48
|
+
verbosity : int, optional
|
|
49
|
+
Verbosity count controlling the log level.
|
|
50
|
+
asynchronous : bool, default=True
|
|
51
|
+
Run with AsynchronousXopt instead of Xopt.
|
|
52
|
+
logfile : str, optional
|
|
53
|
+
File log messages are written to.
|
|
54
|
+
python_path : list of str, optional
|
|
55
|
+
Directories added to the module search path on every rank. Worker ranks import
|
|
56
|
+
the evaluation function themselves, so this must run before the Xopt object is
|
|
57
|
+
built.
|
|
58
|
+
initial_data : str, optional
|
|
59
|
+
CSV file of existing data used to seed the generator, read on the root rank.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
level = "WARN"
|
|
63
|
+
if verbosity:
|
|
64
|
+
iv = verbosity
|
|
65
|
+
if iv == 1:
|
|
66
|
+
level = "WARN"
|
|
67
|
+
elif iv == 2:
|
|
68
|
+
level = "INFO"
|
|
69
|
+
elif iv >= 3:
|
|
70
|
+
level = "DEBUG"
|
|
71
|
+
|
|
72
|
+
set_handler_with_logger(level=level)
|
|
73
|
+
|
|
74
|
+
if logfile:
|
|
75
|
+
set_handler_with_logger(file=logfile, level=level)
|
|
76
|
+
|
|
77
|
+
setup_import_paths(python_path or [])
|
|
78
|
+
|
|
79
|
+
# logger.info(xopt_logo)
|
|
80
|
+
# logger.info('_________________________________')
|
|
81
|
+
logger.info(f"Parallel execution with {mpi_size} workers")
|
|
82
|
+
|
|
83
|
+
if asynchronous:
|
|
84
|
+
logger.info("Enabling async mode")
|
|
85
|
+
X = AsynchronousXopt(**config)
|
|
86
|
+
else:
|
|
87
|
+
X = Xopt(**config)
|
|
88
|
+
|
|
89
|
+
if mpi_rank == 0:
|
|
90
|
+
print(X)
|
|
91
|
+
sys.stdout.flush()
|
|
92
|
+
|
|
93
|
+
# Launch MPI executor (it is None for the workers)
|
|
94
|
+
with MPICommExecutor(MPI.COMM_WORLD, root=0) as executor:
|
|
95
|
+
if executor is not None:
|
|
96
|
+
X.evaluator.executor = executor
|
|
97
|
+
X.evaluator.max_workers = mpi_size
|
|
98
|
+
|
|
99
|
+
if initial_data is not None:
|
|
100
|
+
logger.info(f"Loading initial data from {initial_data}")
|
|
101
|
+
X.add_data(normalize_initial_data(pd.read_csv(initial_data), X.vocs))
|
|
102
|
+
|
|
103
|
+
X.run()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def main():
|
|
107
|
+
parser = argparse.ArgumentParser(description="Configure xopt")
|
|
108
|
+
parser.add_argument("input_file", help="input_file")
|
|
109
|
+
parser.add_argument("--logfile", "-l", help="Log file to write to")
|
|
110
|
+
parser.add_argument("--verbose", "-v", action="count", help="Show more log output")
|
|
111
|
+
parser.add_argument(
|
|
112
|
+
"--asynchronous",
|
|
113
|
+
"-a",
|
|
114
|
+
action=argparse.BooleanOptionalAction,
|
|
115
|
+
help="Use asynchronous execution",
|
|
116
|
+
default=True,
|
|
117
|
+
)
|
|
118
|
+
parser.add_argument(
|
|
119
|
+
"--python_path",
|
|
120
|
+
help="Additional path to add to Python import path for evaluation function module search",
|
|
121
|
+
action="append",
|
|
122
|
+
default=[],
|
|
123
|
+
)
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--override",
|
|
126
|
+
help="Override config values using dot notation (e.g., generator.mutation_operator.eta_m=20)",
|
|
127
|
+
action="append",
|
|
128
|
+
default=[],
|
|
129
|
+
)
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--initial_data",
|
|
132
|
+
help="CSV file with initial data to seed the generator before running",
|
|
133
|
+
type=str,
|
|
134
|
+
default=None,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
args = parser.parse_args()
|
|
138
|
+
if mpi_rank == 0:
|
|
139
|
+
print(args)
|
|
140
|
+
|
|
141
|
+
input_file = args.input_file
|
|
142
|
+
logfile = args.logfile
|
|
143
|
+
verbosity = args.verbose
|
|
144
|
+
asynchronous = args.asynchronous
|
|
145
|
+
|
|
146
|
+
if not os.path.exists(input_file):
|
|
147
|
+
if mpi_rank == 0:
|
|
148
|
+
print(f"Input file does not exist: {input_file}", file=sys.stderr)
|
|
149
|
+
sys.exit(1)
|
|
150
|
+
|
|
151
|
+
with open(input_file) as f:
|
|
152
|
+
config = yaml.safe_load(f)
|
|
153
|
+
config = remove_none_values(config)
|
|
154
|
+
|
|
155
|
+
if args.override:
|
|
156
|
+
logger.info("Applying config file overrides:")
|
|
157
|
+
for override in args.override:
|
|
158
|
+
logger.info(f" {override}")
|
|
159
|
+
config = merge_dicts(config, override_to_dict(override))
|
|
160
|
+
|
|
161
|
+
run_mpi(
|
|
162
|
+
config,
|
|
163
|
+
verbosity=verbosity,
|
|
164
|
+
logfile=logfile,
|
|
165
|
+
asynchronous=asynchronous,
|
|
166
|
+
python_path=[os.getcwd()] + args.python_path,
|
|
167
|
+
initial_data=args.initial_data,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if __name__ == "__main__":
|
|
172
|
+
main()
|
|
@@ -1,61 +1,23 @@
|
|
|
1
|
-
from
|
|
2
|
-
from
|
|
3
|
-
from
|
|
1
|
+
from ..base import Xopt
|
|
2
|
+
from ..evaluator import DummyExecutor
|
|
3
|
+
from ..pydantic import remove_none_values
|
|
4
|
+
from .utils import (
|
|
5
|
+
merge_dicts,
|
|
6
|
+
normalize_initial_data,
|
|
7
|
+
override_to_dict,
|
|
8
|
+
setup_import_paths,
|
|
9
|
+
)
|
|
4
10
|
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
|
|
5
11
|
from contextlib import contextmanager
|
|
6
12
|
import argparse
|
|
7
13
|
import logging
|
|
8
14
|
import os
|
|
9
15
|
import pandas as pd
|
|
10
|
-
import sys
|
|
11
16
|
import yaml
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
logger = logging.getLogger(__name__)
|
|
15
20
|
|
|
16
|
-
_XOPT_INITIAL_COLS = ["xopt_candidate_idx", "xopt_runtime", "xopt_error"]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def normalize_initial_data(df: pd.DataFrame, vocs) -> pd.DataFrame:
|
|
20
|
-
"""
|
|
21
|
-
Validate and normalize a user-supplied initial-data DataFrame before
|
|
22
|
-
passing it to Xopt.add_data.
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
df : pd.DataFrame
|
|
27
|
-
Raw DataFrame loaded from the user's CSV.
|
|
28
|
-
vocs : VOCS
|
|
29
|
-
The VOCS object from the Xopt instance.
|
|
30
|
-
|
|
31
|
-
Returns
|
|
32
|
-
-------
|
|
33
|
-
pd.DataFrame
|
|
34
|
-
Normalized DataFrame with required VOCS columns present, xopt metadata
|
|
35
|
-
columns filled with defaults if absent, and unrecognized columns dropped.
|
|
36
|
-
"""
|
|
37
|
-
missing = set(vocs.all_names) - set(df.columns)
|
|
38
|
-
if missing:
|
|
39
|
-
raise ValueError(
|
|
40
|
-
f"Initial data is missing required VOCS columns: {sorted(missing)}"
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
df = df.copy()
|
|
44
|
-
if "xopt_candidate_idx" not in df.columns:
|
|
45
|
-
df["xopt_candidate_idx"] = range(len(df))
|
|
46
|
-
if "xopt_runtime" not in df.columns:
|
|
47
|
-
df["xopt_runtime"] = 0.0
|
|
48
|
-
if "xopt_error" not in df.columns:
|
|
49
|
-
df["xopt_error"] = False
|
|
50
|
-
|
|
51
|
-
keep = list(vocs.all_names) + _XOPT_INITIAL_COLS
|
|
52
|
-
if "xopt_error_str" in df.columns:
|
|
53
|
-
keep = keep + ["xopt_error_str"]
|
|
54
|
-
extra = sorted(set(df.columns) - set(keep))
|
|
55
|
-
if extra:
|
|
56
|
-
logger.warning(f"Dropping unrecognized columns from initial data: {extra}")
|
|
57
|
-
return df[[c for c in keep if c in df.columns]]
|
|
58
|
-
|
|
59
21
|
|
|
60
22
|
@contextmanager
|
|
61
23
|
def get_executor(name, max_workers=1):
|
|
@@ -88,59 +50,6 @@ def get_executor(name, max_workers=1):
|
|
|
88
50
|
raise ValueError(f"Unknown executor: {name}")
|
|
89
51
|
|
|
90
52
|
|
|
91
|
-
def override_to_dict(override: str) -> dict:
|
|
92
|
-
"""
|
|
93
|
-
Convert strings of form "class_a.class_b.class_c.param=1" to
|
|
94
|
-
{'class_a': {'class_b': {'class_c': {'param': 1}}}}.
|
|
95
|
-
|
|
96
|
-
Uses yaml library for consistent type conversion of values following
|
|
97
|
-
same convention as in config files.
|
|
98
|
-
|
|
99
|
-
Parameters
|
|
100
|
-
----------
|
|
101
|
-
override : str
|
|
102
|
-
The override string
|
|
103
|
-
|
|
104
|
-
Returns
|
|
105
|
-
-------
|
|
106
|
-
dict
|
|
107
|
-
The nested dictionary containing the value.
|
|
108
|
-
"""
|
|
109
|
-
path, value = override.split("=", 1)
|
|
110
|
-
yaml_str = (
|
|
111
|
-
"\n".join([" " * idx + x + ":" for idx, x in enumerate(path.split("."))])
|
|
112
|
-
+ " "
|
|
113
|
-
+ value.strip()
|
|
114
|
-
)
|
|
115
|
-
return yaml.safe_load(yaml_str)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def merge_dicts(dict1: dict, dict2: dict) -> dict:
|
|
119
|
-
"""
|
|
120
|
-
Nested merging of dicts. Will combine nested dicts keeping keys in both with
|
|
121
|
-
the values in dict2 overriding those in dict1.
|
|
122
|
-
|
|
123
|
-
Parameters
|
|
124
|
-
----------
|
|
125
|
-
dict1 : dict
|
|
126
|
-
Parameters to override
|
|
127
|
-
dict2 : dict
|
|
128
|
-
Parameters used to override those in dict1
|
|
129
|
-
|
|
130
|
-
Returns
|
|
131
|
-
-------
|
|
132
|
-
dict
|
|
133
|
-
Values from dict1 with overrides from dict2
|
|
134
|
-
"""
|
|
135
|
-
result = dict1.copy()
|
|
136
|
-
for key, value in dict2.items():
|
|
137
|
-
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
|
138
|
-
result[key] = merge_dicts(result[key], value)
|
|
139
|
-
else:
|
|
140
|
-
result[key] = value
|
|
141
|
-
return result
|
|
142
|
-
|
|
143
|
-
|
|
144
53
|
def main():
|
|
145
54
|
# Handle the CLI arguments
|
|
146
55
|
parser = argparse.ArgumentParser()
|
|
@@ -187,18 +96,7 @@ def main():
|
|
|
187
96
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
|
188
97
|
)
|
|
189
98
|
|
|
190
|
-
|
|
191
|
-
import_paths = [os.getcwd()]
|
|
192
|
-
import_paths.extend(
|
|
193
|
-
[os.path.expanduser(os.path.expandvars(x)) for x in args.python_path]
|
|
194
|
-
)
|
|
195
|
-
if len(import_paths) > 1:
|
|
196
|
-
logger.info("Python path additions:")
|
|
197
|
-
for idx, import_path in enumerate(import_paths):
|
|
198
|
-
if idx:
|
|
199
|
-
logger.info(f" {import_path}")
|
|
200
|
-
if import_path not in sys.path:
|
|
201
|
-
sys.path.insert(0, import_path)
|
|
99
|
+
setup_import_paths([os.getcwd()] + args.python_path)
|
|
202
100
|
|
|
203
101
|
# Create xopt
|
|
204
102
|
with open(args.config) as f:
|
|
@@ -212,14 +110,8 @@ def main():
|
|
|
212
110
|
if args.override:
|
|
213
111
|
logger.info("Applying config file overrides:")
|
|
214
112
|
for override in args.override:
|
|
215
|
-
logger.info(f" {override}")
|
|
216
|
-
# Sanity check
|
|
217
|
-
if "=" not in override:
|
|
218
|
-
raise ValueError(
|
|
219
|
-
f'Invalid override format: "{override}". Expected key=value'
|
|
220
|
-
)
|
|
221
|
-
|
|
222
113
|
# Merge in the config override
|
|
114
|
+
logger.info(f" {override}")
|
|
223
115
|
config = merge_dicts(config, override_to_dict(override))
|
|
224
116
|
|
|
225
117
|
# Construct Xopt object
|