Source code for qiskit.ignis.verification.topological_codes.circuits

# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

# pylint: disable=invalid-name

"""Generates circuits for quantum error correction."""

from qiskit import QuantumRegister, ClassicalRegister
from qiskit import QuantumCircuit


[docs]class RepetitionCode(): """ Implementation of a distance d repetition code, implemented over T syndrome measurement rounds. """ def __init__(self, d, T=0): """ Creates the circuits corresponding to a logical 0 and 1 encoded using a repetition code. Args: d (int): Number of code qubits (and hence repetitions) used. T (int): Number of rounds of ancilla-assisted syndrome measurement. Additional information: No measurements are added to the circuit if `T=0`. Otherwise `T` rounds are added, followed by measurement of the code qubits (corresponding to a logical measurement and final syndrome measurement round). """ self.d = d self.T = 0 self.code_qubit = QuantumRegister(d, 'code_qubit') self.link_qubit = QuantumRegister((d - 1), 'link_qubit') self.qubit_registers = {'code_qubit', 'link_qubit'} self.link_bits = [] self.code_bit = ClassicalRegister(d, 'code_bit') self.circuit = {} for log in ['0', '1']: self.circuit[log] = QuantumCircuit( self.link_qubit, self.code_qubit, name=log) self._preparation() for _ in range(T-1): self.syndrome_measurement() if T != 0: self.syndrome_measurement(reset=False) self.readout()
[docs] def get_circuit_list(self): """ Returns: circuit_list: self.circuit as a list, with circuit_list[0] = circuit['0'] circuit_list[1] = circuit['1'] """ circuit_list = [self.circuit[log] for log in ['0', '1']] return circuit_list
[docs] def x(self, logs=('0', '1'), barrier=False): """ Applies a logical x to the circuits for the given logical values. Args: logs (list or tuple): List or tuple of logical values expressed as strings. barrier (bool): Boolean denoting whether to include a barrier at the end. """ for log in logs: for j in range(self.d): self.circuit[log].x(self.code_qubit[j]) if barrier: self.circuit[log].barrier()
def _preparation(self): """ Prepares logical bit states by applying an x to the circuit that will encode a 1. """ self.x(['1'])
[docs] def syndrome_measurement(self, reset=True, barrier=False): """ Application of a syndrome measurement round. Args: reset (bool): If set to true add a boolean at the end of each round barrier (bool): Boolean denoting whether to include a barrier at the end. """ self.link_bits.append(ClassicalRegister( (self.d - 1), 'round_' + str(self.T) + '_link_bit')) for log in ['0', '1']: self.circuit[log].add_register(self.link_bits[-1]) for j in range(self.d - 1): self.circuit[log].cx(self.code_qubit[j], self.link_qubit[j]) for j in range(self.d - 1): self.circuit[log].cx( self.code_qubit[j + 1], self.link_qubit[j]) for j in range(self.d - 1): self.circuit[log].measure( self.link_qubit[j], self.link_bits[self.T][j]) if reset: self.circuit[log].reset(self.link_qubit[j]) if barrier: self.circuit[log].barrier() self.T += 1
[docs] def readout(self): """ Readout of all code qubits, which corresponds to a logical measurement as well as allowing for a measurement of the syndrome to be inferred. """ for log in ['0', '1']: self.circuit[log].add_register(self.code_bit) self.circuit[log].measure(self.code_qubit, self.code_bit)
[docs] def process_results(self, raw_results): """ Args: raw_results (dict): A dictionary whose keys are logical values, and whose values are standard counts dictionaries, (as obtained from the `get_counts` method of a ``qiskit.Result`` object). Returns: results: Dictionary with the same structure as the input, but with the bit strings used as keys in the counts dictionaries converted to the form required by the decoder. Additional information: The circuits must be executed outside of this class, so that their is full freedom to compile, choose a backend, use a noise model, etc. The results from these executions should then be used to create the input for this method. """ results = {} for log in raw_results: results[log] = {} for string in raw_results[log]: # logical readout taken from measured_log = string[0] + ' ' + string[self.d - 1] # final syndrome deduced from final code qubit readout full_syndrome = '' for j in range(self.d - 1): full_syndrome += '0' * (string[j] == string[j + 1]) \ + '1' * (string[j] != string[j + 1]) # results from all other syndrome measurements then added full_syndrome = full_syndrome + string[self.d:] # changes between one syndrome and the next then calculated syndrome_list = full_syndrome.split(' ') syndrome_changes = '' for t in range(self.T + 1): for j in range(self.d - 1): if t == 0: change = (syndrome_list[-1][j] != '0') else: change = (syndrome_list[-t][j] != syndrome_list[-t - 1][j]) syndrome_changes += '0' * (not change) + '1' * change syndrome_changes += ' ' # the space separated string of syndrome changes then gets a # double space separated logical value on the end new_string = measured_log + ' ' + syndrome_changes[:-1] results[log][new_string] = raw_results[log][string] return results