/// <summary> /// Thanks to Morton Mertner for a fix here /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public static IDigraph DijkstrasAlgorithm(IDigraph g, int s) { int n = g.NumberOfVertices; Entry[] table = new Entry[n]; for (int v = 0; v < n; ++v) { table[v] = new Entry(false, int.MaxValue, int.MaxValue); } table[s].distance = 0; IPriorityQueue queue = new BinaryHeap(g.NumberOfEdges); queue.Enqueue(new Association(0, g.GetVertex(s))); int vertexCount = 0; // MM fix while (!queue.IsEmpty) { Association assoc = (Association)queue.DequeueMin(); IVertex v0 = (IVertex)assoc.Value; if (!table[v0.Number].known) { table[v0.Number].known = true; vertexCount++; // MM fix foreach (IEdge e in v0.EmanatingEdges) { IVertex v1 = e.MateOf(v0); int d = table[v0.Number].distance + (e.Weight != null ? (int)e.Weight : 0); if (table[v1.Number].distance > d) { table[v1.Number].distance = d; table[v1.Number].predecessor = v0.Number; queue.Enqueue(new Association(d, v1)); } } } } // MM fixed loop to filter out unused edges and vertices IDigraph result = new DigraphAsLists(vertexCount); int cv = 0; int[] v2cv = new int[n]; for (int v = 0; v < n; ++v) { if (table[v].known) { result.AddVertex(cv, table[v].distance); v2cv[v] = cv++; } } for (int v = 0; v < n; ++v) { if (v != s && table[v].known && table[v].distance < int.MaxValue) { result.AddConnection(v2cv[v], v2cv[table[v].predecessor]); } } return(result); }
/// <summary> /// Critical path analysis algorithm /// </summary> /// <param name="g"></param> /// <returns></returns> public static IDigraph CriticalPathAnalysis(IDigraph g) { //TODO: more info here int i = g.NumberOfVertices; int[] nums1 = new int[(uint)i]; nums1[0] = 0; g.TopologicalOrderTraversal(new EarliestTimeVisitor(nums1)); int[] nums2 = new int[(uint)i]; nums2[i - 1] = nums1[i - 1]; g.DepthFirstTraversal(new PostOrder(new LatestTimeVisitor(nums2)), 0); IDigraph digraph1 = new DigraphAsLists(i); for (int j = 0; j < i; j++) { digraph1.AddVertex(j); } IEnumerator iEnumerator = g.Edges.GetEnumerator(); try { while (iEnumerator.MoveNext()) { IEdge edge = (IEdge)iEnumerator.Current; int k = nums2[edge.V1.Number] - nums1[edge.V0.Number] - (int)edge.Weight; digraph1.AddConnection(edge.V0.Number, edge.V1.Number, (int)edge.Weight); } } finally { IDisposable iDisposable = iEnumerator as IDisposable; if (iDisposable != null) { iDisposable.Dispose(); } } return(DijkstrasAlgorithm(digraph1, 0)); }