示例#1
0
文件: test_Tensor.py 项目: CaoRX/CTL
    def test_TensorSumOutLeg(self):
        tensor = Tensor(data = np.zeros((3, 4, 5), dtype = np.float64), labels = ['abc', 'def', 'abc'])
        tensor.sumOutLegByLabel('abc')
        tensor.reArrange(['def', 'abc'])
        self.assertTupleEqual(tensor.shape, (4, 5))

        tensor = Tensor(data = np.zeros((3, 4, 5), dtype = np.float64), labels = ['abc', 'def', 'abc'])
        tensor.sumOutLegByLabel('abc', backward = True)
        tensor.reArrange(['def', 'abc'])
        self.assertTupleEqual(tensor.shape, (4, 3))

        tensor = Tensor(data = np.zeros((3, 4, 5), dtype = np.float64), labels = ['abc', 'def', 'abc'])
        with self.assertWarns(RuntimeWarning):
            tensor.sumOutLegByLabel('abd')
        tensor.reArrange(['abc', 'abc', 'def'])
        self.assertTupleEqual(tensor.shape, (3, 5, 4))

        a = Tensor(data = np.zeros((3, 4, 5), dtype = np.float64), labels = ['a3', 'a4', 'a5'])
        b = Tensor(data = np.zeros((4, 5, 6), dtype = np.float64), labels = ['b4', 'b5', 'b6'])
        makeLink('a4', 'b4', a, b)
        with self.assertWarns(RuntimeWarning):
            a.sumOutLegByLabel('a4')
        a.reArrange(['a5', 'a3'])
        self.assertEqual(a.shape, (5, 3))

        bLeg = b.getLeg('b4')
        with self.assertWarns(RuntimeWarning):
            a.sumOutLeg(bLeg)
示例#2
0
    def test_MPSContraction(self):
        mpsA = self.createMPSA(tensorLikeFlag=False)
        mpsB = self.createMPSB(tensorLikeFlag=False)

        tensorA2 = mpsA.getTensor(2)
        tensorB2 = mpsB.getTensor(2)

        makeLink('o', 'o', tensorA2, tensorB2)
        # print(mpsA, mpsB)
        mps = contractMPS(mpsA, mpsB)
        # print(mps)

        mps.canonicalize(idx=2)
        self.assertTrue(mps.checkCanonical())
        self.assertTrue(mps.n, 7)  # 4 + 5 - 2
        self.assertTrue(mps.activeIdx, 2)

        mpsA = self.createMPSA(tensorLikeFlag=True)
        mpsB = self.createMPSB(tensorLikeFlag=True)

        tensorA2 = mpsA.getTensor(2)
        tensorB2 = mpsB.getTensor(2)

        makeLink('o', 'o', tensorA2, tensorB2)
        # print(mpsA, mpsB)
        mps = contractMPS(mpsA, mpsB)
        # print(mps)

        mps.canonicalize(idx=2)
        self.assertTrue(mps.checkCanonical())
        self.assertTrue(mps.n, 7)  # 4 + 5 - 2
        self.assertTrue(mps.activeIdx, 2)
示例#3
0
文件: TRG.py 项目: CaoRX/CTL
    def iterate(self):
        # print('iterate:')
        if (self.iterateFTN is None):
            self.iterateFTN = triangleContractFTN()

        self.a.addTensorTag('a')
        self.b.addTensorTag('b')

        dof = self.a.degreeOfFreedom
        makeLink(self.a.getLeg('a-1'), self.b.getLeg('b-1'))
        iTensor = contractTwoTensors(self.a, self.b)

        a2Dim, b2Dim, a3Dim, b3Dim = iTensor.shapeOfLabels(
            ['a-2', 'b-2', 'a-3', 'b-3'])

        iMat = iTensor.toMatrix(rows=['a-2', 'b-2'], cols=['a-3', 'b-3'])
        u, v, error = SVDDecomposition(iMat, self.chi)
        self.errors.append(error)
        # print(u.shape, v.shape)
        # print(iTensor.shape)

        u = xplib.xp.reshape(u, (a2Dim, b2Dim, u.shape[1]))
        v = xplib.xp.reshape(v, (a3Dim, b3Dim, v.shape[1]))

        uTensor = makeTriangleTensor(u, labels=['2', '3', '1'])
        vTensor = makeTriangleTensor(v, labels=['2', '3', '1'])

        self.a = self.iterateFTN.contract(makeTriangleTensorDict(uTensor))
        self.b = self.iterateFTN.contract(makeTriangleTensorDict(vTensor))

        self.a.degreeOfFreedom = dof * 3
        self.b.degreeOfFreedom = dof * 3

        # self.normalizeTensors()
        self.appendToArchive()
示例#4
0
    def contract(self, tensorDict, removeTensorTag=True):
        self.lock()

        if (isinstance(tensorDict, dict)):
            tensorDict = TensorDict(tensorDict)

        # print(tensorDict.tensors)

        assert funcs.compareLists(
            self.tensorNames, list(tensorDict.tensors.keys())
        ), "Error: input tensorDict {} does not compatible with FTN {}.".format(
            list(tensorDict.tensors.keys()), self.tensorNames)

        localTensors = dict()
        for name in tensorDict.tensors:
            localTensors[name] = tensorDict.tensors[name].copy()

        for tensor, legName, newName in self.changeNameBefore:
            localTensors[tensor].renameLabel(legName, newName)

        for name in localTensors:
            localTensors[name].addTensorTag(name)

        for leg1, leg2 in self.links:
            tensorA, legA = leg1
            tensorB, legB = leg2
            makeLink(legA, legB, localTensors[tensorA], localTensors[tensorB])

        self.changed = False
        self.loadBondDims(localTensors)

        tensorList = [localTensors[name] for name in self.tensorNames]
        if (self.optimalSeq is None) or (self.realCost and self.changed):
            # print('getting optimal seq')
            self.optimalSeq = generateOptimalSequence(
                tensorList, bf=False, typicalDim=self.typicalDim)
            # print('optimal seq = {}'.format(self.optimalSeq))

        res = contractWithSequence(tensorList,
                                   seq=self.optimalSeq,
                                   inplace=True)
        # print(res)
        # print(tensorDict.tensors)

        for labelList, newLabel in self.outProductAfter:
            labelList = [
                self._dealOutProductLabel(label) for label in labelList
            ]
            # print(labelList, newLabel)
            # print(res.labels)
            res.outProduct(labelList, 'res-' + newLabel)
            # print(res.labels)

        for tensor, legName, newName in self.changeNameAfter:
            res.renameLabel(tensor + '-' + legName, tensor + '-' + newName)

        if (removeTensorTag):
            res.removeTensorTag()
        return res
示例#5
0
def twoTensorsContraction():
    shapeA = (3, 4, 5)
    shapeB = (5, 4)

    a = Tensor(labels=['a3', 'a4', 'a5'], data=np.ones(shapeA))
    b = Tensor(labels=['b5', 'b4'], data=np.ones(shapeB))

    makeLink('a4', 'b4', a, b)
    makeLink('a5', 'b5', a, b)
    c = a @ b
    print(c)
示例#6
0
def copyTensorList(tensorList, tensorLikeFlag=False, linkOutgoingBonds=False):
    """
    Make a copy of tensor list. Usually used for not-in-place tensor contraction.

    The difference from [x.copy() for x in tensorList]: it will copy all the bonds between tensors in tensorList.

    Parameters
    ----------
    tensorList : list of Tensor

    tensorLikeFlag : bool, default False
        Whether we are copying a set of TensorLikes(instead of tensors).
    linkOutgoingBonds : bool, default False
        Whether we connect the bonds outgoing(not in tensorList). If true, then all the old bonds will be replaced with new bonds generated for the copies. This is not recommended behavior since the function changes something it should not touch, but this is saved for future usage.
    
    Returns
    -------
    resTensroList : list of Tensor
        A copy of the given tensor list.
    """
    resTensorList = []
    tensorMap = dict()
    for tensor in tensorList:
        if (tensorLikeFlag):
            resTensorList.append(tensor.toTensorLike())
        else:
            resTensorList.append(tensor.copy())
        tensorMap[tensor] = resTensorList[-1]
    # use the objects themselves as key, so no worry about double name
    # print(tensorMap)

    addedBonds = set()
    for tensor in tensorList:
        for leg, newLeg1 in zip(tensor.legs, tensorMap[tensor].legs):
            if (leg.bond is not None) and (leg.bond not in addedBonds):
                leg2 = leg.anotherSide()

                addedBonds.add(leg.bond)

                if (leg2.tensor not in tensorList):
                    if (linkOutgoingBonds):
                        del leg.bond
                        makeLink(newLeg1, leg2)
                    continue

                newTensorB = tensorMap[leg2.tensor]

                newLeg2 = newTensorB.legs[leg2.tensor.legs.index(leg2)]
                makeLink(newLeg1, newLeg2)

                # no consideration about leg name, only from their relative positions

    return resTensorList
示例#7
0
    def createMPSA(self, tensorLikeFlag=False):
        tensor1L = Tensor(shape=(3, 3),
                          labels=['o', 'internal'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor11 = Tensor(shape=(3, 5, 4),
                          labels=['itl', 'oo', 'itr'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor12 = Tensor(shape=(4, 2, 4),
                          labels=['itl', 'oo', 'itr'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor13 = Tensor(shape=(4, 3, 2),
                          labels=['itl', 'oo', 'itr'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor1R = Tensor(shape=(2, 5),
                          labels=['internal', 'o'],
                          tensorLikeFlag=tensorLikeFlag)

        makeLink('internal', 'itl', tensor1L, tensor11)
        makeLink('itr', 'itl', tensor11, tensor12)
        makeLink('itr', 'itl', tensor12, tensor13)
        makeLink('itr', 'internal', tensor13, tensor1R)

        tensorsA = [tensor1L, tensor11, tensor12, tensor13, tensor1R]

        mpsA = FreeBoundaryMPS(tensorList=tensorsA, chi=16)
        return mpsA
示例#8
0
文件: Ising.py 项目: CaoRX/CTL
def IsingTNFromUndirectedGraph(g):
    """
    Create a tensor network of Ising model basing on an undirected graph.

    Parameters
    ----------
    g : UndirectedGraph
        The site-graph to add interaction. The weights represent the betaJ on each edge.
    
    Returns
    -------
    list of Tensor
        A tensor network, each of the tensors represents one site, and the contraction of this tensor network will give the exact partition function Z.
    """

    funcName = 'CTL.models.Ising.IsingTNFromUndirectedGraph'
    assert (isinstance(g, UndirectedGraph)), funcs.errorMessage(
        err=
        "only UndirectedGraph can be trasferred to Ising tensor network, {} obtained."
        .format(g),
        location=funcName)

    nodes = g.v
    edgeIndex = dict()
    for ei, edge in enumerate(g.getEdges()):
        edgeIndex[edge] = ei

    def getLegName(edge, toV):
        return str(toV.index) + '-' + str(edgeIndex[edge])

    def getLabels(v):
        return [getLegName(edge=e, toV=e.anotherSide(v)) for e in v.edges]

    def getWeights(v):
        return [e.weight for e in v.edges]

    tensors = [
        IsingSiteTensor(betaJ=getWeights(v),
                        dim=len(v.edges),
                        labels=getLabels(v)) for v in nodes
    ]

    for ei, edge in enumerate(g.getEdges()):
        v1, v2 = edge.vertices
        idx1, idx2 = v1.index, v2.index
        makeLink(getLegName(edge=edge, toV=v2), getLegName(edge=edge, toV=v1),
                 tensors[idx1], tensors[idx2])

    return tensors
示例#9
0
    def createCompleteGraph(self, n, dimRange=(2, 3)):
        low, high = dimRange
        dims = np.random.randint(low=low, high=high, size=(n, n))
        for i in range(n):
            for j in range(i, n):
                dims[j][i] = dims[i][j]

        tensors = []
        for i in range(n):
            shape = tuple([dims[i][j] for j in range(n) if (j != i)])
            labels = [str(j) for j in range(n) if (j != i)]
            tensor = Tensor(shape=shape, labels=labels)
            tensors.append(tensor)

        for i in range(n):
            for j in range(i + 1, n):
                makeLink(str(j), str(i), tensors[i], tensors[j])

        return tensors
示例#10
0
    def test_MPSMerge(self):
        mpsA = self.createMPSA()
        mpsB = self.createMPSB()

        makeLink('o', 'o', mpsA.getTensor(1), mpsB.getTensor(1))
        makeLink('o', 'o', mpsA.getTensor(4), mpsB.getTensor(3))

        # print(mpsA, mpsB)

        mergeMPS(mpsA, mpsB)
        # print(mpsA, mpsB)

        self.assertTrue(mpsA.checkCanonical(excepIdx=mpsA.n - 1))
        self.assertTrue(mpsB.checkCanonical(excepIdx=mpsB.n - 1))
        self.assertEqual(mpsA.n, 4)
        self.assertEqual(mpsB.n, 3)

        mpsA.moveTensor(mpsA.n - 1, 1)
        mpsB.moveTensor(mpsB.n - 1, 0)
        mps = contractMPS(mpsB, mpsA)
        mps.canonicalize(idx=2)

        self.assertTrue(mps.checkCanonical())
        self.assertEqual(mps.n, 5)

        mpsA = self.createMPSFromDim(dims=[3, 4, 5, 5, 2])
        mpsB = self.createMPSFromDim(dims=[2, 5, 3, 3, 4])
        mpsA.canonicalize(idx=1)
        mpsB.canonicalize(idx=2)
        # print(mpsA, mpsB)

        makeLink('o', 'o', mpsA.getTensor(1), mpsB.getTensor(4))
        makeLink('o', 'o', mpsA.getTensor(0), mpsB.getTensor(2))
        makeLink('o', 'o', mpsB.getTensor(0), mpsA.getTensor(4))

        mergeMPS(mpsA, mpsB, beginFlag=True)
        # print(mpsA, mpsB)

        self.assertEqual(mpsA.n, 3)
        self.assertEqual(mpsB.n, 3)
        mps = contractMPS(mpsA, mpsB)
        self.assertEqual(mps.n, 4)
示例#11
0
    def createMPSFromDim(self,
                         dims,
                         itbRange=(3, 10),
                         tensorLikeFlag=False,
                         chi=16):
        # internal bonds will be automaticall
        lastDim = -1
        tensors = []
        n = len(dims)

        if (n == 1):
            tensors.append(
                Tensor(shape=(dims[0], ),
                       labels=['o'],
                       tensorLikeFlag=tensorLikeFlag))
            return FreeBoundaryMPS(tensorList=tensors, chi=chi)

        itbLow, itbHigh = itbRange

        bondDim = np.random.randint(low=itbLow, high=itbHigh)
        tensor = Tensor(shape=(dims[0], bondDim),
                        labels=['o', 'r'],
                        tensorLikeFlag=tensorLikeFlag)
        tensors.append(tensor)
        lastDim = bondDim
        for i in range(1, n - 1):
            bondDim = np.random.randint(low=itbLow, high=itbHigh)
            newTensor = Tensor(shape=(lastDim, dims[i], bondDim),
                               labels=['l', 'o', 'r'],
                               tensorLikeFlag=tensorLikeFlag)
            tensors.append(newTensor)
            makeLink('r', 'l', tensor, newTensor)
            lastDim = bondDim
            tensor = newTensor

        newTensor = Tensor(shape=(lastDim, dims[-1]),
                           labels=['l', 'o'],
                           tensorLikeFlag=tensorLikeFlag)
        tensors.append(newTensor)
        makeLink('r', 'l', tensor, newTensor)

        return FreeBoundaryMPS(tensorList=tensors, chi=chi)
示例#12
0
def example():
    shapeA = (300, 400, 50)
    shapeB = (300, 600)
    shapeC = (400, 600, 50)
    a = Tensor(labels=['a3', 'b4', 'c5'], data=np.ones(shapeA))
    b = Tensor(labels=['a3', 'd6'], data=np.ones(shapeB))
    c = Tensor(labels=['e4', 'd6', 'c5'], data=np.ones(shapeC))

    # create tensors with labels

    makeLink('a3', 'a3', a, b)
    makeLink('c5', 'c5', a, c)
    makeLink('d6', 'd6', b, c)

    # make links via labels
    # note that labels can also be made between the "Leg" objects to avoid reused leg names, but here for simplicity from leg names

    # now we have a tensor network, we can generate the optimal sequence of this tensor list
    optimalSeq = generateOptimalSequence([a, b, c])
    print('optimal contraction sequence = {}'.format(optimalSeq))

    # if we do not have any knowledge in prior, we can contract the tensor list like
    res = contractTensorList([a, b, c])
    print(res)

    # if you already have a good sequence to use
    res, cost = contractAndCostWithSequence([a, b, c], seq=optimalSeq)
    print(res)
    print('contraction cost = {}'.format(cost))

    # if you want to save time / space by contract in place(note that after this you cannot contract them again, since their bonds between have been broken):
    res = contractWithSequence([a, b, c], seq=optimalSeq, inplace=True)
    print(res)
    print('')
示例#13
0
    def test_TensorGraph(self):
        shapeA = (300, 4, 5)
        shapeB = (300, 6)
        shapeC = (4, 6, 5)
        a = Tensor(shape=shapeA,
                   labels=['a300', 'b4', 'c5'],
                   data=np.ones(shapeA))
        b = Tensor(shape=shapeB, labels=['a300', 'd6'], data=np.ones(shapeB))
        c = Tensor(shape=shapeC,
                   labels=['b4', 'd6', 'c5'],
                   data=np.ones(shapeC))

        makeLink(a.getLeg('a300'), b.getLeg('a300'))
        makeLink(a.getLeg('b4'), c.getLeg('b4'))
        makeLink(a.getLeg('c5'), c.getLeg('c5'))
        makeLink(b.getLeg('d6'), c.getLeg('d6'))

        tensorList = [a, b, c]

        tensorGraph = makeTensorGraph(tensorList)

        # if we use typical dim, then contract between 0 and 2 first is preferred
        # and this is not true if we consider the real bond dimension 300

        seq = tensorGraph.optimalContractSequence(typicalDim=None)
        self.assertListEqual(seq, [(0, 1), (2, 0)])
        self.assertEqual(tensorGraph.optimalCostResult(), 36120)

        seq = tensorGraph.optimalContractSequence(typicalDim=None, bf=True)
        self.assertEqual(tensorGraph.optimalCostResult(), 36120)

        # res1 = contractWithSequence(tensorList, seq = seq)

        seq = tensorGraph.optimalContractSequence(typicalDim=10)
        self.assertListEqual(seq, [(0, 2), (1, 0)])
        self.assertEqual(tensorGraph.optimalCostResult(), 10100)

        seq = tensorGraph.optimalContractSequence(typicalDim=10, bf=True)
        self.assertEqual(tensorGraph.optimalCostResult(), 10100)

        res2 = contractWithSequence(tensorList, seq=seq)
        self.assertEqual(
            res2.a**2,
            funcs.tupleProduct(shapeA) * funcs.tupleProduct(shapeB) *
            funcs.tupleProduct(shapeC))
示例#14
0
def triangleTensorTrace(a, b):
    """
    Take the trace of two triangle tensors, usually work for the end of the RG of triangular lattice.

    Parameters
    ----------
    a, b : Tensor
        Two tensors of the triangular shape(namely, 3 legs ['1', '2', '3']).
    
    Returns
    -------
    Tensor
        The trace tensor of the two tensors. If a and b only have legs ['1', '2', '3'], then shapeless(so the value can be obtained as res.single()), otherwise the tensor of the remaining legs.
    """
    tensorA = a.copy()
    tensorB = b.copy()

    bonds = []

    for label in ['1', '2', '3']:
        bonds += makeLink(label, label, tensorA=tensorA, tensorB=tensorB)

    res = contractTwoTensors(tensorA, tensorB, bonds=bonds)
    return res
示例#15
0
    def createMPSB(self, tensorLikeFlag=False):
        tensor2L = Tensor(shape=(3, 3),
                          labels=['o', 'internal'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor21 = Tensor(shape=(3, 5, 4),
                          labels=['itl', 'oo', 'itr'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor22 = Tensor(shape=(4, 2, 4),
                          labels=['itl', 'oo', 'itr'],
                          tensorLikeFlag=tensorLikeFlag)
        tensor2R = Tensor(shape=(4, 5),
                          labels=['internal', 'o'],
                          tensorLikeFlag=tensorLikeFlag)

        makeLink('internal', 'itl', tensor2L, tensor21)
        makeLink('itr', 'itl', tensor21, tensor22)
        makeLink('itr', 'internal', tensor22, tensor2R)

        tensorsB = [tensor2L, tensor21, tensor22, tensor2R]
        mpsB = FreeBoundaryMPS(tensorList=tensorsB, chi=12)
        return mpsB
示例#16
0
文件: test_cupy.py 项目: CaoRX/CTL
def simplestExample():
    shapeA = (300, 4, 5)
    shapeB = (300, 6)
    shapeC = (4, 6, 5)
    a = Tensor(labels=['a300', 'b4', 'c5'], data=xplib.xp.ones(shapeA))
    b = Tensor(labels=['a300', 'd6'], data=xplib.xp.ones(shapeB))
    c = Tensor(labels=['e4', 'd6', 'c5'], data=xplib.xp.ones(shapeC))

    # create tensors with labels

    makeLink('a300', 'a300', a, b)
    makeLink('c5', 'c5', a, c)
    makeLink('d6', 'd6', b, c)

    # make links via labels
    # note that labels can also be made between the "Leg" objects to avoid reused leg names, but here for simplicity from leg names

    # now we have a tensor network, we can generate the optimal sequence of this tensor list
    optimalSeq = generateOptimalSequence([a, b, c])
    print('optimal contraction sequence = {}'.format(optimalSeq))

    # if we do not have any knowledge in prior, we can contract the tensor list like
    res = contractTensorList([a, b, c])
    print(res)

    # if you already have a good sequence to use
    res = contractWithSequence([a, b, c], seq=optimalSeq)
    print(res)

    # if you want to save time / space by contract in place(note that after this you cannot contract them again, since their bonds between have been broken):
    res = contractWithSequence([a, b, c], seq=optimalSeq, inplace=True)
    print(res)
    print('')

    # for reusable inplace contraction(which is our goal), refer to the use of CTL.tensornetwork.tensornetwork.FiniteTensorNetwork

    return res
示例#17
0
    def test_outerProduct(self):
        a = Tensor(shape=(2, ), labels=['a'])
        b = Tensor(shape=(2, ), labels=['b'])

        op = contractTwoTensors(a, b, outProductWarning=False)
        self.assertTrue(funcs.compareLists(op.labels, ['a', 'b']))

        a = Tensor(shape=(2, 2, 2), labels=['a', 'b', 'c'])
        b = Tensor(shape=(2, ), labels=['x'])
        c = Tensor(shape=(2, ), labels=['y'])

        makeLink('a', 'x', a, b)
        makeLink('b', 'y', a, c)
        prod = contractTensorList([a, b, c], outProductWarning=False)
        self.assertTrue(funcs.compareLists(prod.labels, ['c']))

        dataA = np.random.random_sample((2, 2))
        dataB = np.random.random_sample((3, 3))
        a = Tensor(shape=(2, 2), labels=['a1', 'a2'], data=dataA)
        b = Tensor(shape=(3, 3), labels=['b1', 'b2'], data=dataB)

        prod = contractTensorList([a, b], outProductWarning=False)
        prod.reArrange(['a1', 'a2', 'b1', 'b2'])

        res = np.zeros((2, 2, 3, 3))
        for i in range(2):
            for j in range(2):
                for k in range(3):
                    for l in range(3):
                        res[(i, j, k, l)] = dataA[(i, j)] * dataB[(k, l)]
        # print(res, prod.a)
        self.assertTrue(funcs.floatArrayEqual(res, prod.a))

        a = Tensor(shape=(2, 2), labels=['a1', 'a2'], data=dataA)
        b = DiagonalTensor(shape=(3, 3),
                           labels=['b1', 'b2'],
                           data=np.diag(dataB))
        prod = contractTensorList([a, b], outProductWarning=False)
        prodData = prod.toTensor(['a1', 'a2', 'b1', 'b2'])
        # prod.reArrange(['a1', 'a2', 'b1', 'b2'])

        res = np.zeros((2, 2, 3, 3))
        for i in range(2):
            for j in range(2):
                for k in range(3):
                    # for l in range(3):
                    res[(i, j, k, k)] = dataA[(i, j)] * dataB[(k, k)]
        # print(res, prod.a)
        self.assertTrue(funcs.floatArrayEqual(res, prodData))

        dataA = np.random.random_sample((2, 2))
        dataB = np.random.random_sample(3)

        a = Tensor(shape=(2, 2), labels=['a1', 'a2'], data=dataA)
        b = DiagonalTensor(shape=(3, 3, 3),
                           labels=['b1', 'b2', 'b3'],
                           data=dataB)
        prod = contractTensorList([a, b], outProductWarning=False)
        prodData = prod.toTensor(['a1', 'a2', 'b1', 'b2', 'b3'])
        # prod.reArrange(['a1', 'a2', 'b1', 'b2'])

        res = np.zeros((2, 2, 3, 3, 3))
        for i in range(2):
            for j in range(2):
                for k in range(3):
                    # for l in range(3):
                    res[(i, j, k, k, k)] = dataA[(i, j)] * dataB[k]
        # print(res, prod.a)
        self.assertTrue(funcs.floatArrayEqual(res, prodData))
示例#18
0
文件: test_merge.py 项目: CaoRX/CTL
    def test_merge(self):
        '''
        test the merge(ta, tb) for merge the bonds between ta and tb
        '''

        # normal tensor merge case: 2 shared bonds
        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        ta, tb = merge(ta, tb)

        self.assertTrue(funcs.compareLists(ta.labels, ['a3|a4', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b3|b4', 'b6']))
        ta.reArrange(['a3|a4', 'a5'])
        self.assertTupleEqual(ta.shape, (12, 5))
        tb.reArrange(['b3|b4', 'b6'])
        self.assertTupleEqual(tb.shape, (12, 6))
        self.assertEqual(len(shareBonds(ta, tb)), 1)

        # normal tensor merge case, order changed

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        tb, ta = merge(tb, ta)

        self.assertTrue(funcs.compareLists(ta.labels, ['a4|a3', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b4|b3', 'b6']))

        # test single shared bond: with warning, and do nothing but rename

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        makeLink('a3', 'b3', ta, tb)
        # tb, ta = merge(tb, ta, bondName = 'o')

        with self.assertWarns(RuntimeWarning) as cm:
            tb, ta = merge(tb, ta, bondName='o')

        self.assertIn('link.py', cm.filename)
        message = cm.warning.__str__()
        self.assertIn('mergeLink cannot merge links', message)
        self.assertIn('sharing one bond', message)
        self.assertTrue(funcs.compareLists(['o', 'a4', 'a5'], ta.labels))
        self.assertTrue(funcs.compareLists(['o', 'b4', 'b6'], tb.labels))

        # test for normal merge, tensorLike

        ta = Tensor(shape=(3, 4, 5),
                    labels=['a3', 'a4', 'a5'],
                    tensorLikeFlag=True)
        tb = Tensor(shape=(4, 3, 6),
                    labels=['b4', 'b3', 'b6'],
                    tensorLikeFlag=True)

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        ta, tb = merge(ta, tb)

        self.assertTrue(funcs.compareLists(ta.labels, ['a3|a4', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b3|b4', 'b6']))
        ta.reArrange(['a3|a4', 'a5'])
        self.assertTupleEqual(ta.shape, (12, 5))
        tb.reArrange(['b3|b4', 'b6'])
        self.assertTupleEqual(tb.shape, (12, 6))
        self.assertEqual(len(shareBonds(ta, tb)), 1)
        self.assertTrue(ta.tensorLikeFlag and tb.tensorLikeFlag)

        # test for single bond merge, tensorLike

        ta = Tensor(shape=(3, 4, 5),
                    labels=['a3', 'a4', 'a5'],
                    tensorLikeFlag=True)
        tb = Tensor(shape=(4, 3, 6),
                    labels=['b4', 'b3', 'b6'],
                    tensorLikeFlag=True)

        makeLink('a3', 'b3', ta, tb)
        # tb, ta = merge(tb, ta, bondName = 'o')

        with self.assertWarns(RuntimeWarning) as cm:
            tb, ta = merge(tb, ta, bondName='o')

        self.assertIn('link.py', cm.filename)
        message = cm.warning.__str__()
        self.assertIn('mergeLink cannot merge links', message)
        self.assertIn('sharing one bond', message)
        self.assertTrue(ta.tensorLikeFlag and tb.tensorLikeFlag)

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        with self.assertWarns(RuntimeWarning) as cm:
            ta, tb = merge(ta, tb, bondName='o')
        self.assertIn('link.py', cm.filename)

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        with self.assertWarns(RuntimeWarning) as cm:
            ta, tb = merge(ta, tb, bondName='o', chi=2)
        # print(cm.__dict__)
        self.assertIn('link.py', cm.filename)

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        ta, tb = merge(ta, tb, chi=2)

        self.assertTrue(funcs.compareLists(ta.labels, ['a3|a4', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b3|b4', 'b6']))
        ta.reArrange(['a3|a4', 'a5'])
        self.assertTupleEqual(ta.shape, (2, 5))
        tb.reArrange(['b3|b4', 'b6'])
        self.assertTupleEqual(tb.shape, (2, 6))
        self.assertEqual(len(shareBonds(ta, tb)), 1)

        ta = Tensor(shape=(3, 4, 5),
                    labels=['a3', 'a4', 'a5'],
                    tensorLikeFlag=True)
        tb = Tensor(shape=(4, 3, 6),
                    labels=['b4', 'b3', 'b6'],
                    tensorLikeFlag=True)

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        ta, tb = merge(ta, tb, chi=2)
        # print(ta, tb)

        self.assertTrue(funcs.compareLists(ta.labels, ['a3|a4', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b3|b4', 'b6']))
        ta.reArrange(['a3|a4', 'a5'])
        self.assertTupleEqual(ta.shape, (2, 5))
        tb.reArrange(['b3|b4', 'b6'])
        self.assertTupleEqual(tb.shape, (2, 6))
        self.assertEqual(len(shareBonds(ta, tb)), 1)
        self.assertTrue(ta.tensorLikeFlag and tb.tensorLikeFlag)

        ta = Tensor(shape=(3, 4, 5), labels=['a3', 'a4', 'a5'])
        tb = Tensor(shape=(4, 3, 6), labels=['b4', 'b3', 'b6'])

        makeLink('a3', 'b3', ta, tb)
        makeLink('a4', 'b4', ta, tb)

        # large chi test
        ta, tb = merge(ta, tb, chi=15)
        # the real internal bond size is chosen by min(chi, ta.remainShape, tb.remainShape, mergeShape)

        self.assertTrue(funcs.compareLists(ta.labels, ['a3|a4', 'a5']))
        self.assertTrue(funcs.compareLists(tb.labels, ['b3|b4', 'b6']))
        ta.reArrange(['a3|a4', 'a5'])
        self.assertTupleEqual(ta.shape, (5, 5))
        tb.reArrange(['b3|b4', 'b6'])
        self.assertTupleEqual(tb.shape, (5, 6))
        self.assertEqual(len(shareBonds(ta, tb)), 1)
示例#19
0
def selfTrace(tensor):
    a, b = tensor.copyN(2)
    for leg1, leg2 in zip(a.legs, b.legs):
        makeLink(leg1, leg2)

    return a @ b
示例#20
0
    def test_contraction(self):
        self.showTestCaseBegin("diagonal tensor contraction")
        # print('Begin test diagonalTensor contraction.')
        a = DiagonalTensor(shape = (2, 2), labels = ['a', 'b'])
        b = Tensor(shape = (2, ), labels = ['x'])
        c = Tensor(shape = (2, ), labels = ['y'])

        makeLink('a', 'x', a, b)
        makeLink('b', 'y', a, c)
        seq = generateOptimalSequence([a, b, c], typicalDim = 10)
        # print('optimal sequence = {}'.format(seq))
        prod, cost = contractAndCostWithSequence([a, b, c], seq = seq)
        # print('cost = {}'.format(cost))
        # prod = contractTensorList([a, b, c], outProductWarning = False)
        self.assertTrue(funcs.compareLists(prod.labels, []))
        self.assertListEqual(seq, [(0, 2), (1, 0)])
        self.assertEqual(cost, 4.0)

        # if we use Tensor instead of DiagonalTensor for a
        # then the cost should be 12.0, and the order should be (1, 2), (0, 1)
        # the optimal cost of diagonal tensors can be achieved if we use diagonal nature for contraction

        a = DiagonalTensor(shape = (2, 2, 2), labels = ['a', 'b', 'c'])
        b = DiagonalTensor(shape = (2, 2), labels = ['x', 'y'])
        makeLink('a', 'x', a, b)
        prod, cost = contractAndCostWithSequence([a, b])
        self.assertEqual(cost, 2)
        self.assertTrue(funcs.compareLists(prod.labels, ['b', 'c', 'y']))

        aData = np.array([[[1, 0], [0, 0]], [[0, 0], [0, 3]]])
        bData = np.random.random_sample(2)
        cData = np.random.random_sample(2)

        a = DiagonalTensor(data = aData, labels = ['a', 'b', 'c'])
        b = Tensor(data = bData, labels = ['x'])
        c = Tensor(data = cData, labels = ['y'])

        makeLink('a', 'x', a, b)
        makeLink('b', 'y', a, c)

        res1, _ = contractAndCostWithSequence([a, b, c])
        # print('seq = {}'.format(generateOptimalSequence([a, b, c])))

        a = Tensor(data = aData, labels = ['a', 'b', 'c'])
        b = Tensor(data = bData, labels = ['x'])
        c = Tensor(data = cData, labels = ['y'])

        makeLink('a', 'x', a, b)
        makeLink('b', 'y', a, c)

        res2, _ = contractAndCostWithSequence([a, b, c])
        # self.assertListEqual(list(res1.a), list(res2.a))
        self.assertTrue(funcs.floatArrayEqual(res1.a, res2.a))

        # print(cost1, cost2)

        # print(res1.a, res2.a)

        # test diagonal tensor contraction
        a = DiagonalTensor(shape = (2, 2), labels = ['a1', 'a2'])
        b = DiagonalTensor(shape = (2, 2, 2), labels = ['b1', 'b2', 'b3'])
        makeLink('a1', 'b1', a, b)
        res = a @ b
        self.assertTupleEqual(res.shape, (2, 2, 2))
        self.assertEqual(res.dim, 3)
        self.assertTrue(res.diagonalFlag)
        self.assertTrue((res.a == np.ones(2)).all())

        # test for diagonal * diagonal contraction cost(just O(length))
        a = DiagonalTensor(shape = (2, 2), labels = ['a1', 'a2'])
        b = DiagonalTensor(shape = 2, labels = ['b1', 'b2']) # deduce dim
        makeLink('a1', 'b2', a, b)

        cost, _ = contractCost(a, b)
        self.assertEqual(cost, 2.0)

        res, cost = contractAndCostWithSequence([a, b])
        self.assertEqual(res.dim, 2)
        self.assertEqual(res._length, 2)
        self.assertTupleEqual(res.shape, (2, 2))
        self.assertEqual(cost, 2.0)
        self.assertTrue(res.diagonalFlag)

        a = DiagonalTensor(shape = (2, 2), labels = ['a1', 'a2'])
        b = Tensor(shape = (2, 3, 3), labels = ['b1', 'b2', 'b3']) # deduce dim
        makeLink('a1', 'b1', a, b)

        cost, _ = contractCost(a, b)
        self.assertEqual(cost, 18.0)

        res, cost = contractAndCostWithSequence([a, b])
        # print(res)
        self.assertEqual(res.dim, 3)
        self.assertTrue(funcs.compareLists(list(res.shape), [2, 3, 3]))
        self.assertEqual(cost, 18.0)
        self.showTestCaseEnd("diagonal tensor contraction")
示例#21
0
    def test_extremeContraction(self):

        self.showTestCaseBegin("diagonal tensor extreme contraction")

        aData = np.random.random_sample(2)
        aTensorData = np.array([[[aData[0], 0], [0, 0]], [[0, 0], [0, aData[1]]]])
        bData = np.random.random_sample((2, 2))
        a = DiagonalTensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aData)
        b = Tensor(shape = (2, 2), labels = ['b1', 'b2'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a3', 'b2', a, b)
        res1 = a @ b

        a = Tensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aTensorData)
        b = Tensor(shape = (2, 2), labels = ['b1', 'b2'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a3', 'b2', a, b)
        res2 = b @ a

        self.assertTrue(funcs.compareLists(list(res1.labels), ['a2']))
        self.assertTrue(funcs.compareLists(list(res2.labels), ['a2']))
        # self.assertListEqual(list(res1.a), list(res2.a))
        self.assertTrue(funcs.floatArrayEqual(res1.a, res2.a))

        aData = np.random.random_sample(2)
        aTensorData = np.array([[aData[0], 0], [0, aData[1]]])
        bData = np.random.random_sample((2, 2))
        a = DiagonalTensor(shape = (2, 2), labels = ['a1', 'a2'], data = aData)
        b = Tensor(shape = (2, 2), labels = ['b1', 'b2'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a2', 'b2', a, b)
        res1 = a @ b

        a = Tensor(shape = (2, 2), labels = ['a1', 'a2'], data = aTensorData)
        b = Tensor(shape = (2, 2), labels = ['b1', 'b2'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a2', 'b2', a, b)
        res2 = b @ a

        self.assertTrue(funcs.compareLists(res1.labels, []))
        self.assertTrue(funcs.compareLists(res2.labels, []))
        # self.assertListEqual(list(res1.single(), list(res2.a))
        self.assertTrue(funcs.floatEqual(res1.single(), res2.single()))

        aData = np.random.random_sample(2)
        aTensorData = np.array([[[aData[0], 0], [0, 0]], [[0, 0], [0, aData[1]]]])
        bData = np.random.random_sample((2, 2, 2))
        a = DiagonalTensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aData)
        b = Tensor(shape = (2, 2, 2), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a3', 'b2', a, b)
        res1 = a @ b

        a = Tensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aTensorData)
        b = Tensor(shape = (2, 2, 2), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        makeLink('a3', 'b2', a, b)
        res2 = b @ a

        self.assertTrue(funcs.compareLists(list(res1.labels), ['a2', 'b3']))
        self.assertTrue(funcs.compareLists(list(res2.labels), ['a2', 'b3']))
        # print(res1.labels, res2.labels)
        # print(res1.a, res2.a)
        res2.reArrange(res1.labels)
        self.assertTrue(funcs.floatArrayEqual(res1.a, res2.a))
        # self.assertListEqual(list(np.ravel(res1.a)), list(np.ravel(res2.a)))

        aData = np.random.random_sample(2)
        aTensorData = np.array([[[aData[0], 0], [0, 0]], [[0, 0], [0, aData[1]]]])
        bData = np.random.random_sample((2, 2, 2))
        a = DiagonalTensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aData)
        b = Tensor(shape = (2, 2, 2), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        # makeLink('a3', 'b2', a, b)
        res1 = a @ b

        a = Tensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aTensorData)
        b = Tensor(shape = (2, 2, 2), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        # makeLink('a3', 'b2', a, b)
        res2 = b @ a

        # print('ndEye(2, 2) = {}'.format(funcs.ndEye(2, 2)))
        # print('ndEye(1, 2) = {}'.format(funcs.ndEye(1, 2)))
        # print('ndEye(3, 2) = {}'.format(funcs.ndEye(3, 2)))

        self.assertTrue(funcs.compareLists(list(res1.labels), ['a2', 'a3', 'b2', 'b3']))
        self.assertTrue(funcs.compareLists(list(res2.labels), ['a2', 'a3', 'b2', 'b3']))
        # print(res1.labels, res2.labels)
        res2.reArrange(res1.labels)
        # print('res1 = {}, res2 = {}'.format(res1.a, res2.a))
        self.assertTrue(funcs.floatArrayEqual(res1.a, res2.a))
        # self.assertListEqual(list(np.ravel(res1.a)), list(np.ravel(res2.a)))

        aData = np.random.random_sample(2)
        aTensorData = np.array([[[aData[0], 0], [0, 0]], [[0, 0], [0, aData[1]]]])
        bData = np.random.random_sample((2, 4, 7))
        a = DiagonalTensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aData)
        b = Tensor(shape = (2, 4, 7), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        # makeLink('a3', 'b2', a, b)
        res1 = a @ b

        a = Tensor(shape = (2, 2, 2), labels = ['a1', 'a2', 'a3'], data = aTensorData)
        b = Tensor(shape = (2, 4, 7), labels = ['b1', 'b2', 'b3'], data = bData)
        makeLink('a1', 'b1', a, b)
        # makeLink('a3', 'b2', a, b)
        res2 = b @ a

        # print('ndEye(2, 2) = {}'.format(funcs.ndEye(2, 2)))
        # print('ndEye(1, 2) = {}'.format(funcs.ndEye(1, 2)))
        # print('ndEye(3, 2) = {}'.format(funcs.ndEye(3, 2)))

        self.assertTrue(funcs.compareLists(list(res1.labels), ['a2', 'a3', 'b2', 'b3']))
        self.assertTrue(funcs.compareLists(list(res2.labels), ['a2', 'a3', 'b2', 'b3']))
        # print(res1.labels, res2.labels)
        res2.reArrange(res1.labels)
        # print('res1 = {}, res2 = {}'.format(res1.a, res2.a))
        self.assertTrue(funcs.floatArrayEqual(res1.a, res2.a))

        self.showTestCaseEnd("diagonal tensor extreme contraction")
示例#22
0
    def createSpecialTN(self):
        a = Tensor(shape=(3, 5, 7), labels=['a3', 'a5', 'a7'])
        b = Tensor(shape=(2, 4, 5), labels=['b2', 'b4', 'b5'])
        c = Tensor(shape=(2, 7, 7, 7), labels=['c2', 'c71', 'c72', 'c73'])
        d = Tensor(shape=(7, 7, 3, 4), labels=['d71', 'd72', 'd3', 'd4'])
        makeLink('a3', 'd3', a, d)
        makeLink('a5', 'b5', a, b)
        makeLink('a7', 'c72', a, c)
        makeLink('b2', 'c2', b, c)
        makeLink('b4', 'd4', b, d)
        makeLink('c71', 'd72', c, d)
        makeLink('c73', 'd71', c, d)

        return [a, b, d, c]
示例#23
0
    def createSpecialTN2(self):
        a = Tensor(shape=(3, 5, 7), labels=['a3', 'a5', 'a7'])
        b = Tensor(shape=(2, 4, 5), labels=['b2', 'b4', 'b5'])
        c = Tensor(shape=(2, 7, 7, 7), labels=['c2', 'c71', 'c72', 'c73'])
        d = Tensor(shape=(7, 7, 3, 4), labels=['d71', 'd72', 'd3', 'd4'])
        e = Tensor(shape=(3, 3, 5), labels=['e31', 'e32', 'e5'])
        f = Tensor(shape=(2, 2, 5), labels=['f21', 'f22', 'f5'])
        g = Tensor(shape=(4, 4, 3, 3), labels=['g41', 'g42', 'g31', 'g32'])
        makeLink('a3', 'e31', a, e)
        makeLink('a5', 'b5', a, b)
        makeLink('a7', 'c72', a, c)

        makeLink('b2', 'f21', b, f)
        makeLink('b4', 'g41', b, g)

        makeLink('c2', 'f22', c, f)
        makeLink('c71', 'd72', c, d)
        makeLink('c73', 'd71', c, d)

        makeLink('d3', 'g31', d, g)
        makeLink('d4', 'g42', d, g)

        makeLink('e5', 'f5', e, f)
        makeLink('e32', 'g32', e, g)

        return [a, b, d, c, g, f, e]
示例#24
0
def createMPSFromTensor(tensor, chi=16):
    '''
    tensor is a real Tensor with n outer legs
    transfer it into an MPS with Schimdt decomposition
    after this, we can manage the tensor network decomposition by MPS network decomposition
    finally consider if tensor is only a TensorLike object
    '''

    # TODO: make this function work for tensorLike

    funcName = 'CTL.examples.MPS.createMPSFromTensor'

    legs = [leg for leg in tensor.legs]
    # xp = tensor.xp

    n = len(legs)
    assert (n > 0), funcs.errorMessage(
        "cannot create MPS from 0-D tensor {}.".format(tensor),
        location=funcName)

    if (n == 1):
        warnings.warn(
            funcs.warningMessage(
                "creating MPS for 1-D tensor {}.".format(tensor),
                location=funcName), RuntimeWarning)
        return FreeBoundaryMPS([tensor], chi=chi)

    a = xplib.xp.ravel(tensor.toTensor(labels=None))

    lastDim = -1
    tensors = []
    lastRightLeg = None
    for i in range(n - 1):
        u, v = matrixSchimdtDecomposition(a, dim=legs[i].dim, chi=chi)
        leg = legs[i]
        if (i == 0):
            dim1 = u.shape[1]
            rightLeg = Leg(None, dim=dim1, name='r')
            tensor = Tensor(shape=(leg.dim, u.shape[1]),
                            legs=[leg, rightLeg],
                            data=u)
            lastRightLeg = rightLeg
            lastDim = dim1
        else:
            dim1 = u.shape[-1]
            leftLeg = Leg(None, dim=lastDim, name='l')
            rightLeg = Leg(None, dim=dim1, name='r')
            tensor = Tensor(shape=(lastDim, leg.dim, u.shape[-1]),
                            legs=[leftLeg, leg, rightLeg],
                            data=u)

            makeLink(leftLeg, lastRightLeg)

            lastRightLeg = rightLeg
            lastDim = dim1

        tensors.append(tensor)
        a = v

    leftLeg = Leg(None, dim=lastDim, name='l')
    tensor = Tensor(shape=(lastDim, legs[-1].dim),
                    legs=[leftLeg, legs[-1]],
                    data=a)
    makeLink(leftLeg, lastRightLeg)
    tensors.append(tensor)

    # print(tensors)

    return FreeBoundaryMPS(tensorList=tensors, chi=chi)
示例#25
0
 def copyOfTensors(self):
     tensors = [self.getTensor(i).copy() for i in range(self.n)]
     for i in range(self.n - 1):
         makeLink('r', 'l', tensors[i], tensors[i + 1])
     return tensors
示例#26
0
def makeRandomMPS(n, virtualDim, physicalDim, chi=-1):
    '''
    Create an MPS consisting of n tensors, each has one physical leg.

    Parameters
    ----------
    n : int
        Number of tensors(physical legs) in MPS.
    virtualDim : int
        Bond dimension of bonds between tensors.
    physicalDim : int
        Bond dimension for physical legs.
    chi : int, optional
        The chi for MPS. If -1, then decided according to virtualDim.

    Returns
    -------
    mps : FreeBoundaryMPS
        MPS of n tensors.
    '''

    location = 'CTL.examples.MPS.makeRandomMPS'
    assert (n > 1), funcs.errorMessage(
        err=
        'cannot make random MPS whose number of tensors is not greater than 1, got {}'
        .format(n),
        location=location)

    tensors = []

    if isinstance(virtualDim, int):
        virtualDim = [virtualDim] * (n - 1)
    else:
        assert len(virtualDim) == n - 1, funcs.errorMessage(
            err='virtual dim must be int or length-(n - 1) list, {} found.'.
            format(virtualDim),
            location=location)

    if isinstance(physicalDim, int):
        physicalDim = [physicalDim] * n
    else:
        assert len(physicalDim) == n, funcs.errorMessage(
            err='physical dim must be int or length-n list, {} found.'.format(
                physicalDim),
            location=location)

    if chi == -1:
        chi = virtualDim[0]

    # endsShape = (physicalDim, virtualDim)
    endsLabels = ['p', 'v']
    # middleShape = (physicalDim, virtualDim, virtualDim)
    middleLabels = ['p', 'vl', 'vr']

    leftEndShape = (physicalDim[0], virtualDim[0])
    tensors.append(Tensor(shape=leftEndShape, labels=endsLabels))
    for i in range(n - 2):
        middleShape = (physicalDim[i + 1], virtualDim[i], virtualDim[i + 1])
        tensors.append(Tensor(shape=middleShape, labels=middleLabels))

    rightEndShape = (physicalDim[-1], virtualDim[-1])
    tensors.append(Tensor(shape=rightEndShape, labels=endsLabels))
    for tensor in tensors:
        tensor.a /= tensor.norm()

    if (n == 2):
        makeLink('v', 'v', tensors[0], tensors[-1])
    else:
        makeLink('v', 'vl', tensors[0], tensors[1])
        makeLink('v', 'vr', tensors[-1], tensors[-2])
        for i in range(1, n - 2):
            makeLink('vr', 'vl', tensors[i], tensors[i + 1])
    return FreeBoundaryMPS(tensors, chi=chi, inplace=True)
示例#27
0
def contractHandmadeTN():
    print('contractHandmadeTN():')
    a = Tensor(shape=(3, 5, 7), labels=['a3', 'a5', 'a7'])
    b = Tensor(shape=(2, 4, 5), labels=['b2', 'b4', 'b5'])
    c = Tensor(shape=(2, 7, 7, 7), labels=['c2', 'c71', 'c72', 'c73'])
    d = Tensor(shape=(7, 7, 3, 4), labels=['d71', 'd72', 'd3', 'd4'])
    e = Tensor(shape=(3, 3, 5), labels=['e31', 'e32', 'e5'])
    f = Tensor(shape=(2, 2, 5), labels=['f21', 'f22', 'f5'])
    g = Tensor(shape=(4, 4, 3, 3), labels=['g41', 'g42', 'g31', 'g32'])
    makeLink('a3', 'e31', a, e)
    makeLink('a5', 'b5', a, b)
    makeLink('a7', 'c72', a, c)

    makeLink('b2', 'f21', b, f)
    makeLink('b4', 'g41', b, g)

    makeLink('c2', 'f22', c, f)
    makeLink('c71', 'd72', c, d)
    makeLink('c73', 'd71', c, d)

    makeLink('d3', 'g31', d, g)
    makeLink('d4', 'g42', d, g)

    makeLink('e5', 'f5', e, f)
    makeLink('e32', 'g32', e, g)

    tensors = [a, b, d, c, g, f, e]

    res, _ = contractAndCostWithSequence(tensors)
    print('res from direct contraction = {}'.format(res.single()))

    mpsRes = contractWithMPS(tensors, chi=32)
    print('res from mps = {}'.format(mpsRes.single()))
    print('')
示例#28
0
def merge(ta, tb, chi=None, bondName=None, renameWarning=True):
    """
    Merge the shared bonds of two tensors. If not connected, make a warning and do nothing.

    Parameters
    ----------
    ta, tb : Tensor
    
    chi : int, optional
        The upper-bound of the bond dimension of the bond after merged. If None, then no truncation.
    bondName : str, optional
        The name of bond after merging. If None, then for a list of [name1, name2, ... nameN], the name will be "{name1}|{name2}| .... |{nameN}".
    renameWarning : bool, default True
        If only one bond is shared, then the two

    Returns
    -------
    ta, tb : Tensor
        The two tensors after merging all the common bonds to one bond.

    """
    funcName = "CTL.tensor.contract.contract.truncate"

    # assert (ta.xp == tb.xp), funcs.errorMessage("Truncation cannot accept two tensors with different xp: {} and {} gotten.".format(ta.xp, tb.xp), location = funcName)

    assert (ta.tensorLikeFlag == tb.tensorLikeFlag), funcs.errorMessage(
        'two tensors to be merged must be either Tensor or TensorLike simultaneously, {} and {} obtained.'
        .format(ta, tb),
        location=funcName)

    tensorLikeFlag = ta.tensorLikeFlag

    # xp = ta.xp
    ta, tb = mergeLink(ta, tb, bondName=bondName, renameWarning=renameWarning)
    if (chi is None):
        # no need for truncation
        return ta, tb

    sb = shareBonds(ta, tb)
    # assert (len(sb) > 0), funcs.errorMessage("Truncation cannot work on two tensors without common bonds: {} and {} gotten.".format(ta, tb), location = funcName)

    # if (bondName is None):
    # 	bondNameListA = [bond.sideLeg(ta).name for bond in sb]
    # 	bondNameListB = [bond.sideLeg(tb).name for bond in sb]
    # 	bondNameA = '|'.join(bondNameListA)
    # 	bondNameB = '|'.join(bondNameListB)
    # elif (isinstance(bondName, str)):
    # 	bondNameA = bondName
    # 	bondNameB = bondName
    # else:
    # 	bondNameA, bondNameB = bondName # tuple/list

    # if (renameFlag):
    if (len(sb) == 0):
        if (renameWarning):
            warnings.warn(
                funcs.warningMessage(
                    warn=
                    'mergeLink cannot merge links between two tensors {} and {} not sharing any bond'
                    .format(ta, tb),
                    location=funcName), RuntimeWarning)
        return ta, tb

    assert (len(sb) == 1), funcs.errorMessage(
        "There should only be one common leg between ta and tb after mergeLink, {} obtained."
        .format(sb),
        location=funcName)

    legA = [bond.sideLeg(ta) for bond in sb]
    legB = [bond.sideLeg(tb) for bond in sb]

    bondNameA = legA[0].name
    bondNameB = legB[0].name

    remainLegA = ta.complementLegs(legA)
    remainLegB = tb.complementLegs(legB)

    if (not tensorLikeFlag):

        matA = ta.toMatrix(rows=None, cols=legA)
        matB = tb.toMatrix(rows=legB, cols=None)

        mat = matA @ matB

        u, s, vh = xplib.xp.linalg.svd(mat)

        chi = min(
            [chi, funcs.nonZeroElementN(s), matA.shape[0], matB.shape[1]])
        u = u[:, :chi]
        s = s[:chi]
        vh = vh[:chi]

        uOutLeg = Leg(tensor=None, dim=chi, name=bondNameA)
        vOutLeg = Leg(tensor=None, dim=chi, name=bondNameB)
        # print(legA, legB)

        sqrtS = xplib.xp.sqrt(s)
        uS = funcs.rightDiagonalProduct(u, sqrtS)
        vS = funcs.leftDiagonalProduct(vh, sqrtS)

        uTensor = Tensor(data=uS, legs=remainLegA + [uOutLeg])
        vTensor = Tensor(data=vS, legs=[vOutLeg] + remainLegB)

    else:
        chi = min([
            chi, legA[0].dim, ta.totalSize // legA[0].dim,
            tb.totalSize // legB[0].dim
        ])
        uOutLeg = Leg(tensor=None, dim=chi, name=bondNameA)
        vOutLeg = Leg(tensor=None, dim=chi, name=bondNameB)
        uTensor = Tensor(tensorLikeFlag=True, legs=remainLegA + [uOutLeg])
        vTensor = Tensor(tensorLikeFlag=True, legs=[vOutLeg] + remainLegB)

    makeLink(uOutLeg, vOutLeg)
    return uTensor, vTensor
示例#29
0
def SchimdtDecomposition(ta,
                         tb,
                         chi,
                         squareRootSeparation=False,
                         swapLabels=([], []),
                         singularValueEps=1e-10):
    '''
    Schimdt decomposition between tensor ta and tb
    return ta, s, tb
    ta should be in canonical form, that is, a a^dagger = I
    to do this, first contract ta and tb, while keeping track of legs from a and legs from b
    then SVD over the matrix, take the required chi singular values
    take first chi eigenvectors for a and b, create a diagonal tensor for singular value tensor

    if squareRootSeparation is True: then divide s into two square root diagonal tensors
    and contract each into ta and tb, return ta, None, tb

    if swapLabels is not ([], []): swap the two set of labels for output, so we swapped the locations of two tensors on MPS
    e.g. t[i], t[i + 1] = SchimdtDecomposition(t[i], t[i + 1], chi = chi, squareRootSeparation = True, swapLabels = (['o'], ['o']))
    we can swap the two tensors t[i] & t[i + 1], both have an "o" leg connected to outside
    while other legs(e.g. internal legs in MPS, usually 'l' and 'r') will not be affected
    '''

    funcName = 'CTL.examples.Schimdt.SchimdtDecomposition'
    sb = shareBonds(ta, tb)
    assert (len(sb) > 0), funcs.errorMessage(
        "Schimdt Decomposition cannot accept two tensors without common bonds, {} and {} gotten."
        .format(ta, tb),
        location=funcName)
    assert (ta.tensorLikeFlag == tb.tensorLikeFlag), funcs.errorMessage(
        "Schimdt Decomposition must havge two objects being either Tensor or TensorLike simultaneously, but {} and {} obtained."
        .format(ta, tb),
        location=funcName)

    TLFlag = ta.tensorLikeFlag
    sbDim = funcs.tupleProduct(tuple([bond.legs[0].dim for bond in sb]))

    sharedLabelA = sb[0].sideLeg(ta).name
    sharedLabelB = sb[0].sideLeg(tb).name
    # if (sharedLabelA.startswith('a-')):
    #     raise ValueError(funcs.errorMessage(err = "shared label {} of tensor A starts with 'a-'.".format(sharedLabelA), location = funcName))
    # if (sharedLabelB.startswith('b-')):
    #     raise ValueError(funcs.errorMessage(err = "shared label {} of tensor B starts with 'b-'.".format(sharedLabelB), location = funcName))

    # assert (ta.xp == tb.xp), funcs.errorMessage("Schimdt Decomposition cannot accept two tensors with different xp: {} and {} gotten.".format(ta.xp, tb.xp), location = funcName)

    assert (len(swapLabels[0]) == len(swapLabels[1])), funcs.errorMessage(
        err="invalid swap labels {}.".format(swapLabels), location=funcName)
    assert ta.labelsInTensor(swapLabels[0]), funcs.errorMessage(
        err="{} not in tensor {}.".format(swapLabels[0], ta),
        location=funcName)
    assert tb.labelsInTensor(swapLabels[1]), funcs.errorMessage(
        err="{} not in tensor {}.".format(swapLabels[1], tb),
        location=funcName)

    ta.addTensorTag('a')
    tb.addTensorTag('b')
    for swapLabel in swapLabels[0]:
        ta.renameLabel('a-' + swapLabel, 'b-' + swapLabel)
    for swapLabel in swapLabels[1]:
        tb.renameLabel('b-' + swapLabel, 'a-' + swapLabel)

    tot = contractTwoTensors(ta, tb)

    legA = [leg for leg in tot.legs if leg.name.startswith('a-')]
    legB = [leg for leg in tot.legs if leg.name.startswith('b-')]

    labelA = [leg.name for leg in legA]
    labelB = [leg.name for leg in legB]
    # not remove a- and b- here, since we need to add an internal leg, and we need to distinguish it from others

    shapeA = tuple([leg.dim for leg in legA])
    shapeB = tuple([leg.dim for leg in legB])

    totShapeA = funcs.tupleProduct(shapeA)
    totShapeB = funcs.tupleProduct(shapeB)

    if (TLFlag):
        u = None
        vh = None
        s = None
        chi = min([chi, totShapeA, totShapeB, sbDim])
    else:
        mat = tot.toMatrix(rows=labelA, cols=labelB)

        # np = ta.xp # default numpy

        u, s, vh = xplib.xp.linalg.svd(mat)

        chi = min([
            chi, totShapeA, totShapeB,
            funcs.nonZeroElementN(s, singularValueEps)
        ])
        u = u[:, :chi]
        s = s[:chi]
        vh = vh[:chi]

    if (squareRootSeparation):
        if (TLFlag):
            uS = None
            vS = None
        else:
            sqrtS = xplib.xp.sqrt(s)
            uS = funcs.rightDiagonalProduct(u, sqrtS)
            vS = funcs.leftDiagonalProduct(vh, sqrtS)

        outLegForU = Leg(None, chi, name=sharedLabelA)
        # inLegForU = Leg(None, chi, name = sharedLabelB)
        # internalLegForS1 = Leg(None, chi, name = 'o')
        # internalLegForS2 = Leg(None, chi, name = 'o')
        # inLegForV = Leg(None, chi, name = sharedLabelA)
        outLegForV = Leg(None, chi, name=sharedLabelB)

        uTensor = Tensor(data=uS,
                         legs=legA + [outLegForU],
                         shape=shapeA + (chi, ),
                         tensorLikeFlag=TLFlag)
        # s1Tensor = DiagonalTensor(data = xplib.xp.sqrt(s), legs = [inLegForU, internalLegForS1], shape = (chi, chi))
        # s2Tensor = DiagonalTensor(data = xplib.xp.sqrt(s), legs = [internalLegForS2, inLegForV], shape = (chi, chi))
        vTensor = Tensor(data=vS,
                         legs=[outLegForV] + legB,
                         shape=(chi, ) + shapeB,
                         tensorLikeFlag=TLFlag)

        # legs should be automatically set by Tensor / DiagonalTensor, so no need for setTensor

        # outLegForU.setTensor(uTensor)
        # outLegForV.setTensor(vTensor)

        # inLegForU.setTensor(sTensor)
        # inLegForV.setTensor(sTensor)

        # remove a- and b-
        for leg in legA:
            if (leg.name.startswith('a-')):
                leg.name = leg.name[2:]

        for leg in legB:
            if (leg.name.startswith('b-')):
                leg.name = leg.name[2:]

        makeLink(outLegForU, outLegForV)

        # makeLink(outLegForU, inLegForU)
        # makeLink(outLegForV, inLegForV)
        # makeLink(internalLegForS1, internalLegForS2)
        # uTensor = contractTwoTensors(uTensor, s1Tensor)
        # vTensor = contractTwoTensors(vTensor, s2Tensor)
        return uTensor, None, vTensor

    outLegForU = Leg(None, chi, name=sharedLabelA)
    inLegForU = Leg(None, chi, name=sharedLabelB)
    inLegForV = Leg(None, chi, name=sharedLabelA)
    outLegForV = Leg(None, chi, name=sharedLabelB)

    uTensor = Tensor(data=u,
                     legs=legA + [outLegForU],
                     shape=shapeA + (chi, ),
                     tensorLikeFlag=TLFlag)
    sTensor = DiagonalTensor(data=s,
                             legs=[inLegForU, inLegForV],
                             shape=(chi, chi),
                             tensorLikeFlag=TLFlag)
    vTensor = Tensor(data=vh,
                     legs=[outLegForV] + legB,
                     shape=(chi, ) + shapeB,
                     tensorLikeFlag=TLFlag)

    # legs should be automatically set by Tensor / DiagonalTensor, so no need for setTensor

    # outLegForU.setTensor(uTensor)
    # outLegForV.setTensor(vTensor)

    # inLegForU.setTensor(sTensor)
    # inLegForV.setTensor(sTensor)

    # remove a- and b-
    for leg in legA:
        if (leg.name.startswith('a-')):
            leg.name = leg.name[2:]

    for leg in legB:
        if (leg.name.startswith('b-')):
            leg.name = leg.name[2:]

    makeLink(outLegForU, inLegForU)
    makeLink(outLegForV, inLegForV)

    return uTensor, sTensor, vTensor