-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A example of Qec using Shor's Code (#2922)
This is an example of using Shor's code to do quantum error correction and fault tolerant operations. There is a base class for one qubit code, which encodes one physical qubit with several ancilla qubits and some gates. The Shor's Code class will be derived from the base one qubit class. Then it's easy for us to add other codes in the future. There are multi-qubit codes that take in multiple physical qubits and call one qubit class for each of the input qubits. The class also takes in the original circuit of the original physical qubits and transforms it into fault-tolerate operations on the encoded circuits. The files are under examples/qec | __init__.py | | onequbit_qec.py | | multiqubit_qec.py | | shors_code.py | | fault_tolerate_operations.py | The tests are added to the end of existing examples_test.py
- Loading branch information
1 parent
656e388
commit 3e00896
Showing
3 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
""" Shor's code is a stabilizer code for quantum error correction. | ||
It uses 9 qubits to encode 1 logic qubit and is able to correct | ||
at most one bit flip and one sign flip or their combination. | ||
(0, 0): ───@───@───H───@───@───@───@───X───H───@───@───X───M─── | ||
│ │ │ │ │ │ │ │ │ │ | ||
(0, 1): ───┼───┼───────X───┼───X───┼───@───────┼───┼───┼───M─── | ||
│ │ │ │ │ │ │ │ | ||
(0, 2): ───┼───┼───────────X───────X───@───────┼───┼───┼───M─── | ||
│ │ │ │ │ | ||
(0, 3): ───X───┼───H───@───@───@───@───X───H───X───┼───@───M─── | ||
│ │ │ │ │ │ │ │ | ||
(0, 4): ───────┼───────X───┼───X───┼───@───────────┼───┼───M─── | ||
│ │ │ │ │ │ | ||
(0, 5): ───────┼───────────X───────X───@───────────┼───┼───M─── | ||
│ │ │ | ||
(0, 6): ───────X───H───@───@───@───@───X───H───────X───@───M─── | ||
│ │ │ │ │ | ||
(0, 7): ───────────────X───┼───X───┼───@───────────────────M─── | ||
│ │ │ | ||
(0, 8): ───────────────────X───────X───@───────────────────M─── | ||
reference: P. W. Shor, Phys. Rev. A, 52, R2493 (1995). | ||
""" | ||
|
||
import random | ||
|
||
import cirq | ||
|
||
|
||
class OneQubitShorsCode: | ||
|
||
def __init__(self): | ||
self.num_physical_qubits = 9 | ||
self.physical_qubits = cirq.LineQubit.range(self.num_physical_qubits) | ||
|
||
def encode(self): | ||
yield cirq.ops.Moment( | ||
[cirq.CNOT(self.physical_qubits[0], self.physical_qubits[3])]) | ||
yield cirq.ops.Moment( | ||
[cirq.CNOT(self.physical_qubits[0], self.physical_qubits[6])]) | ||
yield cirq.ops.Moment([ | ||
cirq.H(self.physical_qubits[0]), | ||
cirq.H(self.physical_qubits[3]), | ||
cirq.H(self.physical_qubits[6]) | ||
]) | ||
yield cirq.ops.Moment([ | ||
cirq.CNOT(self.physical_qubits[0], self.physical_qubits[1]), | ||
cirq.CNOT(self.physical_qubits[3], self.physical_qubits[4]), | ||
cirq.CNOT(self.physical_qubits[6], self.physical_qubits[7]) | ||
]) | ||
yield cirq.ops.Moment([ | ||
cirq.CNOT(self.physical_qubits[0], self.physical_qubits[2]), | ||
cirq.CNOT(self.physical_qubits[3], self.physical_qubits[5]), | ||
cirq.CNOT(self.physical_qubits[6], self.physical_qubits[8]) | ||
]) | ||
|
||
def apply_gate(self, gate: cirq.Gate, pos: int): | ||
if pos > self.num_physical_qubits: | ||
raise IndexError | ||
else: | ||
return gate(self.physical_qubits[pos]) | ||
|
||
def correct(self): | ||
yield cirq.ops.Moment([ | ||
cirq.CNOT(self.physical_qubits[0], self.physical_qubits[1]), | ||
cirq.CNOT(self.physical_qubits[3], self.physical_qubits[4]), | ||
cirq.CNOT(self.physical_qubits[6], self.physical_qubits[7]) | ||
]) | ||
yield cirq.ops.Moment([ | ||
cirq.CNOT(self.physical_qubits[0], self.physical_qubits[2]), | ||
cirq.CNOT(self.physical_qubits[3], self.physical_qubits[5]), | ||
cirq.CNOT(self.physical_qubits[6], self.physical_qubits[8]) | ||
]) | ||
yield cirq.ops.Moment([ | ||
cirq.CCNOT(self.physical_qubits[1], self.physical_qubits[2], | ||
self.physical_qubits[0]), | ||
cirq.CCNOT(self.physical_qubits[4], self.physical_qubits[5], | ||
self.physical_qubits[3]), | ||
cirq.CCNOT(self.physical_qubits[7], self.physical_qubits[8], | ||
self.physical_qubits[6]) | ||
]) | ||
yield cirq.ops.Moment([ | ||
cirq.H(self.physical_qubits[0]), | ||
cirq.H(self.physical_qubits[3]), | ||
cirq.H(self.physical_qubits[6]) | ||
]) | ||
yield cirq.ops.Moment( | ||
[cirq.CNOT(self.physical_qubits[0], self.physical_qubits[3])]) | ||
yield cirq.ops.Moment( | ||
[cirq.CNOT(self.physical_qubits[0], self.physical_qubits[6])]) | ||
yield cirq.ops.Moment([ | ||
cirq.CCNOT(self.physical_qubits[3], self.physical_qubits[6], | ||
self.physical_qubits[0]) | ||
]) | ||
|
||
|
||
if __name__ == '__main__': | ||
# coverage: ignore | ||
|
||
# create circuit with 9 physical qubits | ||
code = OneQubitShorsCode() | ||
|
||
circuit = cirq.Circuit(code.apply_gate(cirq.X**(1 / 4), 0)) | ||
print(cirq.dirac_notation(circuit.final_state_vector(initial_state=0))) | ||
|
||
circuit += cirq.Circuit(code.encode()) | ||
print(cirq.dirac_notation(circuit.final_state_vector(initial_state=0))) | ||
|
||
# create error | ||
circuit += cirq.Circuit( | ||
code.apply_gate(cirq.X, random.randint(0, | ||
code.num_physical_qubits - 1))) | ||
print(cirq.dirac_notation(circuit.final_state_vector(initial_state=0))) | ||
|
||
# correct error and decode | ||
circuit += cirq.Circuit(code.correct()) | ||
print(cirq.dirac_notation(circuit.final_state_vector(initial_state=0))) |