Skip to content

SPDX-License-Identifier: AGPL-3.0-or-later

Commercial license available

© Concepts 1996–2026 Miroslav Šotek. All rights reserved.

© Code 2020–2026 Miroslav Šotek. All rights reserved.

ORCID: 0009-0009-3560-0851

Contact: www.anulum.li | protoscience@anulum.li

SCPN Phase Orchestrator — Autotune per-knob attribution API reference

Autotune Per-Knob Attribution

A reward report scores a candidate as a whole and breaks the score into reward components. It does not say which knob earned the score. When a reviewer is asked to trust a candidate before it is promoted, the question is concrete: how much of the gain came from alpha versus zeta versus each channel weight, and is any knob doing nothing — or actively hurting?

attribute_knob_policy answers that. Given a candidate, a baseline to attribute against, and a value function that scores any candidate, it credits each knob that differs between the two with:

  • its Shapley value — the knob's average marginal contribution over every order in which the knobs could switch from the baseline to the candidate. It is the unique attribution that is efficient (the per-knob contributions sum exactly to the candidate-minus-baseline reward), symmetric, and assigns zero to a knob that never moves the value function. It is computed exactly over all coalitions for a small number of active knobs and by deterministic Monte-Carlo permutation sampling, with a reported standard error, above a threshold;
  • its marginal (leave-one-out) contribution — the reward lost when that one knob alone is reset to baseline;
  • the same Shapley breakdown per reward component, so a reviewer can see, for example, that a knob's positive coherence contribution is partly cancelled by its actuation cost.

The value function is supplied by the caller and treated as a black box, so the same attribution works for a fixed-observation reward, a replay evaluator that re-runs the candidate over recorded data, or any other scorer. The module performs no control actuation and has no side effects.

from scpn_phase_orchestrator.autotune import (
    KnobPolicyCandidate,
    RewardObservation,
    attribute_knob_policy,
    evaluate_knob_policy,
)

candidate = KnobPolicyCandidate(alpha=0.2, zeta=0.05, channel_weights=(1.0, 0.8))
baseline = KnobPolicyCandidate(alpha=0.0, zeta=0.0, channel_weights=(0.0, 0.0))

# Any candidate -> reward report scorer works; here a replay evaluator is stubbed
# by a fixed observation so the example is self-contained.
def evaluate(policy: KnobPolicyCandidate):
    observation = RewardObservation(coherence=0.82, previous_coherence=0.74)
    return evaluate_knob_policy(policy, observation)

report = attribute_knob_policy(candidate, baseline, evaluate)

# The most influential knob first; the contributions sum to the reward spread.
for item in report.attributions:
    print(item.knob, round(item.shapley_total, 4))
assert report.attributed_total == report.candidate_reward - report.baseline_reward

Why a Shapley attribution rather than a sensitivity sweep

A one-knob-at-a-time sweep (the leave-one-out marginal) is cheap but double-counts or drops interactions: if two knobs only help in combination, each looks worthless alone. The Shapley value is the only credit assignment that distributes interaction effects consistently and adds up to the whole, which is what makes the resulting record defensible in a review rather than merely suggestive. The marginal is still reported alongside it because it is the quantity an operator's intuition expects, and the gap between the two is itself informative.

Where this sits in the autotune track

Attribution consumes the same candidate and reward surface as Reward Evaluation and Replay Policy Search: a candidate is generated and scored, the search ranks candidates, and attribution then explains the chosen one knob by knob. It produces evidence, not actions — the explanation is part of the review bundle a candidate must carry before any later learner is allowed to propose production control.

knob_attribution

Per-knob attribution — why this knob — for autotune policy candidates.

A reward report scores a candidate (a KnobPolicyCandidate) as a whole and breaks the score into reward components. It does not say which knob earned the score: a reviewer asked to trust a candidate wants to know how much of the gain came from alpha versus zeta versus each channel weight, and whether any knob is doing nothing or actively hurting.

This module answers that. Given a candidate, a baseline to attribute against, and a value function that scores any candidate, it computes each knob's contribution to the total reward and to every component by two complementary measures:

  • Shapley value — the knob's average marginal contribution over every order in which the knobs could be switched from the baseline to the candidate. It is the unique attribution that is efficient (the contributions sum exactly to the candidate-minus-baseline reward), symmetric, and assigns zero to a knob that never changes any value function. It is computed exactly over all coalitions for a small number of active knobs and by deterministic Monte-Carlo sampling, with a reported standard error, above a configurable threshold.
  • Marginal (leave-one-out) — the reward lost when that one knob alone is reset to its baseline. It is cheap and intuitive but, unlike the Shapley value, does not credit interactions consistently.

The value function is supplied by the caller and is treated as a black box, so attribution works for a fixed-observation reward, a replay evaluator that re-runs the candidate over recorded data, or any other scorer. The module performs no control actuation and has no side effects.

Attributes

CandidateEvaluator module-attribute

CandidateEvaluator = Callable[
    [KnobPolicyCandidate], AutotuneRewardReport
]

A scorer mapping a candidate to its reward report (reward plus components).

Classes

KnobAttribution dataclass

KnobAttribution(
    knob: str,
    baseline_value: float,
    candidate_value: float,
    shapley_total: float,
    marginal_total: float,
    shapley_components: Mapping[str, float],
    rank: int,
)

Attribution of one scalar knob's effect on the reward.

Parameters

knob : str Stable name of the knob, e.g. "alpha", "zeta[2]" or "channel_weights[0]". baseline_value : float The knob's value in the baseline candidate. candidate_value : float The knob's value in the attributed candidate. shapley_total : float The knob's Shapley contribution to the total reward. marginal_total : float The reward delta from resetting this knob alone to its baseline value (the leave-one-out contribution). shapley_components : Mapping[str, float] The knob's Shapley contribution to each reward component, keyed by the component name. rank : int The knob's rank by descending absolute Shapley contribution, starting at 0 for the most influential knob.

Methods:
to_audit_record
to_audit_record() -> dict[str, object]

Return a JSON-ready, deterministic record of this attribution.

Returns

dict[str, object] A mapping with the knob name, its baseline and candidate values, the Shapley and marginal totals, the per-component Shapley contributions sorted by component name, and the rank.

Source code in src/scpn_phase_orchestrator/autotune/knob_attribution.py
def to_audit_record(self) -> dict[str, object]:
    """Return a JSON-ready, deterministic record of this attribution.

    Returns
    -------
    dict[str, object]
        A mapping with the knob name, its baseline and candidate values, the
        Shapley and marginal totals, the per-component Shapley contributions
        sorted by component name, and the rank.
    """
    return {
        "knob": self.knob,
        "baseline_value": self.baseline_value,
        "candidate_value": self.candidate_value,
        "shapley_total": self.shapley_total,
        "marginal_total": self.marginal_total,
        "shapley_components": {
            name: self.shapley_components[name]
            for name in sorted(self.shapley_components)
        },
        "rank": self.rank,
    }

KnobAttributionReport dataclass

KnobAttributionReport(
    candidate_reward: float,
    baseline_reward: float,
    attributions: tuple[KnobAttribution, ...],
    method: str,
    sample_error: float | None,
)

The full per-knob attribution of a candidate against a baseline.

Parameters

candidate_reward : float The total reward of the attributed candidate. baseline_reward : float The total reward of the baseline candidate. attributions : tuple[KnobAttribution, ...] One entry per active knob (a knob whose candidate value differs from its baseline value), ordered by ascending rank. method : str "exact" if Shapley values were computed over all coalitions, or "sampled" if they were estimated by Monte-Carlo permutation sampling. sample_error : float | None The largest per-knob standard error of the sampled Shapley estimate, or None when method is "exact".

Attributes
attributed_total property
attributed_total: float

Return the sum of the Shapley totals over all active knobs.

Returns

float For the exact method this equals candidate_reward - baseline_reward to within floating-point tolerance (the Shapley efficiency axiom).

Methods:
to_audit_record
to_audit_record() -> dict[str, object]

Return a JSON-ready, deterministic record of the report.

Returns

dict[str, object] A mapping with the candidate and baseline rewards, the ordered list of per-knob audit records, the method, and the sampling error.

Source code in src/scpn_phase_orchestrator/autotune/knob_attribution.py
def to_audit_record(self) -> dict[str, object]:
    """Return a JSON-ready, deterministic record of the report.

    Returns
    -------
    dict[str, object]
        A mapping with the candidate and baseline rewards, the ordered list
        of per-knob audit records, the method, and the sampling error.
    """
    return {
        "candidate_reward": self.candidate_reward,
        "baseline_reward": self.baseline_reward,
        "method": self.method,
        "sample_error": self.sample_error,
        "attributions": [item.to_audit_record() for item in self.attributions],
    }

KnobAttributionConfig dataclass

KnobAttributionConfig(
    exact_max_knobs: int = 12,
    sample_permutations: int = 512,
    seed: int = 0,
)

Settings controlling exact-versus-sampled Shapley attribution.

Parameters

exact_max_knobs : int The largest number of active knobs for which Shapley values are computed exactly over all coalitions. Above this, sampling is used. Must be at least 1. sample_permutations : int The number of random knob orderings drawn when sampling. Must be at least 1. seed : int Seed for the deterministic permutation sampler.

Methods:
__post_init__
__post_init__() -> None

Validate the configuration bounds.

Raises

ValueError If exact_max_knobs or sample_permutations is below 1.

Source code in src/scpn_phase_orchestrator/autotune/knob_attribution.py
def __post_init__(self) -> None:
    """Validate the configuration bounds.

    Raises
    ------
    ValueError
        If ``exact_max_knobs`` or ``sample_permutations`` is below ``1``.
    """
    if self.exact_max_knobs < 1:
        raise ValueError("exact_max_knobs must be at least 1")
    if self.sample_permutations < 1:
        raise ValueError("sample_permutations must be at least 1")

Functions:

attribute_knob_policy

attribute_knob_policy(
    candidate: KnobPolicyCandidate,
    baseline: KnobPolicyCandidate,
    evaluate: CandidateEvaluator,
    *,
    config: KnobAttributionConfig | None = None,
) -> KnobAttributionReport

Attribute a candidate's reward to its individual knobs against a baseline.

Each knob that differs between candidate and baseline is credited with its Shapley contribution to the total reward and to every reward component, plus its leave-one-out marginal contribution. Knobs that are identical in both candidates are inactive: they contribute nothing by construction and are omitted from the report.

Parameters

candidate : KnobPolicyCandidate The candidate whose reward is being explained. baseline : KnobPolicyCandidate The reference candidate to attribute against. It must have the same shape as candidate (matching scalar-versus-array fields and tuple lengths). evaluate : CandidateEvaluator A side-effect-free scorer returning a reward report for any candidate of the shared shape. It is called once per distinct coalition and the results are memoised. config : KnobAttributionConfig | None Exact-versus-sampled settings. Defaults to :class:KnobAttributionConfig.

Returns

KnobAttributionReport The candidate and baseline rewards and one attribution per active knob, ordered by descending absolute Shapley contribution.

Raises

ValueError If candidate and baseline do not share the same knob shape.

Source code in src/scpn_phase_orchestrator/autotune/knob_attribution.py
def attribute_knob_policy(
    candidate: KnobPolicyCandidate,
    baseline: KnobPolicyCandidate,
    evaluate: CandidateEvaluator,
    *,
    config: KnobAttributionConfig | None = None,
) -> KnobAttributionReport:
    """Attribute a candidate's reward to its individual knobs against a baseline.

    Each knob that differs between ``candidate`` and ``baseline`` is credited
    with its Shapley contribution to the total reward and to every reward
    component, plus its leave-one-out marginal contribution. Knobs that are
    identical in both candidates are inactive: they contribute nothing by
    construction and are omitted from the report.

    Parameters
    ----------
    candidate : KnobPolicyCandidate
        The candidate whose reward is being explained.
    baseline : KnobPolicyCandidate
        The reference candidate to attribute against. It must have the same
        shape as ``candidate`` (matching scalar-versus-array fields and tuple
        lengths).
    evaluate : CandidateEvaluator
        A side-effect-free scorer returning a reward report for any candidate of
        the shared shape. It is called once per distinct coalition and the
        results are memoised.
    config : KnobAttributionConfig | None
        Exact-versus-sampled settings. Defaults to
        :class:`KnobAttributionConfig`.

    Returns
    -------
    KnobAttributionReport
        The candidate and baseline rewards and one attribution per active knob,
        ordered by descending absolute Shapley contribution.

    Raises
    ------
    ValueError
        If ``candidate`` and ``baseline`` do not share the same knob shape.
    """
    active_config = config or KnobAttributionConfig()
    candidate_values = dict(_flatten_candidate(candidate))
    baseline_values = dict(_flatten_candidate(baseline))
    if candidate_values.keys() != baseline_values.keys():
        raise ValueError("candidate and baseline must share the same knob shape")

    active = [
        knob
        for knob in candidate_values
        if candidate_values[knob] != baseline_values[knob]
    ]

    valuer = _CoalitionValuer(
        template=candidate,
        candidate_values=candidate_values,
        baseline_values=baseline_values,
        active=active,
        evaluate=evaluate,
    )
    component_keys = sorted(
        key for key in valuer.value(frozenset()) if key != _TOTAL_KEY
    )
    keys = [_TOTAL_KEY, *component_keys]

    full = valuer.value(frozenset(active))
    empty = valuer.value(frozenset())
    candidate_reward = full[_TOTAL_KEY]
    baseline_reward = empty[_TOTAL_KEY]

    if not active:
        return KnobAttributionReport(
            candidate_reward=candidate_reward,
            baseline_reward=baseline_reward,
            attributions=(),
            method="exact",
            sample_error=None,
        )

    if len(active) <= active_config.exact_max_knobs:
        shapley = _exact_shapley(active, valuer, keys)
        method = "exact"
        sample_error: float | None = None
    else:
        shapley, sample_error = _sampled_shapley(
            active,
            valuer,
            keys,
            permutations=active_config.sample_permutations,
            seed=active_config.seed,
        )
        method = "sampled"

    marginals = {
        knob: full[_TOTAL_KEY] - valuer.value(frozenset(active) - {knob})[_TOTAL_KEY]
        for knob in active
    }

    ordered = sorted(active, key=lambda knob: -abs(shapley[knob][_TOTAL_KEY]))
    attributions = tuple(
        KnobAttribution(
            knob=knob,
            baseline_value=baseline_values[knob],
            candidate_value=candidate_values[knob],
            shapley_total=shapley[knob][_TOTAL_KEY],
            marginal_total=marginals[knob],
            shapley_components={key: shapley[knob][key] for key in component_keys},
            rank=rank,
        )
        for rank, knob in enumerate(ordered)
    )
    return KnobAttributionReport(
        candidate_reward=candidate_reward,
        baseline_reward=baseline_reward,
        attributions=attributions,
        method=method,
        sample_error=sample_error,
    )