jcmgray / quimb

A python library for quantum information and many-body calculations including tensor networks.
http://quimb.readthedocs.io
Other
501 stars 109 forks source link

Multi index per site MPS #262

Open lslattery11 opened 2 months ago

lslattery11 commented 2 months ago

Is your feature request related to a problem?

Cannot tell if this possible or not.

Describe the solution you'd like

I'd like to be able to create a MPS that groups together multiple physical indices onto one site. For example, say I have 3 spin 1/2 systems that I'd like to group together on a single site. Currently, I can group them together onto a single MPS site by letting the physical dimension of the site be = 8. Each site tensor looks like Tijk where the physical index j has dimension 8. I'd like to be able have each spin 1/2 be associated its own index so that each site tensor is Ti(lmn)k where l,m and n are each dimension 2. This would provide a significant computational speed up for my use case by letting me do a reduce-split type decomposition on each tensor where a site tensor under QR decompositon goes to Ti(lmn)k -> Qilm Rnk when I have operations that only act on index n of that tensor.

Describe alternatives you've considered

No response

Additional context

No response

jcmgray commented 4 weeks ago

Hi @lslattery11, sorry for the delayed response!

Yes this is very possible, though one might have to use slightly lower level methods - its not encapsulated in a particular class or algorithm etc. Here's an example for apply some pairwise gates:

import quimb.tensor as qtn

# start with an MPS
psi = qtn.MPS_rand_state(21, 7, seed=0)

# define some groups
groups = [range(i, i + 3)for i in range(0, psi.L, 3)]

# contract the groups into single tensors
for group in groups:
    tags = [psi.site_tag(site) for site in group]
    psi ^= tags

psi.draw(psi.site_tags, show_inds=True)

image

# do an even and odd layer of pairwise gates
for layer in [range(0, psi.L - 1, 2), range(1, psi.L - 1, 2)]:
    for i in layer:
        # canonical gauge (lazily) around target sites
        sites = (i, i + 1)
        tags = [psi.site_tag(site) for site in sites]
        psi.canonize_around_(tags, "any")

        # apply a random unitary
        G = qu.rand_uni(4)
        psi.gate_(G, sites, contract="reduce-split")
psi.draw(psi.site_tags)

image

Other than contracting the initial tensors there's no specific grouped logic here, its all handled automatically by default.