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 }