To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit 0583f9b8 authored by Valerio's avatar Valerio
Browse files

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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment