Information¶
The Union-Find Node-Suspension decoder [hu2020thesis] uses the potential matching weight as a heuristic to prioritize growth in specific partitions – the nodes – of the Union-Find cluster (see Information). The potential matching weight is approximated by levering a node-tree in the Node-Suspension Data-structure. The elements of the node-tree are descendent objects of Node
.
The complexity of the algorithm is determined by the calculation of the node parity in ns_parity
, the node delay in ns_delay
, and the growth of the cluster, which is now applied as a recursive function that inspects all nodes in the node tree (ufns.sim.Toric.grow_node
). During cluster mergers, additional to union
, node-trees are joined by join_node_trees
.
Todo
Proper calculation of delay for erasures/empty nodes in the graph
-
class
qsurface.decoders.ufns.elements.
Node
(primer)¶ Element in the node-tree.
A subgraph \(\mathcal{V}\subseteq C\) is a spanning-tree of a cluster \(C\) if it is a connected acyclic subgraph that includes all vertices of \(C\) and a minimum number of edges. We call the spanning-tree of a cluster its ancilla-tree. An acyclic connected spanning-forest is required for the Union-Find Decoder.
A node-tree \(\mathcal{N}\) is a partition of a ancilla-tree \(\mathcal{V}\), such that each element of the partition – which we call a node \(n\) – represents a set of adjacent vertices that lie at the same distance – the node radius :math:`r` – from the *primer ancilla, which initializes the node and lies at its center. The node-tree is a directed acyclic graph, and its edges \(\mathcal{E}_i\) have lengths equal to the distance between the primer vertices of neighboring nodes.
- Parameters
primer (
AncillaQubit
) – Primer ancilla-qubit.
-
parity
¶ Node parity.
- Type
{0,1}
-
abstract
ns_parity
()¶ Calculates and returns the parity of the current node.
-
ns_delay
(parent=None, min_delay=None)¶ Calculates the node delay.
Head recursive function that calculates the delays of the current node and all its descendent nodes.
\[n_d = m_d + \lfloor n_r-m_r \rfloor - (-1)^{n_p} |(n,m)|\]The minimal delay
min_delay
in the tree is maintained as the actual delay is relative to the minimal delay value within the entire node-tree.
-
class
qsurface.decoders.ufns.elements.
Syndrome
(primer)¶ -
ns_parity
(parent_node=None)¶ Calculates the node parity.
Tail recursive function that calculates the parities of the current node and all its descendent nodes.
\[s_p = \big( \sum_{n \in \text{ children of } s} (1+s_p) \big) \bmod 2\]
-
-
class
qsurface.decoders.ufns.elements.
Junction
(primer)¶ -
ns_parity
(parent_node=None)¶ Calculates the node parity.
Tail recursive function that calculates the parities of the current node and all its children.
\[j_p = 1 - \big(\sum_{n \in \text{ children of } j} (1+n_p) \big) \bmod 2.\]
-
-
class
qsurface.decoders.ufns.elements.
OddNode
(*args, **kwargs)¶
-
qsurface.decoders.ufns.elements.
print_tree
(current_node, parent_node=None)¶ Prints the node-tree of
current_node
and its descendents.Utilizes pptree to print a tree of nodes, which requires a list of children elements per node. Since the node-tree is semi-directional (the root can be any element in the tree), we need to traverse the node-tree from
current_node
in all directions except for theparent_node
to find the children attributes for the current direction.
Simulation¶
The following description also applies to ufns.sim.Planar
.
-
class
qsurface.decoders.ufns.sim.
Toric
(*args, **kwargs)¶ Union-Find Node-Suspension decoder for the toric lattice.
Within the combined Union-Find and Node-Suspension data structure, every
Cluster
is partitioned into one or moreNode
objectss. Thenode
attribute is monkey-patched to theAncillaQubit
object to assist the identification of its parentNode
.The boundary of every cluster is not stored at the cluster object, but divided under its partitioned nodes. Cluster growth is initiated from the root of the node-tree. The attributes
root_node
andmin_delay
are monkey-patched to theCluster
object to assist with cluster growth in the Node-Suspension data structure. Seegrow_node
for more.The current class inherits from
unionfind.sim.Toric
for its application the Union-Find data structure for cluster growth and mergers. To maintain low operating complexity in UFNS, the following parameters are set of the Union-Find parent class.parameter
value
weighted_growth
True
weighted_union
True
dynamic_forest
True
-
cluster_add_ancilla
(cluster, ancilla, parent=None, **kwargs)¶ Recursively adds erased edges to
cluster
and finds the new boundary.For a given
ancilla
, this function finds the neighboring edges and ancillas that are in the the currunt cluster. If the newly found edge is erased, the edge and the corresponding ancilla will be added to the cluster, and the function applied recursively on the new ancilla. Otherwise, the neighbor is added to the new boundaryself.new_boundary
.- Parameters
cluster (
Cluster
) – Current active clusterancilla (
AncillaQubit
) – Ancilla from which the connected erased edges or boundary are searched.
-
bound_ancilla_to_node
()¶ Saves the new boundary to their respective nodes.
Saves all the new boundaries found by
cluster_add_ancilla
, which are of the form[inner_ancilla, edge, outer_ancilla]
, to the node atinner_ancilla.node
. This method is called after cluster union inunion_bucket
, which also joins the node-trees, such that the new boundary is saved to the updated nodes.
-
find_clusters
(**kwargs)¶ Initializes the clusters on the lattice.
For every non-trivial ancilla on the lattice, a
Cluster
is initiated. If any set of ancillas are connected by some set of erased qubits, all connected ancillas are found bycluster_add_ancilla
and a single cluster is initiated for the set.Additionally, a syndrome-node is initiated on the non-trivial ancilla – a syndrome – with the ancilla as primer. New boundaries are saved to the nodes by
bound_ancilla_to_node
.The cluster is then placed into a bucket based on its size and parity by
place_bucket
. Seegrow_clusters
for more information on buckets.
-
grow_clusters
(**kwargs)¶ Grows odd-parity clusters outward for union with others until all clusters are even.
Lists of odd-parity clusters are maintained at
self.buckets
. Starting from bucket 0, odd-parity clusters are popped from the bucket by ‘grow_bucket and grown at the boundary bygrow_boundary
by adding 1 for every boundary edge incluster.bound
inself.support
. Grown clusters are then placed in a new bucket byplace_bucket
based on its size if it has odd parity.Edges are fully added to the cluster per two growth iterations. Since a cluster with half-grown edges at the boundary has the same size (number of ancillas) as before growth, but is non-arguably bigger, the degeneracy in cluster size is differentiated by
cluster.support
. When an union occurs between two clusters during growth, if the merged cluster is odd, it is placed in a new bucket. Thus the real bucket number is saved at the cluster locally ascluster.bucket
. These two checks are performed before a cluster is grown ingrow_bucket
.The chronology of events per bucket must be the following:
Grow all clusters in the bucket if checks passed.
Add all odd-parity clusters after growth to
place_list
.Add all merging clusters to
union_list
.
Merge all clusters in
union_list
Add odd-parity clusters after union to
place_list
.
Place all clusters in
place_list
in new bucket if parity is odd.
For clusters with
cluster.support==1
or with half-grown edges at the boundary, the new boundary atclusters.new_bound
consists of the same half-grown edges. For clusters withcluster.support==0
, the new boundary is found bycluster_add_ancilla
.The current implementation of
grow_clusters
for theufns
decoder currently includes a work-around for a non-frequently occuring bug. Since the grown of a cluster is separated into nodes, and nodes may be buried by surrounding cluster trees such that it is an interior element and has no boundaries, it may be possible that when an odd cluster is grown no edges are actually added to the cluster. In this case, due to cluster parity duality the odd cluster will be placed in the same bucket after two rounds of growth. The work-around is to always check if the previous bucket is empty before moving on to the next one.
-
grow_boundary
(cluster, union_list, **kwargs)¶ Grows the boundary of the
cluster
.See
grow_clusters
for more information. Each element in theroot_list
of the root node of thecluster
is a subroot of an even subtree in the node-tree. From each of these subroots, the node parity and delays are calculated byns_parity
andns_delay
. The node-tree is then recursively grown bygrow_node
.- Parameters
cluster (
Cluster
) – The cluster to be grown.union_list (
List
[Tuple
[AncillaQubit
,Edge
,AncillaQubit
]]) – List of odd-parity clusters to be placed in new buckets.
-
grow_node
(cluster, node, union_list, parent_node=None)¶ Recursive function that grows a
node
and its descendents.Grows the boundary list that is stored at the current node if there the current node is not suspended. The condition required is the following:
where \(\mathcal{N}\) is the node-tree. The minimal delay value in the node-tree here stored as
cluster.min_delay
. Fully grown edges are added tounion_list
to be later considered byunion_bucket
.- Parameters
cluster (
Cluster
) – Parent cluster object ofnode
.node (
Node
) – Node to consider for growth.union_list (
List
[Tuple
[AncillaQubit
,Edge
,AncillaQubit
]]) – List of potential mergers between two cluster-distinct ancillas.parent_node (
Optional
[Node
]) – Parent node in the node-tree to indicate recursive direction.
-
grow_node_boundary
(node, union_list)¶ Grows the boundary of a
node
.
-
union_bucket
(union_list, **kwargs)¶ Potentially merges two neighboring ancillas.
If the check by
union_check
is passed, the clusters ofancilla
andnew_ancilla
are merged. additionally, the node-trees either directly joined, or by the creation of a new junction-node which asnew_ancilla
as its primer. Weighted union is applied to ensure low operating complexity.
-
check_compatibility
()¶ Checks compatibility of the decoder with the code class and loaded errors.
-
correct_edge
(ancilla_qubit, key, **kwargs)¶ Applies a correction.
The correction is applied to the data-qubit located at
ancilla_qubit.parity_qubits[key]
. More specifically, the correction is applied to theEdge
object corresponding to thestate_type
ofancilla_qubit
.- Return type
-
decode
(**kwargs)¶ Decodes the code using the Union-Find algorithm.
Decoding process can be subdivided into 3 sections:
Finding the initial clusters.
Growing and merging these clusters.
Peeling the clusters using the Peeling algorithm.
- Parameters
kwargs – Keyword arguments are passed on to
find_clusters
,grow_clusters
andpeel_clusters
.
-
flip_edge
(ancilla, edge, new_ancilla, **kwargs)¶ Flips the values of the ancillas connected to
edge
.
-
get_cluster
(ancilla)¶ Returns the cluster to which
ancilla
belongs to.If
ancilla
has no cluster or the cluster is not from the current simulation, none is returned. Otherwise, the root element of the cluster-tree is found, updated toancilla.cluster
and returned.- Parameters
ancilla (
AncillaQubit
) – The ancilla for which the cluster is to be found.- Return type
-
static
get_neighbor
(ancilla_qubit, key)¶ Returns the neighboring ancilla-qubit of
ancilla_qubit
in the direction ofkey
.- Return type
-
get_neighbors
(ancilla_qubit, loop=False, **kwargs)¶ Returns all neighboring ancillas, including other time instances.
- Parameters
loop (
bool
) – Include neighbors in time that are not chronologically next to each other during decoding within the same instance.
-
get_syndrome
(find_pseudo=False)¶ Finds the syndrome of the code.
- Parameters
find_pseudo (bool, optional) – If enabled, the lists of syndromes returned are not only
AncillaQubit
objects, but tuples of(ancilla, pseudo)
, wherepseudo
is the closestPseudoQubit
in the boundary of the code.- Return type
Union
[Tuple
[List
[AncillaQubit
],List
[AncillaQubit
]],Tuple
[List
[Tuple
[AncillaQubit
,PseudoQubit
]],List
[Tuple
[AncillaQubit
,PseudoQubit
]]]]- Returns
list – Plaquette operator syndromes.
list – Star operator syndromes.
-
grow_bucket
(bucket, bucket_i, **kwargs)¶ Grows the clusters which are contained in the current bucket.
See
grow_clusters
for more information.
-
peel_clusters
(**kwargs)¶ Loops over all clusters to find pendant ancillas to peel.
To make sure that all cluster-trees are fully peeled, all ancillas are considered in the loop. If the ancilla has not been peeled before and belongs to a cluster of the current simulation, the ancilla is considered for peeling by
peel_leaf
.
-
peel_leaf
(cluster, ancilla)¶ Recursive function which peels a branch of the tree if the input ancilla is a pendant ancilla
If there is only one neighbor of the input ancilla that is in the same cluster, this ancilla is a pendant ancilla and can be peeled. The function calls itself on the other ancilla of the edge leaf.
If [“dynamic_forest”] is disabled, once a pendant leaf is found, the acyclic forest is constructed by
static_forest
.- Parameters
cluster – Current cluster being peeled.
ancilla – Pendant ancilla of the edge to be peeled.
-
place_bucket
(clusters, bucket_i)¶ Places all clusters in
clusters
in a bucket if parity is odd.If
weighted_growth
is enabled. the cluster is placed in a new bucket based on its size, otherwise it is placed inself.buckets[0]
-
static_forest
(ancilla)¶ Constructs an acyclic forest in the cluster of
ancilla
.Applies recursively to all neighbors of
ancilla
. If a cycle is detected, edges are removed from the cluster.- Parameters
ancilla (
AncillaQubit
) –
-
union_check
(edge, ancilla, new_ancilla, cluster, new_cluster)¶ Checks whether
cluster
andnew_cluster
can be joined onedge
.See
union_bucket
for more information.- Return type
-
-
class
qsurface.decoders.ufns.sim.
Planar
(*args, **kwargs)¶ Union-Find Node-Suspension decoder for the planar lattice.
See the description of
ufns.sim.Toric
.
Plotting¶
-
class
qsurface.decoders.ufns.plot.
Toric
(*args, **kwargs)¶ Union-Find Node-Suspension decoder for the toric lattice with union-find plot.
Has all class attributes, methods, and nested figure classes from
ufns.sim.Toric
, with additional parameters below. Default values for these parameters can be supplied via a decoders.ini file under the section of[ufns]
(seedecoders._template.read_config
).The plotting class initiates a
qsurface.plot
object. For its usage, see Usage.- Parameters
step_bucket (bool, optional) – Waits for user after every occupied bucket. Default is false.
step_cluster (bool, optional) – Waits for user after growth of every cluster. Default is false.
step_node (bool, optional) – Waits for user after growth of every node. Default is false.
step_cycle (bool, optional) – Waits for user after every edge removed due to cycle detection. Default is false.
step_peel (bool, optional) – Waits for user after every edge removed during peeling. Default is false.
-
class
qsurface.decoders.ufns.plot.
Planar
(*args, **kwargs)¶ Union-Find Node-Suspension decoder for the planar lattice with union-find plot.
Has all class attributes, methods, and nested figure classes from
ufns.sim.Planar
, with additional parameters below. Default values for these parameters can be supplied via a decoders.ini file under the section of[ufns]
(seedecoders._template.read_config
).The plotting class initiates a
qsurface.plot
object. For its usage, see Usage.- Parameters
step_bucket (bool, optional) – Waits for user after every occupied bucket. Default is false.
step_cluster (bool, optional) – Waits for user after growth of every cluster. Default is false.
step_node (bool, optional) – Waits for user after growth of every node. Default is false.
step_cycle (bool, optional) – Waits for user after every edge removed due to cycle detection. Default is false.
step_peel (bool, optional) – Waits for user after every edge removed during peeling. Default is false.
- hu2020thesis
Hu, Mark Shui, Quasilinear Time Decoding Algorithm for Topological Codes with High Error Threshold, DOI: 10.13140/RG.2.2.13495.96162, 2020.