← Về thư mục
📄 / / profiles / r-and-d / raw_evidence / scientific-agent-skills / skills / qutip / references / advanced.md

QuTiP 5.3 Advanced Methods and Package Boundaries

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.

Bloch-Redfield

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.

Diffusive stochastic evolution

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:

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.

Non-Markovian Monte Carlo with time-local rates

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.

Floquet theory

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:

  1. numerically check H(t + period) - H(t) over representative times;
  2. state the quasi-energy branch convention;
  3. sweep Hilbert truncation and any precomputation grid;
  4. inspect near-degenerate quasi-energies;
  5. compare one-period propagation with direct evolution.

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.

HEOM

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:

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.

Permutational invariance (PIQS)

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:

piqs.collapse_uncoupled returns ordinary collapse operators in a (2^N) space and is only practical for modest N.

Superoperators and channels

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.

QuTiP family packages

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.

qutip-qip 0.4.2

Status: production/stable on PyPI, released 2026-06-23.

Purpose:

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.

qutip-qtrl 0.2.0

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.

qutip-jax 0.1.1

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.

qutip-cupy

The repository belongs to the QuTiP GitHub organization and implements a CuPy data backend, but:

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.

Parallel and performance boundaries

Sources (verified 2026-07-23)