Ejemplo n.º 1
0
    def test_FreeBondFTN(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=['e4', 'd6', 'c5'],
                   data=np.ones(shapeC))

        tensorDict = TensorDict()
        tensorDict.setTensor('a', a)
        tensorDict.setTensor('b', b)
        tensorDict.setTensor('c', c)

        FTN = FiniteTensorNetwork(['a', 'b'], realCost=True)
        FTN.addTensor('c')

        FTN.addLink('a', 'a300', 'b', 'a300')
        FTN.addLink('a', 'c5', 'c', 'c5')
        FTN.addLink('b', 'd6', 'c', 'd6')

        result = FTN.contract(tensorDict, removeTensorTag=False)
        self.assertTrue(funcs.compareLists(result.labels, ['a-b4', 'c-e4']))
        self.assertEqual(int(result.a[0][1]), 9000)

        result = FTN.contract(tensorDict, removeTensorTag=True)
        self.assertTrue(funcs.compareLists(result.labels, ['b4', 'e4']))
        self.assertEqual(int(result.a[0][1]), 9000)

        FTN.unlock()
        FTN.addPostNameChange('c', 'e4', 'e4FromC')
        FTN.addPreNameChange('a', 'b4', 'b4FromA')
        FTN.addPreNameChange('a', 'a300', 'a3')
        FTN.removePreNameChange('a', 'a300', 'a3')
        FTN.addPostNameChange('a', 'd6', 'foo')
        FTN.removePostNameChange('a', 'd6', 'foo')

        result = FTN.contract(tensorDict, removeTensorTag=True)
        # print(result.labels)
        self.assertTrue(
            funcs.compareLists(result.labels, ['b4FromA', 'e4FromC']))
        self.assertEqual(int(result.a[0][1]), 9000)

        FTN.unlock()
        FTN.removePostNameChange('c', 'e4', 'e4FromC')
        FTN.addPreNameChange('c', 'e4', 'e4FromC')
        FTN.addPostOutProduct([('a', 'b4FromA'), ('c', 'e4FromC')], 'out')
        result = FTN.contract(tensorDict, removeTensorTag=True)

        self.assertListEqual(result.labels, ['out'])
        self.assertEqual(result.shape[0], 16)
Ejemplo n.º 2
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
Ejemplo n.º 3
0
    def test_triangleContractFTN(self):
        FTN = triangleContractFTN()
        a = makeTriangleTensor(np.ones((3, 3, 3)))
        tensorDict = TensorDict({'u': a, 'l': a, 'r': a})

        res = FTN.contract(tensorDict)
        self.assertTrue(funcs.compareLists(res.labels, ['1', '2', '3']))
        res.reArrange(['1', '2', '3'])
        self.assertTupleEqual(res.shape, (3, 3, 3))
        self.assertTrue(FTN.locked)
Ejemplo n.º 4
0
    def test_squareContractFTN(self):

        FTN = squareContractFTN()
        a = makeSquareTensor(np.ones((3, 4, 3, 4)))
        tensorDict = TensorDict({'ul': a, 'ur': a, 'dl': a, 'dr': a})

        res = FTN.contract(tensorDict)
        # print(res.labels
        self.assertTrue(funcs.compareLists(res.labels, ['u', 'l', 'd', 'r']))

        res.reArrange(['u', 'l', 'd', 'r'])
        self.assertTupleEqual(res.shape, (9, 16, 9, 16))
Ejemplo n.º 5
0
Archivo: CTMRG.py Proyecto: CaoRX/CTL
    def __init__(self, a, chi=16):
        self.a = a.copy()
        self.chi = chi

        assert funcs.compareLists(a.labels, [
            'l', 'r', 'u', 'd'
        ]), funcs.errorMessage(
            'CTMRG can only accept tensor with legs ["l", "r", "u", "d"], {} obtained.'
            .format(a))

        self.setRecords()
        self.setFTNs()
        self.setInitialTensors()
Ejemplo n.º 6
0
Archivo: tensor.py Proyecto: CaoRX/CTL
    def toMatrix(self, rows=None, cols=None):
        """
        Make a matrix of the data of this tensor, given the labels or legs of rows and cols.

        Parameters
        ----------
        rows : None or list of str or list of Leg
            The legs for the rows of the matrix. If None, deducted from cols.
        cols : None or list of str or list of Leg
            The legs for the cols of the matrix. If None, deducted from rows.

        Returns
        -------
        2D ndarray of float
            The data of this tensor, in the form of (rows, cols).
        """
        # print(rows, cols)
        # print(self.labels)
        # input two set of legs
        assert (not self.tensorLikeFlag), funcs.errorMessage(
            'TensorLike cannot be transferred to matrix since no data contained.',
            'Tensor.toMatrix')
        assert not (
            (rows is None) and (cols is None)
        ), "Error in Tensor.toMatrix: toMatrix must have at least row or col exist."
        if (rows is not None) and (isinstance(rows[0], str)):
            rows = [self.getLeg(label) for label in rows]
        if (cols is not None) and (isinstance(cols[0], str)):
            cols = [self.getLeg(label) for label in cols]
        if (cols is None):
            cols = funcs.listDifference(self.legs, rows)
        if (rows is None):
            rows = funcs.listDifference(self.legs, cols)
        assert (
            funcs.compareLists(rows + cols, self.legs)
        ), "Error Tensor.toMatrix: rows + cols must contain(and only contain) all legs of tensor."

        colIndices = self.getLegIndices(cols)
        rowIndices = self.getLegIndices(rows)

        colShape = tuple([self.shape[x] for x in colIndices])
        rowShape = tuple([self.shape[x] for x in rowIndices])
        colTotalSize = funcs.tupleProduct(colShape)
        rowTotalSize = funcs.tupleProduct(rowShape)

        moveFrom = rowIndices + colIndices
        moveTo = list(range(len(moveFrom)))

        data = xplib.xp.moveaxis(xplib.xp.copy(self.a), moveFrom, moveTo)
        data = xplib.xp.reshape(data, (rowTotalSize, colTotalSize))
        return data
Ejemplo n.º 7
0
Archivo: tensor.py Proyecto: CaoRX/CTL
    def reArrange(self, labels):
        """
        Rearrange the legs to a given order according to labels.

        Parameters
        ----------
        labels : list of str
            The order of labels after rearranging.
        """
        assert (
            funcs.compareLists(self.labels, labels)
        ), "Error: tensor labels must be the same with original labels: get {} but {} needed".format(
            len(labels), len(self.labels))
        self.moveLabelsToFront(labels)
Ejemplo n.º 8
0
    def test_squareContractOutFTN(self):
        FTN = squareContractOutFTN()

        tensorNames = ['ul', 'ur', 'dl', 'dr']
        tensorDict = TensorDict()
        # print('keys = {}'.format(tensorDict.tensors.keys()))
        for tensorName in tensorNames:
            tensorDict.setTensor(
                tensorName,
                makeSquareOutTensor(np.ones((3, 4, 6)), loc=tensorName))
        # print('keys = {}'.format(tensorDict.tensors.keys()))

        res = FTN.contract(tensorDict)
        self.assertTrue(funcs.compareLists(res.labels, ['u', 'd', 'l', 'r']))
        self.assertTupleEqual(res.shape, (6, 6, 6, 6))
        self.assertEqual(int(res.a[(0, 0, 0, 0)]), 144)
Ejemplo n.º 9
0
    def toMatrix(self, rows, cols):
        """
        Deprecated

        Make a matrix of the data of this diagonal tensor, given the labels or legs of rows and cols. 

        Deprecated since this function is time comsuming(O(n^d)), and for most of the cases there are much better ways to use the data rather than making a matrix. For details, see CTL.tensor.contract for more information.

        Parameters
        ----------
        rows : None or list of str or list of Leg
            The legs for the rows of the matrix. If None, deducted from cols.
        cols : None or list of str or list of Leg
            The legs for the cols of the matrix. If None, deducted from rows.

        Returns
        -------
        2D ndarray of float
            The data of this tensor, in the form of (rows, cols).
        """
        assert (not self.tensorLikeFlag), funcs.errorMessage('DiagonalTensorLike cannot be transferred to matrix since no data contained.', 'DiagonalTensor.toMatrix')
        # print(rows, cols)
        # print(self.labels)
        # input two set of legs
        funcs.deprecatedFuncWarning(funcName = "DiagonalTensor.toMatrix", deprecateMessage = "Diagonal tensors should be used in a better way for linear algebra calculation rather than be made into a matrix.")
        assert not ((rows is None) and (cols is None)), "Error in Tensor.toMatrix: toMatrix must have at least row or col exist."
        if (rows is not None) and (isinstance(rows[0], str)):
            rows = [self.getLeg(label) for label in rows]
        if (cols is not None) and (isinstance(cols[0], str)):
            cols = [self.getLeg(label) for label in cols]
        if (cols is None):
            cols = funcs.listDifference(self.legs, rows)
        if (rows is None):
            rows = funcs.listDifference(self.legs, cols)
        assert (funcs.compareLists(rows + cols, self.legs)), "Error Tensor.toMatrix: rows + cols must contain(and only contain) all legs of tensor."

        colIndices = self.getLegIndices(cols)
        rowIndices = self.getLegIndices(rows)

        colShape = tuple([self.shape[x] for x in colIndices])
        rowShape = tuple([self.shape[x] for x in rowIndices])
        colTotalSize = funcs.tupleProduct(colShape)
        rowTotalSize = funcs.tupleProduct(rowShape)

        data = funcs.diagonalNDTensor(self.a, self.dim)
        data = xplib.xp.reshape(data, (rowTotalSize, colTotalSize))
        return data
Ejemplo n.º 10
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))
Ejemplo n.º 11
0
 def test_Ising(self):
     betaJ = 1.0
     a = IsingSiteTensor(betaJ = betaJ, dim = 4, labels = ['u', 'd', 'l', 'r'])
     edgeMat = IsingEdgeMatrix(betaJ = betaJ)
     self.assertTrue(funcs.floatEqual(a.a[(0, 0, 0, 0)], edgeMat[0, 0] ** 4 + edgeMat[0, 1] ** 4))
     self.assertTrue(funcs.compareLists(['u', 'd', 'l', 'r'], a.labels))
Ejemplo n.º 12
0
 def test_diagonalSumOut(self):
     a = DiagonalTensor(shape = (3, 3, 3), labels = ['abc', 'def', 'abc'])
     a.sumOutLegByLabel(['abc', 'abc'])
     self.assertTrue(funcs.compareLists(a.labels, ['def']))
Ejemplo n.º 13
0
    def test_diagonalRename(self):

        a = DiagonalTensor(shape = (3, 3, 3), labels = ['abc', 'def', 'abc'])
        a.renameLabels(['abc', 'abc'], ['abc1', 'abc2'])
        self.assertTrue(funcs.compareLists(a.labels, ['abc1', 'abc2', 'def']))
Ejemplo n.º 14
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")
Ejemplo n.º 15
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")
Ejemplo n.º 16
0
    def test_deduce(self):

        self.showTestCaseBegin("diagonal tensor shape deduction")

        legA = Leg(tensor = None, dim = 5, name = 'a')
        legB = Leg(tensor = None, dim = 5, name = 'b')
        legBError = Leg(tensor = None, dim = 6, name = 'b')

        a = DiagonalTensor(legs = [legA, legB])
        self.assertTupleEqual(a.shape, (5, 5))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(funcs.floatArrayEqual(a.a, np.ones(5)))

        a = DiagonalTensor(legs = [legA, legB], labels = ['a', 'b'])
        self.assertTupleEqual(a.shape, (5, 5))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(funcs.floatArrayEqual(a.a, np.ones(5)))

        a = DiagonalTensor(legs = [legA, legB], shape = 5)
        self.assertTupleEqual(a.shape, (5, 5))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(funcs.floatArrayEqual(a.a, np.ones(5)))

        a = DiagonalTensor(legs = [legA, legB], shape = 5, data = np.zeros(5))
        self.assertTupleEqual(a.shape, (5, 5))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(funcs.floatArrayEqual(a.a, np.zeros(5)))

        def legDimNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legBError])

        def labelsSizeNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], labels = ['a'])
        def labelsOrderNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], labels = ['b', 'a'])

        def shapeSizeNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], shape = (5, 6, 7))
        def shapeOrderNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], shape = (6, 5))
        
        def dataDimNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], data = np.zeros((5, 6, 7)))
        def dataShapeNotEqualFunc():
            _ = DiagonalTensor(legs = [legA, legB], data = np.zeros((5, 6)))
        def labelsShapeNotCompatibleFunc():
            _ = DiagonalTensor(legs = [legA, legB], labels = ['a'], data = np.zeros((5, 5)))
        def dimensionless1DDataErrorFunc():
            _ = DiagonalTensor(legs = [], labels = [], data = np.zeros(3))
        def dimensionless1DDataErrorFunc2():
            _ = DiagonalTensor(labels = [], data = np.zeros(3))

        self.assertRaises(ValueError, legDimNotEqualFunc)
        self.assertRaises(ValueError, labelsSizeNotEqualFunc)
        self.assertRaises(ValueError, labelsOrderNotEqualFunc)
        self.assertRaises(ValueError, shapeSizeNotEqualFunc)
        self.assertRaises(ValueError, shapeOrderNotEqualFunc)
        self.assertRaises(ValueError, dataDimNotEqualFunc)
        self.assertRaises(ValueError, dataShapeNotEqualFunc)
        self.assertRaises(ValueError, labelsShapeNotCompatibleFunc)
        self.assertRaises(ValueError, dimensionless1DDataErrorFunc)
        self.assertRaises(ValueError, dimensionless1DDataErrorFunc2)

        a = DiagonalTensor(shape = (2, 2), labels = ['a1', 'a2'])
        self.assertTupleEqual(a.shape, (2, 2))
        self.assertEqual(a.dim, 2)

        a = DiagonalTensor(shape = (2, 2))
        self.assertTupleEqual(a.shape, (2, 2))
        self.assertEqual(a.dim, 2)
        self.assertTrue((a.a == np.ones(2)).all()) # default as identity tensor

        def shapeNotEqualFunc():
            _ = DiagonalTensor(shape = (2, 3))
        
        self.assertRaises(ValueError, shapeNotEqualFunc)

        def labelsShortFunc():
            _ = DiagonalTensor(shape = (2, 2), labels = ['a1'])
        def labelsLongFunc():
            _ = DiagonalTensor(shape = (2, 2), labels = ['a', 'b', 'c'])

        self.assertRaises(ValueError, labelsShortFunc)
        self.assertRaises(ValueError, labelsLongFunc)

        a = DiagonalTensor(shape = (2, 2), data = np.zeros((2, 2)))
        self.assertTupleEqual(a.shape, (2, 2))
        self.assertEqual(a.dim, 2)

        a = DiagonalTensor(shape = (2, 2, 2), data = np.zeros(2))
        self.assertTupleEqual(a.shape, (2, 2, 2))
        self.assertEqual(a.dim, 3)

        def dataDimErrorFunc():
            _ = DiagonalTensor(shape = (2, 2), data = np.zeros((2, 2, 2)))
        def dataShapeErrorFunc():
            _ = DiagonalTensor(shape = (2, 2), data = np.zeros((2, 3))) # no error in 9be9325, newly added

        self.assertRaises(ValueError, dataDimErrorFunc)
        self.assertRaises(ValueError, dataShapeErrorFunc)

        # now start (shape = None) tests

        a = DiagonalTensor(labels = ['a', 'b'], data = np.zeros(3))
        self.assertEqual(a._length, 3)
        self.assertEqual(a.shape, (3, 3))
        self.assertEqual(a.dim, 2)

        a = DiagonalTensor(labels = ['a', 'b'], data = np.zeros((4, 4)))
        self.assertEqual(a._length, 4)
        self.assertEqual(a.shape, (4, 4))
        self.assertEqual(a.dim, 2)

        a = DiagonalTensor(labels = ['a', 'b'], data = np.array([[1, 2], [3, 4]]))
        self.assertEqual(a._length, 2)
        self.assertEqual(a.shape, (2, 2))
        self.assertTrue((a.a == np.array([1, 4])).all())

        def dataDimErrorFunc2():
            _ = DiagonalTensor(labels = ['a', 'b', 'c'], data = np.zeros((2, 2)))
        
        def dataShapeErrorFunc2():
            _ = DiagonalTensor(labels = ['a', 'b', 'c'], data = np.zeros((2, 2, 3)))
        
        def dataNoneErrorFunc():
            _ = DiagonalTensor(labels = ['a', 'b', 'c'], data = None)
        
        self.assertRaises(ValueError, dataDimErrorFunc2)
        self.assertRaises(ValueError, dataShapeErrorFunc2)
        self.assertRaises(ValueError, dataNoneErrorFunc)

        # now start(shape = None, labels = None)
        
        a = DiagonalTensor(data = np.zeros(2)) # 1D diagonal tensor as a simple vector
        self.assertEqual(a.dim, 1)
        self.assertEqual(a._length, 2)
        self.assertListEqual(a.labels, ['a'])

        a = DiagonalTensor(data = np.array([[1, 2], [4, 3]]))
        self.assertEqual(a.dim, 2)
        self.assertEqual(a._length, 2)
        self.assertTrue((a.a == np.array([1, 3])).all())

        def dataShapeErrorFunc3():
            _ = DiagonalTensor(data = np.zeros((2, 2, 3)))
        
        def nothingErrorFunc():
            _ = DiagonalTensor()

        self.assertRaises(ValueError, dataShapeErrorFunc3)
        self.assertRaises(ValueError, nothingErrorFunc)

        self.showTestCaseEnd("diagonal tensor shape deduction")
Ejemplo n.º 17
0
    def test_TensorLike(self):
        # the deduction rules are just the same as Tensor
        # the only difference is that data is None, and tensorLikeFlag is True
        legA = Leg(tensor = None, dim = 5, name = 'a')
        legB = Leg(tensor = None, dim = 6, name = 'b')

        a = Tensor(legs = [legA, legB], tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(legs = [legA, legB], labels = ['a', 'b'], tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        def labelsSizeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], labels = ['a'], tensorLikeFlag = True)
        def labelsOrderNotEqualFunc():
            _ = Tensor(legs = [legA, legB], labels = ['b', 'a'], tensorLikeFlag = True)

        def shapeSizeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], shape = (5, 6, 7), tensorLikeFlag = True)
        def shapeOrderNotEqualFunc():
            _ = Tensor(legs = [legA, legB], shape = (6, 5), tensorLikeFlag = True)
        
        def dataDimNotEqualFunc():
            _ = Tensor(legs = [legA, legB], data = np.zeros((5, 6, 7)), tensorLikeFlag = True)
        def dataShapeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], data = np.zeros((5, 5)), tensorLikeFlag = True)

        self.assertRaises(ValueError, labelsSizeNotEqualFunc)
        self.assertRaises(ValueError, labelsOrderNotEqualFunc)
        self.assertRaises(ValueError, shapeSizeNotEqualFunc)
        self.assertRaises(ValueError, shapeOrderNotEqualFunc)
        self.assertRaises(ValueError, dataDimNotEqualFunc)
        self.assertRaises(ValueError, dataShapeNotEqualFunc)

        # for data, works if (data size) = (dim product), no matter what the shape of data

        a = Tensor(legs = [legA, legB], data = np.zeros((6, 5)), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(legs = [legA, legB], data = np.zeros((3, 2, 5)), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(legs = [legA, legB], data = np.zeros(30), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        # 2. legs not exist, shape exist
        # if data exist, check the total number of components of data equal to shape, otherwise random
        # if labels exist: check the number of labels equal to dimension, otherwise auto-generate

        a = Tensor(shape = (5, 3, 4), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b', 'c']))
        self.assertEqual(a.dim, 3)
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(shape = (5, 3, 4), data = np.zeros(60), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b', 'c']))
        self.assertEqual(a.dim, 3)
        # self.assertEqual(a.a[(0, 0, 0)], 0)
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(shape = (5, 3, 4), labels = ['c', 'b', 'a'], tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(shape = (5, 3, 4), labels = ('c', 'b', 'a'), tensorLikeFlag = True) # tuple also is acceptable
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        a = Tensor(shape = (5, 3, 4), labels = ['c', 'b', 'a'], data = np.zeros(60), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)

        def dataTotalSizeNotEqualErrorFunc():
            _ = Tensor(shape = (5, 3, 4), data = np.zeros((5, 3, 3)), tensorLikeFlag = True)
        def labelsSizeNotEqualFunc2():
            _ = Tensor(shape = (5, 3, 4), labels = ['a', 'b'])

        self.assertRaises(ValueError, dataTotalSizeNotEqualErrorFunc)
        self.assertRaises(ValueError, labelsSizeNotEqualFunc2)

        # 3. legs not exist, shape not exist
        # if data exist: generate shape according to data, and auto-generate legs

        a = Tensor(data = np.zeros((3, 4, 5)), tensorLikeFlag = True)
        self.assertTupleEqual(a.shape, (3, 4, 5))
        self.assertEqual(a.dim, 3)
        self.assertEqual(a.legs[0].dim, 3)
        self.assertEqual(a.legs[0].name, 'a')
        self.assertTrue(a.tensorLikeFlag)
        self.assertIsNone(a.a)
        self.assertTrue(a.__str__().find('TensorLike') != -1)
        self.assertTrue(a.__repr__().find('TensorLike') != -1)

        def nothingErrorFunc():
            _ = Tensor(tensorLikeFlag = True)

        self.assertRaises(ValueError, nothingErrorFunc)
Ejemplo n.º 18
0
    def test_TensorDeduction(self):
        # test the deduction of Tensor

        # deduce strategy:
        # we want shape, and labels
        # we have legs, shape, labels, data
        # priority for shape: legs > shape > data
        # priority for labels: legs > labels

        # 1. legs exist: 
        # if labels exist: check the length and content of labels with legs
        # if shape exist: check whether shape == tuple([leg.dim for leg in legs])
        # if data exist: check whehter data.shape == tuple([leg.dim for leg in legs]) (if not, but the total size equal, we transfer data to the given shape)
        
        # 3. legs not exist, shape not exist
        # if data exist: generate shape according to data, and auto-generate legs

        legA = Leg(tensor = None, dim = 5, name = 'a')
        legB = Leg(tensor = None, dim = 6, name = 'b')

        a = Tensor(legs = [legA, legB])
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))

        a = Tensor(legs = [legA, legB], labels = ['a', 'b'])
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))

        def labelsSizeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], labels = ['a'])
        def labelsOrderNotEqualFunc():
            _ = Tensor(legs = [legA, legB], labels = ['b', 'a'])

        def shapeSizeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], shape = (5, 6, 7))
        def shapeOrderNotEqualFunc():
            _ = Tensor(legs = [legA, legB], shape = (6, 5))
        
        def dataDimNotEqualFunc():
            _ = Tensor(legs = [legA, legB], data = np.zeros((5, 6, 7)))
        def dataShapeNotEqualFunc():
            _ = Tensor(legs = [legA, legB], data = np.zeros((5, 5)))

        self.assertRaises(ValueError, labelsSizeNotEqualFunc)
        self.assertRaises(ValueError, labelsOrderNotEqualFunc)
        self.assertRaises(ValueError, shapeSizeNotEqualFunc)
        self.assertRaises(ValueError, shapeOrderNotEqualFunc)
        self.assertRaises(ValueError, dataDimNotEqualFunc)
        self.assertRaises(ValueError, dataShapeNotEqualFunc)

        # for data, works if (data size) = (dim product), no matter what the shape of data

        a = Tensor(legs = [legA, legB], data = np.zeros((6, 5)))
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))

        a = Tensor(legs = [legA, legB], data = np.zeros((3, 2, 5)))
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))

        a = Tensor(legs = [legA, legB], data = np.zeros(30))
        self.assertTupleEqual(a.shape, (5, 6))
        self.assertEqual(a.dim, 2)
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b']))

        # 2. legs not exist, shape exist
        # if data exist, check the total number of components of data equal to shape, otherwise random
        # if labels exist: check the number of labels equal to dimension, otherwise auto-generate

        a = Tensor(shape = (5, 3, 4))
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b', 'c']))
        self.assertEqual(a.dim, 3)

        a = Tensor(shape = (5, 3, 4), data = np.zeros(60))
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['a', 'b', 'c']))
        self.assertEqual(a.dim, 3)
        self.assertEqual(a.a[(0, 0, 0)], 0)

        a = Tensor(shape = (5, 3, 4), labels = ['c', 'b', 'a'])
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)

        a = Tensor(shape = (5, 3, 4), labels = ('c', 'b', 'a')) # tuple also is acceptable
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)

        a = Tensor(shape = (5, 3, 4), labels = ['c', 'b', 'a'], data = np.zeros(60))
        self.assertTupleEqual(a.shape, (5, 3, 4))
        self.assertTrue(funcs.compareLists(a.labels, ['c', 'b', 'a']))
        self.assertEqual(a.dim, 3)

        def dataTotalSizeNotEqualErrorFunc():
            _ = Tensor(shape = (5, 3, 4), data = np.zeros((5, 3, 3)))
        def labelsSizeNotEqualFunc2():
            _ = Tensor(shape = (5, 3, 4), labels = ['a', 'b'])

        self.assertRaises(ValueError, dataTotalSizeNotEqualErrorFunc)
        self.assertRaises(ValueError, labelsSizeNotEqualFunc2)

        # 3. legs not exist, shape not exist
        # if data exist: generate shape according to data, and auto-generate legs

        a = Tensor(data = np.zeros((3, 4, 5)))
        self.assertTupleEqual(a.shape, (3, 4, 5))
        self.assertEqual(a.dim, 3)
        self.assertEqual(a.legs[0].dim, 3)
        self.assertEqual(a.legs[0].name, 'a')

        def nothingErrorFunc():
            _ = Tensor()

        self.assertRaises(ValueError, nothingErrorFunc)
Ejemplo n.º 19
0
    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)