8T-1CCZ Distillation Factory

This tutorial compiles two 8T-1CCZ factory layouts and compares their simulated outputs. Each factory consumes eight T states to prepare a three-qubit CCZ state.

Load and compile the layouts

Layout

Gallery entry

Purpose

Conventional

CCZ_4X3X6

Baseline lattice-surgery factory

TELS

CCZ_4X3X7_TELS

Temporally encoded lattice-surgery variant

import bloq

factories = {
    "non-tels": bloq.GalleryItem.CCZ_4X3X6,
    "tels": bloq.GalleryItem.CCZ_4X3X7_TELS,
}
for name, entry in factories.items():
    graph = entry.load()
    graph.save(f"{name}.blog")
    program = bloq.compile(graph, distance=3)
    program.save(f"{name}.bloqir")

Layout

Rounds per lattice-surgery measurement

Postselection

Conventional

\(d\)

Reject odd final X-type parity

TELS

\(\lceil2d/3\rceil\)

Also check an even-parity relation among five Z-type readouts, replacing four independent readouts

Error Contribution

The factory has two error sources: independent logical Z errors of probability \(q\) on its eight T-source proxies, and physical circuit noise of strength \(p\). Measure accepted-output infidelity relative to \(\mathrm{CCZ}|+++\rangle\).

flowchart LR
    A["8 T-source proxies: Z errors with probability q"] --> B["Factory: physical noise p"]
    B --> C["Postselection: accepted CCZ output"]

Run

Parameters

Measures

Circuit-only

\(p>0\), \(q=0\)

Circuit error \(C(d)\) with perfect T inputs

Source-only

\(p=0\), \(q>0\)

Output error \(S(q)\) from faulty T inputs

Mixed

\(p>0\), \(q>0\)

Combined error, including interactions

With \(p=0\), single input faults are rejected, but pairs can cause output errors. The \(\binom{8}{2}=28\) pairs give \(S(q)\approx28q^2\) for small \(q\).

The ideal model accepts even numbers of faulty inputs. Its acceptance \(g_s(q)\) and accepted-output infidelity \(S(q)\) are

\[ g_s(q)=\frac{1+(1-2q)^8}{2},\qquad S(q)=\frac{28q^2(1-q)^6+56q^4(1-q)^4+28q^6(1-q)^2}{g_s(q)}. \]

Compare the mixed results with \(C(d)+S(q)\). This approximation can miss interactions between source and circuit errors.

Simulation

The script samples all sixteen measurement paths and uses offline decoding and postselection to score both factories.

Download the script and the circuit bundle into the same directory. Use Python 3.12 or newer:

uv add "clifft==0.6.0" "pymatching>=2.4,<3" "stim>=1.16,<2"
uv run python tutorial_ccz_simulation.py

The bundled circuits use distance 9 and \(p=0.001\). The default samples 1,000 attempts per path. Increase --shots to resolve rare errors, and use --q to select T-source error probabilities. Counts and results are saved to ccz-results.jsonl.

"""Simulate both CCZ factories from the bundled physical circuits."""

import argparse
import hashlib
import json
import math
import re
from pathlib import Path
from zipfile import ZipFile

import clifft
import numpy as np
import pymatching
import stim

BUNDLE_SHA256 = "3f123f70314189c8fb8e9860a8ad1ba9c3996bd6d6a77d11392938582250fa0e"


def parity(rows, columns):
    return np.bitwise_xor.reduce(rows[:, columns].astype(np.uint8), axis=1)


def score(sample, corrections, spec, manifest):
    frames = [np.column_stack([
        parity(sample.measurements, records[axis]) ^ int(signs[axis])
        ^ parity(corrections, observables[axis])
        for records, signs, observables in zip(
            spec["frame_measurements"], spec["frame_signs"],
            spec["frame_observables"], strict=True)
    ]) for axis in [0, 1]]
    values = sample.exp_vals * np.asarray(spec["probe_signs"])
    for column, label in enumerate(manifest["probe_labels"]):
        flip = np.zeros(len(values), dtype=np.uint8)
        for output, axis in enumerate(label):
            if axis in "YZ":
                flip ^= frames[0][:, output]
            if axis in "XY":
                flip ^= frames[1][:, output]
        values[:, column] *= 1 - 2 * flip.astype(np.int8)
    errors = 1 - (1 + values @ np.asarray(manifest["probe_ideal_coefficients"])) / 8
    if not np.all(np.isfinite(errors)) or np.any((errors < -1e-6) | (errors > 1 + 1e-6)):
        raise ValueError("output probes yielded invalid infidelity")
    exact = np.rint(errors * 8) / 8
    if not np.allclose(errors, exact, atol=1e-6, rtol=0):
        raise ValueError("output probes left the exact eighth alphabet")
    return exact


def bounded_interval(mean, shots):
    # Union over both tails of error and acceptance means: 95% coverage.
    radius = math.log(4 / 0.05) / shots

    def divergence(value):
        if value <= 0:
            return 0 if mean == 0 else math.inf
        if value >= 1:
            return 0 if mean == 1 else math.inf
        return ((mean * math.log(mean / value) if mean else 0)
                + ((1 - mean) * math.log((1 - mean) / (1 - value)) if mean < 1 else 0))

    bounds = []
    for lower, upper, left_tail in [(0, mean, True), (mean, 1, False)]:
        for _ in range(60):
            middle = (lower + upper) / 2
            if (divergence(middle) > radius) == left_tail:
                lower = middle
            else:
                upper = middle
        bounds.append(upper if left_tail else lower)
    return bounds


def simulate(archive, factory, distance, q, shots):
    directory = f"{factory}-d{distance}/"
    manifest = json.loads(archive.read(directory + "manifest.json"))
    if manifest["schema"] != 7 or set(manifest["paths"]) != {f"{i:04b}" for i in range(16)}:
        raise ValueError("circuit metadata must cover all sixteen paths")

    def read(name):
        payload = archive.read(directory + name)
        if hashlib.sha256(payload).hexdigest() != manifest["files"][name]:
            raise ValueError(f"circuit hash mismatch: {name}")
        return payload

    strata = []
    for path, spec in sorted(manifest["paths"].items()):
        physical = read(spec["physical_file"]).decode("ascii")
        physical, count = re.subn(
            r"(?m)^(?:E|Z_ERROR)\(0\.125\)(?= (?:Z)?\d+(?: (?:Z)?\d+)*$)",
            f"Z_ERROR({q:.17g})", physical)
        if count != 8:
            raise ValueError("expected eight independent logical T-source errors")
        program = clifft.compile(physical, hir_passes=None, bytecode_passes=None)
        companion = stim.Circuit(read(spec["decoder_file"]).decode("ascii"))
        converter = companion.compile_m2d_converter()
        matching = pymatching.Matching.from_detector_error_model(
            companion.detector_error_model(decompose_errors=True))
        matched, accepted, total, square = 0, 0, 0.0, 0.0
        for start in range(0, shots, 1024):
            batch = min(1024, shots - start)
            identity = f"7:{directory}:{q:.17g}:{path}:{start}".encode("ascii")
            seed = int.from_bytes(hashlib.sha256(identity).digest()[:8], "little")
            sample = clifft.sample_survivors(program, shots=batch, seed=seed, keep_records=True)
            assert sample.total_shots == batch and sample.discards == 0
            assert len(sample.measurements) == batch
            virtual = np.zeros((batch, spec["virtual_measurements"]), dtype=bool)
            for target, source, length in spec["virtual_ranges"]:
                virtual[:, target:target + length] = sample.measurements[:, source:source + length]
            events = converter.convert(measurements=virtual, separate_observables=False)
            corrections = matching.decode_batch(events)
            conditions = np.column_stack([
                parity(sample.measurements, records) ^ int(sign) ^ parity(corrections, observables)
                for records, sign, observables in zip(
                    spec["selector_measurements"], spec["selector_signs"],
                    spec["condition_corrections"], strict=True)
            ])
            columns = {value: index for index, value in enumerate(manifest["condition_observables"])}
            selectors = conditions[:, [columns[value] for value in manifest["selector_observables"]]]
            choices = np.column_stack([
                parity(selectors, equation) ^ 1 for equation in manifest["selector_equations"]])
            match = np.all(choices == np.asarray(spec["pins"]), axis=1)
            discard = np.any(np.column_stack([
                parity(conditions, [columns[value] for value in equation])
                for equation in manifest["discard_equations"]]), axis=1)
            errors = score(sample, corrections, spec, manifest)[match & ~discard]
            matched += np.count_nonzero(match)
            accepted += len(errors)
            total += errors.sum()
            square += np.square(errors).sum()
        strata.append(dict(path=path, attempts=shots, matched=int(matched), accepted=accepted,
                           infidelity_sum=float(total), infidelity_sq_sum=float(square)))
    accepted = sum(row["accepted"] for row in strata)
    matched = sum(row["matched"] for row in strata)
    total = sum(row["infidelity_sum"] for row in strata)
    if not accepted:
        raise ValueError("no accepted outputs; increase --shots")
    raw_shots = 16 * shots
    low_x, high_x = bounded_interval(total / raw_shots, raw_shots)
    low_a, high_a = bounded_interval(accepted / raw_shots, raw_shots)
    interval = [low_x / high_a, min(1, high_x / low_a) if low_a else 1]
    return dict(factory=factory, distance=distance, physical_error_probability=0.001,
                t_infidelity=q, raw_shots=raw_shots, factory_acceptance=accepted / matched,
                infidelity=total / accepted, infidelity_ci95=interval, strata=strata)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--circuits", type=Path, default=Path("ccz-circuits.zip"))
    parser.add_argument("--q", type=float, nargs="+", default=[0, 0.001, 0.003])
    parser.add_argument("--shots", type=int, default=1000, help="attempts per measurement path")
    parser.add_argument("--output", type=Path, default=Path("ccz-results.jsonl"))
    args = parser.parse_args()
    if args.shots < 2 or any(not 0 <= q <= 1 for q in args.q):
        parser.error("use at least two shots and source probabilities between zero and one")
    if args.output.exists():
        parser.error("choose a new --output file for another run")
    with args.circuits.open("rb") as file:
        if hashlib.file_digest(file, "sha256").hexdigest() != BUNDLE_SHA256:
            parser.error("circuit bundle hash mismatch")
    clifft.set_num_threads(1)
    distance = 9
    with args.output.open("x") as file, ZipFile(args.circuits) as archive:
        for factory in ["non-tels", "tels"]:
            for q in dict.fromkeys(args.q):
                result = simulate(archive, factory, distance, q, args.shots)
                file.write(json.dumps(result, allow_nan=False) + "\n")
                file.flush()
                print(f"{factory},d={distance},q={q:g}: "
                      f"acceptance={result['factory_acceptance']:.6g}, "
                      f"infidelity={result['infidelity']:.6g}, "
                      f"95% interval={result['infidelity_ci95']}", flush=True)


if __name__ == "__main__":
    main()

Simulation Results

The plots compare factory infidelity and discard probability at \(p=0.001\). Discards exclude upstream T-state preparation failures.

CCZ factory response to input T infidelity for conventional and TELS layouts.

The circuit-only floors below use all sixteen paths. Uncertainties are nominal pointwise 95% half-widths.

Distance

Conventional floor

TELS floor

9

\((3.500 \pm 0.257)\times10^{-4}\)

\((2.922 \pm 0.237)\times10^{-4}\)

11

\((5.202 \pm 0.364)\times10^{-5}\)

\((3.723 \pm 0.309)\times10^{-5}\)

13

\((7.251 \pm 0.809)\times10^{-6}\)

\((5.854 \pm 0.598)\times10^{-6}\)

15

\((0.853 \pm 0.278)\times10^{-6}\)

\((1.037 \pm 0.304)\times10^{-6}\)