Skip to content

Model

MoveNoiseModelABC dataclass

MoveNoiseModelABC(
    *,
    local_px: float = 0.0004102,
    local_py: float = 0.0004102,
    local_pz: float = 0.0004112,
    local_loss_prob: float = 0.0,
    local_unaddressed_px: float = 2e-07,
    local_unaddressed_py: float = 2e-07,
    local_unaddressed_pz: float = 1.2e-06,
    local_unaddressed_loss_prob: float = 0.0,
    global_px: float = 6.5e-05,
    global_py: float = 6.5e-05,
    global_pz: float = 6.5e-05,
    global_loss_prob: float = 0.0,
    cz_paired_gate_px: float = 0.0006549,
    cz_paired_gate_py: float = 0.0006549,
    cz_paired_gate_pz: float = 0.003184,
    cz_gate_loss_prob: float = 0.0,
    cz_unpaired_gate_px: float = 0.0005149,
    cz_unpaired_gate_py: float = 0.0005149,
    cz_unpaired_gate_pz: float = 0.002185,
    cz_unpaired_loss_prob: float = 0.0,
    mover_px: float = 0.000806,
    mover_py: float = 0.000806,
    mover_pz: float = 0.002458,
    move_loss_prob: float = 0.0,
    sitter_px: float = 0.0003066,
    sitter_py: float = 0.0003066,
    sitter_pz: float = 0.0004639,
    sit_loss_prob: float = 0.0
)

Bases: ABC

Abstract base class for noise based on atom movement.

This class defines the interface for a noise model. The gate noise is calculated from the parameters provided in this dataclass which can be updated when inheriting from this class. The move error is calculated by implementing the parallel_cz_errors method which takes a set of ctrl and qarg qubits and returns a noise model for all the qubits. The noise model is a dictionary with the keys being the error rates for the qubits and the values being the list of qubits that the error rate applies to.

Once implemented the class can be used with the NoisePass to analyze a circuit and apply the noise model to the circuit.

NOTE: This model is not guaranteed to be supported long-term in bloqade. We will be moving towards a more general approach to noise modeling in the future.

cz_gate_loss_prob class-attribute instance-attribute

cz_gate_loss_prob: float = field(default=0.0, kw_only=True)

The error probability for a loss during CZ gate operation when two qubits are within blockade radius.

cz_paired_errors property

cz_paired_errors: tuple[float, float, float, float]

Returns the error rates for a CZ gate.

cz_paired_gate_px class-attribute instance-attribute

cz_paired_gate_px: float = field(
    default=0.0006549, kw_only=True
)

The error probability for a Pauli-X error during CZ gate operation when two qubits are within blockade radius.

cz_paired_gate_py class-attribute instance-attribute

cz_paired_gate_py: float = field(
    default=0.0006549, kw_only=True
)

The error probability for a Pauli-Y error during CZ gate operation when two qubits are within blockade radius.

cz_paired_gate_pz class-attribute instance-attribute

cz_paired_gate_pz: float = field(
    default=0.003184, kw_only=True
)

The error probability for a Pauli-Z error during CZ gate operation when two qubits are within blockade radius.

cz_unpaired_errors property

cz_unpaired_errors: tuple[float, float, float, float]

Returns the error rates for a CZ gate.

cz_unpaired_gate_px class-attribute instance-attribute

cz_unpaired_gate_px: float = field(
    default=0.0005149, kw_only=True
)

The error probability for Pauli-X error during CZ gate operation when another qubit is not within blockade radius.

cz_unpaired_gate_py class-attribute instance-attribute

cz_unpaired_gate_py: float = field(
    default=0.0005149, kw_only=True
)

The error probability for Pauli-Y error during CZ gate operation when another qubit is not within blockade radius.

cz_unpaired_gate_pz class-attribute instance-attribute

cz_unpaired_gate_pz: float = field(
    default=0.002185, kw_only=True
)

The error probability for Pauli-Z error during CZ gate operation when another qubit is not within blockade radius.

cz_unpaired_loss_prob class-attribute instance-attribute

cz_unpaired_loss_prob: float = field(
    default=0.0, kw_only=True
)

The error probability for a loss during CZ gate operation when another qubit is not within blockade radius.

global_errors property

global_errors: tuple[float, float, float, float]

Returns the error rates for a global single qubit gate.

global_loss_prob class-attribute instance-attribute

global_loss_prob: float = field(default=0.0, kw_only=True)

The error probability for a loss during a global single qubit gate operation.

global_px class-attribute instance-attribute

global_px: float = field(default=6.5e-05, kw_only=True)

The error probability for a Pauli-X error during a global single qubit gate operation.

global_py class-attribute instance-attribute

global_py: float = field(default=6.5e-05, kw_only=True)

The error probability for a Pauli-Y error during a global single qubit gate operation.

global_pz class-attribute instance-attribute

global_pz: float = field(default=6.5e-05, kw_only=True)

The error probability for a Pauli-Z error during a global single qubit gate operation.

local_errors property

local_errors: tuple[float, float, float, float]

Returns the error rates for a local single qubit gate.

local_loss_prob class-attribute instance-attribute

local_loss_prob: float = field(default=0.0, kw_only=True)

The error probability for a loss during a local single qubit gate operation.

local_px class-attribute instance-attribute

local_px: float = field(default=0.0004102, kw_only=True)

The error probability for a Pauli-X error during a local single qubit gate operation.

local_py class-attribute instance-attribute

local_py: float = field(default=0.0004102, kw_only=True)

The error probability for a Pauli-Y error during a local single qubit gate operation.

local_pz class-attribute instance-attribute

local_pz: float = field(default=0.0004112, kw_only=True)

The error probability for a Pauli-Z error during a local single qubit gate operation.

local_unaddressed_errors property

local_unaddressed_errors: tuple[float, float, float, float]

Returns the error rates for a local single qubit gate.

local_unaddressed_loss_prob class-attribute instance-attribute

local_unaddressed_loss_prob: float = field(
    default=0.0, kw_only=True
)

The error probability for a loss during a local single qubit gate operation when the qubit is not addressed.

local_unaddressed_px class-attribute instance-attribute

local_unaddressed_px: float = field(
    default=2e-07, kw_only=True
)

The error probability for a Pauli-X error during a local single qubit gate operation when the qubit is not addressed.

local_unaddressed_py class-attribute instance-attribute

local_unaddressed_py: float = field(
    default=2e-07, kw_only=True
)

The error probability for a Pauli-Y error during a local single qubit gate operation when the qubit is not addressed.

local_unaddressed_pz class-attribute instance-attribute

local_unaddressed_pz: float = field(
    default=1.2e-06, kw_only=True
)

The error probability for a Pauli-Z error during a local single qubit gate operation when the qubit is not addressed.

move_loss_prob class-attribute instance-attribute

move_loss_prob: float = field(default=0.0, kw_only=True)

Probability of loss occurring on a moving qubit during a move operation

mover_px class-attribute instance-attribute

mover_px: float = field(default=0.000806, kw_only=True)

Probability of X error occurring on a moving qubit during a move operation

mover_py class-attribute instance-attribute

mover_py: float = field(default=0.000806, kw_only=True)

Probability of Y error occurring on a moving qubit during a move operation

mover_pz class-attribute instance-attribute

mover_pz: float = field(default=0.002458, kw_only=True)

Probability of Z error occurring on a moving qubit during a move operation

sit_loss_prob class-attribute instance-attribute

sit_loss_prob: float = field(default=0.0, kw_only=True)

Probability of loss occurring on a stationary qubit during a move operation

sitter_errors property

sitter_errors: tuple[float, float, float, float]

Returns the error rates for a move operation.

sitter_px class-attribute instance-attribute

sitter_px: float = field(default=0.0003066, kw_only=True)

Probability of X error occurring on a stationary qubit during a move operation

sitter_py class-attribute instance-attribute

sitter_py: float = field(default=0.0003066, kw_only=True)

Probability of Y error occurring on a stationary qubit during a move operation

sitter_pz class-attribute instance-attribute

sitter_pz: float = field(default=0.0004639, kw_only=True)

Probability of Z error occurring on a stationary qubit during a move operation

join_binary_probs classmethod

join_binary_probs(p1: float, *args: float) -> float

Merge the probabilities of an event happening if the event can only happen once.

For example, finding the effective probability of losing an atom from multiple sources, since a qubit can only be lost once. This is done by using the formula:

p = p1 * (1 - p2) + p2 * (1 - p1)

applied recursively to all the probabilities in the list.

Parameters:

Name Type Description Default
p1 float

The probability of the event happening.

required
arg float

The probabilities of the event happening from other sources.

required

Returns:

Name Type Description
float float

The effective probability of the event happening.

Source code in .venv/lib/python3.12/site-packages/bloqade/qasm2/dialects/noise/model.py
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
@classmethod
def join_binary_probs(cls, p1: float, *args: float) -> float:
    """Merge the probabilities of an event happening if the event can only happen once.

    For example, finding the effective probability of losing an atom from multiple sources, since
    a qubit can only be lost once. This is done by using the formula:

    p = p1 * (1 - p2) + p2 * (1 - p1)

    applied recursively to all the probabilities in the list.

    Args:
        p1 (float): The probability of the event happening.
        arg (float): The probabilities of the event happening from other sources.

    Returns:
        float: The effective probability of the event happening.

    """
    if len(args) == 0:
        return p1
    else:
        p2 = cls.join_binary_probs(*args)
        return p1 * (1 - p2) + p2 * (1 - p1)

parallel_cz_errors abstractmethod

parallel_cz_errors(
    ctrls: list[int], qargs: list[int], rest: list[int]
) -> dict[tuple[float, float, float, float], list[int]]

Takes a set of ctrls and qargs and returns a noise model for all qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/qasm2/dialects/noise/model.py
162
163
164
165
166
167
@abc.abstractmethod
def parallel_cz_errors(
    self, ctrls: list[int], qargs: list[int], rest: list[int]
) -> dict[tuple[float, float, float, float], list[int]]:
    """Takes a set of ctrls and qargs and returns a noise model for all qubits."""
    pass

TwoRowZoneModel dataclass

TwoRowZoneModel(
    *,
    local_px: float = 0.0004102,
    local_py: float = 0.0004102,
    local_pz: float = 0.0004112,
    local_loss_prob: float = 0.0,
    local_unaddressed_px: float = 2e-07,
    local_unaddressed_py: float = 2e-07,
    local_unaddressed_pz: float = 1.2e-06,
    local_unaddressed_loss_prob: float = 0.0,
    global_px: float = 6.5e-05,
    global_py: float = 6.5e-05,
    global_pz: float = 6.5e-05,
    global_loss_prob: float = 0.0,
    cz_paired_gate_px: float = 0.0006549,
    cz_paired_gate_py: float = 0.0006549,
    cz_paired_gate_pz: float = 0.003184,
    cz_gate_loss_prob: float = 0.0,
    cz_unpaired_gate_px: float = 0.0005149,
    cz_unpaired_gate_py: float = 0.0005149,
    cz_unpaired_gate_pz: float = 0.002185,
    cz_unpaired_loss_prob: float = 0.0,
    mover_px: float = 0.000806,
    mover_py: float = 0.000806,
    mover_pz: float = 0.002458,
    move_loss_prob: float = 0.0,
    sitter_px: float = 0.0003066,
    sitter_py: float = 0.0003066,
    sitter_pz: float = 0.0004639,
    sit_loss_prob: float = 0.0
)

Bases: MoveNoiseModelABC

This model assumes that the qubits are arranged in a single storage row with a row corresponding to a gate zone below it.

The CZ gate noise is calculated using the following heuristic: The idle error is calculated by the total duration required to do the move and entangle the qubits. Not every pair can be entangled at the same time, so we first deconflict the qargs by finding subsets in which both the ctrl and the qarg qubits are in ascending order. This breaks the pairs into groups that can be moved and entangled separately. We then take each group and assign each pair to a gate zone slot. The slots are allocated by starting from the middle of the atoms and moving outwards making sure to keep the ctrl qubits in ascending order. The time to move a group is calculated by finding the maximum travel distance of the qarg and ctrl qubits and dviding by the move speed. The total move time is the sum of all the group move times. The error rate for all the qubits is then calculated by using the poisson_pauli_prob function. An additional error for the pick operation is calculated by joining the binary probabilities of the pick operation and the move operation.

move_errors property

move_errors: tuple[float, float, float, float]

Returns the error rates for a move operation.

deconflict

deconflict(
    ctrls: list[int], qargs: list[int]
) -> list[tuple[tuple[int, ...], tuple[int, ...]]]

Return a list of groups of ctrl and qarg qubits that can be moved and entangled separately.

Source code in .venv/lib/python3.12/site-packages/bloqade/qasm2/dialects/noise/model.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
def deconflict(
    self, ctrls: list[int], qargs: list[int]
) -> list[tuple[tuple[int, ...], tuple[int, ...]]]:
    """Return a list of groups of ctrl and qarg qubits that can be moved and entangled separately."""
    # sort by ctrl qubit first to guarantee that they will be in ascending order
    sorted_pairs = sorted(zip(ctrls, qargs))

    groups: list[list[tuple[int, int]]] = []
    # group by qarg only putting it in a group if the qarg is greater than the last qarg in the group
    # thus ensuring that the qargs are in ascending order
    while len(sorted_pairs) > 0:
        ctrl, qarg = sorted_pairs.pop(0)

        found = False
        for group in groups:
            if group[-1][1] < qarg:
                group.append((ctrl, qarg))
                found = True
                break
        if not found:
            groups.append([(ctrl, qarg)])

    new_groups: list[tuple[tuple[int, ...], tuple[int, ...]]] = []

    for group in groups:
        ctrl, qarg = zip(*group)
        ctrl = tuple(ctrl)
        qarg = tuple(qarg)
        new_groups.append((ctrl, qarg))

    return new_groups

parallel_cz_errors

parallel_cz_errors(
    ctrls: list[int], qargs: list[int], rest: list[int]
) -> dict[tuple[float, float, float, float], list[int]]

Apply parallel gates by moving ctrl qubits to qarg qubits.

Source code in .venv/lib/python3.12/site-packages/bloqade/qasm2/dialects/noise/model.py
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
def parallel_cz_errors(
    self, ctrls: list[int], qargs: list[int], rest: list[int]
) -> dict[tuple[float, float, float, float], list[int]]:
    """Apply parallel gates by moving ctrl qubits to qarg qubits."""
    groups = self.deconflict(ctrls, qargs)
    movers = ctrls + qargs
    num_moves = len(groups)
    # ignore order O(p^2) errors since they are small
    effective_move_errors = (
        self.move_errors[0] + self.sitter_errors[0] * (num_moves - 1),
        self.move_errors[1] + self.sitter_errors[1] * (num_moves - 1),
        self.move_errors[2] + self.sitter_errors[2] * (num_moves - 1),
        self.move_errors[3] + self.sitter_errors[3] * (num_moves - 1),
    )
    effective_sitter_errors = (
        self.sitter_errors[0] * num_moves,
        self.sitter_errors[1] * num_moves,
        self.sitter_errors[2] * num_moves,
        self.sitter_errors[3] * num_moves,
    )
    result = {effective_move_errors: list(movers)}
    result.setdefault(effective_sitter_errors, []).extend(rest)

    return result