Noisy Analog Simulation¶
This guide walks through an open-system analog simulation with the tensor jump method (TJM): build a Hamiltonian, attach a noise model, configure AnalogSimParams, and visualize time-resolved observables.
For log-normal disorder on strengths and static calibration spread, see Realistic Noise Models. For execution options (parallelism, progress bars), see Configuring the Simulator. To build Ising, Hubbard, Pauli-string, or hardware Hamiltonians, see Building Hamiltonians.
1. Hamiltonian¶
1from mqt.yaqs import Hamiltonian
2
3L = 5
4J, g = 1.0, 0.8
5H_0 = Hamiltonian.ising(L, J, g)
See Building Hamiltonians for Pauli sums, Fermi–Hubbard, Bose–Hubbard, and coupled-transmon factories.
2. Initial state and noise model¶
We prepare a Néel state \(\ket{01010\ldots}\) and track staggered magnetization under a transverse-field Ising model with on-site amplitude damping. The alternating \(\langle Z_i \rangle\) pattern at \(t=0\) spreads and decays in a site-dependent way.
1from mqt.yaqs import NoiseModel, State
2
3state = State(L, initial="Neel")
4
5gamma = 0.08
6noise_model = NoiseModel([
7 {"name": "lowering", "sites": [i], "strength": gamma} for i in range(L)
8])
Pass a float for each strength here. For distribution-valued strengths (log-normal and other distributions), see Realistic Noise Models.
3. Simulation parameters¶
1from mqt.yaqs import AnalogSimParams, Observable
2
3sim_params = AnalogSimParams(
4 observables=[Observable("z", site) for site in range(L)],
5 elapsed_time=6.0,
6 dt=0.1,
7 num_traj=20,
8 max_bond_dim=16,
9 svd_threshold=1e-6,
10 order=2,
11 sample_timesteps=True,
12)
Optional tdvp_sweeps (default 1) runs multiple symmetric TDVP substeps per physical step dt, improving unitary accuracy without changing the noise timestep.
Evolution integrator: analog simulations default to EvolutionMode.TDVP (two-site TDVP sweeps). EvolutionMode.BUG is available as an alternative on AnalogSimParams when you want the BUG integrator instead.
4. Reproducible stochastic runs¶
With num_traj > 1, each run() call averages independent quantum-jump trajectories. Set random_seed to fix the pseudorandom stream across trajectories (and for distribution-valued noise strengths):
1import copy
2
3import numpy as np
4
5from mqt.yaqs import AnalogSimParams, Observable, Simulator
6
7repro_params = AnalogSimParams(
8 observables=[Observable("z", site) for site in range(L)],
9 elapsed_time=1.0,
10 dt=0.1,
11 num_traj=16,
12 max_bond_dim=4,
13 svd_threshold=1e-6,
14 order=2,
15 sample_timesteps=True,
16 random_seed=42,
17)
18
19sim = Simulator(parallel=True, show_progress=False)
20
21
22def run_reproducible() -> list[np.ndarray]:
23 st = copy.deepcopy(state)
24 params = copy.deepcopy(repro_params)
25 result = sim.run(st, H_0, params, copy.deepcopy(noise_model))
26 return result.expectation_values
27
28
29first_run = run_reproducible()
30second_run = run_reproducible()
The same random_seed field exists on StrongSimParams and WeakSimParams.
5. Run and visualize¶
1result = sim.run(state, H_0, sim_params, noise_model)
1import matplotlib.pyplot as plt
2
3heatmap = result.expectation_values
4
5fig, ax = plt.subplots(figsize=(7, 4), layout="constrained")
6im = ax.imshow(heatmap, aspect="auto", extent=(0, 6, L, 0), vmin=-1, vmax=1)
7ax.set_xlabel("Time")
8ax.set_yticks([x - 0.5 for x in range(1, L + 1)], [str(x) for x in range(L)])
9ax.set_ylabel("Site")
10fig.colorbar(im, ax=ax, shrink=0.9, label=r"$\langle Z \rangle$")
11plt.show()