Page 1 of 1

Problem defining nearest neighbour model

Posted: 08 Feb 2025, 13:23
by stabel
Hi there -- I have a problem defining nearest neighbor models. I'm still in the discovery phase of TeNPy so please be gentle. Here is my code ..

Python: Select all

class Field(CouplingModel, NearestNeighborModel):
    def __init__(self):
        # Define the lattice with custom sites
        site = Qumode()
        lattice = Chain(lattice_size, site=site, bc='periodic')  # Use open boundary conditions
        super().__init__(lattice)
        CouplingModel.__init__(self, lattice)
        print("Nearest-neighbor pairs:", self.lat.pairs['nearest_neighbors'])  # totally screws up apparently 
        print("Number of sites in the unit cell:", len(lattice.unit_cell))  # Output: 1 -- this is so we can have local symmetries
        print("Total number of sites in the lattice:", lattice.N_sites)  # Output: 10  
I have defined a site called Qumode() which seems to work fine. lattice_size is 10. But when I do this ...

Python: Select all

print("Nearest-neighbor pairs:", field.lat.pairs['nearest_neighbors'])
I get this ...

Code: Select all

Nearest-neighbor pairs: [(0, 0, array([1]))]
There only seems to b one "pair". What am I doing wrong? I thought NearestNeighborModel would automatically include nearest neighbor couplings.

The alternative looks like to self.init_H_bonds()

Python: Select all

    def init_H_bonds(self):
        """Initialize `H_bonds` hamiltonian."""
        yada yada ...
        self.H_bonds = H_list
Sorry -- I am bit lost in all the different options. Is there a page that describes how to define your own tebd model with your own couplings?
Thanks for your help.

Re: Problem defining nearest neighbour model

Posted: 08 Feb 2025, 14:37
by stabel
Addendum --- If I manually add the nearest neighbor couplings

Python: Select all

class Field(CouplingModel, NearestNeighborModel):
    def __init__(self):
        # Define the lattice with custom sites
        site = Qumode()
        lattice = Chain(lattice_size, site=site, bc='periodic')  # Use open boundary conditions
        super().__init__(lattice)
        
        nearest_neighbors = [(i, (i + 1) % lattice_size, [1] ) for i in range(lattice_size)]
        print("Manually defined nearest-neighbor pairs:", nearest_neighbors)

        print("Nearest-neighbor pairs:", nearest_neighbors) 
        print("Number of sites in the unit cell:", len(lattice.unit_cell))  # Output: 1 -- this is so we can have local symmetries
        print("Total number of sites in the lattice:", lattice.N_sites)  # Output: 10  
   
        # Add the hopping term (q[n] q[n+1])
        #for u1, u2, dx in self.lat.pairs['nearest_neighbors']:  # doesn't work
        for u1, u2, dx in nearest_neighbors:
            print(f"u1: {u1}, type: {type(u1)}, u2: {u2}, type: {type(u2)}")
            self.add_coupling_term(1.0, u1, 'q', u2, 'q', dx, plus_hc=True) # u1, u2: The unit cell indices of the two sites involved in the interaction. dx = distance between i and j. dx=1 for nearest neighbours
this gives me ==>

Code: Select all

--------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[261], line 1
----> 1 field = Field()

Cell In[259], line 95
     93 for u1, u2, dx in nearest_neighbors:
     94     print(f"u1: {u1}, type: {type(u1)}, u2: {u2}, type: {type(u2)}")
---> 95     self.add_coupling_term(1.0, u1, 'q', u2, 'q', dx, plus_hc=True)

File ~/.venv_QIBO/lib/python3.9/site-packages/tenpy/models/model.py:1250, in CouplingModel.add_coupling_term(self, strength, i, j, op_i, op_j, op_string, category, plus_hc)
   1248     category = "{op_i}_i {op_j}_j".format(op_i=op_i, op_j=op_j)
   1249 ct = self.coupling_terms.setdefault(category, CouplingTerms(self.lat.N_sites))
-> 1250 ct.add_coupling_term(strength, i, j, op_i, op_j, op_string)
   1251 if plus_hc:
   1252     site_i = self.lat.unit_cell[self.lat.order[i, -1]]

File ~/.venv_QIBO/lib/python3.9/site-packages/tenpy/networks/terms.py:540, in CouplingTerms.add_coupling_term(self, strength, i, j, op_i, op_j, op_string)
    538 if not 0 <= i < self.L:
    539     raise ValueError("We need 0 <= i < N_sites, got i={i:d}".format(i=i))
--> 540 if not i < j:
    541     raise ValueError("need i < j")
    542 d1 = self.coupling_terms.setdefault(i, dict())

TypeError: '<' not supported between instances of 'int' and 'str'
It seems to work if I swap the operator and index, i.e.

Python: Select all

self.add_coupling_term(1.0, u1,u2, 'q', 'q', dx, plus_hc=True)
but that seems wrong. Oh boy - I'm so confused.

Re: Problem defining nearest neighbour model

Posted: 08 Feb 2025, 16:45
by stabel
Update ... sorry for the spam but at least I understood something ... judging by

https://github.com/tenpy/tenpy/blob/mai ... #L707-L742 which has ...

Python: Select all

def add_coupling_term(self, strength, i, j, op_i, op_j, op_string='Id'):
        """Add a two-site coupling term on given MPS sites.
the line self.add_coupling_term(1.0, u1,u2, 'q', 'q', dx, plus_hc=True) would be correct -- weird.

Re: Problem defining nearest neighbour model

Posted: 10 Feb 2025, 09:05
by Johannes
Take a look at the userguide for defining new models.

The idea is that you rewrite your Hamiltonian
\[H = \sum_{\langle i,j\rangle} A_i B_j = \sum_{i} \sum_{\delta = j-i} A_i A_{i+\delta}\]
and the nearest_neighbor_couplings for a given lattice are the set of \(\delta\) you need to sum over.
To be precise, we split the sum as \( i = (x,y)\) and \(\delta = (u_i,u_j, dx = (x_j - x_i, y_j - y_i))\) for a 2D lattice. For a 1D lattice, just ignore the y.


The sum over i is handled by TeNPy when you use add_coupling with the delta=u1,u2, dx. This is convenient because it can correctly and consistently handle the boundary conditions (finite vs infinite MPS, open/periodic for the lattice in each direction).


Note the difference to add_coupling_term, which adds a single coupling, not summing over i. For this version, you would hence not use u1, u2, dx from the nearest_neighbor_couplings, but rather manually "sum" by calling this function for i in range(L-1): add_coupling_term(i,i+1, ...). Here, whether you iterator until L or L-1 depends on the boundary conditions.

Re: Problem defining nearest neighbour model

Posted: 10 Feb 2025, 16:29
by stabel
Hi there, - Ah - add_coupling is repeated automatically over the sites. It seems to be working now thanks !!