Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions check_my_spin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from moha.hamiltonians import AlternativeSpinHamiltonian

def main():
print("Testing AlternativeSpinHamiltonian integration...")
H = AlternativeSpinHamiltonian(num_spins=3, coupling_constants=1.0)

print("\nOne-Body Integrals:")
one_body = H.generate_one_body_integral(dense=True)
print(one_body)

print("\nTwo-Body Integrals (Shape):")
two_body = H.generate_two_body_integral(dense=True)
print(two_body.shape)

if __name__ == "__main__":
main()
45 changes: 42 additions & 3 deletions moha/hamiltonians.py
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to manually code spin operators, as we have introduced mapping from spin-operators to fermion creation/annihilation operators

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review and the guidance, @RichRick1! I completely understand. Since I was working from a ground-up approach, I missed that the spin-to-fermion mapping was already introduced.

I see the existing HamHeisenberg class in moha/hamiltonians.py. I will scrap my manual dense matrix generation and pivot to utilizing the built-in fermion creation/annihilation operators instead. Could you point me to the specific file/module where the spin-to-fermion mapping functions are stored so I can review them?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on my previous message—I’ve just reviewed the newly updated docs/spin.rst and the HamHeisenberg / HamIsing classes. I see that the library is already set up to handle these as one-body and two-body integrals. I am currently refactoring my implementation to remove the manual dense matrix Kronecker products and instead utilize the alpha/beta fermion mapping to generate the integral equivalents. This will ensure full compatibility with the existing moha solvers.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"HamPPP",
"HamHuck",
"HamHub",
"HamHeisenberg"
"HamHeisenberg",
"AlternativeSpinHamiltonian"
]


Expand Down Expand Up @@ -393,8 +394,8 @@ class HamHeisenberg(HamiltonianAPI):
Models spin-1/2 particles on a lattice with the Hamiltonian:\r
\r
.. math::\r
\hat{H}_{XXZ} = \sum_p (\mu_p^Z - J_{pp}^{\mathrm{eq}}) S_p^Z
+ \sum_{pq} J_{pq}^{\mathrm{ax}} S_p^Z S_q^Z
\hat{H}_{XXZ} = \sum_p (\mu_p^Z - J_{pp}^{\mathrm{eq}}) S_p^Z
+ \sum_{pq} J_{pq}^{\mathrm{ax}} S_p^Z S_q^Z
+ \sum_{pq} J_{pq}^{\mathrm{eq}} (S_p^+ S_q^- + S_p^- S_q^+)
\r
`HamIsing` and `HamRG` are special cases of this class.\r
Expand Down Expand Up @@ -694,3 +695,41 @@ def __init__(self,
J_ax=J_ax,
connectivity=connectivity
)


class AlternativeSpinHamiltonian(HamHeisenberg):
"""
Alternative approach to Spin Hamiltonians (Issue #179).

Acts as an adapter to map custom spin topologies directly to the
fermion creation/annihilation operators in HamHeisenberg, avoiding
dense Kronecker products.
"""
def __init__(self, num_spins, coupling_constants, connectivity=None):
self.num_spins = int(num_spins)

try:
J_val = float(np.array(coupling_constants)[0] if np.array(coupling_constants).size > 0 else 1.0)
except (TypeError, IndexError):
J_val = float(coupling_constants)

if connectivity is None or len(connectivity) == 0:
self.connectivity_list = [(i, i + 1) for i in range(self.num_spins - 1)]
else:
self.connectivity_list = connectivity

J_matrix = np.zeros((self.num_spins, self.num_spins))
for (i, j) in self.connectivity_list:
J_matrix[i, j] = J_val
J_matrix[j, i] = J_val

mu = np.zeros(self.num_spins)

super().__init__(
mu=mu,
J_eq=J_matrix,
J_ax=J_matrix
)



25 changes: 25 additions & 0 deletions moha/test/test_alternative_spin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import pytest
import numpy as np
from moha.hamiltonians import AlternativeSpinHamiltonian

def test_alternative_spin_initialization():
"""Verify that the adapter correctly maps inputs to J matrices."""
H = AlternativeSpinHamiltonian(num_spins=3, coupling_constants=1.0)

assert H.num_spins == 3
assert H.J_eq.shape == (3, 3)
assert H.J_ax.shape == (3, 3)
# Check that adjacent sites are coupled
assert H.J_eq[0, 1] == 1.0
assert H.J_eq[1, 0] == 1.0

def test_alternative_spin_integral_generation():
"""Verify the fermion mapping generates the correct tensor shapes."""
H = AlternativeSpinHamiltonian(num_spins=3, coupling_constants=1.0)

one_body = H.generate_one_body_integral(dense=True)
two_body = H.generate_two_body_integral(dense=True)

# 3 sites means 6 spin-orbitals (3 alpha, 3 beta)
assert one_body.shape == (6, 6)
assert two_body.shape == (6, 6, 6, 6)