graph-shapley-attribution/module.yaml
flemming-it 43acf4ac1a feat: initial graph-shapley-attribution v0.1.0 (graph.shapley_attribution@0.1.0)
Shapley-style attribution on a weighted norm/citation graph.
Splits a target node's "blame" or "credit" among its ancestors —
useful for transposes-chains where a duty's load must split
between EU origin + national implementation + delegated VO.

v0.1.0 ships a path-count proportional fallback:

  share(ancestor) = paths(ancestor → target)
                    / sum(paths(any ancestor → target))

That matches the true Shapley value exactly when the coalition
value is "did this ancestor reach the target?", which is the
common case for citation chains. The honest Shapley implementation
(Shubik-Owen recursion over the 2^n coalition lattice) lands in
0.2, bounded to graphs with ≤32 ancestor nodes.

Reuse-lens: Shapley attribution on weighted graphs is broadly
useful — causal inference, feature attribution, supply-chain
analysis.

Pure in-WASM, zero filesystem, zero network.

Reserved for next versions:

  - 0.2: honest Shapley on ≤32-node neighbourhoods
  - 0.3: weighted edges (today's fallback treats all edges
         uniformly; weights matter once concretizes vs
         transposes carry different costs)

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-18 11:25:26 +02:00

51 lines
1.4 KiB
YAML

schema_version: 3
provider: chain
name: graph-shapley-attribution
version: 0.1.0
# Shapley-style attribution on a weighted norm/citation graph.
# Splits a target node's "blame" or "credit" among ancestors.
#
# v0.1.0 ships a simple proportional fallback (count-of-paths).
# v0.2 implements the full Shapley value for ≤32-node neighbour-
# hoods (combinatorial explosion above) — useful for transposes-
# chains where blame must split between EU origin + national
# implementation + delegated VO.
#
# Reuse-lens: Shapley attribution on weighted graphs is common
# in causal inference, feature attribution, supply-chain analysis.
provides:
- capability: graph.shapley_attribution
version: 0.1.0
inputs:
graph:
type: json
description:
en: |
{ nodes: [id], edges: [{from, to, weight?}] }.
weight defaults to 1.0 if absent.
de: |
{ nodes: [id], edges: [{from, to, weight?}] }.
weight ist 1.0 wenn nicht gesetzt.
target:
type: text
description:
en: |
Node id whose incoming weight is to be split among
ancestors.
de: |
Knoten-ID, deren eingehendes Gewicht auf die Vorfahren
verteilt wird.
outputs:
attribution:
type: json
description:
en: |
{ target, shares: [{node, share, paths_via_node}] }.
Shares sum to 1.0 across the listed nodes.
de: |
{ target, shares: [{node, share, paths_via_node}] }.
permissions: []