Commit 0583f9b8 by Valerio

### Lectures 13, exercise 10 solutions, exercise 11 text

parent c2584e80
 #Credits: Evert van Nieuwenburg from __future__ import division import numpy as np import scipy as sp import scipy.sparse.linalg import copy class MPS(object): def __init__(self,L,d,D): self.L=L if isinstance(d, (int, long, float)): self.d = d*np.ones(L,dtype=int) else: self.d = np.array(d,dtype=int) if isinstance(D, (int, long, float)): self.D = D*np.ones(L,dtype=int) else: self.D = np.array(D,dtype=int) self.D[-1]=1 self.M={} self.Lambda={} for s in xrange(self.L): self.M[s] = np.zeros( (self.d[s], self.D[s-1], self.D[s]), dtype=np.complex128 ) self.Lambda[s] = np.zeros( self.D[s] ) def orthogonalize(self): """ Move gauge to either end of system So far, only finite system. """ # Move isometric gauge to first site for s in xrange(self.gauge_location,0,-1): self.move_gauge_left(s) def set_random_state(self): """ Randomize MPS matrices, and fully left-orthogonalize """ # Set matrices self.M = {} self.Lambda = {} for s in xrange(self.L): self.M[s] = np.random.rand( self.d[s], self.D[s-1], self.D[s] ) + 1j*np.random.rand( self.d[s], self.D[s-1], self.D[s] ) self.Lambda[s] = np.zeros( self.D[s] ) # Normalize for s in xrange(self.L): norm = np.sqrt( np.tensordot( self.M[s].conj(), self.M[s], axes=((0,1,2),(0,1,2)) ) ) self.M[s] /= norm self.orthogonalize() def move_gauge_left(self, s): """ Move the isometric gauge point to site s-1. """ # Group physical leg with right leg tmp = np.reshape( np.transpose( self.M[s], (1,0,2) ), (self.M[s].shape[1], self.M[s].shape[0]*self.M[s].shape[2]) ) # SVD and store new bond dimension U, S, V = svd( tmp, full_matrices=False ) # Possibly truncate and normalize self.D[s-1] = len(S) # Store singular values self.Lambda[s-1] = S # Reshape V into new local M self.M[s] = np.transpose(np.reshape( V, (len(S), self.M[s].shape[0], self.M[s].shape[2]) ), (1,0,2)) # Prepare prevous matrix if s > 0: self.M[s-1] = np.tensordot( self.M[s-1][:,:,:], np.dot(U, np.diag(S)), axes=(2,0) ) # Update gauge center self.gauge_location -= 1 def move_gauge_right(self, s): """ Move the isometric gauge point to site s+1. """ # Group physical leg with left leg tmp = np.reshape( self.M[s], (self.M[s].shape[0]*self.M[s].shape[1], self.M[s].shape[2]) ) # SVD and store new bond dimension U, S, V = np.linalg.svd( tmp, full_matrices=False ) # Possibly truncate and normalize self.D[s] = len(S) # Store singular values self.Lambda[s] = S # Reshape U into new local M self.M[s] = np.reshape( U, (self.M[s].shape[0], self.M[s].shape[1], len(S)) ) # Prepare next matrix if s < self.L-1: self.M[s+1] = np.transpose( np.tensordot( np.dot(np.diag(S),V), self.M[s+1], axes=(1,1) ), (1,0,2) ) # Update gauge center self.gauge_location += 1