def getTridiagonal(HL, HR, H, k, psi, psiCompare=None): accuracy = 1e-10 # 1e-12 v = bops.multiContraction(psi[k], psi[k + 1], '2', '0') # Small innaccuracies ruin everything! v.set_tensor(v.get_tensor() / bops.getNodeNorm(v)) psiCopy = bops.copyState(psi) base = [] base.append(v) Hv = applyHToM(HL, HR, H, v, k) alpha = bops.multiContraction(v, Hv, '0123', '0123*').get_tensor() if psiCompare is not None: copyV = bops.copyState([v])[0] psiCopy = bops.assignNewSiteTensors(psiCopy, k, copyV, '>>')[0] E = stateEnergy(psi, H) w = bops.addNodes(Hv, bops.multNode(v, -alpha)) beta = bops.getNodeNorm(w) # Start with T as an array and turn into tridiagonal matrix at the end. Tarr = [[0, 0, 0]] Tarr[0][1] = alpha counter = 0 formBeta = 2 * beta # This is just some value to init formBeta > beta. while (beta > accuracy) and (counter <= 50) and (beta < formBeta): Tarr[counter][2] = beta Tarr.append([0, 0, 0]) Tarr[counter + 1][0] = beta counter += 1 v = bops.multNode(w, 1 / beta) base.append(v) if psiCompare is not None: copyV = bops.copyState([v])[0] psiCopy = bops.assignNewSiteTensors(psiCopy, k, copyV, '>>')[0] Hv = applyHToM(HL, HR, H, v, k) alpha = bops.multiContraction(v, Hv, '0123', '0123*').get_tensor() Tarr[counter][1] = alpha w = bops.addNodes(bops.addNodes(Hv, bops.multNode(v, -alpha)), \ bops.multNode(base[counter-1], -beta)) formBeta = beta beta = bops.getNodeNorm(w) T = np.zeros((len(Tarr), len(Tarr)), dtype=complex) T[0][0] = Tarr[0][1] if len(Tarr) > 1: T[0][1] = Tarr[0][2] for i in range(1, len(Tarr)-1): T[i][i-1] = Tarr[i][0] T[i][i] = Tarr[i][1] T[i][i+1] = Tarr[i][2] T[len(Tarr)-1][len(Tarr)-2] = Tarr[len(Tarr)-1][0] T[len(Tarr) - 1][len(Tarr) - 1] = Tarr[len(Tarr) - 1][1] return [T, base]
def lanczos(HL, HR, H, k, psi, psiCompare): [T, base] = getTridiagonal(HL, HR, H, k, psi, psiCompare) [Es, Vs] = np.linalg.eig(T) minIndex = np.argmin(Es) E0 = Es[minIndex] M = None for i in range(len(Es)): M = bops.addNodes(M, bops.multNode(base[i], Vs[i][minIndex])) M = bops.multNode(M, 1/bops.getNodeNorm(M)) return [M, E0]
def applyHToM(HL, HR, H, M, k): k1 = k k2 = k + 1 # Add HL.opSum x h.identity(k1) x h.identity(k2) x I(Right) # and I(Left) x h.identity(k1) x h.identity(k2) x HR.opSum Hv = bops.multiContraction(HL.opSum, M, '0', '0') Hv = bops.addNodes(Hv, bops.multiContraction(M, HR.opSum, '3', '0')) # Add I(Left) x h.single(k1) x h.identity(k2) x I(Right) # And I(Left) x h.identity(k1) x h.single(k2) x I(Right) Hv = bops.addNodes(Hv, \ bops.permute(bops.multiContraction(M, H.singles[k1], '1', '0'), [0, 3, 1, 2])) Hv = bops.addNodes(Hv, \ bops.permute(bops.multiContraction(M, H.singles[k2], '2', '0'), [0, 1, 3, 2])) # Add HL.openOp x h.r2l(k1) x h.identity(k2) x I(Right) # And I(Left) x h.identity(k1) x h.l2r(k2) x HR.openOp HK1R2L = bops.permute(bops.multiContraction(M, H.r2l[k1], '1', '0'), [0, 4, 3, 1, 2]) Hv = bops.addNodes(Hv, \ bops.multiContraction(HL.openOp, HK1R2L, '02', '01')) HK2L2R = bops.permute(bops.multiContraction(M, H.l2r[k2], '2', '0'), [0, 1, 3, 4, 2]) Hv = bops.addNodes(Hv, \ bops.multiContraction(HK2L2R, HR.openOp, '43', '02')) # Add I(Left) x h.l2r(k1) x h.r2l(k2) x I(Right) HK1K2 = bops.multiContraction(M, H.l2r[k1], '1', '0') HK1K2 = bops.multiContraction(HK1K2, H.r2l[k2], '14', '02') HK1K2 = bops.permute(HK1K2, [0, 2, 3, 1]) Hv = bops.addNodes(Hv, HK1K2) return Hv
def getHLR(psi, l, H, dir, HLRold): if dir == '>>': if l == -1: opSum = tn.Node(np.zeros((psi[0].get_dimension(0), psi[0].get_dimension(0)), dtype=complex)) openOp = tn.Node(np.zeros((psi[0].get_dimension(0), psi[0].get_dimension(0)), dtype=complex)) return HExpValMid(opSum, openOp) else: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] singlel = bops.copyState([H.singles[l]], conj=False)[0] psil[0] ^ psilConj[0] psil[1] ^ singlel[0] psilConj[1] ^ singlel[1] opSum1 = tn.contract_between(psil, \ tn.contract_between(singlel, psilConj), name='operator-sum') if np.max(opSum1.tensor) > 100: g=1 if l > 0: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] HLRoldCopy = bops.copyState([HLRold.openOp])[0] r2l_l = bops.copyState([H.r2l[l]], conj=False)[0] psil[0] ^ HLRoldCopy[0] psilConj[0] ^ HLRoldCopy[1] psil[1] ^ r2l_l[0] psilConj[1] ^ r2l_l[1] r2l_l[2] ^ HLRoldCopy[2] opSum2 = tn.contract_between(psil, tn.contract_between(psilConj, tn.contract_between(r2l_l, HLRoldCopy))) opSum1 = bops.addNodes(opSum1, opSum2) if np.max(opSum1.tensor) > 100: g = 1 psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] HLRoldCopy = bops.copyState([HLRold.opSum])[0] psil[0] ^ HLRoldCopy[0] psilConj[0] ^ HLRoldCopy[1] psil[1] ^ psilConj[1] opSum3 = tn.contract_between(psil, tn.contract_between(psilConj, HLRoldCopy)) opSum1 = bops.addNodes(opSum1, opSum3) if np.max(opSum1.tensor) > 100: g=1 if l < len(psi) - 1: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] l2r_l = bops.copyState([H.l2r[l]], conj=False)[0] psil[0] ^ psilConj[0] psil[1] ^ l2r_l[0] psilConj[1] ^ l2r_l[1] openOp = tn.contract_between(psil, tn.contract_between(psilConj, l2r_l), name='open-operator') else: openOp = None return HExpValMid(opSum1, openOp) if dir == '<<': if l == len(psi): opSum = tn.Node(np.zeros((psi[l-1].get_dimension(2), psi[l-1].get_dimension(2)), dtype=complex)) openOp = tn.Node(np.zeros((psi[l-1].get_dimension(2), psi[l-1].get_dimension(2)), dtype=complex)) return HExpValMid(opSum, openOp) else: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] single_l = bops.copyState([H.singles[l]], conj=False)[0] psil[2] ^ psilConj[2] psil[1] ^ single_l[0] psilConj[1] ^ single_l[1] opSum1 = tn.contract_between(psil, \ tn.contract_between(single_l, psilConj), name='operator-sum') if l < len(psi) -1: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] HLRoldCopy = bops.copyState([HLRold.openOp])[0] l2r_l = bops.copyState([H.l2r[l]], conj=False)[0] psil[2] ^ HLRoldCopy[0] psilConj[2] ^ HLRoldCopy[1] psil[1] ^ l2r_l[0] psilConj[1] ^ l2r_l[1] l2r_l[2] ^ HLRoldCopy[2] opSum2 = tn.contract_between(psil, tn.contract_between(psilConj, tn.contract_between(l2r_l, HLRoldCopy))) opSum1 = bops.addNodes(opSum1, opSum2) psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] HLRoldCopy = bops.copyState([HLRold.opSum])[0] psil[2] ^ HLRoldCopy[0] psilConj[2] ^ HLRoldCopy[1] psil[1] ^ psilConj[1] opSum3 = tn.contract_between(psil, tn.contract_between(psilConj, HLRoldCopy)) opSum1 = bops.addNodes(opSum1, opSum3) if l > 0: psil = bops.copyState([psi[l]], conj=False)[0] psilConj = bops.copyState([psi[l]], conj=True)[0] r2l_l = bops.copyState([H.r2l[l]], conj=False)[0] psil[2] ^ psilConj[2] psil[1] ^ r2l_l[0] psilConj[1] ^ r2l_l[1] openOp = tn.contract_between(psil, tn.contract_between(psilConj, r2l_l), name='open-operator') else: openOp = None return HExpValMid(opSum1, openOp)