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.
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 $XZ$ corrections. However, the method
XZCorrectionshas methodsto_causal_flowandto_gflowwhich reverse this prescription to construct, respectively,CausalFlowandGFlowobjects from a given set ofto_pauli_flowis 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:
A more complicated pattern with gflow:
This pattern does not have a causal flow because measurement planes are not restricted to$XY$ . Calling
p.extract_causal_flow()will raise aFlowPropositionError.The following pattern does not have a causal flow or a gflow, but it's compatible with a Pauli flow:
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
OpenGraphwith 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:Method
drawinPattern,PauliFlowandXZCorrectionsobjects may be useful to understand the problem better.Task
Implement a method
XZCorrections.to_pauli_flow, and define a methodextract_pauli_flowinPatternthat calls it for convenience (analogous toPattern.extract_causal_flowandPattern.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:
Footnotes
Browne, Kashefi, Mhalla and Perdrix, 2007 (arXiv:quant-ph/0702212). ↩ ↩2