#This is the class for construcing FSAs. The individual CAs (both inputs #and states) run at 5 ms. There may be problems if they run faster or slower. #The class enables you to build 2 input FSAs. You can't go from state A #to state B, then directly back. #There are test functions at the end. import nest as nest import pyNN.spiNNaker as spinn import numpy as np from nealCoverClass import NealCoverFunctions class FSAHelperFunctions: def __init__(self, simName): self.simulator = simName self.neal = NealCoverFunctions(self.simulator) self.initParams() #FSA Parmaeters def initParams(self): self.CA_SIZE = 5 #This will (almost certainly) not work with a #different sized CA. if self.simulator == "nest": self.INPUT_WEIGHT = 36.0 self.INTRA_CA_WEIGHT = 8.0 self.HALF_ON_WEIGHT = 2.0 self.CA_STOPS_CA_WEIGHT = -20.0 self.CELL_PARAMS = {'V_reset': -70.0, 't_ref':2.0, 'tau_syn_ex':5.0, 'g_L':40.0} elif self.simulator == 'spinnaker': self.INPUT_WEIGHT = 0.1 self.INTRA_CA_WEIGHT = 0.03 self.HALF_ON_WEIGHT = 0.0017 self.CA_STOPS_CA_WEIGHT = -0.3 self.CELL_PARAMS = {'v_thresh':-55.0, 'v_reset' : -70.0, 'tau_refrac': 2.0 , 'tau_syn_E': 5.0, 'v_rest' : -65.0,'i_offset':0.0} #--------Finite State Automata Functions ------------ #-- Function to ignite a state from a spike source #-- Uses INPUT_WEIGHT def turnOnState(self,spikeSource, start, neurons): connector = [] for toOffset in range (0,self.CA_SIZE): toNeuron = toOffset + (start*self.CA_SIZE) connector = connector + [(0,toNeuron,self.INPUT_WEIGHT, self.neal.DELAY)] self.neal.nealProjection(spikeSource, neurons, connector,'excitatory') #---Create a CA that will persistently fire. #-- Assumes neurons in the same population #-- Uses INTRA_CA_WEIGHT def makeCA(self,start, neurons): #print 'makeCA connector = [] for fromOffset in range (0,self.CA_SIZE): fromNeuron = fromOffset + (start*self.CA_SIZE) for toOffset in range (0,self.CA_SIZE): toNeuron = toOffset + (start*self.CA_SIZE) if (toNeuron != fromNeuron): connector = connector + [(fromNeuron,toNeuron, self.INTRA_CA_WEIGHT, self.neal.DELAY)] self.neal.nealProjection(neurons,neurons,connector,'excitatory') #-- Two states are needed to turn on a third. #-- This connects one of the inputs to the the third. #-- Uses HALF_ON_WEIGHT def stateHalfTurnsOnState(self,start, finish, neurons): connector = [] #uses HALF_ON_WEIGHT for fromOffset in range (0,self.CA_SIZE): fromNeuron = fromOffset + (start*self.CA_SIZE) for toOffset in range (0,self.CA_SIZE): toNeuron = toOffset + (finish*self.CA_SIZE) if (toNeuron != fromNeuron): connector=connector+[(fromNeuron,toNeuron, self.HALF_ON_WEIGHT, self.neal.DELAY)] self.neal.nealProjection(neurons,neurons,connector,'excitatory') #-- One State or other CA turns off another #-- Uses CA_STOPS_CA_WEIGHT def stateTurnsOffState(self,start, finish, neurons): connector = [] for fromOffset in range (0,self.CA_SIZE): fromNeuron = fromOffset + (start*self.CA_SIZE) for toOffset in range (0,self.CA_SIZE): toNeuron = toOffset + (finish*self.CA_SIZE) if (toNeuron != fromNeuron): connector = connector + [(fromNeuron,toNeuron, self.CA_STOPS_CA_WEIGHT, self.neal.DELAY)] self.neal.nealProjection(neurons,neurons,connector,'inhibitory') #------test functions #initialize the simulator. def testInit(self): if self.simulator == "nest": nest.ResetKernel() nest.SetKernelStatus({'resolution':self.neal.DELAY}) elif self.simulator == 'spinnaker': #print "spin" spinn.setup(timestep=self.neal.DELAY,min_delay=self.neal.DELAY, max_delay=self.neal.DELAY, debug=0) def testCreateTwoInputs(self): inputSpikeTimes0 = [10.0] inputSpikeTimes1 = [50.0] if self.simulator == "nest": spikeGen0 = nest.Create('spike_generator', #params = {'spike_times': np.array([10.0,15.0, 20.0,25.0,30.0])}) params = {'spike_times': np.array(inputSpikeTimes0)}) spikeGen1 = nest.Create('spike_generator', params = {'spike_times': np.array(inputSpikeTimes1)}) spikeDet = nest.Create('spike_detector') elif self.simulator == 'spinnaker': spikeArray0 = {'spike_times': [inputSpikeTimes0]} spikeGen0=spinn.Population(1,spinn.SpikeSourceArray,spikeArray0, label='inputSpikes_0') spikeArray1 = {'spike_times': [inputSpikeTimes1]} spikeGen1=spinn.Population(1, spinn.SpikeSourceArray, spikeArray1, label='inputSpikes_1') else: print "bad simulator for spike generator" return [spikeGen0,spikeGen1] def testCreateNeurons(self): if self.simulator == "nest": #in python Models() to see all the models including these #print GetDefaults (neuronType) cells = nest.Create("iaf_cond_exp",n=15,params = self.CELL_PARAMS) elif self.simulator == 'spinnaker': cells=spinn.Population(100,spinn.IF_cond_exp,self.CELL_PARAMS) return cells def testCreateRecorder(self): spikeDet = 0 if self.simulator == "nest": spikeDet = nest.Create('spike_detector') #with spinnaker you can just set record on the cells return spikeDet def testSetupRecording(self,cells, spikeDetector): if self.simulator == "nest": nest.Connect(cells,spikeDetector) elif self.simulator == 'spinnaker': cells.record() def test3StateFSA(self, firstSpikeGenerator, secondSpikeGenerator, stateCells): #Build the FSA self.turnOnState(firstSpikeGenerator,0,stateCells) self.turnOnState(secondSpikeGenerator,1,stateCells) self.makeCA(0, stateCells) self.makeCA(1, stateCells) self.makeCA(2, stateCells) self.stateHalfTurnsOnState(0,2,stateCells) self.stateTurnsOffState(2,0,stateCells) #comment below out to check state 0 alone does not turn on state 2 self.stateHalfTurnsOnState(1,2,stateCells) self.stateTurnsOffState(2,1,stateCells) def testRunFSA(self,duration): if self.simulator == "nest": nest.Simulate(duration) elif self.simulator == 'spinnaker': spinn.run(duration) def testPrintResults(self,spinnCells,nestRecorder): #print if self.simulator == "nest": spikes = nest.GetStatus(nestRecorder) test = spikes[0]['events']['times'] print 'spikes', test elif self.simulator == 'spinnaker': spinnCells.printSpikes('temp.sp')