Skill Tracer
Skills › Scientific Agent Skills › qutip › core_concepts.md

core_concepts.md

299 lines · skills/qutip/references/core_concepts.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# QuTiP 5.3 Core Concepts
2
3Research and API verification date: **2026-10-01**. Examples target
4`qutip==5.3.1`.
5

QuTiP 5.3 Core Concepts

Research and API verification date: 2026-10-01. Examples target qutip==5.3.1.

Raw lines 1 to 5
6## Units and the equation being solved
7
8QuTiP does not attach physical units. The standard solver equations use
9\(\hbar=1\), so a Hamiltonian has angular-frequency units and time has reciprocal
10units:
12\[
13\dot{\rho}=-i[H,\rho]+\sum_k\left(C_k\rho C_k^\dagger
14-\tfrac12\{C_k^\dagger C_k,\rho\}\right).
15\]
17Choose one unit system and state it in reports:
19- if time is ns, Hamiltonian coefficients and rates are in ns\(^{-1}\);
20- a frequency quoted in cycles/time becomes angular frequency \(2\pi f\);
21- temperature in HEOM or thermal spectra must be converted consistently with
22 \(k_B=1\) only if that convention was explicitly selected.
24Dimensional consistency is a model property, not something QuTiP can infer.

Units and the equation being solved

QuTiP does not attach physical units. The standard solver equations use \(\hbar=1\), so a Hamiltonian has angular-frequency units and time has reciprocal units:

\[ \dot{\rho}=-i[H,\rho]+\sum_k\left(C_k\rho C_k^\dagger -\tfrac12\{C_k^\dagger C_k,\rho\}\right). \]

Choose one unit system and state it in reports:

  • if time is ns, Hamiltonian coefficients and rates are in ns\(^{-1}\);
  • a frequency quoted in cycles/time becomes angular frequency \(2\pi f\);
  • temperature in HEOM or thermal spectra must be converted consistently with \(k_B=1\) only if that convention was explicitly selected.

Dimensional consistency is a model property, not something QuTiP can infer.

Raw lines 6 to 25
26## Qobj structure
28`Qobj` stores numerical data plus quantum dimension metadata:
30```python
31from qutip import Qobj, basis, sigmaz
33ket = basis(2, 0)
34rho = ket.proj()
35H = 0.5 * sigmaz()
37assert ket.isket and ket.dims == [[2], [1]]
38assert rho.isoper and rho.dims == [[2], [2]]
39assert H.isherm
40```
42Important properties and methods:
44| API | Meaning |
45|---|---|
46| `.dims` | Structured input/output Hilbert spaces |
47| `.shape` | Flattened matrix shape |
48| `.type` | `ket`, `bra`, `oper`, `super`, `operator-ket`, or `operator-bra` |
49| `.isket`, `.isoper`, `.issuper` | Semantic type checks |
50| `.isherm`, `.isunitary` | Cached/computed structural properties |
51| `.dag()` | Adjoint |
52| `.tr()` | Trace |
53| `.norm()` | L2 norm for kets by default; trace norm for operators by default |
54| `.proj()` | Ket/bra projector |
55| `.ptrace(sel)` | Keep selected subsystems and trace out the rest |
56| `.full()` | Dense matrix with flattened shape |
57| `.full_tensor()` | QuTiP 5.3 dense array reshaped by tensor dimensions |
59Construct raw `Qobj` values only when built-in constructors are unsuitable:
61```python
62from qutip import Qobj
64rho = Qobj(
65 [[0.75, 0.1], [0.1, 0.25]],
66 dims=[[2], [2]],
68```
70Supplying correct matrix shape with incorrect `dims` can invalidate later
71tensor, partial-trace, and superoperator operations.

Qobj structure

Qobj stores numerical data plus quantum dimension metadata:

from qutip import Qobj, basis, sigmaz

ket = basis(2, 0)
rho = ket.proj()
H = 0.5 * sigmaz()

assert ket.isket and ket.dims == [[2], [1]]
assert rho.isoper and rho.dims == [[2], [2]]
assert H.isherm

Important properties and methods:

APIMeaning
.dimsStructured input/output Hilbert spaces
.shapeFlattened matrix shape
.typeket, bra, oper, super, operator-ket, or operator-bra
.isket, .isoper, .issuperSemantic type checks
.isherm, .isunitaryCached/computed structural properties
.dag()Adjoint
.tr()Trace
.norm()L2 norm for kets by default; trace norm for operators by default
.proj()Ket/bra projector
.ptrace(sel)Keep selected subsystems and trace out the rest
.full()Dense matrix with flattened shape
.full_tensor()QuTiP 5.3 dense array reshaped by tensor dimensions

Construct raw Qobj values only when built-in constructors are unsuitable:

from qutip import Qobj

rho = Qobj(
    [[0.75, 0.1], [0.1, 0.25]],
    dims=[[2], [2]],
)

Supplying correct matrix shape with incorrect dims can invalidate later tensor, partial-trace, and superoperator operations.

Raw lines 26 to 72
73## States and physicality

States and physicality

Raw lines 73 to 74
75### Kets
77```python
78from qutip import basis, coherent
80qubit = (basis(2, 0) + basis(2, 1)).unit()
81oscillator = coherent(30, 1.5)
83assert abs(qubit.norm() - 1.0) < 1e-12
84```

Kets

from qutip import basis, coherent

qubit = (basis(2, 0) + basis(2, 1)).unit()
oscillator = coherent(30, 1.5)

assert abs(qubit.norm() - 1.0) < 1e-12
Raw lines 75 to 85
86### Density matrices
88A physical finite-dimensional density matrix is Hermitian, trace one, and
89positive semidefinite:
91```python
92import numpy as np
93from qutip import thermal_dm
95rho = thermal_dm(20, 0.7)
96tol = 1e-10
97eigenvalues = np.asarray(rho.eigenenergies(), dtype=float)
99assert rho.isherm
100assert abs(complex(rho.tr()) - 1.0) < tol
101assert eigenvalues.min() >= -tol
102```
104Use a tolerance tied to solver error and matrix scale. Report the minimum
105eigenvalue instead of silently clipping it. If a method such as non-secular
106Bloch-Redfield produces material negativity, revisit its physical assumptions.
108Common constructors:
110```python
111from qutip import (
112 basis,
113 coherent,
114 coherent_dm,
115 fock,
116 fock_dm,
117 maximally_mixed_dm,
118 thermal_dm,
121psi_n = fock(16, 3)
122rho_n = fock_dm(16, 3)
123psi_alpha = coherent(24, 1.2)
124rho_alpha = coherent_dm(24, 1.2)
125rho_th = thermal_dm(24, 0.5)
126rho_mix = maximally_mixed_dm([2, 2])
127```
129Oscillator constructors use a finite truncation. Sweep the cutoff and monitor
130edge population, observables, and state trace. A normalized truncated state is
131not by itself evidence that the cutoff is adequate.

Density matrices

A physical finite-dimensional density matrix is Hermitian, trace one, and positive semidefinite:

import numpy as np
from qutip import thermal_dm

rho = thermal_dm(20, 0.7)
tol = 1e-10
eigenvalues = np.asarray(rho.eigenenergies(), dtype=float)

assert rho.isherm
assert abs(complex(rho.tr()) - 1.0) < tol
assert eigenvalues.min() >= -tol

Use a tolerance tied to solver error and matrix scale. Report the minimum eigenvalue instead of silently clipping it. If a method such as non-secular Bloch-Redfield produces material negativity, revisit its physical assumptions.

Common constructors:

from qutip import (
    basis,
    coherent,
    coherent_dm,
    fock,
    fock_dm,
    maximally_mixed_dm,
    thermal_dm,
)

psi_n = fock(16, 3)
rho_n = fock_dm(16, 3)
psi_alpha = coherent(24, 1.2)
rho_alpha = coherent_dm(24, 1.2)
rho_th = thermal_dm(24, 0.5)
rho_mix = maximally_mixed_dm([2, 2])

Oscillator constructors use a finite truncation. Sweep the cutoff and monitor edge population, observables, and state trace. A normalized truncated state is not by itself evidence that the cutoff is adequate.

Raw lines 86 to 132
133## Tensor products and subsystem order
135Arguments to `tensor` define subsystem order from left to right:
137```python
138from qutip import basis, destroy, qeye, sigmaz, tensor
140N = 12
141psi = tensor(basis(N, 2), basis(2, 0)) # cavity index 0, qubit index 1
142a = tensor(destroy(N), qeye(2))
143sz = tensor(qeye(N), sigmaz())
145assert psi.dims == [[N, 2], [1]]
146assert a.dims == [[N, 2], [N, 2]]
147assert sz.dims == a.dims
148```
150`Qobj.ptrace(sel)` keeps `sel`:
152```python
153rho = psi.proj()
154rho_cavity = rho.ptrace(0)
155rho_qubit = rho.ptrace(1)
156```
158The selected subsystems remain in their original order even if `sel` is passed
159in another order. Use `permute` when an explicit subsystem reordering is
160intended.
162For a composite operator with `dims == [[2, 3], [2, 3]]`,
163`full_tensor().shape` is `(2, 3, 2, 3)`. Treat this as a useful dimensional
164audit, not a replacement for documenting subsystem labels.

Tensor products and subsystem order

Arguments to tensor define subsystem order from left to right:

from qutip import basis, destroy, qeye, sigmaz, tensor

N = 12
psi = tensor(basis(N, 2), basis(2, 0))  # cavity index 0, qubit index 1
a = tensor(destroy(N), qeye(2))
sz = tensor(qeye(N), sigmaz())

assert psi.dims == [[N, 2], [1]]
assert a.dims == [[N, 2], [N, 2]]
assert sz.dims == a.dims

Qobj.ptrace(sel) keeps sel:

rho = psi.proj()
rho_cavity = rho.ptrace(0)
rho_qubit = rho.ptrace(1)

The selected subsystems remain in their original order even if sel is passed in another order. Use permute when an explicit subsystem reordering is intended.

For a composite operator with dims == [[2, 3], [2, 3]], full_tensor().shape is (2, 3, 2, 3). Treat this as a useful dimensional audit, not a replacement for documenting subsystem labels.

Raw lines 133 to 165
166## Operators and observables
168```python
169from qutip import create, destroy, jmat, num, sigmam, sigmap, sigmax, sigmay, sigmaz
171N = 20
172a = destroy(N)
173adag = create(N)
174n = num(N)
175sx, sy, sz = sigmax(), sigmay(), sigmaz()
176sm, sp = sigmam(), sigmap()
177Jx = jmat(1, "x")
178```
180Hamiltonians and ideal observables should be Hermitian within tolerance.
181Collapse operators generally need not be Hermitian.
183Expectation and variance:
185```python
186from qutip import expect, variance
188mean_n = expect(n, rho)
189var_n = variance(n, rho)
190```
192Do not interpret a visibly non-real expectation of a Hermitian observable as a
193physical value; first audit Hermiticity, state validity, dimensions, and solver
194accuracy.

Operators and observables

from qutip import create, destroy, jmat, num, sigmam, sigmap, sigmax, sigmay, sigmaz

N = 20
a = destroy(N)
adag = create(N)
n = num(N)
sx, sy, sz = sigmax(), sigmay(), sigmaz()
sm, sp = sigmam(), sigmap()
Jx = jmat(1, "x")

Hamiltonians and ideal observables should be Hermitian within tolerance. Collapse operators generally need not be Hermitian.

Expectation and variance:

from qutip import expect, variance

mean_n = expect(n, rho)
var_n = variance(n, rho)

Do not interpret a visibly non-real expectation of a Hermitian observable as a physical value; first audit Hermiticity, state validity, dimensions, and solver accuracy.

Raw lines 166 to 195
196## Collapse operators and rate conventions
198If a dissipator is written as \(\gamma\,\mathcal{D}[A]\rho\), pass
199\(C=\sqrt{\gamma}A\):
201```python
202import numpy as np
203from qutip import sigmam, sigmaz
205gamma_down = 0.2
206gamma_phi = 0.05 # desired off-diagonal coherence decay
207c_ops = [
208 np.sqrt(gamma_down) * sigmam(),
209 np.sqrt(gamma_phi / 2.0) * sigmaz(),
211```
213The factor for dephasing depends on how a publication defines its dephasing
214rate. Derive the matrix-element decay for the chosen dissipator and test it on
215a two-level state instead of copying a symbol by name.
217For a thermal oscillator with occupation \(n_\mathrm{th}\):
219```python
220c_ops = [
221 np.sqrt(kappa * (n_th + 1.0)) * a,
222 np.sqrt(kappa * n_th) * a.dag(),
224```
226Rates must be finite and nonnegative in standard Lindblad form. Time-dependent
227rates require extra care: a coefficient multiplies the collapse **amplitude**,
228so a target rate \(\gamma(t)\) needs an amplitude proportional to
229\(\sqrt{\gamma(t)}\).

Collapse operators and rate conventions

If a dissipator is written as \(\gamma\,\mathcal{D}[A]\rho\), pass \(C=\sqrt{\gamma}A\):

import numpy as np
from qutip import sigmam, sigmaz

gamma_down = 0.2
gamma_phi = 0.05  # desired off-diagonal coherence decay
c_ops = [
    np.sqrt(gamma_down) * sigmam(),
    np.sqrt(gamma_phi / 2.0) * sigmaz(),
]

The factor for dephasing depends on how a publication defines its dephasing rate. Derive the matrix-element decay for the chosen dissipator and test it on a two-level state instead of copying a symbol by name.

For a thermal oscillator with occupation \(n_\mathrm{th}\):

c_ops = [
    np.sqrt(kappa * (n_th + 1.0)) * a,
    np.sqrt(kappa * n_th) * a.dag(),
]

Rates must be finite and nonnegative in standard Lindblad form. Time-dependent rates require extra care: a coefficient multiplies the collapse amplitude, so a target rate \(\gamma(t)\) needs an amplitude proportional to \(\sqrt{\gamma(t)}\).

Raw lines 196 to 230
231## Liouvillians and vectorization
233```python
234from qutip import liouvillian, operator_to_vector, vector_to_operator
236L = liouvillian(H, c_ops)
237rho_vec = operator_to_vector(rho)
238derivative = L * rho_vec
239rho_roundtrip = vector_to_operator(rho_vec)
241assert L.issuper
242assert (rho_roundtrip - rho).norm() < 1e-12
243```
245QuTiP uses column-stacked operator vectorization. Use
246`operator_to_vector`/`vector_to_operator`; do not reproduce reshape order by
247guesswork.
249Useful superoperator constructors and conversions include:
251```python
252from qutip import (
253 kraus_to_super,
254 spost,
255 spre,
256 sprepost,
257 to_choi,
258 to_kraus,
259 to_super,
261```
263For a quantum channel, check the intended representation and the map properties
264such as complete positivity and trace preservation. QuTiP exposes properties
265including `iscp`, `istp`, and `iscptp` on suitable map objects.

Liouvillians and vectorization

from qutip import liouvillian, operator_to_vector, vector_to_operator

L = liouvillian(H, c_ops)
rho_vec = operator_to_vector(rho)
derivative = L * rho_vec
rho_roundtrip = vector_to_operator(rho_vec)

assert L.issuper
assert (rho_roundtrip - rho).norm() < 1e-12

QuTiP uses column-stacked operator vectorization. Use operator_to_vector/vector_to_operator; do not reproduce reshape order by guesswork.

Useful superoperator constructors and conversions include:

from qutip import (
    kraus_to_super,
    spost,
    spre,
    sprepost,
    to_choi,
    to_kraus,
    to_super,
)

For a quantum channel, check the intended representation and the map properties such as complete positivity and trace preservation. QuTiP exposes properties including iscp, istp, and iscptp on suitable map objects.

Raw lines 231 to 266
267## Truncation and basis audits
269For every truncated bosonic or spin model:
2711. increase each cutoff independently;
2722. compare the actual reported observables, not only energies;
2733. inspect occupation near the cutoff;
2744. recheck all tensor dimensions after changing a cutoff;
2755. state whether the model is in a bare, dressed, rotating, Floquet, Dicke, or
276 other basis;
2776. document every rotating-wave or excitation-number restriction.
279An excitation-number-restricted space does not have the same factorization as
280the corresponding full tensor space. Do not apply subsystem operations unless
281their meaning in the restricted representation is established.

Truncation and basis audits

For every truncated bosonic or spin model:

  1. increase each cutoff independently;
  2. compare the actual reported observables, not only energies;
  3. inspect occupation near the cutoff;
  4. recheck all tensor dimensions after changing a cutoff;
  5. state whether the model is in a bare, dressed, rotating, Floquet, Dicke, or other basis;
  6. document every rotating-wave or excitation-number restriction.

An excitation-number-restricted space does not have the same factorization as the corresponding full tensor space. Do not apply subsystem operations unless their meaning in the restricted representation is established.

Raw lines 267 to 282
283## Local model validation
285`../scripts/qobj_model_validator.py` accepts a bounded strict-JSON model made
286only of numeric arrays. It rejects URLs, symlinks, duplicate keys, non-finite
287numbers, unknown roles, executable coefficients, dimensions whose product
288exceeds 64, and incompatible subsystem structures. It checks Hamiltonian and
289observable Hermiticity, initial-state norm/trace/positivity, and nonnegative
290collapse rates.
292It is a preflight audit, not a proof that the physical model is appropriate.

Local model validation

../scripts/qobj_model_validator.py accepts a bounded strict-JSON model made only of numeric arrays. It rejects URLs, symlinks, duplicate keys, non-finite numbers, unknown roles, executable coefficients, dimensions whose product exceeds 64, and incompatible subsystem structures. It checks Hamiltonian and observable Hermiticity, initial-state norm/trace/positivity, and nonnegative collapse rates.

It is a preflight audit, not a proof that the physical model is appropriate.

Raw lines 283 to 293
Runs code scripts/qobj_model_validator.py :285
294## Sources (verified 2026-10-01)
296- [QuTiP 5.3 quantum-object API](https://qutip.readthedocs.io/en/stable/apidoc/quantumobject.html)
297- [Tensor-product guide](https://qutip.readthedocs.io/en/stable/guide/guide-tensor.html)
298- [QuTiP 5.3.1 release notes](https://github.com/qutip/qutip/releases/tag/v5.3.1)
299- [QuTiP 5.3 changelog](https://qutip.readthedocs.io/en/stable/changelog.html)