hamiltonian#

Functionality#

The following programs implement the Hamiltonian evolution with the duration \(t(t>0)\) for the position operator \(\hat{x}\) in the coordinate representation.


diagonal_hamiltonian.py#

Callee: DiagonalZHamiltonian

This circuit implements the exact time evolution under a diagonal, non-interacting \(Z\)-type Hamiltonian for an \(n\)-qubit system:

\[ H = \sum_{j=0}^{n-1} 2^j Z_j, \]

Note the \(Z_j\) is the Pauli-\(Z\) operator acting on the \(j\)-th qubit, where \(Z\ket{0} = \ket{0}\) and \(Z\ket{1} = -\ket{1}\), thus the form \(Z=I-2\ket{1}\bra{1}\).

Given the evolution time \(t\) for an \(n\)-qubit quantum system initialized as the computational basis state \(\ket{x}_n\) (i.e., \(\ket{x}_n = \ket{q_{n-1} \cdots q_1 q_0}\) and \(x\) is the decimal value of the binary string \(q_{n-1} \cdots q_0\)), the program performs the unitary transformation

\[ U(t) = e^{-i H t} = \prod_{j=0}^{n-1} e^{-i 2^j Z_j t}, \]

resulting in the phase mapping:

\[ \ket{x}_n \mapsto e^{ixt} \ket{x}_n. \]

Specifically, in Qiskit, the single-qubit \(Z\)-rotation is defined as

\[ R_z(\theta) = e^{-i\theta Z/2}. \]

making the transformation

\[ U(t)=\exp\!\left(-i\frac{t}{2}\sum_{i=0}^{n-1}2^i Z_i\right). \]

For each qubit,

\[ Z_i\ket{q_i} = (-1)^{q_i}\ket{q_i} \]

Hence,

\[ (\sum_{i=0}^{n-1}2^i Z_i)\ket{x} = (\sum_{i=0}^{n-1}2^i (-1)^{q_i})\ket{x} = ((2^n-1)-2x)\ket{x} \]

Finally, the transformation can cause:

\[ U(t)\ket{x} = e ^ {-i\frac{t}{2}((2^n-1)-2x)}\ket{x} = e ^ {-i\frac{t}{2}(2^n-1)} \cdot e^{ixt} \ket{x} \]

Test expectations:

The results are stored in the phase of the corresponding basis state \(\ket{x}\), which can be verified by a state-vector backend during test. Note that it is necessary to consider the complete phase \(e ^ {-i\frac{t}{2}(2^n-1)} e^{ixt}\) when comparing the state vector.

Doc references: [5]


adder_hamiltonian_mixture.py#

Callee: AdderHamiltonianMixture

This is a general oracle quantum program (qubit-phase-mixed) by combining the behaviors of QuantumAdder and DiagonalZHamiltonian.

Given two \(n\)-qubit computational basis states \(\ket{x}_n\) and \(\ket{y}_n\), the program performs the following mapping:

\[ \ket{y}_n \ket{x}_n \mapsto e^{i t y} \ket{(x + y) \text{ mod } 2^n}_n \ket{x}_n . \]

The input states are defined as \(\ket{x}_n = \ket{q_{n-1} \cdots q_1 q_0}\) and \(\ket{y}_n = \ket{q_{2n-1} \cdots q_{n+1} q_n}\), where \(x\) and \(y\) are the decimal values of the binary strings \(q_{n-1} \cdots q_0\) and \(q_{2n-1} \cdots q_n\), respectively.

Test expectations:

The state of \(\ket{y}\) register will be transformed as \(\ket{(x + y) \text{ mod } 2^n}_n\), with an additional phase. Note that during test, the phase is computed as \(e ^ {-i\frac{t}{2}(2^n-1)} e^{iyt}\) on state-vector backend.

Doc references: [5]


sparse_hamiltonian.py#

Callee: SparseHamiltonian

This circuit implements the Hamiltonian simulation for a 2-sparse Hamiltonian matrix \(H\).

  1. When controlled_ver is set to False, the program implements the non-controlled Hamiltonian simulation. The registers and their indexing are as follows:

    Index

    \(0 \sim (n-1)\)

    \(n \sim (2n-1)\)

    \(2n\)

    Register

    State qubits

    Oracle qubits

    Ancilla qubit

    Given the evolution time \(t\) for an \(n\)-qubit quantum system initialized as \(\ket{\psi}_n\) (here, we only care about the system qubits), the program performs the unitary transformation

    \[ U(t): \ket{\psi}_n \mapsto e^{-i H t} \ket{\psi}_n. \]
  2. When controlled_ver is set to True, the program implements the controlled Hamiltonian simulation. The registers and their indexing are as follows:

    Index

    \(0 \sim (n-1)\)

    \(n \sim (2n-1)\)

    \(2n\)

    \(2n+1\)

    Register

    State qubits

    Oracle qubits

    Control qubit

    Ancilla qubit

    Given the evolution time \(t\) for an \(n\)-qubit quantum system initialized as \(\ket{\psi}_n\) and a control qubit initialized as \(\ket{c}_1\), the program performs the unitary transformation:

    \[\begin{split} U_{c}(t): \ket{c}_1 \ket{\psi}_n \mapsto \begin{cases} \ket{0}_1 \ket{\psi}_n, & \text{if } c=0 \\ \ket{1}_1 e^{-i H t} \ket{\psi}_n, & \text{if } c=1 \end{cases} \end{split}\]

Notes:

Considering the intended functionality of this program, a valid input sparse Hamiltonian matrix \(H\) specified by the argument H must satisfy the following conditions:

  • \(H\) is a real-valued Hermitian matrix of size \(N \times N\), where \(N = 2^n\).

  • \(H\) is 2-sparse with exactly one off-diagonal non-zero entry per row, i.e., for each row \(i\), there exists at most one index \(j \neq i\) such that \(H_{i,j} \neq 0\).

  • \(H\) contains at least one off-diagonal non-zero entry (i.e., it is not a purely diagonal matrix).

  • All off-diagonal non-zero entries of \(H\) have the same coupling strength, i.e., there exists a real constant \(g \neq 0\) such that for all indices \(i \neq j\),

    \[ H_{i,j} \neq 0 \;\Longrightarrow\; H_{i,j} = g . \]
  • The off-diagonal structure of \(H\) is globally consistent, i.e., there exists a fixed bitmask \(k\) such that for all \(i\),

    \[ H_{i,j} \neq 0 \iff j = i \oplus k . \]
  • When controlled_ver = False, all diagonal entries of \(H\) must be zero. Diagonal terms are only supported in the controlled version of the circuit.

Input instances:

Several Instances for Valid \(H\)

import numpy as np

def h_instance_0():
    return np.array([
        [0.0, 1.0],
        [1.0, 0.0],
    ])

def h_instance_1():
    return np.array([
        [0, 1, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 0, 1, 0],
    ], dtype=float)

def h_instance_2():
    return np.array([
        [0, 0, 1, 0],
        [0, 0, 0, 1],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
    ], dtype=float)

def h_instance_3():
    H = np.zeros((8, 8))

    k = 5  # 101₂
    g = 1.0

    for i in range(8):
        j = i ^ k
        H[i, j] = g
        H[j, i] = g
    return H

def h_instance_4():
    return np.array([
        [0.3, 1.0, 0.0, 0.0],
        [1.0, 0.3, 0.0, 0.0],
        [0.0, 0.0, 0.3, 1.0],
        [0.0, 0.0, 1.0, 0.3],
    ])

Doc references: [5]

API#

qolumbina.programs.hamiltonian.adder_hamiltonian_mixture#

class AdderHamiltonianMixture(input_qubits, t, name=None)[source]#

Bases: QuantumCircuit

Mixture of Draper Adder and Hamiltonian evolution for position operator.

Parameters:
  • input_qubits (int) – Number of qubits in each register, i.e., \(n\) for both addends \(\ket{x}_n\) and \(\ket{y}_n\).

  • t (float) – Evolution time \(t\) (\(t > 0\)).

  • name (str | None) – Optional name for the circuit.

Raises:

ValueError – If t is negative.

qolumbina.programs.hamiltonian.diagonal_hamiltonian#

class DiagonalZHamiltonian(input_qubits, t, name=None)[source]#

Bases: QuantumCircuit

Implements the Hamiltonian evolution exp(-i * H * t) using only single-qubit Rz gates.

Parameters:
  • input_qubits (int) – Number of qubits in the system (\(n\)).

  • t (float) – Evolution time \(t\) (\(t > 0\)).

  • name (str | None) – Optional name for the circuit.

Raises:

ValueError – If t is negative.

qolumbina.programs.hamiltonian.sparse_hamiltonian#

class SparseHamiltonian(H, t, controlled_ver, name=None)[source]#

Bases: QuantumCircuit

Sparse Hamiltonian Simulation Circuit

Parameters:
  • H (ndarray) – the sparse Hamiltonian matrix \(H\) of size \(N \times N\) where \(N = 2^n\), and \(n\) is the number of qubits.

  • t (float) – Evolution time \(t\).

  • controlled_ver (bool) – Whether to build the controlled version of the Hamiltonian simulation.

  • name (str | None) – Optional name for the circuit.

Raises:
  • ValueError – If t is negative.

  • ValueError – If H does not satisfy the required properties (real-valued, Hermitian, 2-sparse with a consistent global XOR structure and uniform coupling strengths).

V_gate(qc, H, qreg_a, qreg_b)[source]#

Hamiltonian oracle \(V\ket{a,b} = \ket{a,b+v(a)}\)

Parameters:
  • qc (QuantumCircuit) – Quantum Circuit

  • H (ndarray) – Sparse matrix

  • qreg_a (QuantumRegister) – Quantum register

  • qreg_b (QuantumRegister) – Quantum register

Return type:

QuantumCircuit

W_gate(qc, q0, q1)[source]#
Parameters:
  • qc (QuantumCircuit) – QuantumCircuit

  • q0 (QuantumRegister) – QuantumRegister as the first qubit

  • q1 (QuantumRegister) – QuantumRegister as the second qubit

Return type:

QuantumCircuit

build_with_control()[source]#

Controlled Hamiltonian simulation circuit

build_without_control()[source]#

Non-controlled Hamiltonian simulation circuit, which implements \(e^{-i H t}\) on the input register.