diff --git a/pyproject.toml b/pyproject.toml index 78d3d34..74956ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,11 +17,12 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ - "shapiq>=1.2.3", + "shapiq==1.4.1", "numpy>=2.2.6", "scikit-learn>=1.7.1", "matplotlib>=3.10.5", - "networkx>=3.4.2" + "networkx>=3.4.2", + "ConfigSpace>=1.2.1", ] [project.urls] @@ -50,8 +51,6 @@ docs = [ ] dev = [ - "shapiq>=1.2.0", - "ConfigSpace>=1.2.1", "numpy>=1.26.4", "tox-uv>=1.11.3", "deptry>=0.23.0", diff --git a/src/hypershap/hypershap.py b/src/hypershap/hypershap.py index 41fbff1..a3f74e0 100644 --- a/src/hypershap/hypershap.py +++ b/src/hypershap/hypershap.py @@ -12,6 +12,7 @@ if TYPE_CHECKING: from ConfigSpace import Configuration + from shapiq import ValidApproximationIndices from hypershap.utils import ConfigSpaceSearcher @@ -20,7 +21,8 @@ import matplotlib.pyplot as plt import networkx as nx import numpy as np -from shapiq import SHAPIQ, ExactComputer, InteractionValues, KernelSHAPIQ +from shapiq import ExactComputer, InteractionValues +from shapiq.explainer.configuration import setup_approximator_automatically from hypershap.games import ( AblationGame, @@ -66,13 +68,13 @@ class HyperSHAP: __init__(explanation_task: ExplanationTask): Initializes the HyperSHAP instance with an explanation task. - ablation(config_of_interest: Configuration, baseline_config: Configuration, index: str = "FSII", order: int = 2) -> InteractionValues: + ablation(config_of_interest: Configuration, baseline_config: Configuration, index: ValidApproximationIndices = "FSII", order: int = 2) -> InteractionValues: Computes and returns the interaction values for ablation analysis. - tunability(baseline_config: Configuration | None, index: str = "FSII", order: int = 2) -> InteractionValues: + tunability(baseline_config: Configuration | None, index: ValidApproximationIndices = "FSII", order: int = 2) -> InteractionValues: Computes and returns the interaction values for tunability analysis. - optimizer_bias(optimizer_of_interest: ConfigSpaceSearcher, optimizer_ensemble: list[ConfigSpaceSearcher], index: str = "FSII", order: int = 2) -> InteractionValues: + optimizer_bias(optimizer_of_interest: ConfigSpaceSearcher, optimizer_ensemble: list[ConfigSpaceSearcher], index: ValidApproximationIndices = "FSII", order: int = 2) -> InteractionValues: Computes and returns the interaction values for optimizer bias analysis. plot_si_graph(interaction_values: InteractionValues | None = None, save_path: str | None = None): @@ -116,7 +118,13 @@ def __init__( ) self.verbose = verbose - def __get_interaction_values(self, game: AbstractHPIGame, index: str = "FSII", order: int = 2) -> InteractionValues: + def __get_interaction_values( + self, + game: AbstractHPIGame, + index: ValidApproximationIndices = "FSII", + order: int = 2, + seed: int | None = 0, + ) -> InteractionValues: if game.n_players <= EXACT_MAX_HYPERPARAMETERS: # instantiate exact computer if number of hyperparameters is small enough ec = ExactComputer(n_players=game.get_num_hyperparameters(), game=game) # pyright: ignore @@ -124,11 +132,8 @@ def __get_interaction_values(self, game: AbstractHPIGame, index: str = "FSII", o # compute interaction values with the given index and order interaction_values = ec(index=index, order=order) else: - # instantiate kernel - if index == "FSII": - approx = SHAPIQ(n=game.n_players, max_order=2, index=index) - else: - approx = KernelSHAPIQ(n=game.n_players, max_order=2, index=index) + # instantiate approximator + approx = setup_approximator_automatically(index, order, game.n_players, seed) # approximate interaction values with the given index and order interaction_values = approx(budget=self.approximation_budget, game=game) @@ -142,7 +147,7 @@ def ablation( self, config_of_interest: Configuration, baseline_config: Configuration, - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, ) -> InteractionValues: """Compute and return the interaction values for ablation analysis. @@ -150,7 +155,7 @@ def ablation( Args: config_of_interest (Configuration): The configuration of interest. baseline_config (Configuration): The baseline configuration. - index (str, optional): The index to use for computing interaction values. Defaults to "FSII". + index (ValidApproximationIndices, optional): The index to use for computing interaction values. Defaults to "FSII". order (int, optional): The order of the interaction values. Defaults to 2. Returns: @@ -191,7 +196,7 @@ def ablation_multibaseline( config_of_interest: Configuration, baseline_configs: list[Configuration], aggregation: Aggregation = Aggregation.AVG, - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, ) -> InteractionValues: """Compute and return the interaction values for multi-baseline ablation analysis. @@ -200,7 +205,7 @@ def ablation_multibaseline( config_of_interest (Configuration): The configuration of interest. baseline_configs (list[Configuration]): The list of baseline configurations. aggregation (Aggregation): The aggregation method to use for computing interaction values. - index (str, optional): The index to use for computing interaction values. Defaults to "FSII". + index (ValidApproximationIndices, optional): The index to use for computing interaction values. Defaults to "FSII". order (int, optional): The order of the interaction values. Defaults to 2. Returns: @@ -240,7 +245,7 @@ def ablation_multibaseline( def tunability( self, baseline_config: Configuration | None = None, - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, n_samples: int = 10_000, seed: int | None = 0, @@ -298,7 +303,7 @@ def tunability( def sensitivity( self, baseline_config: Configuration | None = None, - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, n_samples: int = 10_000, seed: int | None = 0, @@ -356,7 +361,7 @@ def sensitivity( def mistunability( self, baseline_config: Configuration | None = None, - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, n_samples: int = 10_000, seed: int | None = 0, @@ -365,7 +370,7 @@ def mistunability( Args: baseline_config (Configuration | None, optional): The baseline configuration. Defaults to None. - index (str, optional): The index to use for computing interaction values. Defaults to "FSII". + index (ValidApproximationIndices, optional): The index to use for computing interaction values. Defaults to "FSII". order (int, optional): The order of the interaction values. Defaults to 2. n_samples (int, optional): The number of samples to use for simulating HPO. Defaults to 10_000. seed (int, optiona): The random seed for simulating HPO. Defaults to 0. @@ -414,7 +419,7 @@ def optimizer_bias( self, optimizer_of_interest: ConfigSpaceSearcher, optimizer_ensemble: list[ConfigSpaceSearcher], - index: str = "FSII", + index: ValidApproximationIndices = "FSII", order: int = 2, ) -> InteractionValues: """Compute and return the interaction values for optimizer bias analysis. @@ -422,7 +427,7 @@ def optimizer_bias( Args: optimizer_of_interest (ConfigSpaceSearcher): The optimizer of interest. optimizer_ensemble (list[ConfigSpaceSearcher]): The ensemble of optimizers. - index (str, optional): The index to use for computing interaction values. Defaults to "FSII". + index (ValidApproximationIndices, optional): The index to use for computing interaction values. Defaults to "FSII". order (int, optional): The order of the interaction values. Defaults to 2. Returns: diff --git a/src/hypershap/utils.py b/src/hypershap/utils.py index 149092e..294ad6b 100644 --- a/src/hypershap/utils.py +++ b/src/hypershap/utils.py @@ -5,6 +5,7 @@ from __future__ import annotations +import logging from abc import ABC, abstractmethod from copy import deepcopy from enum import Enum @@ -12,8 +13,15 @@ if TYPE_CHECKING: from hypershap.task import BaselineExplanationTask - import numpy as np +from ConfigSpace.exceptions import ( + ActiveHyperparameterNotSetError, + ForbiddenValueError, + IllegalVectorizedValueError, + InactiveHyperparameterSetError, +) + +logger = logging.getLogger(__name__) class Aggregation(Enum): @@ -106,6 +114,20 @@ def __init__( # cache coalition values to ensure monotonicity for min/max self.coalition_cache = {} + def _is_valid(self, config: np.ndarray) -> bool: + """Check whether a configuration is valid with respect to conditions of the configuration space.""" + try: + self.explanation_task.config_space.check_configuration_vector_representation(config) + except ( + ActiveHyperparameterNotSetError, + IllegalVectorizedValueError, + InactiveHyperparameterSetError, + ForbiddenValueError, + ): + return False + else: + return True + def search(self, coalition: np.ndarray) -> float: """Search the configuration space based on the coalition. @@ -125,6 +147,22 @@ def search(self, coalition: np.ndarray) -> float: column_index = np.where(blind_coalition) temp_random_sample[:, column_index] = self.explanation_task.baseline_config.get_array()[column_index] - # predict performance values with the help of the surrogate model - vals: np.ndarray = np.array(self.explanation_task.get_single_surrogate_model().evaluate(temp_random_sample)) + # in case of conditions in the config space, it might happen that through blinding hyperparameter values + # configurations might become invalid and those should not be considered for calculating vals + if len(self.explanation_task.config_space.conditions) > 0: + # filter invalid configurations + validity = np.apply_along_axis(self._is_valid, axis=1, arr=temp_random_sample) + filtered_samples = temp_random_sample[validity] + + if len(filtered_samples) < 0.05 * len(temp_random_sample): # pragma: no cover + logger.warning( + "WARNING: Due to blinding less than 5% of the samples in the random search remain valid. " + "Consider increasing the sampling budget of the random search.", + ) + + # predict performance values with the help of the surrogate model for the filtered configurations + vals: np.ndarray = np.array(self.explanation_task.get_single_surrogate_model().evaluate(filtered_samples)) + else: + vals: np.ndarray = np.array(self.explanation_task.get_single_surrogate_model().evaluate(temp_random_sample)) + return evaluate_aggregation(self.mode, vals) diff --git a/tests/fixtures/simple_setup.py b/tests/fixtures/simple_setup.py index 9bdd5b2..087f245 100644 --- a/tests/fixtures/simple_setup.py +++ b/tests/fixtures/simple_setup.py @@ -3,7 +3,7 @@ from __future__ import annotations import pytest -from ConfigSpace import Configuration, ConfigurationSpace, UniformFloatHyperparameter +from ConfigSpace import Configuration, ConfigurationSpace, LessThanCondition, UniformFloatHyperparameter from hypershap import ExplanationTask @@ -41,7 +41,7 @@ def evaluate(self, x: Configuration) -> float: Returns: The value of the configuration. """ - return self.value(x["a"], x["b"]) + return self.value(x["a"], x.get("b", 0)) def value(self, a: float, b: float) -> float: """Evaluate the value of a configuration. @@ -71,3 +71,27 @@ def simple_base_et( ) -> ExplanationTask: """Return a base explanation task for the simple setup.""" return ExplanationTask.from_function(simple_config_space, simple_blackbox_function.evaluate) + + +@pytest.fixture(scope="session") +def simple_cond_config_space() -> ConfigurationSpace: + """Return a simple config space with conditions for testing.""" + config_space = ConfigurationSpace() + config_space.seed(42) + + a = UniformFloatHyperparameter("a", 0, 1, 0) + b = UniformFloatHyperparameter("b", 0, 1, 0) + config_space.add(a) + config_space.add(b) + + config_space.add(LessThanCondition(b, a, 0.3)) + return config_space + + +@pytest.fixture(scope="session") +def simple_cond_base_et( + simple_cond_config_space: ConfigurationSpace, + simple_blackbox_function: SimpleBlackboxFunction, +) -> ExplanationTask: + """Return a base explanation task for the simple setup with conditions.""" + return ExplanationTask.from_function(simple_cond_config_space, simple_blackbox_function.evaluate) diff --git a/tests/test_extended_settings.py b/tests/test_extended_settings.py index 0acb07d..b01d1e0 100644 --- a/tests/test_extended_settings.py +++ b/tests/test_extended_settings.py @@ -72,3 +72,10 @@ def test_multi_data_sensitivity(multi_data_baseline_config: Configuration, hyper """Test the multi-data sesntivity task.""" iv = hypershap_inst.sensitivity(baseline_config=multi_data_baseline_config) assert iv is not None, "Interaction values should not be none." + + +def test_tunability_with_conditions(simple_cond_base_et: ExplanationTask) -> None: + """Test the tunability task with a configuration space that has conditions.""" + hypershap = HyperSHAP(simple_cond_base_et) + iv = hypershap.tunability(simple_cond_base_et.config_space.get_default_configuration()) + assert iv is not None, "Interaction values should not be none." diff --git a/uv.lock b/uv.lock index 00149ab..33e63f0 100644 --- a/uv.lock +++ b/uv.lock @@ -1175,6 +1175,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, ] +[[package]] +name = "galois" +version = "0.4.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numba" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/6c/e6343b658836a192d62bd1449f71444b6f0c8b0c1d75b37df50c45ffd4e3/galois-0.4.7.tar.gz", hash = "sha256:db71f979ebc99697fdd8c8fcb13529a37e6c0b4117595dc82e0377e2525fc2c3", size = 7338504, upload-time = "2025-11-07T23:56:48.877Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/6f/56d8b00c25ab5eaf1485e342d78b385025ceffe010b7a377e15329695bf1/galois-0.4.7-py3-none-any.whl", hash = "sha256:b6dc649f950e61ea2af07314c250c18be456605ac6b8823b701bae7cf7dff69a", size = 4171175, upload-time = "2025-11-07T23:56:46.977Z" }, +] + [[package]] name = "ghp-import" version = "2.1.0" @@ -1304,6 +1319,7 @@ name = "hypershap" version = "0.0.4" source = { editable = "." } dependencies = [ + { name = "configspace" }, { name = "matplotlib" }, { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "networkx", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, @@ -1318,7 +1334,6 @@ carps = [ { name = "carps" }, ] dev = [ - { name = "configspace" }, { name = "deptry" }, { name = "mkdocs" }, { name = "mkdocs-material" }, @@ -1332,7 +1347,6 @@ dev = [ { name = "pytest-cov" }, { name = "pytest-xdist" }, { name = "ruff" }, - { name = "shapiq" }, { name = "tox-uv" }, ] docs = [ @@ -1354,17 +1368,17 @@ test = [ [package.metadata] requires-dist = [ + { name = "configspace", specifier = ">=1.2.1" }, { name = "matplotlib", specifier = ">=3.10.5" }, { name = "networkx", specifier = ">=3.4.2" }, { name = "numpy", specifier = ">=2.2.6" }, { name = "scikit-learn", specifier = ">=1.7.1" }, - { name = "shapiq", specifier = ">=1.2.3" }, + { name = "shapiq", specifier = "==1.4.1" }, ] [package.metadata.requires-dev] carps = [{ name = "carps", specifier = ">=1.0.4" }] dev = [ - { name = "configspace", specifier = ">=1.2.1" }, { name = "deptry", specifier = ">=0.23.0" }, { name = "mkdocs", specifier = ">=1.4.2" }, { name = "mkdocs-material", specifier = ">=8.5.10" }, @@ -1377,7 +1391,6 @@ dev = [ { name = "pytest-cov", specifier = ">=6.0.0" }, { name = "pytest-xdist", specifier = ">=3.6.1" }, { name = "ruff", specifier = ">=0.11.5" }, - { name = "shapiq", specifier = ">=1.2.0" }, { name = "tox-uv", specifier = ">=1.11.3" }, ] docs = [ @@ -1953,6 +1966,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/00/d90b10b962b4277f5e64a78b6609968859ff86889f5b898c1a778c06ec00/lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c", size = 111036, upload-time = "2024-08-13T19:48:58.603Z" }, ] +[[package]] +name = "llvmlite" +version = "0.45.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/8d/5baf1cef7f9c084fb35a8afbde88074f0d6a727bc63ef764fe0e7543ba40/llvmlite-0.45.1.tar.gz", hash = "sha256:09430bb9d0bb58fc45a45a57c7eae912850bedc095cd0810a57de109c69e1c32", size = 185600, upload-time = "2025-10-01T17:59:52.046Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/6d/585c84ddd9d2a539a3c3487792b3cf3f988e28ec4fa281bf8b0e055e1166/llvmlite-0.45.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:1b1af0c910af0978aa55fa4f60bbb3e9f39b41e97c2a6d94d199897be62ba07a", size = 43043523, upload-time = "2025-10-01T18:02:58.621Z" }, + { url = "https://files.pythonhosted.org/packages/ae/34/992bd12d3ff245e0801bcf6013961daa8c19c9b9c2e61cb4b8bce94566f9/llvmlite-0.45.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02a164db2d79088bbd6e0d9633b4fe4021d6379d7e4ac7cc85ed5f44b06a30c5", size = 37253122, upload-time = "2025-10-01T18:03:55.159Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7b/6d7585998a5991fa74dc925aae57913ba8c7c2efff909de9d34cc1cd3c27/llvmlite-0.45.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f2d47f34e4029e6df3395de34cc1c66440a8d72712993a6e6168db228686711b", size = 56288210, upload-time = "2025-10-01T18:00:41.978Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e2/a4abea058633bfc82eb08fd69ce242c118fdb9b0abad1fdcbe0bc6aedab5/llvmlite-0.45.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7319e5f9f90720578a7f56fbc805bdfb4bc071b507c7611f170d631c3c0f1e0", size = 55140958, upload-time = "2025-10-01T18:01:55.694Z" }, + { url = "https://files.pythonhosted.org/packages/74/c0/233468e96ed287b953239c3b24b1d69df47c6ba9262bfdca98eda7e83a04/llvmlite-0.45.1-cp310-cp310-win_amd64.whl", hash = "sha256:4edb62e685867799e336723cb9787ec6598d51d0b1ed9af0f38e692aa757e898", size = 38132232, upload-time = "2025-10-01T18:04:41.538Z" }, + { url = "https://files.pythonhosted.org/packages/04/ad/9bdc87b2eb34642c1cfe6bcb4f5db64c21f91f26b010f263e7467e7536a3/llvmlite-0.45.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:60f92868d5d3af30b4239b50e1717cb4e4e54f6ac1c361a27903b318d0f07f42", size = 43043526, upload-time = "2025-10-01T18:03:15.051Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ea/c25c6382f452a943b4082da5e8c1665ce29a62884e2ec80608533e8e82d5/llvmlite-0.45.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98baab513e19beb210f1ef39066288784839a44cd504e24fff5d17f1b3cf0860", size = 37253118, upload-time = "2025-10-01T18:04:06.783Z" }, + { url = "https://files.pythonhosted.org/packages/fe/af/85fc237de98b181dbbe8647324331238d6c52a3554327ccdc83ced28efba/llvmlite-0.45.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3adc2355694d6a6fbcc024d59bb756677e7de506037c878022d7b877e7613a36", size = 56288209, upload-time = "2025-10-01T18:01:00.168Z" }, + { url = "https://files.pythonhosted.org/packages/0a/df/3daf95302ff49beff4230065e3178cd40e71294968e8d55baf4a9e560814/llvmlite-0.45.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f3377a6db40f563058c9515dedcc8a3e562d8693a106a28f2ddccf2c8fcf6ca", size = 55140958, upload-time = "2025-10-01T18:02:11.199Z" }, + { url = "https://files.pythonhosted.org/packages/a4/56/4c0d503fe03bac820ecdeb14590cf9a248e120f483bcd5c009f2534f23f0/llvmlite-0.45.1-cp311-cp311-win_amd64.whl", hash = "sha256:f9c272682d91e0d57f2a76c6d9ebdfccc603a01828cdbe3d15273bdca0c3363a", size = 38132232, upload-time = "2025-10-01T18:04:52.181Z" }, + { url = "https://files.pythonhosted.org/packages/e2/7c/82cbd5c656e8991bcc110c69d05913be2229302a92acb96109e166ae31fb/llvmlite-0.45.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:28e763aba92fe9c72296911e040231d486447c01d4f90027c8e893d89d49b20e", size = 43043524, upload-time = "2025-10-01T18:03:30.666Z" }, + { url = "https://files.pythonhosted.org/packages/9d/bc/5314005bb2c7ee9f33102c6456c18cc81745d7055155d1218f1624463774/llvmlite-0.45.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1a53f4b74ee9fd30cb3d27d904dadece67a7575198bd80e687ee76474620735f", size = 37253123, upload-time = "2025-10-01T18:04:18.177Z" }, + { url = "https://files.pythonhosted.org/packages/96/76/0f7154952f037cb320b83e1c952ec4a19d5d689cf7d27cb8a26887d7bbc1/llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5b3796b1b1e1c14dcae34285d2f4ea488402fbd2c400ccf7137603ca3800864f", size = 56288211, upload-time = "2025-10-01T18:01:24.079Z" }, + { url = "https://files.pythonhosted.org/packages/00/b1/0b581942be2683ceb6862d558979e87387e14ad65a1e4db0e7dd671fa315/llvmlite-0.45.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:779e2f2ceefef0f4368548685f0b4adde34e5f4b457e90391f570a10b348d433", size = 55140958, upload-time = "2025-10-01T18:02:30.482Z" }, + { url = "https://files.pythonhosted.org/packages/33/94/9ba4ebcf4d541a325fd8098ddc073b663af75cc8b065b6059848f7d4dce7/llvmlite-0.45.1-cp312-cp312-win_amd64.whl", hash = "sha256:9e6c9949baf25d9aa9cd7cf0f6d011b9ca660dd17f5ba2b23bdbdb77cc86b116", size = 38132231, upload-time = "2025-10-01T18:05:03.664Z" }, + { url = "https://files.pythonhosted.org/packages/1d/e2/c185bb7e88514d5025f93c6c4092f6120c6cea8fe938974ec9860fb03bbb/llvmlite-0.45.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:d9ea9e6f17569a4253515cc01dade70aba536476e3d750b2e18d81d7e670eb15", size = 43043524, upload-time = "2025-10-01T18:03:43.249Z" }, + { url = "https://files.pythonhosted.org/packages/09/b8/b5437b9ecb2064e89ccf67dccae0d02cd38911705112dd0dcbfa9cd9a9de/llvmlite-0.45.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:c9f3cadee1630ce4ac18ea38adebf2a4f57a89bd2740ce83746876797f6e0bfb", size = 37253121, upload-time = "2025-10-01T18:04:30.557Z" }, + { url = "https://files.pythonhosted.org/packages/f7/97/ad1a907c0173a90dd4df7228f24a3ec61058bc1a9ff8a0caec20a0cc622e/llvmlite-0.45.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:57c48bf2e1083eedbc9406fb83c4e6483017879714916fe8be8a72a9672c995a", size = 56288210, upload-time = "2025-10-01T18:01:40.26Z" }, + { url = "https://files.pythonhosted.org/packages/32/d8/c99c8ac7a326e9735401ead3116f7685a7ec652691aeb2615aa732b1fc4a/llvmlite-0.45.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3aa3dfceda4219ae39cf18806c60eeb518c1680ff834b8b311bd784160b9ce40", size = 55140957, upload-time = "2025-10-01T18:02:46.244Z" }, + { url = "https://files.pythonhosted.org/packages/09/56/ed35668130e32dbfad2eb37356793b0a95f23494ab5be7d9bf5cb75850ee/llvmlite-0.45.1-cp313-cp313-win_amd64.whl", hash = "sha256:080e6f8d0778a8239cd47686d402cb66eb165e421efa9391366a9b7e5810a38b", size = 38132232, upload-time = "2025-10-01T18:05:14.477Z" }, +] + [[package]] name = "markdown" version = "3.8.2" @@ -2461,6 +2502,39 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, ] +[[package]] +name = "numba" +version = "0.62.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "llvmlite" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/20/33dbdbfe60e5fd8e3dbfde299d106279a33d9f8308346022316781368591/numba-0.62.1.tar.gz", hash = "sha256:7b774242aa890e34c21200a1fc62e5b5757d5286267e71103257f4e2af0d5161", size = 2749817, upload-time = "2025-09-29T10:46:31.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/27/a5a9a58f267ec3b72f609789b2a8eefd6156bd7117e41cc9b7cf5de30490/numba-0.62.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a323df9d36a0da1ca9c592a6baaddd0176d9f417ef49a65bb81951dce69d941a", size = 2684281, upload-time = "2025-09-29T10:43:31.863Z" }, + { url = "https://files.pythonhosted.org/packages/3a/9d/ffc091c0bfd7b80f66df3887a7061b6af80c8c2649902444026ee1454391/numba-0.62.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1e1f4781d3f9f7c23f16eb04e76ca10b5a3516e959634bd226fc48d5d8e7a0a", size = 2687311, upload-time = "2025-09-29T10:43:54.441Z" }, + { url = "https://files.pythonhosted.org/packages/a1/13/9a27bcd0baeea236116070c7df458414336f25e9dd5a872b066cf36b74bf/numba-0.62.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:14432af305ea68627a084cd702124fd5d0c1f5b8a413b05f4e14757202d1cf6c", size = 3734548, upload-time = "2025-09-29T10:42:38.232Z" }, + { url = "https://files.pythonhosted.org/packages/a7/00/17a1ac4a60253c784ce59549375e047da98330b82de7df6ac7f4ecc90902/numba-0.62.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f180922adf159ae36c2fe79fb94ffaa74cf5cb3688cb72dba0a904b91e978507", size = 3441277, upload-time = "2025-09-29T10:43:06.124Z" }, + { url = "https://files.pythonhosted.org/packages/86/94/20ae0ff78612c4697eaf942a639db01dd4e2d90f634ac41fa3e015c961fc/numba-0.62.1-cp310-cp310-win_amd64.whl", hash = "sha256:f41834909d411b4b8d1c68f745144136f21416547009c1e860cc2098754b4ca7", size = 2745647, upload-time = "2025-09-29T10:44:15.282Z" }, + { url = "https://files.pythonhosted.org/packages/dd/5f/8b3491dd849474f55e33c16ef55678ace1455c490555337899c35826836c/numba-0.62.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:f43e24b057714e480fe44bc6031de499e7cf8150c63eb461192caa6cc8530bc8", size = 2684279, upload-time = "2025-09-29T10:43:37.213Z" }, + { url = "https://files.pythonhosted.org/packages/bf/18/71969149bfeb65a629e652b752b80167fe8a6a6f6e084f1f2060801f7f31/numba-0.62.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57cbddc53b9ee02830b828a8428757f5c218831ccc96490a314ef569d8342b7b", size = 2687330, upload-time = "2025-09-29T10:43:59.601Z" }, + { url = "https://files.pythonhosted.org/packages/0e/7d/403be3fecae33088027bc8a95dc80a2fda1e3beff3e0e5fc4374ada3afbe/numba-0.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:604059730c637c7885386521bb1b0ddcbc91fd56131a6dcc54163d6f1804c872", size = 3739727, upload-time = "2025-09-29T10:42:45.922Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/3d910d08b659a6d4c62ab3cd8cd93c4d8b7709f55afa0d79a87413027ff6/numba-0.62.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6c540880170bee817011757dc9049dba5a29db0c09b4d2349295991fe3ee55f", size = 3445490, upload-time = "2025-09-29T10:43:12.692Z" }, + { url = "https://files.pythonhosted.org/packages/5b/82/9d425c2f20d9f0a37f7cb955945a553a00fa06a2b025856c3550227c5543/numba-0.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:03de6d691d6b6e2b76660ba0f38f37b81ece8b2cc524a62f2a0cfae2bfb6f9da", size = 2745550, upload-time = "2025-09-29T10:44:20.571Z" }, + { url = "https://files.pythonhosted.org/packages/5e/fa/30fa6873e9f821c0ae755915a3ca444e6ff8d6a7b6860b669a3d33377ac7/numba-0.62.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:1b743b32f8fa5fff22e19c2e906db2f0a340782caf024477b97801b918cf0494", size = 2685346, upload-time = "2025-09-29T10:43:43.677Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d5/504ce8dc46e0dba2790c77e6b878ee65b60fe3e7d6d0006483ef6fde5a97/numba-0.62.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:90fa21b0142bcf08ad8e32a97d25d0b84b1e921bc9423f8dda07d3652860eef6", size = 2688139, upload-time = "2025-09-29T10:44:04.894Z" }, + { url = "https://files.pythonhosted.org/packages/50/5f/6a802741176c93f2ebe97ad90751894c7b0c922b52ba99a4395e79492205/numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6ef84d0ac19f1bf80431347b6f4ce3c39b7ec13f48f233a48c01e2ec06ecbc59", size = 3796453, upload-time = "2025-09-29T10:42:52.771Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/efd21527d25150c4544eccc9d0b7260a5dec4b7e98b5a581990e05a133c0/numba-0.62.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9315cc5e441300e0ca07c828a627d92a6802bcbf27c5487f31ae73783c58da53", size = 3496451, upload-time = "2025-09-29T10:43:19.279Z" }, + { url = "https://files.pythonhosted.org/packages/80/44/79bfdab12a02796bf4f1841630355c82b5a69933b1d50eb15c7fa37dabe8/numba-0.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:44e3aa6228039992f058f5ebfcfd372c83798e9464297bdad8cc79febcf7891e", size = 2745552, upload-time = "2025-09-29T10:44:26.399Z" }, + { url = "https://files.pythonhosted.org/packages/22/76/501ea2c07c089ef1386868f33dff2978f43f51b854e34397b20fc55e0a58/numba-0.62.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:b72489ba8411cc9fdcaa2458d8f7677751e94f0109eeb53e5becfdc818c64afb", size = 2685766, upload-time = "2025-09-29T10:43:49.161Z" }, + { url = "https://files.pythonhosted.org/packages/80/68/444986ed95350c0611d5c7b46828411c222ce41a0c76707c36425d27ce29/numba-0.62.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:44a1412095534a26fb5da2717bc755b57da5f3053965128fe3dc286652cc6a92", size = 2688741, upload-time = "2025-09-29T10:44:10.07Z" }, + { url = "https://files.pythonhosted.org/packages/78/7e/bf2e3634993d57f95305c7cee4c9c6cb3c9c78404ee7b49569a0dfecfe33/numba-0.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c9460b9e936c5bd2f0570e20a0a5909ee6e8b694fd958b210e3bde3a6dba2d7", size = 3804576, upload-time = "2025-09-29T10:42:59.53Z" }, + { url = "https://files.pythonhosted.org/packages/e8/b6/8a1723fff71f63bbb1354bdc60a1513a068acc0f5322f58da6f022d20247/numba-0.62.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:728f91a874192df22d74e3fd42c12900b7ce7190b1aad3574c6c61b08313e4c5", size = 3503367, upload-time = "2025-09-29T10:43:26.326Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ec/9d414e7a80d6d1dc4af0e07c6bfe293ce0b04ea4d0ed6c45dad9bd6e72eb/numba-0.62.1-cp313-cp313-win_amd64.whl", hash = "sha256:bbf3f88b461514287df66bc8d0307e949b09f2b6f67da92265094e8fa1282dd8", size = 2745529, upload-time = "2025-09-29T10:44:31.738Z" }, +] + [[package]] name = "numpy" version = "2.2.6" @@ -4062,25 +4136,29 @@ wheels = [ [[package]] name = "shapiq" -version = "1.2.3" +version = "1.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colour" }, + { name = "galois" }, + { name = "joblib" }, { name = "matplotlib" }, { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "networkx", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas" }, + { name = "pillow" }, { name = "requests" }, { name = "scikit-learn" }, { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sparse-transform" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/09/b8c2cbdb3362f658b33986973a96b2c34f5cd6cda8d1079178735e1b4d6d/shapiq-1.2.3.tar.gz", hash = "sha256:e121afc7835acea7a7647c4ebd14bb5fa29cec3801aacafead74dbb2fd0c33d3", size = 193168, upload-time = "2025-03-24T18:22:16.362Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a8/20/8e7bf8e1d2ad5e50c5ddb884760fe67657eee38b0ebe9d9996a0ab227221/shapiq-1.4.1.tar.gz", hash = "sha256:7f612c84fcfe4746ff826db72efa2944f9aa693c5c00c6e17a882613471534f8", size = 5781786, upload-time = "2025-11-10T19:43:31.882Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/71/5b6e7456ef76459d27acb590350a5fcdb90bf136626487525224735e2dbc/shapiq-1.2.3-py3-none-any.whl", hash = "sha256:b2b0ca9fcaadf44f5be655c46a17870e68b823f641caaba8a4dbf81dadbb51e4", size = 244214, upload-time = "2025-03-24T18:22:14.611Z" }, + { url = "https://files.pythonhosted.org/packages/af/cc/13fefd7203ffe71d5107221be939dd64945378b93f7c0a7cb82d7f281071/shapiq-1.4.1-py3-none-any.whl", hash = "sha256:c86667eb28ea0de56005fbe9fd072783242b74aa87fede11e07b6b915b93e7b3", size = 5871550, upload-time = "2025-11-10T19:43:29.858Z" }, ] [[package]] @@ -4119,6 +4197,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, ] +[[package]] +name = "sparse-transform" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "galois" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "scikit-learn" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "scipy", version = "1.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/da/82132137fdc207c4a14abb52fedcd8cc3dd697175f548cfb8689bd2afab8/sparse_transform-0.2.1.tar.gz", hash = "sha256:470d54c884600d97254469a3d85fac775480d18a8aa2c43574350695e1015c66", size = 24803, upload-time = "2025-04-03T08:11:39.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/ec/c85f95289e4638faf889ca02b588ad3af0f3ef8f92b99bee3ce936ef3860/sparse_transform-0.2.1-py3-none-any.whl", hash = "sha256:d01b19f8add68e2b4c98a17272830af0e03d163667f03b1dc2b0c9eb8471727b", size = 27034, upload-time = "2025-04-03T08:11:38.551Z" }, +] + [[package]] name = "sshtunnel" version = "0.4.0"