Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2520: changed all usages of StorableClass to use StorableType with an auto-generated GUID (did not add StorableType to other type definitions yet)

File size: 6.3 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  // TODO: move to HeuristicLab.Collections
28
29  // Code Taken from branch: RoutePlanning, Heap4
30  // implementation based on C++ version from Peter Sanders
31  // http://www.mpi-inf.mpg.de/~sanders/programs/spq/
32  public sealed class PriorityQueue<TK, TV> where TK : IComparable {
33    private class KNElement {
34      public TK Key { get; set; }
35      public TV Value { get; set; }
36    }
37
38    private readonly int capacity;
39    private int size; // index of last used element
40    private int finalLayerSize; // size of first layer with free space
41    private int finalLayerDist; // distance to end of layer
42                                //private KNElement[] rawData;
43    private readonly KNElement[] data;    // aligned version of rawData
44
45    public PriorityQueue(TK supremum, TK infimum, int cap) {
46      capacity = cap;
47      data = Enumerable.Range(0, capacity + 4).Select(x => new KNElement()).ToArray();
48
49      data[0].Key = infimum; // sentinel
50      data[capacity + 1].Key = supremum;
51      data[capacity + 2].Key = supremum;
52      data[capacity + 3].Key = supremum;
53      Reset();
54    }
55
56    public int Size {
57      get { return size; }
58    }
59
60    public TK Supremum {
61      get { return data[capacity + 1].Key; }
62    }
63
64    public KeyValuePair<TK, TV> PeekMin() {
65      if (size == 0) {
66        throw new InvalidOperationException("Heap is empty");
67      }
68      return new KeyValuePair<TK, TV>(data[1].Key, data[1].Value);
69    }
70
71    public TK PeekMinKey() {
72      return data[1].Key;
73    }
74
75    public TV PeekMinValue() {
76      return data[1].Value;
77    }
78
79    public void RemoveMin() {
80      // first move up elements on a min-path
81      var hole = 1;
82      var succ = 2;
83      var layerSize = 4;
84      var layerPos = 0;
85      var sz = size;
86      size = sz - 1;
87      finalLayerDist++;
88      if (finalLayerDist == finalLayerSize) {
89        finalLayerSize >>= 2;
90        finalLayerDist = 0;
91      }
92
93      while (succ < sz) {
94        var minKey = data[succ].Key;
95        var delta = 0;
96
97        var otherKey = data[succ + 1].Key;
98        if (otherKey.CompareTo(minKey) < 0) {
99          minKey = otherKey;
100          delta = 1;
101        }
102        otherKey = data[succ + 2].Key;
103        if (otherKey.CompareTo(minKey) < 0) {
104          minKey = otherKey;
105          delta = 2;
106        }
107        otherKey = data[succ + 3].Key;
108        if (otherKey.CompareTo(minKey) < 0) {
109          minKey = otherKey;
110          delta = 3;
111        }
112        succ += delta;
113        layerPos += delta;
114
115        // move min successor up
116        data[hole].Key = minKey;
117        data[hole].Value = data[succ].Value;
118
119        // step to next layer
120        hole = succ;
121        succ = succ - layerPos + layerSize; // beginning of next layer
122        layerPos <<= 2;
123        succ += layerPos; // now correct value
124        layerSize <<= 2;
125      }
126
127      // bubble up rightmost element
128      var bubble = data[sz].Key;
129      layerSize >>= 2; // now size of hole's layer
130      layerPos >>= 2; // now pos of hole within its layer
131
132      var layerDist = layerSize - layerPos - 1; // hole's dist to end of layer
133      var pred = hole + layerDist - layerSize; // end of pred's layer for now
134      layerSize >>= 2; // now size of pred's layer
135      layerDist >>= 2; // now pred's pos in layer
136      pred = pred - layerDist; // finally preds index
137
138      while (data[pred].Key.CompareTo(bubble) > 0) {  // must terminate since inf at root
139        data[hole].Key = data[pred].Key;
140        data[hole].Value = data[pred].Value;
141        hole = pred;
142        pred = hole + layerDist - layerSize; // end of hole's layer for now
143        layerSize >>= 2;
144        layerDist >>= 2;
145        pred = pred - layerDist; // finally preds index
146      }
147
148      // finally move data to hole
149      data[hole].Key = bubble;
150      data[hole].Value = data[sz].Value;
151
152      data[sz].Key = Supremum; // mark as deleted
153    }
154
155    public void Insert(TK key, TV value) {
156      var layerSize = finalLayerSize;
157      var layerDist = finalLayerDist;
158      finalLayerDist--;
159
160      if (finalLayerDist == -1) { // layer full
161                                  // start next layer
162        finalLayerSize <<= 2;
163        finalLayerDist = finalLayerSize - 1;
164      }
165
166      size++;
167
168      var hole = size;
169      var pred = hole + layerDist - layerSize; // end of pred's layer for now
170      layerSize >>= 2; // now size of pred's layer
171      layerDist >>= 2;
172      pred = pred - layerDist; // finally preds index
173      var predKey = data[pred].Key;
174      while (predKey.CompareTo(key) > 0) {
175        data[hole].Key = predKey;
176        data[hole].Value = data[pred].Value;
177        hole = pred;
178        pred = hole + layerDist - layerSize; // end of pred's layer for now
179        layerSize >>= 2; // now isze of pred's layer
180        layerDist >>= 2;
181        pred = pred - layerDist; // finally preds index
182        predKey = data[pred].Key;
183      }
184
185      // finally move data to hole
186      data[hole].Key = key;
187      data[hole].Value = value;
188    }
189
190    // reset size to 0 and fill data array with sentinels
191    private void Reset() {
192      size = 0;
193      finalLayerSize = 1;
194      finalLayerDist = 0;
195      var sup = Supremum;
196      var cap = capacity;
197      for (var i = 1; i <= cap; i++) {
198        data[i].Key = sup;
199      }
200    }
201  }
202}
Note: See TracBrowser for help on using the repository browser.