econiac.routing.attribution
econiac.routing.attribution
Thermal Shapley values: differentiable attribution with latent bottleneck detection.
φ_i(β) = Gibbs-weighted average marginal contribution of player i. Λ_i(β) = |∂φ_i/∂β| — latent bottleneck index. As β→∞: Laplace concentration on the bottleneck permutation. Pacioli constraint: Σ φ_i(β) = 0 for inter-sectoral SFC attribution.
Reference: Buckley (2026) Thermal Attribution, doi:10.5281/zenodo.20236870
ShapleyResult
dataclass
Container for thermal Shapley analysis outputs.
Source code in src/econiac/routing/attribution.py
bottleneck_player
property
Player with the largest absolute Shapley value.
total_value
property
Sum of Shapley values = v(grand coalition).
thermal_shapley(value_fn, n_players, beta=1.0)
Thermal Shapley values φ_i(β) for each player.
The standard Shapley value is the uniform average of marginal contributions across all n! permutations. The thermal generalisation weights permutations by Gibbs weights proportional to exp(β · v(σ)), where v(σ) is the total value generated by permutation σ.
At β=0: uniform weights → classical Shapley values. At β→∞: all weight on the max-value permutation (bottleneck).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value_fn
|
Callable[[frozenset], float]
|
characteristic function v: frozenset → float. v(∅) = 0 is assumed. |
required |
n_players
|
int
|
number of players (0, 1, …, n_players-1) |
required |
beta
|
float
|
inverse temperature |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
shape (n_players,) — thermal Shapley values, summing to v(grand coalition). |
Source code in src/econiac/routing/attribution.py
bottleneck_index(value_fn, n_players, beta_range)
Latent bottleneck index Λ_i(β) = |∂φ_i/∂β| for each player over beta_range.
A sharp peak in Λ_i near some β* indicates player i is the bottleneck that dominates value creation as the system cools (β increases).
Uses finite differences over the provided beta_range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value_fn
|
Callable[[frozenset], float]
|
characteristic function |
required |
n_players
|
int
|
number of players |
required |
beta_range
|
Array
|
shape (m,) — beta values at which to evaluate Λ |
required |
Returns:
| Type | Description |
|---|---|
Array
|
shape (m-1, n_players) — |∂φ_i/∂β| at interior beta points. |
Source code in src/econiac/routing/attribution.py
tropical_limit(value_fn, n_players)
Bottleneck player index in the tropical (β→∞) limit.
As β→∞, Gibbs weights concentrate on the permutation σ with maximum total value. The bottleneck player is the one with the largest marginal contribution in σ (Laplace method: the contribution that most determines whether σ* beats all other permutations).
Returns:
| Type | Description |
|---|---|
int
|
Index of the bottleneck player (0-indexed). |
Source code in src/econiac/routing/attribution.py
nonassociative_shapley(value_fn, n_players, beta=1.0)
Non-associative Shapley values: average thermal_shapley over all Catalan trees.
The C_{n-1} rooted binary trees on n players encode different coalition-formation orders. For each tree, only coalitions that appear as subtrees are admissible. The non-associative Shapley value is the average over all tree topologies.
At n=2: C_1=1 tree → coincides with classical Shapley. At n=3: C_2=2 trees → average of left- and right-associative brackets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value_fn
|
Callable[[frozenset], float]
|
characteristic function (called only on admissible coalitions) |
required |
n_players
|
int
|
number of players |
required |
beta
|
float
|
inverse temperature for Gibbs weighting within each tree |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
shape (n_players,) — non-associative Shapley values. |
Source code in src/econiac/routing/attribution.py
pacioli_attribution(value_fn, n_sectors, beta=1.0)
Pacioli-constrained thermal Shapley values.
In an SFC model the grand coalition has v(N) = 0 (double-entry: every asset is someone else's liability). Standard Shapley values then sum to 0 by efficiency: Σ φ_i = v(N) = 0.
This function computes thermal_shapley and enforces the constraint explicitly by subtracting the mean — a small correction for numerical drift at finite β.
The Pacioli constraint Σ φ_i = 0 corresponds to ∂²=0 (Godley's conservation law) in the SFC balance sheet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value_fn
|
Callable[[frozenset], float]
|
characteristic function with v(grand_coalition) ≈ 0 |
required |
n_sectors
|
int
|
number of sectors (players) |
required |
beta
|
float
|
inverse temperature |
1.0
|
Returns:
| Type | Description |
|---|---|
Array
|
shape (n_sectors,) — sector attributions with zero sum (Pacioli-normalised). |
Source code in src/econiac/routing/attribution.py
full_shapley_analysis(value_fn, n_players, beta=1.0, beta_range=None)
Run full thermal Shapley analysis.
Returns:
| Type | Description |
|---|---|
ShapleyResult
|
(ShapleyResult, bottleneck_index_array or None) |
Optional[Array]
|
bottleneck_index_array has shape (m-1, n_players) if beta_range given. |