tucoopy.solutions.shapley¶
Shapley value and semivalues.¶
This module implements the Shapley value, weighted Shapley variants, Monte Carlo approximation, and a generic semivalue helper.
semivalue ¶
semivalue(game, *, weights_by_k, normalize=False)
Compute a semivalue for a TU cooperative game.
A semivalue is defined by weights \(p_k\) for coalition sizes \(k=0,\ldots,n-1\):
The standard semivalue normalization is:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | GameProtocol | TU game. | required |
weights_by_k | Sequence[float] | Sequence of length | required |
normalize | bool | If True, rescale \(p_k\) to satisfy the semivalue normalization. | False |
Returns:
| Type | Description |
|---|---|
list[float] | Allocation vector of length |
Raises:
| Type | Description |
|---|---|
InvalidParameterError | If |
Notes
- The Shapley value is a special case of a semivalue with \(p_k = \frac{k!(n-k-1)!}{n!}\).
- Complexity is \(O(n 2^n)\) due to coalition enumeration.
Examples:
>>> # Example: choose p_k proportional to 1/(n * C(n-1,k)) and normalize
>>> phi = semivalue(g, weights_by_k=[1.0]*g.n_players, normalize=True)
>>> len(phi) == g.n_players
True
shapley_value ¶
shapley_value(game)
Compute the Shapley value for a TU cooperative game.
The Shapley value assigns to each player their expected marginal contribution under a uniformly random permutation of players.
Formally:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | Game | TU cooperative game. | required |
Returns:
| Type | Description |
|---|---|
list[float] | Shapley value allocation (length |
Notes
- Complexity is \(O(n 2^n)\).
- Exact and deterministic; suitable for small to medium
n.
Examples:
>>> g = Game.from_value_function(n_players=3, value_fn=lambda S: float(len(S)))
>>> shapley_value(g)
[1.0, 1.0, 1.0]
shapley_value_fast ¶
shapley_value_fast(game, *, backend='auto')
Fast exact Shapley value via Harsanyi dividends (Möbius transform).
Using Harsanyi dividends d(S) (unanimity coordinates), the Shapley value admits the closed form:
This implementation computes dividends via a fast Möbius transform and then aggregates contributions across coalitions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | Game | TU game. | required |
backend | ('auto', 'numpy', 'python') | Backend for the Möbius transform: - "auto": try NumPy, fall back to Python - "numpy": force NumPy (raises ImportError if unavailable) - "python": pure-Python | "auto" |
Returns:
| Type | Description |
|---|---|
list[float] | The Shapley value allocation (length |
Notes
- Complexity is \(O(n 2^n)\), like the classic formula, but with substantially better constants when the Möbius transform uses NumPy.
- This is an exact method (not Monte Carlo).
- Conceptually, it decomposes the game into unanimity games and distributes each dividend equally among players in the coalition.
Examples:
>>> phi = shapley_value_fast(g, backend="auto")
>>> len(phi) == g.n_players
True
shapley_value_sample ¶
shapley_value_sample(game, *, n_samples, seed=None)
Monte Carlo estimate of the Shapley value using random permutations.
For each sampled permutation, the marginal contribution vector is computed. The estimator returns the sample mean and an estimated per-player standard error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | Game | TU cooperative game. | required |
n_samples | int | Number of random permutations to sample. | required |
seed | int | None | Random seed for reproducibility. | None |
Returns:
| Type | Description |
|---|---|
(phi_hat, stderr) | Estimated Shapley value and per-player standard error. |
Notes
- Complexity is \(O(n \cdot n_{samples})\).
- Suitable for large
nwhen exact computation is infeasible.
Examples:
>>> phi_hat, stderr = shapley_value_sample(g, n_samples=1000)
shapley_value_sample_stratified ¶
shapley_value_sample_stratified(
game, *, samples_per_k, seed=None
)
Stratified Monte Carlo estimate of the Shapley value by coalition size.
This estimator samples random coalitions \(S\) of each size \(k = 0 \ldots n-1\) from \(N \setminus \{i\}\) and averages the marginal contributions:
weighted by the Shapley coefficient:
Compared to permutation sampling, this can reduce variance in games where marginal contributions depend strongly on coalition size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | Game | TU game. | required |
samples_per_k | int | Number of sampled coalitions per coalition size k, for each player. Must be >= 1. | required |
seed | int | None | RNG seed. | None |
Returns:
| Type | Description |
|---|---|
(phi_hat, stderr) |
|
Notes
- Total samples scale as O(n^2 * samples_per_k) because we sample for each player and each k.
- This is still much cheaper than O(n 2^n) when n is moderate/large.
- stderr here is an empirical standard error from the stratified samples.
Examples:
>>> phi_hat, se = shapley_value_sample_stratified(g, samples_per_k=200, seed=0)
>>> len(phi_hat) == g.n_players
True
weighted_shapley_value ¶
weighted_shapley_value(game, *, weights)
Compute the weighted Shapley value (Shapley value with weighted symmetry).
Using Harsanyi dividends \(d(S)\), the weighted Shapley value is:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game | GameProtocol | TU game. | required |
weights | Sequence[float] | Positive player weights (length | required |
Returns:
| Type | Description |
|---|---|
list[float] | Allocation vector of length |
Raises:
| Type | Description |
|---|---|
InvalidParameterError | If the weights are non-positive or have the wrong length. |
Notes
- This uses Harsanyi dividends internally, so the overall cost is dominated by computing the Möbius transform (typically \(O(n2^n)\)).
- Setting all weights equal reduces to the standard Shapley value.
Examples:
>>> phi_w = weighted_shapley_value(g, weights=[2.0, 1.0, 1.0])
>>> len(phi_w) == g.n_players
True