Free cookie consent management tool by TermsFeed Policy Generator

source: branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/PriorityQueue.cs @ 14767

Last change on this file since 14767 was 14767, checked in by gkronber, 7 years ago

#2700: made some changes while reviewing the code

File size: 6.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25
26namespace HeuristicLab.Algorithms.DataAnalysis {
27
28  // Code Taken from branch: RoutePlanning, Heap4
29  // implementation based on C++ version from Peter Sanders
30  // http://www.mpi-inf.mpg.de/~sanders/programs/spq/
31  public sealed class PriorityQueue<TK, TV> where TK : IComparable {
32    private class KNElement {
33      public TK Key { get; set; }
34      public TV Value { get; set; }
35    }
36
37    private readonly int capacity;
38    private int size; // index of last used element
39    private int finalLayerSize; // size of first layer with free space
40    private int finalLayerDist; // distance to end of layer
41                                //private KNElement[] rawData;
42    private readonly KNElement[] data;    // aligned version of rawData
43
44    public PriorityQueue(TK supremum, TK infimum, int cap) {
45      capacity = cap;
46      data = Enumerable.Range(0, capacity + 4).Select(x => new KNElement()).ToArray();
47
48      data[0].Key = infimum; // sentinel
49      data[capacity + 1].Key = supremum;
50      data[capacity + 2].Key = supremum;
51      data[capacity + 3].Key = supremum;
52      Reset();
53    }
54
55    public int Size {
56      get { return size; }
57    }
58
59    public TK Supremum {
60      get { return data[capacity + 1].Key; }
61    }
62
63    public KeyValuePair<TK, TV> PeekMin() {
64      if(size == 0) {
65        throw new InvalidOperationException("Heap is empty");
66      }
67      return new KeyValuePair<TK, TV>(data[1].Key, data[1].Value);
68    }
69
70    public TK PeekMinKey() {
71      return data[1].Key;
72    }
73
74    public TV PeekMinValue() {
75      return data[1].Value;
76    }
77
78    public void RemoveMin() {
79      // first move up elements on a min-path
80      var hole = 1;
81      var succ = 2;
82      var layerSize = 4;
83      var layerPos = 0;
84      var sz = size;
85      size = sz - 1;
86      finalLayerDist++;
87      if(finalLayerDist == finalLayerSize) {
88        finalLayerSize >>= 2;
89        finalLayerDist = 0;
90      }
91
92      while(succ < sz) {
93        var minKey = data[succ].Key;
94        var delta = 0;
95
96        var otherKey = data[succ + 1].Key;
97        if(otherKey.CompareTo(minKey) < 0) {
98          minKey = otherKey;
99          delta = 1;
100        }
101        otherKey = data[succ + 2].Key;
102        if(otherKey.CompareTo(minKey) < 0) {
103          minKey = otherKey;
104          delta = 2;
105        }
106        otherKey = data[succ + 3].Key;
107        if(otherKey.CompareTo(minKey) < 0) {
108          minKey = otherKey;
109          delta = 3;
110        }
111        succ += delta;
112        layerPos += delta;
113
114        // move min successor up
115        data[hole].Key = minKey;
116        data[hole].Value = data[succ].Value;
117
118        // step to next layer
119        hole = succ;
120        succ = succ - layerPos + layerSize; // beginning of next layer
121        layerPos <<= 2;
122        succ += layerPos; // now correct value
123        layerSize <<= 2;
124      }
125
126      // bubble up rightmost element
127      var bubble = data[sz].Key;
128      layerSize >>= 2; // now size of hole's layer
129      layerPos >>= 2; // now pos of hole within its layer
130
131      var layerDist = layerSize - layerPos - 1; // hole's dist to end of layer
132      var pred = hole + layerDist - layerSize; // end of pred's layer for now
133      layerSize >>= 2; // now size of pred's layer
134      layerDist >>= 2; // now pred's pos in layer
135      pred = pred - layerDist; // finally preds index
136
137      while(data[pred].Key.CompareTo(bubble) > 0) {  // must terminate since inf at root
138        data[hole].Key = data[pred].Key;
139        data[hole].Value = data[pred].Value;
140        hole = pred;
141        pred = hole + layerDist - layerSize; // end of hole's layer for now
142        layerSize >>= 2;
143        layerDist >>= 2;
144        pred = pred - layerDist; // finally preds index
145      }
146
147      // finally move data to hole
148      data[hole].Key = bubble;
149      data[hole].Value = data[sz].Value;
150
151      data[sz].Key = Supremum; // mark as deleted
152    }
153
154    public void Insert(TK key, TV value) {
155      var layerSize = finalLayerSize;
156      var layerDist = finalLayerDist;
157      finalLayerDist--;
158
159      if(finalLayerDist == -1) { // layer full
160                                 // start next layer
161        finalLayerSize <<= 2;
162        finalLayerDist = finalLayerSize - 1;
163      }
164
165      size++;
166
167      var hole = size;
168      var pred = hole + layerDist - layerSize; // end of pred's layer for now
169      layerSize >>= 2; // now size of pred's layer
170      layerDist >>= 2;
171      pred = pred - layerDist; // finally preds index
172      var predKey = data[pred].Key;
173      while(predKey.CompareTo(key) > 0) {
174        data[hole].Key = predKey;
175        data[hole].Value = data[pred].Value;
176        hole = pred;
177        pred = hole + layerDist - layerSize; // end of pred's layer for now
178        layerSize >>= 2; // now isze of pred's layer
179        layerDist >>= 2;
180        pred = pred - layerDist; // finally preds index
181        predKey = data[pred].Key;
182      }
183
184      // finally move data to hole
185      data[hole].Key = key;
186      data[hole].Value = value;
187    }
188
189    // reset size to 0 and fill data array with sentinels
190    private void Reset() {
191      size = 0;
192      finalLayerSize = 1;
193      finalLayerDist = 0;
194      var sup = Supremum;
195      var cap = capacity;
196      for(var i = 1; i <= cap; i++) {
197        data[i].Key = sup;
198      }
199    }
200  }
201}
Note: See TracBrowser for help on using the repository browser.