Skip to content

Commit

Permalink
variable edge weight
Browse files Browse the repository at this point in the history
  • Loading branch information
quantumjim committed Apr 11, 2024
1 parent d61cb32 commit 6a1151c
Showing 1 changed file with 41 additions and 18 deletions.
59 changes: 41 additions & 18 deletions src/qiskit_qec/decoders/hdrg_decoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from typing import Dict, List, Set, Tuple

from rustworkx import PyGraph, connected_components, distance_matrix
import numpy as np

from qiskit_qec.decoders.decoding_graph import DecodingGraph
from qiskit_qec.utils import DecodingGraphEdge
Expand Down Expand Up @@ -291,7 +292,11 @@ class UnionFindDecoder(ClusteringDecoder):
by the peeling decoder for compatible codes or by the standard HDRG
method in general.
See arXiv:1709.06218v3 for more details.
To avoid using the peeling decoder, and instead use the standard
method for clustering decoders to get corrections, set `use_peeling=False`.
Growth unit is 0.5 by default, but can be changed with `growth_unit`.
To use half the minimum boundarye edge weight for each clustering round,
set `growth_unit=None`.
"""

def __init__(
Expand All @@ -300,6 +305,7 @@ def __init__(
decoding_graph: DecodingGraph = None,
use_peeling=True,
use_is_cluster_neutral=False,
growth_unit=0.5,
) -> None:
super().__init__(code, decoding_graph=deepcopy(decoding_graph))
self.graph = self.decoding_graph.graph
Expand All @@ -308,6 +314,8 @@ def __init__(
self.use_peeling = use_peeling
self.use_is_cluster_neutral = use_is_cluster_neutral
self._clusters4peeling = []
self.growth_unit = growth_unit
self._growth_unit = None

def process(self, string: str, predecoder=None):
"""
Expand Down Expand Up @@ -463,10 +471,20 @@ def _grow_clusters(self) -> List[FusionEntry]:
clusters that will be merged in the next step.
"""
fusion_edge_list: List[FusionEntry] = []

if self.growth_unit:
self._growth_unit = self.growth_unit
else:
min_weight = np.inf
for root in self.odd_cluster_roots:
cluster = self.clusters[root]
for edge in cluster.boundary:
min_weight = max(min(min_weight, edge.data.weight), 0)
self._growth_unit = min_weight / 2
for root in self.odd_cluster_roots:
cluster = self.clusters[root]
for edge in cluster.boundary:
edge.data.properties["growth"] += 0.5
edge.data.properties["growth"] += self._growth_unit
if (
edge.data.properties["growth"] >= edge.data.weight
and not edge.data.properties["fully_grown"]
Expand Down Expand Up @@ -546,22 +564,27 @@ def _merge_clusters(self, fusion_edge_list: List[FusionEntry]):

# see if the cluster is neutral and update odd_cluster_roots accordingly
fully_neutral = False
for nodes in [
[self.graph[node] for node in cluster.atypical_nodes],
[
self.graph[node]
for node in cluster.atypical_nodes
| (set(list(cluster.boundary_nodes)[:1]) if cluster.boundary_nodes else set())
],
]:
if self.use_is_cluster_neutral:
fully_neutral = self.code.is_cluster_neutral(nodes)
else:
neutral, extras, num = self.code.check_nodes(nodes)
for node in extras:
neutral = neutral and (not node.is_boundary)
neutral = neutral and num <= len(cluster.edge_support)
fully_neutral = fully_neutral or neutral
if self._growth_unit: # assume non-neutral while growing along 0-weight edges
for nodes in [
[self.graph[node] for node in cluster.atypical_nodes],
[
self.graph[node]
for node in cluster.atypical_nodes
| (
set(list(cluster.boundary_nodes)[:1])
if cluster.boundary_nodes
else set()
)
],
]:
if self.use_is_cluster_neutral:
fully_neutral = self.code.is_cluster_neutral(nodes)
else:
neutral, extras, num = self.code.check_nodes(nodes)
for node in extras:
neutral = neutral and (not node.is_boundary)
neutral = neutral and num <= len(cluster.edge_support)
fully_neutral = fully_neutral or neutral
if fully_neutral:
if new_root in self.odd_cluster_roots:
self.odd_cluster_roots.remove(new_root)
Expand Down

0 comments on commit 6a1151c

Please sign in to comment.