skills/qutip/references/advanced.md
Research and API verification date: 2026-07-23. Examples target
qutip==5.3.0.
Specialized methods add assumptions and convergence parameters. Use them only when the physical model requires them.
brmesolve derives dissipative dynamics from system coupling operators and bath
noise-power spectra:
import numpy as np
from qutip import basis, brmesolve, sigmax, sigmaz
def bath_spectrum(w):
return 0.02 * w if w > 0.0 else 0.0
result = brmesolve(
0.5 * sigmaz(),
basis(2, 0),
np.linspace(0.0, 30.0, 601),
a_ops=[(sigmax(), bath_spectrum)],
e_ops={"z": sigmaz()},
sec_cutoff=0.1,
options={"atol": 1e-10, "rtol": 1e-8, "progress_bar": ""},
)
Required assumptions:
sec_cutoff=-1 disables secularization. QuTiP's documentation warns that the
non-secular equation may produce negativity. Inspect trace, Hermiticity, and
minimum density-matrix eigenvalue through the entire run.
Environment objects can express thermal and fitted spectra more clearly than callbacks. When using a callback, test it over every transition frequency and near zero.
Use ssesolve for conditioned pure states and smesolve for density matrices:
result = smesolve(
H,
rho0,
tlist,
c_ops=unmonitored_channels,
sc_ops=monitored_channels,
heterodyne=False,
e_ops={"signal": measured_quadrature},
ntraj=300,
seeds=20260723,
options={
"dt": 0.001,
"store_measurement": True,
"progress_bar": "",
},
)
heterodyne=False selects homodyne and True selects heterodyne. Legacy
integer noise selectors are stale.
Converge:
dt;"start" versus default end-of-step semantics when
relevant).SMESolver.run_from_experiment can replay known numeric noise or measurement
records. Treat records as bounded numeric data; do not accept executable
callbacks from untrusted configuration.
nm_mcsolve is for time-local master equations whose decay rates can become
negative. Its current input is a collection of operator/rate pairs, not a
generic two-time bath-correlation callback:
import numpy as np
from qutip import basis, nm_mcsolve, sigmam, sigmaz
def rate(t):
return 0.1 * np.cos(t)
result = nm_mcsolve(
0.5 * sigmaz(),
basis(2, 0),
np.linspace(0.0, 5.0, 101),
[(sigmam(), rate)],
e_ops=[basis(2, 0).proj()],
ntraj=400,
seeds=20260723,
options={"progress_bar": ""},
)
This method does not make an arbitrary non-Markovian model valid. Verify that the time-local generator and influence-martingale construction apply, report sampling uncertainty, and audit completeness/positivity behavior.
For (H(t+T)=H(t)), the current QuTiP 5 abstraction is FloquetBasis:
import numpy as np
from qutip import FloquetBasis, QobjEvo, sigmax, sigmaz
drive_frequency = 2.0
period = 2.0 * np.pi / drive_frequency
def drive(t, amplitude, omega):
return amplitude * np.cos(omega * t)
H = QobjEvo(
[0.5 * sigmaz(), [sigmax(), drive]],
args={"amplitude": 0.2, "omega": drive_frequency},
)
floquet = FloquetBasis(H, period)
quasienergies = floquet.e_quasi
modes_at_zero = floquet.mode(0.0)
Before using Floquet dynamics:
H(t + period) - H(t) over representative times;fsesolve handles closed periodic dynamics. fmmesolve handles a
Floquet-Markov construction:
result = fmmesolve(
floquet,
rho0,
tlist,
c_ops=coupling_operators,
spectra_cb=spectrum_callbacks,
e_ops={"z": sigmaz()},
w_th=temperature,
)
The coupling operators and spectrum callbacks are paired by position. They are
not ordinary Lindblad channels. Verify weak-coupling, bath, and thermal
assumptions. QuTiP 5 result states are in the lab basis by default; the
store_floquet_state option controls additional Floquet-basis storage.
Old free-function mode workflows may remain for compatibility, but new work
should use FloquetBasis.
Import from the current namespace:
from qutip.solver.heom import DrudeLorentzBath, HEOMSolver
The legacy QuTiP 4 nonmarkov HEOM namespace is stale.
Example:
import numpy as np
from qutip import basis, sigmax, sigmaz
from qutip.solver.heom import DrudeLorentzBath, HEOMSolver
H_system = 0.5 * sigmaz()
rho0 = basis(2, 0).proj()
bath = DrudeLorentzBath(
sigmax(),
lam=0.05,
gamma=1.0,
T=0.5,
Nk=3,
)
solver = HEOMSolver(
H_system,
bath,
max_depth=4,
options={
"atol": 1e-10,
"rtol": 1e-8,
"store_states": True,
"store_ados": False,
"progress_bar": "",
},
)
result = solver.run(rho0, np.linspace(0.0, 10.0, 201))
reduced_states = result.states
For arbitrary exponential expansions, the full current constructor is:
BosonicBath(Q, ck_real, vk_real, ck_imag, vk_imag,
combine=True, tag=None)
Do not omit the imaginary coefficient/frequency lists; use empty lists only when the modeled correlation genuinely has no imaginary expansion.
HEOM convergence requires independent sweeps of:
max_depth;Nk or fitted exponent count);Record (\lambda), cutoff, temperature, and all energies in one consistent (\hbar=k_B=1) unit convention if that convention is used.
result.states are reduced system states. Set store_ados=True only when the
full auxiliary-density hierarchy is needed; then result.ado_states can be
large. A previous final ADO state may initialize a continuation only when its
hierarchy is compatible.
HEOM can mix supported bosonic and fermionic baths. Fermionic odd parity is a special solver construction and must match the initial operator parity.
In QuTiP 5.3, use the piqs module exported by qutip:
import numpy as np
from qutip import mesolve, piqs
N = 10
Jz = piqs.jspin(N, "z", basis="dicke")
rho0 = piqs.dicke(N, N / 2, N / 2)
ensemble = piqs.Dicke(
N,
emission=0.05,
dephasing=0.01,
collective_emission=0.02,
)
L = ensemble.liouvillian()
result = mesolve(
L,
rho0,
np.linspace(0.0, 20.0, 201),
e_ops={"Jz": Jz},
)
piqs.Dicke.pisolve(initial_state, tlist) is an optimized method only for
diagonal Hamiltonians and diagonal initial density matrices. It takes no
e_ops; use the general Liouvillian path for arbitrary observables and
non-diagonal cases.
PIQS exploits permutation symmetry in a Dicke basis. Before using it:
dicke or uncoupled basis;piqs.collapse_uncoupled returns ordinary collapse operators in a (2^N)
space and is only practical for modest N.
Current conversions:
from qutip import (
choi_to_kraus,
choi_to_super,
kraus_to_super,
operator_to_vector,
spre,
spost,
super_to_choi,
super_to_kraus,
vector_to_operator,
)
QuTiP column-stacks vectorized operators. Use the conversion functions rather than manual reshape logic. Check complete positivity and trace preservation in the intended representation, and preserve structured dimensions.
Official PyPI metadata snapshot:
| Distribution | Latest published | Release date | Maturity | Requires-Python | Required distributions |
|---|---|---|---|---|---|
qutip | 5.3.0 | 2026-05-22 | production/stable | >=3.11 | NumPy >=1.23.2; SciPy >=1.9.2 except 1.16.0/1.17.0; packaging |
qutip-qip | 0.4.2 | 2026-06-23 | production/stable | not declared | NumPy >=1.16.6; SciPy >=1.0; QuTiP >=4.6; packaging |
qutip-qtrl | 0.2.0 | 2026-06-23 | pre-alpha classifier | not declared | NumPy >=1.19; SciPy >=1.0; QuTiP >=5.0.1; packaging |
qutip-jax | 0.1.1 | 2025-05-29 | pre-alpha classifier | not declared | QuTiP >=5.1.0; JAX; Diffrax; Equinox |
qutip-cupy | no PyPI project | — | unreleased repository | — | no released metadata |
“Not declared” means the current PyPI Requires-Python field is empty, not
that every Python release is supported. Resolve and test each extension in the
same Python 3.11+ environment as QuTiP 5.3. Direct pins do not freeze transitive
JAX/CuPy stacks; use a lockfile for a deployable environment.
Status: production/stable on PyPI, released 2026-06-23.
Purpose:
QubitCircuit unitary circuit simulation;Processor pulse/noise/open-system device simulation.Migration boundary:
from qutip_qip.circuit import QubitCircuit
Do not import qutip.qip in QuTiP 5 code. This package is a local simulator,
not a hardware provider or execution service.
Status: latest published release 2026-06-23; PyPI classifier is pre-alpha.
Purpose: quantum optimal control with GRAPE and CRAB, emphasizing integration with QuTiP physics models.
Migration boundary:
from qutip_qtrl import pulseoptim
It replaces the old qutip.control import. It is not a trajectory viewer.
Optimization success does not establish robustness: report bounds, objective,
gradient/termination status, seeds, discretization, and validation under model
uncertainty.
Status: latest published release 2025-05-29; explicitly pre-alpha and described as not ready for production use.
Purpose: a JAX linear-algebra data backend for GPU execution and automatic differentiation. It depends on QuTiP 5.1 or newer plus JAX, Diffrax, and Equinox.
Validate dtype, device placement, JIT/gradient support for each operation, and results against the built-in QuTiP data backend.
The repository belongs to the QuTiP GitHub organization and implements a CuPy data backend, but:
qutip-cupy project;Do not recommend it as a stable extension. If a user explicitly accepts an experimental source build, isolate and audit that separately rather than adding it to this pinned skill snapshot.
mcsolve/stochastic solvers expose map, num_cpus, and related options.
Parallelism changes scheduling and cost, not the required trajectory
convergence.parallel_map executes Python callables. Use only trusted, statically defined
local functions and bounded task lists.matrix_form option for mesolve and new Krylov density-matrix
support are performance choices that require output equivalence tests.