open-standards/wai/wai-quantum-py/python/wai_quantum/_job.py
Transaction Science 6b947aa379 wai-quantum: every verify surface holds every rule, and a host seals nothing its verifier refuses
job::verify runs job::check. POST /v1/verify, the service's tool, the command
line's tool and its verify on a set, an estimate or an algorithm's answer, the
Python package, the desktop app and the browser all apply section 8.4, reading
a job's text as text where they hold it, so a member named twice is found. Each
gives reasons beside valid and key, and a set's items are held to a job's rules.

A local host's qec, compile, pulse, estimate, @Seal and intent check now refuse
a request holding a number no double holds, as a run does, and seal_into writes
one in a result as the double sealed. A receipt already sealed with one stays
refused, its signature good, and verifies written as that double's digits.

A job recorded by the last release gets a receipt this one accepts: its program's
text from its record, and execution stated by nobody, which every kind takes.
compiled.qubit_names says which of the device's qubits each index was. sampler-v2
reads a backend's simulator member. The reference's ceiling on every whole number
is gone, as section 8.4 has it, with sums exact, and the differential now tries
numbers past a double's whole numbers, with a plant that proves it can see them.
verify --json keeps --history. The earlier form claims no sealing time. A made
receipt is pinned by digest. R of small order is tested where the equation holds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 18:03:27 -05:00

140 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""A job's answer as a plain dict, with helpers for what is read most."""
from __future__ import annotations
import json
from typing import Any, Dict, List, Optional
__all__ = ["Job", "Verification"]
class Verification(dict):
"""Whether a receipt seals its request and its result and every rule
holds: ``valid``, the ``reasons`` when it is not, the ``key`` it names (64
hex digits) and the ``signer`` (that key as a ``did:key``). True exactly
when the receipt is valid."""
@property
def valid(self) -> bool:
return self.get("valid") is True
@property
def reasons(self) -> List[str]:
return list(self.get("reasons") or [])
@property
def signer(self) -> Optional[str]:
return self.get("signer")
@property
def key(self) -> Optional[str]:
return self.get("key")
def __bool__(self) -> bool:
return self.valid
def _repr_html_(self) -> str:
from . import _render
return _render.verification_html(self)
class Job(dict):
"""A job as every surface returns it, the service's form: ``status``,
``method``, ``why``, ``estimate``, ``request``, and ``result`` with its
``receipt``. It is a plain dict (``json.dumps`` writes it as the service
sends it); the properties read the parts most often wanted.
"""
@property
def status(self) -> Optional[str]:
return self.get("status")
@property
def method(self) -> Optional[str]:
return self.get("method") or self.result.get("method")
@property
def request(self) -> Dict[str, Any]:
return self.get("request") or {}
@property
def result(self) -> Dict[str, Any]:
return self.get("result") or {}
@property
def accuracy(self) -> Optional[str]:
"""The result's accuracy class: ``bit-exact``, ``exact``, ``bounded``,
``estimate``, ``heuristic`` or ``single``."""
a = self.result.get("accuracy")
return a.get("class") if isinstance(a, dict) else a
@property
def receipt(self) -> Optional[Dict[str, Any]]:
return self.result.get("receipt")
@property
def verdict(self) -> Optional[Dict[str, Any]]:
"""How far the engine checked the job, sealed by its receipt, when
the job asked for it (``intent=``, or ``verdict=True``): its
``level``, whether its intents ``hold``, and its ``statement``."""
return self.result.get("verdict")
@property
def counts(self) -> Dict[str, int]:
"""Each outcome's count, the most frequent first (bit strings with
the highest classical bit first)."""
return dict(self.result.get("counts") or {})
@property
def shots(self) -> int:
"""The shots sampled: the counts listed and those omitted."""
return sum(self.counts.values()) + int(self.result.get("omitted_shots") or 0)
def probabilities(self) -> Dict[str, float]:
"""Each listed outcome's sampled frequency: its count over the shots.
These are samples of the distribution, as exact as the shots allow;
for an exact probability ask for the amplitude."""
n = self.shots
return {k: v / n for k, v in self.counts.items()} if n else {}
@property
def expectations(self) -> Dict[str, float]:
"""Each observable's expectation value, by the observable as asked."""
return {e["observable"]: e["value"] for e in self.result.get("expectations") or []}
@property
def amplitudes(self) -> Dict[str, complex]:
"""Each asked-for basis state's amplitude, by its bit string (one bit
per qubit, qubit n − 1 first)."""
return {a["bits"]: complex(a["re"], a["im"]) for a in self.result.get("amplitudes") or []}
def verify(self) -> Verification:
"""Whether the result's receipt seals it and the request, checked
here, offline."""
from ._api import verify
return verify(self)
def to_json(self, **kw: Any) -> str:
return json.dumps(self, **kw)
def summary(self) -> str:
"""One line: the method, the accuracy class and what the result holds."""
bits: List[str] = [f"{self.method or '?'}", f"accuracy {self.accuracy or '?'}"]
if self.counts:
bits.append(f"{self.shots} shots, {len(self.counts)} outcomes listed")
if self.result.get("expectations"):
bits.append(f"{len(self.result['expectations'])} expectation values")
if self.result.get("amplitudes"):
bits.append(f"{len(self.result['amplitudes'])} amplitudes")
if self.verdict:
bits.append(f"verdict {self.verdict.get('level')}")
if self.receipt:
bits.append("sealed")
return ", ".join(bits)
def _repr_html_(self) -> str:
from . import _render
return _render.job_html(self)