Skip to content

Pauli-flow extraction from pattern #432

@thierry-martinez

Description

@thierry-martinez

This issue is part of unitaryHACK 2026. You have to be registered to participate. Please read carefully the unitaryHack rules before submitting a PR for this issue.

A note about AI Slop: while we are open to collaboration with LLMs for unitaryHACK, fully AI-generated PRs are not acceptable. It is at the maintainers' discretion whether or not LLM-generated PRs are the right fit for the issues, and those that appear fully AI-generated may be immediately rejected. Please read carefully the AI policy if you are using LLMs for your work.

Context

Theorems 1, 2 and 4 in Ref. 1 prescribe how to recover an $XZ$-correction strategy (and therefore, an MBQC pattern) from a causal, g- or Pauli flow. The class XZCorrections has methods to_causal_flow and to_gflow which reverse this prescription to construct, respectively, CausalFlow and GFlow objects from a given set of $XZ$ corrections. However, the method to_pauli_flow is missing.

Extracting a Pauli flow from a deterministic $XZ$ correction strategy does not seem trivial, since the anachronical corrections do not appear in the pattern (compare Eq. in Theorem 2 vs Eq. in Theorem 4 in 1).

Examples

A simple pattern with causal flow implementing a Hadamard gate:

from graphix.command import N, E, M, X
from graphix import Measurement, Pattern
p = Pattern(input_nodes=[0], cmds=[N(1), E((0, 1)), M(0, Measurement.XY(0)), X(1, {0})], output_nodes=[1])
cf = p.extract_causal_flow()
print(cf)  # c(0) = {1}; {0} < {1}

A more complicated pattern with gflow:

from graphix.command import N, E, M, X, Z
from graphix import Measurement, Pattern

p = Pattern(
    input_nodes=[0],
    cmds=[
        N(1), N(2), N(3),
        E((0, 1)), E((0, 2)), E((1, 2)), E((1, 3)),
        M(0, Measurement.XY(0.1)), X(2, {0}), X(3, {0}),
        M(1, Measurement.XZ(0.2)), Z(2, {1}), Z(3, {1}), X(2, {1})],
    output_nodes=[2, 3])

gf = p.extract_gflow()
print(gf) # g(0) = {2, 3}, g(1) = {1, 2}; {0, 1} < {2, 3}

This pattern does not have a causal flow because measurement planes are not restricted to $XY$. Calling p.extract_causal_flow() will raise a FlowPropositionError.

The following pattern does not have a causal flow or a gflow, but it's compatible with a Pauli flow:

from graphix.command import N, E, M, X, Z
from graphix import Measurement, Pattern

p = Pattern(
    input_nodes=[0],
    cmds=[
        N(1), N(2), N(3), E((0, 1)), E((1, 2)), E((2, 3)),
        M(0, Measurement.X), X(3, {0}),
        M(1, Measurement.X), Z(3, {1}),
        M(2, Measurement.X), X(3, {2})],
    output_nodes=[3])

# p.extract_causal_flow() # Raises exception
# p.extract_gflow() # Raises exception

pf = p.extract_opengraph().extract_pauli_flow()
print(pf) # p(0) = {1, 3}, p(1) = {2}, p(2) = {3}; {0} < {1} < {2} < {3}

The question that we are trying to address is how to extract the Pauli flow directly from the pattern, without passing through the underlying open graph. This is because, in general, it is not guaranteed that a Pauli flow of the underlying open graph of the pattern generates the pattern itself because the Pauli flow of an open graph is not unique.

To generate patterns with Pauli flow but no gflow (useful for testing), one can start from an OpenGraph with Pauli flow, and convert it to a pattern. In general, any open graph with Pauli measurements does not have a causal flow or a gflow, but it may have a Pauli flow:

from graphix import OpenGraph, Measurement
import networkx as nx
og = OpenGraph(
        graph=nx.Graph([(0, 2), (2, 4), (3, 4), (4, 6), (1, 4), (1, 6), (2, 3), (3, 5), (2, 6), (3, 6)]),
        input_nodes=[0],
        output_nodes=[5, 6],
        measurements={
            0: Measurement.XY(0.1),
            1: Measurement.XZ(0.1),
            2: Measurement.Y,
            3: Measurement.XY(0.1),
            4: Measurement.Z,
        },
    )
og.to_pattern()

Method draw in Pattern, PauliFlow and XZCorrections objects may be useful to understand the problem better.

Task

Implement a method XZCorrections.to_pauli_flow, and define a method extract_pauli_flow in Pattern that calls it for convenience (analogous to Pattern.extract_causal_flow and Pattern.extract_gflow).

Acceptance criteria

For the PR to be considered for review:

  • It should pass the CI, including linting and type-checking.

  • New functions should be tested and documented appropriately following numpy style.

  • Unitary Hack AI use guidelines should be respected.

  • Author should be ready to engage in a feedback loop.

  • PR description should explicitly explain how the difficulty of dealing with anachronical corrections in the Pauli flow was tackled.

For the PR to be accepted:

  • All provided feedback should have been implemented.

Footnotes

  1. Browne, Kashefi, Mhalla and Perdrix, 2007 (arXiv:quant-ph/0702212). 2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions