Noise¶
- class NoiseModel(*args, **kwargs)¶
Python wrapper around C++ NoiseModel enabling multiprocessing and pickle serialization.
- compute_damping(self, pauli_string: str) float¶
Damping factor for a Pauli string observable from ONE application of the configured Pauli channels.
Exact only when the channel acts once, immediately before measurement; for a circuit with noise after every gate it underestimates the noise. Only the all-gates Pauli layer contributes.
- compute_damping_covers_model(self) bool¶
Return True iff compute_damping() captures every layer that affects Pauli expectations. False for thermal, T1, gate-type Pauli, 2Q depolarizing, coherent, correlated and crosstalk.
- get_t1_2q(self, qubit: int) float¶
Get T1 decay probability for 2Q gates (falls back to get_t1 if not set).
- get_t1_for_gate(self, qubit: int, is_2q: bool) float¶
Get gate-type-aware T1: returns t1_2q if is_2q and set, else t1.
- has_additional_quantum_channels(self) bool¶
Return True if a channel that ONLY an exact density-matrix/MPO backend can run is configured: generalized amplitude damping, correlated phase flips or custom Kraus maps. Phase damping and thermal relaxation are excluded – both have an exact or well-defined stochastic realization on sampled backends.
Return True if any correlated noise parameters have been set.
- has_thermal_in_sampled_overdephasing_regime(self) bool¶
Return True if any thermal-relaxation layer has T2 > T1, where the sampled reset+Z mixture over-dephases. Use density-matrix or MPO execution in that regime.
- requires_exact_quantum_channels(self) bool¶
Return True if sampled injection cannot faithfully realize this model (exact-only Kraus maps, or T2 > T1 requiring approximation on sampled paths).
- set_1_over_f_noise(self, qubit: int, total_power: float, f_min: float, f_max: float, num_bands: int, gate_time: float, after_1q: bool = True, after_2q: bool = True, stationary_init: bool = True) None¶
Synthesize 1/f noise spectrum via logarithmically spaced OU fluctuator bands.
- set_1q_gate_depolarizing(self, qubit: int, p: float) None¶
Set depolarizing noise applied only after single-qubit gates.
This is separate from set_depolarizing() which applies after ALL gates.
Example
nm.set_1q_gate_depolarizing(0, 2.3e-4)
- set_2q_depolarizing(self, q1: int, q2: int, p: float) None¶
Set a correlated two-qubit depolarizing channel applied after every two-qubit gate on the pair (q1, q2).
Channel: Λ(ρ) = (1-p)ρ + p/15 · Σ PρP† (15 non-identity two-qubit Paulis), the same as Stim’s DEPOLARIZE2(p). Applied ONLY after 2Q gates, separate from per-qubit noise. Not to be confused with set_2q_gate_depolarizing(qubit, p), which applies independent single-qubit depolarizing to each qubit after its 2Q gates.
Example
nm.set_2q_depolarizing(0, 1, 1.8e-3)
- set_2q_gate_depolarizing(self, qubit: int, p: float) None¶
Set single-qubit depolarizing noise (DEPOLARIZE1(p)) applied to this qubit only after two-qubit gates involving it.
Each qubit of the gate gets an independent channel, so this is NOT Stim’s DEPOLARIZE2(p); for that use set_2q_depolarizing(q1, q2, p).
Example
nm.set_2q_gate_depolarizing(0, 1.8e-3)
- set_all_1q_gate_depolarizing(self, num_qubits: int, p: float) None¶
Set uniform 1Q gate depolarizing on qubits [0, num_qubits).
- set_all_2q_gate_depolarizing(self, num_qubits: int, p: float) None¶
Set uniform single-qubit depolarizing after 2Q gates on qubits [0, num_qubits). See set_2q_gate_depolarizing; for Stim’s DEPOLARIZE2 use set_2q_depolarizing on each coupled pair.
- set_all_coherent_dephasing(self, num_qubits: int, p: float) None¶
Set uniform coherent dephasing on qubits [0, num_qubits).
- set_all_coherent_depolarizing(self, num_qubits: int, p: float) None¶
Set uniform coherent depolarizing noise on qubits [0, num_qubits).
Set correlated noise from total noise power.
P_tot = N * sigma^2 * pi * alpha * gate_time Derives sigma from P_tot and sets OU noise on all qubits.
- Parameters:
num_qubits – Number of qubits N.
power – Total noise power P_tot.
alpha – Correlation time in gate-time units.
gate_time – Gate duration in seconds.
after_1q – If True (default), inject after 1Q gates too.
after_2q – If True (default), inject after 2Q gates too.
Example
nm.set_all_correlated_from_power(20, power=1e-3, alpha=0.5, gate_time=100e-9)
Set identical OU correlated noise on qubits [0, num_qubits).
Example
nm.set_all_correlated_ou(20, sigma=15.0, alpha=0.5, gate_time=100e-9)
- set_all_dephasing(self, num_qubits: int, p: float) None¶
Add uniform dephasing noise to all qubits [0, num_qubits).
- set_all_depolarizing(self, num_qubits: int, p: float) None¶
Add uniform depolarizing noise to all qubits [0, num_qubits).
Uniform multi-OU setter across qubits 0..num_qubits-1.
- set_all_readout_error(self, num_qubits: int, p_error: float) None¶
Set uniform symmetric readout error on qubits [0, num_qubits).
Applied per measured qubit when the measurement writes its classical bit.
- set_all_t1(self, num_qubits: int, gamma: float) None¶
Set uniform T1 decay probability on qubits [0, num_qubits).
- set_coherent_bit_flip(self, qubit: int, p: float) None¶
Set coherent bit-flip noise: Rx rotation from probability p. Replaces the X angle only, so it composes with other axes.
- set_coherent_dephasing(self, qubit: int, p: float) None¶
Set coherent dephasing noise: Rz rotation from probability p. Replaces the Z angle only, so it composes with other axes.
- set_coherent_depolarizing(self, qubit: int, p: float) None¶
Set isotropic coherent noise calibrated to DEPOLARIZE1(p).
After every gate on this qubit, rotates by ε = 2·arcsin(√p) about a body diagonal (±1, ±1, ±1)/√3 of the Bloch sphere, with the signs drawn once per qubit per noise realization. The Pauli twirl of that rotation is exactly DEPOLARIZE1(p), so it has the same infidelity and affects X-, Y- and Z-basis measurements. Composes with set_coherent_bit_flip/dephasing/rotation.
- set_coherent_rotation(self, qubit: int, rx: float, ry: float, rz: float) None¶
Set per-qubit coherent noise as rotation angles (radians). After every gate on this qubit, Rx(±rx), Ry(±ry), Rz(±rz) rotations are applied, with each ± sign drawn once per qubit per noise realization. Replaces the X, Y and Z angles only; set_coherent_depolarizing is kept.
- set_coherent_strength(self, num_qubits: int, p: float) None¶
Convenience: set uniform isotropic coherent noise on qubits [0, num_qubits). Equivalent to set_all_coherent_depolarizing(n, p).
Set AR(1) correlated dephasing on a qubit.
- After every gate, Rz(y[k]) is injected where:
y[k] = phi * y[k-1] + eta[k], eta ~ N(0, sigma_eta^2)
- Parameters:
qubit – Qubit index.
phi – AR(1) autoregressive coefficient.
sigma_eta – Driving noise standard deviation.
after_1q – If True (default), inject after 1Q gates.
after_2q – If True (default), inject after 2Q gates.
stationary_init – If True (default), sample step 0 from stationary equilibrium.
Example
nm.set_correlated_ar1(0, phi=0.135, sigma_eta=2.35e-3)
Set correlated noise from Ornstein-Uhlenbeck parameters.
- OU: dX = -theta*X*dt + sigma*dW, discretized as AR(1).
theta = 1/(alpha * gate_time) phi = exp(-theta * gate_time) sigma_eta^2 = (sigma^2 / 2*theta) * (1 - phi^2)
- Parameters:
qubit – Qubit index.
sigma – OU diffusion coefficient (noise strength).
alpha – Correlation time in gate-time units.
gate_time – Gate duration in seconds.
after_1q – If True (default), inject after 1Q gates.
after_2q – If True (default), inject after 2Q gates.
stationary_init – If True (default), sample step 0 from stationary equilibrium.
Example
nm.set_correlated_ou(0, sigma=15.0, alpha=0.5, gate_time=100e-9)
Append an OU fluctuator band to a qubit’s band list, keeping the bands already set on it.
Set a correlated two-qubit phase-flip channel after gates on the pair. correlation=0 is independent; correlation=1 is II/ZZ.
- set_crosstalk(self, q1: int, q2: int, strength: float) None¶
Set spectator-Z crosstalk between two qubits. After a gate on q1, Rz(strength) is applied on q2, and vice versa. This is not a genuine two-qubit ZZ interaction.
- set_generalized_amplitude_damping(self, qubit: int, gamma: float, excited_population: float) None¶
Set finite-temperature generalized amplitude damping after each gate on a qubit. Requires an exact density-matrix or MPO backend.
- set_idle_noise(self, qubit: int, t1: float, t2: float, excited_population: float = 0.0, detuning_hz: float = 0.0) None¶
Configure idle dephasing/relaxation and detuning for delay instructions.
- Parameters:
qubit – Qubit index.
t1 – T1 relaxation time in seconds.
t2 – T2 dephasing time in seconds (T2 <= 2*T1).
excited_population – Equilibrium
|1>state population (default 0.0).detuning_hz – Coherent detuning frequency in Hz (default 0.0).
- set_kraus_channel(self, targets: collections.abc.Sequence[int], kraus_operators: collections.abc.Sequence[collections.abc.Sequence[collections.abc.Sequence[complex]]]) None¶
Attach an arbitrary one- or two-qubit CPTP Kraus channel after gates on the same targets. Matrices are nested row-major lists; completeness (sum_k E_k^dag E_k = I) is validated.
BASIS ORDER for two-qubit operators: targets[0] is the LEAST significant bit of the 4x4 matrix index, targets[1] the most significant. So an operator acting as A on targets[0] and B on targets[1] must be supplied as the Kronecker product B (x) A. Getting this backwards silently transposes the channel onto the wrong qubit.
Example
# X on targets[0], identity on targets[1] nm.set_kraus_channel([0, 2], [[[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]]])
Batch multi-OU setter: clears existing bands and populates from a list of (sigma, alpha) pairs.
- set_phase_damping(self, qubit: int, gamma: float) None¶
Set phase damping with coherence multiplier sqrt(1-gamma).
Phase damping and the stochastic phase flip are the same channel (sqrt(1-gamma) = 1-2p), so this is realized exactly on every backend, not only density-matrix/MPO.
- set_phase_damping_from_time(self, qubit: int, gate_time_s: float, t_phi_s: float) None¶
Set pure phase damping so coherence decays as exp(-gate_time/T_phi). Realized exactly on every backend.
- set_qubit_noise(self, qubit: int, px: float, py: float, pz: float) None¶
Add Pauli channel: Λ(ρ) = (1-px-py-pz)ρ + px·XρX + py·YρY + pz·ZρZ
- set_readout_error(self, qubit: int, p_meas1_prep0: float, p_meas0_prep1: float) None¶
Set asymmetric readout error on a qubit.
Applied when a measurement of this qubit writes its classical bit, whatever bit index it targets, so mid-circuit and repeated measurements are covered and classically-conditioned operations downstream observe the noisy outcome.
- Parameters:
qubit – Qubit index.
p_meas1_prep0 – P(measure 1 | state was 0) — false positive.
p_meas0_prep1 – P(measure 0 | state was 1) — false negative.
Example
nm.set_readout_error(0, 0.003, 0.06)
- set_readout_error_symmetric(self, qubit: int, p_error: float) None¶
Set symmetric readout error (same rate for both directions).
Applied per measured qubit when the measurement writes its classical bit.
Example
nm.set_readout_error_symmetric(0, 0.01)
- set_t1(self, qubit: int, gamma: float) None¶
Set per-gate T1 decay probability. Density-matrix/MPO execution uses exact amplitude damping; pure-state execution retains the legacy sampled-reset approximation.
- set_t1_2q(self, qubit: int, gamma: float) None¶
Set T1 decay probability applied only after two-qubit gates. When set, 2Q gates use this gamma instead of the ‘all gates’ value.
- set_t1_2q_from_time(self, qubit: int, gate_time_s: float, t1_time_s: float) None¶
Set T1 for 2Q gates from physical time constants. gamma = 1 - exp(-gate_time / T1).
Example
nm.set_t1_2q_from_time(0, gate_time_s=40e-9, t1_time_s=100e-6)
- set_t1_from_time(self, qubit: int, gate_time_s: float, t1_time_s: float) None¶
Set T1 from physical time constants. gamma = 1 - exp(-gate_time / T1).
Example
nm.set_t1_from_time(0, gate_time_s=30e-9, t1_time_s=100e-6)
- set_thermal_relaxation(self, qubit: int, gate_time_s: float, t1_s: float, t2_s: float, excited_population: float = 0.0) None¶
Set hardware-style T1/T2 thermal relaxation after each gate.
This is the preferred way to specify decoherence. Because T1 and T2 are given together, every backend reproduces the same coherence decay exp(-gate_time/T2): density-matrix/MPO use the exact CPTP channel, pure-state/MPS use the equivalent reset+Z mixture. Calling set_t1() and set_dephasing() separately cannot achieve that – the phase-flip probability that is correct for the sampled reset model under-dephases by exp(t/2*T1) per gate on the exact amplitude-damping path.
The physical constraint T2 <= 2*T1 is enforced.
- noisy_estimate(circuit: maestro.circuits.QuantumCircuit, observables: object, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig()) dict¶
- noisy_estimate(qasm_circuit: str, observables: object, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig()) dict
Overloaded function.
noisy_estimate(circuit: maestro.circuits.QuantumCircuit, observables: object, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig()) -> dict
Compute expectation values with single-layer analytical Pauli noise damping. Runs the noiseless simulation then applies the damping factor – zero simulation overhead compared to noiseless.
WARNING – this is a SINGLE-LAYER approximation, not an exact result. The damping factor is exact only for one Pauli layer applied immediately before measurement. A circuit that carries noise after every gate is not modelled: Pauli channels do not commute through non-Clifford gates, and the damping does not compound with the number of noisy layers acting on each qubit. The returned values therefore UNDERESTIMATE the noise, increasingly so with circuit depth.
Only the all-gates Pauli layer is modelled; a NoiseModel with any other layer (T1, thermal, coherent, correlated, gate-type or two-qubit noise) raises ValueError, see compute_damping_covers_model(). Readout error is ignored. Use noisy_estimate_montecarlo(), full_noise_estimate(), or noisy_execute() with a density-matrix or MPO method, when the magnitude of the noise matters.
noisy_estimate(qasm_circuit: str, observables: object, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig()) -> dict
Compute expectation values from a QASM circuit with single-layer analytical Pauli noise damping. Zero simulation overhead.
WARNING – this is a SINGLE-LAYER approximation, not an exact result. The damping factor is exact only for one Pauli layer applied immediately before measurement. A circuit that carries noise after every gate is not modelled: Pauli channels do not commute through non-Clifford gates, and the damping does not compound with the number of noisy layers acting on each qubit. The returned values therefore UNDERESTIMATE the noise, increasingly so with circuit depth.
Only the all-gates Pauli layer is modelled; a NoiseModel with any other layer raises ValueError, see compute_damping_covers_model(). Use noisy_estimate_montecarlo(), full_noise_estimate(), or noisy_execute() with a density-matrix or MPO method, when the magnitude of the noise matters.
- noisy_estimate_montecarlo(circuit: maestro.circuits.QuantumCircuit, observables: object, noise_model: maestro.NoiseModel, noise_realizations: int = 100, config: maestro.SimulatorConfig = SimulatorConfig(), noise_seed: int | None = None) dict¶
Gate-by-gate Monte Carlo noisy estimation. Injects random Pauli errors after every gate and averages expectation values over noise_realizations independent samples. More accurate than analytical noisy_estimate for deep circuits. Coherent, correlated and crosstalk noise are not applied and raise ValueError; use full_noise_estimate for those.
- noisy_execute(circuit: maestro.circuits.QuantumCircuit, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig(), shots: int = 1024, noise_realizations: int = 64, noise_seed: int | None = None) dict¶
Execute with exact Pauli/T1 channels for density-matrix/MPO methods, or sampled trajectories for pure-state methods. Shots are distributed evenly across ‘noise_realizations’ batches. Coherent, correlated and crosstalk noise are not applied and raise ValueError; use full_noise_execute for those.
- coherent_estimate(circuit: maestro.circuits.QuantumCircuit, observables: object, noise_model: maestro.NoiseModel, noise_realizations: int = 100, config: maestro.SimulatorConfig = SimulatorConfig(), noise_seed: int | None = None) dict¶
Estimate expectation values with coherent noise (rotation errors). Injects systematic Rx/Ry/Rz rotations after every gate and averages expectation values over noise_realizations independent sign samples. Unlike Pauli noise, coherent noise preserves phase coherence and does not commute with the circuit — it can model systematic calibration errors.
Example
nm = maestro.NoiseModel() nm.set_coherent_strength(n_qubits, 0.001) result = maestro.coherent_estimate(qc, ['ZZ', 'XX'], nm)
- coherent_execute(circuit: maestro.circuits.QuantumCircuit, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig(), shots: int = 1024, noise_realizations: int = 64, noise_seed: int | None = None) dict¶
Execute a circuit with sampled coherent over/under-rotation errors. After every gate, Rx/Ry/Rz rotations are injected with random ± signs. Each of ‘noise_realizations’ batches uses a different sign pattern. Supported by statevector, MPS, density-matrix, and MPO methods (not Stabilizer). Readout error is applied; any other non-coherent layer raises ValueError (use full_noise_execute).
Example
nm = maestro.NoiseModel() nm.set_all_coherent_depolarizing(n_qubits, 0.001) result = maestro.coherent_execute(qc, nm, shots=1000)
- full_noise_estimate(circuit: maestro.circuits.QuantumCircuit, observables: object, noise_model: maestro.NoiseModel, noise_realizations: int = 100, config: maestro.SimulatorConfig = SimulatorConfig(), noise_seed: int | None = None) dict¶
Estimate expectation values with combined noise (coherent + crosstalk + T1 + Pauli). All configured noise layers are applied per gate.
Example
nm = maestro.NoiseModel() nm.set_all_coherent_depolarizing(n, 0.001) nm.set_crosstalk(0, 1, 0.005) nm.set_all_t1(n, 0.0003) result = maestro.full_noise_estimate(qc, ['ZZ'], nm)
- full_noise_execute(circuit: maestro.circuits.QuantumCircuit, noise_model: maestro.NoiseModel, config: maestro.SimulatorConfig = SimulatorConfig(), shots: int = 1024, noise_realizations: int = 64, noise_seed: int | None = None) dict¶
Execute a circuit with combined noise (coherent + crosstalk + T1 + Pauli). Density-matrix/MPO methods apply Markovian T1 and Pauli layers as exact channels; trajectory-only layers remain sampled.
Example
nm = maestro.NoiseModel() nm.set_all_coherent_depolarizing(n, 0.001) nm.set_crosstalk(0, 1, 0.005) nm.set_all_t1(n, 0.0003) nm.set_all_depolarizing(n, 0.001) result = maestro.full_noise_execute(qc, nm, shots=1000)
- noisy_fidelity(circuit: maestro.circuits.QuantumCircuit, noise_model: maestro.NoiseModel, noise_realizations: int = 100, config: maestro.SimulatorConfig = SimulatorConfig(), noise_seed: int | None = None) dict¶
Compute fidelity to the ideal unitary circuit state under noise.
Injects all configured noise types (correlated, coherent, crosstalk, T1, Pauli) and averages
|<psi_ideal|psi_noisy>|^2over noise realizations.Returns dict with ‘fidelity’, ‘infidelity’, ‘std_error’, ‘time_taken’, ‘noise_realizations’.
Example
maestro.noisy_fidelity(qc, nm, noise_realizations=200)