import memories.memexp as mx

%matplotlib notebook
import matplotlib.pyplot as plt
import os as os
import numpy as np

"""
Explanation: Kinetic and energetic exploration of stored memories
Introduction, equilibrium relaxation
In this notebook, we use the memexp module to show some examples of memory explorations using energetic as well as kinetic exploratory mechanisms. To begin, we load the module (as well as other modules that will be useful).
End of explanation
"""


MySim = mx.Simulation(model = 'hopfield', N = 300, p=10, mu=3, seed=100, beta = 100., swipes=300, ds=1.)

"""
Explanation: We will start studying the simple case of relaxation to a stored memory using stochastic dynamics. That is, we use a stochastic Hopfield model. This will introduce us to the Simulation class, as well as the Network class
End of explanation
"""


MySim.run()

"""
Explanation: Above we have created a simulation object for a system with $N=500$ neurons and $p=10$ patterns. We have chosen patter $\mu=3$ as the target pattern, which means that the original state contains an overlap of 50 neurons with the target state pattern. Since we have fixed the inverse temperature to a large value $\beta=100$ the system will behave deterministically, as in Hopfield's original paper.  We will run the simulation for $10^2$ swipes, which means $500\times 10^2$ time steps, and we will save the state fo the system every $ds=1$ swipes.
End of explanation
"""


MySim.net.overlaps()

"""
Explanation: We can see that the system converged by checking the last state of the network class inside the simulation:
End of explanation
"""


import pickle

net = pickle.load( open( MySim.path + '/net.pkl','rb') )

"""
Explanation: Graphically the evolution can be seen by loading the stored data and plotting the overlaps over time. First we load the network class, which contains the network parameters and useful functions.
End of explanation
"""


neuron_t = np.zeros_like(net.N)
file_list =[ x for x in os.listdir(MySim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: We now create the variables where we will store the overlaps.
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MySim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


MyKinSim = mx.Simulation(model = 'kinetic', N = 300, p = 8, k = 3,  seed=250, beta = 5., swipes=100*5, ds=1., lamda = 1.5, tau=150.*300)

"""
Explanation: Kinetic memory exploration
We now generate a simulation class for the kinetic dynamics (model = 'kinetic'), which runs over a longer time $T$ (swipes = 300). We choose values for the delay time $\tau$ (tau = 50.*300) and the non-equilibrium driving $\lambda$ (lambda=1.5). The length of the encoded sequence is k=3.
End of explanation
"""


MyKinSim.run()

"""
Explanation: We run the simulation
End of explanation
"""


net = pickle.load( open( MyKinSim.path + '/net.pkl','rb') )

neuron_t = np.zeros_like(MyKinSim.N)
file_list = [ x for x in os.listdir(MyKinSim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: Before evaluating the simulaion results, we create the variables where we will store the overlaps
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MyKinSim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


from matplotlib.ticker import MultipleLocator, FormatStrFormatter

ax = plt.subplot(111)
plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
plt.axis([0, MyKinSim.swipes, -.4, 1.2])

for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

ax.xaxis.set_major_locator(MultipleLocator(50))
ax.xaxis.grid(True,'major')

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


import tools.evaluation as ev

ev.my_score((net.k, net.p), [overlaps_t], cutoff = 0.5, time_retrieved = 0.10 * net.tau / net.N)

"""
Explanation: Test of analysis
End of explanation
"""


reload(mx)
MyEnSim = mx.Simulation(model = 'energetic', N = 300, p=10, k = 3, seed=250, beta = 3., swipes=15*100, ds=1., tau=150.*300)

"""
Explanation: Energetic memory exploration
We  generate a simulation class for the energetic dynamics case (model = 'energetic'), keeping all values equal to the kinetic case.
End of explanation
"""


MyEnSim.run()

"""
Explanation: We run the simulation, which is now slower. The reason is that for each time step the hebbian matrix has to be re-calculated.
End of explanation
"""


net = pickle.load( open( MyEnSim.path + '/net.pkl','rb') )

neuron_t = np.zeros_like(net.N)
file_list = [ x for x in os.listdir(MyEnSim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: As before, we create the variables where the results will be stored
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MyEnSim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

import tools.evaluation as ev

ev.my_score((net.k, net.p), [overlaps_t], cutoff = 0.5, time_retrieved = 0.1 * net.tau / net.N)

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


reload(mx)
MyEnSim = mx.Simulation(model = 'energetic-modified', N = 300, p=20, k = 3, seed=250, beta = 3., swipes=5*100, ds=1., tau=150.*300)

"""
Explanation: Modified energetic memory exploration
We  generate a simulation class for the energetic dynamics case (model = 'energetic'), keeping all values equal to the kinetic case.
End of explanation
"""


MyEnSim.run()

"""
Explanation: We run the simulation, which is now slower. The reason is that for each time step the hebbian matrix has to be re-calculated.
End of explanation
"""


net = pickle.load( open( MyEnSim.path + '/net.pkl','rb') )

neuron_t = np.zeros_like(net.N)
file_list = [ x for x in os.listdir(MyEnSim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: As before, we create the variables where the results will be stored
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MyEnSim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


reload(mx)
MyKinSim = mx.Simulation(model = 'kinetic', N = 300, p = 7, k = 10, correlation = 10, seed=250, beta = 5., swipes = 100*15, ds = 1., lamda = 1.5, tau=150.*300)

"""
Explanation: Kinetic exploration of correlated memories
We now generate a simulation class for the kinetic dynamics (model = 'kinetic'), which runs over a longer time $T$ (swipes = 300). We choose values for the delay time $\tau$ (tau = 50.*300) and the non-equilibrium driving $\lambda$ (lambda=1.5).
End of explanation
"""


MyKinSim.run()

"""
Explanation: We run the simulation
End of explanation
"""


net = pickle.load( open( MyKinSim.path + '/net.pkl','rb') )

neuron_t = np.zeros_like(net.N)
file_list = [ x for x in os.listdir(MyKinSim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: Before evaluating the simulaion results, we create the variables where we will store the overlaps
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MyKinSim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


reload(mx)
MyEnSim = mx.Simulation(model = 'energetic', N = 300, p = 10, k = 7, correlation = 30, seed=298, beta = 5., swipes = 100*15, ds=1., tau=150.*300)

"""
Explanation: Energetic exploration of correlated memories
We  generate a simulation class for the energetic dynamics case (model = 'energetic'), keeping all values equal to the kinetic case.
End of explanation
"""


MyEnSim.run()

"""
Explanation: We run the simulation, which is now slower. The reason is that for each time step the hebbian matrix has to be re-calculated.
End of explanation
"""


net = pickle.load( open( MyKinSim.path + '/net.pkl','rb') )

neuron_t = np.zeros_like(net.N)
file_list = [ x for x in os.listdir(MyEnSim.path) if x[0]=='S' ]
overlaps_t = np.zeros((len(file_list), net.p))

"""
Explanation: As before, we create the variables where the results will be stored
End of explanation
"""


for i in range(len(file_list)):
    sigma  = np.load(MyEnSim.path + '/' + file_list[i])
    net.neurons = sigma
    overlaps_t[i,:] = net.overlaps()

"""
Explanation: We can now read the files and calculate the overlaps over time
End of explanation
"""


plt.ylabel('overlaps, $m^{\mu}$',fontdict={'fontsize':20})
plt.xlabel('time, ',fontdict={'fontsize':20})
for i in range(len(overlaps_t[0,:])):
    plt.plot(overlaps_t[:,i],label='%d' % (i))
plt.legend(title='overlaps')

import tools.evaluation as ev

ev.my_score((net.k, net.p), [overlaps_t], cutoff = 0.5, time_retrieved = 0.1 * net.tau / net.N)

"""
Explanation: Finally, we plot the overlaps
End of explanation
"""


