cpsc-qft / src /cpsc /hamiltonian.py
SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
eef9104 verified
Raw History Blame Contribute Delete
2.31 kB
# *******************************************************************************
# Copyright (c) 2026 Ahmad Ali Parr and others.
#
# This program and the accompanying materials are made available under the
# terms of the CPSC Eclipse Strict Copyleft License, Version 1.0, which is
# available in LICENSES/CPSC-ESCL-1.0.txt, or, at your option, under the
# GNU Affero General Public License, Version 3 only, which is available in
# LICENSES/AGPL-3.0.txt. Both options are strict copyleft. There is no
# classpath exception and no permissive relicensing.
#
# SPDX-License-Identifier: LicenseRef-CPSC-ESCL-1.0 OR AGPL-3.0-only
# *******************************************************************************
"""Transverse-field Ising stand-in for the 1+1D lattice specification.
The draft quartic (g/4!) sum_i X_i^4 is identically (g/24) N I, because X^2 = I.
It is reported and then omitted from the matrix.
"""
from __future__ import annotations
import numpy as np
def x4_identity_shift(n: int, g: float) -> float:
"""Constant added by sum_i X_i^4 / 24. Does not change eigenvectors."""
return (g / 24.0) * n
def transverse_ising(n: int, j: float = 1.0, lam: float = 0.5) -> np.ndarray:
"""Periodic H = -J sum Z_i Z_{i+1} + lam sum X_i, shape (2^n, 2^n)."""
if n < 2 or n > 10:
raise ValueError("n must be in 2..10 for the dense prototype")
dim = 1 << n
h = np.zeros((dim, dim), dtype=np.complex128)
for i in range(n):
# X_i on qubit i (little-endian bit i).
for basis in range(dim):
flipped = basis ^ (1 << i)
h[flipped, basis] += lam
# Z_i Z_{i+1}
nxt = (i + 1) % n
for basis in range(dim):
zi = 1.0 if ((basis >> i) & 1) == 0 else -1.0
zj = 1.0 if ((basis >> nxt) & 1) == 0 else -1.0
h[basis, basis] += -j * zi * zj
return h
def parity_of(basis: int, n: int) -> int:
"""Z-parity as the popcount mod 2. P_Z |b> = (-1)^{popcount} |b>."""
return (basis.bit_count() if hasattr(basis, "bit_count") else bin(basis).count("1")) & 1
def magnetization_of(basis: int, n: int) -> int:
"""Sum of Z eigenvalues. |0> contributes +1, |1> contributes -1."""
mag = 0
for i in range(n):
mag += 1 if ((basis >> i) & 1) == 0 else -1
return mag