Source code for tlquantum.tt_precontraction

import tensorly as tl
from torch import tensordot, transpose
from itertools import chain


# Author: Taylor Lee Patti <taylorpatti@g.harvard.edu>

# License: BSD 3 clause


[docs]def layers_contract(layer_list, ncontrl): """Contracts sublists of a list of layers vertically (merging cores of multiple layers for a single qubit) up to some maximum contraction depth. Parameters ---------- layer_list : List of tt-tensor layers ncontrl : Maximum number of layers to contract into each composite layer. Returns ------- List of layers resulting from vertically contracting the layers of layer_list """ nlayers = len(layer_list) contrsets, merge_layers = list(range(nlayers)), [] contrsets = [contrsets[i:i+ncontrl] for i in range(0, nlayers, ncontrl)] for contrset in contrsets: merge_layers.append(_vertical_contract([layer_list[i] for i in contrset])) merge_layers = list(chain.from_iterable(merge_layers)) #merge list of core lists (layers) into single list return merge_layers
def _vertical_contract(layer_list): """Contracts list of layers vertically (merging cores of multiple layers for a single qubit). Parameters ---------- layer_list : List of tt-tensor layers Returns ------- Single layer (list of cores) resulting from vertically contracting the layers of layer_list """ nlayers = len(layer_list) nqubits, merge_layers = len(layer_list[0]), [] for q in range(nqubits): cont = layer_list[0][q] #first layer of each qubit to start contraction for l in range(1, nlayers): dim1, dim2 = cont.shape, layer_list[l][q].shape cont = tensordot(layer_list[l][q], cont, dims=([2],[1])) #abdefg --> aedbfg --> aebdfg --> cont = transpose(transpose(transpose(cont, 1, 3), 2, 3), 3, 4) cont = tl.reshape(cont, (dim1[0]*dim2[0], dim1[1], dim1[2], dim1[3]*dim2[3])) merge_layers.append(cont) return merge_layers
[docs]def qubits_contract(layer, ncontraq, contrsets=None): """Contracts lists (layers) of tt-tensor cores horizontally (merging multiple cores in a single layer) up to some maximum number of qubits. Parameters ---------- layer : List of tt-tensor cores ncontrq : Maximum number of qubits to contract into each composite core. Returns ------- Layer (list of cores) resulting from horizontally contracting the cores of layer """ merge_layer, nqubits = [], len(layer) if contrsets == None: contrsets = _get_contrsets(nqubits, ncontraq) if len(layer[0].shape) == 3: #if cores have 3 indices, state tensor for contrset in contrsets: merge_layer.append(_horizontal_state_contract([layer[i] for i in contrset])) else: #if cores do not have 3 indices (here, they would have 4 indices), operator tensor for contrset in contrsets: merge_layer.append(_horizontal_contract([layer[i] for i in contrset])) return merge_layer
def _horizontal_contract(qubits): """Contracts list of qubits horizontally (merging multiple cores in a single layer). Parameters ---------- qubits : List of tt-tensor cores state : tt-tensor, input state to be evolved by unitary Returns ------- Single core resulting from horizontally contracting the cores of qubits """ cont = qubits[0] for i in range(1, len(qubits)): cont = tensordot(cont, qubits[i], dims=([3],[0])) cont = transpose(cont, 2, 3) cont = tl.reshape(cont, (cont.shape[0], cont.shape[1]*cont.shape[2], cont.shape[3]*cont.shape[4], cont.shape[-1])) return cont def _horizontal_state_contract(qubits): """Contracts list of qubits horizontally (merging multiple cores in a single layer). Parameters ---------- qubits : List of tt-tensor cores state : tt-tensor, input state to be evolved by unitary Returns ------- Single core resulting from horizontally contracting the cores of qubits """ cont = qubits[0] for i in range(1, len(qubits)): cont = tensordot(cont, qubits[i], dims=([2],[0])) cont = tl.reshape(cont, (cont.shape[0], cont.shape[1]*cont.shape[2], cont.shape[3])) return cont def _get_contrsets(nqubits, ncontraq): contrsets = list(range(nqubits)) return [contrsets[i:i+ncontraq] for i in range(0, nqubits, ncontraq)]