• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mmschlk / shapiq / 18466795972

13 Oct 2025 01:07PM UTC coverage: 93.362% (-0.5%) from 93.845%
18466795972

Pull #430

github

web-flow
Merge e2f2f6de9 into dede390c9
Pull Request #430: Enhance type safety and fix bugs across the codebase

290 of 334 new or added lines in 49 files covered. (86.83%)

12 existing lines in 9 files now uncovered.

4993 of 5348 relevant lines covered (93.36%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.0
/src/shapiq/explainer/configuration.py
1
"""Configuration for the ``shapiq`` explainers."""
2

3
from __future__ import annotations
1✔
4

5
from typing import Literal
1✔
6

7
from shapiq import (
1✔
8
    SHAPIQ,
9
    SPEX,
10
    SVARM,
11
    SVARMIQ,
12
    KernelSHAP,
13
    KernelSHAPIQ,
14
    PermutationSamplingSII,
15
    PermutationSamplingSTII,
16
    PermutationSamplingSV,
17
    RegressionFBII,
18
    RegressionFSII,
19
    UnbiasedKernelSHAP,
20
    kADDSHAP,
21
)
22
from shapiq.approximator.base import Approximator, ValidApproximationIndices
1✔
23
from shapiq.approximator.regression.base import Regression
1✔
24
from shapiq.game_theory.indices import index_generalizes_bv, index_generalizes_sv
1✔
25

26
ValidApproximatorTypes = Literal["spex", "montecarlo", "svarm", "permutation", "regression"]
1✔
27
APPROXIMATOR_CONFIGURATIONS: dict[
1✔
28
    ValidApproximatorTypes, dict[ValidApproximationIndices, type[Approximator]]
29
] = {
30
    "regression": {
31
        "SII": KernelSHAPIQ,
32
        "FSII": RegressionFSII,
33
        "FBII": RegressionFBII,
34
        "k-SII": KernelSHAPIQ,
35
        "SV": KernelSHAP,
36
        "BV": RegressionFBII,
37
        "kADD-SHAP": kADDSHAP,
38
    },
39
    "permutation": {
40
        "SII": PermutationSamplingSII,
41
        "STII": PermutationSamplingSTII,
42
        "k-SII": PermutationSamplingSII,
43
        "SV": PermutationSamplingSV,
44
    },
45
    "montecarlo": {
46
        "SII": SHAPIQ,
47
        "STII": SHAPIQ,
48
        "FSII": SHAPIQ,
49
        "FBII": SHAPIQ,
50
        "k-SII": SHAPIQ,
51
        "SV": UnbiasedKernelSHAP,
52
        "BV": SHAPIQ,
53
        "BII": SHAPIQ,
54
        "CHII": SHAPIQ,
55
    },
56
    "svarm": {
57
        "SII": SVARMIQ,
58
        "STII": SVARMIQ,
59
        "FSII": SVARMIQ,
60
        "FBII": SVARMIQ,
61
        "k-SII": SVARMIQ,
62
        "SV": SVARM,
63
        "BV": SVARM,
64
        "BII": SVARMIQ,
65
        "CHII": SVARMIQ,
66
    },
67
    "spex": {
68
        "SII": SPEX,
69
        "STII": SPEX,
70
        "FSII": SPEX,
71
        "FBII": SPEX,
72
        "k-SII": SPEX,
73
        "SV": SPEX,
74
        "BV": SPEX,
75
    },
76
}
77

78

79
def choose_spex(max_order: int, n_players: int) -> bool:
1✔
80
    """Decide whether to use SPEX based on the number of players and max order.
81

82
    Args:
83
        max_order: The maximum order of interactions to be computed.
84
        n_players: The number of players in the game.
85

86
    Returns:
87
        True if SPEX should be used, False otherwise.
88
    """
89
    if max_order == 2 and n_players > 64:
1✔
90
        return True
1✔
91
    if max_order == 3 and n_players > 32:
1✔
92
        return True
1✔
93
    if max_order == 4 and n_players > 16:
1✔
94
        return True
1✔
95
    return bool(max_order > 4 and n_players > 16)
1✔
96

97

98
def setup_approximator_automatically(
1✔
99
    index: ValidApproximationIndices,
100
    max_order: int,
101
    n_players: int,
102
    random_state: int | None = None,
103
) -> Approximator:
104
    """Select the approximator automatically based on the index and max_order.
105

106
    Args:
107
        index: The index to be used for the approximator.
108
        max_order: The maximum order of interactions to be computed.
109
        n_players: The number of players in the game.
110
        random_state: The random state to initialize the approximator with.
111

112
    Returns:
113
        The selected approximator.
114
    """
115
    if choose_spex(max_order=max_order, n_players=n_players) and index in SPEX.valid_indices:
1✔
NEW
116
        return SPEX(
×
117
            n=n_players,
118
            max_order=max_order,
119
            index=index,
120
            random_state=random_state,
121
        )
122
    if index == "SV" or (max_order == 1 and (index == "SV" or index_generalizes_sv(index))):
1✔
123
        return KernelSHAP(n=n_players, random_state=random_state)
1✔
124
    if index == "BV" or (max_order == 1 and (index == "BV" or index_generalizes_bv(index))):
1✔
125
        return RegressionFBII(n=n_players, max_order=1, random_state=random_state)
1✔
126
    if index == "FSII":
1✔
127
        return RegressionFSII(n=n_players, max_order=max_order, random_state=random_state)
1✔
128
    if index == "FBII":
1✔
129
        return RegressionFBII(n=n_players, max_order=max_order, random_state=random_state)
1✔
130
    if index in KernelSHAPIQ.valid_indices:
1✔
131
        return KernelSHAPIQ(
1✔
132
            n=n_players,
133
            max_order=max_order,
134
            index=index,
135
            random_state=random_state,
136
        )
137
    if index in SVARMIQ.valid_indices:
1✔
138
        return SVARMIQ(
1✔
139
            n=n_players,
140
            max_order=max_order,
141
            top_order=False,
142
            random_state=random_state,
143
            index=index,
144
        )
NEW
145
    msg = f"Could not set up approximator automatically for index {index}."
×
NEW
146
    raise ValueError(msg)
×
147

148

149
def setup_approximator(
1✔
150
    approximator: ValidApproximatorTypes | Approximator | Literal["auto"],
151
    index: ValidApproximationIndices,
152
    max_order: int,
153
    n_players: int,
154
    random_state: int | None = None,
155
) -> Approximator:
156
    """Set up the approximator for the explainer based on the selected index and order.
157

158
    Args:
159
        approximator: The approximator to be used. If ``"auto"``, the approximator is selected based
160
            on the index and max_order.
161
        index: The index to be used for the approximator.
162
        max_order: The maximum order of interactions to be computed.
163
        n_players: The number of players in the game.
164
        random_state: The random state to initialize the approximator with.
165

166
    Returns:
167
        The initialized approximator.
168
    """
169
    # we simply return the approximator if it is already an instance of Approximator
170
    if isinstance(approximator, Approximator):
1✔
171
        return approximator
1✔
172

173
    # if the approximator is "auto", we set it up automatically
174
    if approximator == "auto":
1✔
175
        return setup_approximator_automatically(
1✔
176
            index=index,
177
            max_order=max_order,
178
            n_players=n_players,
179
            random_state=random_state,
180
        )
181

182
    # if the approx is a string and not "auto", we get it from the configurations and set it up
183
    if isinstance(approximator, str):
1✔
184
        if approximator in APPROXIMATOR_CONFIGURATIONS:
1✔
185
            approximator_cls: type[Approximator] = APPROXIMATOR_CONFIGURATIONS[approximator][index]
1✔
186
        else:
187
            msg = (
1✔
188
                f"Invalid approximator `{approximator}`. "
189
                f"Valid configurations are described in {APPROXIMATOR_CONFIGURATIONS}."
190
            )
191
            raise ValueError(msg)
1✔
192
    elif not issubclass(type(approximator), Approximator):
1✔
193
        msg = (
1✔
194
            f"Invalid approximator class `{approximator}`. "
195
            f"Expected a subclass of `Approximator`, but got {type(approximator)}."
196
        )
197
        raise TypeError(msg)
1✔
198
    else:
NEW
199
        approximator_cls: type[Approximator] = approximator
×
200

201
    # initialize the approximator class with params
202
    if issubclass(approximator_cls, Regression):
1✔
203
        return approximator_cls(
1✔
204
            n=n_players,
205
            max_order=max_order,
206
            random_state=random_state,
207
            index=index,
208
        )
209
    return approximator_cls(
1✔
210
        n=n_players,
211
        max_order=max_order,
212
        top_order=False,
213
        random_state=random_state,
214
        index=index,
215
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc