How to convert between npc.Array and one dimension np.array efficiently?

How do I use this algorithm? What does that parameter do?
Post Reply
qazwsx
Posts: 2
Joined: 09 Oct 2024, 05:03

How to convert between npc.Array and one dimension np.array efficiently?

Post by qazwsx »

In my code, I need to convert between npc.Array and one dimension np.array frequently. This code is my implementation. How can this be made more efficient?

Python: Select all

def Array_to_nparray(M):
    Arrayshape=M.shape
    Mlegs=M.legs
    flat_array = []
    block_shapes = []  
    slices_list = []
    for block, blockslices, charges, qindices in M:
        elements = block.flatten()  
        flat_array.extend(elements)  
        block_shapes.append(block.shape)
        slices_list.append(blockslices)
    flat_array = np.array(flat_array)
    return flat_array,block_shapes,slices_list,Arrayshape,Mlegs

def nparray_to_Array(flat_array,block_shapes,slices_list,Arrayshape,Mlegs):
    M_array=np.zeros(Arrayshape)
    current_index = 0
    for shape, slices in zip(block_shapes, slices_list):
        num_elements = np.prod(shape) 
        block_elements = flat_array[current_index:current_index + num_elements]
        current_index += len(block_elements)
        M_array[slices]=block_elements.reshape(shape)
    M=npc.Array.from_ndarray(M_array,legcharges=Mlegs,cutoff=1e-9)
    return M
Jakob
Posts: 5
Joined: 30 Jan 2023, 22:57

Re: How to convert between npc.Array and one dimension np.array efficiently?

Post by Jakob »

For Array_to_ndarray, the low hanging fruits are to operate on numpy arrays instead of python lists.
I probably would initialize a final_array of correct length (sum of the ``block.size`` for all blocks) and dtype, then in the loop set elements of the final_array to the block (keep somecounter variable for the current index).

For nparray_to_Array you should probably avoid building M_array, which has a lot of zeros, and instead build only the blocks.
Basically, you should use the (not super user-friendly) Array.__init__ constructor and manually set the ._data and ._qdata and ._qdatasorted.
You can have a look at e.g. the implementations of Array.copy() or Array.from_ndarray() to see examples of how these attributes are typically modified.
The ._data are the blocks that you already used in the first method and the ._qdata and ._qdatasorted should be the same as before you convert to numpy, so you just need to store them, like the Mlegs.

I dont think there is much to gain beyond these modifications.
I hope I have given enough pointers for you to have a go.

Please let us know how it went!
Possibly, we want to include your solution into the codebase.

By the way, why do you need this?
qazwsx
Posts: 2
Joined: 09 Oct 2024, 05:03

Re: How to convert between npc.Array and one dimension np.array efficiently?

Post by qazwsx »

Thank you for your advice. I am trying to optimize a translation invariant MPS with internal Zn symmetry using variational method. Since the MPS is translation invariant, it is constructed from some same tensors M. With the help of np_conserved, I have built the cost function and gradient function for M. Then, I use the conjugate gradient method to optimize M. However, scipy.minimize only accepts a one-dimensional np.array as input. Thus, I need to provide a one-dimensional np.array as the initial value and later convert this np.array into a Zn-symmetric M in the cost function and gradient function. Although I don't know the details of the conjugate gradient method, I guess that the optimization process requires iterative solving and repeated calculation of the cost function and gradient function. So I think that the nparray_to_Array function will be used many times during the optimization process.
Based on your advice, I tried to improve nparray_to_Array using Array_init_, but I was unsuccessful. Below is my code:

Python: Select all

def nparray_to_Array(flat_array, block_shapes, slices_list, Arrayshape, Mlegs):
    M = npc.Array(legcharges = Mlegs)
    data = []  
    qdata = []  
    current_index = 0  
    
    for shape, slices in zip(block_shapes, slices_list):
        num_elements = np.prod(shape)
        block_elements = flat_array[current_index:current_index + num_elements]
        current_index += num_elements
        
        block_data = block_elements.reshape(shape)
        data.append(block_data)
        
        qdata.append(slices)  

    M._data = data
    M._qdata = qdata
    M._qdata_sorted = True
    

    return M
And the error message is "TypeError: copy() takes no arguments (1 given)"
Jakob
Posts: 5
Joined: 30 Jan 2023, 22:57

Re: How to convert between npc.Array and one dimension np.array efficiently?

Post by Jakob »

At first glance, I do not see why this code should raise such an error.
Please make sure you are using an up to date version of tenpy.
If the problem persists, please open an issue on github with a minimal code example that reproduces the bug, and include the full error message.
Post Reply