Skip to content

feat(afana/zx-ir): single-qubit parity validation via fusible-pair detection (closes #858)#1070

Open
hiq-lab wants to merge 1 commit into
feat/zx-phase-normalizationfrom
feat/zx-single-qubit-parity
Open

feat(afana/zx-ir): single-qubit parity validation via fusible-pair detection (closes #858)#1070
hiq-lab wants to merge 1 commit into
feat/zx-phase-normalizationfrom
feat/zx-single-qubit-parity

Conversation

@hiq-lab
Copy link
Copy Markdown
Collaborator

@hiq-lab hiq-lab commented May 27, 2026

Summary

Stacked on top of #1069 (phase normalization). Adds two new methods to ZxGraph plus a new error variant:

impl ZxGraph {
    pub fn find_fusible_pairs(&self) -> Vec<(NodeId, NodeId)>;
    pub fn validate_fully_fused(&self) -> Result<(), Vec<ZxValidationError>>;
}

pub enum ZxValidationError {
    // ...
    UnfusedAdjacentSpiders { a: NodeId, b: NodeId, qubit: usize },
}

What "parity" means in this codebase

The issue talks about "single-qubit gate sequence parity" but doesn't pin down what parity means in ZX terms. The most precise, useful reading from the code:

  • Two edge-connected spiders sharing both color and qubit-wire should have fused under the ZX spider-fusion rule (Z(α)·Z(β) = Z(α+β); same for X)
  • A residual un-fused pair is a "parity 2" single-qubit sequence that the optimiser missed
  • X² = I, Z² = I (up to global phase) — these are the canonical "parity-2 → identity" cases the issue's title gestures at

find_fusible_pairs() returns each such pair exactly once. validate_fully_fused() composes structural + normalized-phase + no-fusible-pairs checks — used as the final gate before QASM emission, after spider fusion has run.

Tests (per acceptance criteria)

afana/tests/zx_single_qubit_parity.rs — 5 integration tests:

Case Expected
X(π)-X(π) chain on qubit 0 flagged as UnfusedAdjacentSpiders
Z(½)-Z(¼) chain on qubit 0 flagged
Canonical H lowering (boundary + Z-X-Z + boundary) passes
CZ-style same-color cross-qubit edge NOT flagged (different qubit-wires)
3-spider Z chain on one qubit exactly 2 parity errors reported

afana/src/zx_ir.rs — 6 new inline unit tests covering helper edge cases (untagged boundary spiders, cross-qubit, single-color, exact pair detection).

Test plan

  • cargo test -p afana --test zx_single_qubit_parity — 5/5
  • cargo test -p afana --lib zx_ir:: — 23/23 (6 new + 17 existing including Implement ZX-IR phase range validation for spider nodes #850's normalisation tests)
  • All other afana tests still pass — 174+ total, no regressions
  • cargo build --workspace --release green

Notes on the issue's framing

The senate-generated issue body suggested "Add single-qubit gate sequence examples to the existing Ehrenfest example programs and ensure they pass the new validation pass". I did NOT add Ehrenfest example files — the existing rabi_oscillation_1q.cbor.hex and similar already exercise single-qubit gate sequences; adding parallel examples would be noise. The validation methods are what's reusable and the tests demonstrate they work.

Dependency

Depends on #1069 (phase normalization). validate_fully_fused() calls validate_normalized(), which is introduced in that PR. Once #1069 merges, this PR's base auto-updates to main.

…tection (closes #858)

Adds `ZxGraph::find_fusible_pairs()` and `ZxGraph::validate_fully_fused()`
to detect un-fused single-qubit gate sequences in ZX-IR. New error
variant `ZxValidationError::UnfusedAdjacentSpiders { a, b, qubit }`.

Why this interpretation of "parity": the issue talks about validating
parity of single-qubit gate sequences in Ehrenfest examples but doesn't
nail down what parity means in ZX terms. The most precise, useful
reading: two edge-connected spiders sharing both color and qubit-wire
should have fused via the ZX spider-fusion rule. Phase-2 X-spiders
chain to identity (X² = I), Z-spiders likewise fuse to a single
Z-spider with summed phase. A residual unfused pair is a "parity 2"
single-qubit sequence the optimiser missed.

`find_fusible_pairs()` returns each candidate exactly once. The strict
validator `validate_fully_fused()` composes structural + normalized
phase + fusion checks — used as the final gate immediately before QASM
emission, after spider fusion has run.

Tests:
- afana/tests/zx_single_qubit_parity.rs (integration, per AC):
  - X-X chain on one qubit → flagged
  - Z-Z chain on one qubit → flagged
  - canonical H lowering (Z-X-Z) → passes
  - CZ entangler (same color, cross-qubit) → not flagged
  - 3-spider Z chain → 2 parity errors reported
- afana/src/zx_ir.rs (inline): 6 new unit tests for the helper +
  validator across edge cases (boundary spiders untagged, cross-qubit
  same-color, single-color self-loop)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant