Spiking Neuron Network Simulator  1.0
Simulation and training of spiking neuron networks, primarily theta neurons
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
SpikePriorityQueue.cs
Go to the documentation of this file.
1 namespace SpikingNeuronNetwork.Lib
2 {
3  using System;
4  using System.Collections;
5  using System.Collections.Generic;
6  using System.Linq;
7 
11  public class SpikePriorityQueue : ICollection<Spike>
12  {
16  private readonly SortedDictionary<double, Queue<int>> _baseQueue;
17 
24  public static SpikePriorityQueue CreateSpikeQueue(IEnumerable<Spike> inputSpikes, double currentTime)
25  {
26  var inputSpikeTimesList = inputSpikes.ToList();
27  var spikeQueue = new SpikePriorityQueue(inputSpikeTimesList);
28  if (spikeQueue.Count == 0)
29  {
30  return spikeQueue;
31  }
32 
33  // Protect against non-causality
34  while (currentTime > spikeQueue.PeekTime())
35  {
36  spikeQueue.Dequeue();
37  }
38 
39  return spikeQueue;
40  }
41 
42 
47  public SpikePriorityQueue(IEnumerable<Spike> inputSpikes)
48  : this()
49  {
50  foreach (var inputSpike in inputSpikes)
51  {
52  Add(inputSpike);
53  }
54  }
55 
60  {
61  _baseQueue = new SortedDictionary<double, Queue<int>>();
62  }
63 
64  #region Priority queue operations
65 
69  public void Enqueue(Spike inputSpike)
70  {
71  if (_baseQueue.ContainsKey(inputSpike.Time))
72  {
73  _baseQueue[inputSpike.Time].Enqueue(inputSpike.NeuronIndex);
74  }
75  else
76  {
77  _baseQueue.Add(inputSpike.Time, new Queue<int>(new[] {inputSpike.NeuronIndex}));
78  }
79  }
80 
88  public Spike Dequeue()
89  {
90  if (!IsEmpty)
91  {
92  var result = Peek();
93  Remove(result);
94  return result;
95  }
96  throw new InvalidOperationException("Priority queue is empty");
97  }
98 
106  public int DequeueValue()
107  {
108  return Dequeue().NeuronIndex;
109  }
110 
118  public Spike Peek()
119  {
120  if (!IsEmpty)
121  {
122  var first = _baseQueue.First();
123  return new Spike { Time = first.Key, NeuronIndex = first.Value.Peek()};
124  }
125  throw new InvalidOperationException("Priority queue is empty");
126  }
127 
135  public double PeekTime()
136  {
137  return Peek().Time;
138  }
139 
143  public bool IsEmpty
144  {
145  get { return _baseQueue.Count == 0; }
146  }
147 
154  public bool Update(Spike oldSpike, double newFiringTime)
155  {
156  if (!Remove(oldSpike))
157  return false;
158  if (!Double.IsInfinity(newFiringTime))
159  {
160  Add(new Spike { Time = newFiringTime, NeuronIndex = oldSpike.NeuronIndex });
161  }
162  return true;
163  }
164 
169  public void AddRange(ICollection<Spike> spikes)
170  {
171  foreach (var spike in spikes)
172  {
173  Add(spike);
174  }
175  }
176 
177  #endregion
178 
179  #region ICollection<Spike> implementation
180 
185  public void Add(Spike spike)
186  {
187  Enqueue(spike);
188  }
189 
193  public void Clear()
194  {
195  _baseQueue.Clear();
196  }
197 
203  public bool Contains(Spike spike)
204  {
205  if (!_baseQueue.ContainsKey(spike.Time))
206  {
207  return false;
208  }
209  return _baseQueue[spike.Time].Contains(spike.NeuronIndex);
210  }
211 
215  public int Count
216  {
217  get { return _baseQueue.Sum(x => x.Value.Count); }
218  }
219 
228  public void CopyTo(Spike[] array, int arrayIndex)
229  {
230  var arrayList = new List<Spike>();
231  foreach (var kvp in _baseQueue)
232  {
233  var queueList = kvp.Value.ToList();
234  arrayList.AddRange(queueList.Select(item => new Spike { Time = kvp.Key, NeuronIndex = item}));
235  }
236  arrayList.CopyTo(array, arrayIndex);
237  }
238 
245  public bool IsReadOnly
246  {
247  get { return false; }
248  }
249 
256  public bool Remove(Spike spike)
257  {
258  // find element in the collection and remove it
259  if (!_baseQueue.ContainsKey(spike.Time))
260  {
261  return false;
262  }
263  if (_baseQueue[spike.Time].Count == 1)
264  {
265  _baseQueue.Remove(spike.Time);
266  return true;
267  }
268  // This is expensive, should be avoided
269  var queueList = _baseQueue[spike.Time].ToList();
270  queueList.Remove(spike.NeuronIndex);
271  _baseQueue[spike.Time] = new Queue<int>(queueList);
272  return true;
273  }
274 
281  public IEnumerator<Spike> GetEnumerator()
282  {
283  return (from kvp in _baseQueue
284  from item in kvp.Value.ToList()
285  select new Spike{ Time = kvp.Key, NeuronIndex = item}).GetEnumerator();
286  }
287 
294  IEnumerator IEnumerable.GetEnumerator()
295  {
296  return GetEnumerator();
297  }
298 
299  #endregion
300  }
301 }
int DequeueValue()
Dequeues spike with next firing time and returns its index
SpikePriorityQueue()
Initializes a new instance of the spike priority queue
Spike Peek()
Returns the spike with next firing time, without removing it from the queue
static SpikePriorityQueue CreateSpikeQueue(IEnumerable< Spike > inputSpikes, double currentTime)
Creates a new spike priority queue
void Enqueue(Spike inputSpike)
Enqueues spike into the priority queue
double Time
Gets or sets the time.
Definition: Spike.cs:30
void Add(Spike spike)
Enqueus spike into priority queue
bool Update(Spike oldSpike, double newFiringTime)
Updates a spike in the queue with a new firing time
bool Contains(Spike spike)
Determines whether the priority queue contains a specific spike
void AddRange(ICollection< Spike > spikes)
Adds a range of spikes to the priority queue
Spike Priority Queue used for determining what spike to process next based on spike timing ...
SpikePriorityQueue(IEnumerable< Spike > inputSpikes)
Initializes a new instance of priority queue with specified input spikes
Spike Dequeue()
Dequeues spike with next firing time and returns the spike/>
void CopyTo(Spike[] array, int arrayIndex)
Copies the spikes of the priority queue to an Array, starting at a particular Array index...
IEnumerator< Spike > GetEnumerator()
Returns an enumerator that iterates through the collection.
double PeekTime()
Returns the next firing time of a spike, without removing the spike from the queue ...
bool Remove(Spike spike)
Removes the first occurrence of a specific spike from the priority queue.