/** * "FNS" (Firnet NeuroScience), ver.3.x * * FNS is an event-driven Spiking Neural Network framework, oriented * to data-driven neural simulations. * * (c) 2020, Gianluca Susi, Emanuele Paracone, Mario Salerno, * Alessandro Cristini, Fernando Maestú. * * CITATION: * When using FNS for scientific publications, cite us as follows: * * Gianluca Susi, Pilar Garcés, Alessandro Cristini, Emanuele Paracone, * Mario Salerno, Fernando Maestú, Ernesto Pereda (2020). * "FNS: an event-driven spiking neural network simulator based on the * LIFL neuron model". * Laboratory of Cognitive and Computational Neuroscience, UPM-UCM * Centre for Biomedical Technology, Technical University of Madrid; * University of Rome "Tor Vergata". * Paper under review. * * FNS is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * FNS is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FNS. If not, see <http://www.gnu.org/licenses/>. * * ----------------------------------------------------------- * * Website: http://www.fnsneuralsimulator.org * * Contacts: fnsneuralsimulator (at) gmail.com * gianluca.susi82 (at) gmail.com * emanuele.paracone (at) gmail.com * * * ----------------------------------------------------------- * ----------------------------------------------------------- **/ package spiking.controllers.node; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.PriorityQueue; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import spiking.internode.InterNodeBurningSpike; import spiking.internode.InterNodeSpike; import spiking.node.Node; import spiking.node.NodesManager; import spiking.node.Synapse; import spiking.node.SynapsesManager; import spiking.node.neuron.NodeNeuronsManager; import spiking.node.spikes.FixedBurnSpike; import utils.constants.Constants; import utils.tools.NiceNode; import utils.tools.NiceQueue; import utils.math.FastMath; import utils.statistics.StatisticsCollector; import utils.statistics.BurningWriter; import utils.statistics.FiringWriter; public class NodeThread extends Thread{ private final static String TAG = "[Node Thread "; private final static Boolean verbose = true; private Node n; private NodeNeuronsManager nnMan; private NodesManager nMan; private SynapsesManager synMan; private Boolean plasticity; //queues map enqueues the spikes sended by a specific firing neuron //to a specific burning neuron //extendible private HashMap<Synapse, NiceQueue>queuesMap; private double currentTime=0.0; private double stopTime=0.0; private double startTime=0.0; private Boolean debug = false; private Boolean activePassiveDebug = false; private int debug_level = 3; private int debNum=28; private ArrayList<InterNodeSpike> internodeFires; private Boolean keepRunning=true; private Lock lock = new ReentrantLock(); private Condition newTimeSplitCond = lock.newCondition(); private PriorityQueue<InterNodeBurningSpike> interNodeBurningSpikes= new PriorityQueue<InterNodeBurningSpike>(); private PriorityQueue<FixedBurnSpike> burningQueueSpikes= new PriorityQueue<FixedBurnSpike>(); private FastMath fm = new FastMath(); private Double debugMaxWPDiff=0.0; private Boolean do_fast; private Boolean isNOI; private Boolean lif = false; private Boolean exp_decay = false; long[] times= new long[10]; private StatisticsCollector sc; private int toremDebug=0; private BurningWriter burningWriter; private FiringWriter firingWriter; <<<<<<< HEAD //private NodeFiringsThread nft; //private NodeBurningsThread nbt; ======= private NodeFiringsThread nft; private NodeBurningsThread nbt; >>>>>>> 48bb69b3e778691a096596083425b528609c0729 /** * The NodeThread object * * @param nMan the simulation NodesManager object * @param id the node id * @param n the number of neurons of the node * @param excitProportion the ratio of excitatory neurons over the total * number of neurons 'n' * @param k the conn-degree of each neuron * @param prew the prob of small-world topology rewinig * @param Bn the number of bursts spike for each * firing neuron * @param IBI the burst inter-spike time * @param D_exc * @param D_inh * @param mu_w_exc the mean of the postsynaptic weight * distribution for excitatory neurons * @param mu_w_inh the mean of the postsynaptic weight * distribution for inhibitory neurons * @param sigma_w_exc the std deviation of the postsynaptic weight * distribution for excitatory neurons * @param sigma_w_inh the std deviation of the postsynaptic weight * distribution for inhibitory neurons * @param w_pre_exc the presynaptic weight for excitatory neurons * @param w_pre_inh the presynaptic weight for inhibitory neurons * @param externalPresynapticDefVal * @param plasticity simulate neuron plasticity * @param etap the Etap for plasticity * @param etam the Etam for plasticity * @param taup the Taup for plasticity * @param taum the Taum for plasticity * @param pwMax the pwMax for plasticity * @param to the to for plasticity * @param avgNeuronalSignalSpeed the signal speed through synapsis * @param lif do lif simulation * @param exp_decay use exponential sub-threashold decay * @param do_fast use fastest algorithms (some aproximations) * */ public NodeThread( NodesManager nMan, Integer id, Long n, Double excitProportion, Integer k, Double prew, Integer Bn, Double IBI, Double D_exc, Double D_inh, Double ld, Double kr, Double mu_w_exc, Double mu_w_inh, Double sigma_w_exc, Double sigma_w_inh, Double w_pre_exc, Double w_pre_inh, Double externalPresynapticDefVal, Boolean plasticity, Double etap, Double etam, Double taup, Double taum, Double pwMax, Double to, Double avgNeuronalSignalSpeed, Boolean lif, Boolean exp_decay, Boolean do_fast, Boolean isNOI, StatisticsCollector sc){ this.n=new Node( id, n, excitProportion, mu_w_exc, mu_w_inh, sigma_w_exc, sigma_w_inh, w_pre_exc, w_pre_inh, k, prew, Bn, IBI, plasticity, etap, etam, taup, taum, pwMax, to); init(nMan, D_exc, D_inh, ld, kr, w_pre_exc, w_pre_inh, externalPresynapticDefVal, avgNeuronalSignalSpeed, lif, exp_decay, do_fast, isNOI, sc); } /** * The NodeThread object * * @param nMan the simulation NodesManager object * @param id the node id * @param n the number of neurons of the node * @param externalInputs the number of neurons with external inputs * @param externalInputType the type of external input * 0. poisson * 1. constant * 2.noise * @param externalInputsTimeOffset the time offset before external input * firings to begin * @param timeStep the avg for the external input fire distribution * @param fireDuration the duration of external input activity * @param externalAmplitude the amplitude of an external input signal * @param externalOutdegree the external out-degree of each external input * @param excitRatio the ratio of excitatory neurons over the total * number of neurons 'n' * @param k the conn-degree of each neuron * @param prew the prob of small-world topology rewinig * @param Bn the number of bursts spike for each * firing neuron * @param IBI the burst inter-spike time * @param D_exc * @param D_inh * @param mu_w_exc the mean of the postsynaptic weight * distribution for excitatory neurons * @param mu_w_inh the mean of the postsynaptic weight * distribution for inhibitory neurons * @param sigma_w_exc the std deviation of the postsynaptic weight * distribution for excitatory neurons * @param sigma_w_inh the std deviation of the postsynaptic weight * distribution for inhibitory neurons * @param w_pre_exc the presynaptic weight for excitatory neurons * @param w_pre_inh the presynaptic weight for inhibitory neurons * @param externalPresynapticDefVal * @param plasticity simulate neuron plasticity * @param etap the Etap for plasticity * @param etam the Etam for plasticity * @param taup the Taup for plasticity * @param taum the Taum for plasticity * @param pwMax the pwMax for plasticity * @param to the to for plasticity * @param avgNeuronalSignalSpeed the signal speed through synapsis * @param lif do lif simulation * @param exp_decay use exponential sub-threashold decay * @param do_fast use fastest algorithms (some aproximations) * */ public NodeThread( NodesManager nMan, Integer id, Long n, Integer externalInputs, int externalInputType, Double externalInputsTimeOffset, double timeStep, //Double fireRate, int fireDuration, Double externalAmplitude, int externalOutdegree, Double excitRatio, Integer k, Double prew, Integer Bn, Double IBI, Double c, Double D_exc, Double D_inh, Double t_arp, Double mu_w_exc, Double mu_w_inh, Double sigma_w_exc, Double sigma_w_inh, Double w_pre_exc, Double w_pre_inh, Double externalPresynapticDefVal, Boolean plasticity, Double etap, Double etam, Double taup, Double taum, Double pwMax, Double to, Double avgNeuronalSignalSpeed, Boolean lif, Boolean exp_decay, Boolean do_fast, Boolean isNOI, StatisticsCollector sc){ this.n=new Node(id, n, externalInputs, externalInputType, externalInputsTimeOffset, timeStep, //fireRate, fireDuration, externalAmplitude, externalOutdegree, excitRatio, mu_w_exc, mu_w_inh, sigma_w_exc, sigma_w_inh, w_pre_exc, w_pre_inh, k, prew, Bn, IBI, plasticity, etap, etam, taup, taum, pwMax, to); init(nMan, c, D_exc, D_inh, t_arp, w_pre_exc, w_pre_inh, externalPresynapticDefVal, avgNeuronalSignalSpeed, lif, exp_decay, do_fast, isNOI, sc); } /** * The initialization function for NodeThread * @param nMan the NodesManager * @param c * @param D_exc * @param D_inh * @param t_arp * @param excitatoryPresynapticDefVal the presynaptic weight for * excitatory neurons * @param inhibithoryPresynapticDefVal the presynaptic weight for * inhibitory neurons * @param externalPresynapticDefVal the presynaptic weight for * external inputs * @param avgNeuronalSignalSpeed the avg signal through axons * @param lif if true, a least integrate * and fire simulation is performed * @param exp_decay if true, the underthreashold * neuronal decay would be * exponential * @param do_fast if true, fastest algorithm * are used for expensive * calculations. This introduces * some kind of aproximations */ public void init( NodesManager nMan, Double c, Double D_exc, Double D_inh, Double t_arp, Double excitatoryPresynapticDefVal, Double inhibithoryPresynapticDefVal, Double externalPresynapticDefVal, Double avgNeuronalSignalSpeed, Boolean lif, Boolean exp_decay, Boolean do_fast, Boolean isNOI, StatisticsCollector sc){ this.sc=sc; <<<<<<< HEAD //nft=new NodeFiringsThread(this.sc); //nbt=new NodeBurningsThread(this.sc); //nft.start(); //nbt.start(); ======= nft=new NodeFiringsThread(this.sc); nbt=new NodeBurningsThread(this.sc); nft.start(); nbt.start(); >>>>>>> 48bb69b3e778691a096596083425b528609c0729 queuesMap = new HashMap<Synapse, NiceQueue>(); internodeFires = new ArrayList<InterNodeSpike>(); nnMan = new NodeNeuronsManager(n, c, D_exc, D_inh, t_arp, excitatoryPresynapticDefVal, inhibithoryPresynapticDefVal, externalPresynapticDefVal); this.plasticity=n.getPlasticity(); initExtInput(); synMan = new SynapsesManager(n,avgNeuronalSignalSpeed); this.nMan=nMan; println("Bn: "+n.getBn()); println("IBI: "+n.getIBI()); println("c: "+c); println("D exc: "+D_exc); println("D inh: "+D_inh); println("t arp: "+t_arp); this.lif=lif; this.exp_decay=exp_decay; this.do_fast=do_fast; this.isNOI=isNOI; } /** * starts the main thread routine */ public void run(){ NiceNode minFiringNeuron; Long firingNeuronId=null; Double spikeTime=null; Double tmpMinFiringTime; Double tmpMinInterNodeBurningTime; Double minFixedBurnTime; InterNodeBurningSpike tmpInterNodeBurningSpike; FixedBurnSpike tmpFixedBurnSpike; Integer lastCollectedBurstFiringNodeId=-1; Long lastCollectedBurstFiringNeuronId=-1l; Double lastCollectedBurstFiringBurnTime=-1.0; int fires=0; Boolean stopped=false; //the actual thread routine while (keepRunning){ for (; currentTime<stopTime; ++fires){ if (!stopped){ /* check which is the minimum between the * next firing time, the next burn due to inter-node * spikes and the next burn due to bursting queue * of a fire already happened */ tmpMinFiringTime=nnMan.getMinFiringTime(); tmpInterNodeBurningSpike=interNodeBurningSpikes.peek(); tmpFixedBurnSpike=burningQueueSpikes.peek(); minFixedBurnTime=(tmpFixedBurnSpike==null)? Double.MAX_VALUE: tmpFixedBurnSpike.getBurnTime(); // case of first arrival of inter-node burn if (tmpInterNodeBurningSpike!=null){ tmpMinInterNodeBurningTime = tmpInterNodeBurningSpike.getTimeToBurn(); if ((tmpMinInterNodeBurningTime!=null)&& (tmpMinInterNodeBurningTime<stopTime)){ if (tmpMinFiringTime!=null){ // inter-node burn processing first if ((tmpMinInterNodeBurningTime<tmpMinFiringTime) && (tmpMinInterNodeBurningTime<minFixedBurnTime)){ InterNodeSpike irs= interNodeBurningSpikes.poll().getInterNodeSpike(); if (tmpMinInterNodeBurningTime<currentTime) { println("internode burning:"+ tmpMinInterNodeBurningTime+ " min FixedBurn:"+ minFixedBurnTime+ " tmpMinFiringTime:"+ tmpMinFiringTime); if (interNodeBurningSpikes.peek()!=null) println("polled:"+ irs.getBurnTime()+ " peeked:"+ interNodeBurningSpikes.peek().getTimeToBurn()+ "\n"); } if ((interNodeBurningSpikes.peek()!=null)&& (irs.getBurnTime()>interNodeBurningSpikes.peek().getTimeToBurn())) println("polled:"+ irs.getBurnTime()+ " peeked:"+ interNodeBurningSpikes.peek().getTimeToBurn()+ " syn:"+ tmpInterNodeBurningSpike.getInterNodeSpike().getSyn()); currentTime=tmpMinInterNodeBurningTime; burnNeuron( irs.getSyn(), irs.getBurnTime(), irs.getFireTime(), false); continue; } } // there is no next node-internal spike, check inter-node // against fixed burn else if (tmpMinInterNodeBurningTime<minFixedBurnTime){ InterNodeSpike irs= interNodeBurningSpikes.poll().getInterNodeSpike(); currentTime=tmpMinInterNodeBurningTime; burnNeuron( irs.getSyn(), irs.getBurnTime(), irs.getFireTime(), false); continue; } } } // case of first arrival of bursting queue spike to be burn if (minFixedBurnTime<stopTime) { if (tmpMinFiringTime!=null){ if (minFixedBurnTime<tmpMinFiringTime) { FixedBurnSpike fixedBurnSpike = burningQueueSpikes.poll(); if (tmpFixedBurnSpike.getBurnTime()!= fixedBurnSpike.getBurnTime()) { println("tada!:"+ tmpFixedBurnSpike.getBurnTime()+ "!="+ fixedBurnSpike.getBurnTime()); System.exit(1); } currentTime=minFixedBurnTime; burnNeuron( fixedBurnSpike.getSyn(), fixedBurnSpike.getBurnTime(), minFixedBurnTime, false); if( (! lastCollectedBurstFiringNodeId.equals(n.getId()))|| (! lastCollectedBurstFiringNeuronId.equals( fixedBurnSpike.getSyn().getAxonNeuronId()))|| (! lastCollectedBurstFiringBurnTime.equals( fixedBurnSpike.getBurnTime())) ){ lastCollectedBurstFiringNodeId=n.getId(); lastCollectedBurstFiringNeuronId= fixedBurnSpike.getSyn().getAxonNeuronId(); lastCollectedBurstFiringBurnTime= fixedBurnSpike.getBurnTime(); if(isNOI) <<<<<<< HEAD sc.collectFireSpike( ======= nft.collectFireSpike( >>>>>>> 48bb69b3e778691a096596083425b528609c0729 n.getId(), fixedBurnSpike.getSyn().getAxonNeuronId(), fixedBurnSpike.getBurnTime(), nMan.getMaxN(), nMan.getCompressionFactor(), (fixedBurnSpike.getSyn().getAxonNeuronId()<n.getExcitatory()), (fixedBurnSpike.getSyn().getAxonNeuronId()>=n.getN()) ); } continue; } } else if (minFixedBurnTime<Double.MAX_VALUE) { FixedBurnSpike fixedBurnSpike = burningQueueSpikes.poll(); currentTime=minFixedBurnTime; burnNeuron( fixedBurnSpike.getSyn(), fixedBurnSpike.getBurnTime(), fixedBurnSpike.getFireTime(), false); if( (! lastCollectedBurstFiringNodeId.equals(n.getId()))|| (! lastCollectedBurstFiringNeuronId.equals( fixedBurnSpike.getSyn().getAxonNeuronId()))|| (! lastCollectedBurstFiringBurnTime.equals( fixedBurnSpike.getBurnTime())) ){ lastCollectedBurstFiringNodeId=n.getId(); lastCollectedBurstFiringNeuronId= fixedBurnSpike.getSyn().getAxonNeuronId(); lastCollectedBurstFiringBurnTime= fixedBurnSpike.getBurnTime(); if(isNOI) <<<<<<< HEAD sc.collectFireSpike( ======= nft.collectFireSpike( >>>>>>> 48bb69b3e778691a096596083425b528609c0729 n.getId(), fixedBurnSpike.getSyn().getAxonNeuronId(), fixedBurnSpike.getBurnTime(), nMan.getMaxN(), nMan.getCompressionFactor(), (fixedBurnSpike.getSyn().getAxonNeuronId()<n.getExcitatory()), (fixedBurnSpike.getSyn().getAxonNeuronId()>=n.getN()) ); } continue; } else { stopped=true; break; } } if ((tmpMinFiringTime==null)||(tmpMinFiringTime>stopTime)){ stopped=true; break; } //get the next neuron ready to fire in the list of //the active neurons //debprintln("\n\ngetting next firing neuron..."); minFiringNeuron=nnMan.getNextFiringNeuron(); if (minFiringNeuron==null){ stopped=true; break; } //debprintln("got next firing neuron."); firingNeuronId=minFiringNeuron.fn; spikeTime=minFiringNeuron.tf; if (spikeTime>stopTime){ stopped=true; break; } } else{ break; } //case of first firing of a burst //time update currentTime = spikeTime; //firing spikes detecting and storing if (firingNeuronId<n.getN()){ //State resetting to passive mode nnMan.resetState(firingNeuronId); nnMan.resetTimeToFire(firingNeuronId); } // last firing time for neuron nnMan.setLastFiringTime(firingNeuronId, currentTime); if (firingNeuronId>=n.getN()){ //ext time-to-fire resetting nnMan.resetTimeToFire(firingNeuronId); //external routine nnMan.extInputReset(firingNeuronId, currentTime); if (currentTime>n.getExternalInput().getFireDuration()) continue; } if(isNOI) <<<<<<< HEAD sc.collectFireSpike( ======= nft.collectFireSpike( >>>>>>> 48bb69b3e778691a096596083425b528609c0729 n.getId(), firingNeuronId, spikeTime, nMan.getMaxN(), nMan.getCompressionFactor(), (firingNeuronId<n.getExcitatory()), (firingNeuronId>=n.getN()) ); //search for burning neurons connected to neuron_id makeNeuronFire(firingNeuronId, currentTime); } completed(); stopped=false; } } /** * Adds a new internode fire spike * @param syn the inter-node synapse object through wich the * spike signal is sent * @param fireTime the fire-spike generation time */ private void addInterNodeFire(Synapse syn, Double fireTime){ Double axonalDelay=synMan.getAxDelay(syn); internodeFires.add(new InterNodeSpike(syn, fireTime+axonalDelay,fireTime,axonalDelay)); } /** * @return true if this node has still any inter-node spike to be * processed */ public Boolean hasInterNodeSpikes(){ if (internodeFires.size()>0) return true; return false; } /** * @return the list of internode spikes and clean it */ public ArrayList<InterNodeSpike> pullInternodeFires() { ArrayList<InterNodeSpike> retval=internodeFires; internodeFires=new ArrayList<InterNodeSpike>(); return retval; } /* * @return the current simulation time (which is the time of the * current fire event being processed) */ public double getCurrentTime() { return currentTime; } /** * Updates the current time * @param currentTime the updated current time */ public void setCurrentTime(double currentTime) { this.currentTime = currentTime; } /** * @return the current split stop time */ public double getStopTime() { return stopTime; } /** * set the next split stop time * @param stopTime the new stop time defined for the next split */ public void setStopTime(double stopTime) { this.stopTime = stopTime; } /** * @return the (unique) node id for the current node */ public Integer getNodeId(){ return n.getId(); } /** * create and adds a new inter-node synapse * @param firingNodeId the id of the firing node * @param firingNeuronId the id of the firing neuron (within a node) * @param burningNodeId the id of the burning node * @param burningNeuronId the id of the burning neuron (within a node) * @param presynaptic_w the presynaptic weight of the synapse * @param mu the postsynaptic weight for the synapse * @param lambda the avg length of the inter-node axon */ public void addInterNodeSynapse( Integer firingNodeId, Long firingNeuronId, Integer burningNodeId, Long burningNeuronId, Double presynaptic_w, Double mu, Double lambda) { synMan.addInterNodeSynapse( firingNodeId, firingNeuronId, burningNodeId, burningNeuronId, mu, n.getPresynapticForNeuron(firingNeuronId), lambda); } public Long getN(){ return n.getN(); } public Long getExcitatory(){ return n.getExcitatory(); } public Long getInhibithory(){ return n.getInhibithory(); } public Double getExcitatoryPresynapticWeight() { return n.getExc_ampl(); } public boolean hasExternalInput() { return n.hasExternalInput(); } public Integer getExternalInputs(){ return n.getExternalInputs(); } /** * Plasticity Rule. * Multiplicative Learning Rule using STDP (soft-bound) Spike time * depending plasticity * * LTP: Pw = Pwold + (pwmax - Pwold)*Etap*(-delta/taup) * LTD: Pw = Pwold - Pwold*Etam*(delta/taum) * with delta = tpost - tpre * * NB: in the case of LTD, tpost represents the burning neuron last burning * time, whereas tpre is the current "tempo". * This rule is applied for only exc-exc intermolule connections * * @param spikingNeuronId * @param presentNeuronId * @param currentTime */ /** * Plasticity rule for firing events. * Update postsynaptic weight, increasing it according to the delta i * between the firing time * and the last burning time of the firing neuron. * * @param syn * @param fireTime */ private void fire_ltp(Synapse syn, Double fireTime){ if (!plasticity) return; if (syn.getFiring()==null) return; Long firingNeuronId = syn.getFiring(); ArrayList <Synapse> synapses = synMan.getFiringNeuronSynapses(firingNeuronId); ArrayList <Synapse> interNodeSynapses = synMan.getFiringNeuronInterNodesSynapses(firingNeuronId); for(int i=0; i<synapses.size();++i){ if (synapses.get(i).getLastBurningTime()==null) continue; Double delta; delta=fireTime-synapses.get(i).getLastBurningTime(); if (delta < n.getPlasticityTo()){ Double wp=synapses.get(i).getPostSynapticWeight(); double wpold=wp; wp+=do_fast? (n.getPwMax()-wp)*n.getEtap()*fm.fastexp(-delta/n.getTaup()): (n.getPwMax()-wp)*n.getEtap()*Math.exp(-delta/n.getTaup()); synMan.setIntraNodePostSynapticWeight(synapses.get(i),wp); } } for(int i=0; i<interNodeSynapses.size();++i){ if (interNodeSynapses.get(i).getLastBurningTime()==null) continue; Double delta; delta=fireTime-interNodeSynapses.get(i).getLastBurningTime(); if (delta < n.getPlasticityTo()){ Double wp=interNodeSynapses.get(i).getPostSynapticWeight(); double wpold=wp; wp+=do_fast? (n.getPwMax()-wp)*n.getEtap()*fm.fastexp(-delta/n.getTaup()): (n.getPwMax()-wp)*n.getEtap()*Math.exp(-delta/n.getTaup()); synMan.setIntraNodePostSynapticWeight( interNodeSynapses.get(i), wp); } } } /** * Plasticity rule for burning events. * Update postsynaptic weight, decreasing it according to * the delta between the burning time * and the last firing time of the burning neuron. * @param syn * @param lastBurningTime * @param fireTime */ private void burning_ltd( Synapse syn, Double burningTime, Double lastFiringTime){ if (!plasticity) return; if (syn.getBurning()==null) return; syn.setLastBurningTime(burningTime); Double delta; delta=burningTime-lastFiringTime; if (delta < n.getPlasticityTo()){ Double wp=syn.getPostSynapticWeight(); double wpold=wp; wp -= do_fast? wp*n.getEtam()*fm.fastexp(-delta/n.getTaum()): wp*n.getEtam()*Math.exp(-delta/n.getTaum()); if (wp<0) wp=0.0; synMan.setIntraNodePostSynapticWeight(syn,wp); } } /** * Elicit a spike from the firing neuron to each connected burning. * * @param firingNeuronId * @param currentTime */ private void makeNeuronFire(Long firingNeuronId, Double currentTime){ ArrayList <Synapse> synapses = synMan.getFiringNeuronSynapses(firingNeuronId); ArrayList <Synapse> interNodeSynapses = synMan.getFiringNeuronInterNodesSynapses(firingNeuronId); if (n.isExternalInput(firingNeuronId)){ int eod=n.getExternalOutDegree(); int eoj=n.getExternalOutJump(); if (eod==1){ burnNeuron( null, firingNeuronId, n.getId(), firingNeuronId%n.getN(), n.getId(), 0.1, 1.0, n.getExternalAmplitude(), currentTime, currentTime, true); } else for (int i=0; i<eod; ++i){ burnNeuron( null, firingNeuronId, n.getId(), (firingNeuronId+(eoj*i))%n.getN(), n.getId(), 0.1, 1.0, n.getExternalAmplitude(), currentTime, currentTime, true); } return; } for (int i=0; i<synapses.size();++i){ fire_ltp( synapses.get(i), currentTime); // this is an inter-node synapse, the burning node // must deal with this spike if (!(synapses.get(i).getBurningNodeId().equals(n.getId()))){ continue; } burnNeuron(synapses.get(i), currentTime, currentTime, false); for (int j=1; j<n.getBn(); ++j) burningQueueSpikes.add( new FixedBurnSpike(synapses.get(i), (currentTime+n.getIBI()*j), currentTime)); } for (int i=0; i<interNodeSynapses.size();++i){ for (int j=0; j<n.getBn(); ++j) addInterNodeFire(interNodeSynapses.get(i), (currentTime+n.getIBI()*j)); } } public void burnNeuron( Synapse s, Double burnTime, Double fireTime, Boolean fromExternalInput){ burnNeuron( s, s.getFiring(), s.getFiringNodeId(), s.getBurning(), s.getBurningNodeId(), s.getLength(), s.getPostSynapticWeight(), s.getPreSynapticWeight(), burnTime, fireTime, fromExternalInput); } public void burnNeuron( Synapse s, long firingNeuronId, int firingNodeId, long burningNeuronId, int burningNodeId, double axon_length, double postsynapticWeight, double presynapticWeight, double burnTime, double fireTime, boolean fromExternalInput){ double tmp, dsxNumerator, dsxDenominator, riseTermXFactor, oldSx; int arp; //distinguish cases of no initial network activity : already activated arp=(nnMan.getLastFiringTime(burningNeuronId).equals(Constants.TIME_TO_FIRE_DEF_VAL))?0:1; //absolutely refractory period check if (burnTime>=(( nnMan.getLastFiringTime(burningNeuronId)+ nnMan.getT_arp()+ ((n.getBn()-1)*n.getIBI())) *arp) ){ long startTime = System.currentTimeMillis(); if (!fromExternalInput) burning_ltd( s, burnTime, nnMan.getLastFiringTime(burningNeuronId)); tmp=nnMan.getState(burningNeuronId); //passive state linear decay if (tmp<nnMan.getSpikingThr()){ Double decay; //linear decay if (!exp_decay){ decay = ( nnMan.getLinearDecayD(burningNeuronId)* (burnTime- (nnMan.getLastBurningTime( burningNeuronId)))); nnMan.setState( burningNeuronId, tmp-decay); } //exponential decay //Sj = Spj + A * W -Tl = A W + Spj e^(-delta t / D) //Tl = Spj (1 - e^(-delta t / D)) //if (exp_decay){ else{ decay = do_fast? ( tmp * ( 1 - fm.fastexp( - ( burnTime - nnMan.getLastBurningTime(burningNeuronId) )/ nnMan.getLinearDecayD(burningNeuronId))) ):( tmp * ( 1 - Math.exp( -(burnTime- nnMan.getLastBurningTime(burningNeuronId) )/ nnMan.getLinearDecayD(burningNeuronId))) ); nnMan.setState( burningNeuronId, tmp-decay); } if (nnMan.getState(burningNeuronId)<0.0) nnMan.setState(burningNeuronId, 0.0); } times[0]+=System.currentTimeMillis()-startTime; startTime = System.currentTimeMillis(); //BURNING NEURON double sx = nnMan.getState(burningNeuronId); oldSx=sx; //step in state double sy = postsynapticWeight*presynapticWeight; // UPDATING List of Active Neurons // case of passive neuron if (nnMan.getTimeToFire(burningNeuronId) .equals(Constants.TIME_TO_FIRE_DEF_VAL)){ oldSx=sx; sx = ((sx+sy)<0)?0:sx+sy; nnMan.setState(burningNeuronId, sx); //passive to active if (sx>=nnMan.getSpikingThr()){ //nnMan.setTimeToFire(s.getBurning(), burnTime+ 1.0/(sx-1)); if (lif) nnMan.setTimeToFire( burningNeuronId, burnTime+Constants.EPSILON); else{ double activeTransitionDelay=(1.0/(sx-1)); nnMan.setTimeToFire( burningNeuronId, burnTime+ activeTransitionDelay); } //if(isNOI) // sc.collectPassive2active(); nnMan.addActiveNeuron( burningNeuronId, nnMan.getTimeToFire(burningNeuronId), currentTime, 2); } //else{ // if(isNOI) // sc.collectPassive(); //} times[1]+=System.currentTimeMillis()-startTime; } // case of active neuron // avoid update on lif else if (!lif){ //else { if (nnMan.getTimeToFire(burningNeuronId)==0.0) nnMan.setTimeToFire(burningNeuronId, Constants.EPSILON); if (sx>=nnMan.getSpikingThr()){ nnMan.removeActiveNeuron(burningNeuronId); if ( (burnTime < nnMan.getTimeToFire(burningNeuronId) ) && (!nnMan.getLastBurningTime(burningNeuronId) .equals(Constants.BURNING_TIME_DEF_VAL)) ){ //Rise Term riseTermXFactor= (burnTime==nnMan.getLastBurningTime(burningNeuronId))? Constants.EPSILON : ( burnTime-nnMan.getLastBurningTime(burningNeuronId)); tmp=(sx-1)*riseTermXFactor; dsxNumerator = (sx-1)*tmp; dsxDenominator= 1.0-tmp; sx+=(dsxNumerator/dsxDenominator); } oldSx=sx; sx += sy; nnMan.setState(burningNeuronId,sx); //active to passive if (sx<nnMan.getSpikingThr()){ nnMan.removeActiveNeuron(burningNeuronId); nnMan.resetTimeToFire(burningNeuronId); //if (isNOI) // sc.collectActive2passive(); } else{ //updating firing delay nnMan.setTimeToFire(burningNeuronId, burnTime + 1.0/(sx-1)); nnMan.setState(burningNeuronId, sx); nnMan.addActiveNeuron( burningNeuronId, nnMan.getTimeToFire(burningNeuronId), currentTime, 3); //if(isNOI) // sc.collectActive(); } //active to passive if (sx<0){ sx=0.0; oldSx=sx; nnMan.setState(burningNeuronId,sx); nnMan.removeActiveNeuron(burningNeuronId); nnMan.resetTimeToFire(burningNeuronId); //if(isNOI) // sc.collectActive2passive(); } } else{ oldSx=sx; nnMan.removeActiveNeuron(burningNeuronId); nnMan.resetTimeToFire(burningNeuronId); //if(isNOI) // sc.collectActive2passive(); } times[2]+=System.currentTimeMillis()-startTime; } //end of case of active neuron startTime = System.currentTimeMillis(); nnMan.setLastBurningTime(burningNeuronId, burnTime); times[4]+=System.currentTimeMillis()-startTime; // collecting the spike if(isNOI) <<<<<<< HEAD sc.collectBurnSpike( ======= nbt.collectBurnSpike( >>>>>>> 48bb69b3e778691a096596083425b528609c0729 firingNeuronId, firingNodeId, burningNeuronId, burningNodeId, burnTime, fromExternalInput, oldSx, sy, postsynapticWeight, presynapticWeight, nnMan.getTimeToFire(burningNeuronId), fireTime); times[3]+=System.currentTimeMillis()-startTime; } else{ // collecting the spike if(isNOI) <<<<<<< HEAD sc.collectBurnSpike( ======= nbt.collectBurnSpike( >>>>>>> 48bb69b3e778691a096596083425b528609c0729 firingNeuronId, firingNodeId, burningNeuronId, burningNodeId, burnTime, fromExternalInput, null, null, postsynapticWeight, presynapticWeight, nnMan.getTimeToFire(burningNeuronId), fireTime); } } public void burnInterNodeSpike(InterNodeSpike irs){ // the comparison is done against the stoptime, since when this method is called // it still holds the value for the last split run (not the current one) and // current time may hold a very old value. if (irs.getBurnTime()>=stopTime) interNodeBurningSpikes.add(new InterNodeBurningSpike(irs, irs.getBurnTime())); else{ sc.collectMissedFire(irs.getAxonalDelay()); println("missed fire at time:"+ irs.getBurnTime()+ ", axonal del:"+ irs.getAxonalDelay()+ ", fire time:"+ irs.getFireTime()+ ", current time:"+ currentTime+ ", syn:"+ irs.getSyn()); } } private void initExtInput(){ println("initializing external input..."); for (int j=0; j<n.getExternalInputs();++j){ nnMan.extInputReset(n.getN()+j,0.0); } println("external input initialization done."); } //======================================= thread functions ======================================= public void runNewSplit(double newStopTime){ /* * current time is updated with the last value for stoptime, ccause otherwise it can hold * value belonging to a past split and then could generate inconsistency against * spikes coming frmo external nodes */ startTime=stopTime; if (currentTime<stopTime) currentTime=stopTime; stopTime = newStopTime; lock.lock(); newTimeSplitCond.signal(); lock.unlock(); } private void completed(){ double oldStopTime=stopTime; print_times(); if (nMan.splitComplete(getNodeId())){ lock.lock(); try { newTimeSplitCond.await(); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); } else{ while (keepRunning && (stopTime<=oldStopTime) ){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void kill(){ keepRunning=false; lock.lock(); newTimeSplitCond.signal(); lock.unlock(); } //======================================= printing function ======================================= public void printQueues(){ Iterator<Synapse> it = queuesMap.keySet().iterator(); println("Printing queues:"); while (it.hasNext()){ Synapse s = it.next(); System.out.println(s + ": "); ((NiceQueue)queuesMap.get(s)).printQueue(); } System.out.println(); } private void println(String s){ if (verbose){ if (nMan != null) System.out.println(TAG+getNodeId()+"/"+(nMan.getNodeThreadsNum()-1)+"] "+s); else System.out.println(TAG+getNodeId()+"/-] "+s); } } private void debprintln(String s){ if (verbose&&debug) System.out.println(TAG+getNodeId()+"/"+(nMan.getNodeThreadsNum()-1)+" [debug] ] "+s); } private void leveldebprintln(String s, int level){ if (this.debug_level>=level) debprintln(s); } private void debActiveprintln(String s){ if (verbose&&debug&&activePassiveDebug) System.out.println(TAG+getNodeId()+"/"+(nMan.getNodeThreadsNum()-1)+"[debug] ] "+s); } public void printDebug(){ println("max pw approximation:"+debugMaxWPDiff); System.out.println(); } public void print_times() { return; // for (int i=0; i<5;++i) // println("times["+i+"]: "+times[i]); } }