def update_cv(vset, sset, qnset, compset, nexciton, Mmax, spectratype, percent=0): sidx = select_Xbasis(qnset, sset, range(nexciton + 1), Mmax, spectratype, percent=percent) xdim = len(sidx) x = np.zeros((vset.shape[0], xdim), dtype=vset.dtype) xqn = [] if compset is not None: compx = np.zeros((compset.shape[0], xdim), dtype=compset.dtype) else: compx = None for idim in range(xdim): x[:, idim] = vset[:, sidx[idim]].copy() if (compset is not None) and (sidx[idim] < compset.shape[1]): compx[:, idim] = compset[:, sidx[idim]].copy() * sset[sidx[idim]] xqn.append(qnset[sidx[idim]]) if compx is not None: compx = Matrix(compx) return Matrix(x), xdim, xqn, compx
def updatemps(vset, sset, qnset, compset, nexciton, Mmax, percent=0): """ select basis to construct new mps, and complementary mps vset, compset is the column vector """ sidx = select_basis(qnset, sset, range(nexciton + 1), Mmax, percent=percent) mpsdim = len(sidx) # need to set value column by column. better in CPU ms = np.zeros((vset.shape[0], mpsdim), dtype=vset.dtype) if compset is not None: compmps = np.zeros((compset.shape[0], mpsdim), dtype=compset.dtype) else: compmps = None mpsqn = [] stot = 0.0 for idim in range(mpsdim): ms[:, idim] = vset[:, sidx[idim]].copy() if (compset is not None) and sidx[idim] < compset.shape[1]: compmps[:, idim] = compset[:, sidx[idim]].copy() * sset[sidx[idim]] mpsqn.append(qnset[sidx[idim]]) stot += sset[sidx[idim]]**2 # print("discard:", 1.0 - stot) if compmps is not None: compmps = asxp(compmps) return asxp(ms), mpsdim, mpsqn, compmps
def cvec2cmat(cshape, c, qnmat, nexciton, nroots=1): # recover good quantum number vector c to matrix format if nroots == 1: cstruct = np.zeros(cshape, dtype=c.dtype) np.place(cstruct, qnmat == nexciton, c) else: cstruct = [] for ic in c: icstruct = np.zeros(cshape, dtype=ic.dtype) np.place(icstruct, qnmat == nexciton, ic) cstruct.append(icstruct) return cstruct
def cvec2cmat(cshape, c, qnmat, nexciton, nroots=1): # recover good quantum number vector c to matrix format if nroots == 1: cstruct = np.zeros(cshape, dtype=c.dtype) np.place(cstruct, qnmat == nexciton, c) else: cstruct = [] if type(c) is not list: assert c.ndim == 2 c = [c[:, iroot] for iroot in range(c.shape[1])] for ic in c: icstruct = np.zeros(cshape, dtype=ic.dtype) np.place(icstruct, qnmat == nexciton, ic) cstruct.append(icstruct) return cstruct
def blockrecover(indices, U, dim): """ recover the block element to its original position """ resortU = np.zeros([dim, U.shape[1]], dtype=U.dtype) resortU[indices, :] = U return resortU
def _array2mt(self, array, idx): if isinstance(array, Matrix): mt = array.astype(self.dtype) else: mt = Matrix(array, dtype=self.dtype) if self.use_dummy_qn: mt.sigmaqn = np.zeros(mt.pdim_prod, dtype=np.int) else: mt.sigmaqn = self._get_sigmaqn(idx) return mt
def dag2mat(self, xshape, x, dag_qnmat, direction): if self.spectratype == "abs": up_exciton, down_exciton = 1, 0 else: up_exciton, down_exciton = 0, 1 xdag = np.zeros(xshape, dtype=x.dtype) mask = self.condition(dag_qnmat, [down_exciton, up_exciton]) np.place(xdag, mask, x) shape = list(xdag.shape) if xdag.ndim == 3: if direction == 'left': xdag = xdag.reshape(shape + [1]) else: xdag = xdag.reshape([1] + shape) return xdag
def qnmat_add(self, mat_l, mat_r): lshape, rshape = mat_l.shape, mat_r.shape lena = int(np.prod(np.array(lshape)) / 2) lenb = int(np.prod(np.array(rshape)) / 2) matl = mat_l.reshape(lena, 2) matr = mat_r.reshape(lenb, 2) lr1 = np.add.outer(matl[:, 0], matr[:, 0]).flatten() lr2 = np.add.outer(matl[:, 1], matr[:, 1]).flatten() lr = np.zeros((len(lr1), 2)) lr[:, 0] = lr1 lr[:, 1] = lr2 shapel = list(mat_l.shape) del shapel[-1] shaper = list(mat_r.shape) del shaper[-1] lr = lr.reshape(shapel + shaper + [2]) return lr
def blockappend( vset, vset0, qnset, qnset0, svset0, v, n, dim, indice, shape, full_matrices=True, ): vset.append(blockrecover(indice, v[:, :dim], shape)) qnset += [n] * dim if full_matrices: vset0.append(blockrecover(indice, v[:, dim:], shape)) qnset0 += [n] * (v.shape[0] - dim) svset0.append(np.zeros(v.shape[0] - dim)) return vset, vset0, qnset, qnset0, svset0
def select_basis(vset, sset, qnset, compset, Mmax, percent=0): """ select basis to construct new mps, and complementary mps vset, compset is the column vector """ # allowed qn subsection qnlist = set(qnset) # convert to dict basdic = dict() for i in range(len(qnset)): # clean quantum number outside qnlist if qnset[i] in qnlist: basdic[i] = [qnset[i], sset[i]] # each good quantum number block equally get percent/nblocks def block_select(basdic, qn, n): block_basdic = {i: basdic[i] for i in basdic if basdic[i][0] == qn} sort_block_basdic = sorted(block_basdic.items(), key=lambda x: x[1][1], reverse=True) nget = min(n, len(sort_block_basdic)) # print(qn, "block # of retained basis", nget) sidx = [i[0] for i in sort_block_basdic[0:nget]] for idx in sidx: del basdic[idx] return sidx nbasis = min(len(basdic), Mmax) # print("# of selected basis", nbasis) sidx = [] # equally select from each quantum number block if percent != 0: nbas_block = int(nbasis * percent / len(qnlist)) for iqn in qnlist: sidx += block_select(basdic, iqn, nbas_block) # others nbasis = nbasis - len(sidx) sortbasdic = sorted(basdic.items(), key=lambda x: x[1][1], reverse=True) sidx += [i[0] for i in sortbasdic[0:nbasis]] assert len(sidx) == len(set(sidx)) # there must be no duplicated mpsdim = len(sidx) # need to set value column by column. better in CPU ms = np.zeros((vset.shape[0], mpsdim), dtype=vset.dtype) if compset is not None: compmps = np.zeros((compset.shape[0], mpsdim), dtype=compset.dtype) else: compmps = None mpsqn = [] stot = 0.0 for idim in range(mpsdim): ms[:, idim] = vset[:, sidx[idim]].copy() if (compset is not None) and sidx[idim] < compset.shape[1]: compmps[:, idim] = compset[:, sidx[idim]].copy() * sset[sidx[idim]] mpsqn.append(qnset[sidx[idim]]) stot += sset[sidx[idim]]**2 # print("discard:", 1.0 - stot) if compmps is not None: compmps = asxp(compmps) return asxp(ms), mpsdim, mpsqn, compmps
def x_svd(self, xstruct, xqnbigl, xqnbigr, nexciton, direction, percent=0): Gamma = xstruct.reshape( np.prod(xqnbigl.shape) // 2, np.prod(xqnbigr.shape) // 2) localXqnl = xqnbigl.ravel() localXqnr = xqnbigr.ravel() list_locall = [] list_localr = [] for i in range(0, len(localXqnl), 2): list_locall.append([localXqnl[i], localXqnl[i + 1]]) for i in range(0, len(localXqnr), 2): list_localr.append([localXqnr[i], localXqnr[i + 1]]) localXqnl = copy.deepcopy(list_locall) localXqnr = copy.deepcopy(list_localr) xuset = [] xuset0 = [] xvset = [] xvset0 = [] xsset = [] xsuset0 = [] xsvset0 = [] xqnlset = [] xqnlset0 = [] xqnrset = [] xqnrset0 = [] if self.spectratype == "abs": combine = [[[y, 0], [nexciton - y, 0]] for y in range(nexciton + 1)] elif self.spectratype == "emi": combine = [[[0, y], [0, nexciton - y]] for y in range(nexciton + 1)] for nl, nr in combine: lset = np.where(self.condition(np.array(localXqnl), [nl]))[0] rset = np.where(self.condition(np.array(localXqnr), [nr]))[0] if len(lset) != 0 and len(rset) != 0: Gamma_block = Gamma.ravel().take( (lset * Gamma.shape[1]).reshape(-1, 1) + rset) try: U, S, Vt = \ scipy.linalg.svd(Gamma_block, full_matrices=True, lapack_driver='gesdd') except: U, S, Vt = \ scipy.linalg.svd(Gamma_block, full_matrices=True, lapack_driver='gesvd') dim = S.shape[0] xsset.append(S) # U part quantum number xuset.append( svd_qn.blockrecover(lset, U[:, :dim], Gamma.shape[0])) xqnlset += [nl] * dim xuset0.append( svd_qn.blockrecover(lset, U[:, dim:], Gamma.shape[0])) xqnlset0 += [nl] * (U.shape[0] - dim) xsuset0.append(np.zeros(U.shape[0] - dim)) # V part quantum number VT = Vt.T xvset.append( svd_qn.blockrecover(rset, VT[:, :dim], Gamma.shape[1])) xqnrset += [nr] * dim xvset0.append( svd_qn.blockrecover(rset, VT[:, dim:], Gamma.shape[1])) xqnrset0 += [nr] * (VT.shape[0] - dim) xsvset0.append(np.zeros(VT.shape[0] - dim)) xuset = np.concatenate(xuset + xuset0, axis=1) xvset = np.concatenate(xvset + xvset0, axis=1) xsuset = np.concatenate(xsset + xsuset0) xsvset = np.concatenate(xsset + xsvset0) xqnlset = xqnlset + xqnlset0 xqnrset = xqnrset + xqnrset0 bigl_shape = list(xqnbigl.shape) del bigl_shape[-1] bigr_shape = list(xqnbigr.shape) del bigr_shape[-1] if direction == "left": x, xdim, xqn, compx = update_cv(xvset, xsvset, xqnrset, xuset, nexciton, self.m_max, self.spectratype, percent=percent) if (self.method == "1site") and (len(bigr_shape + [xdim]) == 3): return np.moveaxis( x.reshape(bigr_shape + [1] + [xdim]), -1, 0),\ xdim, xqn, compx.reshape(bigl_shape + [xdim]) else: return np.moveaxis(x.reshape(bigr_shape + [xdim]), -1, 0),\ xdim, xqn, compx.reshape(bigl_shape + [xdim]) elif direction == "right": x, xdim, xqn, compx = update_cv(xuset, xsuset, xqnlset, xvset, nexciton, self.m_max, self.spectratype, percent=percent) if (self.method == "1site") and (len(bigl_shape + [xdim]) == 3): return x.reshape([1] + bigl_shape + [xdim]), xdim, xqn, \ np.moveaxis(compx.reshape(bigr_shape + [xdim]), -1, 0) else: return x.reshape(bigl_shape + [xdim]), xdim, xqn, \ np.moveaxis(compx.reshape(bigr_shape + [xdim]), -1, 0)
def zeros(shape, dtype=None): if dtype is None: dtype = backend.real_dtype return Matrix(np.zeros(shape), dtype=dtype)
def check_property(mp): electron_occupation = np.zeros((mol_list.mol_num)) electron_occupation[mol_list.mol_num // 2] = 1 assert mp.norm == pytest.approx(1) assert np.allclose(mp.e_occupations, electron_occupation) assert np.allclose(mp.ph_occupations, np.zeros((mol_list.ph_modes_num)))