Ejemplo n.º 1
0
def ising_impo(J, g):
    site = SpinHalfSite(None)
    Id, Sp, Sm, Sz = site.Id, site.Sp, site.Sm, 2*site.Sz
    Sx = Sp + Sm
    W = [[Id,Sx,g*Sz], [None,None,-J*Sx], [None,None,Id]]
    H = MPO.from_grids([site], [W], bc='infinite', IdL=0, IdR=-1)
    return H
Ejemplo n.º 2
0
    def __init__(self, model_param):
        # 0) Read and set parameters.
        L = get_parameter(model_param, 'L', 1, self.__class__)
        bc_MPS = get_parameter(model_param, 'bc_MPS', 'finite', self.__class__)
        t = get_parameter(model_param, 't', 1., self.__class__)
        alpha = get_parameter(model_param, 'alpha', 1.0, self.__class__)
        delta = get_parameter(model_param, 'delta', 1.0, self.__class__)
        beta = get_parameter(model_param, 'beta', 1.0, self.__class__)
        conserve_fermionic_boson = get_parameter(model_param, \
                            'conserve_fermionic_boson', 'Sz', self.__class__)
        conserve_spin = get_parameter(model_param, 'conserve_spin', None,
                                      self.__class__)
        unused_parameters(model_param, self.__class__)

        # 1) Sites and lattice.
        boson_site = SpinHalfSite(conserve=conserve_fermionic_boson, )
        bond_spin = SpinHalfSite(conserve=conserve_spin)
        double_site = DoubleSite(site0=boson_site,
                                 site1=bond_spin,
                                 label0='0',
                                 label1='1',
                                 charges='independent')
        #        lat = Lattice(Ls=[1], unit_cell=[bond_spin], order='default', bc_MPS=bc_MPS,
        #                      basis=None, positions=None)
        lat = Chain(L=L, site=double_site, bc_MPS='finite')

        # 2) Initialize CouplingModel
        bc_coupling = 'periodic' if bc_MPS == 'infinite' else 'open'
        CouplingModel.__init__(self, lat, bc_coupling)

        # 3) Build the Hamiltonian.
        # 3a) on-site terms
        self.add_onsite(delta / 2.0, 0, 'Sigmaz1')
        self.add_onsite(beta, 0, 'Sigmax1')

        # 3b) coupling terms.
        # 3bi) standard Bose-Hubbard coupling terms
        self.add_coupling(-t, 0, 'Sp0', 0, 'Sm0', 1)
        self.add_coupling(-t, 0, 'Sm0', 0, 'Sp0', 1)
        # 3bii) coupling on site bosons to bond spin
        self.add_coupling(-alpha, 0, 'Sp0 Sigmaz1', 0, 'Sm0', 1)
        self.add_coupling(-alpha, 0, 'Sm0 Sigmaz1', 0, 'Sp0', 1)

        # 4) Initialize MPO
        MPOModel.__init__(self, lat, self.calc_H_MPO())
        # 5) Initialize H bond  # LS: what does this mean?
        NearestNeighborModel.__init__(self, self.lat, self.calc_H_bond())
Ejemplo n.º 3
0
 def init_sites(self, model_params):
     conserve = model_params.get('conserve', 'parity')
     assert conserve != 'Sz'
     if conserve == 'best':
         conserve = 'parity'
         if self.verbose >= 1.:
             print(self.name + ": set conserve to", conserve)
     site = SpinHalfSite(conserve=conserve)
     return site
Ejemplo n.º 4
0
    def __init__(self, model_param):
        # model parameters
        L  = get_parameter(model_param, 'L', 2, self.__class__)
        xi = get_parameter(model_param, 'xi', 0.5, self.__class__)
        Jxx  = get_parameter(model_param, 'Jxx', 1., self.__class__)
        Jz = get_parameter(model_param, 'Jz', 1.5, self.__class__)
        hz = get_parameter(model_param, 'hz', 0., self.__class__)
        conserve = get_parameter(model_param, 'conserve', 'Sz', self.__class__)
        if xi == 0.:
            g = 0.
        elif xi == np.inf:
            g = 1.
        else:
            g = np.exp(-1/(xi))
        unused_parameters(model_param, self.__class__)

        # Define the sites and the lattice, which in this case is a simple uniform chain
        # of spin 1/2 sites
        site = SpinHalfSite(conserve=conserve)
        lat = Chain(L, site, bc_MPS='infinite')

        # The operators that appear in the Hamiltonian. Standard spin operators are
        # already defined for the spin 1/2 site, but it is also possible to add new
        # operators using the add_op method
        Sz, Sp, Sm, Id = site.Sz, site.Sp, site.Sm, site.Id

        # yapf:disable
        # The grid (list of lists) that defines the MPO. It is possible to define the
        # operators in the grid in the following ways:
        # 1) NPC arrays, defined above:
        grid = [[Id,   Sp,   Sm,   Sz,   -hz*Sz    ],
                [None, g*Id, None, None, 0.5*Jxx*Sm],
                [None, None, g*Id, None, 0.5*Jxx*Sp],
                [None, None, None, g*Id, Jz*Sz     ],
                [None, None, None, None, Id        ]]
        # 2) In the form [("OpName", strength)], where "OpName" is the name of the
        # operator (e.g. "Sm" for Sm) and "strength" is a number that multiplies it.
        grid = [[[("Id", 1)], [("Sp",1)], [("Sm",1)], [("Sz",1)], [("Sz", -hz)]    ],
                [None       , [("Id",g)], None      , None      , [("Sm", 0.5*Jxx)]],
                [None       , None      , [("Id",g)], None      , [("Sp", 0.5*Jxx)]],
                [None       , None      , None      , [("Id",g)], [("Sz",Jz)]      ],
                [None       , None      , None      , None      , [("Id",1)]       ]]
        # 3) It is also possible to write a single "OpName", equivalent to
        # [("OpName", 1)].
        grid = [["Id"       , "Sp"      , "Sm"      , "Sz"      , [("Sz", -hz)]    ],
                [None       , [("Id",g)], None      , None      , [("Sm", 0.5*Jxx)]],
                [None       , None      , [("Id",g)], None      , [("Sp", 0.5*Jxx)]],
                [None       , None      , None      , [("Id",g)], [("Sz",Jz)]      ],
                [None       , None      , None      , None      , "Id"             ]]
        # yapf:enable
        grids = [grid]*L

        # Generate the MPO from the grid. Note that it is not necessary to specify
        # the physical legs and their charges, since the from_grids method can extract
        # this information from the position of the operators inside the grid.
        H = MPO.from_grids(lat.mps_sites(), grids, bc='infinite', IdL=0, IdR=-1)
        MPOModel.__init__(self, lat, H)
Ejemplo n.º 5
0
 def init_sites(self, model_params):
     # conserve = get_parameter(model_params, 'conserve', 'parity', self.name)
     # assert conserve != 'Sz'
     # if conserve == 'best':
     #     conserve = 'parity'
     #     if self.verbose >= 1.:
     #         print(self.name + ": set conserve to", conserve)
     site = SpinHalfSite(conserve=None)
     return site
Ejemplo n.º 6
0
def ising_mpo(J, g, N, bc='finite'):
    site = SpinHalfSite(None)
    Id, Sp, Sm, Sz = site.Id, site.Sp, site.Sm, 2*site.Sz
    Sx= Sp + Sm
    # confirmed from TeNPy docs, lines below directly copied from docs
    W_bulk = [[Id,Sx,g*Sz],[None,None,-J*Sx],[None,None,Id]] 
    W_first = [W_bulk[0]]  # first row
    W_last = [[row[-1]] for row in W_bulk]  # last column
    Ws = [W_first] + [W_bulk]*(N-2) + [W_last]
    H = MPO.from_grids([site]*N, Ws, bc, IdL=0, IdR=-1) # (probably leave the IdL,IdR)
    return H
Ejemplo n.º 7
0
def xxz_mpo(J=1.0, Delta=1.0, hz=0.2, N=4, bc='finite'):
    site = SpinHalfSite(None)
    Id, Sp, Sm, Sz = site.Id, site.Sp, site.Sm, 2*site.Sz
    W_bulk = [[Id, Sp, Sm, Sz, -hz * Sz],
              [None, None, None, None, 0.5 * J * Sm],
              [None, None, None, None, 0.5 * J * Sp],
              [None, None, None, None, J * Delta * Sz],
              [None, None, None, None, Id]]
    W_first = [W_bulk[0]]  # first row
    W_last = [[row[-1]] for row in W_bulk]  # last column
    Ws = [W_first] + [W_bulk]*(N - 2) + [W_last]
    H = MPO.from_grids([site]*N, Ws, bc, IdL=0, IdR=-1) # (probably leave the IdL,IdR)
    return H
Ejemplo n.º 8
0
def circuit_mps(params, circuit, N, bc='finite'):
    site = SpinHalfSite(None)    
    tensors = [circuit.get_tensor(params)]*N    
    B_arrs = [np.swapaxes(tensor[:,:,0,:],1,2) for tensor in tensors]
    B_arrs[0] = B_arrs[0][:,0:1,:]
    B_arrs[-1] = B_arrs[-1][:,:,0:1]
    
    psi = MPS.from_Bflat([site]*N, B_arrs, bc, dtype=complex, form=None)    
    if psi.form is not None:
        try:
            psi.canonical_form()
            psi.convert_form(psi.form)
        except:
            print("psi form thing didn't work")    
    return psi
Ejemplo n.º 9
0
def circuit_imps(params, circuit):
    site = SpinHalfSite(None)
    # evaluate circuit, get rank-4 (p_out, b_out, p_in, b_in) unitary
    unitary = circuit.get_tensor(params)
    # change the order of indices to [p, vL, vR] = [p_out, b_in, b_out] 
    # (with p_in = 0 to go from unitary to isometry)
    B = [np.swapaxes(unitary[:,:,0,:],1,2)]
    psi = MPS.from_Bflat([site], B, bc='infinite', dtype=complex, form=None)    
    if psi.form is not None:
        try:
            psi.canonical_form()
            psi.convert_form(psi.form)
        except:
            print("psi form thing didn't work")
    return psi
Ejemplo n.º 10
0
def test_RandomUnitaryEvolution():
    L = 8
    spin_half = SpinHalfSite(conserve='Sz')
    psi = MPS.from_product_state([spin_half] * L, [0, 1] * (L // 2), bc='finite')  # Neel state
    assert tuple(psi.chi) == (1, 1, 1, 1, 1, 1, 1)
    TEBD_params = dict(N_steps=2, trunc_params={'chi_max': 10})
    eng = tebd.RandomUnitaryEvolution(psi, TEBD_params)
    eng.run()
    print(eng.psi.chi)
    assert tuple(eng.psi.chi) == (2, 4, 8, 10, 8, 4, 2)

    # infinite versions
    TEBD_params['trunc_params']['chi_max'] = 20
    psi = MPS.from_product_state([spin_half] * 2, [0, 0], bc='infinite')
    eng = tebd.RandomUnitaryEvolution(psi, TEBD_params)
    eng.run()
    print(eng.psi.chi)
    assert tuple(eng.psi.chi) == (1, 1)  # all up can not be changed
    eng.psi = MPS.from_product_state([spin_half] * 2, [0, 1], bc='infinite')
    eng.run()
    print(eng.psi.chi)
    assert tuple(eng.psi.chi) == (16, 8)
Ejemplo n.º 11
0
# some more imports
from tenpy.networks.site import SpinHalfSite
from tenpy.models.lattice import Chain
from tenpy.networks.mps import MPS
from tenpy.networks.mpo import MPO, MPOEnvironment
from tenpy.algorithms.truncation import svd_theta

# model parameters
Jxx, Jz = 1., 1.
L = 20
dt = 0.1
cutoff = 1.e-10
print("Jxx={Jxx}, Jz={Jz}, L={L:d}".format(Jxx=Jxx, Jz=Jz, L=L))

print("1) create Arrays for an Neel MPS")
site = SpinHalfSite(conserve='Sz')  # predefined charges and Sp,Sm,Sz operators
p_leg = site.leg
chinfo = p_leg.chinfo
# make lattice from unit cell and create product state MPS
lat = Chain(L, site, bc_MPS='finite')
state = ["up", "down"] * (L // 2) + ["up"] * (L % 2)  # Neel state
print("state = ", state)
psi = MPS.from_product_state(lat.mps_sites(), state, lat.bc_MPS)

print("2) create an MPO representing the AFM Heisenberg Hamiltonian")

# predefined physical spin-1/2 operators Sz, S+, S-
Sz, Sp, Sm, Id = site.Sz, site.Sp, site.Sm, site.Id

mpo_leg = npc.LegCharge.from_qflat(chinfo, [[0], [2], [-2], [0], [0]])
Ejemplo n.º 12
0
"""Initialization of sites, MPS and MPO."""
# Copyright 2019 TeNPy Developers, GNU GPLv3

from tenpy.networks.site import SpinHalfSite
from tenpy.networks.mps import MPS
from tenpy.networks.mpo import MPO

spin = SpinHalfSite(conserve="Sz")
print(spin.Sz.to_ndarray())
# [[ 0.5  0. ]
#  [ 0.  -0.5]]

N = 6  # number of sites
sites = [spin] * N  # repeat entry of list N times
pstate = ["up", "down"] * (N // 2)  # Neel state
psi = MPS.from_product_state(sites, pstate, bc="finite")
print("<Sz> =", psi.expectation_value("Sz"))
# <Sz> = [ 0.5 -0.5  0.5 -0.5]
print("<Sp_i Sm_j> =", psi.correlation_function("Sp", "Sm"), sep="\n")
# <Sp_i Sm_j> =
# [[1. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0.]
#  [0. 0. 1. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 1. 0.]
#  [0. 0. 0. 0. 0. 0.]]

# define an MPO
Id, Sp, Sm, Sz = spin.Id, spin.Sp, spin.Sm, spin.Sz
J, Delta, hz = 1., 1., 0.2
W_bulk = [[Id, Sp, Sm, Sz, -hz * Sz], [None, None, None, None, 0.5 * J * Sm],
Ejemplo n.º 13
0
    def network_from_cells(self, network_type, 
                           L, chi_MPO=None, 
                           params=None, bdry_vecs=None, 
                           method=None, T=None):      
        """
        Returns network of finite thermal-holographic Matrix Product State (random-holoMPS), finite 
        holo-MPS, finite holographic Matrix Product Operator (holoMPO), or MPO of a given model.
        --------------
        Inputs:
              --the input assumes the list of unitary tensors at each unit-cell or rank-4 numpy.ndarray--       
          network_type: str
             One of "random_state", "circuit_MPS", "circuit_MPO", or "MPO" options.
          L: int
             Length (number) of repetitions of unit cell in the main network chain.
          chi_MPO: int
             Bond leg dimension for MPO-based structures. 
          params: numpy.ndarray
             Optimized parameters for unitary structure and probability weights.
          bdry_vecs: list
            List of left (first element) and right (second element) boundary vectors.
            (must be set to [None,None] by default, which gives left and right boundary vectors = |0> 
            for MPO-based structures. For holoMPS-based structures, the default [None,None]
            would give left boundary = |0> while the right boundary is traced over). 
          method: str 
            One of "thermal_state_class" or "tenpy" options. (if set to "tenpy", the returned structure
            would be one of physics-TenPy networks). This option is currently only available for 
            "random_state", "circuit_MPS", and "MPO" options. 
           T: float
            Temperature (for thermal-holoMPS option).
        Note:
          -For random_state, circuit_MPS and circuit_MPO options, the original circuit with 
           parameters must be inserted as args. In this case, the returned list of bulk tensors
           includes rank-3 numpy.ndarray for random_state/circuit_MPS and rank-4 numpy.ndarray for
           circuit_MPO.
          -For holoMPS-based structures, the index ordering is: site, physical_out, bond-in, bond-out
           while for holoMPO-based structures, the index ordering is: physical-out, bond-out,
           physical-in, bond-in (with "in/out" referring to right canonical form ordering).
          -For MPO structures constructed by "thermal_state_class method", the unit cell tensor of MPO 
           network must be inserted as arg (e.g. Hamiltonian unit cell). In this case, the bulk tensors 
           would be rank-4 numpy.ndarray (consistent with final structure of MPO). For "tenpy"-method-based
           structures, the list of bulk tensors must be inserted (see TeNPy docs for more detail).     
          -Tracing over right boundary for holoMPS-based structures is appropriate for 
           holographic simulations. 
          -Set bdry_vecs to None by default for "tenpy" method. Set method to None for holoMPO-based 
           structures.
        """
        
        # for circuit-based structures:
        # both circuit and params must be included
        if network_type == 'random_state' or network_type == 'circuit_MPS' or network_type == 'circuit_MPO':
            
            l_uc = len(self) # length of unit-cell
            N = l_uc * L # number of sites
            unitary_list = L * self # list of unitaries
            
            # if network_type is set to random-holoMPS:
            if network_type == 'random_state':
                
                # defining tensor dimensions
                tensor = np.swapaxes(unitary_list[0][:,:,0,:],1,2) # change to MPS-based structure
                d = tensor[:,0,0].size # physical leg dimension (for random state)
                chi = tensor[0,:,0].size # bond leg dimension (for random state)
                
                if T == 0:
                    tensor_list1 = [np.swapaxes(unitary[:,:,0,:],1,2) for unitary in unitary_list]
                else:
                    # list of variational probability weights and random selections at each site
                    probs_list = L * thermal_state.prob_list(self,params,T)
                    random_list = [random.choice(p) for p in probs_list]
                    index_list = [probs_list[j].index(random_list[j]) for j in range(N)]
                    tensor_list1 = [np.swapaxes(unitary[:,:,j,:],1,2) for unitary,j in zip(unitary_list,
                                                                                           index_list)]      

            # if network_type is set to holoMPS:
            elif network_type == 'circuit_MPS':
                
                # defining tensor dimensions
                tensor = np.swapaxes(unitary_list[0][:,:,0,:],1,2) # change to MPS-based structure
                d = tensor[:,0,0].size # physical leg dimension (for random state)
                chi = tensor[0,:,0].size # bond leg dimension (for random state)
                # bulk tensors of holoMPS structure
                tensor_list1 = [np.swapaxes(unitary[:,:,0,:],1,2) for unitary in unitary_list]  

            # if network_type is set to circuit_MPO 
            # this option assumes original, circuit-based MPO structures (e.g. holoMPO)
            elif network_type == 'circuit_MPO':
                
                # defining tensor dimensions (consistent with rank-4 structures)
                # index ordering consistent with holographic-based MPO structures
                d = unitary_list[0][:,0,0,0].size # physical leg dimension (for MPO)
                chi = unitary_list[0][0,:,0,0].size # bond leg dimension (for MPO)
                tensor_list1 = unitary_list
            
            # testing boundary conditions 
            
            if network_type == 'random_state' or network_type == 'circuit_MPS':
                # specific to holoMPS-based structures
                
                if method == 'tenpy':
                    # based on previous circuit file
                    tensor_list1[0] = tensor_list1[0][:,0:1,:]
                    tensor_list1[-1] = tensor_list1[-1][:,:,0:1]
                    site = SpinHalfSite(None) 
                    M = MPS.from_Bflat([site]*N, tensor_list1, bc='finite', dtype=complex, form=None)
                    MPS.canonical_form_finite(M,renormalize=True,cutoff=0.0)
                
                elif method == 'thermal_state_class':
                    bdry = []
                    # if boundary vectors are not specified for holoMPS-based structures:     
                    # checking left boundary vector
                    # if left boundary vector not specified, set to (1,0,0,0...)
                    if np.array(bdry_vecs[0] == None).all():
                        bdry += [np.zeros(chi)]
                        bdry[0][0] = 1
                    else:
                        if bdry_vecs[0].size != chi:
                            raise ValueError('left boundary vector different size than bulk tensors')
                        bdry += [bdry_vecs[0]]
                
                    # checking right boundary vector (special to holoMPS-based structures)
                    if np.array(bdry_vecs[1] == None).all():
                        bdry += [None]
                    else:
                        if bdry_vecs[1].size != chi:
                            raise ValueError('right boundary vector different size than bulk tensors')
                        bdry += [bdry_vecs[1]]
                    
                    # if both boundary vectors are specified
                    for j in range(2):
                        if np.array(bdry_vecs[j] != None).all() and bdry_vecs[j].size == chi:
                            bdry.append(bdry_vecs[j]) 
                    
                    M = [[bdry[0]],tensor_list1,[bdry[1]]] # final state structure
                    
                else: 
                    raise ValueError('only one of "thermal_state_class" or "tenpy" options')
                        
            elif network_type == 'circuit_MPO': # specific to holoMPO-based structures
                bdry = []
                for j in range(2):
                    # if both boundary vectors are specified 
                    if np.array(bdry_vecs[j] != None).all() and bdry_vecs[j].size == chi:
                        bdry.append(bdry_vecs[j])
                    
                    # if boundary vectors not specified, set to (1,0,0,0...)
                    elif np.array(bdry_vecs[j] == None).all():
                        bdry += [np.zeros(chi)]
                        bdry[j][0] = 1
                    else:
                        if bdry_vecs[j].size != chi:
                            raise ValueError('boundary vectors different size than bulk tensors')
                        bdry += [bdry_vecs[j]]         
            
                M = [[bdry[0]],tensor_list1,[bdry[1]]] # final state structure
                      
        # if network_type is set to MPO: 
        # this option assumes genuine MPO_based structures (e.g. Hamiltonian MPO)  
        elif network_type == 'MPO':  
            
            if method == 'tenpy': # tenpy-based MPO
                site = SpinHalfSite(None)
                M = MPO.from_grids([site]*L, self, bc = 'finite', IdL=0, IdR=-1)  
                
            elif method == 'thermal_state_class':               
                # only bulk tensors of the main chain must be included (w/out params)
                tensor_list1 = [self]*L
                # testing boundary conditions
                bdry = []
                for j in range(2):
                    # if both boundary vectors are specified 
                    if np.array(bdry_vecs[j] != None).all() and bdry_vecs[j].size == chi_MPO:
                        bdry.append(bdry_vecs[j])
                
                    # if boundary vectors not specified, set to (1,0,0,0...)
                    elif np.array(bdry_vecs[j] == None).all():
                        bdry += [np.zeros(chi_MPO)]
                        bdry[j][0] = 1
                    else:
                        if bdry_vecs[j].size != chi_MPO:
                            raise ValueError('boundary vectors different size than bulk tensors')
                        bdry += [bdry_vecs[j]]
                        
                M = [[bdry[0]],tensor_list1,[bdry[1]]] # final state structure
            else: 
                raise ValueError('only one of "thermal_state_class" or "tenpy" options')              
        else:
            raise ValueError('only one of "random_state", "circuit_MPS", "circuit_MPO", "MPO" options')
            
        return M