Density Matrices and Noise Models
Use execute_density() to simulate mixed states or noise:
import numpy as np
from unitarylab import Circuit
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
result = qc.execute_density(device="cpu", dtype=np.complex128)
print(result.state)
print(result.trace)
print(result.purity)
print(result.probabilities)execute_density(initial_state=None, device="cpu",
dtype=np.complex128, noise_model=None, shots=1, seed=42)initial_state may be None, a state vector, a density matrix, or DensityMatrixState. A vector is converted to . A density matrix must be , Hermitian, positive semidefinite, and have trace 1.
| Property or method | Description |
|---|---|
state | Final density matrix |
trace | ; close to 1 for a valid state |
purity | ; close to 1 for a pure state |
probabilities, probability() | Computational-basis probabilities |
marginal_probabilities() | Marginal probabilities for selected qubits |
expectation() | Observable expectation value |
Noise models
from unitarylab.backend import AmplitudeDamping, BitFlip, NoiseModel, NoiseOperator
noise_model = NoiseModel([
NoiseOperator(BitFlip(0.02), gate_ids=("x", "rx")),
NoiseOperator(AmplitudeDamping(0.05), qubits=(1,)),
])
noisy_result = qc.execute_density(noise_model=noise_model)Built-in channels also include PhaseFlip, DepolarizingNoise, and PhaseDamping. Rules are applied after matching primitive gates. qubits matches target qubits, while gate_ids=None matches every physical primitive gate.
| Channel | Main parameter | Use |
|---|---|---|
BitFlip(p) | Probability p | Bit-flip error |
PhaseFlip(p) | Probability p | Phase error |
DepolarizingNoise(p) | Probability p | Symmetric Pauli noise |
AmplitudeDamping(gamma) | Damping rate gamma | Energy relaxation |
PhaseDamping(gamma) | Damping rate gamma | Dephasing |
Probabilities and damping rates must be within their valid ranges. Multiple matching rules are applied in configuration order.
The CPU and CUDA density-matrix backends both support projective circuit measurements, including mid-circuit measurement. device accepts "cpu", "gpu"/"cuda" (equivalent to "cuda:0"), or "cuda:<id>"; dtype supports np.complex64 and np.complex128. The CUDA backend requires unitarylab[cuda].
Public custom Kraus channels, pre-gate noise, correlated multi-qubit noise, and readout error are currently unsupported.
A density matrix contains complex values. Validate noise rules on small circuits and retain a noise-free baseline.
Circuit measurement and repeated execution
qc.measure([0, 1], [0, 1])
measured = qc.execute_density(device="cpu", shots=100, seed=42)
print(measured.counts)
print(measured.classical_results_map)Independent executions accumulate counts over shots. state and classical_results_map correspond to the final execution, while classical_registers groups results by register. Mid-circuit measurement collapses the density matrix and affects subsequent gates. seed=42 fixes the measurement random seed; None uses non-fixed sampling. Without circuit measurement, full-qubit counts are not generated implicitly.