xopt 3.2.1__tar.gz → 3.2.2__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.1 → xopt-3.2.2}/PKG-INFO +1 -1
- {xopt-3.2.1 → xopt-3.2.2}/environment.yml +2 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/_version.py +3 -3
- {xopt-3.2.1 → xopt-3.2.2}/xopt/base.py +87 -14
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/turbo.py +4 -3
- xopt-3.2.2/xopt/generators/checkpoints.py +123 -0
- xopt-3.2.2/xopt/generators/ga/base.py +239 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/cnsga.py +3 -1
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/nsga2.py +11 -204
- {xopt-3.2.1 → xopt-3.2.2}/xopt/pydantic.py +14 -1
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_high_level.py +3 -3
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_turbo.py +25 -1
- xopt-3.2.2/xopt/tests/generators/ga/test_base.py +474 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/ga/test_cnsga.py +2 -2
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/ga/test_nsga2.py +2 -8
- xopt-3.2.2/xopt/tests/generators/test_checkpoints.py +122 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_log.py +1 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_xopt.py +125 -6
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/PKG-INFO +1 -1
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/SOURCES.txt +4 -60
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/scm_file_list.json +174 -230
- xopt-3.2.2/xopt.egg-info/scm_version.json +8 -0
- xopt-3.2.1/.github/workflows/gh-pages.yml +0 -353
- xopt-3.2.1/.github/workflows/lint.yml +0 -64
- xopt-3.2.1/.github/workflows/pypi_upload.yml +0 -36
- xopt-3.2.1/.github/workflows/test-notebooks.yml +0 -265
- xopt-3.2.1/.github/workflows/tests.yml +0 -62
- xopt-3.2.1/docs/examples/basic/checkpointing_and_restarts.ipynb +0 -155
- xopt-3.2.1/docs/examples/basic/xopt_basic.ipynb +0 -532
- xopt-3.2.1/docs/examples/basic/xopt_cli.md +0 -77
- xopt-3.2.1/docs/examples/basic/xopt_evaluator.ipynb +0 -448
- xopt-3.2.1/docs/examples/basic/xopt_generator.ipynb +0 -222
- xopt-3.2.1/docs/examples/basic/xopt_parallel.ipynb +0 -584
- xopt-3.2.1/docs/examples/basic/xopt_stopping_condition.ipynb +0 -791
- xopt-3.2.1/docs/examples/basic/xopt_vocs.ipynb +0 -506
- xopt-3.2.1/docs/examples/bayes_exp/bayesian_exploration.ipynb +0 -261
- xopt-3.2.1/docs/examples/bayes_exp/bayesian_exploration_from_yaml.ipynb +0 -169
- xopt-3.2.1/docs/examples/bayes_exp/bayesian_exploration_w_interpolation.ipynb +0 -299
- xopt-3.2.1/docs/examples/bayes_exp/bayesian_exploration_with_nans.ipynb +0 -191
- xopt-3.2.1/docs/examples/developer/benchmarking.md +0 -87
- xopt-3.2.1/docs/examples/ga/cnsga_tnk.ipynb +0 -537
- xopt-3.2.1/docs/examples/ga/nsga2/assets/benchmarking.pdf +0 -0
- xopt-3.2.1/docs/examples/ga/nsga2/assets/zdt3_pf.png +0 -0
- xopt-3.2.1/docs/examples/ga/nsga2/genetic_operators.ipynb +0 -165
- xopt-3.2.1/docs/examples/ga/nsga2/index.md +0 -40
- xopt-3.2.1/docs/examples/ga/nsga2/nsga2_python.ipynb +0 -379
- xopt-3.2.1/docs/examples/ga/nsga2/nsga2_to_cnsga.ipynb +0 -276
- xopt-3.2.1/docs/examples/ga/nsga2/yaml_interface/assets/yaml_runner_example/eval_fun.py +0 -41
- xopt-3.2.1/docs/examples/ga/nsga2/yaml_interface/assets/yaml_runner_example/nsga2_from_checkpoint.yml +0 -71
- xopt-3.2.1/docs/examples/ga/nsga2/yaml_interface/assets/yaml_runner_example/nsga2_zdt3.yml +0 -72
- xopt-3.2.1/docs/examples/ga/nsga2/yaml_interface/index.md +0 -297
- xopt-3.2.1/docs/examples/ga/nsga2/yaml_interface/nsga2_yaml.ipynb +0 -201
- xopt-3.2.1/docs/examples/gp_model_creation/approximate.ipynb +0 -186
- xopt-3.2.1/docs/examples/gp_model_creation/batched_model.ipynb +0 -264
- xopt-3.2.1/docs/examples/gp_model_creation/model_creation.ipynb +0 -243
- xopt-3.2.1/docs/examples/multi_objective_bayes_opt/mggpo.ipynb +0 -205
- xopt-3.2.1/docs/examples/multi_objective_bayes_opt/mobo.ipynb +0 -220
- xopt-3.2.1/docs/examples/multi_objective_bayes_opt/multi_fidelity_mobo.ipynb +0 -335
- xopt-3.2.1/docs/examples/scipy/latin_hypercube.ipynb +0 -190
- xopt-3.2.1/docs/examples/sequential/extremum_seeking.ipynb +0 -962
- xopt-3.2.1/docs/examples/sequential/neldermead.ipynb +0 -653
- xopt-3.2.1/docs/examples/sequential/rcds.ipynb +0 -862
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/bax_tutorial.ipynb +0 -378
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/benchmarking.ipynb +0 -280
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/bo_tutorial.ipynb +0 -313
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/constrained_bo_tutorial.ipynb +0 -383
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/contextual_bo.ipynb +0 -380
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/custom_model.ipynb +0 -270
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/custom_objective.ipynb +0 -231
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/fast_model_eval.ipynb +0 -160
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/fixed_features.ipynb +0 -309
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/hessian_kernel.ipynb +0 -157
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/heteroskedastic_noise_tutorial.ipynb +0 -314
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/interpolate_tutorial.ipynb +0 -298
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/mixed_discrete.ipynb +0 -274
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/multi_fidelity_simple.ipynb +0 -339
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/noisy_bo_tutorial.ipynb +0 -312
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/time_dependent_bo.ipynb +0 -425
- xopt-3.2.1/docs/examples/single_objective_bayes_opt/upper_confidence_bound.ipynb +0 -153
- xopt-3.2.1/docs/examples/trust_region_bo/turbo_basics.ipynb +0 -222
- xopt-3.2.1/docs/examples/trust_region_bo/turbo_optimize.ipynb +0 -361
- xopt-3.2.1/docs/examples/trust_region_bo/turbo_safety.ipynb +0 -368
- xopt-3.2.1/xopt.egg-info/scm_version.json +0 -8
- {xopt-3.2.1 → xopt-3.2.2}/.pre-commit-config.yaml +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/LICENSE +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/MANIFEST.in +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/README.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/benchmarks/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/benchmarks/test_mo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/benchmarks/test_neldermead.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/benchmarks/test_ucb.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/codecov.yml +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/algorithms.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/evaluator.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bax/acquisition_functions.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bax/algorithms.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bax/bax_generator.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bax/visualize.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bayesian_exploration.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/bayesian_generator.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/expected_improvement.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/mggpo.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/mobo.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/models/base_model_constructor.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/models/standard_model_constructor.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/models/time_dependent_model_constructor.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/multi_fidelity.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/time_dependent.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/turbo.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/upper_confidence_bound.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/bayesian/utils.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/deduplicated.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/ga/cnsga.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/ga/deap_creator.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/ga/deap_fitness_with_constraints.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/ga/nsga2.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/ga/operators.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/random.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/sequential/extremumseeking.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/sequential/neldermead.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/sequential/rcds.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/sequential/sequential_generator.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators/utils.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/generators.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/numerical_optimizer.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/stopping_conditions.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/utils.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/vocs.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/api/xopt.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/assets/Xopt-logo.png +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/assets/xopt_overview.pdf +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/hooks/zip_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/index.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/installation.md +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/overrides/main.html +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/docs/stylesheets/extra.css +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/mkdocs.yml +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/pyproject.toml +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/scripts/execute_notebooks.bash +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/scripts/run_benchmarks.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/scripts/run_examples.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/scripts/run_tests.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/setup.cfg +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/asynchronous.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/entrypoint.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/errors.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/evaluator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/base_model.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bax/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bax/acquisition.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bax/algorithms.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bax/visualize.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bax_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bayesian_exploration.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/bayesian_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/constrained_acquisition.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/hessian_kernel.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/heteroskedastic.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/log_acquisition_function.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/custom_botorch/multi_fidelity.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/expected_improvement.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/mggpo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/mobo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/models/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/models/approximate.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/models/prior_mean.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/models/standard.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/models/time_dependent.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/multi_fidelity.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/objectives.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/time_dependent.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/upper_confidence_bound.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/bayesian/visualize.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/deduplicated.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/deap_creator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/deap_fitness_with_constraints.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/ga/operators.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/random.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/scipy/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/scipy/latin_hypercube.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/sequential/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/sequential/extremumseeking.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/sequential/neldermead.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/sequential/rcds.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/sequential/sequential_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/generators/utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/log.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/mpi/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/mpi/run.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/numerical_optimizer.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_framework.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_functions/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_functions/generators.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_functions/models.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_profiler.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/bench_runner.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/ackley_20.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/haverly_pooling.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/modified_tnk.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/multi_objective.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/problem.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/rosenbrock.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/sinusoid_1d.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/tnk.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/test_functions/zdt.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/resources/testing.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/stopping_conditions.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/__init__.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/conftest.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_bax.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_bax_visualize.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_bayesian_exploration.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_bayesian_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_constraints.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_contextual_bo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_custom_model.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_discrete_integration.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_expected_improvement.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_hessian_kernel.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_mggpo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_mobo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_model_constructor.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_multi_fidelity.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_objectives.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_time_dependent_bo.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_upper_confidence_bound.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/bayesian/test_visualize.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/external/test_aposmm.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/ga/test_deap_creator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/sequential/test_extremum_seeking.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/sequential/test_neldermead.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/sequential/test_rcds.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/sequential/test_sequential.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/sequential/test_serialization.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/test_deduplicated.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/test_latin_hypercube.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/test_operators.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/test_random.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/generators/test_utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_asynch_xopt.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_entrypoint.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_evaluator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_generator.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_io.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_mpi.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_numerical_optimizer.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_perf.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_pydantic.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_resources.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_stopping_condition.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/tests/test_vocs.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/utils.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt/vocs.py +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/dependency_links.txt +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/entry_points.txt +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/requires.txt +0 -0
- {xopt-3.2.1 → xopt-3.2.2}/xopt.egg-info/top_level.txt +0 -0
|
@@ -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.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (3, 2,
|
|
21
|
+
__version__ = version = '3.2.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 2, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gd4c488f75'
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
+
import os
|
|
3
4
|
from copy import deepcopy
|
|
4
5
|
from typing import Any, Optional, Union
|
|
5
6
|
|
|
@@ -40,6 +41,11 @@ from .errors import DataError
|
|
|
40
41
|
|
|
41
42
|
logger = logging.getLogger(__name__)
|
|
42
43
|
|
|
44
|
+
DUMP_FILE_RENAME_MESSAGE = (
|
|
45
|
+
"The attribute `dump_file` in `Xopt` has been renamed to `xopt_dump_file`. "
|
|
46
|
+
"Support for the old name will be removed in later versions of the Xopt library."
|
|
47
|
+
)
|
|
48
|
+
|
|
43
49
|
|
|
44
50
|
class Xopt(XoptBaseModel):
|
|
45
51
|
"""
|
|
@@ -59,9 +65,13 @@ class Xopt(XoptBaseModel):
|
|
|
59
65
|
strict : bool, optional
|
|
60
66
|
A flag indicating whether exceptions raised during evaluation should stop the
|
|
61
67
|
optimization process.
|
|
62
|
-
|
|
68
|
+
xopt_dump_file : str, optional
|
|
63
69
|
An optional file path for dumping attributes of the xopt object and the
|
|
64
|
-
results of evaluations.
|
|
70
|
+
results of evaluations. Environment variables and `~` are expanded when
|
|
71
|
+
dumping.
|
|
72
|
+
data_dump_file : str, optional
|
|
73
|
+
An optional file path for dumping the evaluation data as a CSV file.
|
|
74
|
+
Environment variables and `~` are expanded when dumping.
|
|
65
75
|
data : DataFrame, optional
|
|
66
76
|
An optional DataFrame object for storing internal data related to the optimization
|
|
67
77
|
process.
|
|
@@ -98,6 +108,8 @@ class Xopt(XoptBaseModel):
|
|
|
98
108
|
Serializes the Xopt configuration to a YAML string.
|
|
99
109
|
dump(file: str = None, **kwargs)
|
|
100
110
|
Dumps the Xopt configuration to a specified file.
|
|
111
|
+
dump_data()
|
|
112
|
+
Dumps the evaluation data to the file given by `data_dump_file`.
|
|
101
113
|
dict(**kwargs) -> dict
|
|
102
114
|
Provides a custom dictionary representation of the Xopt configuration.
|
|
103
115
|
json(**kwargs) -> str
|
|
@@ -115,8 +127,11 @@ class Xopt(XoptBaseModel):
|
|
|
115
127
|
description="flag to indicate if exceptions raised during evaluation "
|
|
116
128
|
"should stop Xopt",
|
|
117
129
|
)
|
|
118
|
-
|
|
119
|
-
None, description="file to dump the
|
|
130
|
+
xopt_dump_file: Optional[str] = Field(
|
|
131
|
+
None, description="file to dump the serialized Xopt object to"
|
|
132
|
+
)
|
|
133
|
+
data_dump_file: Optional[str] = Field(
|
|
134
|
+
None, description="file to dump the evaluation data to as CSV"
|
|
120
135
|
)
|
|
121
136
|
data: Optional[DataFrame] = Field(None, description="internal DataFrame object")
|
|
122
137
|
serialize_torch: bool = Field(
|
|
@@ -243,6 +258,35 @@ class Xopt(XoptBaseModel):
|
|
|
243
258
|
)
|
|
244
259
|
return data
|
|
245
260
|
|
|
261
|
+
@model_validator(mode="before")
|
|
262
|
+
@classmethod
|
|
263
|
+
def dump_file_legacy(cls, data: Any):
|
|
264
|
+
"""
|
|
265
|
+
Handle backward compatibility: convert the old dump_file parameter to
|
|
266
|
+
xopt_dump_file.
|
|
267
|
+
"""
|
|
268
|
+
if isinstance(data, dict) and "dump_file" in data:
|
|
269
|
+
warnings.warn(DUMP_FILE_RENAME_MESSAGE, DeprecationWarning, stacklevel=2)
|
|
270
|
+
dump_file = data.pop("dump_file")
|
|
271
|
+
if dump_file is not None:
|
|
272
|
+
if data.get("xopt_dump_file") is not None:
|
|
273
|
+
raise ValueError(
|
|
274
|
+
"Cannot specify both 'dump_file' and 'xopt_dump_file'. "
|
|
275
|
+
"Use 'xopt_dump_file' instead."
|
|
276
|
+
)
|
|
277
|
+
data["xopt_dump_file"] = dump_file
|
|
278
|
+
return data
|
|
279
|
+
|
|
280
|
+
@property
|
|
281
|
+
def dump_file(self) -> Optional[str]:
|
|
282
|
+
warnings.warn(DUMP_FILE_RENAME_MESSAGE, DeprecationWarning, stacklevel=2)
|
|
283
|
+
return self.xopt_dump_file
|
|
284
|
+
|
|
285
|
+
@dump_file.setter
|
|
286
|
+
def dump_file(self, value: Optional[str]):
|
|
287
|
+
warnings.warn(DUMP_FILE_RENAME_MESSAGE, DeprecationWarning, stacklevel=2)
|
|
288
|
+
self.xopt_dump_file = value
|
|
289
|
+
|
|
246
290
|
@property
|
|
247
291
|
def n_data(self) -> int:
|
|
248
292
|
if self.data is None:
|
|
@@ -440,9 +484,11 @@ class Xopt(XoptBaseModel):
|
|
|
440
484
|
|
|
441
485
|
self.add_data(output_data)
|
|
442
486
|
|
|
443
|
-
# dump
|
|
444
|
-
if self.
|
|
487
|
+
# dump to file(s) if specified
|
|
488
|
+
if self.xopt_dump_file is not None:
|
|
445
489
|
self.dump()
|
|
490
|
+
if self.data_dump_file is not None:
|
|
491
|
+
self.dump_data()
|
|
446
492
|
|
|
447
493
|
return output_data
|
|
448
494
|
|
|
@@ -624,31 +670,58 @@ class Xopt(XoptBaseModel):
|
|
|
624
670
|
|
|
625
671
|
def dump(self, file: str = None, **kwargs):
|
|
626
672
|
"""
|
|
627
|
-
Dump data to a file.
|
|
673
|
+
Dump the Xopt configuration and data to a YAML file.
|
|
674
|
+
|
|
675
|
+
Environment variables and `~` in the path are expanded.
|
|
628
676
|
|
|
629
677
|
Parameters
|
|
630
678
|
----------
|
|
631
679
|
file : str, optional
|
|
632
680
|
The path to the file where the Xopt configuration will be dumped.
|
|
681
|
+
Defaults to the `xopt_dump_file` attribute.
|
|
633
682
|
**kwargs
|
|
634
683
|
Additional keyword arguments for customizing the dump.
|
|
635
684
|
|
|
636
685
|
Raises
|
|
637
686
|
------
|
|
638
687
|
ValueError
|
|
639
|
-
If no dump file is specified via argument or in the `
|
|
688
|
+
If no dump file is specified via argument or in the `xopt_dump_file`
|
|
689
|
+
attribute.
|
|
640
690
|
|
|
641
691
|
"""
|
|
642
|
-
fname = file if file is not None else self.
|
|
692
|
+
fname = file if file is not None else self.xopt_dump_file
|
|
643
693
|
|
|
644
694
|
if fname is None:
|
|
645
695
|
raise ValueError(
|
|
646
|
-
"no dump file specified via argument or in `
|
|
696
|
+
"no dump file specified via argument or in `xopt_dump_file` attribute"
|
|
647
697
|
)
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
698
|
+
|
|
699
|
+
fname = os.path.expanduser(os.path.expandvars(fname))
|
|
700
|
+
with open(fname, "w") as f:
|
|
701
|
+
f.write(self.yaml(**kwargs))
|
|
702
|
+
logger.debug(f"Dumped state to YAML file: {fname}")
|
|
703
|
+
|
|
704
|
+
def dump_data(self):
|
|
705
|
+
"""
|
|
706
|
+
Dump the evaluation data to the CSV file given by `data_dump_file`.
|
|
707
|
+
|
|
708
|
+
Environment variables and `~` in the path are expanded.
|
|
709
|
+
|
|
710
|
+
Raises
|
|
711
|
+
------
|
|
712
|
+
ValueError
|
|
713
|
+
If no data dump file is specified in the `data_dump_file` attribute.
|
|
714
|
+
|
|
715
|
+
"""
|
|
716
|
+
if self.data_dump_file is None:
|
|
717
|
+
raise ValueError(
|
|
718
|
+
"no data dump file specified in `data_dump_file` attribute"
|
|
719
|
+
)
|
|
720
|
+
|
|
721
|
+
fname = os.path.expanduser(os.path.expandvars(self.data_dump_file))
|
|
722
|
+
data = self.data if self.data is not None else pd.DataFrame()
|
|
723
|
+
data.to_csv(fname, index_label="xopt_index")
|
|
724
|
+
logger.debug(f"Dumped data to CSV file: {fname}")
|
|
652
725
|
|
|
653
726
|
def dict(self, **kwargs) -> dict:
|
|
654
727
|
"""
|
|
@@ -256,10 +256,11 @@ class TurboController(XoptBaseModel, ABC):
|
|
|
256
256
|
if active_indices:
|
|
257
257
|
lengthscales = lengthscales[active_indices]
|
|
258
258
|
|
|
259
|
-
#
|
|
259
|
+
# Normalize by the geometric mean without forming the raw
|
|
260
|
+
# product, which can overflow or underflow.
|
|
260
261
|
active_dim = len(active_variable_names)
|
|
261
|
-
weights = lengthscales / torch.prod(
|
|
262
|
-
1 / active_dim
|
|
262
|
+
weights = lengthscales / torch.prod(
|
|
263
|
+
lengthscales ** (1 / active_dim)
|
|
263
264
|
)
|
|
264
265
|
|
|
265
266
|
# calculate the tr bounding box
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pydantic import BaseModel, Field, model_validator
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from ..vocs import VOCS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CheckpointMixin(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
Mix-in class adding checkpoint saving and loading to a generator.
|
|
12
|
+
|
|
13
|
+
Checkpoints are written to a caller-supplied directory. The VOCS object is
|
|
14
|
+
serialized into the checkpoint itself. Legacy checkpoints which predate this
|
|
15
|
+
instead carry the VOCS object in a "vocs.txt" file one level above the
|
|
16
|
+
directory holding the checkpoints and are still supported when loading.
|
|
17
|
+
|
|
18
|
+
The host class must provide a ``vocs`` attribute and a ``to_json`` method.
|
|
19
|
+
Writing of the checkpoint file is the responsibility of the concrete class
|
|
20
|
+
as it will be implementation dependent.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
checkpoint_file : str, optional
|
|
25
|
+
Path to checkpoint file to load from. If provided, the generator will be
|
|
26
|
+
initialized from the checkpoint state. User-specified parameters will
|
|
27
|
+
override checkpoint values.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
checkpoint_file: str | None = Field(
|
|
31
|
+
None, description="Path to checkpoint file to load from", exclude=True
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def _load_checkpoint_data(fname: str) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Internal function to load generator data from checkpoint file as well as VOCS object.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
fname : str
|
|
42
|
+
Path to the checkpoint file
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
dict
|
|
47
|
+
Dictionary containing VOCS and checkpoint data
|
|
48
|
+
"""
|
|
49
|
+
# Load the checkpoint
|
|
50
|
+
with open(fname) as f:
|
|
51
|
+
checkpoint_data = json.load(f)
|
|
52
|
+
|
|
53
|
+
if "vocs" in checkpoint_data:
|
|
54
|
+
return checkpoint_data
|
|
55
|
+
|
|
56
|
+
# Legacy checkpoints w/o VOCS
|
|
57
|
+
vocs_fname = os.path.join(os.path.dirname(fname), "../vocs.txt")
|
|
58
|
+
if not os.path.exists(vocs_fname):
|
|
59
|
+
raise ValueError(
|
|
60
|
+
f'Checkpoint "{fname}" does not contain a VOCS object and no '
|
|
61
|
+
f'VOCS file was found at "{vocs_fname}".'
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
with open(vocs_fname) as f:
|
|
65
|
+
vocs = VOCS(**json.load(f))
|
|
66
|
+
|
|
67
|
+
return {"vocs": vocs, **checkpoint_data}
|
|
68
|
+
|
|
69
|
+
@model_validator(mode="before")
|
|
70
|
+
@classmethod
|
|
71
|
+
def load_from_checkpoint(cls, values):
|
|
72
|
+
"""
|
|
73
|
+
Load from checkpoint file if checkpoint_file is provided.
|
|
74
|
+
"""
|
|
75
|
+
# Case when a checkpoint file has been supplied
|
|
76
|
+
if isinstance(values, dict) and "checkpoint_file" in values:
|
|
77
|
+
checkpoint_file = values.pop("checkpoint_file")
|
|
78
|
+
if checkpoint_file is not None:
|
|
79
|
+
# Load checkpoint data
|
|
80
|
+
checkpoint_data = cls._load_checkpoint_data(checkpoint_file)
|
|
81
|
+
|
|
82
|
+
# Merge with user data precedence
|
|
83
|
+
merged_data = {**checkpoint_data, **values}
|
|
84
|
+
return merged_data
|
|
85
|
+
|
|
86
|
+
# No checkpoint
|
|
87
|
+
return values
|
|
88
|
+
|
|
89
|
+
def _save_checkpoint(self, path: str | os.PathLike) -> str:
|
|
90
|
+
"""
|
|
91
|
+
Write a checkpoint of the generator state to disk.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
path : str or os.PathLike
|
|
96
|
+
Directory into which the checkpoint file is written. Created if it
|
|
97
|
+
does not already exist.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
str
|
|
102
|
+
Path to the checkpoint file which was written.
|
|
103
|
+
"""
|
|
104
|
+
# Set up the output directory
|
|
105
|
+
os.makedirs(path, exist_ok=True)
|
|
106
|
+
|
|
107
|
+
# Create a base filename
|
|
108
|
+
base_checkpoint_filename = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
109
|
+
checkpoint_path = os.path.join(path, f"{base_checkpoint_filename}_1.txt")
|
|
110
|
+
|
|
111
|
+
# Check if file exists and increment counter until we find a free filename
|
|
112
|
+
counter = 2
|
|
113
|
+
while os.path.exists(checkpoint_path):
|
|
114
|
+
checkpoint_path = os.path.join(
|
|
115
|
+
path, f"{base_checkpoint_filename}_{counter}.txt"
|
|
116
|
+
)
|
|
117
|
+
counter += 1
|
|
118
|
+
|
|
119
|
+
# Now we have a unique filename
|
|
120
|
+
with open(checkpoint_path, "w") as f:
|
|
121
|
+
f.write(self.to_json())
|
|
122
|
+
|
|
123
|
+
return checkpoint_path
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, computed_field, field_validator, model_validator
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from ..checkpoints import CheckpointMixin
|
|
8
|
+
from ..deduplicated import DeduplicatedGeneratorBase
|
|
9
|
+
|
|
10
|
+
POPULATION_METADATA_COLUMNS = [
|
|
11
|
+
"xopt_generation",
|
|
12
|
+
"xopt_candidate_idx",
|
|
13
|
+
"xopt_runtime",
|
|
14
|
+
"xopt_error",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _InstanceLogger(logging.Logger):
|
|
19
|
+
"""
|
|
20
|
+
Logger owned by a single object. Used for per-object logging in generator.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __reduce__(self):
|
|
24
|
+
return _make_instance_logger, (self.name, self.parent.name, self.level)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _make_instance_logger(name: str, parent_name: str, level: int) -> logging.Logger:
|
|
28
|
+
"""
|
|
29
|
+
Build an unregistered logger which propagates to an existing named logger.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
name : str
|
|
34
|
+
Name recorded on emitted records.
|
|
35
|
+
parent_name : str
|
|
36
|
+
Name of the logger records propagate to.
|
|
37
|
+
level : int
|
|
38
|
+
Level of the new logger.
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
logging.Logger
|
|
43
|
+
"""
|
|
44
|
+
logger = _InstanceLogger(name, level)
|
|
45
|
+
logger.parent = logging.getLogger(parent_name)
|
|
46
|
+
return logger
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class _ResolvedOutputDirMixin(BaseModel):
|
|
50
|
+
"""
|
|
51
|
+
This mixin just adds a validator to strip the parameter `output_dir_resolved` from input.
|
|
52
|
+
This is saved as a computed field by the model, but will error on loading from checkpoint
|
|
53
|
+
due to extra fields being disallows. It has to be a mixin here to get run before the
|
|
54
|
+
`CheckpointMixin` is fired.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
@model_validator(mode="before")
|
|
58
|
+
@classmethod
|
|
59
|
+
def drop_resolved_output_dir(cls, values):
|
|
60
|
+
"""Discard "output_dir_resolved" so a reloaded generator resolves its own."""
|
|
61
|
+
if isinstance(values, dict) and "output_dir_resolved" in values:
|
|
62
|
+
values = dict(values)
|
|
63
|
+
values.pop("output_dir_resolved")
|
|
64
|
+
return values
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class GAGeneratorBase(
|
|
68
|
+
CheckpointMixin, _ResolvedOutputDirMixin, DeduplicatedGeneratorBase
|
|
69
|
+
):
|
|
70
|
+
"""
|
|
71
|
+
Base class for genetic algorithm generators which write output and checkpoints.
|
|
72
|
+
|
|
73
|
+
Handles the output directory, log file, and periodic checkpointing on behalf of
|
|
74
|
+
subclasses. Subclasses call `end_generation` once each time a generation is
|
|
75
|
+
completed and everything else is taken care of.
|
|
76
|
+
|
|
77
|
+
Nothing is written to disk until the generator is used, so building or
|
|
78
|
+
deserializing one never touches the filesystem. Each generator owns its logger.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
output_dir : str or os.PathLike, optional
|
|
83
|
+
Directory to save algorithm state and population history, or None to write
|
|
84
|
+
nothing. Stored as a string and never modified; environment variables and "~"
|
|
85
|
+
are expanded when the path is used. If the directory already contains data, a
|
|
86
|
+
number is appended to avoid overwriting it.
|
|
87
|
+
checkpoint_freq : int, default=1
|
|
88
|
+
Frequency (in generations) at which checkpoints are saved. Set to -1 to
|
|
89
|
+
disable checkpointing.
|
|
90
|
+
log_level : int
|
|
91
|
+
Level of log messages written to "log.txt".
|
|
92
|
+
|
|
93
|
+
Attributes
|
|
94
|
+
----------
|
|
95
|
+
output_dir_resolved : str
|
|
96
|
+
Expanded, collision free path `output_dir` was resolved to. All file writes go
|
|
97
|
+
here. Empty until the directory has been created.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
output_dir: str | None = Field(
|
|
101
|
+
None,
|
|
102
|
+
description="Directory to save algorithm state and population history, or None "
|
|
103
|
+
"to write nothing. Environment variables and a leading '~' are expanded when "
|
|
104
|
+
"it is used and a number is appended if it already contains data",
|
|
105
|
+
)
|
|
106
|
+
checkpoint_freq: int = Field(
|
|
107
|
+
1,
|
|
108
|
+
description="How often (in generations) to save checkpoints (set to -1 to disable)",
|
|
109
|
+
)
|
|
110
|
+
log_level: int = Field(
|
|
111
|
+
logging.INFO, description="Log message level output to log.txt"
|
|
112
|
+
)
|
|
113
|
+
_output_dir_resolved: str = "" # Empty until the output directory has been created
|
|
114
|
+
|
|
115
|
+
@field_validator("output_dir", mode="before")
|
|
116
|
+
@classmethod
|
|
117
|
+
def validate_output_dir(cls, value):
|
|
118
|
+
"""Accept any os.PathLike, storing it as a string."""
|
|
119
|
+
if isinstance(value, os.PathLike):
|
|
120
|
+
return os.fspath(value)
|
|
121
|
+
return value
|
|
122
|
+
|
|
123
|
+
@computed_field
|
|
124
|
+
@property
|
|
125
|
+
def output_dir_resolved(self) -> str:
|
|
126
|
+
"""Directory output is written to, empty until it has been created."""
|
|
127
|
+
return self._output_dir_resolved
|
|
128
|
+
|
|
129
|
+
def model_post_init(self, context):
|
|
130
|
+
# Get a unique logger owned by this instance.
|
|
131
|
+
self._logger = _make_instance_logger(
|
|
132
|
+
f"{type(self).__module__}.{type(self).__name__}",
|
|
133
|
+
type(self).__module__,
|
|
134
|
+
self.log_level,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def _prepare_output(self) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Resolve and create the output directory and begin logging to file.
|
|
140
|
+
|
|
141
|
+
Repeated calls do nothing. The requested path is expanded and, if it already
|
|
142
|
+
holds data, a number is appended. The result is kept in `output_dir_resolved`.
|
|
143
|
+
"""
|
|
144
|
+
if (self.output_dir is None) or self._output_dir_resolved:
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
# Check if directory exists and do collision avoidance. Suffixes are applied to
|
|
148
|
+
# the expanded path so that they cannot land inside an environment variable or
|
|
149
|
+
# "~". The path is normalized first so that a trailing separator does not put
|
|
150
|
+
# the suffixed directory inside the one being protected.
|
|
151
|
+
requested = os.path.normpath(
|
|
152
|
+
os.path.expanduser(os.path.expandvars(self.output_dir))
|
|
153
|
+
)
|
|
154
|
+
resolved = requested
|
|
155
|
+
counter = 2
|
|
156
|
+
while os.path.exists(resolved) and os.listdir(resolved):
|
|
157
|
+
resolved = f"{requested}_{counter}"
|
|
158
|
+
counter += 1
|
|
159
|
+
if resolved != requested:
|
|
160
|
+
self._logger.info(
|
|
161
|
+
f'detected existing output_dir "{requested}" and corrected '
|
|
162
|
+
f'to "{resolved}" to avoid overwriting'
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# We are now setup
|
|
166
|
+
os.makedirs(resolved, exist_ok=True)
|
|
167
|
+
self._output_dir_resolved = resolved
|
|
168
|
+
|
|
169
|
+
# Set up file logging
|
|
170
|
+
log_file_path = os.path.join(resolved, "log.txt")
|
|
171
|
+
file_handler = logging.FileHandler(log_file_path, mode="w")
|
|
172
|
+
file_handler.setLevel(self.log_level)
|
|
173
|
+
file_handler.setFormatter(
|
|
174
|
+
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
|
175
|
+
)
|
|
176
|
+
self._logger.addHandler(file_handler)
|
|
177
|
+
self._logger.info(f"routing log output to file: {log_file_path}")
|
|
178
|
+
|
|
179
|
+
# Record the problem definition alongside the data
|
|
180
|
+
# Note: this is necessary to include in output for users running analysis on the results
|
|
181
|
+
# ie to plot Pareto front, you need to know the names and direction of the objectives
|
|
182
|
+
with open(os.path.join(resolved, "vocs.txt"), "w") as f:
|
|
183
|
+
f.write(self.vocs.model_dump_json())
|
|
184
|
+
|
|
185
|
+
def end_generation(self, generation_index: int, population: list[dict]) -> None:
|
|
186
|
+
"""
|
|
187
|
+
Record a completed generation, writing output and checkpoints as configured.
|
|
188
|
+
|
|
189
|
+
Parameters
|
|
190
|
+
----------
|
|
191
|
+
generation_index : int
|
|
192
|
+
Index of the generation which was just completed.
|
|
193
|
+
population : list of dict
|
|
194
|
+
The individuals making up the completed population.
|
|
195
|
+
"""
|
|
196
|
+
self._prepare_output()
|
|
197
|
+
if not self._output_dir_resolved:
|
|
198
|
+
return
|
|
199
|
+
output_dir = self._output_dir_resolved
|
|
200
|
+
save_start_t = time.perf_counter()
|
|
201
|
+
|
|
202
|
+
# Save all Xopt data
|
|
203
|
+
self.data.to_csv(os.path.join(output_dir, "data.csv"), index=False)
|
|
204
|
+
|
|
205
|
+
# Construct the DataFrame for this population
|
|
206
|
+
pop_df = pd.DataFrame(population)
|
|
207
|
+
pop_df["xopt_generation"] = generation_index
|
|
208
|
+
|
|
209
|
+
# Normalize the columns in the DataFrame
|
|
210
|
+
# Avoid schema changing part way through optimization so we can write CSV in append mode
|
|
211
|
+
pop_df = pop_df.reindex(
|
|
212
|
+
columns=self.vocs.all_names + POPULATION_METADATA_COLUMNS
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Write population DataFrame to file
|
|
216
|
+
csv_path = os.path.join(output_dir, "populations.csv")
|
|
217
|
+
pop_df.to_csv(
|
|
218
|
+
csv_path, index=False, mode="a", header=not os.path.isfile(csv_path)
|
|
219
|
+
)
|
|
220
|
+
self._logger.debug(
|
|
221
|
+
f'saved optimization data to "{output_dir}" '
|
|
222
|
+
f"in {1000 * (time.perf_counter() - save_start_t):.2f}ms"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# Save a checkpoint if one is due
|
|
226
|
+
if self.checkpoint_freq > 0 and (generation_index % self.checkpoint_freq == 0):
|
|
227
|
+
checkpoint_path = self._save_checkpoint(
|
|
228
|
+
os.path.join(output_dir, "checkpoints")
|
|
229
|
+
)
|
|
230
|
+
self._logger.debug(f'saved checkpoint file "{checkpoint_path}"')
|
|
231
|
+
|
|
232
|
+
def close_log_file(self):
|
|
233
|
+
"""
|
|
234
|
+
Closes out the log file (if used)
|
|
235
|
+
"""
|
|
236
|
+
for handler in list(self._logger.handlers):
|
|
237
|
+
if isinstance(handler, logging.FileHandler):
|
|
238
|
+
handler.close()
|
|
239
|
+
self._logger.removeHandler(handler)
|
|
@@ -2,7 +2,7 @@ import array
|
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
4
|
import random
|
|
5
|
-
from typing import Dict, List, Optional
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from deap import algorithms as deap_algorithms, base as deap_base, tools as deap_tools
|
|
@@ -88,6 +88,8 @@ class CNSGAGenerator(Generator):
|
|
|
88
88
|
)
|
|
89
89
|
_children: List[Dict] = PrivateAttr([])
|
|
90
90
|
_offspring: Optional[pd.DataFrame] = PrivateAttr(None)
|
|
91
|
+
_loaded_population: pd.DataFrame | None = PrivateAttr(None)
|
|
92
|
+
_toolbox: Any = PrivateAttr(None)
|
|
91
93
|
population: Optional[pd.DataFrame] = Field(None)
|
|
92
94
|
|
|
93
95
|
model_config = ConfigDict(extra="allow")
|