Grand Finale: Three Encodings, One Molecule
Letβs tie every chapter together. This script encodes Hβ with three different encodings and compares the results:
open Encodings
open System.Numerics
// βββ Integrals (from the Hamiltonian chapter) βββββββββββββββ
let nModes = 4u
let integrals = Map [
("0,0", Complex(-1.2563, 0.0)); ("1,1", Complex(-1.2563, 0.0))
("2,2", Complex(-0.4719, 0.0)); ("3,3", Complex(-0.4719, 0.0))
("0,0,0,0", Complex(0.6745, 0.0)); ("1,1,1,1", Complex(0.6745, 0.0))
("2,2,2,2", Complex(0.6974, 0.0)); ("3,3,3,3", Complex(0.6974, 0.0))
("0,0,1,1", Complex(0.6745, 0.0)); ("1,1,0,0", Complex(0.6745, 0.0))
("0,0,2,2", Complex(0.6636, 0.0)); ("2,2,0,0", Complex(0.6636, 0.0))
("0,0,3,3", Complex(0.6636, 0.0)); ("3,3,0,0", Complex(0.6636, 0.0))
("1,1,2,2", Complex(0.6636, 0.0)); ("2,2,1,1", Complex(0.6636, 0.0))
("1,1,3,3", Complex(0.6636, 0.0)); ("3,3,1,1", Complex(0.6636, 0.0))
("2,2,3,3", Complex(0.6974, 0.0)); ("3,3,2,2", Complex(0.6974, 0.0))
("0,2,2,0", Complex(0.1809, 0.0)); ("2,0,0,2", Complex(0.1809, 0.0))
("1,3,3,1", Complex(0.1809, 0.0)); ("3,1,1,3", Complex(0.1809, 0.0))
]
let lookup key =
match (key : string).Split(',').Length with
| 2 | 4 -> integrals |> Map.tryFind key
| _ -> None
// βββ Encode and compare βββββββββββββββββββββββββββββββββββββ
let encoders = [
("Jordan-Wigner", jordanWignerTerms)
("Bravyi-Kitaev", bravyiKitaevTerms)
("Ternary Tree", ternaryTreeTerms)
]
for (name, encoder) in encoders do
let ham = computeHamiltonianWith encoder lookup nModes
let terms = ham.DistributeCoefficient.SummandTerms
let avgWeight =
terms
|> Array.averageBy (fun t ->
t.Signature
|> Seq.filter (fun c -> c <> 'I')
|> Seq.length
|> float)
printfn "βββ %s βββ" name
printfn " Terms: %d Avg Pauli weight: %.2f\n" terms.Length avgWeight
for t in terms do
let sign = if t.Coefficient.Real >= 0.0 then "+" else ""
printfn " %s%.4f %s" sign t.Coefficient.Real t.Signature
printfn ""
All three Hamiltonians have the same eigenvalues β they represent identical physics. The differences in term count and Pauli weight affect the cost of measurement on real quantum hardware.
From Pauli Weight to CNOT Count
Pauli weight isnβt just an abstract metric β it directly determines the number of CNOT gates needed on real hardware. To implement a single Pauli rotation $e^{-i\theta P}$ where $P$ has weight $w$, the standard CNOT staircase decomposition requires $2(w-1)$ CNOTs.
For a first-order Trotter step, you apply one rotation per Hamiltonian term, so the total CNOT cost is $\sum_k 2(w_k - 1)$ over all terms.
| Encoding | Terms | Max weight | Avg weight | CNOTs / Trotter step |
|---|---|---|---|---|
| JordanβWigner | 6 | 2 | 1.3 | 4 |
| BravyiβKitaev | 6 | 3 | 2.0 | 12 |
| Ternary Tree | 6 | 3 | 1.7 | 8 |
Surprise: For Hβ (4 qubits), JordanβWigner has the lowest CNOT count! The $O(n)$ weight scaling only becomes problematic at larger $n$. At $n = 32$, JW needs 62 CNOTs per worst-case rotation while the ternary tree needs only 8. See Lab 07 for the full scaling analysis.
Next: Bosonic-to-Qubit Encodings β Unary, Binary, and Gray code truncation encodings
Back to: Cookbook index β quick reference and further reading