Skip to content

NoiseModel

Noise model for color code quantum circuits with dictionary-like access.

This class encapsulates all noise parameters used in color code circuits, providing a clean interface for setting.

Examples:

Uniform circuit-level noise model:

>>> noise = NoiseModel.uniform_circuit_noise(0.001)
>>> print(noise['cnot'])  # 0.001

Code capacity noise model (depolarizing noise on data qubits before each round):

>>> noise = NoiseModel(depol=0.01)

Bit-flip noise on data qubits before each round:

>>> noise = NoiseModel(bitflip=0.01)

Phenomenological noise model:

>>> noise = NoiseModel(depol=0.01, meas=0.01)

Noise model with specific parameters:

>>> noise = NoiseModel(cnot=0.002, idle=0.001, reset=0.005, meas=0.003)
Source code in src/color_code_stim/noise_model.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
class NoiseModel:
    """
    Noise model for color code quantum circuits with dictionary-like access.

    This class encapsulates all noise parameters used in color code circuits,
    providing a clean interface for setting.


    Examples
    --------
    Uniform circuit-level noise model:
    >>> noise = NoiseModel.uniform_circuit_noise(0.001)
    >>> print(noise['cnot'])  # 0.001

    Code capacity noise model (depolarizing noise on data qubits before each round):
    >>> noise = NoiseModel(depol=0.01)

    Bit-flip noise on data qubits before each round:
    >>> noise = NoiseModel(bitflip=0.01)

    Phenomenological noise model:
    >>> noise = NoiseModel(depol=0.01, meas=0.01)

    Noise model with specific parameters:
    >>> noise = NoiseModel(cnot=0.002, idle=0.001, reset=0.005, meas=0.003)
    """

    def __init__(
        self,
        bitflip: float = 0.0,
        depol: float = 0.0,
        reset: float = 0.0,
        meas: float = 0.0,
        cnot: float = 0.0,
        idle: float = 0.0,
        cult: Optional[float] = None,
        initial_data_qubit_depol: float = 0.0,
        depol1_after_cnot: float = 0.0,
        idle_during_cnot: Optional[float] = None,
        idle_during_meas: Optional[float] = None,
        reset_data: Optional[float] = None,
        reset_anc_X: Optional[float] = None,
        reset_anc_Z: Optional[float] = None,
        meas_data: Optional[float] = None,
        meas_anc_X: Optional[float] = None,
        meas_anc_Z: Optional[float] = None,
    ):
        """
        Initialize noise model with individual parameters.

        All parameters must be non-negative floats representing error rates.

        Parameters
        ----------
        bitflip : float, default 0.0
            Bit-flip noise rate on data qubits at the start of each round.
        depol : float, default 0.0
            Depolarizing noise rate on data qubits at the start of each round.
        reset : float, default 0.0
            Error rate for reset operations (producing orthogonal state).
        meas : float, default 0.0
            Error rate for measurement operations (flipped outcome).
        cnot : float, default 0.0
            Two-qubit depolarizing noise rate for CNOT gates.
        idle : float, default 0.0
            Single-qubit depolarizing noise rate for idle operations.
        cult : float, optional
            Physical error rate during cultivation (for cult+growing circuits).
            If not provided, defaults to cnot rate when needed.
        initial_data_qubit_depol : float, default 0.0
            Depolarizing noise rate applied to all data qubits after the first
            syndrome extraction round (if perfect_first_syndrome_extraction=True)
            or after data qubit initialization (if perfect_first_syndrome_extraction=False).
        depol1_after_cnot : float, default 0.0
            Single-qubit depolarizing noise rate applied to each qubit participating
            in CNOT gates after the gates are applied. If provided and positive,
            DEPOLARIZE1 is added for each qubit involved in the CNOT operations.
        idle_during_cnot : float, optional
            Single-qubit depolarizing noise rate for idle qubits during CNOT operations.
            If None (default), uses the idle parameter. If set to any value (including 0),
            overrides idle for qubits not participating in CNOT gates.
        idle_during_meas : float, optional
            Single-qubit depolarizing noise rate for idle qubits during measurement operations.
            If None (default), uses the idle parameter. If set to any value (including 0),
            overrides idle for qubits not participating in measurement operations.
        reset_data : float, optional
            Error rate for reset operations on data qubits (producing orthogonal state).
            If None (default), uses the reset parameter.
        reset_anc_X : float, optional
            Error rate for reset operations on X-type ancilla qubits (producing orthogonal state).
            If None (default), uses the reset parameter.
        reset_anc_Z : float, optional
            Error rate for reset operations on Z-type ancilla qubits (producing orthogonal state).
            If None (default), uses the reset parameter.
        meas_data : float, optional
            Error rate for measurement operations on data qubits (flipped outcome).
            If None (default), uses the meas parameter.
        meas_anc_X : float, optional
            Error rate for measurement operations on X-type ancilla qubits (flipped outcome).
            If None (default), uses the meas parameter.
        meas_anc_Z : float, optional
            Error rate for measurement operations on Z-type ancilla qubits (flipped outcome).
            If None (default), uses the meas parameter.
        """
        # Store parameters in internal dict for easy access
        self._params = {
            "bitflip": float(bitflip),
            "depol": float(depol),
            "reset": float(reset),
            "meas": float(meas),
            "cnot": float(cnot),
            "idle": float(idle),
            "initial_data_qubit_depol": float(initial_data_qubit_depol),
            "depol1_after_cnot": float(depol1_after_cnot),
        }

        # Handle special parameters that can be None
        if cult is not None:
            self._params["cult"] = float(cult)
        else:
            self._params["cult"] = None

        if idle_during_cnot is not None:
            self._params["idle_during_cnot"] = float(idle_during_cnot)
        else:
            self._params["idle_during_cnot"] = None

        if idle_during_meas is not None:
            self._params["idle_during_meas"] = float(idle_during_meas)
        else:
            self._params["idle_during_meas"] = None

        # Handle granular reset parameters that can be None
        if reset_data is not None:
            self._params["reset_data"] = float(reset_data)
        else:
            self._params["reset_data"] = None

        if reset_anc_X is not None:
            self._params["reset_anc_X"] = float(reset_anc_X)
        else:
            self._params["reset_anc_X"] = None

        if reset_anc_Z is not None:
            self._params["reset_anc_Z"] = float(reset_anc_Z)
        else:
            self._params["reset_anc_Z"] = None

        # Handle granular measurement parameters that can be None
        if meas_data is not None:
            self._params["meas_data"] = float(meas_data)
        else:
            self._params["meas_data"] = None

        if meas_anc_X is not None:
            self._params["meas_anc_X"] = float(meas_anc_X)
        else:
            self._params["meas_anc_X"] = None

        if meas_anc_Z is not None:
            self._params["meas_anc_Z"] = float(meas_anc_Z)
        else:
            self._params["meas_anc_Z"] = None

        # Validate all parameters
        self.validate()

    @classmethod
    def uniform_circuit_noise(cls, p_circuit: float) -> Self:
        """
        Create noise model with uniform circuit-level noise. Equivalent to:
        >>> NoiseModel(reset=p_circuit, meas=p_circuit, cnot=p_circuit, idle=p_circuit)

        Parameters
        ----------
        p_circuit : float
            Circuit-level error rate to apply uniformly.

        Returns
        -------
        NoiseModel
            New noise model with uniform rates.
        """
        return cls(
            bitflip=0.0,  # Not included in circuit-level noise
            depol=0.0,  # Not included in circuit-level noise
            reset=p_circuit,
            meas=p_circuit,
            cnot=p_circuit,
            idle=p_circuit,
            cult=None,  # Will default to cnot when needed
            initial_data_qubit_depol=0.0,  # Not included in circuit-level noise
            depol1_after_cnot=0.0,  # Not included in circuit-level noise
            idle_during_cnot=None,  # Not included in circuit-level noise
            idle_during_meas=None,  # Not included in circuit-level noise
            reset_data=None,  # Will default to reset when needed
            reset_anc_X=None,  # Will default to reset when needed
            reset_anc_Z=None,  # Will default to reset when needed
            meas_data=None,  # Will default to meas when needed
            meas_anc_X=None,  # Will default to meas when needed
            meas_anc_Z=None,  # Will default to meas when needed
        )

    def __getitem__(self, key: str) -> float:
        """
        Enable dictionary-like access: noise_model['depol'].

        Parameters
        ----------
        key : str
            Parameter name to retrieve.

        Returns
        -------
        float
            Parameter value.

        Raises
        ------
        KeyError
            If parameter name is not recognized.
        """
        if key not in self._params:
            valid_keys = list(self._params.keys())
            raise KeyError(
                f"Unknown noise parameter '{key}'. Valid parameters: {valid_keys}"
            )

        # Handle special cases of parameters that can fallback to other parameters
        value = self._params[key]
        if key == "cult" and value is None:
            # Default cult to cnot rate if not explicitly set
            return self._params["cnot"]
        elif key == "idle_during_cnot" and value is None:
            # Default idle_during_cnot to idle rate if not explicitly set
            return self._params["idle"]
        elif key == "idle_during_meas" and value is None:
            # Default idle_during_meas to idle rate if not explicitly set
            return self._params["idle"]
        # Handle granular reset parameters fallback to base reset
        elif key == "reset_data" and value is None:
            return self._params["reset"]
        elif key == "reset_anc_X" and value is None:
            return self._params["reset"]
        elif key == "reset_anc_Z" and value is None:
            return self._params["reset"]
        # Handle granular measurement parameters fallback to base meas
        elif key == "meas_data" and value is None:
            return self._params["meas"]
        elif key == "meas_anc_X" and value is None:
            return self._params["meas"]
        elif key == "meas_anc_Z" and value is None:
            return self._params["meas"]

        return value

    def __setitem__(self, key: str, value: Optional[float]) -> None:
        """
        Enable dictionary-like assignment: noise_model['depol'] = 0.01.

        Parameters
        ----------
        key : str
            Parameter name to set.
        value : float or None
            Parameter value to assign. None is allowed for certain parameters.

        Raises
        ------
        KeyError
            If parameter name is not recognized.
        ValueError
            If value is negative.
        """
        if key not in self._params:
            valid_keys = list(self._params.keys())
            raise KeyError(
                f"Unknown noise parameter '{key}'. Valid parameters: {valid_keys}"
            )

        # Handle None values for special parameters
        if value is None:
            if key in {
                "cult",
                "idle_during_cnot",
                "idle_during_meas",
                "reset_data",
                "reset_anc_X",
                "reset_anc_Z",
                "meas_data",
                "meas_anc_X",
                "meas_anc_Z",
            }:
                self._params[key] = None
                return
            else:
                raise ValueError(
                    f"Noise parameter '{key}' cannot be None. "
                    f"Only 'cult', 'idle_during_cnot', 'idle_during_meas', "
                    f"and granular reset/measurement parameters can be None."
                )

        # Convert to float and validate
        float_value = float(value)
        if float_value < 0:
            raise ValueError(
                f"Noise parameter '{key}' must be non-negative, got {float_value}"
            )

        # Special handling for special parameters
        if key == "cult":
            self._params[key] = float_value if float_value > 0 else None
        elif key in {"idle_during_cnot", "idle_during_meas"}:
            # For idle context parameters, any explicit value (including 0) overrides idle
            self._params[key] = float_value
        elif key in {
            "reset_data",
            "reset_anc_X",
            "reset_anc_Z",
            "meas_data",
            "meas_anc_X",
            "meas_anc_Z",
        }:
            # For granular reset/measurement parameters, any explicit value (including 0) overrides base parameter
            self._params[key] = float_value
        else:
            self._params[key] = float_value

    def __contains__(self, key: str) -> bool:
        """
        Enable 'in' operator: 'depol' in noise_model.

        Parameters
        ----------
        key : str
            Parameter name to check.

        Returns
        -------
        bool
            True if parameter exists.
        """
        return key in self._params

    def keys(self) -> Iterator[str]:
        """
        Return parameter names.

        Returns
        -------
        Iterator[str]
            Iterator over parameter names.
        """
        return iter(self._params.keys())

    def values(self) -> Iterator[float]:
        """
        Return parameter values.

        Returns
        -------
        Iterator[float]
            Iterator over parameter values.
        """
        for key in self._params:
            yield self[key]  # Use __getitem__ to handle cult parameter

    def items(self) -> Iterator[Tuple[str, float]]:
        """
        Return (parameter, value) pairs.

        Returns
        -------
        Iterator[Tuple[str, float]]
            Iterator over (name, value) pairs.
        """
        for key in self._params:
            yield (key, self[key])  # Use __getitem__ to handle cult parameter

    def validate(self) -> None:
        """
        Validate all parameters are non-negative.

        Raises
        ------
        ValueError
            If any parameter is negative.
        """
        for key, value in self._params.items():
            if (
                key
                in {
                    "cult",
                    "idle_during_cnot",
                    "idle_during_meas",
                    "reset_data",
                    "reset_anc_X",
                    "reset_anc_Z",
                    "meas_data",
                    "meas_anc_X",
                    "meas_anc_Z",
                }
                and value is None
            ):
                continue  # These parameters can be None
            if value < 0:
                raise ValueError(
                    f"Noise parameter '{key}' must be non-negative, got {value}"
                )

    def is_noiseless(self) -> bool:
        """
        Check if all noise parameters are zero.

        Returns
        -------
        bool
            True if all parameters are zero (noiseless model).
        """
        for value in self.values():
            if value > 0:
                return False
        return True

    def __str__(self) -> str:
        """
        String representation for end users.

        Returns
        -------
        str
            Human-readable string representation.
        """
        if self.is_noiseless():
            return "NoiseModel(noiseless)"

        # Show only non-zero parameters
        nonzero_params = []
        for key, value in self.items():
            if value > 0:
                nonzero_params.append(f"{key}={value}")

        return f"NoiseModel({', '.join(nonzero_params)})"

    def __repr__(self) -> str:
        """
        Developer representation.

        Returns
        -------
        str
            Detailed string representation for debugging.
        """
        param_strs = []
        for key, value in self._params.items():
            if (
                key
                in {
                    "cult",
                    "idle_during_cnot",
                    "idle_during_meas",
                    "reset_data",
                    "reset_anc_X",
                    "reset_anc_Z",
                    "meas_data",
                    "meas_anc_X",
                    "meas_anc_Z",
                }
                and value is None
            ):
                param_strs.append(f"{key}=None")
            else:
                param_strs.append(f"{key}={value}")

        return f"NoiseModel({', '.join(param_strs)})"

__contains__(key)

Enable 'in' operator: 'depol' in noise_model.

Parameters:

Name Type Description Default
key str

Parameter name to check.

required

Returns:

Type Description
bool

True if parameter exists.

Source code in src/color_code_stim/noise_model.py
def __contains__(self, key: str) -> bool:
    """
    Enable 'in' operator: 'depol' in noise_model.

    Parameters
    ----------
    key : str
        Parameter name to check.

    Returns
    -------
    bool
        True if parameter exists.
    """
    return key in self._params

__getitem__(key)

Enable dictionary-like access: noise_model['depol'].

Parameters:

Name Type Description Default
key str

Parameter name to retrieve.

required

Returns:

Type Description
float

Parameter value.

Raises:

Type Description
KeyError

If parameter name is not recognized.

Source code in src/color_code_stim/noise_model.py
def __getitem__(self, key: str) -> float:
    """
    Enable dictionary-like access: noise_model['depol'].

    Parameters
    ----------
    key : str
        Parameter name to retrieve.

    Returns
    -------
    float
        Parameter value.

    Raises
    ------
    KeyError
        If parameter name is not recognized.
    """
    if key not in self._params:
        valid_keys = list(self._params.keys())
        raise KeyError(
            f"Unknown noise parameter '{key}'. Valid parameters: {valid_keys}"
        )

    # Handle special cases of parameters that can fallback to other parameters
    value = self._params[key]
    if key == "cult" and value is None:
        # Default cult to cnot rate if not explicitly set
        return self._params["cnot"]
    elif key == "idle_during_cnot" and value is None:
        # Default idle_during_cnot to idle rate if not explicitly set
        return self._params["idle"]
    elif key == "idle_during_meas" and value is None:
        # Default idle_during_meas to idle rate if not explicitly set
        return self._params["idle"]
    # Handle granular reset parameters fallback to base reset
    elif key == "reset_data" and value is None:
        return self._params["reset"]
    elif key == "reset_anc_X" and value is None:
        return self._params["reset"]
    elif key == "reset_anc_Z" and value is None:
        return self._params["reset"]
    # Handle granular measurement parameters fallback to base meas
    elif key == "meas_data" and value is None:
        return self._params["meas"]
    elif key == "meas_anc_X" and value is None:
        return self._params["meas"]
    elif key == "meas_anc_Z" and value is None:
        return self._params["meas"]

    return value

__init__(bitflip=0.0, depol=0.0, reset=0.0, meas=0.0, cnot=0.0, idle=0.0, cult=None, initial_data_qubit_depol=0.0, depol1_after_cnot=0.0, idle_during_cnot=None, idle_during_meas=None, reset_data=None, reset_anc_X=None, reset_anc_Z=None, meas_data=None, meas_anc_X=None, meas_anc_Z=None)

Initialize noise model with individual parameters.

All parameters must be non-negative floats representing error rates.

Parameters:

Name Type Description Default
bitflip float

Bit-flip noise rate on data qubits at the start of each round.

0.0
depol float

Depolarizing noise rate on data qubits at the start of each round.

0.0
reset float

Error rate for reset operations (producing orthogonal state).

0.0
meas float

Error rate for measurement operations (flipped outcome).

0.0
cnot float

Two-qubit depolarizing noise rate for CNOT gates.

0.0
idle float

Single-qubit depolarizing noise rate for idle operations.

0.0
cult float

Physical error rate during cultivation (for cult+growing circuits). If not provided, defaults to cnot rate when needed.

None
initial_data_qubit_depol float

Depolarizing noise rate applied to all data qubits after the first syndrome extraction round (if perfect_first_syndrome_extraction=True) or after data qubit initialization (if perfect_first_syndrome_extraction=False).

0.0
depol1_after_cnot float

Single-qubit depolarizing noise rate applied to each qubit participating in CNOT gates after the gates are applied. If provided and positive, DEPOLARIZE1 is added for each qubit involved in the CNOT operations.

0.0
idle_during_cnot float

Single-qubit depolarizing noise rate for idle qubits during CNOT operations. If None (default), uses the idle parameter. If set to any value (including 0), overrides idle for qubits not participating in CNOT gates.

None
idle_during_meas float

Single-qubit depolarizing noise rate for idle qubits during measurement operations. If None (default), uses the idle parameter. If set to any value (including 0), overrides idle for qubits not participating in measurement operations.

None
reset_data float

Error rate for reset operations on data qubits (producing orthogonal state). If None (default), uses the reset parameter.

None
reset_anc_X float

Error rate for reset operations on X-type ancilla qubits (producing orthogonal state). If None (default), uses the reset parameter.

None
reset_anc_Z float

Error rate for reset operations on Z-type ancilla qubits (producing orthogonal state). If None (default), uses the reset parameter.

None
meas_data float

Error rate for measurement operations on data qubits (flipped outcome). If None (default), uses the meas parameter.

None
meas_anc_X float

Error rate for measurement operations on X-type ancilla qubits (flipped outcome). If None (default), uses the meas parameter.

None
meas_anc_Z float

Error rate for measurement operations on Z-type ancilla qubits (flipped outcome). If None (default), uses the meas parameter.

None
Source code in src/color_code_stim/noise_model.py
def __init__(
    self,
    bitflip: float = 0.0,
    depol: float = 0.0,
    reset: float = 0.0,
    meas: float = 0.0,
    cnot: float = 0.0,
    idle: float = 0.0,
    cult: Optional[float] = None,
    initial_data_qubit_depol: float = 0.0,
    depol1_after_cnot: float = 0.0,
    idle_during_cnot: Optional[float] = None,
    idle_during_meas: Optional[float] = None,
    reset_data: Optional[float] = None,
    reset_anc_X: Optional[float] = None,
    reset_anc_Z: Optional[float] = None,
    meas_data: Optional[float] = None,
    meas_anc_X: Optional[float] = None,
    meas_anc_Z: Optional[float] = None,
):
    """
    Initialize noise model with individual parameters.

    All parameters must be non-negative floats representing error rates.

    Parameters
    ----------
    bitflip : float, default 0.0
        Bit-flip noise rate on data qubits at the start of each round.
    depol : float, default 0.0
        Depolarizing noise rate on data qubits at the start of each round.
    reset : float, default 0.0
        Error rate for reset operations (producing orthogonal state).
    meas : float, default 0.0
        Error rate for measurement operations (flipped outcome).
    cnot : float, default 0.0
        Two-qubit depolarizing noise rate for CNOT gates.
    idle : float, default 0.0
        Single-qubit depolarizing noise rate for idle operations.
    cult : float, optional
        Physical error rate during cultivation (for cult+growing circuits).
        If not provided, defaults to cnot rate when needed.
    initial_data_qubit_depol : float, default 0.0
        Depolarizing noise rate applied to all data qubits after the first
        syndrome extraction round (if perfect_first_syndrome_extraction=True)
        or after data qubit initialization (if perfect_first_syndrome_extraction=False).
    depol1_after_cnot : float, default 0.0
        Single-qubit depolarizing noise rate applied to each qubit participating
        in CNOT gates after the gates are applied. If provided and positive,
        DEPOLARIZE1 is added for each qubit involved in the CNOT operations.
    idle_during_cnot : float, optional
        Single-qubit depolarizing noise rate for idle qubits during CNOT operations.
        If None (default), uses the idle parameter. If set to any value (including 0),
        overrides idle for qubits not participating in CNOT gates.
    idle_during_meas : float, optional
        Single-qubit depolarizing noise rate for idle qubits during measurement operations.
        If None (default), uses the idle parameter. If set to any value (including 0),
        overrides idle for qubits not participating in measurement operations.
    reset_data : float, optional
        Error rate for reset operations on data qubits (producing orthogonal state).
        If None (default), uses the reset parameter.
    reset_anc_X : float, optional
        Error rate for reset operations on X-type ancilla qubits (producing orthogonal state).
        If None (default), uses the reset parameter.
    reset_anc_Z : float, optional
        Error rate for reset operations on Z-type ancilla qubits (producing orthogonal state).
        If None (default), uses the reset parameter.
    meas_data : float, optional
        Error rate for measurement operations on data qubits (flipped outcome).
        If None (default), uses the meas parameter.
    meas_anc_X : float, optional
        Error rate for measurement operations on X-type ancilla qubits (flipped outcome).
        If None (default), uses the meas parameter.
    meas_anc_Z : float, optional
        Error rate for measurement operations on Z-type ancilla qubits (flipped outcome).
        If None (default), uses the meas parameter.
    """
    # Store parameters in internal dict for easy access
    self._params = {
        "bitflip": float(bitflip),
        "depol": float(depol),
        "reset": float(reset),
        "meas": float(meas),
        "cnot": float(cnot),
        "idle": float(idle),
        "initial_data_qubit_depol": float(initial_data_qubit_depol),
        "depol1_after_cnot": float(depol1_after_cnot),
    }

    # Handle special parameters that can be None
    if cult is not None:
        self._params["cult"] = float(cult)
    else:
        self._params["cult"] = None

    if idle_during_cnot is not None:
        self._params["idle_during_cnot"] = float(idle_during_cnot)
    else:
        self._params["idle_during_cnot"] = None

    if idle_during_meas is not None:
        self._params["idle_during_meas"] = float(idle_during_meas)
    else:
        self._params["idle_during_meas"] = None

    # Handle granular reset parameters that can be None
    if reset_data is not None:
        self._params["reset_data"] = float(reset_data)
    else:
        self._params["reset_data"] = None

    if reset_anc_X is not None:
        self._params["reset_anc_X"] = float(reset_anc_X)
    else:
        self._params["reset_anc_X"] = None

    if reset_anc_Z is not None:
        self._params["reset_anc_Z"] = float(reset_anc_Z)
    else:
        self._params["reset_anc_Z"] = None

    # Handle granular measurement parameters that can be None
    if meas_data is not None:
        self._params["meas_data"] = float(meas_data)
    else:
        self._params["meas_data"] = None

    if meas_anc_X is not None:
        self._params["meas_anc_X"] = float(meas_anc_X)
    else:
        self._params["meas_anc_X"] = None

    if meas_anc_Z is not None:
        self._params["meas_anc_Z"] = float(meas_anc_Z)
    else:
        self._params["meas_anc_Z"] = None

    # Validate all parameters
    self.validate()

__repr__()

Developer representation.

Returns:

Type Description
str

Detailed string representation for debugging.

Source code in src/color_code_stim/noise_model.py
def __repr__(self) -> str:
    """
    Developer representation.

    Returns
    -------
    str
        Detailed string representation for debugging.
    """
    param_strs = []
    for key, value in self._params.items():
        if (
            key
            in {
                "cult",
                "idle_during_cnot",
                "idle_during_meas",
                "reset_data",
                "reset_anc_X",
                "reset_anc_Z",
                "meas_data",
                "meas_anc_X",
                "meas_anc_Z",
            }
            and value is None
        ):
            param_strs.append(f"{key}=None")
        else:
            param_strs.append(f"{key}={value}")

    return f"NoiseModel({', '.join(param_strs)})"

__setitem__(key, value)

Enable dictionary-like assignment: noise_model['depol'] = 0.01.

Parameters:

Name Type Description Default
key str

Parameter name to set.

required
value float or None

Parameter value to assign. None is allowed for certain parameters.

required

Raises:

Type Description
KeyError

If parameter name is not recognized.

ValueError

If value is negative.

Source code in src/color_code_stim/noise_model.py
def __setitem__(self, key: str, value: Optional[float]) -> None:
    """
    Enable dictionary-like assignment: noise_model['depol'] = 0.01.

    Parameters
    ----------
    key : str
        Parameter name to set.
    value : float or None
        Parameter value to assign. None is allowed for certain parameters.

    Raises
    ------
    KeyError
        If parameter name is not recognized.
    ValueError
        If value is negative.
    """
    if key not in self._params:
        valid_keys = list(self._params.keys())
        raise KeyError(
            f"Unknown noise parameter '{key}'. Valid parameters: {valid_keys}"
        )

    # Handle None values for special parameters
    if value is None:
        if key in {
            "cult",
            "idle_during_cnot",
            "idle_during_meas",
            "reset_data",
            "reset_anc_X",
            "reset_anc_Z",
            "meas_data",
            "meas_anc_X",
            "meas_anc_Z",
        }:
            self._params[key] = None
            return
        else:
            raise ValueError(
                f"Noise parameter '{key}' cannot be None. "
                f"Only 'cult', 'idle_during_cnot', 'idle_during_meas', "
                f"and granular reset/measurement parameters can be None."
            )

    # Convert to float and validate
    float_value = float(value)
    if float_value < 0:
        raise ValueError(
            f"Noise parameter '{key}' must be non-negative, got {float_value}"
        )

    # Special handling for special parameters
    if key == "cult":
        self._params[key] = float_value if float_value > 0 else None
    elif key in {"idle_during_cnot", "idle_during_meas"}:
        # For idle context parameters, any explicit value (including 0) overrides idle
        self._params[key] = float_value
    elif key in {
        "reset_data",
        "reset_anc_X",
        "reset_anc_Z",
        "meas_data",
        "meas_anc_X",
        "meas_anc_Z",
    }:
        # For granular reset/measurement parameters, any explicit value (including 0) overrides base parameter
        self._params[key] = float_value
    else:
        self._params[key] = float_value

__str__()

String representation for end users.

Returns:

Type Description
str

Human-readable string representation.

Source code in src/color_code_stim/noise_model.py
def __str__(self) -> str:
    """
    String representation for end users.

    Returns
    -------
    str
        Human-readable string representation.
    """
    if self.is_noiseless():
        return "NoiseModel(noiseless)"

    # Show only non-zero parameters
    nonzero_params = []
    for key, value in self.items():
        if value > 0:
            nonzero_params.append(f"{key}={value}")

    return f"NoiseModel({', '.join(nonzero_params)})"

is_noiseless()

Check if all noise parameters are zero.

Returns:

Type Description
bool

True if all parameters are zero (noiseless model).

Source code in src/color_code_stim/noise_model.py
def is_noiseless(self) -> bool:
    """
    Check if all noise parameters are zero.

    Returns
    -------
    bool
        True if all parameters are zero (noiseless model).
    """
    for value in self.values():
        if value > 0:
            return False
    return True

items()

Return (parameter, value) pairs.

Returns:

Type Description
Iterator[Tuple[str, float]]

Iterator over (name, value) pairs.

Source code in src/color_code_stim/noise_model.py
def items(self) -> Iterator[Tuple[str, float]]:
    """
    Return (parameter, value) pairs.

    Returns
    -------
    Iterator[Tuple[str, float]]
        Iterator over (name, value) pairs.
    """
    for key in self._params:
        yield (key, self[key])  # Use __getitem__ to handle cult parameter

keys()

Return parameter names.

Returns:

Type Description
Iterator[str]

Iterator over parameter names.

Source code in src/color_code_stim/noise_model.py
def keys(self) -> Iterator[str]:
    """
    Return parameter names.

    Returns
    -------
    Iterator[str]
        Iterator over parameter names.
    """
    return iter(self._params.keys())

uniform_circuit_noise(p_circuit) classmethod

Create noise model with uniform circuit-level noise. Equivalent to:

NoiseModel(reset=p_circuit, meas=p_circuit, cnot=p_circuit, idle=p_circuit)

Parameters:

Name Type Description Default
p_circuit float

Circuit-level error rate to apply uniformly.

required

Returns:

Type Description
NoiseModel

New noise model with uniform rates.

Source code in src/color_code_stim/noise_model.py
@classmethod
def uniform_circuit_noise(cls, p_circuit: float) -> Self:
    """
    Create noise model with uniform circuit-level noise. Equivalent to:
    >>> NoiseModel(reset=p_circuit, meas=p_circuit, cnot=p_circuit, idle=p_circuit)

    Parameters
    ----------
    p_circuit : float
        Circuit-level error rate to apply uniformly.

    Returns
    -------
    NoiseModel
        New noise model with uniform rates.
    """
    return cls(
        bitflip=0.0,  # Not included in circuit-level noise
        depol=0.0,  # Not included in circuit-level noise
        reset=p_circuit,
        meas=p_circuit,
        cnot=p_circuit,
        idle=p_circuit,
        cult=None,  # Will default to cnot when needed
        initial_data_qubit_depol=0.0,  # Not included in circuit-level noise
        depol1_after_cnot=0.0,  # Not included in circuit-level noise
        idle_during_cnot=None,  # Not included in circuit-level noise
        idle_during_meas=None,  # Not included in circuit-level noise
        reset_data=None,  # Will default to reset when needed
        reset_anc_X=None,  # Will default to reset when needed
        reset_anc_Z=None,  # Will default to reset when needed
        meas_data=None,  # Will default to meas when needed
        meas_anc_X=None,  # Will default to meas when needed
        meas_anc_Z=None,  # Will default to meas when needed
    )

validate()

Validate all parameters are non-negative.

Raises:

Type Description
ValueError

If any parameter is negative.

Source code in src/color_code_stim/noise_model.py
def validate(self) -> None:
    """
    Validate all parameters are non-negative.

    Raises
    ------
    ValueError
        If any parameter is negative.
    """
    for key, value in self._params.items():
        if (
            key
            in {
                "cult",
                "idle_during_cnot",
                "idle_during_meas",
                "reset_data",
                "reset_anc_X",
                "reset_anc_Z",
                "meas_data",
                "meas_anc_X",
                "meas_anc_Z",
            }
            and value is None
        ):
            continue  # These parameters can be None
        if value < 0:
            raise ValueError(
                f"Noise parameter '{key}' must be non-negative, got {value}"
            )

values()

Return parameter values.

Returns:

Type Description
Iterator[float]

Iterator over parameter values.

Source code in src/color_code_stim/noise_model.py
def values(self) -> Iterator[float]:
    """
    Return parameter values.

    Returns
    -------
    Iterator[float]
        Iterator over parameter values.
    """
    for key in self._params:
        yield self[key]  # Use __getitem__ to handle cult parameter