Unitary transformations

A unitary transformation changes the operator basis while preserving the operator algebra. In SecondQuantizedAlgebra, a UnitaryTransform stores the transformed fundamental operators, their inverse transformation, and—when the basis moves in time—the corresponding Hamiltonian gauge term.

The basic workflow is:

using SecondQuantizedAlgebra

h = FockSpace(:resonator)
@qnumbers a::Destroy(h)
@variables θ ω t

U = Rotation(a, θ)
conjugate(a, U)

Here conjugate(A, U) evaluates $U^\dagger A U$ by substituting the transformed fundamental operators into A. The same substitution works for products and sums:

n = a' * a
X = a + a'

conjugate(n, U)
conjugate(X^2, U)

Available transformations

The named constructors select the transformation from the operator type and their arguments.

SystemConstructorAction
Fock modeDisplace(a, α)$a \mapsto a+\alpha$
Fock modeRotation(a, θ)$a \mapsto e^{-i\theta}a$
Fock modeSqueeze(a, r, ϕ=0)$a \mapsto \cosh(r)a+e^{i\phi}\sinh(r)a^\dagger$
Two Fock modesRotation(a, b, θ)beamsplitter rotation
Two Fock modesSqueeze(a, b, r)two-mode squeezing
Canonical quadraturesDisplace(x, p, dx, dp)$x\mapsto x+dx$, $p\mapsto p+dp$
Canonical quadraturesRotation(x, p, θ)phase-space rotation
Canonical quadraturesSqueeze(x, p, r)$x\mapsto e^r x$, $p\mapsto e^{-r}p$
Spin or Pauli operatorsRotation(S, axis, θ)rotation around axis 1, 2, or 3
N-level transitionsRotation(σ, W)basis change defined by the unitary matrix W

Each constructor also defines the inverse transformation, so inv(U) can be used without deriving another set of rules.

Static and time-dependent transformations

Use conjugate for observables and static changes of basis. For a Hamiltonian in a moving basis, use transform:

\[\operatorname{transform}(H,U) = U^\dagger H U + i(\partial_t U^\dagger)U.\]

The second term accounts for the motion of the basis. It is available through gauge_term(U).

H = ω * a' * a

Ustatic = Rotation(a, θ)
transform(H, Ustatic) == conjugate(H, Ustatic)

Utimed = Rotation(a, ω * t, t)
Hmoving = transform(H, Utimed)
gauge_term(Utimed)

The final argument identifies the differentiation variable. It must be a real symbolic variable. When a parameter depends on time, pass the time variable to the constructor if the gauge term is needed; for example, use Rotation(a, ω*t, t) for a rotating Hamiltonian frame.

Inversion and composition

inv(U) reverses a transformation. Transform products follow application order: the left transformation is applied first.

U1 = Displace(a, 1 // 3)
U2 = Rotation(a, θ)
U = U1 * U2

conjugate(a, U) == conjugate(conjugate(a, U1), U2)
iszero(simplify(conjugate(conjugate(a, U), inv(U)) - a))

Static and timed transformations can be composed. Timed transformations in a single product must use the same time variable. The gauge terms are composed in the same order as the operator maps, so transform(H, U1 * U2) agrees with applying the two frame changes successively.

generators(U) returns the fundamental operators acted on by a transformation.

N-level basis rotations

For an ordinary NLevelSpace, Rotation(σ, W) transforms all transitions on the same site according to the basis matrix W.

h_atom = NLevelSpace(:atom, (:g, :e))
σ = Transition(h_atom, :σ, 1, 2)

W = [cos(θ) -sin(θ); sin(θ) cos(θ)]
Ulevels = Rotation(σ, W)
conjugate(σ, Ulevels)

W must be square, match the number of levels, and satisfy $W^\dagger W=I$ symbolically. For a time-dependent matrix, use Rotation(σ, W, t). Its gauge is computed entrywise from $i\dot W^\dagger W$.