Skip to content

Commit

Permalink
Add Steane-type and teleportation-based QEC for the Steane code (#115)
Browse files Browse the repository at this point in the history
* draft steane_qec

* fix qec_steane_z

* factor out permute changes to another PR

* factor out Steane.m cleanup to another PR

* set flag bit correctly

* add qec_steane_.*tel templates

* fix Steane.qec_steane_tel

* permute all qubits for teleportation

* formatting fixes

* formatting fixes

* formatting fix

* formatting fix

* no need to permute ancillas

* minor rearrangement

* fix teleportation-based QEC

* fix typo

* maybe fix classical registers in teleportation-based QEC

* two flag bits for Steane.qec_tel

* add warnings

* rename flag_bit --> flag, in agreement with elsewhere in the repo

* minor cleanup

* minor renaming

* standardize docstring

* fix If statement

* maybe fix Steane QEC and an incorrect type hint

* fix typo

* fix warning typo
  • Loading branch information
perlinm authored Jan 7, 2025
1 parent cc28567 commit 5982e51
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(
syndromes: CReg,
raw_syn: CReg,
pf: Bit,
flag: Bit,
flag: CReg,
flags: CReg,
scratch: CReg,
):
Expand Down Expand Up @@ -96,7 +96,7 @@ def __init__(
syndromes: CReg,
raw_syn: CReg,
pf: Bit,
flag: Bit,
flag: CReg,
flags: CReg,
scratch: CReg,
pf_bit_copy: Bit | None = None,
Expand Down
155 changes: 155 additions & 0 deletions python/quantum-pecos/src/pecos/qeclib/steane/steane_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from warnings import warn

from pecos.qeclib.steane.decoders.lookup import (
FlagLookupQASMActiveCorrectionX,
FlagLookupQASMActiveCorrectionZ,
)
from pecos.qeclib.steane.gates_sq import paulis, sqrt_paulis
Expand Down Expand Up @@ -496,6 +497,160 @@ def qec(self, flag: Bit | None = None):
block.extend(If(self.flags != 0).Then(flag.set(1)))
return block

def qec_steane(
self,
aux: Steane,
reject_x: Bit | None = None,
reject_z: Bit | None = None,
flag_x: Bit | None = None,
flag_z: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a Steane-type error-correction cycle of this code."""
return Block(
self.qec_steane_x(
aux,
reject=reject_x,
flag=flag_x,
rus_limit=rus_limit,
),
self.qec_steane_z(
aux,
reject=reject_z,
flag=flag_z,
rus_limit=rus_limit,
),
)

def qec_steane_x(
self,
aux: Steane,
reject: Bit | None = None,
flag: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a Steane-type error-correction cycle for X errors."""
warn("Using experimental feature: qec_steane_x", stacklevel=2)
block = Block(
aux.px(reject=reject, rus_limit=rus_limit),
self.cx(aux),
aux.mz(),
self.syn_z.set(aux.syn_meas),
self.last_raw_syn_z.set(0),
self.pf_x.set(0),
FlagLookupQASMActiveCorrectionZ(
self.d,
self.syn_z,
self.syn_z,
self.last_raw_syn_z,
self.pf_x,
self.syn_z,
self.syn_z,
self.scratch,
),
)
if flag is not None:
block.extend(If(self.syn_z != 0).Then(flag.set(1)))
return block

def qec_steane_z(
self,
aux: Steane,
reject: Bit | None = None,
flag: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a Steane-type error-correction cycle for Z errors."""
warn("Using experimental feature: qec_steane_z", stacklevel=2)
block = Block(
aux.pz(reject=reject, rus_limit=rus_limit),
aux.cx(self),
aux.mx(),
self.syn_x.set(aux.syn_meas),
self.last_raw_syn_x.set(0),
self.pf_z.set(0),
FlagLookupQASMActiveCorrectionX(
self.d,
self.syn_x,
self.syn_x,
self.last_raw_syn_x,
self.pf_z,
self.syn_x,
self.syn_x,
self.scratch,
),
)
if flag is not None:
block.extend(If(self.syn_x != 0).Then(flag.set(1)))
return block

def qec_tel(
self,
aux: Steane,
reject_x: Bit | None = None,
reject_z: Bit | None = None,
flag_x: Bit | None = None,
flag_z: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a teleportation-based error correction cycle."""
return Block(
self.qec_tel_x(aux, reject_x, flag_x, rus_limit),
self.qec_tel_z(aux, reject_z, flag_z, rus_limit),
)

def qec_tel_x(
self,
aux: Steane,
reject: Bit | None = None,
flag: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a teleportation-based error correction cycle for X errors."""
warn("Using experimental feature: qec_tel_x", stacklevel=2)
block = Block(
# teleport
aux.px(reject=reject, rus_limit=rus_limit),
aux.cx(self),
self.mz(),
If(self.log == 1).Then(aux.x()),
Permute(self.d, aux.d),
# update syndromes and pauli frame
self.last_raw_syn_x.set(0),
self.last_raw_syn_z.set(0),
self.syn_z.set(self.syn_meas),
self.pf_x.set(0),
)
if flag is not None:
block.extend(If(self.syn_meas != 0).Then(flag.set(1)))
return block

def qec_tel_z(
self,
aux: Steane,
reject: Bit | None = None,
flag: Bit | None = None,
rus_limit: int | None = None,
) -> Block:
"""Run a teleportation-based error correction cycle for Z errors."""
warn("Using experimental feature: qec_tel_z", stacklevel=2)
block = Block(
# teleport
aux.pz(reject=reject, rus_limit=rus_limit),
self.cx(aux),
self.mx(),
If(self.log == 1).Then(aux.z()),
Permute(self.d, aux.d),
# update syndromes and pauli frame
self.last_raw_syn_x.set(0),
self.last_raw_syn_z.set(0),
self.syn_x.set(self.syn_meas),
self.pf_z.set(0),
)
if flag is not None:
block.extend(If(self.syn_meas != 0).Then(flag.set(1)))
return block

def permute(self, other: Steane):
"""Permute this code block (including both quantum and classical registers) with another."""
block = Block(
Expand Down

0 comments on commit 5982e51

Please sign in to comment.