microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
samples/algorithms/BitFlipCode.qs
128lines · modecode
| 1 | /// # Sample |
| 2 | /// Bit-Flip Code |
| 3 | /// |
| 4 | /// # Description |
| 5 | /// This sample demonstrates the three-qubit bit-flip code. This code is a |
| 6 | /// simple quantum error correction strategy for protecting against a single |
| 7 | /// bit-flip error by encoding a logical qubit into three physical qubits. A |
| 8 | /// single bit-flip error is when one of the three physical qubits has its |
| 9 | /// state changed erroneously in a way that is equivalent to applying the X |
| 10 | /// gate to it. |
| 11 | /// |
| 12 | /// The bit-flip correction code works by checking the parity of the physical |
| 13 | /// qubits. By measuring only their parity, the quantum superposition of the |
| 14 | /// qubits is preserved. Because all the physical qubits are supposed to have |
| 15 | /// the same state, when the parity checks detect a difference in state, the |
| 16 | /// erroneous qubit can be identified and corrected. |
| 17 | /// |
| 18 | /// This Q# program prepares a logical qubit encoded as three physical qubits |
| 19 | /// with one of the qubits being bit-flipped. It then identifies and corrects |
| 20 | /// the flipped qubit. |
| 21 | import Std.Math.*; |
| 22 | import Std.Diagnostics.*; |
| 23 | |
| 24 | operation Main() : Result { |
| 25 | use logicalQubit = Qubit[3]; |
| 26 | |
| 27 | // Set the initial state of the first physical qubit. |
| 28 | SetSampleState(logicalQubit[0]); |
| 29 | |
| 30 | // Using two additional qubits, encode the first physical qubit into a |
| 31 | // logical qubit. |
| 32 | EncodeAsLogicalQubit(logicalQubit[0], logicalQubit[1...]); |
| 33 | |
| 34 | // Induce a bit-flip error on the second qubit. |
| 35 | X(logicalQubit[1]); |
| 36 | |
| 37 | // Show the logical qubit with the error state. |
| 38 | DumpMachine(); |
| 39 | |
| 40 | // Find and correct the bit-flip error. |
| 41 | CorrectError(logicalQubit); |
| 42 | |
| 43 | // Show the logical qubit with the corrected state. |
| 44 | DumpMachine(); |
| 45 | |
| 46 | // Decode the logical qubit back into a single physical qubit. |
| 47 | Adjoint EncodeAsLogicalQubit(logicalQubit[0], logicalQubit[1...]); |
| 48 | |
| 49 | // Measure and reset the physical qubit before releasing it. |
| 50 | let result = M(logicalQubit[0]); |
| 51 | Reset(logicalQubit[0]); |
| 52 | return result; |
| 53 | } |
| 54 | |
| 55 | /// # Summary |
| 56 | /// This operation sets the state of the given qubit such that |
| 57 | /// it will have a 20% likelihood of resulting in a `Zero` and |
| 58 | /// 80% likelihood of resulting in a `One` when measured in the |
| 59 | /// computational basis. The input qubit is expected to be in |
| 60 | /// the |0〉 state. |
| 61 | /// |
| 62 | /// # Input |
| 63 | /// ## q |
| 64 | /// The given qubit to be put into superposition. It is assumed that this |
| 65 | /// qubit is in its default |0〉 state. |
| 66 | operation SetSampleState(q : Qubit) : Unit { |
| 67 | let alpha = 0.20; |
| 68 | Ry(2.0 * ArcCos(Sqrt(alpha)), q); |
| 69 | } |
| 70 | |
| 71 | /// # Summary |
| 72 | /// This operation takes the given `physicalQubit` state, |
| 73 | /// (α|0〉 + β|1〉) / √2, and encodes it in the `aux` qubits. This |
| 74 | /// encodes all the qubits into a single logical qubit whose state reflects |
| 75 | /// the state of the given `physicalQubit`: (α|000〉 + β|111〉) / √2. |
| 76 | /// |
| 77 | /// # Input |
| 78 | /// ## physicalQubit |
| 79 | /// The qubit whose state, (α|0〉 + β|1〉) / √2, is to be encoded in the |
| 80 | /// logical qubit. |
| 81 | /// |
| 82 | /// ## aux |
| 83 | /// The auxiliary qubits that will be used as part of the encoding. These |
| 84 | /// should be grouped with the `physicalQubit` to form the logical qubit. |
| 85 | operation EncodeAsLogicalQubit(physicalQubit : Qubit, aux : Qubit[]) : Unit is Adj { |
| 86 | ApplyToEachA(CNOT(physicalQubit, _), aux); |
| 87 | } |
| 88 | |
| 89 | /// # Summary |
| 90 | /// This operation detects and corrects a single bit-flip error for a logical |
| 91 | /// qubit encoded as three physical qubits. When finished, the given register |
| 92 | /// of qubits will be in the state: (α|000〉 + β|111〉) / √2. |
| 93 | /// |
| 94 | /// # Input |
| 95 | /// ## logicalQubit |
| 96 | /// The given register of three physical qubits representing a single logical qubit |
| 97 | /// having superposition (α|0〉 + β|1〉) / √2. |
| 98 | /// This logical qubit can have up to one bit-flip error that will be corrected. |
| 99 | operation CorrectError(logicalQubit : Qubit[]) : Unit { |
| 100 | Fact(Length(logicalQubit) == 3, "`logicalQubit` must be length 3"); |
| 101 | |
| 102 | // Entangle the parity of the physical qubits into two auxiliary qubits. |
| 103 | use aux = Qubit[2]; |
| 104 | CNOT(logicalQubit[0], aux[0]); |
| 105 | CNOT(logicalQubit[1], aux[0]); |
| 106 | CNOT(logicalQubit[1], aux[1]); |
| 107 | CNOT(logicalQubit[2], aux[1]); |
| 108 | |
| 109 | // Measure the parity information from the auxiliary qubits. |
| 110 | let (parity01, parity12) = (M(aux[0]), M(aux[1])); |
| 111 | ResetAll(aux); |
| 112 | |
| 113 | // Determine which of the three qubits has the error based on the |
| 114 | // parity measurements. |
| 115 | if parity01 == One { |
| 116 | if parity12 == One { |
| 117 | X(logicalQubit[1]); |
| 118 | } else { |
| 119 | X(logicalQubit[0]); |
| 120 | } |
| 121 | } else { |
| 122 | if parity12 == One { |
| 123 | X(logicalQubit[2]); |
| 124 | } else { |
| 125 | // No error was detected. |
| 126 | } |
| 127 | } |
| 128 | } |
| 129 | |