Overview
Maestro provides a high-performance noise simulation suite with multiple approaches balancing speed, accuracy, and memory usage:
| Function | Overhead | Noise Mechanism | Best For |
| noisy_estimate | Zero | Analytical Pauli damping | Fast ansatz screening |
| noisy_estimate_montecarlo | N x noiseless | Gate-by-gate stochastic Pauli | QML training with noise |
| noisy_execute | N x noiseless | Gate-by-gate Pauli + shot noise | Shot-based sampling |
| coherent_estimate | N x noiseless | Systematic rotation overshoots | Coherent error analysis |
| coherent_execute | N x noiseless | Coherent errors + shot noise | Shot-based coherent noise |
| full_noise_execute | N x noiseless | All physical noise layers combined | Full device simulation |
| full_noise_estimate | N x noiseless | All physical noise layers combined | Hardware-realistic expectation values |
| noisy_fidelity | N x inner_product | All noise layers (MPS-native) | Fast overlap & infidelity estimation |
| qc.noisy_prob | O(n) path integral | Readout error correction | Direct path-integral probability queries |
NoiseModel Builder
The NoiseModel class specifies error parameters across qubits and gate operations:
import maestro
nm = maestro.NoiseModel()
nm.set_depolarizing(qubit=0, p=0.01)
nm.set_all_depolarizing(num_qubits=5, p=0.005)
nm.set_dephasing(qubit=1, p=0.02)
nm.set_bit_flip(qubit=2, p=0.01)
nm.set_qubit_noise(qubit=3, px=0.005, py=0.002, pz=0.01)
Analytical Noisy Estimation (Zero Overhead)
noisy_estimate executes a single noiseless simulation and analytically damps each Pauli expectation value according to the noise model. This incurs zero additional simulation cost.
from maestro.circuits import QuantumCircuit
qc = QuantumCircuit()
qc.h(0)
qc.cx(0, 1)
nm = maestro.NoiseModel()
nm.set_all_depolarizing(num_qubits=2, p=0.05)
result = maestro.noisy_estimate(qc, ["ZZ", "XX", "YY"], nm)
print("Noisy values:", result["expectation_values"])
print("Ideal values:", result["ideal_expectation_values"])
print(f"Time taken: {result['time_taken']:.4f}s (zero extra overhead)")
Gate-by-Gate Monte Carlo Simulation
For depth-dependent noise accumulation, noisy_estimate_montecarlo injects stochastic Pauli errors after each gate across multiple realization circuits:
result = maestro.noisy_estimate_montecarlo(
qc, ["ZZ", "XX"], nm,
noise_realizations=200,
seed=42
)
print("Expectation values:", result["expectation_values"])
print("Ideal reference:", result["ideal_expectation_values"])
For shot-based measurement counts with gate-level noise:
qc.measure_all()
result = maestro.noisy_execute(
qc, nm,
shots=1024,
noise_realizations=64,
seed=42
)
print("Counts:", result["counts"])
Coherent Noise (Systematic Calibration Errors)
Coherent noise injects deterministic unitary rotations (Rx, Ry, Rz) after gates rather than random Pauli flips, modeling systematic over-rotation and phase drift:
nm = maestro.NoiseModel()
nm.set_coherent_depolarizing(qubit=0, p=0.01)
nm.set_all_coherent_depolarizing(num_qubits=5, p=0.001)
nm.set_coherent_rotation(qubit=0, rx=0.01, ry=0.0, rz=0.05)
result = maestro.coherent_estimate(qc, ["ZZ", "XX"], nm, noise_realizations=100)
print(result["expectation_values"])
Thermal Relaxation (T1 and T2 Decoherence)
Thermal relaxation models physical energy decay (T1) and dephasing (T2) based on physical gate execution times.
nm = maestro.NoiseModel()
nm.set_thermal_relaxation(qubit=0, gate_time_s=30e-9, t1_s=100e-6, t2_s=80e-6)
nm.set_thermal_relaxation_2q(qubit=0, gate_time_s=300e-9, t1_s=100e-6, t2_s=80e-6)
Note: Physical consistency requires T2 <= 2 * T1.
CPTP Quantum Channels (MPO & Density Matrix)
For exact open quantum systems using Matrix Product Operator (MPO) or Density Matrix backends:
- Phase Damping: Pure dephasing with coherence multiplier sqrt(1 - gamma) or exp(-t / T_phi).
- Generalized Amplitude Damping: Energy relaxation at finite thermal equilibrium population.
- Correlated Phase Flip: Correlated two-qubit ZZ phase error.
- Arbitrary Kraus Channels: Custom single-qubit or two-qubit Kraus operator matrices satisfying sum_k (E_k^dagger * E_k) = I.
nm = maestro.NoiseModel()
nm.set_phase_damping(qubit=0, gamma=0.05)
nm.set_phase_damping_from_time(qubit=1, gate_time_s=30e-9, t_phi_s=50e-6)
nm.set_generalized_amplitude_damping(qubit=2, gamma=0.02, excited_population=0.05)
nm.set_correlated_phase_flip(q1=0, q2=1, probability=0.01, correlation=0.8)
bit_flip_kraus = [
[[0.994987, 0.0], [0.0, 0.994987]],
[[0.0, 0.1], [0.1, 0.0]]
]
nm.set_kraus_channel([0], bit_flip_kraus)
ZZ Crosstalk & Two-Qubit Errors
nm = maestro.NoiseModel()
nm.set_crosstalk(q1=0, q2=1, strength=0.005)
nm.set_2q_depolarizing(q1=0, q2=1, p=1.8e-3)
Readout Error & Path Integral Correction
Readout errors model classical measurement confusion matrices:
nm = maestro.NoiseModel()
nm.set_readout_error(qubit=0, p_meas1_prep0=0.003, p_meas0_prep1=0.06)
nm.set_all_readout_error(num_qubits=5, p_error=0.02)
result = qc.noisy_prob("11", nm)
print("Readout-corrected probability:", result["probability"])
Time-Correlated (OU & AR(1)) Dephasing
Real quantum hardware experiences non-Markovian phase drift from background fluctuators. Maestro models continuous Ornstein-Uhlenbeck (OU) stochastic processes discretized as AR(1) autoregressive noise after each gate:
nm = maestro.NoiseModel()
nm.set_correlated_ou(
qubit=0,
sigma=15.0,
alpha=0.5,
gate_time=100e-9,
stationary_init=True,
)
nm.set_all_correlated_ou(num_qubits=5, sigma=15.0, alpha=0.5, gate_time=100e-9)
Multi-Band OU & 1/f Spectrum Noise
To accurately reproduce true 1/f power spectral density over multiple decades of frequency, Maestro allows superposing multiple independent OU fluctuator bands on each qubit:
nm = maestro.NoiseModel()
nm.add_correlated_ou_band(qubit=0, sigma=10.0, alpha=0.1, gate_time=100e-9)
nm.add_correlated_ou_band(qubit=0, sigma=5.0, alpha=1.0, gate_time=100e-9)
nm.add_correlated_ou_band(qubit=0, sigma=2.0, alpha=10.0, gate_time=100e-9)
bands = [(10.0, 0.1), (5.0, 1.0), (2.0, 10.0)]
nm.set_multi_correlated_ou(qubit=1, bands=bands, gate_time=100e-9)
nm.set_1_over_f_noise(
qubit=2,
total_power=1e-3,
f_min=1e3,
f_max=1e7,
num_bands=6,
gate_time=100e-9,
stationary_init=True,
)
Idle Channels & Delay Decoherence
Real devices accumulate significant decoherence while idling. Maestro provides native idle channels configured via set_idle_noise() that act on qc.delay(qubit, duration) operations:
nm = maestro.NoiseModel()
nm.set_idle_noise(
qubit=0,
t1=100e-6,
t2=80e-6,
excited_population=0.01,
detuning_hz=5e3,
)
qc = QuantumCircuit()
qc.h(0)
qc.delay(0, 20e-6)
qc.h(0)
qc.measure_all()
result = qc.full_noise_execute(nm, shots=1024)
print(result["counts"])
Combined Device-Level Simulation
Run full device simulation with all active noise layers combined in physical sequence:
nm = maestro.NoiseModel()
nm.set_all_correlated_ou(num_qubits=5, sigma=15.0, alpha=0.5, gate_time=100e-9)
nm.set_all_coherent_depolarizing(num_qubits=5, p=0.002)
nm.set_all_readout_error(num_qubits=5, p_error=0.01)
exec_result = qc.full_noise_execute(nm, shots=1024, noise_realizations=64)
print("Full noise counts:", exec_result["counts"])
est_result = qc.full_noise_estimate(["ZZ", "XX"], nm, noise_realizations=100)
print("Full noise expectation values:", est_result["expectation_values"])
fid_result = qc.noisy_fidelity(nm, noise_realizations=100)
print(f"Fidelity: {fid_result['fidelity']:.4f} +/- {fid_result['std_error']:.4f}")