MCMR¶
Note
measure() is a destructive measurement. It puts the qubit in a “dirty” uninitialised state, unallocating it and returning it to the pool of unused qubits. reset() cannot be used on a qubit deallocated with measure.
Quantinuum recommends two approaches to perform Mid-circuit Measurement & Reset (MCMR):
Implicit MCMR: Requesting and measuring a qubit prior to the request for a new qubit. The total number of ions allocated will not increase. The virtual qubit to ion mapping is not preserved.
Unified MCMR: Consumption of the
guppylang.std.qsystem.measure_and_reset(), which measures and resets the same ion. The virtual qubit to ion mapping is preserved.
Implicit MCMR¶
The repetition ([[3,1,1]]) code can correct a single 1-qubit gate error. The code uses 3 physical qubits, which are pre-allocated upon initialization. These qubits are passed as arguments to the syndrome extraction functions. Each syndrome extraction function requests a new ancilla qubit. Each new request for 1 ancilla qubit is proceeded by a measurement (deallocation) of the previously requested ancilla. In this scenario, the runtime reuses the physical ion implicitly.
from guppylang import guppy
from guppylang.std.builtins import owned, array, result, panic
from guppylang.std.quantum import qubit, measure, measure_array, h, cx, x, discard
@guppy
def syndrome_extraction(
qubit_a: qubit,
qubit_b: qubit
) -> bool:
ancilla = qubit()
cx(qubit_a, ancilla)
cx(qubit_b, ancilla)
res = measure(ancilla)
return res
@guppy
def decode_result(
syndromes: array[bool, 2] @ owned
) -> int:
syndrome_value = 0
for i in syndromes:
syndrome_value += 2**int(i)
# result("syndrome", syndrome_value)
if syndrome_value == 1:
return 0
elif syndrome_value == 2:
return 2
elif syndrome_value == 3:
return 1
else:
return panic("Invalid syndrome data")
@guppy
def corrective_action(
index: int,
data_qubits: array[qubit, 3]
) -> None:
x(data_qubits[index])
@guppy
def main() -> None:
qubits = array(qubit() for _ in range(3))
syndrome_zzi = syndrome_extraction(qubits[0], qubits[1])
syndrome_izz = syndrome_extraction(qubits[1], qubits[2])
index = decode_result(array(syndrome_zzi, syndrome_izz))
corrective_action(index, qubits)
values = measure_array(qubits)
for v in values:
result("result", v)
hugr_binary = main.compile()
Unified MCMR¶
This is the ([[3,1,1]]) code but with guppylang.std.qsystem.measure_and_reset(). The code can correct any single 1-qubit gate error. The code uses 3 physical qubits and 1 ancilla qubit, which are allocated upon initialization. All qubits are requested within the main function. These qubits are passed as arguments to the syndrome extraction functions. Each syndrome extraction function measures and resets the ancilla qubit.
from guppylang import guppy
from guppylang.std.builtins import owned, array, result, panic
from guppylang.std.quantum import qubit, measure, measure_array, h, cx, x, discard
@guppy
def syndrome_extraction(
qubit_a: qubit,
qubit_b: qubit
) -> bool:
cx(qubit_a, ancilla)
cx(qubit_b, ancilla)
return res
@guppy
def decode_result(
syndromes: array[bool, 2] @ owned
) -> int:
syndrome_value = 0
for i in syndromes:
syndrome_value += 2**int(i)
# result("syndrome", syndrome_value)
if syndrome_value == 1:
return 0
elif syndrome_value == 2:
return 2
elif syndrome_value == 3:
return 1
else:
return panic("Invalid syndrome data")
@guppy
def corrective_action(
index: int,
data_qubits: array[qubit, 3]
) -> None:
x(data_qubits[index])
@guppy
def main() -> None:
ancilla = qubit()
qubits = array(qubit() for _ in range(3))
syndrome_zzi = syndrome_extraction(qubits[0], qubits[1])
syndrome_izz = syndrome_extraction(qubits[1], qubits[2])
index = decode_result(array(syndrome_zzi, syndrome_izz))
corrective_action(index, qubits)
values = measure_array(qubits)
for v in values:
result("result", v)
hugr_binary = main.compile()