Ordering of exact diagonalization basis

How do I use this algorithm? What does that parameter do?
Post Reply
bart
Posts: 29
Joined: 23 Jan 2019, 09:35

Ordering of exact diagonalization basis

Post by bart »

I am trying to match the results of TeNPy with a few other codes and am trying to figure out the TeNPy convention for the ordering of the basis in ExactDiag. For example, if we have SpinHalfFermionSites with 3 sites and (2, 2) electrons, then in total the Hilbert space has dimension 9 (N and Sz are conserved). Usually, I would expect that the Hilbert space is ordered in ascending binary numbers. For example, I would expect the statevector in this case, to be returned in the following order (using SpinHalfFermionSite notation):
[3, 3, 0]
[3, 1, 2]
[1, 3, 2]
[3, 2, 1]
[3, 0, 3]
[1, 2, 3]
[2, 3, 1]
[2, 1, 3]
[0, 3, 3]
However, it is actually returned in this order (which I can deduce by converting all the product states one-by-one):
[2, 3, 1]
[2, 1, 3]
[0, 3, 3]
[3, 2, 1]
[3, 0, 3]
[3, 3, 0]
[3, 1, 2]
[1, 2, 3]
[1, 3, 2]
Does anyone know what is the TeNPy convention for the ordering? Is it sorted in some binary representation?

Sample code to recover the basis ordering by brute force:

Python: Select all

basis_ordering = []
for i, state in enumerate(product_states):
    prod_mps = MPS.from_product_state(ED.model.lat.mps_sites(), state)     
    prod_statevector = list(ED.mps_to_full(prod_mps).to_ndarray())
    idx = prod_statevector.index(1)
    basis_ordering.append(idx)
User avatar
Johannes
Site Admin
Posts: 463
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Ordering of exact diagonalization basis

Post by Johannes »

Hi Bart,
it's essentially defined by the following line in ExactDiag.__init__()

Python: Select all

self._pipe = npc.LegPipe(legs, qconj=1, sort=(not sparse), bunch=(not sparse))
Unless you use the `sort=False` keyword, the pipe internally sorts by charge values, more precises such that it's `qmap` is lexiographically sorted - that's why you get that strange order in this case.
The task of the Pipe is essentially to 1) store the orginal legs it was contracted from and 2) the permutations done, such that the combine_legs can be un-done with the `split_legs`. Which order the pipe chooses is considered an implementation detail (it's a somewhat arbitrary convention how we do that), but we guarantee that the `split_legs` can undo the permutation done.

When you call psi_full.to_ndarray() where psi_full is e.g. the ground state returend by exact_diag.groundstate(), you will get a full single leg with d^L entries. The straightforward solution is to call split_legs() first, which undoes whatever permutation was done for the combine_legs, such that
psi_full.split_legs().to_ndarray() is simply a shape [d]*L array instead - then the mapping of indices should be very clear.
This is a bit inefficient (since it fills on all the zeros that are guaranteed by to be zero by charge conservation) - if you need to avoid that as well, you instead need to directly get the data block out of the np_conserved array, and undo the permutation yourself.
Technically, the permutation data is stored in LegPipe._perm and ._qmap, but it's probably hard to read that out and disentangle the code, if you don't know the structure. The more bruteforce but simple way would be to just call LegPipe.map_incoming_inds() for all combinations of indices you need, and get the permutation from that. (Given that we are currently rewriting the np_conserved for version 2.0, I would recommend to not invest too much time into understanding the LegPipe's internal details)
bart
Posts: 29
Joined: 23 Jan 2019, 09:35

Re: Ordering of exact diagonalization basis

Post by bart »

Ah I see, it is lexiographically sorted by `qmap`. Thank you, I will try out these suggestions to restore the conventional ordering of the statevectors. As long as one of these methods is faster than explicitly checking/converting each product state MPS, then it should be an improvement.
Jakob
Posts: 6
Joined: 30 Jan 2023, 22:57

Re: Ordering of exact diagonalization basis

Post by Jakob »

Hi bart, just FYI that this will be resolved in the next version of tenpy, developed at https://github.com/tenpy/cyten.
There, we consider this permutation in ``Tensor.to_numpy()`` such that it behaves as expected, i.e. such that ``.combine_legs(...).to_numpy()`` is equivalent to ``.to_numpy().reshape(...)``, *without* any permutations
bart
Posts: 29
Joined: 23 Jan 2019, 09:35

Re: Ordering of exact diagonalization basis

Post by bart »

I see, that's great to hear. In that case, I will not dig too deep into this. Thank you!
Post Reply