jcmgray / quimb

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

Class SuperOperator1D does not work #196

Open stfnmangini opened 1 year ago

stfnmangini commented 1 year ago

What happened?

There is a problem with the SuperOperator1D class, as various errors regarding missing site tags, missing tag_map, and oset concatenations are raised when the class is called (see below).

Here is the original definition of the class: https://quimb.readthedocs.io/en/latest/autoapi/quimb/tensor/tensor_1d/index.html#quimb.tensor.tensor_1d.SuperOperator1D

I was able to circumvent the errors with minimal corrections to the original class, even though I am not completely sure that I haven't introduced other mistakes. Here is the updated definition of the class with highlighted changes:

class SuperOperator1D(TensorNetwork1D):
    r"""A 1D tensor network super-operator class::

        0   1   2       n-1
        |   |   |        |     <-- outer_upper_ind_id
        O===O===O==     =O
        |\  |\  |\       |\     <-- inner_upper_ind_id
          )   )   ) ...    )   <-- K (size of local Kraus sum)
        |/  |/  |/       |/     <-- inner_lower_ind_id
        O===O===O==     =O
        |   | : |        |     <-- outer_lower_ind_id
              :
             chi (size of entangling bond dim)

    Parameters
    ----------
    arrays : sequence of arrays
        The data arrays defining the superoperator, this should be a sequence
        of 2n arrays, such that the first two correspond to the upper and lower
        operators acting on site 0 etc. The arrays should be 5 dimensional
        unless OBC conditions are desired, in which case the first two and last
        two should be 4-dimensional. The dimensions of array can be should
        match the ``shape`` option.

    """

    _EXTRA_PROPS = (
        '_site_tag_id',
        '_outer_upper_ind_id',
        '_inner_upper_ind_id',
        '_inner_lower_ind_id',
        '_outer_lower_ind_id',
        'cyclic',
        '_L',
    )

    def __init__(
        self, arrays,
        shape='lrkud',
        site_tag_id='I{}',
        outer_upper_ind_id='kn{}',
        inner_upper_ind_id='k{}',
        inner_lower_ind_id='b{}',
        outer_lower_ind_id='bn{}',
        tags=None,
        tags_upper=None,
        tags_lower=None,
        **tn_opts,
    ):
        # short-circuit for copying
        if isinstance(arrays, SuperOperator1D):
            super().__init__(arrays)
            return

        arrays = tuple(arrays)
        self._L = len(arrays) // 2

        # process indices
        self._outer_upper_ind_id = outer_upper_ind_id
        self._inner_upper_ind_id = inner_upper_ind_id
        self._inner_lower_ind_id = inner_lower_ind_id
        self._outer_lower_ind_id = outer_lower_ind_id

        ### ! Moved process tags section here, and added tuple command() ! ###
        # process tags
        self._site_tag_id = site_tag_id
        tags = tuple(tags_to_oset(tags))
        tags_upper = tuple(tags_to_oset(tags_upper))
        tags_lower = tuple(tags_to_oset(tags_lower))

        ### ! Changed definition of sites_present ! ###
        #sites_present = tuple(self.gen_sites_present())
        sites_present = tuple(self.sites)
        outer_upper_inds = map(outer_upper_ind_id.format, sites_present)
        inner_upper_inds = map(inner_upper_ind_id.format, sites_present)
        inner_lower_inds = map(inner_lower_ind_id.format, sites_present)
        outer_lower_inds = map(outer_lower_ind_id.format, sites_present)

        ### ! Moved this section up ! ###
        # process tags
        # self._site_tag_id = site_tag_id
        # tags = tags_to_oset(tags)
        # tags_upper = tags_to_oset(tags_upper)
        # tags_lower = tags_to_oset(tags_lower)

       # The rest is the same ...
       # ....

What did you expect to happen?

No errors raised.

Minimal Complete Verifiable Example

import quimb.tensor as qtn
L = 2
K = 3
chi = 4
qtn.SuperOperator1D.rand(L, K, chi)

Relevant log output

AttributeError: 'SuperOperator1D' object has no attribute '_site_tag_id'

Anything else we need to know?

The same error arises if you specify the tensor data, instead of instantiating a random SuperOperator as in the example above.

Such error AttributeError: 'SuperOperator1D' object has no attribute '_site_tag_id' is solved by moving the process tags section in the class right after the process indices section (see updated version of the class above).

Then, another error occurs within the function self.gen_sites_present(), namely AttributeError: 'SuperOperator1D' object has no attribute 'tag_map'. In the modified class above, this is solved with the substitution:

#sites_present = tuple(self.gen_sites_present())
sites_present = tuple(self.sites)

Lastly, there is a final error in the function gen_tags(), namely TypeError: can only concatenate tuple (not "oset") to tuple. This is solved by transforming the tags to tuples, as follows.

#tags = tags_to_oset(tags)
tags = tuple(tags_to_oset(tags))

and similarly for the other tags.

As I said earlier, these small modifications fix the class but I'm not proficient enough with quimb to be sure that these do not introduce undesired behaviours.

Environment

quimb.__version__ = '1.5.0'

Open to suggestions and comments :)
And kudos to Johnnie for quimb, it's truly impressive!

jcmgray commented 1 year ago

Yes this class was a bit of an experimental afterthought that has become outdated. My suggestion would be simply to remove it for the moment. Since it currently doesn't have a real use case for me! but were you hoping to use for something specific?

stfnmangini commented 1 year ago

I see, thank you for the quick reply! As for my use case, my goal was to build an LPDO-like tensor network to represent a CP channel, and with the tweaks above it seems to do the job :D

Do you think it is worth working on it to make it compatible again with the newer versions of quimb?