Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replacing AutoFolio with ASF-lib #141

Merged
merged 16 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ ignore = D300 # Conflicts with docstring-quotes rule
S404 # Just a warning about the usage of subprocess
S603 # Flags only false positives as of now
exclude =
sparkle/Components/AutoFolio/,
sparkle/Components/ablationAnalysis-0.9.4/,
sparkle/Components/runsolver/,
sparkle/Components/smac2-v2.10.03-master-778/
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/publish_pypi.yml
hadarshavit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Upload Python Package to PyPI when a Release is Created

on:
workflow_dispatch:

release:
types: [created]


jobs:
pypi-publish:
name: Publish release to PyPI
runs-on: ubuntu-latest
environment:
name: release
url: https://pypi.org/p/sparkleai
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel build
- name: Build package
run: |
python -m build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Notable changes to Sparkle will be documented in this file.

### Changed
- CI pipeline for unittest now tests for Python 3.10, 3.11 and 3.12
- Replaced AutoFolio with ASF-lib for algorithm selection [SPRK-336]
hadarshavit marked this conversation as resolved.
Show resolved Hide resolved

## [0.9.2] - 07/01/2025

Expand Down
2 changes: 1 addition & 1 deletion Documentation/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Asside from several package dependencies, Sparkle's package / CLI relies on a fe
Other dependencies are handled by the Conda environment, but if that is not an option for you please ensure you have the following:

- [libnuma](https://anaconda.org/esrf-bcu/libnuma) and [numactl](https://anaconda.org/brown-data-science/numactl) for [Runsolver](http://www.cril.univ-artois.fr/~roussel/runsolver/) compilation which sparkle uses to measure solvers meta data. This is restricted to Linux based systems.
- [Swig](https://anaconda.org/conda-forge/swig/) 4.0.2 for [SMAC3](https://github.com/automl/SMAC3), which is in turn used by [AutoFolio](https://github.com/automl/AutoFolio).
- [Swig](https://anaconda.org/conda-forge/swig/) 4.0.2 for [SMAC3](https://github.com/automl/SMAC3).
hadarshavit marked this conversation as resolved.
Show resolved Hide resolved

For detailed installation instructions see the documentation: https://ada-research.github.io/Sparkle/

Expand Down
17 changes: 12 additions & 5 deletions Documentation/source/platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,21 @@ The options below are exclusive to `srun` and are thus discouraged:

---

`selector`
> aliases: `selector`
`selector_class`
> aliases: `selector_class`
>
> values: Path.
> values: Class.
>
> Note: Currently only AutoFolio is supported by Sparkle. This setting is soon to be deprecated for a more flexible solution.
> Description: The ASF-lib Algorithm selector class to use.

---

`selector_model`
> aliases: `selector_model`
>
> values: Model.
>
> Description: The Algorithm selector to use.
> Description: The sklearn model to use for algorithm selection.

---

Expand Down
6 changes: 3 additions & 3 deletions Examples/selection.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ To make sure feature computation and solver performance computation are done bef
sparkle jobs
```

Now we can construct a portfolio selector, using the previously computed features and the objective value results of running the solvers. We can specify an objective to select on with the `--objective` flag, but if we do not, Sparkle will default to the first objective specified in the Settings file. The `--selector-timeout` argument determines for how many seconds we will train our selector for. We can set the flag `--solver-ablation` for actual marginal contribution computation later.
Now we can construct a portfolio selector, using the previously computed features and the objective value results of running the solvers. We can specify an objective to select on with the `--objective` flag, but if we do not, Sparkle will default to the first objective specified in the Settings file. We can set the flag `--solver-ablation` for actual marginal contribution computation later.

```bash
sparkle construct portfolio selector --selector-timeout 1000 --solver-ablation
sparkle construct portfolio selector --solver-ablation
sparkle jobs # Wait for the constructor to complete its computations
```

Expand Down Expand Up @@ -138,7 +138,7 @@ sparkle jobs
Now we can train a selector based on these features.

```bash
sparkle construct portfolio selector --selector-timeout 1000
sparkle construct portfolio selector
sparkle jobs # Wait for the computation to be done
```

Expand Down
6 changes: 3 additions & 3 deletions Examples/selection.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ sparkle run solvers --performance-data

sparkle jobs

# Now we can construct a portfolio selector, using the previously computed features and the objective value results of running the solvers. We can specify an objective to select on with the `--objective` flag, but if we do not, Sparkle will default to the first objective specified in the Settings file. The `--selector-timeout` argument determines for how many seconds we will train our selector for. We can set the flag `--solver-ablation` for actual marginal contribution computation later.
# Now we can construct a portfolio selector, using the previously computed features and the objective value results of running the solvers. We can specify an objective to select on with the `--objective` flag, but if we do not, Sparkle will default to the first objective specified in the Settings file. We can set the flag `--solver-ablation` for actual marginal contribution computation later.

sparkle construct portfolio selector --selector-timeout 1000 --solver-ablation
sparkle construct portfolio selector --solver-ablation
sparkle jobs # Wait for the constructor to complete its computations

### Generate a report
Expand Down Expand Up @@ -106,7 +106,7 @@ sparkle jobs

# Now we can train a selector based on these features.

sparkle construct portfolio selector --selector-timeout 1000
sparkle construct portfolio selector 1000
sparkle jobs # Wait for the computation to be done

# And generate the report. When running on the PTN/PTN2 data sets, you can compare the two to see the impact of different feature extractors.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Asside from several package dependencies, Sparkle's package / CLI relies on a fe
Other dependencies are handled by the Conda environment, but if that is not an option for you please ensure you have the following:

- [libnuma](https://anaconda.org/esrf-bcu/libnuma) and [numactl](https://anaconda.org/brown-data-science/numactl) for [Runsolver](http://www.cril.univ-artois.fr/~roussel/runsolver/) compilation which sparkle uses to measure solvers meta data. This is restricted to Linux based systems.
- [Swig](https://anaconda.org/conda-forge/swig/) 4.0.2 for [SMAC3](https://github.com/automl/SMAC3), which is in turn used by [AutoFolio](https://github.com/automl/AutoFolio).
- [Swig](https://anaconda.org/conda-forge/swig/) 4.0.2 for [SMAC3](https://github.com/automl/SMAC3).

For detailed installation instructions see the documentation: https://ada-research.github.io/Sparkle/

Expand Down
9 changes: 4 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@
"tabulate==0.9.0",
"pytermgui==7.7.2",
"tqdm==4.66.5",
"smac==2.2.0",
"RunRunner==0.1.9.1",
"asf-lib==0.0.1.15",
# ASF-lib requirements
"xgboost==2.1.3",
# Reporting packages
"plotly==5.24.1",
"kaleido==0.2.1",
# Autofolio packages
"xgboost==2.0.3",
"scikit-learn==1.3.2",
"liac-arff==2.5.0",
"smac==2.2.0",
],
include_package_data=True,
entry_points={"console_scripts": ["sparkle=sparkle.CLI._cli_:main"], },)
9 changes: 6 additions & 3 deletions sparkle/CLI/compute_marginal_contribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import tabulate

from sparkle.solver import Selector
from sparkle.CLI.help import global_variables as gv
from sparkle.CLI.help import logging as sl
from sparkle.platform.settings_objects import SettingState
Expand Down Expand Up @@ -60,14 +61,16 @@ def compute_selector_performance(
selector_performance_data.add_solver("portfolio_selector")
selector_performance_data.csv_filepath =\
actual_portfolio_selector.parent / "performance.csv"
selector = gv.settings().get_general_sparkle_selector()
selector = Selector(gv.settings().get_selection_class(),
gv.settings().get_selection_model())

schedule = {}
for instance in performance_data.instances:
# We get the performance for an instance by infering the model predicition
# for the instance.
feature_vector = feature_data.get_instance(instance)
schedule[instance] = selector.run(actual_portfolio_selector, feature_vector)
schedule[instance] = selector.run(actual_portfolio_selector,
instance,
feature_data)

schedule_performance = selector_performance_data.schedule_performance(
schedule, target_solver="portfolio_selector", objective=objective)
Expand Down
25 changes: 12 additions & 13 deletions sparkle/CLI/construct_portfolio_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@
import argparse
from pathlib import Path

# from asf import selectors
thijssnelleman marked this conversation as resolved.
Show resolved Hide resolved

# from sklearn.base import ClassifierMixin, RegressorMixin
# from asf.predictors import SklearnWrapper, AbstractPredictor
# from asf.selectors.abstract_model_based_selector import AbstractModelBasedSelector

import runrunner as rrr
from runrunner.base import Runner

from sparkle.solver import Selector
from sparkle.platform.settings_objects import SettingState
from sparkle.structures import PerformanceDataFrame, FeatureDataFrame
from sparkle.types import resolve_objective
Expand All @@ -24,8 +31,6 @@ def parser_function() -> argparse.ArgumentParser:
"solver performances.")
parser.add_argument(*ac.RecomputePortfolioSelectorArgument.names,
**ac.RecomputePortfolioSelectorArgument.kwargs)
parser.add_argument(*ac.SelectorTimeoutArgument.names,
**ac.SelectorTimeoutArgument.kwargs)
parser.add_argument(*ac.ObjectiveArgument.names,
**ac.ObjectiveArgument.kwargs)
parser.add_argument(*ac.SelectorAblationArgument.names,
Expand Down Expand Up @@ -66,7 +71,6 @@ def main(argv: list[str]) -> None:

# Process command line arguments
args = parser.parse_args(argv)
selector_timeout = args.selector_timeout
flag_recompute_portfolio = args.recompute_portfolio_selector
solver_ablation = args.solver_ablation

Expand All @@ -86,14 +90,14 @@ def main(argv: list[str]) -> None:
run_on = gv.settings().get_run_on()

print("Start constructing Sparkle portfolio selector ...")
selector = gv.settings().get_general_sparkle_selector()
selector = Selector(gv.settings().get_selection_class(),
gv.settings().get_selection_model())

judge_exist_remaining_jobs(
gv.settings().DEFAULT_feature_data_path,
gv.settings().DEFAULT_performance_data_path)

# Selector (AutoFolio) cannot handle cutoff time less than 2, adjust if needed
cutoff_time = max(gv.settings().get_general_target_cutoff_time(), 2)
cutoff_time = gv.settings().get_general_target_cutoff_time()

performance_data = PerformanceDataFrame(gv.settings().DEFAULT_performance_data_path)
feature_data = FeatureDataFrame(gv.settings().DEFAULT_feature_data_path)
Expand All @@ -107,10 +111,8 @@ def main(argv: list[str]) -> None:

# Selector is named after the solvers it can predict, sort for permutation invariance
solvers = sorted([s.name for s in gv.settings().DEFAULT_solver_dir.iterdir()])
selection_scenario_path = (
gv.settings().DEFAULT_selection_output
/ gv.settings().DEFAULT_general_sparkle_selector.name
/ "_".join(solvers))
selection_scenario_path =\
gv.settings().DEFAULT_selection_output / selector.name / "_".join(solvers)

# Update latest scenario
gv.latest_scenario().set_selection_scenario_path(selection_scenario_path)
Expand All @@ -125,13 +127,11 @@ def main(argv: list[str]) -> None:
sys.exit()

selector_path.parent.mkdir(exist_ok=True, parents=True)

selector_run = selector.construct(selector_path,
performance_data,
feature_data,
objective,
cutoff_time,
selector_timeout,
run_on=run_on,
sbatch_options=sbatch_options,
base_dir=sl.caller_log_dir)
Expand All @@ -158,7 +158,6 @@ def main(argv: list[str]) -> None:
feature_data,
objective,
cutoff_time,
selector_timeout,
run_on=run_on,
sbatch_options=sbatch_options,
base_dir=sl.caller_log_dir)
Expand Down
8 changes: 5 additions & 3 deletions sparkle/CLI/core/run_portfolio_selector_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from sparkle.CLI.help import global_variables as gv
from sparkle.structures import PerformanceDataFrame, FeatureDataFrame
from sparkle.solver import Solver
from sparkle.solver import Solver, Selector
from sparkle.types import SolverStatus


Expand Down Expand Up @@ -95,9 +95,11 @@ def call_solver_solve_instance(

# Run portfolio selector
print("Sparkle portfolio selector predicting ...")
selector = gv.settings().get_general_sparkle_selector()
selector = Selector(gv.settings().get_selection_class(),
gv.settings().get_selection_model())
predict_schedule = selector.run(args.selector,
feature_data.get_instance(str(args.instance)))
args.instance,
feature_data)

if predict_schedule is None: # Selector Failed to produce prediction
sys.exit(-1)
Expand Down
7 changes: 0 additions & 7 deletions sparkle/CLI/help/argparse_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,6 @@ def __init__(self: ArgumentContainer, names: list[str], kwargs: dict[str, Any])\
"help": "configuration budget per configurator run in "
"seconds (wallclock)"})

SelectorTimeoutArgument = \
ArgumentContainer(names=["--selector-timeout"],
kwargs={"type": int,
"default": Settings.DEFAULT_portfolio_construction_timeout,
"help": "Cuttoff time (in seconds) for the algorithm"
"selector construction"})

SolutionVerifierArgument = \
ArgumentContainer(names=["--solution-verifier"],
kwargs={"type": str,
Expand Down
62 changes: 0 additions & 62 deletions sparkle/Components/AutoFolio/.gitignore

This file was deleted.

7 changes: 0 additions & 7 deletions sparkle/Components/AutoFolio/CITATION.cff

This file was deleted.

Loading
Loading