def directedIterateTrial(self, d): funcs.assertInSet(d, ['u', 'd', 'l', 'r'], 'direction') # make projector, and return the truncation error # for l: use M, M', calculate MM', return U_L if (d == 'l') or (d == 'r'): # horizontal project squareTensor = self.horizontalProjectFTN[d].contract( makeSquareTensorDict(self.a)) # l, r # labels = [d, funcs.oppositeDirection(d)] # print('a = {}'.format(self.a)) # print('squareTensor = {}'.format(squareTensor)) squareMat = squareTensor.toMatrix( rows=[d], cols=[funcs.oppositeDirection(d)]) # print(squareTensor) prjMat, error = linalgFuncs.solveEnv(squareMat, self.chiH) # prjTensor = Tensor(data = prjMat, shape = (chiH ** 2, prjMat.shape[1]), labels = ['i', 'o']) else: squareTensor = self.verticalProjectFTN[d].contract( makeSquareTensorDict(self.a)) # print('a = {}'.format(self.a)) # print('squareTensor = {}'.format(squareTensor)) squareMat = squareTensor.toMatrix( rows=[d], cols=[funcs.oppositeDirection(d)]) prjMat, error = linalgFuncs.solveEnv(squareMat, self.chiV) # prjTensor = Tensor(data = prjMat, shape = (chiV ** 2, prjMat.shape[1]), labels = ['i', 'o']) # envTrace = xplib.xp.trace(squareMat) # envTraceApprox = xplib.xp.trace(prjMat.T @ squareMat @ prjMat) # error = (envTrace - envTraceApprox) / envTrace # deltaTensor = (prjMat.T @ squareMat @ prjMat) - squareMat # error = xplib.xp.linalg.norm(deltaTensor) / xplib.xp.linalg.norm(squareMat) return {'error': error, 'projectTensor': prjMat}
def squareVerticalContractFTN(d): funcs.assertInSet(d, ['u', 'd'], 'vertical direction') opd = funcs.oppositeSingleDirection(d) FTN = FiniteTensorNetwork(tensorNames=['ul', 'ur', 'dr', 'dl']) FTN.addLink('ul', opd, 'dl', opd) FTN.addLink('ul', 'r', 'ur', 'l') FTN.addLink('ur', opd, 'dr', opd) FTN.addLink('dl', 'r', 'dr', 'l') FTN.addLink('ul', 'l', 'dl', 'l') FTN.addLink('ur', 'r', 'dr', 'r') FTN.addPostOutProduct([d + 'l-' + d, d + 'r-' + d], d) FTN.addPostOutProduct([opd + 'l-' + d, opd + 'r-' + d], opd) return FTN
def directedIterate(self, d, prjTensor, inputTensor1=None, inputTensor2=None): # print(inputTensor1, inputTensor2) # print(prjTensor.shape) funcs.assertInSet(d, ['u', 'd', 'l', 'r'], 'direction') # use the real projector for iteration if (inputTensor1 is None): inputTensor1 = self.a if (inputTensor2 is None): inputTensor2 = self.a chiH = inputTensor1.shapeOfLabel('l') chiV = inputTensor1.shapeOfLabel('u') if (d == 'l') or (d == 'r'): # given U_L: # the prjTensor lTensor = Tensor(data=prjTensor, shape=(chiH, chiH, prjTensor.shape[1]), labels=['u', 'd', 'o']) rTensor = Tensor(data=funcs.transposeConjugate(prjTensor), shape=(prjTensor.shape[1], chiH, chiH), labels=['o', 'u', 'd']) if (d == 'r'): lTensor, rTensor = rTensor, lTensor return self.horizontalIterateFTN.contract({ 'u': inputTensor1, 'd': inputTensor2, 'l': lTensor, 'r': rTensor }) else: uTensor = Tensor(data=prjTensor, shape=(chiV, chiV, prjTensor.shape[1]), labels=['l', 'r', 'o']) dTensor = Tensor(data=funcs.transposeConjugate(prjTensor), shape=(prjTensor.shape[1], chiV, chiV), labels=['o', 'l', 'r']) if (d == 'd'): uTensor, dTensor = dTensor, uTensor return self.verticalIterateFTN.contract({ 'u': uTensor, 'd': dTensor, 'l': inputTensor1, 'r': inputTensor2 })
def squareHorizontalContractFTN(d): # TODO: add docstrings for following functions funcs.assertInSet(d, ['l', 'r'], 'horizontal direction') opd = funcs.oppositeSingleDirection(d) FTN = FiniteTensorNetwork(tensorNames=['ul', 'ur', 'dr', 'dl']) FTN.addLink('ul', 'd', 'dl', 'u') FTN.addLink('ul', opd, 'ur', opd) FTN.addLink('ur', 'd', 'dr', 'u') FTN.addLink('dl', opd, 'dr', opd) FTN.addLink('ul', 'u', 'ur', 'u') FTN.addLink('dl', 'd', 'dr', 'd') FTN.addPostOutProduct(['u' + d + '-' + d, 'd' + d + '-' + d], d) FTN.addPostOutProduct(['u' + opd + '-' + d, 'd' + opd + '-' + d], opd) return FTN
def squareTensorMeasure(idx, obs=None): """ Local measurement on a square of four Ising spins. Parameters ---------- idx : (4, ) tuple of {0, 1} The local spins on the square. obs : str, {'M', 'E'}, optional The observable to be measured. If None, then return 1.0. Returns ------- float If obs is 'M': return the local magnetization(since each site is shared by two squares if we divide the system into such squares, only 0.5 counted for one spin). If obs is 'E': return the local energy(if neighbor spin is equal, then -1, else +1) If obs is None: considering partition function, return 1.0 """ if (obs is None): return 1.0 funcs.assertInSet(obs, ['M', 'E'], 'Ising obervables') if (obs == 'M'): res = 0.0 for x in idx: if (x == 0): res -= 0.5 else: res += 0.5 return res if (obs == 'E'): res = 0.0 for i in range(4): if (idx[i] == idx[(i + 1) % 4]): res -= 1.0 else: res += 1.0 return res return 1.0