scipy minimize generator - #424
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@copilot address the coverage, linting and notebook failures |
…fix notebook ruff format
Fixed in commits
|
|
@copilot add tests to achieve needed coverage |
Added 8 new tests in the latest commit covering all previously untested branches in
Also removed a dead-code |
There was a problem hiding this comment.
Pull request overview
This pull request adds a new sequential optimization generator, ScipyGenerator, that adapts scipy.optimize.minimize to Xopt’s external ask/tell workflow, and updates tests, docs, and generator registration to support it.
Changes:
- Introduce
ScipyGenerator(sequential wrapper aroundscipy.optimize.minimize) and register it under generator namescipy. - Add unit tests (including serialization/restart coverage) for the new generator and update existing sequential serialization tests.
- Add documentation + example notebook for
ScipyGenerator, and update MkDocs navigation and algorithms/index references; refactor LatinHypercubeGenerator imports/location.
Reviewed changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| xopt/generators/sequential/scipy.py | New ScipyGenerator implementation wrapping scipy.optimize.minimize in a sequential ask/tell pattern |
| xopt/generators/sequential/init.py | Export ScipyGenerator from the sequential generators package |
| xopt/generators/init.py | Register ScipyGenerator for dynamic loading; improve defaults handling for default_factory fields |
| xopt/generators/scipy/init.py | Removes old scipy generator re-exports (package content removed) |
| xopt/generators/latin_hypercube.py | Adds/relocates LatinHypercubeGenerator under a new import path |
| xopt/tests/generators/sequential/test_scipy.py | Adds test coverage for ScipyGenerator |
| xopt/tests/generators/sequential/test_serialization.py | Adds ScipyGenerator to sequential generator serialization/restart tests |
| xopt/tests/generators/test_latin_hypercube.py | Updates import path for LatinHypercubeGenerator |
| docs/api/generators/sequential/scipy.md | API documentation page for ScipyGenerator |
| docs/examples/sequential/scipy.ipynb | New example notebook demonstrating ScipyGenerator usage |
| docs/examples/other/latin_hypercube.ipynb | Updates import path for LatinHypercubeGenerator and relocates example |
| mkdocs.yml | Adds new docs + example notebook to navigation; updates Latin Hypercube example path |
| docs/index.md | Mentions the new scipy sequential generator in the feature list |
| docs/algorithms.md | Adds ScipyGenerator to algorithms list (but link maintenance needed) |
| .gitignore | Ignores local test output artifacts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
FYI I'll try catch up this week |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
electronsandstuff
left a comment
There was a problem hiding this comment.
OK, overall I think it's a cool concept. Obviously it's a bit of a hack to get it to work, but it's kind of cool. Because of that, I would strongly recommend adding the below mentioned test. I can't think of how to do it outside of this without threading. There are also obvious performance issues, but it might be good enough for now.
| "source": [ | ||
| "# ScipyGenerator with scipy.optimize.minimize\n", | ||
| "\n", | ||
| "This notebook demonstrates how to use Xopt's `ScipyGenerator` to drive any supported scipy `optimize.minimize` method in a sequential ask/tell workflow." |
There was a problem hiding this comment.
"ask/tell" isn't jargon we use anywhere else. This feels like an LLM'ism making up terms. I would recommend using the names used elsewhere for the generator. Check your PR for other uses of this phrase.
| "source": [ | ||
| "## Notes on performance\n", | ||
| "\n", | ||
| "`ScipyGenerator` bridges scipy's in-process `minimize` API into Xopt's external evaluation loop by replaying cached points each step. This adds overhead that is small for expensive evaluations but can be noticeable for very fast toy objectives." |
There was a problem hiding this comment.
Style thing: I don't know if I'd add low level details in the example
There was a problem hiding this comment.
Formatting, make titles title case. Probably don't need a header for imports.
| cached points. This is robust and method-agnostic, but adds repeated optimizer | ||
| bookkeeping work compared to a persistent in-memory scipy run. | ||
| - Point keys are rounded (12 decimals) before cache lookup to avoid fragile | ||
| floating-point equality checks. This improves replay stability across methods |
There was a problem hiding this comment.
I am a little worried about dealing with "numerically close" points like this. My understanding is that the scipy optimizers are deterministic, so the hack to get it to work in Xopt is you feed it back the same points and it will always revisit the same sequence seen before and you replay it the objective value. I am worried about trying to do things where we feed it points "nearby" without carefully thinking about how this affects the algorithm.
If the cache is really just replaying points, I would imagine it can be a list, not a dict right? Ie the list of points in the order they have been seen by the optimizer, then we just replay without hashing the variables in a dict. This should work under the same assumptions as in the current version of the code and also be significantly faster (no computation during replay.
There was a problem hiding this comment.
Given that we are doing something not supported by scipy, I think this PR needs the following test:
Given a test objective function, perform an optimization once with scipy.minimize and once with Xopt.ScipyGenerator. Collect all of the x points and confirm all of them are the same down to numerical precision. Parameterize the test by method and do for each of the methods we are supporting in scipy (presumably all that support bounds).
This will ensure that the replay method is doing what we think it should even if scipy changes.
There was a problem hiding this comment.
tests revealed issues with this, so thanks for the suggestion! I have moved the implementation to a threaded one such that it exactly reproduces the output from scipy minimize
|
Thanks for the comments @electronsandstuff, I will work on this over the next couple of weeks and ping you again when its ready |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
This implementation has a few issues, but overall idea is pretty elegant and worth to add. My big concern is this PR breaks some workflows in unexpected ways. That should be fixed. I'll just paste the LLM comments I agree with, critical ones in bold. Up to you how much to address.
|
This pull request introduces the new
ScipyGenerator, a generic wrapper forscipy.optimize.minimize, and integrates it into the Xopt sequential optimization framework. The documentation and example notebooks are updated to reflect this addition, and some generator imports and references are reorganized for clarity and consistency.Integration model
Xopt uses ask/tell semantics (one new point per
step), while scipyminimizeexpects direct access to objective evaluations. This class bridges the two by running one persistentminimizecall in a worker thread:scipy.optimize.minimizeonce with an objective function that first checks the cache.Performance implications
_build_cacheis O(N) in number of past evaluations and is executed when the persistent session starts.stepcalls.Key changes:
1. ScipyGenerator Integration
ScipyGeneratoras a new sequential generator, providing a generic interface toscipy.optimize.minimizemethods within Xopt's ask/tell workflow. This includes registration in generator discovery and import paths. [1] [2] [3]2. Documentation Enhancements
docs/api/generators/sequential/scipy.md) describingScipyGenerator, its integration model, configuration, and performance considerations.docs/algorithms.md) to listScipyGeneratorand clarify the location of theLatinHypercubeGeneratorexample.ScipyGeneratorto the main feature list in the project index.mkdocs.ymlto include the new Scipy Minimize example and API documentation, and moved the Latin Hypercube example to the "Other" section. [1] [2]3. Example Notebooks
docs/examples/sequential/scipy.ipynb) demonstrating the use ofScipyGeneratorwith the Rosenbrock function.4. Generator Import and Registration Cleanup
xopt/generators/scipy/__init__.pyand updated import paths to reflect the new organization.default_factoryinxopt/generators/__init__.py.These changes collectively add a powerful new optimization capability to Xopt and improve the clarity and usability of the documentation and generator registration.