API Reference

Main Functions

Schrieffer-Wolff Transformation

UnitaryTransformations.schrieffer_wolffFunction
schrieffer_wolff(H::QuExpr, P::Subspace; order::Int=2)

Perform the Schrieffer-Wolff transformation on Hamiltonian H with respect to the low-energy subspace P.

The transformation finds a unitary U = e^S such that H_eff = e^S H e^{-S} is block-diagonal with respect to P and Q = 1-P, up to the specified order in perturbation theory.

Arguments

  • H: The full Hamiltonian to transform
  • P: The low-energy subspace definition
  • order: Perturbation theory order in the coupling strength (default: 2).
    • order=2: Standard SW, captures g² corrections (dispersive shifts)
    • order=4: Includes g⁴ corrections (Kerr nonlinearity, Bloch-Siegert, etc.)
  • simplify_generator: Whether to simplify the generator S (default: false). Simplifying S can be slow at high orders. Set to true if you need simplified S.
  • simplify_mode: Simplification mode for final output (default: :fast).
    • :none - No simplification (fastest)
    • :fast - Expansion only (default, very fast, recommended)
    • :standard - Basic algebraic simplification with expansion
    • :fractions - Simplify fractions with GCD (slow on complex expressions)
    • :aggressive - Full simplification (slowest)
  • diagonal_only: If true, only compute H_eff (skip computing higher-order generators). This is much faster for high orders when you only need the effective Hamiltonian. Note: This uses a simplified algorithm that only uses S₁.
  • parallel: If true, use multi-threading for orders > 3 (default: false). Requires Julia to be started with multiple threads (e.g., julia -t 4). For best performance, use 4-8 threads; more threads can cause lock contention. Parallelization is most beneficial for orders 4-6 with complex Hamiltonians.

Returns

  • Named tuple (H_eff, S, H_P) where:
    • H_eff: The full block-diagonal effective Hamiltonian
    • S: The generator of the transformation (S = S₁ + S₂ + ... where Sₙ is O(gⁿ)) Note: If diagonal_only=true, S contains only S₁.
    • H_P: The effective Hamiltonian projected onto subspace P

Algorithm

The SW transformation uses S = S₁ + S₂ + S₃ + ... where each Sₙ is order gⁿ. At each order, the off-diagonal terms from the BCH expansion determine Sₙ, and the diagonal terms contribute to H_eff.

Key commutator rules (D=diagonal, O=off-diagonal):

  • [O, O] → D
  • [O, D] → O
  • [D, D] → D

Example

using QuantumAlgebra, UnitaryTransformations, Symbolics

# Jaynes-Cummings in dispersive regime
@variables ω Δ g  # ω = cavity frequency, Δ = qubit splitting, g = coupling strength

H = ω * a'()*a() + Δ/2 * σz() + g * (a'()*σm() + a()*σp())

# Transform to eliminate qubit-photon coupling
P = Subspace(σz() => -1)  # qubit ground state
result = schrieffer_wolff(H, P; order=2)

# For 4th order corrections (Kerr effect, etc.) - parallel computation
result4 = schrieffer_wolff(H, P; order=4, parallel=true)
source
schrieffer_wolff(H::SymExpr, P::Subspace; order::Int=2, ...)

Perform the Schrieffer-Wolff transformation on a Hamiltonian expressed with symbolic sums (SymExpr).

This extends the standard SW transformation to handle Hamiltonians like the Tavis-Cummings model:

H = ω_c a†a + Σᵢ (Δ/2)σz(i) + Σᵢ g(a†σ⁻(i) + aσ⁺(i))

The key capability is correct handling of:

  • Same-site contributions: Σᵢ [Aᵢ, Bᵢ]
  • Cross-site contributions: Σᵢ Σⱼ≠ᵢ [Aᵢ, Bⱼ] (exchange interactions)

Arguments

Same as the schrieffer_wolff(H::QuExpr, ...) method.

Returns

  • Named tuple (H_eff, S, H_P) where H_eff and S may be SymExpr types.

Example

using QuantumAlgebra, UnitaryTransformations, Symbolics
import QuantumAlgebra: sumindex, SymSum, SymExpr

@variables ω_c Δ g

i = sumindex(1)
H = SymExpr(ω_c * a'()*a()) + 
    SymSum(Δ/2 * σz(i), i) + 
    SymSum(g * (a'()*σm(i) + a()*σp(i)), i)

P = Subspace(a'()*a() => 0)  # Zero photon sector
result = schrieffer_wolff(H, P; order=2)

Notes

  • Currently only supports order=2 for SymExpr inputs
  • The effective Hamiltonian includes both same-site and cross-site terms
  • For higher orders, expand the SymSum to explicit indices first
source
schrieffer_wolff(H::SymSum, P::Subspace; order::Int=2, ...)

Convenience method: wrap a single SymSum in a SymExpr and call the main method.

source
UnitaryTransformations.sw_generatorFunction
sw_generator(H::QuExpr, P::Subspace; order::Int=1)

Compute only the generator S for the Schrieffer-Wolff transformation, without computing the full effective Hamiltonian.

This is useful when you only need S, or want to manually compute the transformation using bch_transform.

source

Magnus Expansion (Floquet Systems)

UnitaryTransformations.magnus_expansionFunction
magnus_expansion(H::FourierHamiltonian; order::Int=2, check_hermitian::Bool=true)

Compute the Magnus expansion for a periodically driven system to arbitrary order.

Arguments

  • H: A FourierHamiltonian representing H(t) = Σₙ Hₙ e^{inωt}
  • order: Maximum order of the expansion (default: 2, no upper limit)
  • check_hermitian: Whether to verify H is Hermitian (default: true)

Returns

A MagnusResult containing:

  • H_eff: The effective time-independent Hamiltonian
  • orders: Dict mapping order k to Ωₖ
  • Ω1, Ω2, ...: Direct access to individual contributions

Example

using QuantumAlgebra, UnitaryTransformations, Symbolics
QuantumAlgebra.use_σpm(true)

@variables Δ Ω ω
modes = Dict(0 => Δ/2*σz(), 1 => Ω/2*σp(), -1 => Ω/2*σm())
result = magnus_expansion(modes, ω; order=5)
println("Order 5: ", result.Ω5)
source
UnitaryTransformations.FourierHamiltonianType
FourierHamiltonian

Represents a time-periodic Hamiltonian in Fourier representation: H(t) = Σₙ Hₙ e^{inωt}

The modes are stored as a Dict{Int, QuExpr} mapping Fourier index n to operator Hₙ.

For Hermiticity, we require H₋ₙ = Hₙ†.

source
UnitaryTransformations.check_hermiticityFunction
check_hermiticity(H::FourierHamiltonian; warn_only::Bool=false)

Check that the Fourier Hamiltonian satisfies H₋ₙ = Hₙ† for all modes.

Returns true if Hermitian, throws an error otherwise.

source

Subspace Definition

UnitaryTransformations.SubspaceType
Subspace(constraints...)

Define a low-energy subspace P by specifying constraints on operators.

Examples

# Spin-down subspace
P = Subspace(σz() => -1)

# Vacuum subspace (zero bosons)
P = Subspace(a'()*a() => 0)

# Product state: spin-down AND zero bosons
P = Subspace(σz() => -1, a'()*a() => 0)

# Indexed systems
P = Subspace(σz(:i) => -1)  # All spins down
source

Hamiltonian Decomposition

UnitaryTransformations.decomposeFunction
decompose(H::QuExpr, P::Subspace)

Decompose H into diagonal and off-diagonal parts with respect to subspace P.

Returns (Hd, Hod) where:

  • H_d is the block-diagonal part
  • H_od is the off-block-diagonal part
  • H = Hd + Hod
source
decompose(s::SymSum, P::Subspace)

Decompose a symbolic sum into diagonal and off-diagonal parts. The decomposition is applied to the inner expression of the sum.

Returns (SymSumd, SymSumod) where both are SymSum with the same index.

source
decompose(s::SymProd, P::Subspace)

Decompose a symbolic product. Products are generally treated as off-diagonal unless explicitly simplified.

source
decompose(e::SymExpr, P::Subspace)

Decompose a symbolic expression containing sums, products, and regular terms. Returns (SymExprd, SymExprod).

source
UnitaryTransformations.diagonal_partFunction
diagonal_part(H::QuExpr, P::Subspace)

Extract the block-diagonal part of H with respect to subspace P. This includes terms that preserve P (P·H·P) and terms that preserve Q (Q·H·Q).

Note: Terms classified as MIXED (like σx when not using σpm mode) are skipped. For proper handling, ensure Hamiltonians are expressed in the σ± basis.

source
diagonal_part(s::SymSum, P::Subspace)

Extract the diagonal part of a symbolic sum.

source
diagonal_part(e::SymExpr, P::Subspace)

Extract the diagonal part of a symbolic expression.

source
UnitaryTransformations.off_diagonal_partFunction
off_diagonal_part(H::QuExpr, P::Subspace)

Extract the off-block-diagonal part of H with respect to subspace P. This includes terms that couple P to Q (P·H·Q + Q·H·P).

Note: MIXED terms (like σx in σz basis, or off-diagonal Lie algebra generators) are included in the off-diagonal part since they contain off-diagonal components that couple different subspaces.

source
off_diagonal_part(s::SymSum, P::Subspace)

Extract the off-diagonal part of a symbolic sum.

source
off_diagonal_part(e::SymExpr, P::Subspace)

Extract the off-diagonal part of a symbolic expression.

source
UnitaryTransformations.is_diagonalFunction
is_diagonal(expr::QuExpr, P::Subspace)

Check if an expression is purely block-diagonal with respect to subspace P.

source
is_diagonal(s::SymSum, P::Subspace)

Check if a symbolic sum is purely diagonal.

source
is_diagonal(e::SymExpr, P::Subspace)

Check if a symbolic expression is purely diagonal.

source

Generator Solution

The core operation in Schrieffer-Wolff is solving $[S, H_d] = -V_{od}$ for the generator $S$.

Main Function

UnitaryTransformations.solve_for_generatorFunction
solve_for_generator(H_d::QuExpr, V_od::QuExpr, P::Subspace)

Solve [S, Hd] = -Vod for the generator S.

This is the core equation in Schrieffer-Wolff: we need to find S such that the commutator with the diagonal part cancels the off-diagonal perturbation.

The fundamental solution in the energy eigenbasis is: S{ij} = V{ij} / (Ei - Ej)

Two methods are automatically selected based on operator types:

  1. Eigenoperator method (TLS, bosons, N-level transitions): For operators O where [H_d, O] = ε·O, the solution is S = V/ε directly.

  2. Matrix-element method (SU(N) Lie algebras): Convert to the Cartan-Weyl (transition) basis where operators ARE eigenoperators, apply S{ij} = V{ij}/(Ei - Ej), then convert back.

Uses Symbolics.jl for proper symbolic division, allowing denominators like (Δ - ω).

Arguments

  • H_d: The diagonal (unperturbed) Hamiltonian
  • V_od: The off-diagonal perturbation to be eliminated
  • P: The subspace defining the block structure

Returns

  • S: The generator of the transformation
source
solve_for_generator(H_d::QuExpr, V_od::SymSum, P::Subspace)

Solve [S, Hd] = -Vod for the generator S when V_od is a symbolic sum.

For a symbolic sum Σᵢ V(i), the generator is also a symbolic sum Σᵢ S(i) where each S(i) is computed using the eigenoperator method.

Key insight

For operators with sum indices, [Hd, Σᵢ O(i)] = Σᵢ [Hd, O(i)] since H_d typically doesn't depend on the sum index. The generator is then: S = Σᵢ V(i)/ε(i) where ε(i) is the energy denominator for each term.

source
solve_for_generator(H_d::QuExpr, V_od::SymExpr, P::Subspace)

Solve [S, Hd] = -Vod for the generator S when V_od is a symbolic expression.

For a symbolic expression with multiple terms, solve for each term separately and combine the results.

source
solve_for_generator(H_d::SymExpr, V_od::QuExpr, P::Subspace)

Solve when Hd is a SymExpr and Vod is a regular QuExpr. Extract the scalar (QuExpr) part of H_d for the generator equation.

source
solve_for_generator(H_d::SymExpr, V_od::SymSum, P::Subspace)

Solve when both Hd and Vod involve symbolic sums.

source
solve_for_generator(H_d::SymExpr, V_od::SymExpr, P::Subspace)

Solve when both Hd and Vod are symbolic expressions.

source

Method-Specific Functions

Two methods are available, automatically selected based on the operator types:

UnitaryTransformations.solve_for_generator_eigenoperatorFunction
solve_for_generator_eigenoperator(H_d::QuExpr, V_od::QuExpr, P::Subspace)

Solve [S, Hd] = -Vod using the eigenoperator method.

This method works for operators O where [H_d, O] = ε·O (eigenoperators of the adjoint action). The solution is simply S = V/ε.

Examples of eigenoperators:

  • σ± for TLS with H_d ∝ σz: [σz, σ±] = ±2σ±
  • a, a† for bosons with H_d ∝ a†a: [a†a, a] = -a, [a†a, a†] = a†
  • |i⟩⟨j| for N-level with diagonal Hd: [Hd, |i⟩⟨j|] = (Ei - Ej)|i⟩⟨j|

For each term in Vod, the corresponding term in S is Vterm / ε.

source
UnitaryTransformations.solve_for_generator_lieFunction
solve_for_generator_lie(H_d::QuExpr, V_od::QuExpr, N::Int, generators::Tuple;
                        algebra_id=SU3_ALGEBRA_ID)

Solve [S, Hd] = -Vod for the generator S by building the commutator matrix in the off-diagonal generator basis and solving a linear system.

This matches QuantumAlgebra's normal-form commutator semantics, which can differ from the ideal matrix-element method for SU(3).

Arguments

  • H_d: The diagonal Hamiltonian (in diagonal generators only)
  • V_od: The off-diagonal perturbation to be eliminated
  • N: Dimension of the representation (2 for SU(2), 3 for SU(3))
  • generators: Tuple of SU(N) generators (from su_generators)
  • algebra_id: The algebra identifier (default: SU3ALGEBRAID)

Returns

  • S: The generator of the transformation
source

The eigenoperator method works when $[H_d, O] = \varepsilon \cdot O$ (TLS, bosons, N-level transitions).

The Lie algebra method works for SU(N) systems by converting to the Cartan-Weyl basis where generators become eigenoperators.

Supporting Functions

UnitaryTransformations.compute_energy_denominatorFunction
compute_energy_denominator(H_d::QuExpr, term::QuTerm, P::Subspace)

Compute the energy denominator for a given off-diagonal term.

For an off-diagonal operator O, computes ε where [Hd, O] = ε·O. This is the energy difference Ei - E_j for the transition that O represents.

Returns the energy denominator as a Symbolics Num expression, or nothing if the operator commutes with H_d (degenerate case).

source
UnitaryTransformations.compute_energy_eigenvaluesFunction
compute_energy_eigenvalues(H_d::QuExpr, N::Int, algebra_id::UInt16)

Compute energy eigenvalues for an N-level system from a diagonal Hamiltonian expressed in terms of Lie algebra generators.

For SU(N), the diagonal generators (Cartan subalgebra) have known eigenvalues. This function extracts the coefficients from H_d and computes Eᵢ for each state.

Returns a vector of symbolic expressions [E₁, E₂, ..., Eₙ].

source
UnitaryTransformations.detect_lie_algebra_systemFunction
detect_lie_algebra_system(V_od::QuExpr)

Detect if V_od contains Lie algebra generators and return information about the algebra.

Returns nothing if no Lie algebra operators found, or a NamedTuple with:

  • N: dimension of the algebra (2 for SU(2), 3 for SU(3))
  • algebra_id: the UInt16 algebra identifier
  • name: the generator name (e.g., :λ)
  • inds: the indices tuple
source

Projection

UnitaryTransformations.project_to_subspaceFunction
project_to_subspace(H::QuExpr, P::Subspace)

Project an operator onto the subspace P.

This replaces diagonal operators by their eigenvalues in P:

  • σz → eigenvalue (e.g., -1 for spin down)
  • σ⁺σ⁻ → 0 for spin down, 1 for spin up
  • a†a → eigenvalue (e.g., 0 for vacuum)

And removes any remaining off-diagonal terms.

source
project_to_subspace(s::SymSum, P::Subspace)

Project a symbolic sum onto the subspace P.

The projection is applied to the inner expression of the sum. If the inner expression projects to zero (e.g., σ⁺σ⁻ in spin-down subspace), the entire sum becomes zero.

Example

For Σᵢ σ⁺(i)σ⁻(i) with P = Subspace(σz() => -1):

  • The inner term σ⁺σ⁻ → 0 for spin-down
  • Therefore the entire sum → 0
source
project_to_subspace(s::SymProd, P::Subspace)

Project a symbolic product onto the subspace P.

source
project_to_subspace(e::SymExpr, P::Subspace)

Project a symbolic expression onto the subspace P.

This applies project_to_subspace to both the scalar (QuExpr) part and all symbolic aggregate terms (SymSum, SymProd).

Notes

  • Cross-site terms like Σᵢ≠ⱼ σ⁺(i)σ⁻(j) are kept (they don't involve single-site projections that would set them to zero)
  • Same-site terms like Σᵢ σ⁺(i)σ⁻(i) become zero if P is spin-down

Example

using QuantumAlgebra, UnitaryTransformations
import QuantumAlgebra: sumindex, SymSum, SymExpr

i = sumindex(1)
H = SymExpr(a'()*a()) + SymSum(σz(i)/2, i)

P = Subspace(a'()*a() => 0, σz() => -1)
H_P = project_to_subspace(H, P)
# H_P will have a†a → 0 and Σᵢ σz(i)/2 → Σᵢ(-1/2) = -N/2 (symbolic)
source

Projection with Symbolic Sums

The project_to_subspace function supports SymExpr, SymSum, and SymProd types for multi-atom systems:

using QuantumAlgebra, UnitaryTransformations
import QuantumAlgebra: sumindex, SymSum, SymExpr

i = sumindex(1)
H_eff = SymExpr(ω_c * a'()*a()) + SymSum(Δ/2 * σz(i), i)

P = Subspace(a'()*a() => 0, σz() => -1)
H_P = project_to_subspace(H_eff, P)
# σz(i) → -1 for spin-down subspace
# Symbolic sums are preserved in the result

Supported types:

  • QuExpr — standard quantum expressions
  • SymSum — symbolic sums over site indices
  • SymProd — symbolic products over site indices
  • SymExpr — combinations of the above

BCH Expansion

The Baker-Campbell-Hausdorff expansion is used to compute $e^S H e^{-S}$.

UnitaryTransformations.bch_transformFunction
bch_transform(S::QuExpr, A::QuExpr; order::Int=4)

Compute e^S A e^{-S} using the BCH formula to the specified order.

This computes the adjoint action of e^S on an operator A: e^S A e^{-S} = A + [S,A] + (1/2!)[S,[S,A]] + (1/3!)[S,[S,[S,A]]] + ...

Arguments

  • S: The generator (typically anti-Hermitian: S† = -S)
  • A: The operator to transform (e.g., a Hamiltonian)
  • order: Number of nested commutators to include (default: 4)

Example

using QuantumAlgebra, UnitaryTransformations, Symbolics
@variables g Δ

# Generator from SW transformation
S = (g/Δ) * (a'()*σm() - a()*σp())

# Transform the Hamiltonian
H = Δ/2 * σz() + g * (a'()*σm() + a()*σp())
H_transformed = bch_transform(S, H; order=2)
source
UnitaryTransformations.commutator_seriesFunction
commutator_series(S::QuExpr, H::QuExpr, order::Int)

Compute the BCH expansion of e^S H e^{-S} to the given order.

e^S H e^{-S} = Σₙ (1/n!) [S, [S, [..., [S, H]...]]] (n nested commutators)

The expansion is truncated at order nested commutators.

Arguments

  • S: The generator of the unitary transformation (anti-Hermitian: S† = -S)
  • H: The operator to transform
  • order: Maximum number of nested commutators to include

Returns

  • The transformed operator as a QuExpr
source
UnitaryTransformations.nested_commutatorFunction
nested_commutator(S::QuExpr, H::QuExpr, n::Int)

Compute the n-fold nested commutator [S, [S, [..., [S, H]...]]] with S appearing n times.

  • n=0 returns H
  • n=1 returns [S, H]
  • n=2 returns [S, [S, H]]
  • etc.
source
nested_commutator(operators::Vector{QuExpr})

Compute the left-nested commutator [...[[A₁, A₂], A₃], ..., Aₙ].

source
nested_commutator(H::FourierHamiltonian, indices)

Compute the nested commutator for given Fourier indices.

source

Symbolic Utilities

Coefficient Manipulation

UnitaryTransformations.simplify_coefficientsFunction
simplify_coefficients(expr::QuExpr; mode::Symbol=:fast)

Simplify all Symbolics coefficients in a QuExpr. Returns a new QuExpr with simplified coefficients.

Modes

  • :none - No simplification (fastest, for internal computations)
  • :fast - Basic expansion only (default, very fast)
  • :standard - Use simplify(; expand=true) (slower but more thorough)
  • :fractions - Use simplify_fractions (slow, simplifies rational expressions)
  • :aggressive - Use full simplify (slowest, most thorough)

Note: The :fractions and :aggressive modes can be extremely slow on complex expressions due to polynomial GCD and rewriting computations. Use :fast for most cases - it flattens expressions and combines like terms efficiently.

source
UnitaryTransformations.substitute_valuesFunction
substitute_values(expr::QuExpr, values::Dict{Symbol, Number})

Substitute numerical values for symbolic parameters in a QuExpr.

Arguments

  • expr: A QuExpr with symbolic coefficients
  • values: Dict mapping parameter symbols to numerical values

Example

H_P = result.H_P
values = Dict(:g => 0.1, :Δ => 1.0)
H_numeric = substitute_values(H_P, values)
source
UnitaryTransformations.extract_coefficientFunction
extract_coefficient(expr::QuExpr, target_ops::QuExpr)

Extract the coefficient of a specific operator structure from a QuExpr.

Arguments

  • expr: The full QuExpr to search
  • target_ops: The operator structure to match (e.g., a'()*a())

Returns

  • The coefficient (Num or Number) if found, nothing otherwise
source
UnitaryTransformations.collect_termsFunction
collect_terms(expr::QuExpr)

Collect and display all terms in a QuExpr with their simplified coefficients. Returns a vector of (operatorstring, simplifiedcoefficient) pairs.

source

Simplification Modes

The simplify_coefficients function supports several modes for different speed/quality trade-offs:

ModeDescriptionSpeed
:noneNo simplificationFastest
:fastExpansion only (flattens nested expressions)Fast (default)
:standardFull algebraic simplification with expansionModerate
:fractionsSimplify rational expressions with GCDSlow
:aggressiveMaximum simplificationSlowest
# For exploration and debugging (fastest)
result = schrieffer_wolff(H, P; order=4, simplify_mode=:none)

# For final results (default, good balance)
result = schrieffer_wolff(H, P; order=4, simplify_mode=:fast)

# For publication-ready expressions
H_simplified = simplify_coefficients(result.H_P; mode=:standard)

LaTeX Output

UnitaryTransformations.to_latexFunction
to_latex(expr::QuExpr; simplify_coeff::Bool=true)

Convert a QuExpr to a LaTeX string with simplified coefficients.

Arguments

  • expr: The quantum expression to convert
  • simplify_coeff: Whether to simplify coefficients first (default: true)

Returns

A LaTeX string representation of the expression.

Example

H = Δ/2 * σz() + g * (a'() * σm() + a() * σp())
println(to_latex(H))
source
to_latex(result::NamedTuple; simplify_coeff::Bool=true)

Convert a Schrieffer-Wolff result to LaTeX strings.

Returns

A NamedTuple with LaTeX strings for each component:

  • H_eff: The effective Hamiltonian
  • S: The generator
  • H_P: The projected Hamiltonian

Example

result = schrieffer_wolff(H, P; order=2)
latex_result = to_latex(result)
println(latex_result.H_P)
source
UnitaryTransformations.print_latexFunction
print_latex(expr::QuExpr; name::String="", display::Bool=true, simplify_coeff::Bool=true)

Print a QuExpr as LaTeX, optionally wrapped in display math environment.

Arguments

  • expr: The quantum expression to print
  • name: Optional name to show (e.g., "H_{eff}")
  • display: If true, wrap in \[ ... \] for display math
  • simplify_coeff: Whether to simplify coefficients first

Example

print_latex(result.H_P; name="H_P")
# Output: H_P = - \frac{1}{2} \Delta + ...
source
UnitaryTransformations.show_resultFunction
show_result(result::NamedTuple; display::Bool=false, simplify_coeff::Bool=true)

Pretty-print all components of a Schrieffer-Wolff result in LaTeX.

Arguments

  • result: The result from schrieffer_wolff
  • display: If true, wrap each in display math environment
  • simplify_coeff: Whether to simplify coefficients

Example

result = schrieffer_wolff(H, P; order=2)
show_result(result)
source

Parameter Conversion

Functions for converting between QuantumAlgebra's Param and Symbolics.jl variables:


Re-exported from QuantumAlgebra

The following functions are re-exported for convenience:

  • comm(A, B) - Compute commutator $[A, B] = AB - BA$
  • normal_form(expr) - Normal-order an operator expression
  • a(), a'() - Bosonic annihilation/creation operators
  • σx(), σy(), σz() - Pauli matrices
  • σp(), σm() - Raising/lowering operators (when use_σpm(true))
  • nlevel_ops(N, name) - N-level transition operators $|i\rangle\langle j|$
  • su_generators(N, name) - SU(N) generators (generalized Gell-Mann matrices)

Symbolic Parameters

Use Symbolics.jl @variables to define symbolic parameters:

using Symbolics
@variables Δ g ω  # Define symbolic parameters

For N-level systems with indexed parameters:

# Create ω₁, ω₂, ..., ωₙ
ω = [Symbolics.variable(Symbol("ω", i)) for i in 1:N]

Types

SWResult

The schrieffer_wolff function returns a named tuple:

result = schrieffer_wolff(H, P; order=2)

result.S      # Generator of the transformation
result.H_eff  # Block-diagonal effective Hamiltonian  
result.H_P    # H_eff projected onto subspace P

Subspace

# Single constraint
P = Subspace(σz() => -1)

# Multiple constraints
P = Subspace(σz() => -1, a'()*a() => 0)

# N-level constraint
P = Subspace(a'()*a() => 0)  # zero photons

Classification Enums

The package uses classification enums for operator analysis:

DIAGONAL   # Operator preserves the subspace
RAISING    # Operator raises out of subspace P
LOWERING   # Operator lowers into subspace P
MIXED      # Operator has mixed character

Performance Tips

Parallel Computation

For high-order SW transformations, enable multi-threading:

# Start Julia with 4 threads
julia -t 4
# Enable parallel BCH term computation
result = schrieffer_wolff(H, P; order=5, parallel=true)

Benchmarks (Jaynes-Cummings model, 4 threads)

Ordersimplify_mode=:nonesimplify_mode=:fast
40.4 s0.6 s
51.7 s1.7 s
650 s80 s
  1. Explore with simplify_mode=:none for speed
  2. Verify with simplify_mode=:fast (default)
  3. Simplify for publication with simplify_coefficients(expr; mode=:standard)

Internal Functions

These functions are not exported but may be useful for advanced users:

Lie Algebra Support

# Get generators for detected Lie algebra
get_generators_for_lie_system(lie_info::NamedTuple)

# Convert between bases
gellmann_to_cartan_weyl(V_od, N, algebra_id)
cartan_weyl_to_gellmann(transitions, N, generators)

Operator Classification

# Classify a single term
classify_term(term::QuTerm, coeff, constraints)

# Check if operator contains only specific types
has_only_bosons(term::QuTerm)
has_only_tls(term::QuTerm)