create_model.py 4.23 KB
Newer Older
mgassner's avatar
...  
mgassner committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import lattice_symmetries as ls
import numpy as np
import yaml

from entropy_new import idxs_rearrangement

# Spin operators
sigma_x = np.array([[0., 1.], [1., 0.]])
sigma_y = np.array([[0., -1.0j], [1.0j, 0.]])
sigma_z = np.diag([1., -1.])
sigma_0 = np.diag([1., 1.])
sigma_p = sigma_x + 1j * sigma_y
sigma_m = sigma_x - 1j * sigma_y

def create_2spin_matrix(model_name, param):
    """
    :model_name: xxz or tfim
    :param: delta_over_J or h_over_J for the respective models
    returns 2 spin hamiltonian
    """
    if model_name == 'xxz':
        return (0.5 * (np.kron(sigma_p, sigma_m) + np.kron(sigma_m, sigma_p)) +
                param * np.kron(sigma_z, sigma_z)).astype('float64').tolist()
    elif model_name == 'tfim':
        return ( np.kron(sigma_z, sigma_z) - 0.5*param*(np.kron(sigma_x, sigma_0) + np.kron(sigma_0, sigma_x))).astype('float64').tolist()
    elif model_name == 'txxx':
        return ((0.5 * (np.kron(sigma_p, sigma_m) + np.kron(sigma_m, sigma_p)) + np.kron(sigma_z, sigma_z))
                + 0.5*param*(np.kron(sigma_x, sigma_0) + np.kron(sigma_0, sigma_x))).astype('float64').tolist()
    else: 
        raise NameError

def generate_symmetries(model_name, number_spins, periodic):
    symmetries = []
    sites = np.arange(number_spins)
    # Momentum in x direction with eigenvalue π
    if periodic: 
mgassner's avatar
mgassner committed
37
        T = (sites + 1) % number_spins
mgassner's avatar
...  
mgassner committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
        symmetries.append(ls.Symmetry(T, sector=number_spins // 2))
    # Parity with eigenvalue π
    P = sites[::-1]
    symmetries.append(ls.Symmetry(P, sector=1))
    return symmetries

def create_edges(number_spins, periodic):
    edges = [(i, i+1) for i in range(number_spins-1)]
    if periodic: 
        edges.append((number_spins-1, 0))
    return edges

class spin_model:
    #constructor
mgassner's avatar
mgassner committed
52
    def __init__(self, model_name, number_spins, periodic, param, hamming_weight, use_symmetries=False, spin_inversion=None):
mgassner's avatar
...  
mgassner committed
53
54
        self.__number_spins = number_spins
        self.__periodic = periodic
mgassner's avatar
mgassner committed
55
56
        self.__symmetries = []
        self.__spin_inversion = spin_inversion
mgassner's avatar
...  
mgassner committed
57
        if use_symmetries:
mgassner's avatar
mgassner committed
58
            self.__symmetries = generate_symmetries(model_name, number_spins, periodic)
mgassner's avatar
...  
mgassner committed
59
60
61
62
        self.__name = model_name
        self.__hamming_weight = hamming_weight
        self.basis = None
        self.create_basis()
mgassner's avatar
mgassner committed
63
64
65
        #creating Hamiltonian
        self.__matrix = create_2spin_matrix(model_name, param)
        self.edges = create_edges(number_spins, periodic)
mgassner's avatar
...  
mgassner committed
66
67
68
69
70
71
72
73
74
75
76
77
78
        self.hamiltonian = None
        self.create_hamiltonian()
        self.eigenvalues = None
        self.eigenstates = None
        
    def print_characterisitcs(self):
        print("MODEL:           ", self.__name)
        print("Number of Spins: ", self.__number_spins)
        print("Periodic:        ", self.__periodic)
        print("2-spin-Matrix    ", self.__matrix)

    def create_basis(self):
        # Constructing the basis
mgassner's avatar
mgassner committed
79
        symmetry_group = ls.Group(self.__symmetries)
mgassner's avatar
...  
mgassner committed
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        self.basis = ls.SpinBasis(symmetry_group, number_spins=self.__number_spins, 
                            hamming_weight=self.__hamming_weight, spin_inversion=self.__spin_inversion)
        self.basis.build()
        print ("Hilbert space dimension is {}".format(self.basis.number_states))

    def create_hamiltonian(self):
        self.hamiltonian = ls.Operator(self.basis, [ls.Interaction(self.__matrix, self.edges)])
    
    def update_basis_and_hamiltonian(self, rearrangement):
        # TODO: find out if I need to update edges as well!!!
        new_states = idxs_rearrangement(self.basis.states, rearrangement)
        self.basis.build(representatives=new_states)
        self.hamiltonian = ls.Operator(self.basis, [ls.Interaction(self.__matrix, self.edges)])

    def compute_ew_and_ev(self, print_gs_energy=True):
        self.eigenvalues, self.eigenstates = ls.diagonalize(self.hamiltonian, k=1)
        if print_gs_energy:
            print("Ground state energy is {:.10f}".format(self.eigenvalues[0]))
    
    
    # Getters for private variables 
    def number_spins(self):
        return self.__number_spins
    def periodic(self):
        return self.__periodic
    def hamming_weight(self):
        return self.__hamming_weight
    def matrix(self):
        return self.__matrix
    # destructor
    def __del__(self):
        del self