-
Notifications
You must be signed in to change notification settings - Fork 39
Refactor of flow tools - Part I #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
LGTM! Thanks! |
|
Hi @thierry-martinez, I've being thinking and I'm not fully convinced by 0c21256 By introducing the new functions In addition, these new functions lead to a circular import structure (which, if not a red boundary on its own, can be symptomatic of bad design). At the same time, as discussed above, having functions which return one type only is very handy for chaining method calls without getting static-typing errors. Should we add two methods to (Sorry to bring this up after your pass!) |
|
I think that having both |
shinich1
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we add/update examples? otherwise, LGTM.
Thanks for reviewing! Yes, we definitely should, but I propose that adding tutorials/documentation beyond the docstrings is done in separate PRs for conciseness. |
understood! |
Summary
This is the first of a series of PRs refactoring the flow tools in the library.
In the current implementation, the transformation "Open graph"$\rightarrow$ "Flow" $\rightarrow$ "XZ-corrections" $\rightarrow$ "Pattern" occurs under the hood in the
:func: OpenGraph.to_pattern()method. This refactor aims at exposing the intermediate objects to offer users more control on pattern extraction and ease the analysis of flow objects.Related issues: #120, #306, #196, #276, #181
File structure
graphix.opengraph.pyintroduces the newOpenGraphobjects. The associated filetests.test_opengraph.pycontains the bulk of the unit tests verifying the correctness of the flow-finding algorithms (these tests have been refactor fromtests.test_gflow.pyandtests.test_find_pflow).graphix.flow.core.pycontains all the flow-related functionalities, except the flow-finding algorithms which are placed ingraphix.flow._find_cflow.pyandgraphix.flow._find_gpflow.pyThe existing files
graphix.gflow.py,graphix.find_pflow.pywill be eliminated once the refactor is completed. Their modification consists of just minor changes to comply with the new interface ofOpenGraph. The modulegraphix.patternstill depends on the old flow implementation.Refactor overview
Public API
XZCorrectionscontains anOpenGraph.Examples
Define an open graph without measurement angles and extract a gflow
Define an open graph with measurement angles and extract flow, corrections and pattern
Attributes of the objects in the public API
OpenGraph (frozen dataclass)
graph: nx.Graph[int]input_nodes: Sequence[int]output_nodes: Sequence[int]measurements: Mapping[int, _M_co]PauliFlow (frozen dataclass)
og: OpenGraph[_M_co]correction_function: Mapping[int, AbstractSet[int]]partial_order_layers: Sequence[AbstractSet[int]]GFlow, CausalFlow
Same as PauliFlow but with
og: OpenGraph[_PM_co]XZCorrections (frozen dataclass)
og: OpenGraph[_M_co]x_corrections: Mapping[int, AbstractSet[int]]z_corrections: Mapping[int, AbstractSet[int]]partial_order_layers: Sequence[AcstractSet[int]]All the new classes inherit from
Generic[_M_co]. We introduce the following parametric types:_M_co = TypeVar("_M_co", bound=AbstractMeasurement, covariant=True)_PM_co = TypeVar("_PM_co", bound=AbstractPlanarMeasurement, covariant=True)Q&A attributes
Why do
PauliFlow, its children andXZCorrectionshave apartial_order_layersattribute ?In Ref. [1], it's noted that the correction function and the partial order of a flow are not independent, but rather, that the former determines the latter:
"In the problem of finding Pauli flow, instead of looking for correction function and partial order, it now suffices to look only for a (focused) extensive correction function. [...] Given a correction function$c$ we can define a minimal relation induced by the Pauli flow definition, and consider whether this relation extends to a partial order."
This observation suggests that flow objects should not have a "partial order" attribute, but instead, that it should be computed from the correction function when needed, e.g., when computing the$X,Z$ -corrections for a Pauli flow. However, this operation is costly and, crucially, the partial order is a byproduct of the flow-finding algorithms. Therefore, it is reasonable to store it as an attribute at initialization time instead.
We store in the form of layers owing to the following reasons:
Nevertheless, we endow the flow objects with class methods allowing to initialize them directly from a correction matrix or a correction function.
Similarly, the mappings
XZCorrections.x_correctionsandXZCorrections.z_correctionsdefine a partial order which is necessary to extract a pattern (specifically, the input "total order" has to be compatible with the intrinsic partial order of the XZ-corrections). Computing this partial order is expensive (it amounts to extracting a DAG and doing a topological sort as well), therefore we also store it as an attribute. Further, when theXZCorrectionsinstance is derived from a flow object, the flow's partial order is a valid partial order for the XZ-corrections, so it is useful to pass it as a parameter to the dataclass constructor.We also introduce an static method allowing to initialize
XZCorrectionsinstances directly from thex_correctionsand thez_correctionsmappings.Why do we treat open graphs as parametric objects ?
XZCorrectionsobject) requires information on the measurement angles. Treating the angles list as an object independent of the open graph demands a rather cumbersome bookkeeping (e.g., angles must be defined w.r.t. measured nodes, for Pauli axes the notion of angle is replaced by aSign, etc.). At the same time, certain operations on an open graph (namely, trying to find flows), do not need information on the angles. Therefore, it should be possible to have "plane/axis-open graphs" and "measurement-open graphs", respectively without and with information about the angles. The static type-checker should only allow "to_pattern" conversions on open graphs with angle information.We propose to achieve this by implementing a "type superstructure" on top of the existing classes
Axis,PlaneandMeasurementto avoid modifying the existing functionalities unrelated to flows. We detail this next.Measurement types
flowchart TD n(**ABC**) n0("**AbstractMeasurement**") n1("**AbstractPlanarMeasurement**") n2("**Enum**") n3("**Plane**") n4("**Axis**") n5("**Measurement** (dataclass)") n .-> n0 n0 .-> n1 n0 .-> n4 n1 .-> n5 n2 .-> n3 n2 .-> n4 n1 .-> n3This type structure should allow the following:
OpenGraph[Axis|Plane]we can look for Pauli flow only (enforced statically).OpenGraph[Plane]we can look for causal, g- and Pauli flow.OpenGraph[Measurement]we can look for causal, g- and Pauli flow.To that purpose, we introduce the following abstract class methods:
:func: AbstractMeasurement.to_plane_or_axis:func: AbstractPlanarMeasurement.to_planeFurther, a conversion to
Patternis only possible fromOpenGraph[Measurement]andXZCorrections[Measurement]objects (which have information on the measurement angles).Methods implemented in this PR
(See docstrings for further details)
OpenGraphfrom_pattern(static method)to_patternneighborsodd_neighborsfind_causal_flowfind_gflowfind_pauli_flowPauliFlow(and children)from_correction_matrix(class method)to_correctionsXZCorrectionsfrom_measured_nodes_mapping(static method)to_patterngenerate_total_measurement_orderextract_dagis_compatibleComments
The old function
graphix.generator._pflow2pattern,graphix.generator._gflow2patternandgraphix.generator._flow2patternare respectively implemented inPauliFlow/GFlow/CausalFlow.to_correctionsandXZCorrections.to_pattern.The method
OpenGraph.to_patternprovides an immediate way to extract a deterministic pattern on a given resource open graph state in similar way to the old API: it attempts to compute a flow (first causal, then Pauli) and then uses the recipe in Ref. [3] to write the pattern.However, the new API also allows the following:
Finding flows of an open graph
We provide here additional details on the interface of the
OpenGraphobject with the flow-finding algorithms.Causal flow
flowchart TD n0["OpenGraph.find_causal_flow()"] n1["find_cflow(self)"] n2("None") n3("CausalFlow") n0 --> n1 n1 --> n2 n1 --> n3 style n2 stroke:#A6280A, stroke-width:4px style n3 stroke:#0AA643, stroke-width:4pxThe function$O(N^2)$ complexity in Ref. [2]
graphix.flow._find_cflow.find_cflowimplements the layer-by-layer algoritm withGflow and Pauli flow
--- config: layout: elk --- flowchart TD n0["OpenGraph.find_gflow()"] n00["PlanarAlgebraicOpenGraph(self)"] n1["compute_correction_matrix(aog)"] n3["GFlow.from_correction_matrix(correction_matrix)"] n9("GFlow") n2("None") nn0["OpenGraph.find_pauli_flow()"] nn00["AlgebraicOpenGraph(self)"] nn1["compute_correction_matrix(aog)"] nn3["PauliFlow.from_correction_matrix(correction_matrix)"] nn9("PauliFlow") nn2("None") n0 --> n00 n00 --"aog"--> n1 n1 --> n2 n1 -- "correction_matrix"--> n3 n3 --> n9 n3 --> n2 nn0 --> nn00 nn00 --"aog"--> nn1 nn1 --> nn2 nn1 -- "correction_matrix"--> nn3 nn3 --> nn9 nn3 --> nn2 style n2 stroke:#A6280A, stroke-width:4px style n9 stroke:#0AA643, stroke-width:4px style nn2 stroke:#A6280A, stroke-width:4px style nn9 stroke:#0AA643, stroke-width:4pxThe function
graphix.flow._find_gpflow.compute_correction_matrixperforms the first part of the algebraic flow-finding algorithm in Ref. [1]. The second part (i.e., verifying that a partial order compatible with the correction matrix exists) is done by the class method.from_correction_matrix:--- config: layout: elk --- flowchart TD n3[".from_correction_matrix(correction_matrix)"] n7["compute_partial_order_layers(correction_matrix)"] n5["correction_matrix.to_correction_function()"] n2("None") n9("cls( aog.og, correction_function, partial_order_layers)") n3 --> n5 n3 --> n7 n7 -- "partial_order_layers" --> n9 n5 -- "correction_function" --> n9 n7 --> n2 style n2 stroke:#A6280A, stroke-width:4px style n9 stroke:#0AA643, stroke-width:4pxDetails on the interface with the algebraic flow-finding algorithm
We introduce two parametric dataclasses:
flowchart TD n0("**AlgebraicOpenGraph[_M_co]**") n1("**PlanarAlgebraicOpenGraph[_PM_co]**") n0 --> n1 linkStyle 0 stroke: #276cf5ffwhere the parametric type variable
_M_coand_PM_cowhere defined above.AlgebraicOpenGraphis a dataclass to manage the mapping between the open graph nodes and the row and column indices of the matrices involved in the algebraic flow-finding algorithm. This class replaces the classOpenGraphIndexintroduced in PR 337.The class$M$ and the order-demand $N$ matrices by reading out the measurement planes (or axes) of the open graph. In particular,
PlanarAlgebraicOpenGraphonly rewrites the method_compute_og_matriceswhich calculates the flow-demandAlgebraicOpenGraph._compute_og_matricescallsself.og.measurements[node].to_plane_or_axiswhich will intepret measurements with a Pauli angle as axes.This is the adequate behavior when we seek to compute a Pauli flow.
PlanarAlgebraicOpenGraph._compute_og_matricescallsself.og.measurements[node].to_planewhich will intepret measurements with a Pauli angle as planes.This is the adequate behavior when we seek to compute a gflow or a causal flow.
Feautures to be included in the next PR of this series
Methods to verify the correctness of flow and XZ-corrections objects:
PauliFlow.is_well_formedGFlow.is_well_formedCausalFlow.is_well_formedXZCorrections.is_well_formedAdapt exisiting methods in the class
OpenGraph:OpenGraph.composeOpenGraph.is_closeMethods to replace parametric angles with float values in
PauliFlow, its children andXZCorrections.Method to extract
XZCorrectionsfrom aPatterninstance.Class method
.from_correction_functionforPauliFlowand its children.Method to a extract a
GFlowfrom aPatterninstance. This requires analysis of the existing algorithms in the codebase.Re-introduce benchmark tests on flow algorithms (formerly in
tests.test_find_pflow.py.Visualization features (optional)
References
[1] Mitosek and Backens, 2024 (arXiv:2410.23439).
[2] Mhalla and Perdrix, (2008), Finding Optimal Flows Efficiently, doi.org/10.1007/978-3-540-70575-8_70
[3] Browne et al., 2007 New J. Phys. 9 250 (arXiv:quant-ph/0702212).