Quick reference

The whole library on one page, for a reader who knows quantum mechanics and wants a correct computation quickly, a person or an AI. ?name at the Julia prompt, or println(@doc name) in a script after using REPL, gives the details of any function or type below, that of a site type, as ?Qubit, its states and its operators, and that of an operator, as ?X, what it is on each site type that has it.

Loading

using TensorMixedStates, .Qubits, .Fermions, .Bosons   # the module of each site type: also
                                                      # .Spins, .Electrons, .Tjs, .Qudits, .Qbosons
using .Circuits                                       # the gates: H, S, T, rotations, CX

These modules bring short names, as N or H: a script using them as variables takes only what it needs, using .Qubits: Qubit, X, Z, or writes them qualified after import .Qubits as Q, as Q.X(1).

Run scripts with julia --threads=auto script.jl. The first call of a session compiles, a few seconds; the precompiled workload covers the common paths.

Systems and states

sys = System(10, Qubit())                          # 10 qubits
mixed_sys = System([Qubit(), Boson(4), Fermion()]) # sites of several types
ψ = State{Pure}(sys, "Up")                         # a product state, the same on every site
ψ = State{Pure}(sys, [isodd(i) ? "Up" : "Dn" for i in 1:10])
ρ = State{Mixed}(sys, "FullyMixed")                # density matrices are Mixed
ρ = mix(ψ)                                         # |ψ⟩⟨ψ|
ψ = random_state(Pure, sys, 8)                     # random, bond dimension 8
ψ = ghz_state(sys, "Up", "Dn")                     # also dicke_state, w_state, dimer_state,
                                                   # fermi_sea, slater_state, fully_mixed,
                                                   # graph_state (Qubits), aklt_state (Spins)
ψ2 = ψ ⊗ State{Pure}(System(2, Qubit()), "Up")     # on sys ⊗ System(2, Qubit()), 12 sites
ψ3 = permute_sites(ψ2, p)                          # site k moved to position p[k]

A local state is a name of the site ("Up", "Dn", "+", "0", "1" on a qubit), a vector, a density matrix, or Level => n, the basis state n counted from 0. Conservation: a site Qubit(conserve = N), Fermion(conserve = N), on a mixed state also conserve = strong(N); weaken(state) drops a level of it.

Operators

ham = -sum(Z(i) * Z(i + 1) for i in 1:9) - 0.5 * sum(X(i) for i in 1:10) # X(i): X on site i;
                                          # not H, the Hadamard gate of Circuits
hop = -sum(dag(C)(i) * C(i + 1) + dag(C)(i + 1) * C(i) for i in 1:9)      # fermions: strings
                                                                         # laid automatically
L = -im * ham + sum(Dissipator(sqrt(0.1) * Sm)(i) for i in 1:10)          # a Lindbladian
gates = CX(1, 2) * H(1)                   # a product acts right to left: H first
noisy = depolarizing_channel(0.01)(3)        # a channel, for a mixed state
myop = named([1 1 ; 1 -1] / √2, "MyOp")   # an operator of one's own

X, Y, Z, Sp, Sm, N on qubits; C, N on fermions; A, N on bosons; Sx, Sy, Sz, Sp, Sm on spins; Id, F, Level, Swap and controlled on every site; the gates H, S, T, Phase(θ), Rx(θ), Ry, Rz, Rxx(θ), Ryy, Rzz, CX or CNOT, CY, CZ, CCX or Toffoli in Circuits. ⊗ makes an operator of several sites, X ⊗ X, placed by (X ⊗ X)(2, 5); exp, sqrt, dag, Proj("Up") and Proj(Z => 1) work on operators, and dag or ' on placed ones too, h + h'.

Conventions

whatconvention
the evolver-im * H plus dissipators: $d\psi/dt = -iH\psi$, $\hbar = 1$
a jump operatorDissipator(L), $L\rho L^\dagger - \frac12\{L^\dagger L, \rho\}$; Dissipator(c * L) is abs2(c) * Dissipator(L), so a rate $\gamma$ is γ * Dissipator(L)
qubit states"Up" = $\vert 0\rangle$, "Dn" = $\vert 1\rangle$; Z is +1 on "Up"; N counts "Dn"; Sp takes "Dn" to "Up"
amplitude dampingamplitude_damping_channel(p), amplitude_damping_dissipator(γ): "Dn" decays to "Up"
depolarizationdepolarizing_channel(p) is $(1-p)\rho + p\,I/d$: each Pauli error with probability $p/3$ is depolarizing_channel(4p/3)
a product of gatesthe rightmost factor acts first
rotationsRx(θ) is $e^{-i\theta X/2}$ and Rxx(θ) $e^{-i\theta X \otimes X/2}$, as in OpenQASM and Qiskit; Rx(θ) is $e^{-i\theta S_x}$ on a spin
values measuredby measure, expect, expect1 and expect2 alike, real for a Hermitian operator, complex otherwise; expect(ψ, op; complex = true) the complex number computed; Trace and trace complex

Solvers

lim = Limits(maxdim = 100)          # truncation: cutoff (default 1e-26, rounding), maxdim, mindim
E, gs = ground_state(ham, random_state(Pure, sys, 8); algo = Dmrg(nsweeps = 10), limits = lim)
E1, ex = ground_state(ham, random_state(Pure, sys, 8); algo = Dmrg(nsweeps = 20), limits = lim,
                      orthogonal_to = [gs])                     # the first excited state
ψt = evolve(-im * ham, 1.0, gs; nsteps = 20, limits = lim)        # algo = Tdvp() by default
ρt = evolve(L, 1.0, mix(gs); algo = ApproxW(order = 4), nsteps = 20, limits = lim)
v, ρs = steady_state(L, mix(gs); algo = Dmrg(nsweeps = 10), limits = lim)
lt, ρβ = thermalize(ham, 0.5, State{Mixed}(sys, "FullyMixed"); nsteps = 10, limits = lim)
                                                                # lt = log Z - Σ log dᵢ
ψg = apply(gates, State{Pure}(sys, "Up"); limits = lim)

Every field of the options at its default, but nsweeps and order, which have none; ?Dmrg and the others say what each does:

Limits(cutoff = nothing, maxdim = nothing, mindim = nothing)  # nothing: the default of the
                                                              # function; a vector, one value
                                                              # per step or per sweep
Dmrg(nsweeps = 10, noise = 0, krylov = Krylov(), tol = 0)     # tol = 0: every sweep is made
Tdvp(krylov = Krylov(), expand_period = 0, hermitianize_period = 0)       # a period 0: never
ApproxW(order = 4, w = 2, apply_algo = "naive", hermitianize_period = 0)  # order: 1 to 4
Krylov(dim = nothing, maxiter = nothing, tol = nothing)       # nothing: (30, 100, 1e-12) for
                                                              # tdvp, (3, 1, 1e-14) for dmrg,
                                                              # (8, 3, 1e-14) for steady_state

evolve takes a time dependent evolver as a vector of terms, [A, B => g] for $A + g(t) B$, g a real function of the time, read from time (keyword, default 0). The error is set by limits, the time step (nsteps, or time_step, one of which evolve and thermalize require, as the phases) and the sweeps: a result is trusted once it does not move when each is improved, see Checking the accuracy. On a small system, matrix(ham, sys), the dense matrix of an operator, its Jordan-Wigner strings laid, and Vector(ψ), that of a pure state, give the exact result to compare with.

Measurements

measure(ψt, [X(1) * X(10), Z, (X, X), Purity, EntanglementEntropy(5)])
# a list gives a vector of pairs name => value: an operator on sites gives a number, an
# operator of one site a vector of a value per site, a pair a correlation matrix
measure(ψt, Z)  # a measurement alone gives its value, [Z] the vector of one pair
measure(ψt, ["E" => ham, "t" => c -> c.time]; time = 1.0)
# one value at a time
expect(ψt, X(1) * X(10)); expect1(ψt, Z); expect2(ψt, (X, X))
purity(ρt); maxlinkdim(ψt); entanglement_entropy(ψt, 5); entanglement_spectrum(ψt, 5)
probabilities(ψt, Z(1) * Z(2)); sample(ψt, Z(1)); collapse(ψt, Z(1))  # (result, probability, state)

Simulations

runTMS(SimData(
    name = "quench",                      # the directory of its files
    seed = 1,                             # the random draws, reproducible
    phases = [
        CreateState{Pure}(10, Qubit(), "Up"),
        GroundState(hamiltonian = ham, algo = Dmrg(nsweeps = 10), limits = lim),
        CopyState(:state => :ground),     # a named state, for Fidelity(:ground)
        Evolve(evolver = -im * (ham + 0.5 * sum(Z(i) for i in 1:10)), duration = 1.0,
               time_step = 0.05, limits = lim,
               measurements = "data" => [Z(1), Fidelity(:ground), :step]),
    ],
))

Other phases: ToMixed, Weaken, PartialTrace, Gates, Thermalize, SteadyState, SaveState, LoadState, Update. A phase acts on :state, or on a named state by on = :φ, and Evolve and Gates on several, on = [:state, :φ]; a list :φ => [Z, Purity] measures the named state, and Overlap(:φ, X) gives $\langle φ \vert X_i \vert state \rangle$ on every site, the correlations at two times of φ = A|ψ⟩ evolved with |ψ⟩. A destination is a file name (a table), "name.jsonl" (JSON Lines), "name.json" (a JSON array), "stdout", or Data("name") (kept in sim.data, row["X(1)"], a table: DataFrame(sim.data["name"])). Running the program again resumes a stopped run from its checkpoint; runTMS(sd; max_time, checkpoint_interval) or the variables TMS_MAX_TIME, TMS_CHECKPOINT_INTERVAL set them; a file restart in the directory, or cleanTMS(sd), starts over. runTMS(sd; output = devnull) makes no directory, a SaveState alone writing its file.

When something fails

An error on a name or a keyword of version 1.x ends with a line saying what 2.0 writes instead, see Upgrading from 1.x. The log of a run, in its directory, holds its warnings, which the line runTMS prints at the end counts.