Spaces:
Running
Running
| /** | |
| * kitaev_surface.test.ts | |
| * | |
| * Vitest tests for the Lutar.QEC.Kitaev (KitaevSurface) gate. | |
| * | |
| * Tests: | |
| * 1. 1000-input random parity check — single-site error always produces odd parity | |
| * 2. No-error and all-error edge cases (zero parity) | |
| * 3. Weight-2 / weight-4 error patterns | |
| * 4. Receipt emission with mock signer | |
| * | |
| * Lean commit: c4d13795689601324fce0236351bfe0ade990a43 | |
| */ | |
| import { describe, it, expect } from "vitest"; | |
| import { | |
| vertexParity, | |
| detectSyndromes, | |
| singleSiteError, | |
| emitKitaevSurfaceReceipt, | |
| kitaevSurfaceGate, | |
| siteKey, | |
| type Site, | |
| type VertexCheck, | |
| type ErrorMap, | |
| type Signer, | |
| } from "../../src/gates/kitaev_surface"; | |
| // --------------------------------------------------------------------------- | |
| // Seeded LCG | |
| // --------------------------------------------------------------------------- | |
| function seedRandom(seed: number) { | |
| let s = seed >>> 0; | |
| return () => { | |
| s = (Math.imul(1664525, s) + 1013904223) >>> 0; | |
| return s / 0x100000000; | |
| }; | |
| } | |
| const mockSigner: Signer = (p: string) => | |
| `mock-sig::${Buffer.from(p).slice(0, 16).toString("hex")}`; | |
| // --------------------------------------------------------------------------- | |
| // Helper: build a vertex check from 4 sites | |
| // --------------------------------------------------------------------------- | |
| function makeVertex( | |
| na: number, ns: number, | |
| sa: number, ss: number, | |
| ea: number, es: number, | |
| wa: number, ws: number | |
| ): VertexCheck { | |
| return { | |
| n: { agent: na, slice: ns }, | |
| s: { agent: sa, slice: ss }, | |
| e: { agent: ea, slice: es }, | |
| w: { agent: wa, slice: ws }, | |
| }; | |
| } | |
| const V0 = makeVertex(0, 0, 0, 1, 1, 0, 0, 2); | |
| // --------------------------------------------------------------------------- | |
| // 1. 1000-input random: single-site error flips parity | |
| // --------------------------------------------------------------------------- | |
| describe("kitaev_surface: 1000-input single-site error parity test", () => { | |
| it("single north-site error yields parity = true for 1000 random vertices", () => { | |
| const rand = seedRandom(0x11223344); | |
| let failures = 0; | |
| for (let i = 0; i < 1000; i++) { | |
| const na = Math.floor(rand() * 100); | |
| const ns = Math.floor(rand() * 100); | |
| const v = makeVertex( | |
| na, ns, | |
| na, ns + 1, | |
| na + 1, ns, | |
| na, ns + 2 | |
| ); | |
| const errors = singleSiteError(v.n); | |
| const parity = vertexParity(errors, v); | |
| if (!parity) failures++; | |
| } | |
| expect(failures).toBe(0); | |
| }); | |
| it("single south-site error yields parity = true for 1000 random vertices", () => { | |
| const rand = seedRandom(0xaabbccdd); | |
| let failures = 0; | |
| for (let i = 0; i < 1000; i++) { | |
| const a = Math.floor(rand() * 100); | |
| const s = Math.floor(rand() * 100); | |
| const v = makeVertex(a, s, a + 1, s, a, s + 1, a, s + 2); | |
| const errors = singleSiteError(v.s); | |
| if (!vertexParity(errors, v)) failures++; | |
| } | |
| expect(failures).toBe(0); | |
| }); | |
| }); | |
| // --------------------------------------------------------------------------- | |
| // 2. Edge cases: no-error, all-error | |
| // --------------------------------------------------------------------------- | |
| describe("kitaev_surface: edge cases", () => { | |
| it("no errors → parity = false (kitaev_no_errors_zero_parity)", () => { | |
| expect(vertexParity(new Map(), V0)).toBe(false); | |
| }); | |
| it("all 4 sites corrupted → parity = false (kitaev_all_errors_zero_parity)", () => { | |
| const errors: ErrorMap = new Map(); | |
| errors.set(siteKey(V0.n), true); | |
| errors.set(siteKey(V0.s), true); | |
| errors.set(siteKey(V0.e), true); | |
| errors.set(siteKey(V0.w), true); | |
| expect(vertexParity(errors, V0)).toBe(false); | |
| }); | |
| it("weight-2 error (n and s) → parity = false", () => { | |
| const errors: ErrorMap = new Map(); | |
| errors.set(siteKey(V0.n), true); | |
| errors.set(siteKey(V0.s), true); | |
| expect(vertexParity(errors, V0)).toBe(false); | |
| }); | |
| it("weight-3 error (n, s, e) → parity = true", () => { | |
| const errors: ErrorMap = new Map(); | |
| errors.set(siteKey(V0.n), true); | |
| errors.set(siteKey(V0.s), true); | |
| errors.set(siteKey(V0.e), true); | |
| expect(vertexParity(errors, V0)).toBe(true); | |
| }); | |
| it("single east-site error → parity = true", () => { | |
| const errors = singleSiteError(V0.e); | |
| expect(vertexParity(errors, V0)).toBe(true); | |
| }); | |
| it("single west-site error → parity = true", () => { | |
| const errors = singleSiteError(V0.w); | |
| expect(vertexParity(errors, V0)).toBe(true); | |
| }); | |
| }); | |
| // --------------------------------------------------------------------------- | |
| // 3. detectSyndromes | |
| // --------------------------------------------------------------------------- | |
| describe("kitaev_surface: detectSyndromes", () => { | |
| const V1 = makeVertex(5, 0, 5, 1, 6, 0, 5, 2); | |
| const V2 = makeVertex(10, 0, 10, 1, 11, 0, 10, 2); | |
| it("no errors → no syndromes detected", () => { | |
| const syndromes = detectSyndromes([V0, V1, V2], new Map()); | |
| expect(syndromes.length).toBe(0); | |
| }); | |
| it("single error on V0.n → exactly one syndrome at V0", () => { | |
| const errors = singleSiteError(V0.n); | |
| const syndromes = detectSyndromes([V0, V1, V2], errors); | |
| expect(syndromes.length).toBe(1); | |
| expect(syndromes[0]).toEqual(V0); | |
| }); | |
| }); | |
| // --------------------------------------------------------------------------- | |
| // 4. Receipt emission | |
| // --------------------------------------------------------------------------- | |
| describe("kitaev_surface: DSSE receipt emission", () => { | |
| it("single-site error emits receipt with output = true (syndrome detected)", () => { | |
| const { parity, receipt } = emitKitaevSurfaceReceipt(V0, [V0.n], mockSigner); | |
| expect(parity).toBe(true); | |
| expect(receipt.output).toBe(true); | |
| expect(receipt.theorem).toBe( | |
| "Lutar.QEC.Kitaev.kitaev_single_site_flips_parity_n" | |
| ); | |
| expect(receipt.lean_commit_sha).toBe("c4d13795689601324fce0236351bfe0ade990a43"); | |
| expect(receipt.inputs_hash).toMatch(/^[0-9a-f]{64}$/); | |
| }); | |
| it("no errors emits receipt with output = false (no syndrome)", () => { | |
| const { parity, receipt } = emitKitaevSurfaceReceipt(V0, [], mockSigner); | |
| expect(parity).toBe(false); | |
| expect(receipt.output).toBe(false); | |
| }); | |
| it("gate returns hasSyndrome correctly", () => { | |
| const { hasSyndrome, receipt } = kitaevSurfaceGate(V0, [V0.s], mockSigner); | |
| expect(hasSyndrome).toBe(true); | |
| expect(receipt.output).toBe(true); | |
| }); | |
| it("deterministic inputs_hash for same vertex + error sites", () => { | |
| const r1 = emitKitaevSurfaceReceipt(V0, [V0.n], mockSigner); | |
| const r2 = emitKitaevSurfaceReceipt(V0, [V0.n], mockSigner); | |
| expect(r1.receipt.inputs_hash).toBe(r2.receipt.inputs_hash); | |
| }); | |
| it("different error patterns yield different inputs_hash", () => { | |
| const r1 = emitKitaevSurfaceReceipt(V0, [V0.n], mockSigner); | |
| const r2 = emitKitaevSurfaceReceipt(V0, [V0.s], mockSigner); | |
| expect(r1.receipt.inputs_hash).not.toBe(r2.receipt.inputs_hash); | |
| }); | |
| }); | |