nx_shapley.nx
buildroot/runtime/nx_shapley.nx
about
nx_shapley.nx -- game-theoretic feature attribution.
Shapley 1953 ("A Value for n-Person Games"): the UNIQUE fair
allocation of a coalition's value back to its members. The
substrate's third attribution primitive after nx_attribution
(top-K of W @ x) and nx_patch_attribution (Cohen's d per axis).
phi_i = sum over S subset N\{i} of
|S|! * (N-|S|-1)! / N! * [ f(S union {i}) - f(S) ]
Closes the WORLD-CLASS attribution gap named in
nxc2/docs/TOPDOWN_BOTTOMUP_GAP_ANALYSIS.md. No existing
image-gen / LLM stack ships Shapley in typed bits-up form;
they all defer to SHAP / KernelSHAP Python libs that hide
per-coalition evaluation under floating-point opacity.
Two modes:
EXACT -- N <= 10 features; full 2^N coalition enumeration.
SAMPLED -- N > 10; Castro/Gomez/Tejada 2009 permutation
sampling estimator. Unbiased.
Caller supplies f(active_mask, n_features, ctx) returning a
scalar value in Q10. Substrate computes the contribution
vector phi[] (Q10 each) such that sum(phi) + baseline = f(all_on).
genealogy_id: shapley_1953_castro_2009
lineage_id: substrate_attribution_v3
5W+H+GLP linkage: each phi[i] is the WHY answer for "feature i
contributed how much to output f(all_on)". Caller emits one
Nx5whRecord with what=ATTRIBUTION per non-trivial phi[i].
dependencies 4 imports · 0 importers
imports: nx_syscalls.nxnx_runtime.nxnx_tier.nxnx_random.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 69 | struct NxShapleyResult |
consts
| 43 | const NX_MAGIC_5040: i64 = 5040 |
| 44 | const NX_MAGIC_40320: i64 = 40320 |
| 45 | const NX_MAGIC_362880: i64 = 362880 |
| 46 | const NX_MAGIC_3628800: i64 = 3628800 |
| 47 | const NX_MAGIC_4096: i64 = 4096 |
| 51 | const NX_SHAPLEY_MODE_EXACT: nx_int = 0 |
| 52 | const NX_SHAPLEY_MODE_SAMPLED: nx_int = 1 |
| 55 | const NX_SHAPLEY_MAX_EXACT_N: nx_int = 10 |
| 58 | const NX_SHAPLEY_MAX_FEATURES: nx_int = 256 |
| 61 | const NX_SHAPLEY_DEFAULT_SAMPLES: nx_int = 2048 |
| 62 | const NX_SHAPLEY_MAX_SAMPLES: nx_int = 65536 |
| 65 | const NX_SHAPLEY_Q10: nx_int = 1024 |
| 78 | const NX_SHAPLEY_RESULT_BYTES: nx_size = 48 |
functions
| 86 | func _shapley_factorial(n: nx_int) -> nx_int called by 1: _shapley_weight_q10 |
| 106 | func _shapley_weight_q10(s: nx_int, n: nx_int) -> nx_int |
| 120 | func _shapley_popcount(mask: nx_int) -> nx_int called by 1: nx_shapley_compute_exact |
| 134 | func _shapley_bit_set(mask: nx_int, bit: nx_int) -> nx_int |
| 142 | func _shapley_bit_test(mask: nx_int, bit: nx_int) -> nx_int |
| 156 | func nx_shapley_compute_exact( called by 1: main calls 5: sys_mmap_shapley_popcount_shapley_bit_test_shapley_bit_set_shapley_weight_q10 |
| 232 | func _shapley_permute(perm: *nx_int, n: nx_int, rng: *NxRng) -> nx_int |
| 251 | func nx_shapley_compute_sampled( |
| 327 | func nx_shapley_efficiency_residual( called by 1: main |
| 349 | func nx_shapley_topk( |
| 397 | func _test_fn_additive(active_mask: nx_int, n_features: nx_int, ctx: *u8) -> nx_int calls 1: _shapley_bit_test |
| 407 | func _test_fn_and_gate(active_mask: nx_int, n_features: nx_int, ctx: *u8) -> nx_int calls 1: _shapley_bit_test |
| 418 | func main() -> nx_int |