Source code for diffpes.certify.reproduction

"""Reproduce a certified forward result from resolved artifacts.

Extended Summary
----------------
The runner resolves normalized inputs and the recorded result at the eager I/O
boundary. It executes the exact registered model and compares the resulting
PyTree numerically. A successful report is resolver-backed evidence; a stored
checksum alone is not a reproduction claim.

Routine Listings
----------------
:func:`reproduce_forward`
    Re-execute a registered model and compare its recorded result.
"""

from __future__ import annotations

import jax
import jax.numpy as jnp
from beartype import beartype
from beartype.typing import Any
from jax.flatten_util import ravel_pytree
from jaxtyping import jaxtyped

from diffpes.types import (
    ArtifactRef,
    ArtifactResolver,
    ForwardCertificate,
    ReproductionReport,
    make_reproduction_report,
)

from .checksums import checksum_pytree
from .registry import get_model
from .resolvers import resolve_artifact


def _unique_role(
    artifacts: tuple[ArtifactRef, ...],
    roles: frozenset[str],
    label: str,
) -> ArtifactRef:
    """Return the single artifact whose role is in ``roles``."""
    matches: tuple[ArtifactRef, ...] = tuple(
        artifact for artifact in artifacts if artifact.role in roles
    )
    if len(matches) != 1:
        msg: str = f"certificate requires exactly one {label} artifact"
        raise ValueError(msg)
    result: ArtifactRef = matches[0]
    return result


[docs] @jaxtyped(typechecker=beartype) def reproduce_forward( certificate: ForwardCertificate, *, resolver: ArtifactResolver, tolerance: float = 1e-10, ) -> ReproductionReport: """Re-execute a registered model and compare its recorded result. The runner resolves one normalized input and one separately stored result. :see: :class:`~.test_reproduction.TestReproduceForward` Implementation Logic -------------------- 1. **Resolve and re-execute**:: reproduced_value = registered.executor(inputs) Exact registry lookup binds the rerun to the certificate model. 2. **Compare numerical leaves**:: absolute = jnp.abs(actual_flat - expected_flat) The report stores maximum absolute and relative errors. Parameters ---------- certificate : ForwardCertificate Certificate with one normalized-input and one result artifact. resolver : ArtifactResolver Eager resolver for both normalized artifacts. tolerance : float Nonnegative absolute and relative comparison tolerance. Default 1e-10. Returns ------- report : ReproductionReport Numerical comparison and reproduced result identity. Raises ------ ValueError If required artifact roles or result tree structure are inconsistent. Notes ----- The comparison uses ``tolerance`` for both the absolute and relative terms. Each leaf must satisfy ``absolute <= tolerance * (1 + abs(expected))``. """ if tolerance < 0.0: msg: str = "tolerance must be nonnegative" raise ValueError(msg) input_roles: frozenset[str] = frozenset( ("model-input", "normalized-input") ) result_roles: frozenset[str] = frozenset(("forward-result", "result")) input_ref: ArtifactRef = _unique_role( certificate.artifacts, input_roles, "normalized-input", ) result_ref: ArtifactRef = _unique_role( certificate.artifacts, result_roles, "result", ) inputs: Any = resolve_artifact(input_ref, resolver) expected: Any = resolve_artifact(result_ref, resolver) registered: Any = get_model( certificate.model.model_id, certificate.model.model_version, ) reproduced_value: Any = registered.executor(inputs) if jax.tree.structure(reproduced_value) != jax.tree.structure(expected): msg = "reproduced result tree structure does not match" raise ValueError(msg) actual_flat: Any = ravel_pytree(reproduced_value)[0] expected_flat: Any = ravel_pytree(expected)[0] absolute: Any = jnp.abs(actual_flat - expected_flat) denominator: Any = jnp.maximum( jnp.abs(expected_flat), jnp.finfo(absolute.dtype).tiny, ) relative: Any = absolute / denominator max_abs: Any = jnp.max(absolute) max_rel: Any = jnp.max(relative) allowed: Any = tolerance + tolerance * jnp.abs(expected_flat) reproduced: Any = jnp.all(absolute <= allowed) result_identity: str = checksum_pytree( reproduced_value, record_kind="normalized-content", ) report: ReproductionReport = make_reproduction_report( execution_id=certificate.manifest.execution_id, result_checksum=result_identity, reproduced=reproduced, max_abs_error=max_abs, max_rel_error=max_rel, tolerance=jnp.asarray(tolerance), ) return report
__all__: list[str] = ["reproduce_forward"]