Commit 3fdbebc5 authored by mgassner's avatar mgassner
Browse files

added computation of MI

parent 799e42bf
......@@ -2,8 +2,6 @@ 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.]])
......@@ -84,13 +82,13 @@ class spin_model:
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:
......
......@@ -37,7 +37,8 @@ def sector_dm(trace_states, sub_states, amplitudes, spin_inversion):
distinct_sub_states = list(set(sub_states))
distinct_trace_states = list(set(trace_states))
n = len(distinct_sub_states)
print(trace_states, sub_states)
# print('Trace states:', trace_states)
# print('Sub_states:', sub_states)
matrix = np.zeros((n,n))
for state in distinct_trace_states:
......@@ -54,31 +55,41 @@ def sector_dm(trace_states, sub_states, amplitudes, spin_inversion):
matrix += matrix_add
return matrix
def reduced_dm(sub_dim, dim, hamming, amplitudes, states_of_amplitudes, spin_inversion=False):
def reduced_dm(sub_dim, dim, hamming, amplitudes, states_of_amplitudes, spin_inversion=None, first_trace_spin=None):
"""
:sub_dim: amount of spins in the subsystem (uint)
:dim: amount of spins of total system (uint)
:hamming: amount of upspins of total system(uint or None)
:amplitudes: amplitudes of input state (1d-array of floats)
:states_of_amplitudes: state which belongs to amplitude (1d-array of uints)
:first_spin: first spin that's traced out; start counting at 0 (rightmost spin)!
:return: List of sector density matrices
"""
if spin_inversion is not None:
dim -= 1
if first_trace_spin is None:
sub_states = states_of_amplitudes >> (dim - sub_dim)
trace_states = states_of_amplitudes & (2**(dim-sub_dim)-1)
trace_states = states_of_amplitudes & (2**(dim-sub_dim) - 1)
else:
right_sub_states = states_of_amplitudes & (2**first_trace_spin - 1)
left_sub_states = states_of_amplitudes >> (dim - (sub_dim - first_trace_spin))
sub_states = right_sub_states + (left_sub_states << first_trace_spin)
trace_states = states_of_amplitudes & (2**(dim - sub_dim + first_trace_spin) - 2**first_trace_spin )
trace_states >>= first_trace_spin
hamming_of_sub_states = np.array([_hamming_weight(n) for n in sub_states])
#print(sub_states, trace_states, hamming_of_sub_states, amplitudes)
# print(sub_states, trace_states, hamming_of_sub_states, amplitudes)
rho = []
if hamming is None:
rho.append(sector_dm(trace_states, sub_states, amplitudes, spin_inversion))
else:
for sub_hamming in range(max(0, hamming - (dim - sub_dim)), min(hamming, sub_dim) + 1):
print('Sub hamming is', sub_hamming)
# print('Sub hamming is', sub_hamming)
indices = np.where(hamming_of_sub_states == sub_hamming)[0].tolist()
sector_sub_states = [sub_states[i] for i in indices]
sector_trace_states = [trace_states[i] for i in indices]
#print(sector_trace_states)
# print(sector_trace_states)
sector_amplitudes = [amplitudes[i] for i in indices]
rho.append(sector_dm(sector_trace_states, sector_sub_states, sector_amplitudes, spin_inversion))
return rho
......@@ -105,27 +116,23 @@ def compute_entropy(rho):
entropy -= lambda_log_lambda(spectrum).sum()
return entropy
def idxs_rearrangement(old_states, rearrangement):
"""
Rearranges the old states according to the spin number list rearrangement
:old_states: index of old states
:rearrangement: list of new spin positions
:return: index of rearranged spins
"""
new_states = []
batch_size = 1000000
number_spins = len(rearrangement)
# Rearranges the columns in the old spin matrix and computes the index of the rearranged spins
for i in range(len(old_states) // batch_size + 1):
print(i * 1. / (len(old_states) // batch_size + 1), "not zero if len(old_states) is large", flush=True)
new_states.append(
spin_to_index(
index_to_spin(
old_states[i * batch_size:np.min([(i + 1) * batch_size, len(old_states)])], number_spins
)[:, rearrangement].astype(bool), number_spins
)
)
return np.concatenate(new_states)
\ No newline at end of file
def compute_MI(sub_dim, dim, hamming, amplitudes, states_of_amplitudes, spin_inversion=None, first_trace_spin=None):
# so far left and right sub-dimension is the same and equal to sub_dim
assert (first_trace_spin + sub_dim) <= dim and first_trace_spin >= sub_dim
first_trace_spin_left = first_trace_spin + (dim - 2*sub_dim)
#S_AB:
print('--------------A and B---------------')
rhos_AB = reduced_dm(sub_dim*2, dim, hamming, amplitudes, states_of_amplitudes,
spin_inversion=spin_inversion, first_trace_spin=first_trace_spin)
S_AB = compute_entropy(rhos_AB)
#S_B (right)
print('-----------------B------------------')
rhos_B = reduced_dm(sub_dim, dim, hamming, amplitudes, states_of_amplitudes,
spin_inversion=spin_inversion, first_trace_spin=first_trace_spin)
S_B = compute_entropy(rhos_B)
#S_A (left)
print('-----------------A------------------')
rhos_A = reduced_dm(sub_dim, dim, hamming, amplitudes, states_of_amplitudes,
spin_inversion=spin_inversion, first_trace_spin=first_trace_spin_left)
S_A = compute_entropy(rhos_A)
return [S_A, S_B, S_AB]
\ No newline at end of file
......@@ -2,13 +2,17 @@ from heisenberg import test_xxz, test_area_law
from tfim import test_tfim, test_area_law_tfim
from package_fails import test_symmetries_xxx
from ls_example_from_github import github_test
from mutual_information import test_mutual_information
if __name__ == "__main__":
#test_xxz()
#test_area_law()
#test_area_law_tfim()
#test_tfim()
test_symmetries_xxx()
#test_symmetries_xxx('tfim')
test_mutual_information()
"""print('------------------------------------------------')
print('---With symmetries and spin inversion---')
github_test()
......
import numpy as np
import yaml
import time
import matplotlib.pyplot as plt
from create_model import spin_model
from entropy_new import compute_MI, compute_entropy, reduced_dm
def test_mutual_information():
model_name = 'xxz'
number_spins = 10
periodic = False
spin_inversion = None
param = 1.0
if param < -1.0:
hamming_weight = None
else:
hamming_weight = number_spins // 2
model = spin_model(model_name=model_name, number_spins=number_spins, periodic=periodic,
param=param, hamming_weight=hamming_weight ,spin_inversion=spin_inversion)
model.compute_ew_and_ev()
print('EIGENSTATE at h/J = ', param, 'is: ', model.eigenstates[:,0])
sub_dim = 4
first_trace_spin = 4
number_spins = model.number_spins()
basis_states = model.basis.states
gs = model.eigenstates[:,0]
print('Number Spins: ', model.basis.number_spins)
print('States', model.basis.states)
print('Sub Dimension is ', sub_dim)
entropies = compute_MI(sub_dim, number_spins, hamming_weight, gs, basis_states, spin_inversion=None, first_trace_spin=first_trace_spin)
MI = entropies[0] + entropies[1] - entropies[2]
print(MI)
print(entropies)
print('--------------------Test-----------------------')
rhos4 = reduced_dm(4, number_spins, hamming_weight, gs, basis_states)
rhos8 = reduced_dm(4, number_spins, hamming_weight, gs, basis_states)
print(compute_entropy(rhos4), compute_entropy(rhos8))
\ No newline at end of file
......@@ -6,24 +6,23 @@ import matplotlib.pyplot as plt
from create_model import spin_model
from entropy_new import _hamming_weight, reduced_dm, compute_entropy
def test_symmetries_xxx():
model_name = 'xxz'
def test_symmetries_xxx(model_name='xxz'):
number_spins = [8,10,12]
periodic = True
param = 1.0
print('Test if gs-energy stays the same if we use symmetries for the ls package:')
for length in number_spins:
hamming_weight = length // 2
hamming_weight = length // 2 if model_name=='xxz' else None
print('\n' , '------- Number spins is: ' + str(length) + '-----------' )
print('---With symmetries and spin inversion---')
model = spin_model(model_name=model_name, number_spins=length, periodic=periodic,
param=param, hamming_weight=hamming_weight, use_symmetries=True, spin_inversion=-1)
param=param, hamming_weight=hamming_weight, use_symmetries=True, spin_inversion=-1 if model_name=='xxz' else 1)
model.compute_ew_and_ev()
#print('EIGENSTATE at Delta/J = ', param, 'is: ', model.eigenstates[:,0])
del model
print('---Without symmetries, but spin inversion---')
model = spin_model(model_name=model_name, number_spins=length, periodic=periodic,
param=param, hamming_weight=hamming_weight, spin_inversion=-1)
param=param, hamming_weight=hamming_weight, spin_inversion=-1 if model_name=='xxz' else 1)
model.compute_ew_and_ev()
#print('EIGENSTATE at Delta/J = ', param, 'is: ', model.eigenstates[:,0])
del model
......
Supports Markdown
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