From 69daa22f096b64fd8c3be0182219174071df5f82 Mon Sep 17 00:00:00 2001 From: guluchen Date: Fri, 13 Nov 2026 22:24:04 +0800 Subject: [PATCH] test: add rotated toric [[10,2,3]] untiered benchmark --- .github/workflows/ci.yml | 3 ++ data/matrices/README.md | 10 +++- data/matrices/untiered/README.md | 4 ++ data/matrices/untiered/ROTATED_TORIC.md | 34 +++++++++++++ data/matrices/untiered/TORIC_10_2_3_Gx.txt | 3 ++ data/matrices/untiered/TORIC_10_2_3_Gz.txt | 3 ++ data/matrices/untiered/TORIC_10_2_3_Hx.txt | 5 ++ data/matrices/untiered/TORIC_10_2_3_Hz.txt | 5 ++ tests/test_rotated_toric.py | 55 ++++++++++++++++++++++ 9 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 data/matrices/untiered/ROTATED_TORIC.md create mode 100644 data/matrices/untiered/TORIC_10_2_3_Gx.txt create mode 100644 data/matrices/untiered/TORIC_10_2_3_Gz.txt create mode 100644 data/matrices/untiered/TORIC_10_2_3_Hx.txt create mode 100644 data/matrices/untiered/TORIC_10_2_3_Hz.txt create mode 100644 tests/test_rotated_toric.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4acd05b6..e4e45312 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,9 @@ jobs: - name: Build DistQLDPC run: make --jobs="$(nproc)" + - name: Validate rotated-toric exact distance and both engines + run: python3 tests/test_rotated_toric.py + - name: Run smoke validation run: bash scripts/smoke_test.sh diff --git a/data/matrices/README.md b/data/matrices/README.md index 03cbfa2e..8fbdc370 100644 --- a/data/matrices/README.md +++ b/data/matrices/README.md @@ -6,7 +6,7 @@ which lived in [untiered/](untiered/README.md), were measured with main 02879a93 bundled code and placed into the tiers on 2026-11-04 (PI plan of 2026-11-04; placement table in [untiered/README.md](untiered/README.md#placement-2026-11-04)). Their generators, MANIFEST.csv (now with `placed_tier` / `placed_stem` columns), validation evidence and provenance documents stay in untiered/, which -holds no matrices any more. New, unmeasured codes are added there first and stay out of the tier sets and the +holds the new rotated-toric fixture described below. New, unmeasured codes are added there first and stay out of the tier sets and the QDistSAT mirror until a PI-approved tier assignment; use their full path when invoking DistQLDPC. Each code `` is four text files `_Hx.txt`, `_Hz.txt`, `_Gx.txt`, @@ -21,6 +21,12 @@ is used as given (`./bin/distqldpc data/matrices/tier1/BB_144_12_12`). restricts it to one tier). `scripts/compute_logicals.py --dir` and `scripts/preprocess_matrices.py --src` take one flat directory, e.g. `data/matrices/tier0`. +## New untiered correctness fixture + +[Rotated toric [[10,2,3]]](untiered/ROTATED_TORIC.md) is available as +`data/matrices/untiered/TORIC_10_2_3`. It is not included in the tier counts +or performance panels pending dedicated-server measurement and tier approval. + ## Tiers `[[n, k, d]]`: n = columns of Hx, k = rows of Gx, d = certified distance (`{lb}to{ub}` or `ge{lb}` if not @@ -48,7 +54,7 @@ pre-registered plan and kept identical for baseline and candidate. ## Naming rule -`{family}_{n}_{k}_{d}` with family in `AMC`, `BB`, `COLOR`, `GB`, `HGP`, `LP`, `TN` (`HGP` = hypergraph product, `COLOR` = 6.6.6 color code, `AMC` = abelian multi-cycle, all 2026-11-04; the twisted-torus codes keep `BB`); n = columns of Hx, k = rows +`{family}_{n}_{k}_{d}` with family in `TORIC` (rotated toric), `AMC`, `BB`, `COLOR`, `GB`, `HGP`, `LP`, `TN` (`HGP` = hypergraph product, `COLOR` = 6.6.6 color code, `AMC` = abelian multi-cycle, all 2026-11-04; the twisted-torus codes keep `BB`); n = columns of Hx, k = rows of Gx, d = minimum distance once our tool has found it (PI 2026-10-11), otherwise the current proven bounds: `{lb}to{ub}` when an upper bound (a logical operator of that weight) is known, `ge{lb}` when only a lower bound is known (PI 2026-10-11: "Unknown可以改成目前上下界"); names are updated when bounds improve; codes with equal n and k are first checked for being the same code (duplicates are removed); genuinely different codes would get a suffix `_a`, `_b`. `GB` keeps its own prefix (not merged into `BB`). Former `PK_*` / `xu_*` codes are `LP_*`; former `QT_*` codes are `TN_*`. Upstream ids and attribution are recorded in [NOTICE](../../NOTICE), diff --git a/data/matrices/untiered/README.md b/data/matrices/untiered/README.md index fbe5d8bd..f7604fdc 100644 --- a/data/matrices/untiered/README.md +++ b/data/matrices/untiered/README.md @@ -1,5 +1,9 @@ # Untiered matrix library +New fixture: [rotated toric [[10,2,3]]](ROTATED_TORIC.md), with exhaustive +distance regression tests. This standalone fixture is not part of the historical +29-code MANIFEST.csv or validation.json batches below. + The library contains [repetition-factor HGP codes](#construction-and-distance-provenance) (GH-153), [nonzero-rate cycle-factor HGP codes](CYCLE_HGP.md) (GH-154), [triangular 6.6.6 color codes](COLOR666.md) (GH-156), and diff --git a/data/matrices/untiered/ROTATED_TORIC.md b/data/matrices/untiered/ROTATED_TORIC.md new file mode 100644 index 00000000..74f9328c --- /dev/null +++ b/data/matrices/untiered/ROTATED_TORIC.md @@ -0,0 +1,34 @@ +# Rotated toric [[10,2,3]] correctness benchmark + +`TORIC_10_2_3` is the ten-qubit rotated toric CSS code. The check supports +are transcribed in the column order of the CSS tableau linked from the +[Error Correction Zoo entry](https://errorcorrectionzoo.org/c/xzzx_10_2_3). +See also the [published construction](https://doi.org/10.1103/PhysRevA.88.012311). +The local fixture is CSS, not the locally Clifford-equivalent non-CSS XZZX tableau. +All support indices below are zero-based. + +- Hx: {0,2,3,9}, {1,2,4,5}, {3,4,6,7}, {5,6,8,9}. +- Hz: {0,1,3,4}, {2,3,5,6}, {4,5,7,8}, {0,6,7,9}. +- Gx: {0,1,2}, {0,3,7}. +- Gz: {1,2,3}, {0,1,2,6}. + +The repository convention is **Gx = Z logicals** in ker(Hx)/row(Hz), +**Gz = X logicals** in ker(Hz)/row(Hx). These are quotient bases, not +necessarily a canonical paired logical basis. Hx and Hz commute, each has +rank 4, and the logical pairing has rank 2. Exhaustive enumeration of all +1,024 binary vectors per half proves dX = dZ = 3. + +```sh +make --jobs=2 bin/distqldpc +python3 tests/test_rotated_toric.py +./bin/distqldpc -engine=cc data/matrices/untiered/TORIC_10_2_3 +./bin/distqldpc -engine=maxsat data/matrices/untiered/TORIC_10_2_3 +``` + +Both solver runs should report `o 3`. This is a correctness fixture, not a +performance or physical-layout claim. In particular, a torus drawing is +not an implementation on a planar square grid with one dedicated ancilla +per check and no SWAPs. No such embedding is supplied here. + +The fixture stays untiered pending server measurements and PI tier approval; +no tier panel, QDistSAT mirror, or historical MANIFEST is changed. diff --git a/data/matrices/untiered/TORIC_10_2_3_Gx.txt b/data/matrices/untiered/TORIC_10_2_3_Gx.txt new file mode 100644 index 00000000..3342c175 --- /dev/null +++ b/data/matrices/untiered/TORIC_10_2_3_Gx.txt @@ -0,0 +1,3 @@ +# Rotated toric [[10,2,3]]; Gx; see ROTATED_TORIC.md +1 1 1 0 0 0 0 0 0 0 +1 0 0 1 0 0 0 1 0 0 diff --git a/data/matrices/untiered/TORIC_10_2_3_Gz.txt b/data/matrices/untiered/TORIC_10_2_3_Gz.txt new file mode 100644 index 00000000..ca5b1d2a --- /dev/null +++ b/data/matrices/untiered/TORIC_10_2_3_Gz.txt @@ -0,0 +1,3 @@ +# Rotated toric [[10,2,3]]; Gz; see ROTATED_TORIC.md +0 1 1 1 0 0 0 0 0 0 +1 1 1 0 0 0 1 0 0 0 diff --git a/data/matrices/untiered/TORIC_10_2_3_Hx.txt b/data/matrices/untiered/TORIC_10_2_3_Hx.txt new file mode 100644 index 00000000..94524a15 --- /dev/null +++ b/data/matrices/untiered/TORIC_10_2_3_Hx.txt @@ -0,0 +1,5 @@ +# Rotated toric [[10,2,3]]; Hx; see ROTATED_TORIC.md +1 0 1 1 0 0 0 0 0 1 +0 1 1 0 1 1 0 0 0 0 +0 0 0 1 1 0 1 1 0 0 +0 0 0 0 0 1 1 0 1 1 diff --git a/data/matrices/untiered/TORIC_10_2_3_Hz.txt b/data/matrices/untiered/TORIC_10_2_3_Hz.txt new file mode 100644 index 00000000..eb783954 --- /dev/null +++ b/data/matrices/untiered/TORIC_10_2_3_Hz.txt @@ -0,0 +1,5 @@ +# Rotated toric [[10,2,3]]; Hz; see ROTATED_TORIC.md +1 1 0 1 1 0 0 0 0 0 +0 0 1 1 0 1 1 0 0 0 +0 0 0 0 1 1 0 1 1 0 +1 0 0 0 0 0 1 1 0 1 diff --git a/tests/test_rotated_toric.py b/tests/test_rotated_toric.py new file mode 100644 index 00000000..08946999 --- /dev/null +++ b/tests/test_rotated_toric.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Exact, solver-independent checks of the bundled rotated-toric fixture.""" +from pathlib import Path +import sys +import subprocess +import unittest + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / 'scripts/codegen')) +import validate_css as css + + +class RotatedToricTests(unittest.TestCase): + def setUp(self): + self.n, self.matrices = css.read_code( + ROOT / 'data/matrices/untiered', 'TORIC_10_2_3') + + def test_css_and_logical_bases(self): + result = css.validate(self.n, self.matrices) + self.assertEqual((result['n'], result['k'], result['rank_Hx'], + result['rank_Hz']), (10, 2, 4, 4)) + self.assertTrue(all(row.bit_count() == 4 + for rows in self.matrices[:2] for row in rows)) + + def test_exact_distance_both_halves(self): + hx, hz, gx, gz = self.matrices + # Enumerate the stabilizer spans directly, independently of elimination. + def span(rows): + words = {0} + for row in rows: + words |= {word ^ row for word in words} + return words + for parity, stabilizers in ((hx, hz), (hz, hx)): + stabilizer_span = span(stabilizers) + logicals = [word for word in range(1 << self.n) + if all((word & row).bit_count() % 2 == 0 for row in parity) + and word not in stabilizer_span] + self.assertEqual(min(word.bit_count() for word in logicals), 3) + self.assertEqual(len(logicals), 48) + + + @unittest.skipUnless((ROOT / 'bin/distqldpc').is_file(), 'build bin/distqldpc first') + def test_solver_engines(self): + for engine in ('cc', 'maxsat'): + with self.subTest(engine=engine): + run = subprocess.run( + [str(ROOT / 'bin/distqldpc'), '-engine=' + engine, + str(ROOT / 'data/matrices/untiered/TORIC_10_2_3')], + capture_output=True, text=True, timeout=20) + self.assertEqual(run.returncode, 0, run.stdout + run.stderr) + self.assertIn('o 3', run.stdout.splitlines()) + + +if __name__ == '__main__': + unittest.main()