qecsim demos

Comparing planar MPS and MWPM decoders for a correlated error

This demo shows verbosely that the matrix product state (MPS) decoder can successfully recover from a correlated error on the planar code when the minimum weight perfect matching (MWPM) decoder fails.

For normal use, the simulation of a single error correction run is encapsulated in the function:
qecsim.app.run_once(code, error_model, decoder, error_probability),
and the simulation of many error correction runs is encapsulated in the function:
qecsim.app.run(code, error_model, decoder, error_probability, max_runs, max_failures).

Initialise the models

%run qsu.ipynb  # color-printing functions
from qecsim import paulitools as pt
from qecsim.models.planar import PlanarCode, PlanarMPSDecoder, PlanarMWPMDecoder

# initialise models
my_code = PlanarCode(3, 3)
my_mps_decoder = PlanarMPSDecoder()
my_mwpm_decoder = PlanarMWPMDecoder()
# print models
print(my_code)
print(my_mps_decoder)
print(my_mwpm_decoder)
PlanarCode(3, 3)
PlanarMPSDecoder(None, 'c', None, None)
PlanarMWPMDecoder()

Create a correlated error

# error: correlated error
error = my_code.new_pauli().site('Y', (2, 0), (2, 4)).to_bsf()
qsu.print_pauli('error:\n{}'.format(my_code.new_pauli(error)))
error:
·─┬─·─┬─·
  ·   ·
Y─┼─·─┼─Y
  ·   ·
·─┴─·─┴─·

Evaluate the syndrome

The syndrome is a binary array indicating the stabilizers with which the error does not commute.

# syndrome: stabilizers that do not commute with the error
syndrome = pt.bsp(error, my_code.stabilizers.T)
qsu.print_pauli('syndrome:\n{}'.format(my_code.ascii_art(syndrome)))
syndrome:
──┬───┬──
Z │   │ Z
──X───X──
Z │   │ Z
──┴───┴──

Decoding fails using the MWPM decoder

In this case, the recovery operation is found by a minimum weight perfect matching (MWPM) decoder that processes X errors and Z errors separately and so fails to find a successful recovery operation.

# recovery: best match recovery operation based on decoder
mwpm_recovery = my_mwpm_decoder.decode(my_code, syndrome)
qsu.print_pauli('mwpm_recovery:\n{}'.format(my_code.new_pauli(mwpm_recovery)))
qsu.print_pauli('mwpm_recovery ^ error:\n{}'.format(my_code.new_pauli(mwpm_recovery ^ error)))
print('check mwpm_recovery ^ error commutes with stabilizers (i.e. all zeros by construction):\n{}\n'.format(
        pt.bsp(mwpm_recovery ^ error, my_code.stabilizers.T)))
print('success iff mwpm_recovery ^ error commutes with logicals (i.e. all zeros):\n{}\n'.format(
        pt.bsp(mwpm_recovery ^ error, my_code.logicals.T)))
mwpm_recovery:
·─┬─·─┬─·
  ·   ·
X─┼─Z─┼─X
  ·   ·
·─┴─·─┴─·
mwpm_recovery ^ error:
·─┬─·─┬─·
  ·   ·
Z─┼─Z─┼─Z
  ·   ·
·─┴─·─┴─·
check mwpm_recovery ^ error commutes with stabilizers (i.e. all zeros by construction):
[0 0 0 0 0 0 0 0 0 0 0 0]

success iff mwpm_recovery ^ error commutes with logicals (i.e. all zeros):
[1 0]

Decoding succeeds using the MPS decoder

In this case, the recovery operation is found by a matrix product state (MPS) decoder that approximates a maximum likelihood decoder and so succeeds in finding a successful recovery operation.

# recovery: best match recovery operation based on decoder
mps_recovery = my_mps_decoder.decode(my_code, syndrome)
qsu.print_pauli('mps_recovery:\n{}'.format(my_code.new_pauli(mps_recovery)))
qsu.print_pauli('mps_recovery ^ error:\n{}'.format(my_code.new_pauli(mps_recovery ^ error)))
print('check mps_recovery ^ error commutes with stabilizers (i.e. all zeros by construction):\n{}\n'.format(
        pt.bsp(mps_recovery ^ error, my_code.stabilizers.T)))
print('success iff mps_recovery ^ error commutes with logicals (i.e. all zeros):\n{}\n'.format(
        pt.bsp(mps_recovery ^ error, my_code.logicals.T)))
mps_recovery:
X─┬─·─┬─X
  ·   ·
Z─┼─·─┼─Z
  ·   ·
X─┴─·─┴─X
mps_recovery ^ error:
X─┬─·─┬─X
  ·   ·
X─┼─·─┼─X
  ·   ·
X─┴─·─┴─X
check mps_recovery ^ error commutes with stabilizers (i.e. all zeros by construction):
[0 0 0 0 0 0 0 0 0 0 0 0]

success iff mps_recovery ^ error commutes with logicals (i.e. all zeros):
[0 0]