Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

From a Hermitian Matrix to a Quantum Circuit

Tags: tutorial primitive encoding simulation

In many quantum algorithms you start from a Hermitian matrix — a Hamiltonian given as a dense 2n×2n2^n \times 2^n numpy array — and you want to simulate its time evolution e−iHte^{-iHt} on a quantum computer. The standard path is:

  1. Decompose HH into a weighted sum of Pauli strings.

  2. Feed that sum into pauli_evolve, which emits the corresponding quantum circuit.

Qamomile exposes this as a tiny, type-safe pipeline:

np.ndarray  →  HermitianMatrix  →  Hamiltonian  →  pauli_evolve  →  circuit

In this chapter we will:

The decomposition uses the Fast Walsh-Hadamard Transform internally and runs in O(n⋅4n)O(n \cdot 4^n) time with only NumPy — no Qiskit dependency.

A Small Hermitian Matrix

We will use the two-site transverse-field Ising model:

M  =  −Z0Z1  −  h (X0+X1),M \;=\; -Z_0 Z_1 \;-\; h \, (X_0 + X_1),

with transverse field h=0.7h = 0.7. Nothing here is Qamomile-specific — we just build an ordinary 4×44 \times 4 numpy array with np.kron.

shape: (4, 4)
Hermitian: True

Wrap and Decompose

HermitianMatrix is a thin wrapper that validates the array on construction (2D, square, power-of-two dimension, Hermitian) and exposes to_hamiltonian(). The resulting Hamiltonian lives in qamomile.observable — the same type consumed by pauli_evolve, expval, and the optimization helpers.

In Qamomile’s decomposition convention, qubit 0 corresponds to the least-significant bit of the matrix’s computational-basis indices, which matches Qiskit’s internal ordering.

num_qubits: 2
constant: 0.0
  (Z0, Z1): -1.000
  (X0,): -0.700
  (X1,): -0.700

For a two-site transverse-field Ising model we expect exactly three non-zero terms: one Z0Z1Z_0 Z_1 with coefficient -1 and two single-qubit XX terms with coefficient −h-h.

Time Evolution in a @qkernel

pauli_evolve(q, H, t) applies e−iHte^{-iHt} to a qubit register. H is declared with the qmc.Observable handle type and supplied via bindings at transpile time; t can be bound or left as a sweepable parameter.

We start from ∣00⟩\lvert 00\rangle, put qubit 0 into a superposition with a Hadamard, apply the time-evolution step, and measure so the top-level kernel has a classical output (a requirement for entry points passed to transpile() / to_circuit()).

Transpile with all three bindings fixed. The Qiskit circuit comes back as a plain QuantumCircuit via transpiler.to_circuit().

     ┌───┐┌───────────────────────────────┐┌─┐   
q_0: ┤ H ├┤0                              ├┤M├───
     └───┘│  exp(-it (ZZ + IX + XI))(0.8) │└╥┘┌─┐
q_1: ─────┤1                              ├─╫─┤M├
          └───────────────────────────────┘ ║ └╥┘
c: 2/═══════════════════════════════════════╩══╩═
                                            0  1 

Verify Against the Exact Exponential

For small Hermitian matrices we can build U=e−iMtU = e^{-iMt} directly from an eigendecomposition with numpy, apply it to the same initial state, and check that the Qamomile-generated circuit produces the same final state up to a global phase.

fidelity (|<exact|qamomile>|): 1.000000000000

The fidelity is numerically indistinguishable from 1: the circuit Qamomile built from the Pauli decomposition realises the same unitary as the direct matrix exponential.

Recap

  • HermitianMatrix validates a dense Hermitian numpy array and owns the conversion to a Pauli sum via an FWHT-based decomposition.

  • to_hamiltonian() returns a qamomile.observable.Hamiltonian, which is the same type consumed by pauli_evolve, expval, and the rest of the quantum algorithms toolbox.

  • Together this gives a direct np.ndarray → Hamiltonian → circuit path for algorithms that start from a Hermitian matrix, such as Hamiltonian simulation, VQE, and the Hermitian side of block-encoding / LCU workflows.

Support for non-self-adjoint operators (e.g. advection stencils that appear in numerical fluid simulations) is a natural follow-up and will be revisited once the right integration point for non-Hermitian matrices has been decided.