def set_up_network(self, turn_on_learning=True): net = nx.NxNet() # Define compartment prototype(all neurons are the same) if turn_on_learning is True: comProto = nx.CompartmentPrototype(vThMant=10, compartmentCurrentDecay=4096, compartmentVoltageDecay=0, enableSpikeBackprop=1, enableSpikeBackpropFromSelf=1) elif turn_on_learning is False: comProto = nx.CompartmentPrototype(vThMant=10, compartmentCurrentDecay=4096, compartmentVoltageDecay=0) else: print('ERROR! turn_on_learning can only be True or False.') # Create compartment group for different layers comGrp = {} comGrp['inputGrp'] = net.createCompartmentGroup(size=self.num_input, prototype=comProto) comGrp['hiddenGrp'] = net.createCompartmentGroup(size=self.num_hidden, prototype=comProto) comGrp['outputGrp'] = net.createCompartmentGroup(size=self.num_output, prototype=comProto) # Create spike generator as teaching neurons comGrp['inputGen'] = net.createSpikeGenProcess(numPorts=self.num_input) comGrp['outputGen'] = net.createSpikeGenProcess(numPorts=self.num_output) # Define learning rule lr = net.createLearningRule(dw='2*x1*y0', x1Impulse=40, x1TimeConstant=4, y1Impulse=40, y1TimeConstant=4, tEpoch=2) # Define connection prototype if turn_on_learning is True: connProto = nx.ConnectionPrototype(enableLearning=1, learningRule=lr) connTeachingProto = nx.ConnectionPrototype(enableLearning=0) elif turn_on_learning is False: connProto = nx.ConnectionPrototype(enableLearning=0) else: print('ERROR! turn_on_learning can only be True or False.') # Create connections conn = {} if turn_on_learning is True: conn['inputGen_inputGrp'] = comGrp['inputGen'].connect(comGrp['inputGrp'], prototype=connTeachingProto, weight=np.array([[255, 0], [0, 255]])) conn['inputGrp_hiddenGrp'] = comGrp['inputGrp'].connect(comGrp['hiddenGrp'], prototype=connProto, weight=np.ones((4, 2), dtype=int)*50) conn['hiddenGrp_outputGrp'] = comGrp['hiddenGrp'].connect(comGrp['outputGrp'], prototype=connProto, weight=np.ones((1, 4), dtype=int)*50) conn['outputGen_outputGrp'] = comGrp['outputGen'].connect(comGrp['outputGrp'], prototype=connTeachingProto, weight=np.array([255])) elif turn_on_learning is False: conn['inputGen_inputGrp'] = comGrp['inputGen'].connect(comGrp['inputGrp'], prototype=connProto, weight=np.array([[255, 0], [0, 255]])) conn['inputGrp_hiddenGrp'] = comGrp['inputGrp'].connect(comGrp['hiddenGrp'], prototype=connProto, weight=self.weight_1) conn['hiddenGrp_outputGrp'] = comGrp['hiddenGrp'].connect(comGrp['outputGrp'], prototype=connProto, weight=self.weight_2) else: print('ERROR! turn_on_learning can only be True or False.') return net, comGrp, conn
def connectGCToMC(self, excDelay=20, inhDelay=20): """ creates the GC->MC inhibitory connections """ ConnGroup = namedtuple("ConnGroup", "positive negative") self.gcToMCConnGrpsPerCore = list() self.inh2ExcConnProbesPos = list() self.inh2ExcConnProbesNeg = list() iSTDPLearningRule = self.net.createLearningRule( dd='4*2^-7*x1*y0 - 4*2^-7*y1*x0 + 4*x0 - 4*y0', x1Impulse=127, x1TimeConstant=25, y1Impulse=127, y1TimeConstant=25, r1Impulse=127, r1TimeConstant=25, tEpoch=40) for coreIdx in range(self.numColumns): excWgts = np.zeros((self.numMCsPerColumn, self.numGCsPerColumn), int) excDlys = np.ones_like(excWgts) * excDelay inhWgts = np.zeros_like(excWgts) inhDlys = np.ones_like(excDlys) * inhDelay excConnProtoBox = nx.ConnectionPrototype( numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE, enableLearning=1, learningRule=iSTDPLearningRule) inhConnProtoBox = nx.ConnectionPrototype( numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE, enableLearning=1, learningRule=iSTDPLearningRule) posConnGrp = self.net.createConnectionGroup( src=self.gcNeuronGrpPerCoreList[coreIdx], dst=self.mcSomaGrpPerCoreList[coreIdx], prototype=excConnProtoBox, weight=excWgts, delay=excDlys) negConnGrp = self.net.createConnectionGroup( src=self.gcNeuronGrpPerCoreList[coreIdx], dst=self.mcSomaGrpPerCoreList[coreIdx], prototype=inhConnProtoBox, weight=inhWgts, delay=inhDlys) self.gcToMCConnGrpsPerCore.append( ConnGroup(positive=posConnGrp, negative=negConnGrp))
def _add_prototypes(self): or_w = self.blocks['reward_buffer'].get_synproto().weight and_w = self.blocks['reward_gate'].get_synproto().weight self.s_prototypes['or_delayed'] = nx.ConnectionPrototype(weight=or_w, delay=3) self.s_prototypes['or_delayed_long'] = nx.ConnectionPrototype( weight=or_w, delay=6) self.s_prototypes['and_delayed'] = nx.ConnectionPrototype(weight=and_w, delay=5)
def connectInhibitoryGCToExcitatoryMCNeurons(self): ConnGroup = namedtuple("ConnGroup", "positive negative") self.inh2ExcConnGroups = list() for coreIdx in range(self.numCores): """ wgts = np.zeros((self.numMCsPerCore, self.numGCsPerCore), int) delays = np.ones(wgts.shape) """ if not self.debug: excWgts = self.inhGCToExcMCWeights[0, coreIdx] excDlys = self.inhGCToExcMCDelays[0, coreIdx] inhWgts = self.inhGCToExcMCWeights[1, coreIdx] inhDlys = self.inhGCToExcMCDelays[1, coreIdx] else: wgts = self.inhGCToExcMCWeights dlys = self.inhGCToExcMCDelays excWgts = np.ones_like(wgts[0, coreIdx]) excDlys = np.ones_like(dlys[0, coreIdx]) * 2 inhWgts = np.ones_like(wgts[1, coreIdx]) * -1 inhDlys = np.ones_like(dlys[1, coreIdx]) * 1 excConnProtoBox = nx.ConnectionPrototype( numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) inhConnProtoBox = nx.ConnectionPrototype( numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) posConnGrp = self.net.createConnectionGroup( src=self.gcNeuronGrpPerCoreList[coreIdx], dst=self.mcNeuronGrpPerCoreList[coreIdx], prototype=excConnProtoBox, connectionMask=(excWgts > 0), weight=excWgts, delay=excDlys) negConnGrp = self.net.createConnectionGroup( src=self.gcNeuronGrpPerCoreList[coreIdx], dst=self.mcNeuronGrpPerCoreList[coreIdx], prototype=inhConnProtoBox, connectionMask=(inhWgts < 0), weight=inhWgts, delay=inhDlys) self.inh2ExcConnGroups.append( ConnGroup(positive=posConnGrp, negative=negConnGrp))
def connectInputNeurons(self, inputs, num, connectionMask=1, weight=10): """ connection Presynaptic neurons with astrocyte :param inputs: CompartmentGroup :param num: input number :param connectionMask: int for full connection, numpy for connection :param weight: int for full connection, numpy for connection :return: """ assert (isinstance(inputs, nx.CompartmentGroup) or isinstance(inputs, BasicSpikeGen)) mask = connectionMask w = weight if isinstance(mask, int): mask = np.int_(np.ones((1, num))) if isinstance(w, int): w = np.int_(np.ones((1, num))) * w assert isinstance(mask, np.ndarray) assert isinstance(w, np.ndarray) assert (mask.shape[1] == num) assert (w.shape[1] == num) """ Create connection """ input_conn_prototype = nx.ConnectionPrototype(numWeightBits=8, signMode=2) self.astrocyte_input_conn = inputs.connect( self.astrocyte_setup[0], prototype=input_conn_prototype, connectionMask=mask, weight=w)
def connectOutputNeurons(self, outputs, num, connectionMask=1, weight=30): """ connection Postsynaptic neurons with astrocyte :param outputs: CompartmentGroup :param num: output number :param connectionMask: int for full connection, numpy for connection :param weight: int for full connection, numpy for connection :return: """ assert isinstance(outputs, nx.CompartmentGroup) mask = connectionMask w = weight if isinstance(mask, int): mask = np.int_(np.ones((num, 1))) if isinstance(w, int): w = np.int_(np.ones((num, 1))) * w assert isinstance(mask, np.ndarray) assert isinstance(w, np.ndarray) assert (mask.shape[0] == num) assert (w.shape[0] == num) """ Create connection """ output_conn_prototype = nx.ConnectionPrototype(numWeightBits=8, signMode=2) self.astrocyte_output_conn = self.astrocyte_setup[-1].connect( outputs, prototype=output_conn_prototype, connectionMask=mask, weight=w)
def _build_input_gen(self, nb_neurons, input_dim, nb_of_conn_per_input): if self.get_power_eff: # Create an input neuron for power/time efficiency as spike injector are time costly # That will spike at some specific frequency neuron_spikegen_param = nx.CompartmentPrototype( biasMant=self.power_eff_input_freq, biasExp=6, compartmentVoltageDecay=0, vThMant=1000, ) self.spike_gen = self.net.createCompartmentGroup( size=input_dim, prototype=neuron_spikegen_param ) else: self.spike_gen = self.net.createSpikeGenProcess(numPorts=input_dim) input_proto = nx.ConnectionPrototype(weight=128, weightExponent=6,) pre = np.arange(input_dim * nb_of_conn_per_input) % input_dim post = ( np.random.permutation(max(input_dim, nb_neurons) * nb_of_conn_per_input)[ : input_dim * nb_of_conn_per_input ] % nb_neurons ) connection_mask = np.zeros((input_dim, nb_neurons), dtype=np.int) connection_mask[pre, post] = 1 connection_mask = coo_matrix(connection_mask) self.spike_gen.connect( self.grp, prototype=input_proto, connectionMask=connection_mask.T )
def createMCNeurons(self, biasMant=0): """ configures the MC neurons""" tauU = 2 tauV = 25 decayU = int(1 / tauU * 2 ** 12) decayV = int(1 / tauV * 2 ** 12) decayU = 4095 decayV = 0 vth = 256 inWgt = 35 # Input spike connection weight self.dtrite = [] maxColsPerCore = 200 for colIdx in range(self.numInputs): coreIdx = self.lastUsedLogicalCoreId + \ math.ceil((colIdx + 1) / maxColsPerCore) np0 = nx.NeuronPrototypes.NeuronSoftResetTwoCompartments(decayU, decayV, vth, logicalCoreId=coreIdx) # create a two-compartment neuron with prototype np0 neuron0 = self.net.createNeuron(np0) # Connect somatic compartment with dendritic compartment wgtInh = -int(vth * decayU / 4096) connProto1 = nx.ConnectionPrototype(weight=wgtInh) neuron0.soma.connect(neuron0.dendrites[0], connProto1) neuron0.dendrites[0].biasExp = 6 self.allMCSomaGrp.addNeuron(neuron0) # self.dtrite = self.allMCSomaGrp.dendrites[0].nodeIds self.lastUsedLogicalCoreId += math.ceil(self.numInputs / maxColsPerCore)
def __core(self): """ Private function for setup feedforward nan :return: poisson_spikes: list :return: pre_2_post_conn: nx.Connection :return: post_neurons: nx.CompartmentGroup :return: astrocyte: combra.Astrocyte """ """ define spike generator as presynaptic neurons """ pre_neurons = self.net.createSpikeGenProcess(self.pre_num) random_spikes = np.random.rand(self.pre_num, self.sim_time) < (self.pre_fr / 1000.) poisson_spikes = [ np.where(random_spikes[num, :])[0].tolist() for num in range(self.pre_num) ] # add spikes to spike generator pre_neurons.addSpikes( spikeInputPortNodeIds=[num for num in range(self.pre_num)], spikeTimes=poisson_spikes) """ define post synaptic neurons """ post_neurons_prototype = nx.CompartmentPrototype( vThMant=self.post_vth, compartmentCurrentDecay=self.post_cdecay, compartmentVoltageDecay=self.post_vdecay, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) post_neurons = self.net.createCompartmentGroup( size=self.post_num, prototype=post_neurons_prototype) """ define astrocyte """ astrocyte = Astrocyte(self.net) """ define connection between presynaptic neurons and postsynaptic neurons """ pre_2_post_conn_prototype = nx.ConnectionPrototype() mask = np.int_( np.random.rand(self.post_num, self.pre_num) < self.pre_post_conn_p) weight = self.pre_post_w * mask pre_2_post_conn = pre_neurons.connect( post_neurons, prototype=pre_2_post_conn_prototype, connectionMask=mask, weight=weight) """ define connection between neurons and astrocyte """ astrocyte.connectInputNeurons(pre_neurons, self.pre_num) astrocyte.connectOutputNeurons(post_neurons, self.post_num) """ return """ return poisson_spikes, pre_2_post_conn, post_neurons, astrocyte
def __init__(self, network, shape, logicalCore=-1, **kwargs): super().__init__(network, shape, logicalCore) self.blocks = {} self._create_prototypes() self._create_blocks() self.prototypes['s_prototypes']['delay_conn'] = nx.ConnectionPrototype( weight=self.blocks['tracker'].get_synproto().weight, delay=1) self._connect_blocks()
def __init__(self, network, shape, logicalCore=-1, **kwargs): super().__init__(network, shape, logicalCore) self.numInputs = kwargs.get("numInputs", 2) self._create_prototypes() and_weight = int(self.prototypes['vth'] / self.numInputs) + 1 self.prototypes['s_prototypes']['andconn'] = nx.ConnectionPrototype( weight=and_weight) self._create_compartments()
def createMCNeurons(self, biasMant=0): """ configures the MC neurons""" mcADProto = nx.CompartmentPrototype( logicalCoreId=1, compartmentCurrentDecay=0, vThMant=10, # i.e. 10 * 64 = 640 biasMant=biasMant, refractoryDelay=20, vMinExp=0, numDendriticAccumulators=64, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE.SPIKE_AND_RESET) self.allMCADGroup = self.net.createCompartmentGroup( prototype=mcADProto, size=self.numMCs) mcSomaProto = nx.CompartmentPrototype( logicalCoreId=2, compartmentCurrentDecay=0, compartmentVoltageDecay=4095, enableSpikeBackprop=1, enableSpikeBackpropFromSelf=1, vThMant=2, # i.e. 2 * 64 = 128 refractoryDelay=19, vMinExp=0, numDendriticAccumulators=64, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE.SPIKE_AND_RESET) self.allMCSomaGrp = self.net.createCompartmentGroup() self.mcSomaGrpPerColumn = list() for colIdx in range(self.numColumns): self.mcSomaGrpPerColumn.append(self.net.createCompartmentGroup()) for mcIdx in range(self.numMCsPerColumn): mcSomaCx = self.net.createCompartment(prototype=mcSomaProto) self.mcSomaGrpPerColumn[colIdx].addCompartments(mcSomaCx) self.allMCSomaGrp.addCompartments(mcSomaCx) # Connect each MC-AD neuron to its MC-Soma neuron mcADToSomaConnProtoBox = nx.ConnectionPrototype( weight=3, numWeightBits=8, delay=19, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) self.mcADToSomaConns = list() for idx in range(self.numMCs): conn = self.net._createConnection(src=self.allMCADGroup[idx], dst=self.allMCSomaGrp[idx], prototype=mcADToSomaConnProtoBox) self.mcADToSomaConns.append(conn)
def __init__(self, agent, logicalCore=-1): self.n_states = agent.n_states self.input_shape = (self.n_states, 1) self.output_shape = (self.n_states, 1) super().__init__(agent.network, self.output_shape, logicalCore) self.blocks = {} self._create_prototypes() self.prototypes['s_prototypes'][ 'activation_conn'] = nx.ConnectionPrototype( weight=self.prototypes['vth'], delay=5) self._create_blocks() self._connect_blocks()
def _create_special_prototypes(self): selfBiasMant = 5 startupCycles = 2 starterThMant = selfBiasMant * startupCycles - 1 self.prototypes['c_prototypes'][ 'starterProto'] = nx.CompartmentPrototype( vThMant=starterThMant, biasMant=selfBiasMant, biasExp=6, functionalState=2, compartmentVoltageDecay=0, compartmentCurrentDecay=4095, logicalCoreId=self.logicalCore, **prototypes.noise_kwargs) self.prototypes['s_prototypes'][ 'starterInhConn'] = nx.ConnectionPrototype(weight=-selfBiasMant)
def connectSTONeuronsWithMCADNeurons(self, wgt=20): connProtoBox = nx.ConnectionPrototype( weight=-wgt, delay=20, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) # stoNeuronGroup.connect(dst=eNeuronADGroup, prototype=connProtoBox) for coreIdx in range(self.numENeurons): self.net._createConnection(src=self.stoNeuronGroup[coreIdx], dst=self.mcADNeuronGroup[coreIdx], prototype=connProtoBox) for idx in range(self.numENeuronsPerCore): self.net._createConnection( src=self.stoNeuronGroup[coreIdx], dst=self.mcNeuronGrpPerCoreList[coreIdx][idx], prototype=connProtoBox)
def connectSTOsWithMCADs(self, wgt=-20): """ creates the STO->MC connections """ connProtoBox = nx.ConnectionPrototype( weight=wgt, delay=20, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) # ToDo: use only 1 STO per core # stoNeuronGroup.connect(dstGrp=eNeuronADGroup, prototype=connProtoBox) for idx in range(self.numMCs): self.net._createConnection(src=self.stoNeuronGroup[idx], dst=self.allMCADGroup[idx], prototype=connProtoBox) self.net._createConnection(src=self.stoNeuronGroup[idx], dst=self.allMCSomaGrp[idx], prototype=connProtoBox)
def connectExcitatoryMCToInhibitoryGCNeurons(self): minDelay = self.delayMCToGC numDelays = self.numMCToGCDelays #percent = int(100 * self.conn_prob) """ eSTDPLearningRule= net.createLearningRule( dw='2^-4*x1*y0', x1Impulse=20, x1TimeConstant=2, tEpoch=trainEpoch ) """ self.exc2InhConnGroups = list() for delay in range(minDelay, minDelay + numDelays): """ wgtMat = np.zeros((self.numGCs, self.numMCs), int) rand = np.random.uniform(0, 100, size=wgtMat.shape) wgtMat[rand <= percent] = 10 """ wgtMat = self.excMCToInhGCWeights[delay - minDelay] connProtoE2I = nx.ConnectionPrototype( delay=delay if not self.debug else 0, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE, #enableLearning=1 if enableSTDP else 0, # learningRule=eSTDPLearningRule, # learningEnableMode=nx.SYNAPSE_LEARNING_ENABLE_MODE.SHARED ) connGrp = self.net.createConnectionGroup( dst=self.allGCNeuronsGroup, src=self.allMCSomaNeuronsGrp, prototype=connProtoE2I, connectionMask=(wgtMat > 0), weight=wgtMat) self.exc2InhConnGroups.append(connGrp)
def set_online_input_encoding(self): """ Create Fake Connections for online input encoding :return online_fanin_axon_id """ assert isinstance(self.network_input_layer, CompartmentGroup) assert len(self.core_list[0]) == self.loihi_snn_dimension[0] neuron_prototype = nx.CompartmentPrototype() pseudo_neurons = self.net.createCompartmentGroup(size=0) for core in self.core_list[0]: pseudo_single = self.net.createCompartment( prototype=neuron_prototype) pseudo_single.logicalCoreId = core pseudo_neurons.addCompartments(pseudo_single) conn_w = np.eye(self.loihi_snn_dimension[0]) * 120 conn_mask = np.int_(np.eye(self.loihi_snn_dimension[0])) self.pseudo_2_input = pseudo_neurons.connect( self.network_input_layer, prototype=nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY), connectionMask=conn_mask, weight=conn_w)
def connectMCToGC(self): """ creates the MC->GC excitatory connections """ minDelay = self.minDelaysMCToGC numDelays = self.numDelaysMCToGC percent = int(self.connProbMCToGC * 100) eSTDPLearningRule = self.net.createLearningRule( dw='2^-6*x1*y0', x1Impulse=127, x1TimeConstant=1, y1Impulse=127, y1TimeConstant=25, tEpoch=40 ) self.mcToGCConnGrpsPerDelay = list() for delay in range(minDelay, minDelay + numDelays): wgtMat = np.zeros((self.numGCs, self.numMCs), int) rand = np.random.uniform(0, 100, size=wgtMat.shape) wgtMat[rand <= percent] = 201 connProtoMCToGC = nx.ConnectionPrototype( delay=delay, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE, enableLearning=1, learningRule=eSTDPLearningRule, ) connGrp = self.net.createConnectionGroup( dst=self.allGCsGroup, src=self.allMCSomaGrp, prototype=connProtoMCToGC, connectionMask=(wgtMat > 0), weight=wgtMat ) self.mcToGCConnGrpsPerDelay.append(connGrp)
def create_prototypes(self, vth=255, logicalCoreId=-1): prototypes = {} prototypes['vth'] = vth #setup compartment prototypes c_prototypes = {} n_prototypes = {} s_prototypes = {} #Q Neuron c_prototypes['somaProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId) c_prototypes['spkProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=2, logicalCoreId=logicalCoreId) c_prototypes['ememProto'] = nx.CompartmentPrototype( vThMant=vth, #vMaxExp=15, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=3, logicalCoreId=logicalCoreId) c_prototypes['somaProto'].addDendrite([c_prototypes['spkProto']], nx.COMPARTMENT_JOIN_OPERATION.OR) c_prototypes['spkProto'].addDendrite([c_prototypes['ememProto']], nx.COMPARTMENT_JOIN_OPERATION.ADD) n_prototypes['qProto'] = nx.NeuronPrototype(c_prototypes['somaProto']) #S Inverter c_prototypes['invProto'] = nx.CompartmentPrototype( vThMant=vth - 1, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=0, functionalState=2, logicalCoreId=logicalCoreId) c_prototypes['spkProto'] = nx.CompartmentPrototype( vThMant=vth - 1, biasMant=vth, biasExp=6, thresholdBehavior=0, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, functionalState=2, logicalCoreId=logicalCoreId) c_prototypes['receiverProto'] = nx.CompartmentPrototype( vThMant=vth - 1, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=0, logicalCoreId=logicalCoreId) c_prototypes['invProto'].addDendrite([c_prototypes['receiverProto']], nx.COMPARTMENT_JOIN_OPERATION.BLOCK) n_prototypes['invNeuron'] = nx.NeuronPrototype(c_prototypes['invProto']) c_prototypes['bufferProto'] = nx.CompartmentPrototype( vThMant=1, compartmentCurrentDecay=4095, compartmentVoltageDecay=4095, logicalCoreId=logicalCoreId) #AND c_prototypes['andProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=4095, logicalCoreId=logicalCoreId) #Counter (debug) v_th_max = 2**17 - 1 c_prototypes['counterProto'] = nx.CompartmentPrototype( vThMant=v_th_max, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId) #Connections s_prototypes['econn'] = nx.ConnectionPrototype(weight=2) s_prototypes['iconn'] = nx.ConnectionPrototype(weight=-2) s_prototypes['vthconn'] = nx.ConnectionPrototype(weight=-vth) s_prototypes['spkconn'] = nx.ConnectionPrototype(weight=vth) s_prototypes['halfconn'] = nx.ConnectionPrototype(weight=int(vth / 2) + 1) s_prototypes['thirdconn'] = nx.ConnectionPrototype(weight=int(vth / 3) + 1) s_prototypes['single'] = nx.ConnectionPrototype(weight=2) prototypes['c_prototypes'] = c_prototypes prototypes['n_prototypes'] = n_prototypes prototypes['s_prototypes'] = s_prototypes return prototypes
def _build_synapses(self, topology, alpha, beta): number_of_neurons = topology.number_of_nodes() weight_matrix = ( netx.adjacency_matrix(topology).tocoo() * _SCALING_FACTOR ).astype( int ) # Scale sparse weight matrix _logger.info("number_of_neurons: %i", number_of_neurons) _logger.info("number_of_synapses: %i", topology.number_of_edges()) _logger.info("Average initial weight: %.3f", np.mean(weight_matrix.data)) _logger.info( "Average excitatory weights: %.3f", np.mean(weight_matrix.data[weight_matrix.data > 0]), ) _logger.info( "Average inhibitory weights: %.3f", np.mean(weight_matrix.data[weight_matrix.data < 0]), ) _logger.info("Excitatory connections: %i", np.sum(weight_matrix.data > 0)) _logger.info("Inhibitory connections: %i", np.sum(weight_matrix.data < 0)) inhibitory_neurons = np.unique( np.nonzero(weight_matrix < 0)[0] ) # Pre-synaptic neurons with negative weights excitatory_neurons = np.array( list(set(range(number_of_neurons)) - set(inhibitory_neurons)) ) _logger.info( "Excitatory/inhibitory neurons: %i / %i", len(excitatory_neurons), len(inhibitory_neurons), ) connection_mask = np.abs(weight_matrix.sign()).astype(int) def bin_notation(x): if np.isclose(x, 0): return "0" binary = bin(int(x * 2 ** 8))[2:] exp = binary[::-1].index("1") - 8 mant = int(x / 2 ** exp) mant_str = "" if mant == 1 else str(mant) + "*" return mant_str + "2^" + str(exp) # Build the learning rules (one per excitatory neuron with out degree > 0) delta_tag = "x1*y0-2^-1*u0" delta_w = "%s*u0-%s*r1*t*u0" % (bin_notation(beta), bin_notation(alpha),) learning_rule_parameters = { "dw": delta_w, "dt": delta_tag, "r1Impulse": 2, "r1TimeConstant": 1, "x1Impulse": 2, "x1TimeConstant": 50, } _logger.info("Learning rule dw: %s", delta_w) _logger.info("Learning rule dt: %s", delta_tag) self._learning_rules = [] for i in excitatory_neurons: if topology.out_degree(i) > 0: learning_rule = self.net.createLearningRule(**learning_rule_parameters) self._learning_rules.append(learning_rule) else: _logger.info("Neuron id %i was not assigned a learning rule", i) self._learning_rules.append(None) # Add None for index matching # TODO: We could re-use prototypes for inhibitory neurons -- if that's helpful prototypes = ( [] ) # Every neuron in the reservoir is associated with a connection prototype for the learning rule for i in range(number_of_neurons): is_excitatory = i in excitatory_neurons prototype_args = { "numWeightBits": 8, "numTagBits": 8, "signMode": nx.SYNAPSE_SIGN_MODE.EXCITATORY if is_excitatory else nx.SYNAPSE_SIGN_MODE.INHIBITORY, "weightLimitMant": 8, # Doesn't stop the weight from growing but limits accumulation "weigthLimitExp": 5, "enableDelay": 0, } if is_excitatory: # Create learning rule only for excitatory synapses learning_index = np.where(excitatory_neurons == i)[0][0] lr = self._learning_rules[learning_index] if lr is not None: # No learning rule for neurons with out_degree of 0 prototype_args["enableLearning"] = 1 prototype_args["learningRule"] = lr prototypes.append(nx.ConnectionPrototype(**prototype_args)) prototype_map = np.tile(np.arange(number_of_neurons), (number_of_neurons, 1)) self.connections = self.grp.connect( self.grp, prototype=prototypes, prototypeMap=prototype_map, weight=weight_matrix.T, # transpose for (src, dst) => (dst, src) connectionMask=connection_mask.T, ) # We now create the "pair" connection using the transpose graph of the topology pair_proto = nx.ConnectionPrototype( numWeightBits=8, delay=0, enableDelay=0, enableLearning=0, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, ) # TODO: We could save memory by removing inhibitory pair neurons self.connection_mask_grp_to_pair = connection_mask if self.pair_weight_mode & self.PairWeightMode.HALF_VTH: pair_wgt_matrix = connection_mask * (_SCALING_FACTOR - 1) elif self.pair_weight_mode & self.PairWeightMode.BIN_SIZE_SYNC: pair_wgt_matrix = weight_matrix elif self.pair_weight_mode & self.PairWeightMode.MEAN_VALUE: pair_wgt_matrix = connection_mask * int(np.mean(weight_matrix)) self._grp_to_pair = self.grp.connect( self._pair_grp, prototype=pair_proto, connectionMask=connection_mask, weight=pair_wgt_matrix, ) # We now connect the pair neurons to their respective RL channels for i, n_idx in enumerate(excitatory_neurons): learning_rule = self._learning_rules[i] if learning_rule is None: continue self._pair_grp[n_idx].connect(learning_rule.reinforcementChannel)
def __init__(self, parameters=None): # Get parameters self.p = Parameters() if parameters is None else parameters # Set seed if self.p.seed is not None: np.random.seed(self.p.seed) # Instanciate nx net object self.nxNet = nx.NxNet() # Excitatory connection prototype self.exConnProto = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, weightExponent=self.p.weightExponent, numTagBits=self.p.numTagBits, numDelayBits=self.p.numDelayBits, numWeightBits=self.p.numWeightBits) # Inhibitory connection prototype self.inConnProto = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, weightExponent=self.p.weightExponent, numTagBits=self.p.numTagBits, numDelayBits=self.p.numDelayBits, numWeightBits=self.p.numWeightBits) # Mixed connection prototype self.mixedConnProto = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.MIXED, weightExponent=self.p.weightExponent, numTagBits=self.p.numTagBits, numDelayBits=self.p.numDelayBits, numWeightBits=self.p.numWeightBits) # Generator connection prototype self.genConnProto = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, weightExponent=self.p.inputWeightExponent, numTagBits=self.p.numTagBits, numDelayBits=self.p.numDelayBits, numWeightBits=self.p.numWeightBits) """ Network objects """ # Cores self.coresAvailable = np.arange(self.p.numCores) self.numCoresUsed = 0 self.numChipsUsed = 0 # Weights self.initialMasks = SimpleNamespace(**{ 'exex': None, 'inin': None, 'inex': None, 'exin': None }) self.initialWeights = SimpleNamespace(**{ 'exex': None, 'inin': None, 'inex': None, 'exin': None }) self.trainedWeightsExex = None # NxSDK compartment group chunks self.exReservoirChunks = [] self.inReservoirChunks = [] self.outputLayerChunks = [] self.connectionChunks = [] # Probes self.exSpikeProbes = [] self.inSpikeProbes = [] self.outSpikeProbes = [] self.exVoltageProbes = [] self.inVoltageProbes = [] self.outVoltageProbes = [] self.exCurrentProbes = [] self.inCurrentProbes = [] self.weightProbes = [] # Output self.outputMask = None self.outputWeights = None # Spikes self.exSpikeTrains = [] self.inSpikeTrains = [] self.outSpikeTrains = [] # Voltages self.outVoltageTrains = [] # Trace input self.traceSpikes = [] self.traceMasks = [] self.traceWeights = [] # Input self.inputTargetNeurons = [] self.inputSpikes = [] self.inputWeights = None self.inputTrials = [] # Noise input spikes self.noiseSpikes = None self.noiseMask = None self.noiseWeights = None # Instantiate utils and plot self.utils = Utils.instance() self.plot = Plot(self)
def _create_prototypes(self): #setup compartment prototypes c_prototypes = {} n_prototypes = {} s_prototypes = {} #Q Neuron c_prototypes['somaProto'] = nx.CompartmentPrototype( vThMant=self.vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0) c_prototypes['spkProto'] = nx.CompartmentPrototype( vThMant=self.vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=2) c_prototypes['ememProto'] = nx.CompartmentPrototype( vThMant=self.vth, #vMaxExp=15, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=3) c_prototypes['somaProto'].addDendrite([c_prototypes['spkProto']], nx.COMPARTMENT_JOIN_OPERATION.OR) c_prototypes['spkProto'].addDendrite([c_prototypes['ememProto']], nx.COMPARTMENT_JOIN_OPERATION.ADD) n_prototypes['qProto'] = nx.NeuronPrototype(c_prototypes['somaProto']) #S Inverter c_prototypes['invProto'] = nx.CompartmentPrototype( vThMant=self.vth - 1, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=0, functionalState=2) c_prototypes['spkProto'] = nx.CompartmentPrototype( vThMant=self.vth - 1, biasMant=self.vth, biasExp=6, thresholdBehavior=0, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, functionalState=2) c_prototypes['receiverProto'] = nx.CompartmentPrototype( vThMant=self.vth - 1, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=0) c_prototypes['invProto'].addDendrite( [c_prototypes['receiverProto']], nx.COMPARTMENT_JOIN_OPERATION.BLOCK) n_prototypes['invNeuron'] = nx.NeuronPrototype( c_prototypes['invProto']) #AND c_prototypes['andProto'] = nx.CompartmentPrototype( vThMant=self.vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=4095) #Counter (debug) v_th_max = 2**17 - 1 c_prototypes['counterProto'] = nx.CompartmentPrototype( vThMant=v_th_max, compartmentCurrentDecay=4095, compartmentVoltageDecay=0) #Connections s_prototypes['econn'] = nx.ConnectionPrototype(weight=2) s_prototypes['iconn'] = nx.ConnectionPrototype(weight=-2) s_prototypes['vthconn'] = nx.ConnectionPrototype(weight=-self.vth) s_prototypes['spkconn'] = nx.ConnectionPrototype(weight=self.vth) s_prototypes['halfconn'] = nx.ConnectionPrototype( weight=int(self.vth / 2) + 1) s_prototypes['single'] = nx.ConnectionPrototype(weight=2) self.c_prototypes = c_prototypes self.n_prototypes = n_prototypes self.s_prototypes = s_prototypes
def __core(self): """ Private function for core function of Astrocyte computation Point Astrocyte is consists 4 compartments spike_receiver: spiking compartment receive all spikes from presynaptic neurons ip3_integrator: slow spiking compartment integrate spikes from spike_receiver sic_generator: non-spike compartment generate voltage sic from ip3 spike spike_generator: spiking compartment :return: spike_receiver: nx.Compartment :return: sr_2_ip3_conn: nx.Connection :return: ip3_integrator: nx.Compartment :return: ip3_2_sic_conn: nx.Connection :return: sic_generator: nx.Compartment :return: spike_generator: nx.CompartmentGroup """ spike_receiver_prototype = nx.CompartmentPrototype( vThMant=self.srVThMant, compartmentCurrentDecay=self.srCurrentDecay, compartmentVoltageDecay=self.srVoltageDecay, activityImpulse=self.srActivityImpulse, activityTimeConstant=self.srActivityTimeConstant, enableHomeostasis=self.srEnableHomeostasis, maxActivity=self.srMinActivity, minActivity=self.srMaxActivity, homeostasisGain=self.srHomeostasisGain, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) ip3_integrator_prototype = nx.CompartmentPrototype( vThMant=self.ip3VThMant, compartmentCurrentDecay=self.ip3CurrentDecay, compartmentVoltageDecay=self.ip3VoltageDecay, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) sic_generator_prototype = nx.CompartmentPrototype( compartmentCurrentDecay=self.sicCurrentDecay, compartmentVoltageDecay=self.sicVoltageDecay, thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE. NO_SPIKE_AND_PASS_V_LG_VTH_TO_PARENT, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, stackOut=nx.COMPARTMENT_OUTPUT_MODE.PUSH) spike_generator_prototype = nx.CompartmentPrototype( vThMant=self.sgVThMant, compartmentCurrentDecay=self.sgCurrentDecay, compartmentVoltageDecay=self.sgVoltageDecay, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, compartmentJoinOperation=nx.COMPARTMENT_JOIN_OPERATION.ADD, stackIn=nx.COMPARTMENT_INPUT_MODE.POP_A) sr_2_ip3_conn_prototype = nx.ConnectionPrototype( signMode=2, numWeightBits=8, weight=self.sr2ip3Weight) ip3_2_sic_conn_prototype = nx.ConnectionPrototype( signMode=2, numWeightBits=8, weight=self.ip32sicWeight) """ Astrocyte model part 1: simulate IP3 integration """ spike_receiver = self.net.createCompartment( prototype=spike_receiver_prototype) ip3_integrator = self.net.createCompartment( prototype=ip3_integrator_prototype) sr_2_ip3_conn = spike_receiver.connect( ip3_integrator, prototype=sr_2_ip3_conn_prototype) """ Astrocyte model part 2: simulate SIC """ sic_generator = self.net.createCompartment( prototype=sic_generator_prototype) spike_generator_tmp = self.net.createCompartment( prototype=spike_generator_prototype) spike_generator = self.net.createCompartmentGroup() spike_generator.addCompartments([spike_generator_tmp]) ip3_2_sic_conn = ip3_integrator.connect( sic_generator, prototype=ip3_2_sic_conn_prototype) """ return """ return [ spike_receiver, sr_2_ip3_conn, ip3_integrator, ip3_2_sic_conn, sic_generator, spike_generator ]
def connectReservoir(self): # Predefine some helper variables nEx = self.p.reservoirExSize nExCores = int(np.ceil(nEx / self.p.neuronsPerCore)) nLastExCore = nEx % self.p.neuronsPerCore # number of excitatory neurons in last core nIn = self.p.reservoirInSize nInCores = int(np.ceil(nIn / self.p.neuronsPerCore)) nLastInCore = nIn % self.p.neuronsPerCore # number of inhibitory neurons in last core exConnProto = None # Create learning rule if self.p.isLearningRule: # Define learning rule lr = self.nxNet.createLearningRule( dw=self.p.learningRule, tEpoch=self.p.learningEpoch, x1Impulse=self.p.learningImpulse, x1TimeConstant=self.p.learningTimeConstant, y1Impulse=self.p.learningImpulse, y1TimeConstant=self.p.learningTimeConstant) # Define connection prototype with learning rule exConnProto = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, weightExponent=self.p.weightExponent, enableLearning=1, learningRule=lr) else: # Define connection prototype from basic network exConnProto = self.exConnProto # Define excitatory compartment prototypes and compartment groups # initial value is first available core id in core list frCore, toCore = self.coresAvailable[0], self.coresAvailable[0] + nExCores for i in range(frCore, toCore): # Excitatory compartment prototype exCompProto = nx.CompartmentPrototype( compartmentVoltageDecay=int(1 / self.p.voltageTau * 2**12), compartmentCurrentDecay=int(1 / self.p.currentTau * 2**12), vThMant=self.p.thresholdMant, refractoryDelay=self.p.refractoryDelay, logicalCoreId=i, enableSpikeBackprop=self.p.isLearningRule, enableSpikeBackpropFromSelf=self.p.isLearningRule, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) # Calculate size of compartment: if last core has remainder, use remainder as size size = nLastExCore if (i == (toCore - 1) and nLastExCore > 0) else self.p.neuronsPerCore # Excitatory compartment group self.exReservoirChunks.append( self.nxNet.createCompartmentGroup(size=size, prototype=exCompProto)) # Remove used core from core list self.removeCoreFromList() # Define inhibitory compartment prototypes and compartment groups # initial value is first available core id in core list frCore, toCore = self.coresAvailable[0], self.coresAvailable[0] + nInCores for i in range(frCore, toCore): # Inhibitory compartment prototype inCompProto = nx.CompartmentPrototype( compartmentVoltageDecay=int(1 / self.p.voltageTau * 2**12), compartmentCurrentDecay=int(1 / self.p.currentTau * 2**12), vThMant=self.p.thresholdMant, refractoryDelay=self.p.refractoryDelay, logicalCoreId=i, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) # Calculate size of compartment: if last core has remainder, use remainder as size size = nLastInCore if (i == (toCore - 1) and nLastInCore > 0) else self.p.neuronsPerCore # Inhibitory compartment prototype self.inReservoirChunks.append( self.nxNet.createCompartmentGroup(size=size, prototype=inCompProto)) # Remove used core from core list self.removeCoreFromList() # Interconnect excitatory and inhibitory network chunks connectNetworkChunks(self, fromChunks=self.exReservoirChunks, toChunks=self.exReservoirChunks, mask=self.initialMasks.exex, weights=self.initialWeights.exex, prototype=exConnProto, store=self.p.isWeightProbe) connectNetworkChunks(self, fromChunks=self.inReservoirChunks, toChunks=self.inReservoirChunks, mask=self.initialMasks.inin, weights=self.initialWeights.inin, prototype=self.inConnProto) connectNetworkChunks(self, fromChunks=self.exReservoirChunks, toChunks=self.inReservoirChunks, mask=self.initialMasks.exin, weights=self.initialWeights.exin, prototype=self.exConnProto) connectNetworkChunks(self, fromChunks=self.inReservoirChunks, toChunks=self.exReservoirChunks, mask=self.initialMasks.inex, weights=self.initialWeights.inex, prototype=self.inConnProto) # Log that all cores are interconnected logging.info('All cores are sucessfully interconnected')
def setup_loihi_network(params): """ sets up the HD network :param num_rings: determines the dimensionality, in how many axes do we estimate :param num_neurons: number of neurons on one ring network :param feature_size: number of pixels, determines the size of the visual receptive field :param params: dictionary defined in the main with all parameters (e.g. threshold, tau, and weight values) :param with_vision: True if vision data is used :return: net, InputPort, spike_probes, state_probes, port_cons, HD """ num_rings = params['num_rings'] num_hd = params['num_neurons'] num_vis = params['feature_size'] # num_src determines the number of neurons in spike generators and "helper" neurons num_src = 1 # start position is set to the center neuron start_pos = [int(num_hd / 2), int(num_hd / 2)] # include GHD to enable gazing at learned positions include_GHD = True # Create Loihi network net = nx.NxNet() # Create Prototypes cxProto0 = nx.CompartmentPrototype( vThMant=params['threshold0'], compartmentCurrentDecay=decay(params['taui0']), compartmentVoltageDecay=decay(params['tauv0'])) cxProto1 = nx.CompartmentPrototype( vThMant=params['threshold1'], compartmentCurrentDecay=decay(params['taui1']), compartmentVoltageDecay=decay(params['tauv1'])) cxProto_learn = nx.CompartmentPrototype( vThMant=params['threshold_RHD'], compartmentCurrentDecay=decay(params['taui0']), compartmentVoltageDecay=decay(params['tauv_RHD']), enableSpikeBackprop=1, enableSpikeBackpropFromSelf=1) cxProto_vis = nx.CompartmentPrototype( vThMant=params['threshold_vis'], # refractoryDelay=63, compartmentCurrentDecay=decay(params['taui_vis']), compartmentVoltageDecay=decay(params['tauv_vis'])) cxProto_in = nx.CompartmentPrototype( vThMant=params['threshold_in'], compartmentCurrentDecay=decay(params['taui_in']), compartmentVoltageDecay=decay(params['tauv_in'])) # Create Compartments HD, IHD, SL, SR, VR, VL, North = [], [], [], [], [], [], [] In, RHD, GHD, vision, goal, Keep_gate, HD_gate = [], [], [], [], [], [], [] # In will receive external stimulation from the InputPort In.append( create_group_core_zero(net, name="In1", prototype=cxProto_in, size=5 + num_vis + num_vis)) sc = 0 ''' Names of neuron groups: VR, VL: Velocity Right, Velocity Left, receives encoder information North: Used to set the initial activity at a specific place on the ring HD: Head Direction, outputs the estimated orientation as neuron index which is converted to degrees in /data_visualization IHD: Integrated Head Direction SL, SR: Shift Left, Shift Right RHD: Reset Heading Direction, is connected to the visual input neuron and learns object associations GHD: Goal Heading Direction, is connected to the visual input neuron and learns object associations see https://doi.org/10.3389/fnins.2020.00551 for more information ''' # specify how many 1D rings you want to have, here we have one for pitch and one for yaw, so range(2) # the number of rings determines the dimensions, i.e. how many axis are estimated # the parameters are set in main_hd_net.py for ii in range(num_rings): # create groups VR.append( create_group_core_zero(net, name="VR" + str(ii), prototype=cxProto1, size=num_src)) VL.append( create_group_core_zero(net, name="VL" + str(ii), prototype=cxProto1, size=num_src)) # This group simply initilizes the peak at a given position on the ring North.append( create_group_core_zero(net, name="N" + str(ii), prototype=cxProto0, size=1)) # Groups are distributed over cores on Loihi HD.append( create_group(net, 1 + sc, 5 + sc, name="HD" + str(ii), prototype=cxProto0, size=num_hd)) IHD.append( create_group(net, 5 + sc, 10 + sc, name="IHD" + str(ii), prototype=cxProto0, size=num_hd)) SL.append( create_group(net, 10 + sc, 15 + sc, name="SL" + str(ii), prototype=cxProto0, size=num_hd)) SR.append( create_group(net, 15 + sc, 20 + sc, name="SR" + str(ii), prototype=cxProto0, size=num_hd)) RHD.append( create_group(net, 20 + sc, 25 + sc, name="RHD" + str(ii), prototype=cxProto_learn, size=num_hd)) if include_GHD: GHD.append( create_group(net, 25 + sc, 30 + sc, name="GHD" + str(ii), prototype=cxProto_learn, size=num_hd)) sc += 30 else: sc += 30 vision.append( create_group(net, start_core=61, end_core=62, name="vision", prototype=cxProto_vis, size=num_vis)) if include_GHD: goal.append( create_group(net, start_core=62, end_core=63, name="goal", prototype=cxProto_vis, size=num_vis)) # Create spike input port InputPort = net.createSpikeInputPortGroup(size=In[0].numNodes) # Connection prototypes connProtoEx = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY) connProtoInh = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY) connProtoMix = nx.ConnectionPrototype(signMode=nx.SYNAPSE_SIGN_MODE.MIXED) connProtoEx_in = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, weight=params['w_in']) connProtoInh_V = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.INHIBITORY, weight=-1) connProtoEx_vis = nx.ConnectionPrototype( signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, weight=params['w_in_vis']) connProto_iport = nx.ConnectionPrototype(weight=2) # Create learning rule used by the learning-enabled synapse lr = net.createLearningRule(dw='2*y0*x1-32*x0', x1Impulse=125, x1TimeConstant=2, tEpoch=20) connProtoLrn = nx.ConnectionPrototype( enableLearning=True, learningRule=lr, numWeightBits=8, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY) # connect initialization input In[0][0].connect(North[0], prototype=connProtoEx_in) In[0][0].connect(North[1], prototype=connProtoEx_in) # connect input to velocity neurons In[0][1].connect(VR[0], prototype=connProtoEx_in) In[0][2].connect(VL[0], prototype=connProtoEx_in) In[0][3].connect(VR[1], prototype=connProtoEx_in) In[0][4].connect(VL[1], prototype=connProtoEx_in) if params['with_vision']: # connect vision input for i in range(num_vis): In[0][5 + i].connect(vision[0][i], prototype=connProtoEx_vis) # connect goal input if include_GHD: for j in range(num_vis): In[0][5 + j].connect(goal[0][j], prototype=connProtoEx_vis) In[0][5 + j + num_vis].connect(goal[0][j], prototype=connProtoEx_vis) for i in range(num_rings): # Set all connections inside each ring network # Vision inhibits IHD and Velocities w_matrix = con.all2all(num_vis, num_hd, params['w_vis_IHD_i']) vision[0].connect(IHD[i], prototype=connProtoInh, weight=w_matrix) if params['w_RHD_IHD_e'] > 0.0: vision[0].connect(VL[i], prototype=connProtoInh_V) vision[0].connect(VR[i], prototype=connProtoInh_V) # HD WTA w_matrix = np.ones((num_hd, num_hd)) * params['w_HD_HD_i'] pre_e, post_e = con.connect_populations_1to1(num_hd, num_hd) for j in range(len(pre_e)): w_matrix[post_e[j], pre_e[j]] = params['w_HD_HD_e'] HD[i].connect(HD[i], prototype=connProtoMix, weight=w_matrix) # Connect HD to Shifts via inhibition w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_inh_shift(num_hd, num_hd) for j in range(len(pre)): w_matrix[post[j], pre[j]] = params['w_HD_S'] HD[i].connect(SR[i], prototype=connProtoInh, weight=w_matrix, connectionMask=w_matrix != 0) HD[i].connect(SL[i], prototype=connProtoInh, weight=w_matrix, connectionMask=w_matrix != 0) # Shifts asymmetric connection to IHD w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd, shift_offset=1) for j in range(len(pre) - 1): # in order not to connect the last one -1 w_matrix[pre[j], post[j]] = params['w_S_IHD'] SR[i].connect(IHD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd, shift_offset=-1) for j in range(len(pre) - 1): # in order not to connect the last one -1 w_matrix[pre[j], post[j]] = params['w_S_IHD'] SL[i].connect(IHD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) # IHD to HD, here one2one excitatory w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd) for j in range(len(pre)): w_matrix[pre[j], post[j]] = params['w_IHD_HD_e'] IHD[i].connect(HD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) # IHD to HD, here inhibitory to all others w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_inh_shift(num_hd, num_hd) for j in range(len(pre)): w_matrix[post[j], pre[j]] = params['w_IHD_HD_i'] IHD[i].connect(HD[i], prototype=connProtoMix, weight=w_matrix, connectionMask=(w_matrix != 0)) # RHD to IHD for reset, one-to-one excitatory, inhibitory to all others if params['w_RHD_IHD_e'] > 0.0: w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd) for j in range(len(pre)): w_matrix[pre[j], post[j]] = params['w_RHD_IHD_e'] RHD[i].connect(IHD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) if params['w_RHD_IHD_i'] > 0.0: w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_inh_shift(num_hd, num_hd) for j in range(len(pre)): w_matrix[post[j], pre[j]] = params['w_RHD_IHD_i'] RHD[i].connect(IHD[i], prototype=connProtoMix, weight=w_matrix, connectionMask=(w_matrix != 0)) # HD to RHD subthreshold w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd) for j in range(len(pre)): w_matrix[pre[j], post[j]] = params['w_HD_RHD'] HD[i].connect(RHD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) if include_GHD: # HD to GHD subthreshold w_matrix = np.zeros((num_hd, num_hd)) pre, post = con.connect_populations_1to1(num_hd, num_hd) for j in range(len(pre)): w_matrix[pre[j], post[j]] = params['w_HD_RHD'] # uses the same weight HD[i].connect(GHD[i], prototype=connProtoEx, weight=w_matrix, connectionMask=(w_matrix != 0)) # plastic synapse to learn landmark position (RHD/GHD) association w_matrix = con.all2all(num_vis, num_hd, params['w_init_plast']) if params['w_RHD_IHD_e'] > 0.0: syn_plast = vision[0].connect(RHD[i], prototype=connProtoLrn, weight=w_matrix) if include_GHD: syn_plast_GHD = goal[0].connect(GHD[i], prototype=connProtoLrn, weight=w_matrix) # Velocities excite shifts w_matrix = con.all2all(num_vis, num_hd, params['w_V_S']) VR[i].connect(SR[i], prototype=connProtoEx, weight=w_matrix) VL[i].connect(SL[i], prototype=connProtoEx, weight=w_matrix) # Initial Heading w_matrix = np.zeros((num_hd, num_src)) w_matrix[start_pos[i], :] = params['w_North_HD'] North[i].connect(HD[i], prototype=connProtoEx, weight=w_matrix) # , connectionMask=(w_matrix != 0)) # input port to input group port_cons = InputPort.connect(In[0], prototype=connProto_iport, connectionMask=sparse.eye(In[0].numNodes)) logicalAxonIds = [] for port_c in port_cons: logicalAxonIds.append(port_c.nodeIds) # Hacking spike probes to create spike counter and defer probing # Check tutorial on lakemont spike counters # lmt counters created will be read from Embedded snip probeParameters = [nx.ProbeParameter.SPIKE] pc_yarp = SpikeProbeCondition(dt=1, tStart=100000000) pc_probe = SpikeProbeCondition(dt=1, tStart=1) # if real-time recording using yarp: set to pc_yarp, for offline probing set to pc_probe pc = pc_yarp # pc_probe spike_probes = OrderedDict() spike_probes['HD1'] = HD[0].probe(probeParameters, pc) spike_probes['HD2'] = HD[1].probe(probeParameters, pc) if include_GHD: # plot GHD instead of RHD spike_probes['RHD1'] = GHD[0].probe(probeParameters, pc) spike_probes['RHD2'] = GHD[1].probe(probeParameters, pc) spike_probes['vision'] = goal[0].probe(probeParameters, pc) else: spike_probes['RHD1'] = RHD[0].probe(probeParameters, pc) spike_probes['RHD2'] = RHD[1].probe(probeParameters, pc) spike_probes['vision'] = vision[0].probe(probeParameters, pc) # Create state probes # voltageProbe1 = HD[1].probe([nx.ProbeParameter.COMPARTMENT_VOLTAGE]) state_probes = OrderedDict() # state_probes['weight'] = syn_plast.probe([nx.ProbeParameter.SYNAPSE_WEIGHT], IntervalProbeCondition(dt=50)) return net, InputPort, spike_probes, state_probes, port_cons, HD
def create_prototypes(vth=255, logicalCoreId=-1, noisy=0, synscale=1): prototypes = {} prototypes['vth'] = vth #setup compartment prototypes c_prototypes = {} n_prototypes = {} s_prototypes = {} #Q Neuron c_prototypes['somaProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) c_prototypes['spkProto'] = nx.CompartmentPrototype( vThMant=vth, biasMant=int(vth / 2), biasExp=6, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=2, logicalCoreId=logicalCoreId, enableNoise=noisy, **noise_kwargs) c_prototypes['ememProto'] = nx.CompartmentPrototype( vThMant=vth, #vMaxExp=15, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=3, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) c_prototypes['somaProto'].addDendrite([c_prototypes['spkProto']], nx.COMPARTMENT_JOIN_OPERATION.OR) c_prototypes['spkProto'].addDendrite([c_prototypes['ememProto']], nx.COMPARTMENT_JOIN_OPERATION.ADD) n_prototypes['qProto'] = nx.NeuronPrototype(c_prototypes['somaProto']) #Soft Reset Neuron c_prototypes['srSomaProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) c_prototypes['srSpkProto'] = nx.CompartmentPrototype( vThMant=vth, biasMant=0, biasExp=6, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, thresholdBehavior=2, logicalCoreId=logicalCoreId, enableNoise=noisy, **noise_kwargs) c_prototypes['intProto'] = nx.CompartmentPrototype( vThMant=vth, #vMaxExp=15, compartmentCurrentDecay=4095, compartmentVoltageDecay=4095, thresholdBehavior=0, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) c_prototypes['srSomaProto'].addDendrite([c_prototypes['srSpkProto']], nx.COMPARTMENT_JOIN_OPERATION.OR) c_prototypes['srSpkProto'].addDendrite([c_prototypes['intProto']], nx.COMPARTMENT_JOIN_OPERATION.ADD) n_prototypes['srProto'] = nx.NeuronPrototype(c_prototypes['srSomaProto']) #FF Neuron c_prototypes['ffSomaProto'] = nx.CompartmentPrototype( vThMant=1, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) c_prototypes['ffSomaProto'].addDendrite([c_prototypes['ememProto']], nx.COMPARTMENT_JOIN_OPERATION.ADD) n_prototypes['ffProto'] = nx.NeuronPrototype(c_prototypes['ffSomaProto']) #Inverter compartment c_prototypes['invProto'] = nx.CompartmentPrototype( vThMant=1, biasMant=2, biasExp=6, compartmentVoltageDecay=0, functionalState=2, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) #buffer / OR c_prototypes['bufferProto'] = nx.CompartmentPrototype( vThMant=1, compartmentVoltageDecay=4095, compartmentCurrentDecay=4095, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) #AND c_prototypes['andProto'] = nx.CompartmentPrototype( vThMant=vth, compartmentCurrentDecay=4095, compartmentVoltageDecay=4095, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) #Counter v_th_max = 2**17 - 1 c_prototypes['counterProto'] = nx.CompartmentPrototype( vThMant=v_th_max, compartmentCurrentDecay=4095, compartmentVoltageDecay=0, logicalCoreId=logicalCoreId, enableNoise=0, **noise_kwargs) #Connections #scaled vth used when synscale is being used to increase dynamic range vth = vth / synscale s_prototypes['econn'] = nx.ConnectionPrototype(weight=2) s_prototypes['iconn'] = nx.ConnectionPrototype(weight=-2) s_prototypes['invconn'] = nx.ConnectionPrototype(weight=-1) s_prototypes['vthconn'] = nx.ConnectionPrototype(weight=-vth) s_prototypes['spkconn'] = nx.ConnectionPrototype(weight=vth) s_prototypes['halfconn'] = nx.ConnectionPrototype(weight=int(vth / 2) + 1) s_prototypes['thirdconn'] = nx.ConnectionPrototype(weight=int(vth / 3) + 1) s_prototypes['single'] = nx.ConnectionPrototype(weight=2) prototypes['c_prototypes'] = c_prototypes prototypes['n_prototypes'] = n_prototypes prototypes['s_prototypes'] = s_prototypes return prototypes
def createExcitatoryMCNeurons(self): # Create MC-AD neurons recieve the input biases. The activity of # the MC-AD neurons is gated by the STO Neurons. if self.inputBiases is None: self.inputBiases = [0] * self.numCores self.mcADNeuronGroup = self.net.createCompartmentGroup() for coreIdx in range(self.numCores): mcADProto = nx.CompartmentPrototype( logicalCoreId=coreIdx, compartmentCurrentDecay=0, vThMant=10, # i.e. 10 * 64 = 640 biasMant=self.inputBiases[coreIdx], refractoryDelay=20, vMinExp=0, numDendriticAccumulators=64, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE.SPIKE_AND_RESET ) mcADCx = self.net.createCompartment(prototype=mcADProto) self.mcADNeuronGroup.addCompartments(mcADCx) # Create MC-Soma neurons which get input form MC-AD neurons. MC-Soma # neurons connect to the Inhibitory GC neurons. self.allMCSomaNeuronsGrp = self.net.createCompartmentGroup() self.mcNeuronGrpPerCoreList = [] for coreIdx in range(self.numCores): mcSomaNeuronProto = nx.CompartmentPrototype( logicalCoreId=coreIdx, compartmentCurrentDecay=0, compartmentVoltageDecay=4095, vThMant=2, # i.e. 2 * 64 = 128 refractoryDelay=19, vMinExp=0, numDendriticAccumulators=64, functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE, thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE.SPIKE_AND_RESET ) mcNeuronGrpPerCore = self.net.createCompartmentGroup() for _ in range(self.numENeuronsPerCore): mcSomaNeuronCx = self.net.createCompartment( prototype=mcSomaNeuronProto) self.allMCSomaNeuronsGrp.addCompartments(mcSomaNeuronCx) mcNeuronGrpPerCore.addCompartments(mcSomaNeuronCx) self.mcNeuronGrpPerCoreList.append(mcNeuronGrpPerCore) # Connect each MC-AD neuron to its MC-Soma neuron mcADToSomaConnProtoBox = nx.ConnectionPrototype( weight=3, delay=19, numDelayBits=6, enableDelay=1, signMode=nx.SYNAPSE_SIGN_MODE.EXCITATORY, postSynResponseMode=nx.SYNAPSE_POST_SYN_RESPONSE_MODE.BOX, compressionMode=nx.SYNAPSE_COMPRESSION_MODE.SPARSE) for coreIdx in range(self.numENeurons): self.net._createConnection(src=self.mcADNeuronGroup[coreIdx], dst=self.allMCSomaNeuronsGrp[coreIdx], prototype=mcADToSomaConnProtoBox)
input_spike_times = gen_rand_spikes(pre_neuron_cnt, sim_time, 10) pre_synaptic_neurons.addSpikes( spikeInputPortNodeIds=[num for num in range(pre_neuron_cnt)], spikeTimes=input_spike_times) # Create post-synaptic neuron post_neuron_proto = nx.CompartmentPrototype( vThMant=10, compartmentCurrentDecay=int(1 / 10 * 2**12), compartmentVoltageDecay=int(1 / 4 * 2**12), functionalState=nx.COMPARTMENT_FUNCTIONAL_STATE.IDLE) post_neurons = net.createCompartmentGroup(size=post_neuron_cnt, prototype=post_neuron_proto) # Create a connection from the pre to post-synaptic neuron conn_proto = nx.ConnectionPrototype() conn_mask = np.zeros((20, 20)) # Turn on connections in the mask between the first 10 pre-synaptic and first 10 post-synaptic neurons conn_mask[0:10] = np.arange(20) < 10 # Turn on connections in the mask between the last 10 pre-synaptic and last 10 post-synaptic neurons conn_mask[-10:] = np.arange(20) >= 10 # Randomly turn off some of the connections enabled in the two groups conn_mask *= (np.random.rand(20, 20) < 0.5) # Generate random weights for the connections ranging anywhere in the range [0, 2) weight = 2 * conn_mask conn = pre_synaptic_neurons.connect(post_neurons, prototype=conn_proto, connectionMask=conn_mask, weight=weight)
def __init__(self, params, net=None, name=None): """ The STDE_group contains the sTDE neurons. One neuron consists of 4 compartments that are connected as follows: D (main/soma) | C (current) / \\ (trigger) A B (facilitator) A is the gate and lets B's current pass whenever it spikes. C receives B's current on its voltage variable and decays D receives C's voltage and integrates it, so C is basically a second current input to D The two inputs are called trigger and facilitator following Milde (2018) params are 'tau_fac': current tau of facilitator input 'tau_trigg': current tau of trigger input 'tau_v': voltage tau of TDE Neuron 'tau_c': current tau of TDE Neuron 'weight_fac': amplitude of the facilitator spike 'do_probes' : can be 'all', 'spikes' or None 'num_neurons' : number of sTDE neurons that are created """ if net is None: net = nx.NxNet() self.net = net self.num_neurons = params['num_neurons'] self.neurongroups = {} self.probes = {} self.spikegens = {} weight_fac, exponent_fac = calculate_mant_exp( params['weight_fac'] / params['tau_fac'], 7) # Create auxiliary compartments cpA = nx.CompartmentPrototype( vThMant=1, compartmentCurrentDecay=int(1 / 1 * 2**12), compartmentVoltageDecay=4095, # thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE.NO_SPIKE_AND_PASS_V_LG_VTH_TO_PARENT ) cpB = nx.CompartmentPrototype(vThMant=100, compartmentCurrentDecay=int( 1 / params['tau_fac'] * 2**12), compartmentVoltageDecay=4095) cpC = nx.CompartmentPrototype( vThMant=1000, compartmentCurrentDecay=int(1 / 1 * 2**12), compartmentVoltageDecay=int(1 / params['tau_trigg'] * 2**12), thresholdBehavior=nx.COMPARTMENT_THRESHOLD_MODE. NO_SPIKE_AND_PASS_V_LG_VTH_TO_PARENT) # Create main compartment cpD = nx.CompartmentPrototype( vThMant=100, compartmentCurrentDecay=int(1 / params['tau_v'] * 2**12), compartmentVoltageDecay=int(1 / params['tau_c'] * 2**12), ) # build compartment tree cpC.addDendrites(prototypeA=cpA, prototypeB=cpB, joinOp=nx.COMPARTMENT_JOIN_OPERATION.PASS) cpD.addDendrite(prototype=[cpC], joinOp=nx.COMPARTMENT_JOIN_OPERATION.ADD) num_neurons = params['num_neurons'] neuronPrototype = nx.NeuronPrototype(cpD) neurongroup = net.createNeuronGroup(prototype=neuronPrototype, size=num_neurons) sgpA = net.createSpikeGenProcess(numPorts=num_neurons) sgpB = net.createSpikeGenProcess(numPorts=num_neurons) # sgpC = net.createSpikeGenProcess(numPorts=1) connProto = nx.ConnectionPrototype(weight=weight_fac, weightExponent=exponent_fac) sgpA.connect(neurongroup.dendrites[0].dendrites[1], prototype=connProto, connectionMask=sp.sparse.identity(num_neurons)) sgpB.connect(neurongroup.dendrites[0].dendrites[0], prototype=connProto, connectionMask=sp.sparse.identity(num_neurons)) spikegens = [sgpA, sgpB] if params['do_probes'] == 'all': (uA, vA, sA) = neurongroup.dendrites[0].dendrites[1].probe([ nx.ProbeParameter.COMPARTMENT_CURRENT, nx.ProbeParameter.COMPARTMENT_VOLTAGE, nx.ProbeParameter.SPIKE ]) (uB, vB, sB) = neurongroup.dendrites[0].dendrites[0].probe([ nx.ProbeParameter.COMPARTMENT_CURRENT, nx.ProbeParameter.COMPARTMENT_VOLTAGE, nx.ProbeParameter.SPIKE ]) (uC, vC, sC) = neurongroup.dendrites[0].probe([ nx.ProbeParameter.COMPARTMENT_CURRENT, nx.ProbeParameter.COMPARTMENT_VOLTAGE, nx.ProbeParameter.SPIKE ]) (uD, vD, sD) = neurongroup.soma.probe([ nx.ProbeParameter.COMPARTMENT_CURRENT, nx.ProbeParameter.COMPARTMENT_VOLTAGE, nx.ProbeParameter.SPIKE ]) probes = { 'A_current': uA, 'A_voltage': vA, 'A_spikes': sA, 'B_current': uB, 'B_voltage': vB, 'B_spikes': sB, 'C_current': uC, 'C_voltage': vC, 'C_spikes': sC, 'D_current': uD, 'D_voltage': vD, 'D_spikes': sD, } elif params['do_probes'] == 'spikes': sA = neurongroup.dendrites[0].dendrites[1].probe( [nx.ProbeParameter.SPIKE]) sB = neurongroup.dendrites[0].dendrites[0].probe( [nx.ProbeParameter.SPIKE]) sC = neurongroup.dendrites[0].probe([nx.ProbeParameter.SPIKE]) sD = neurongroup.soma.probe([nx.ProbeParameter.SPIKE]) probes = { 'A_spikes': sA, 'B_spikes': sB, 'C_spikes': sC, 'D_spikes': sD, } else: probes = None self.neurongroup = neurongroup self.probes = probes self.spikegens = spikegens self.input0 = neurongroup.dendrites[0].dendrites[0] self.input1 = neurongroup.dendrites[0].dendrites[1]