1
$\begingroup$

If I were interested in modeling qubit leakage errors using stim, how should I go about this? There are two scenarios of interest:

  1. Any leaked population can be treated as lost, until I reset the qubit. This applies to both data and ancilla qubits. When a qubit goes into the leakage subspace, any CZ gate becomes identity on both qubits.
  2. Leaked population can come back, or can hop around.

For the specific simulation I have in mind, the first might suffice, so if there is a simple workaround just for that case that would also be great.

$\endgroup$

1 Answer 1

1
$\begingroup$

Unfortunately, stim's circuit format doesn't have good capability for sampling time correlated errors like leakage. You will have to use the tableau simulator and track the leakage yourself.

For example, suppose that every CZ has a small chance of causing or spreading leakage and that when a CZ involves a leaked qubit the noise experienced by that CZ is much higher. Here's an example of what that might look like (this is NOT physically motivated it's just an example):

import random
from typing import List

import stim

def do_leakage_simulation(circuit: stim.Circuit) -> List[bool]:
    leakage_chance = 0.001
    leakage_decay_chance = 0.005
    leakage_spread_chance = 0.1
    depolarization_error_during_leaky_cz = 0.05

    circuit = circuit.flattened()  # unroll loops so we don't have to deal with them

    simulator = stim.TableauSimulator()
    leaked_qubits = set()
    for k in range(len(circuit)):
        instruction = circuit[k]
        sub_circuit = circuit[k:k+1]
        if instruction.name == "CZ":
            ts = instruction.targets_copy()
            for i in range(0, len(ts), 2):
                q0 = ts[i].value
                q1 = ts[i + 1].value
                # Leakage spreads over CZs, and can also spontaneously appear.
                if random.random() < leakage_chance or (q0 in leaked_qubits or q1 in leaked_qubits and random.random() < leakage_spread_chance):
                    leaked_qubits.add(q0)
                    leaked_qubits.add(q1)
                    sub_circuit.append("DEPOLARIZE2", [q0, q1], depolarization_error_during_leaky_cz)

        elif instruction.name in ["RX", "RY", "R", "MR", "MRX", "MRY"]:
            # Reset qubits are no longer leaked.
            leaked_qubits -= {t.value for t in instruction.targets_copy()}


        elif instruction.name == "TICK":
            # Leaked qubits can decay as time passes. (This requires the circuit to annotate TICKs appropriately!)
            leaked_qubits = {
                q for q in leaked_qubits if random.random() >= leakage_decay_chance
            }

        simulator.do_circuit(sub_circuit)

    return simulator.current_measurement_record()


def main():
    result = do_leakage_simulation(stim.Circuit("""
        REPEAT 50 {
            CZ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
            TICK
            CZ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
            TICK
            M 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
            TICK
        }
    """))
    for step in range(0, len(result), 20):
        print("".join("_!"[e] for e in result[step:step+20]))


if __name__ == '__main__':
    main()

Run this a few times and you'll see an output like this where leakage errors occurred:

____________________
____________________
____________________
____________________
__________!_________
__________!_________
__________!_________
__________!_________
_________!!____!____
_________!!____!____
_________!!____!____
_________!!____!____
_________!!____!____
_________!!____!__!_
_________!!___!!__!_
_________!!___!!__!_
______________!!__!_
______________!!__!_
______________!!__!_
______________!!__!_
______________!!__!_
______________!!!_!_
______________!!!_!_
______________!!!_!_
______________!!!_!_
______________!!!_!_
______________!!!_!_
_____________!!!!_!_
_____________!!!!_!_
_____________!!!!_!_
___________!_!____!_
___________!_!____!_
__________!__!____!_
_________!!__!____!_
_________!!__!____!_
__________!__!____!_
__________!__!____!_
_____!____!__!____!_
_____!____!__!____!_
_____!_!_____!____!_
_____!_!!____!____!_
_____!_!!__!______!_
_____!!!!!_!______!_
_____!!!!!_!______!_
_____!!!!!_!!!____!_
_____!!!!!_!!!_____!
_____!!!!_!!!!_____!
_____!!!!_!!!___!__!
_____!__!_!!!_!_!__!
_____!_!__!!!_!_!__!
$\endgroup$
2
  • $\begingroup$ Hi Craig, do you have any thoughts on decoding syndrome from leakage error which causes CZ gates to becomes identity? $\endgroup$ Nov 9, 2023 at 1:16
  • $\begingroup$ @JiakaiWang Conditionally removing Clifford gates makes bulk sampling much more expensive (this is why stim bans it), so such simulations are notably more complex. $\endgroup$ Nov 9, 2023 at 3:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.