Skip to content

Commit

Permalink
Merge branch 'main' into 289_fib_decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
grace-harper authored Oct 2, 2023
2 parents 04a10bc + aba9d5a commit 07e95c3
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 257 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
qiskit-terra>=0.24.0
qiskit-aer>=0.11.0
qiskit_ibm_provider>=0.5.0
pybind11<=2.9.1
PyMatching>=0.6.0,!=2.0.0
rustworkx>=0.12.0
Expand Down
172 changes: 111 additions & 61 deletions src/qiskit_qec/circuits/repetition_code.py

Large diffs are not rendered by default.

126 changes: 124 additions & 2 deletions src/qiskit_qec/decoders/decoding_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
"""
import itertools
import logging
import copy
from typing import List, Tuple, Union

import numpy as np
import rustworkx as rx
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

from qiskit_qec.analysis.faultenumerator import FaultEnumerator
from qiskit_qec.exceptions import QiskitQECError
Expand Down Expand Up @@ -119,7 +122,7 @@ def _make_syndrome_graph(self):
self.graph = graph

def get_error_probs(
self, counts, logical: str = "0", method: str = METHOD_SPITZ
self, counts, logical: str = "0", method: str = METHOD_SPITZ, return_samples=False
) -> List[Tuple[Tuple[int, int], float]]:
"""
Generate probabilities of single error events from result counts.
Expand All @@ -129,6 +132,8 @@ def get_error_probs(
logical (string): Logical value whose results are used.
method (string): Method to used for calculation. Supported
methods are 'spitz' (default) and 'naive'.
return_samples (bool): Whether to also return the number of
samples used to calculated each probability.
Returns:
dict: Keys are the edges for specific error
events, and values are the calculated probabilities.
Expand Down Expand Up @@ -236,6 +241,7 @@ def get_error_probs(
# ratio of error on both to error on neither is, to first order,
# p/(1-p) where p is the prob to be determined.
error_probs = {}
samples = {}
for n0, n1 in self.graph.edge_list():
if count[n0, n1]["00"] > 0:
ratio = count[n0, n1]["11"] / count[n0, n1]["00"]
Expand All @@ -249,8 +255,12 @@ def get_error_probs(
else:
edge = (n0, n1)
error_probs[edge] = p
samples[edge] = count[n0, n1]["11"] + count[n0, n1]["00"]

return error_probs
if return_samples:
return error_probs, samples
else:
return error_probs

def weight_syndrome_graph(self, counts, method: str = METHOD_SPITZ):
"""Generate weighted syndrome graph from result counts.
Expand Down Expand Up @@ -570,3 +580,115 @@ def _decoding_graph(self):
self.idxmap = idxmap
self.node_layers = node_layers
self.graph = graph


def make_syndrome_graph_from_aer(code, shots=1):
"""
Generates a graph and list of hyperedges for a given code by inserting single qubit
Paulis into the base circuit for that code. Also supplied information regarding which
edges where generated by which Pauli insertions.
Args:
code (CodeCircuit): Code for which the graph is to be made
shots (int): Number of shots used in simulations.
Returns:
graph (PyGraph): Graph of the form used in `DecodingGraph`.
hyperedges (list): List of hyperedges of the form used in `DecodingGraph`.
hyperedge_errors (list): A list of the Pauli insertions that causes each hyperedge.
These are specified by a tuple that specifies the type of Pauli and where it was
inserted: (circuit depth, qreg index, qubit index, Pauli type).
error_circuit (dict): Keys are the above tuples, and values are the corresponding
circuits.
"""

graph = rx.PyGraph(multigraph=False)
hyperedges = []
hyperedge_errors = []

qc = code.circuit[code.base]
blank_qc = QuantumCircuit()
for qreg in qc.qregs:
blank_qc.add_register(qreg)
for creg in qc.cregs:
blank_qc.add_register(creg)

error_circuit = {}
depth = len(qc)
for j in range(depth):
gate = qc.data[j][0].name
qubits = qc.data[j][1]
if gate not in ["measure", "reset", "barrier"]:
for error in ["x", "y", "z"]:
for qubit in qubits:
temp_qc = copy.deepcopy(blank_qc)
for qreg in qc.qregs:
if qubit in qreg:
break
temp_qc_name = (j, qc.qregs.index(qreg), qreg.index(qubit), error)
temp_qc.data = qc.data[0:j]
getattr(temp_qc, error)(qubit)
temp_qc.data += qc.data[j : depth + 1]
error_circuit[temp_qc_name] = temp_qc
elif gate == "measure":
pre_error = "x"
for post_error in ["id", "x"]:
for qubit in qubits:
temp_qc = copy.deepcopy(blank_qc)
for qreg in qc.qregs:
if qubit in qreg:
break
temp_qc_name = (
j,
qc.qregs.index(qreg),
qreg.index(qubit),
pre_error + "_" + post_error,
)
temp_qc.data = qc.data[0:j]
getattr(temp_qc, pre_error)(qubit)
temp_qc.data.append(qc.data[j])
getattr(temp_qc, post_error)(qubit)
temp_qc.data += qc.data[j + 1 : depth + 1]
error_circuit[temp_qc_name] = temp_qc

errors = []
circuits = []
for error, circuit in error_circuit.items():
errors.append(error)
circuits.append(circuit)

result = AerSimulator().run(circuits, shots=shots).result()
no_nodes = []
for j, circuit in enumerate(circuits):
for string in result.get_counts(j):
nodes = code.string2nodes(string)
for node in nodes:
if node not in graph.nodes():
graph.add_node(node)
hyperedge = {}
for source in nodes:
for target in nodes:
if target != source or (len(nodes) == 1):
n0 = graph.nodes().index(source)
n1 = graph.nodes().index(target)
if not (source.is_boundary and target.is_boundary):
qubits = list(set(source.qubits).intersection(target.qubits))
if source.time != target.time and len(qubits) > 1:
qubits = []
edge = DecodingGraphEdge(qubits, 1)
graph.add_edge(n0, n1, edge)
if (n1, n0) not in hyperedge:
hyperedge[n0, n1] = edge
if hyperedge:
if hyperedge not in hyperedges:
hyperedges.append(hyperedge)
hyperedge_errors.append([])
k = hyperedges.index(hyperedge)
if errors[j] not in hyperedge_errors[k]:
hyperedge_errors[k].append(errors[j])
else:
if errors[j] not in no_nodes:
no_nodes.append(errors[j])
hyperedges.append({})
hyperedge_errors.append(no_nodes)

return graph, hyperedges, hyperedge_errors, error_circuit
4 changes: 3 additions & 1 deletion src/qiskit_qec/decoders/hdrg_decoders.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ def _cluster(self, ns, dist_max):

# it's fully neutral if no extra logicals are needed
# and if the error num is less than the max dist
fully_neutral = neutral and logicals == [] and num_errors < dist_max
fully_neutral = neutral and logicals == []
if num_errors:
fully_neutral = fully_neutral and num_errors < dist_max

# if a cluster is neutral, all nodes are labelled with c
# otherwise, it gets a None
Expand Down
6 changes: 3 additions & 3 deletions src/qiskit_qec/geometry/tiles/hexagontile.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ class HexagonTile(Tile):
None, # 11
],
"cYZX2-hXX": [
PauliList(["YZXYXZ"], input_qubit_order="left-to-right"), # 0
PauliList(["YZXYXZ"], input_qubit_order="left-to-right"), # 1
PauliList(["YZXYXZ"], input_qubit_order="left-to-right"), # 2
PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 0
PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 1
PauliList(["YZXYZX"], input_qubit_order="left-to-right"), # 2
None, # 3
PauliList(["XX"]), # 4
None, # 5
Expand Down
2 changes: 0 additions & 2 deletions src/qiskit_qec/linear/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@
is_stabilizer_group
"""

from .bit.bit import Bit
from .smatrix_api.smatrix import SMatrix
from .matrix import create_lambda_matrix, augment_mat, rref, rank, rref_complete
from .symplectic import (
all_commute,
Expand Down
15 changes: 0 additions & 15 deletions src/qiskit_qec/linear/bit/__init__.py

This file was deleted.

22 changes: 0 additions & 22 deletions src/qiskit_qec/linear/bit/bit.py

This file was deleted.

15 changes: 0 additions & 15 deletions src/qiskit_qec/linear/smatrix_api/__init__.py

This file was deleted.

42 changes: 0 additions & 42 deletions src/qiskit_qec/linear/smatrix_api/sm_numpy.py

This file was deleted.

15 changes: 0 additions & 15 deletions src/qiskit_qec/linear/smatrix_api/sm_sparse.py

This file was deleted.

73 changes: 0 additions & 73 deletions src/qiskit_qec/linear/smatrix_api/smatrix.py

This file was deleted.

Loading

0 comments on commit 07e95c3

Please sign in to comment.