def trace(mpo): """ \sum_{n1n2...} A[n1n1] A[n2n2] A[nknk] """ traced_mts = [N.einsum("innj", mt) for mt in mpo] val = traced_mts[0] nsites = len(mpo) for i in xrange(1, nsites): val = N.dot(val, traced_mts[i]) return N.trace(val) #[0,0]
def ceval(mps, config): """ Evaluates mps at given config """ mps_mats = [None] * len(config) nsites = len(config) for i, pval in enumerate(config): mps_mats[i] = mps[i][:, pval, :] # multiply "backwards" from right to left val = mps_mats[0] for i in xrange(1, nsites): val = N.dot(val, mps_mats[i]) # turn into scalar return N.trace(val)
def check_lortho(tens): tensm = N.reshape(tens, [N.prod(tens.shape[:-1]), tens.shape[-1]]) s = N.dot(N.conj(tensm.T), tensm) return scipy.linalg.norm(s - N.eye(s.shape[0]))
def check_rortho(tens): tensm = N.reshape(tens, [tens.shape[0], N.prod(tens.shape[1:])]) s = N.dot(tensm, N.conj(tensm.T)) return scipy.linalg.norm(s - N.eye(s.shape[0]))
def compress(mps, side, trunc=1.e-12, check_canonical=False): """ inp: canonicalise MPS (or MPO) trunc=0: just canonicalise 0<trunc<1: sigma threshold trunc>1: number of renormalised vectors to keep side='l': compress LEFT-canonicalised MPS by sweeping from RIGHT to LEFT output MPS is right canonicalised i.e. CRRR side='r': reverse of 'l' returns: truncated or canonicalised MPS """ assert side in ["l", "r"] # if trunc==0, we are just doing a canonicalisation, # so skip check, otherwise, ensure mps is canonicalised if trunc != 0 and check_canonical: if side == "l": assert is_left_canonical(mps) else: assert is_right_canonical(mps) ret_mps = [] nsites = len(mps) if side == "l": res = mps[-1] else: res = mps[0] for i in xrange(1, nsites): # physical indices exclude first and last indices pdim = list(res.shape[1:-1]) if side == "l": res = N.reshape(res, (res.shape[0], N.prod(res.shape[1:]))) else: res = N.reshape(res, (N.prod(res.shape[:-1]), res.shape[-1])) if svd_iop == 0: u, sigma, vt = svd(res, full_matrices=False, lapack_driver='gesvd') else: u, sigma, vt = svd(res, full_matrices=False) if trunc == 0: m_trunc = len(sigma) elif trunc < 1.: # count how many sing vals < trunc normed_sigma = sigma / scipy.linalg.norm(sigma) m_trunc = len([s for s in normed_sigma if s > trunc]) else: m_trunc = int(trunc) m_trunc = min(m_trunc, len(sigma)) u = u[:, 0:m_trunc] sigma = N.diag(sigma[0:m_trunc]) vt = vt[0:m_trunc, :] if side == "l": u = N.dot(u, sigma) res = N.dot(mps[nsites - i - 1], u) ret_mpsi = N.reshape(vt, [m_trunc] + pdim + [vt.shape[1] / N.prod(pdim)]) else: vt = N.dot(sigma, vt) res = N.tensordot(vt, mps[i], 1) ret_mpsi = N.reshape(u, [u.shape[0] / N.prod(pdim)] + pdim + [m_trunc]) ret_mps.append(ret_mpsi) ret_mps.append(res) if side == "l": ret_mps.reverse() #fidelity = dot(ret_mps, mps)/dot(mps, mps) #print "compression fidelity:: ", fidelity return ret_mps