--- name: qutip description: Simulate and audit closed and open quantum-system models with QuTiP 5, including deterministic, trajectory, steady-state, spectral, and phase-space workflows. Use for local quantum-dynamics work where physical assumptions, dimensions, and numerical convergence must be explicit. license: MIT compatibility: Requires Python 3.11+, uv, and qutip==5.3.0 for executable simulations. Bundled planners and all script help run with the Python standard library; plotting requires the pinned graphics extra. No network service or credentials are used. metadata: version: "1.1" skill-author: K-Dense Inc. last-reviewed: "2026-07-23" --- # QuTiP 5 ## Scope Use QuTiP for finite-dimensional quantum mechanics, quantum optics, Lindblad dynamics, trajectories, weak-coupling Bloch-Redfield models, and specialized Floquet, HEOM, and permutational-invariance methods. It is not a hardware execution SDK. Circuit and control functionality moved to separate QuTiP family packages. This skill targets **QuTiP 5.3.0**, released 2026-05-22. QuTiP 5.3 requires Python 3.11 or newer. Its required distributions are NumPy (`>=1.23.2`), SciPy (`>=1.9.2`, excluding `1.16.0` and `1.17.0`), and `packaging`. ## Reproducible uv snapshot Create a dedicated environment and pin every direct distribution: ```bash uv venv --python 3.11 uv pip install "qutip==5.3.0" ``` For plots: ```bash uv pip install "qutip[graphics]==5.3.0" ``` Optional QuTiP family packages are independently versioned: ```bash uv pip install "qutip-qip==0.4.2" uv pip install "qutip-qtrl==0.2.0" uv pip install "qutip-jax==0.1.1" ``` - `qutip-qip` 0.4.2 (2026-06-23) is the production/stable circuit, gate, and noisy-device simulation package. Import from `qutip_qip`, not `qutip.qip`. - `qutip-qtrl` 0.2.0 (2026-06-23) provides GRAPE and CRAB **quantum optimal control**. It is not a trajectory viewer. Import from `qutip_qtrl`, not `qutip.control`; PyPI still classifies it pre-alpha. - `qutip-jax` 0.1.1 (2025-05-29) is the official JAX data backend for GPU and automatic-differentiation experiments. It is explicitly pre-alpha. - `qutip-cupy` is an official QuTiP-organization repository, but it has no PyPI release and its own README says it is not officially released. Do not put an unreleased Git install into a reproducible workflow. Use a project lockfile or a hash-generating `uv pip compile` workflow when transitive dependency identity must also be frozen. ## Non-negotiable model contract Before solving, record: 1. **Units and convention.** QuTiP equations normally set \(\hbar=1\). Hamiltonian entries are angular frequencies and rates have reciprocal-time units. Convert cyclic frequency with \(2\pi f\); never mix Hz and rad/s. 2. **Subsystem order.** `tensor(A, B, C)` fixes subsystem indices `0, 1, 2`. Preserve that order in every state, operator, collapse channel, and partial trace. `obj.ptrace([0, 2])` keeps those subsystems; it does not trace them. 3. **State validity.** Check ket norm or density-matrix Hermiticity, unit trace, and eigenvalues above a stated negative tolerance. Tiny negative values may be numerical; material negativity invalidates a claimed state. 4. **Generator meaning.** A Lindblad channel with rate `gamma` is represented by `sqrt(gamma) * A`, not `gamma * A`. Define what each rate measures. For example, `sqrt(gamma_phi / 2) * sigmaz()` gives coherence decay `exp(-gamma_phi * t)`. 5. **Approximations.** State rotating-wave, Born-Markov, secular, weak-coupling, bath-equilibrium, truncation, symmetry, and initial-factorization assumptions wherever used. 6. **Numerics.** Justify Hilbert truncation, output grid, integration method, tolerances, trajectory count, and random seeds. Report `result.stats`. 7. **Convergence.** Sweep every artificial cutoff: Fock dimension, time/frequency window and spacing, ODE tolerances, trajectories, Floquet harmonics, HEOM depth and bath exponents, or PIQS representation as applicable. ## Qobj, dimensions, and tensor order Prefer explicit imports and inspect both shape and structured dimensions: ```python from qutip import basis, qeye, sigmaz, tensor psi = tensor(basis(2, 0), basis(3, 1)) z_on_first = tensor(sigmaz(), qeye(3)) assert psi.shape == (6, 1) assert psi.dims == [[2, 3], [1]] assert z_on_first.dims == [[2, 3], [2, 3]] rho_first = psi.proj().ptrace(0) # keep subsystem 0 ``` Matrix shape alone is insufficient: two objects can both be 6-by-6 but encode different tensor factorizations. Read `references/core_concepts.md` before building composite, superoperator, or channel models. ## Choose the solver by physics | Model | Current API | Required justification | |---|---|---| | Closed, pure, unitary | `sesolve` | Hermitian Hamiltonian; no dissipation | | Lindblad/open or mixed | `mesolve` | Markovian completely positive model and channel rates | | Quantum jumps | `mcsolve` | Unravelling, trajectory convergence, seeds | | Microscopic weak bath | `brmesolve` | Born-Markov/weak coupling, spectra, secular choice | | Diffusive measurement | `ssesolve`, `smesolve` | monitored versus unmonitored channels | | Periodic drive | `FloquetBasis`, `fsesolve`, `fmmesolve` | verified period and Floquet convergence | | Structured non-Markovian bath | `qutip.solver.heom` | bath expansion and hierarchy convergence | | Symmetric spin ensemble | `qutip.piqs` | permutation symmetry and basis choice | Do not select a more specialized solver merely because it exists. ## Deterministic open-system example QuTiP 5.3 uses ordinary option dictionaries. Solver controls, `e_ops`, and `args` are keyword-only; the old mutable options object is gone. ```python import numpy as np from qutip import basis, mesolve, sigmam, sigmaz omega = 2.0 gamma = 0.15 tlist = np.linspace(0.0, 20.0, 401) excited = basis(2, 0) result = mesolve( 0.5 * omega * sigmaz(), excited, tlist, c_ops=[np.sqrt(gamma) * sigmam()], e_ops={"sigma_z": sigmaz(), "excited": excited.proj()}, options={ "method": "adams", "atol": 1e-10, "rtol": 1e-8, "store_final_state": True, "progress_bar": "", }, ) population = np.asarray(result.e_data["excited"]) assert np.max(np.abs(population - np.exp(-gamma * tlist))) < 2e-6 assert isinstance(result.stats, dict) ``` If the problem is stiff, compare `bdf` or `lsoda`; do not change an integrator without rerunning tolerance and invariant checks. QuTiP 5.3 also supports `options={"matrix_form": True}` in `mesolve`; benchmark and validate it before using it as a default. ## Time-dependent systems Prefer trusted Pythonic callables or numeric coefficient arrays. Do not create coefficient source strings from user input. ```python import numpy as np from qutip import QobjEvo, sigmax, sigmaz def envelope(t, amplitude, center, width): return amplitude * np.exp(-0.5 * ((t - center) / width) ** 2) H = QobjEvo( [0.5 * sigmaz(), [sigmax(), envelope]], args={"amplitude": 0.2, "center": 5.0, "width": 1.0}, ) instantaneous_H = H(5.0) H.arguments(amplitude=0.1) ``` The older `f(t, args)` coefficient signature is deprecated in 5.3 and is scheduled for removal in 5.5. See `references/time_evolution.md`. ## Trajectories and stochastic solvers ```python import numpy as np from qutip import basis, mcsolve, sigmam, sigmaz tlist = np.linspace(0.0, 10.0, 201) result = mcsolve( 0.5 * sigmaz(), basis(2, 0), tlist, [np.sqrt(0.2) * sigmam()], e_ops=[basis(2, 0).proj()], ntraj=400, seeds=20260723, options={"keep_runs_results": False, "progress_bar": ""}, ) ``` Report `ntraj`, `result.seeds`, uncertainty or repeated-seed sensitivity, and whether individual runs were retained. Reuse `seeds=previous_result.seeds` only when paired trajectories are intentional. `ssesolve` and `smesolve` use the boolean `heterodyne` argument, not legacy integer noise codes. ## Steady states, spectra, and phase space ```python import numpy as np from qutip import QFunc, liouvillian, operator_to_vector, qfunc, steadystate rho_ss = steadystate(H, c_ops, method="direct") residual = (liouvillian(H, c_ops) * operator_to_vector(rho_ss)).norm() assert residual < 1e-9 xvec = np.linspace(-5.0, 5.0, 151) Q_once = qfunc(rho_ss, xvec, xvec) q_many = QFunc(xvec, xvec) Q_again = q_many(rho_ss) assert Q_once.shape == (len(xvec), len(xvec)) ``` For `wigner`, `qfunc`, and `QFunc`, array element `[j, k]` corresponds to `yvec[j]`, `xvec[k]`. In QuTiP 5.3, `QFunc` is initialized with fixed coordinates and called with a state; it has no `.eval` method. This skill never uses Python dynamic-code execution. Prefer `plot_wigner`, `Result.plot_expect`, or explicit Matplotlib axes as documented in `references/visualization.md`. Direct `spectrum` is a stationary steady-state spectrum. An FFT of a finite correlation requires explicit checks for tail decay, timestep aliasing, frequency resolution, window sensitivity, and transform convention. See `references/analysis.md`. ## Advanced boundaries - Import HEOM from `qutip.solver.heom`; the legacy QuTiP 4 nonmarkov HEOM namespace is stale. - Use `FloquetBasis` for modes and quasi-energies. Verify `H(t + T) == H(t)` numerically and sweep basis/truncation choices. - Access PIQS with `from qutip import piqs`. `Dicke.pisolve` is only the optimized diagonal-state/diagonal-Hamiltonian route; general Dicke-basis dynamics use the Liouvillian with `mesolve`. - `brmesolve` can violate positivity, especially without secularization. Check density-matrix eigenvalues over time. - QIP and optimal control are extension-package concerns. Never present local simulation as quantum-hardware execution. See `references/advanced.md` for HEOM, Floquet, PIQS, stochastic, and extension boundaries. ## Safe local CLIs All bundled tools are local-only, emit strict JSON, reject non-finite JSON and unknown keys, and never load pickle files or executable model code. Simulation imports are lazy, so every `--help` works without QuTiP installed. | Script | Purpose | |---|---| | `scripts/qobj_model_validator.py` | Validate bounded Qobj model JSON, dimensions, states, rates, and role compatibility | | `scripts/two_level_simulation.py` | Run a bounded two-level Lindblad or jump simulation | | `scripts/solver_config_planner.py` | Select a current solver and option/checklist plan | | `scripts/convergence_sweep.py` | Sweep tolerances/grid size or trajectory count on a synthetic model | | `scripts/result_audit.py` | Audit JSON output without deserializing Python objects | | `scripts/steady_state_spectrum_planner.py` | Plan bounded steady-state and direct/FFT spectral checks | Example: ```bash python skills/qutip/scripts/two_level_simulation.py --help python skills/qutip/scripts/two_level_simulation.py \ --decay-rate 0.2 --t-final 10 --time-points 201 \ --output two-level.json python skills/qutip/scripts/result_audit.py two-level.json ``` ## Completion checklist - Record units, \(\hbar\), tensor order, initial state, channels, and model assumptions. - Validate Hermiticity, norm/trace, positivity, dimensions, and generator units. - Pin QuTiP and direct extensions; record platform, Python, NumPy, and SciPy. - Inspect result options and stats; do not assume states were stored. - Perform cutoff, grid, tolerance/integrator, and stochastic convergence sweeps. - Save portable numeric/configuration summaries as JSON or text. Do not load untrusted QuTiP object/result files because object serialization can execute code. ## References - `references/core_concepts.md` — Qobj, dimensions, tensor products, states, channels, and unit conventions - `references/time_evolution.md` — current solver signatures, options, results, QobjEvo, trajectories, and numerical controls - `references/analysis.md` — physical-state audits, steady states, correlations, spectra, and convergence - `references/visualization.md` — Wigner, Q functions, `QFunc`, Bloch, result, and matrix plots - `references/advanced.md` — Bloch-Redfield, stochastic, Floquet, HEOM, PIQS, and QuTiP family package boundaries ## Dated official sources Verified **2026-07-23**: - [QuTiP 5.3.0 PyPI metadata](https://pypi.org/project/qutip/) - [QuTiP 5.3.0 release](https://github.com/qutip/qutip/releases/tag/v5.3.0) - [QuTiP 5.3 changelog](https://qutip.readthedocs.io/en/stable/changelog.html) - [QuTiP 5.3 API](https://qutip.readthedocs.io/en/stable/apidoc/apidoc.html) - [QuTiP version-5 tutorials](https://github.com/qutip/qutip-tutorials/tree/main/tutorials-v5) - [qutip-qip PyPI](https://pypi.org/project/qutip-qip/) - [qutip-qtrl PyPI](https://pypi.org/project/qutip-qtrl/) - [qutip-jax PyPI](https://pypi.org/project/qutip-jax/) - [official unreleased qutip-cupy repository](https://github.com/qutip/qutip-cupy)