From 513114f1cf28a4aecfe626e55f6a8fb303f990e2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Jun 2026 16:41:51 +0000 Subject: [PATCH 1/4] chore(release): 7.1.0-rc.1 [skip ci] ## [7.1.0-rc.1](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v7.0.0...v7.1.0-rc.1) (2026-06-10) ### Features * **deps:** require spotforecast2-safe >=21.2.0 ([1f52d04](https://github.com/sequential-parameter-optimization/spotforecast2/commit/1f52d04b1e0e09fe1977b3f49a875454a93a08c2)) * **multitask:** forward max_time_spotoptim to SpotOptim ([6bff756](https://github.com/sequential-parameter-optimization/spotforecast2/commit/6bff756ed3ebf063cd2f8b45904ce79668f2e64f)) --- CHANGELOG.md | 7 +++++++ pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1811bdf2..3f723be1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.1.0-rc.1](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v7.0.0...v7.1.0-rc.1) (2026-06-10) + +### Features + +* **deps:** require spotforecast2-safe >=21.2.0 ([1f52d04](https://github.com/sequential-parameter-optimization/spotforecast2/commit/1f52d04b1e0e09fe1977b3f49a875454a93a08c2)) +* **multitask:** forward max_time_spotoptim to SpotOptim ([6bff756](https://github.com/sequential-parameter-optimization/spotforecast2/commit/6bff756ed3ebf063cd2f8b45904ce79668f2e64f)) + ## [7.0.0](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v6.1.0...v7.0.0) (2026-06-09) ### ⚠ BREAKING CHANGES diff --git a/pyproject.toml b/pyproject.toml index b03ec566..70f1956b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "spotforecast2" -version = "7.0.0" +version = "7.1.0-rc.1" description = "Forecasting with spot" readme = "README.md" license = { text = "AGPL-3.0-or-later" } From 8565b8fec2273873e006496c4d0fefd690a1bea2 Mon Sep 17 00:00:00 2001 From: bartzbeielstein <32470350+bartzbeielstein@users.noreply.github.com> Date: Thu, 11 Jun 2026 01:07:34 +0200 Subject: [PATCH 2/4] feat(multitask)!: seed SpotOptim warm start from warm_start_lags list SpotOptimStrategy reads the seed lag set directly from config.warm_start_lags (sf2-safe >= 22.0.0, list-valued; default DEFAULT_WARM_START_LAGS) instead of combining the old boolean flag with lags_consider. None or an empty list disables the warm start; lags_consider keeps only its passive roles. BREAKING CHANGE: configs with warm_start_lags=True no longer warm-start the search with lags_consider; set warm_start_lags to the seed lag list itself (or None to disable). Co-Authored-By: Claude Fable 5 --- .../model_selection/spotoptim_search.py | 2 +- src/spotforecast2/multitask/strategies.py | 23 ++++++++++--------- tests/test_multitask_strategies.py | 2 +- tests/test_spotoptim_warm_start.py | 11 ++++----- uv.lock | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/spotforecast2/model_selection/spotoptim_search.py b/src/spotforecast2/model_selection/spotoptim_search.py index 9f462386..8f905295 100644 --- a/src/spotforecast2/model_selection/spotoptim_search.py +++ b/src/spotforecast2/model_selection/spotoptim_search.py @@ -877,7 +877,7 @@ def build_warm_start_x0( ``SpotOptimStrategy.prepare_forecaster``). forecaster: The pre-tuning forecaster; its ``estimator`` supplies the starting values for the numeric hyperparameter dimensions. - lags_seed: The lag configuration to seed (e.g. ``config.lags_consider``). + lags_seed: The lag configuration to seed (e.g. ``config.warm_start_lags``). Returns: A 1-D float array of length ``len(var_name)``, or ``None`` when the diff --git a/src/spotforecast2/multitask/strategies.py b/src/spotforecast2/multitask/strategies.py index 118f2606..f0352792 100644 --- a/src/spotforecast2/multitask/strategies.py +++ b/src/spotforecast2/multitask/strategies.py @@ -241,9 +241,10 @@ def prepare_forecaster( task: A `BaseTask` (or compatible) instance that supplies ``cv_ts``, ``config``, ``logger``, ``save_tuning_results``, and ``create_forecaster``. The config must expose - ``n_trials_spotoptim``, ``n_initial_spotoptim``, - ``random_state``, ``warm_start_lags``, and optionally - ``lags_consider`` and the TensorBoard knobs described + ``n_trials_spotoptim``, ``n_initial_spotoptim``, and + ``random_state``; optionally ``warm_start_lags`` (the seed + lag set, sf2-safe >= 22.0.0; ``None``/empty = cold start), + ``max_time_spotoptim``, and the TensorBoard knobs described above. target: Target column name; forwarded to ``task.create_forecaster`` and ``task.save_tuning_results``. @@ -288,7 +289,7 @@ def prepare_forecaster( n_trials_spotoptim=5, n_initial_spotoptim=3, random_state=0, - warm_start_lags=False, + warm_start_lags=None, ) task = types.SimpleNamespace( config=cfg, @@ -318,15 +319,15 @@ def prepare_forecaster( search_space = self.search_space or _default_spotoptim_search_space() cv = task.cv_ts(y_train) - # Warm start: inject ``lags_consider`` as a candidate lag set and seed - # the optimizer's first evaluation with it. Only dict search spaces - # with a ``"lags"`` list are eligible; anything else falls through to a - # normal cold-start run. + # Warm start: ``config.warm_start_lags`` (sf2-safe >= 22.0.0) is the + # seed lag set itself — it is injected as a search-space candidate and + # seeds the optimizer's first evaluation. ``None``/empty disables the + # warm start. Only dict search spaces with a ``"lags"`` list are + # eligible; anything else falls through to a normal cold-start run. kwargs_spotoptim: Dict[str, Any] = {} - lags_seed = getattr(task.config, "lags_consider", None) + lags_seed = getattr(task.config, "warm_start_lags", None) if ( - getattr(task.config, "warm_start_lags", False) - and lags_seed + lags_seed and isinstance(search_space, dict) and isinstance(search_space.get("lags"), list) ): diff --git a/tests/test_multitask_strategies.py b/tests/test_multitask_strategies.py index ce6354a3..1753d82a 100644 --- a/tests/test_multitask_strategies.py +++ b/tests/test_multitask_strategies.py @@ -75,7 +75,7 @@ def _make_fake_task(**config_extra): n_trials_spotoptim=2, n_initial_spotoptim=1, random_state=0, - warm_start_lags=False, + warm_start_lags=None, **config_extra, ) return types.SimpleNamespace( diff --git a/tests/test_spotoptim_warm_start.py b/tests/test_spotoptim_warm_start.py index b8f8b919..951309bf 100644 --- a/tests/test_spotoptim_warm_start.py +++ b/tests/test_spotoptim_warm_start.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2026 bartzbeielstein # SPDX-License-Identifier: AGPL-3.0-or-later -"""Tests for warm-starting the SpotOptim search with ``lags_consider``. +"""Tests for warm-starting the SpotOptim search with ``warm_start_lags``. Covers the ``build_warm_start_x0`` helper (full-dim seed point, clipping, graceful ``None`` cases) and an end-to-end check that the seeded lag @@ -112,8 +112,7 @@ def test_warm_start_x0_round_trips_to_seed(): class _MockConfig: - warm_start_lags = True - lags_consider = [1, 2, 24] + warm_start_lags = [1, 2, 24] random_state = 1 n_trials_spotoptim = 4 n_initial_spotoptim = 3 @@ -141,7 +140,7 @@ def create_forecaster(self, target): def test_strategy_injects_seed_and_forwards_x0(monkeypatch): - """The strategy injects lags_consider as a candidate and forwards x0.""" + """The strategy injects warm_start_lags as a candidate and forwards x0.""" from spotforecast2.multitask.strategies import SpotOptimStrategy captured = {} @@ -186,7 +185,7 @@ def fake_search(**kwargs): def test_strategy_no_x0_when_flag_disabled(monkeypatch): - """With warm_start_lags False, no x0 is passed and lags is untouched.""" + """With warm_start_lags None, no x0 is passed and lags is untouched.""" from spotforecast2.multitask.strategies import SpotOptimStrategy captured = {} @@ -207,7 +206,7 @@ def fake_search(**kwargs): ) task = _MockTask() - task.config.warm_start_lags = False + task.config.warm_start_lags = None y = pd.Series( np.sin(np.arange(400) * 2 * np.pi / 24), index=pd.date_range("2022-01-01", periods=400, freq="h"), diff --git a/uv.lock b/uv.lock index fd654820..f6c72523 100644 --- a/uv.lock +++ b/uv.lock @@ -3491,7 +3491,7 @@ wheels = [ [[package]] name = "spotforecast2" -version = "7.0.0" +version = "7.1.0" source = { editable = "." } dependencies = [ { name = "astral" }, From 48c02a3bb306d04b6f4ace5472588ecb1e099767 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Jun 2026 23:14:51 +0000 Subject: [PATCH 3/4] chore(release): 8.0.0-rc.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [8.0.0-rc.1](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v7.1.0...v8.0.0-rc.1) (2026-06-10) ### ⚠ BREAKING CHANGES * **multitask:** configs with warm_start_lags=True no longer warm-start the search with lags_consider; set warm_start_lags to the seed lag list itself (or None to disable). Co-Authored-By: Claude Fable 5 ### Features * **multitask:** seed SpotOptim warm start from warm_start_lags list ([8565b8f](https://github.com/sequential-parameter-optimization/spotforecast2/commit/8565b8fec2273873e006496c4d0fefd690a1bea2)) --- CHANGELOG.md | 14 ++++++++++++++ pyproject.toml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2ff8ea7..ff7b8d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [8.0.0-rc.1](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v7.1.0...v8.0.0-rc.1) (2026-06-10) + +### ⚠ BREAKING CHANGES + +* **multitask:** configs with warm_start_lags=True no longer warm-start +the search with lags_consider; set warm_start_lags to the seed lag list +itself (or None to disable). + +Co-Authored-By: Claude Fable 5 + +### Features + +* **multitask:** seed SpotOptim warm start from warm_start_lags list ([8565b8f](https://github.com/sequential-parameter-optimization/spotforecast2/commit/8565b8fec2273873e006496c4d0fefd690a1bea2)) + ## [7.1.0](https://github.com/sequential-parameter-optimization/spotforecast2/compare/v7.0.0...v7.1.0) (2026-06-10) ### Features diff --git a/pyproject.toml b/pyproject.toml index 9e9c6edb..317c248b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "spotforecast2" -version = "7.1.0" +version = "8.0.0-rc.1" description = "Forecasting with spot" readme = "README.md" license = { text = "AGPL-3.0-or-later" } From 13893ad9173ef6988fad50614c633676dbaea9d3 Mon Sep 17 00:00:00 2001 From: bartzbeielstein <32470350+bartzbeielstein@users.noreply.github.com> Date: Thu, 11 Jun 2026 01:56:35 +0200 Subject: [PATCH 4/4] feat(deps): require spotforecast2-safe >=22.0.0 22.0.0 carries the list-valued warm_start_lags seed field consumed by SpotOptimStrategy. Co-Authored-By: Claude Fable 5 --- pyproject.toml | 7 ++++--- uv.lock | 10 +++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 317c248b..8264d3c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,9 +31,10 @@ dependencies = [ "ruff>=0.15.6", "scikit-learn>=1.8.0", "shap>=0.49.1", - # 21.2.0 added the max_time_spotoptim config field that SpotOptimStrategy - # forwards as SpotOptim's max_time. - "spotforecast2-safe>=21.2.0,<22", + # 22.0.0 made warm_start_lags the seed lag list itself (default + # DEFAULT_WARM_START_LAGS, None disables) — consumed by SpotOptimStrategy. + # 21.2.0 added max_time_spotoptim, forwarded as SpotOptim's max_time. + "spotforecast2-safe>=22.0.0,<23", # spotoptim 1.0 is sequential-only and lean: torch/tensorboard moved to its # ``[torch]`` extra. sf2 forwards tensorboard_* kwargs into SpotOptim, so we # pin the extra to keep the TensorBoard tuning dashboards working (they were diff --git a/uv.lock b/uv.lock index f6c72523..ddac7dee 100644 --- a/uv.lock +++ b/uv.lock @@ -3491,7 +3491,7 @@ wheels = [ [[package]] name = "spotforecast2" -version = "7.1.0" +version = "8.0.0rc1" source = { editable = "." } dependencies = [ { name = "astral" }, @@ -3571,7 +3571,7 @@ requires-dist = [ { name = "safety", marker = "extra == 'dev'", specifier = ">=3.0.0" }, { name = "scikit-learn", specifier = ">=1.8.0" }, { name = "shap", specifier = ">=0.49.1" }, - { name = "spotforecast2-safe", specifier = ">=21.2.0,<22" }, + { name = "spotforecast2-safe", specifier = ">=22.0.0,<23" }, { name = "spotoptim", extras = ["torch"], specifier = ">=1.0.0,<2" }, { name = "tqdm", specifier = ">=4.67.2" }, { name = "ty", marker = "extra == 'dev'", specifier = ">=0.0.29" }, @@ -3590,7 +3590,7 @@ dev = [ [[package]] name = "spotforecast2-safe" -version = "21.2.0" +version = "22.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astral" }, @@ -3607,9 +3607,9 @@ dependencies = [ { name = "statsmodels" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a5/48/e12f37462beae893f901751648f8b830475cd58d19d8e8e9703236cd25c8/spotforecast2_safe-21.2.0.tar.gz", hash = "sha256:1b181bc157a0765b15a5348831902465d356b21cba3b6ad36b57d54f6a51b07c", size = 20630614, upload-time = "2026-06-10T16:28:37.526Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/89/00f24736a21666be93e6e59fdc0958e497178eb890ab5cefadd88e6d980f/spotforecast2_safe-22.0.0.tar.gz", hash = "sha256:f2c411e074b41a0421185c58a086b6e61b90d4d4fcab9860a93fa7faa09e18bf", size = 20630930, upload-time = "2026-06-10T23:51:54.156Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/73/0537ab7ce84308bfd49b04b365fde4a58ef2f8b3d40b415b8963777b71c7/spotforecast2_safe-21.2.0-py3-none-any.whl", hash = "sha256:1a80b4629062a0600b108416e93a07f75e1d31cf7bec0bcd02cb77089826e11c", size = 20696409, upload-time = "2026-06-10T16:28:34.959Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5a/d2bd77a6233ea08df61903391ab27bfe810dc4e107c2f452500e04c73f97/spotforecast2_safe-22.0.0-py3-none-any.whl", hash = "sha256:18906e1371cd93f03af4dbead15bb94db7945624aa24777cf12c06fe2d951e23", size = 20696710, upload-time = "2026-06-10T23:51:51.911Z" }, ] [[package]]