1 module anansi.algorithms.vertex_queue; 2 3 import anansi.container.priorityqueue; 4 import anansi.traits; 5 import anansi.types; 6 import std.math; 7 8 version(unittest) { import std.stdio; import anansi.adjacencylist; } 9 10 11 /** 12 * A priority queue item for sorting vertices by the cost to get to them. 13 */ 14 15 package struct VertexQueue(GraphT, DistanceMapT) { 16 static assert(isGraph!GraphT); 17 static assert(isPropertyMap!(DistanceMapT, GraphT.VertexDescriptor, real)); 18 19 alias Vertex = GraphT.VertexDescriptor; 20 21 package static struct Item { 22 public Vertex vertex; 23 public real cost; 24 25 public int opCmp(ref const(Item) other) const { 26 return cast(int) sgn(other.cost - this.cost); 27 } 28 } 29 30 this(ref const(DistanceMapT) distances) { 31 _distanceMap = &distances; 32 } 33 34 public void push(Vertex v) { 35 const auto distance = (*_distanceMap)[v]; 36 _queue.push(Item(v, distance)); 37 } 38 39 public void pop() { 40 _queue.pop(); 41 } 42 43 public Vertex front() const { 44 return _queue.front.vertex; 45 } 46 47 public void updateVertex(Vertex v) { 48 const auto distance = (*_distanceMap)[v]; 49 _queue.updateIf((ref Item x) => x.vertex == v, 50 (ref Item i) => i.cost = distance); 51 } 52 53 @property public bool empty() const { 54 return _queue.empty; 55 } 56 57 @property public size_t length() const { 58 return _queue.length; 59 } 60 61 PriorityQueue!Item _queue; 62 const (DistanceMapT*) _distanceMap; 63 } 64 65 unittest { 66 writeln("VertexQueue: queue items are ordered by increasing cost."); 67 alias G = AdjacencyList!(); 68 alias V = G.VertexDescriptor; 69 alias Item = VertexQueue!(G, real[V]).Item; 70 71 auto a = Item(0, 0.1); 72 auto b = Item(0, 0.2); 73 74 assert (a > b); 75 assert (!(b > a)); 76 assert (b < a); 77 assert (!(a < b)); 78 assert (a != b); 79 }