def dmrg_shared_exec(mpo_tensors, init_mps_tensors, max_mps_rank, num_iter=1, sequence='R'): """ Perform DMRG iterations with shared executions. """ if sequence != "R": raise NotImplementedError num = len(mpo_tensors) size = mpo_tensors[0].shape[1] mpo_ranks = [mpo_tensors[i].shape[0] for i in range(1, len(mpo_tensors))] mps_tensors = copy.deepcopy(init_mps_tensors) mps_ranks = [mps_tensors[i].shape[0] for i in range(1, len(mps_tensors))] dg = DmrgGraph.create(num, mpo_ranks, mps_ranks, size) for i, hes in enumerate(dg.hessians): dg.hessians[i] = simplify(hes) assert isinstance(hes, ad.EinsumNode) dg.hessians = generate_sequential_optimal_tree(dg.hessians, dg.mps_inputs) executor = ad.Executor(dg.hessians) # sequence is R for iter in range(num_iter): mps_tensors = gauge_transform_mps(mps_tensors, right=True) mps_ranks = [ mps_tensors[i].shape[0] for i in range(1, len(mps_tensors)) ] for i in range(num - 1): dg.update_graph(num, mpo_ranks, mps_ranks, size) feed_dict = dict(zip(dg.mpo_inputs, mpo_tensors)) feed_dict.update(dict(zip(dg.mps_inputs, mps_tensors))) hes_val, = executor.run(feed_dict=feed_dict, out_nodes=[dg.hessians[i]]) # get the smallest eigenvalue and the corresponding eigenvector of the hesval eigvec_shape = dg.intermediates[i].shape eig_val, eigvec = get_smallest_eigenpair(hes_val, dg.intermediates[i].shape) # Update the two sites of mps mps_tensors[i], mps_tensors[i + 1] = dmrg_local_update( dg.intermediates[i], eigvec, max_mps_rank) # update the rank mps_ranks[i] = mps_tensors[i + 1].shape[0] print(f'At iteration {iter} the smallest eigenvalue is: {eig_val}') return mps_tensors, eig_val
def test_gauge_transform_left(backendopt): for datatype in backendopt: T.set_backend(datatype) tensors_input = rand_mps(num=4, rank=4, size=2) tensors = gauge_transform_mps(tensors_input, right=False) # make sure the transformation will not change the mps results mps = T.einsum('ab,acd,cef,eg->bdfg', *tensors_input) mps_gauge = T.einsum('ab,acd,cef,eg->bdfg', *tensors) assert T.norm(mps - mps_gauge) < 1e-8 dim = len(tensors_input) # test all tensors except the right one's orthogonality inner = T.einsum("ab,cb->ac", tensors[0], tensors[0]) assert T.norm(inner - T.identity(inner.shape[0])) < 1e-8 for i in range(1, dim - 1): inner = T.einsum("abc,adc->bd", tensors[i], tensors[i]) assert T.norm(inner - T.identity(inner.shape[0])) < 1e-8
def dmrg(mpo_tensors, init_mps_tensors, max_mps_rank, num_iter=1, sequence='R'): """ Perform DMRG iterations. Parameters ---------- mpo_tensors: an array of mpo tensor data init_mps_tensors: an array of mps tensor data max_mps_rank: maximum mps rank in the iterations num_iter: total number of iterations sequence: str, String made of 'L' and 'R' defining the sweep sequence, e.g 'RRL'. The sequence will be repeated until num_iter is reached. """ if sequence != "R": raise NotImplementedError num = len(mpo_tensors) size = mpo_tensors[0].shape[1] mpo_ranks = [mpo_tensors[i].shape[0] for i in range(1, len(mpo_tensors))] mps_tensors = copy.deepcopy(init_mps_tensors) mps_ranks = [mps_tensors[i].shape[0] for i in range(1, len(mps_tensors))] dg = DmrgGraph.create(num, mpo_ranks, mps_ranks, size) executor = ad.Executor(dg.hessians) # sequence is R for iter in range(num_iter): mps_tensors = gauge_transform_mps(mps_tensors, right=True) mps_ranks = [ mps_tensors[i].shape[0] for i in range(1, len(mps_tensors)) ] for i in range(num - 1): dg.update_graph(num, mpo_ranks, mps_ranks, size) feed_dict = dict(zip(dg.mpo_inputs, mpo_tensors)) feed_dict.update(dict(zip(dg.mps_inputs, mps_tensors))) hes_val, = executor.run(feed_dict=feed_dict, out_nodes=[dg.hessians[i]]) # get the smallest eigenvalue and the corresponding eigenvector of the hesval eigvec_shape = dg.intermediates[i].shape eig_val, eigvec = get_smallest_eigenpair(hes_val, dg.intermediates[i].shape) # Update the two sites of mps mps_tensors[i], mps_tensors[i + 1] = dmrg_local_update( dg.intermediates[i], eigvec, max_mps_rank) # update the rank mps_ranks[i] = mps_tensors[i + 1].shape[0] print(f'At iteration {iter} the smallest eigenvalue is: {eig_val}') return mps_tensors, eig_val
def dmrg_shared_exec_iterative_solve(mpo_tensors, init_mps_tensors, max_mps_rank, num_iter=1, sequence='R'): """ Perform DMRG iterations with shared execution and iterative solve. """ if sequence != "R": raise NotImplementedError num = len(mpo_tensors) size = mpo_tensors[0].shape[1] mpo_ranks = [mpo_tensors[i].shape[0] for i in range(1, len(mpo_tensors))] mps_tensors = copy.deepcopy(init_mps_tensors) mps_ranks = [mps_tensors[i].shape[0] for i in range(1, len(mps_tensors))] dg = DmrgImplicitUpdateGraph.create(num, mpo_ranks, mps_ranks, size) for i, hvp in enumerate(dg.hvps): dg.hvps[i] = simplify(hvp) assert isinstance(hvp, ad.EinsumNode) dg.hvps = generate_sequential_optimal_tree(dg.hvps, dg.mps_inputs) executor_hvps = ad.Executor(dg.hvps) executor_intermediates = ad.Executor(dg.intermediates) # sequence is R for iter in range(num_iter): mps_tensors = gauge_transform_mps(mps_tensors, right=True) mps_ranks = [ mps_tensors[i].shape[0] for i in range(1, len(mps_tensors)) ] for i in range(num - 1): dg.update_graph(num, mpo_ranks, mps_ranks, size) feed_dict = dict(zip(dg.mpo_inputs, mpo_tensors)) feed_dict.update(dict(zip(dg.mps_inputs, mps_tensors))) intermediate, = executor_intermediates.run( feed_dict=feed_dict, out_nodes=[dg.intermediates[i]]) # Calculate the eigenvector using the implicit solver. # Note: This only supports NumPy datatype. # TODO: Add a general Lanczos solver that adapts to all the backends. operator = DMRGLinearOperator(dg, executor_hvps, i, feed_dict) # Reference: https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.eigsh.html eig_vals, eigvecs = spla.eigsh(operator, k=1, ncv=4, tol=1e-3, which='SA', v0=intermediate.ravel()) eig_val, eigvec = eig_vals[0], eigvecs[:, 0] eigvec = T.reshape(eigvec, dg.intermediates[i].shape) # Update the two sites of mps mps_tensors[i], mps_tensors[i + 1] = dmrg_local_update( dg.intermediates[i], eigvec, max_mps_rank) # update the rank mps_ranks[i] = mps_tensors[i + 1].shape[0] print(f'At site {i}, the smallest eigenvalue is: {eig_val}') print(f'At iteration {iter} the smallest eigenvalue is: {eig_val}') return mps_tensors, eig_val