/// <summary> /// check that algorithm computes either the topological order or finds a directed cycle /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void dfs(EdgeWeightedDigraph g, int v) { onStack[v] = true; marked[v] = true; foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); //short circuit if directed cycle found if (cycle != null) { return; } else if (!marked[v]) //found new vertex { edgeTo[w] = e; dfs(g, w); } // trace back directed cycle else if (onStack[w]) { cycle = new Stack <DirectedEdge>(); DirectedEdge de = e; while (de.From() != w) { cycle.Push(de); de = edgeTo[de.From()]; } cycle.Push(de); } } onStack[v] = false; }
public static double Cpm(List <Job> jobs) { //the jobs id start from 0 to n-1 int n = jobs.Count; for (int i = 0; i < n; i++) { jobs[i].JobID = i; } //source and sink vertex int source = 2 * n; int sink = 2 * n + 1; //build network EdgeWeightedDigraph g = new EdgeWeightedDigraph(2 * n + 2); for (int i = 0; i < n; i++) { g.AddEdge(new DirectedEdge(source, i, 0)); g.AddEdge(new DirectedEdge(i + n, sink, 0)); g.AddEdge(new DirectedEdge(i, i + n, jobs[i].Duration)); foreach (var job in jobs[i].Constaints) { g.AddEdge(new DirectedEdge(job.JobID + n, i, 0)); } } //compute longest paths AcyclicLP lp = new AcyclicLP(g, source); return(lp.DistTo(sink)); }
public DijkstraAllPairsSP(EdgeWeightedDigraph g) { all = new DijkstraSP[g.V]; for (int v = 0; v < g.V; v++) { all[v] = new DijkstraSP(g, v); } }
/// <summary> /// topological sort in an edge-weighted digraph /// </summary> /// <param name="g"></param> public Topological(EdgeWeightedDigraph g) { EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(g); if (!finder.HasCycle()) { DepthFirstOrder dfs = new DepthFirstOrder(g); order = dfs.ReversePost(); } }
private Stack <DirectedEdge> cycle; // directed cycle (or null if no such cycle) public EdgeWeightedDirectedCycle(EdgeWeightedDigraph g) { marked = new bool[g.V]; onStack = new bool[g.V]; edgeTo = new DirectedEdge[g.V]; for (int v = 0; v < g.V; v++) { if (!marked[v]) { dfs(g, v); } } }
/// <summary> /// depth-first search preorder and postorder in an edge-weighted digraph /// </summary> /// <param name="g"></param> public DepthFirstOrder(EdgeWeightedDigraph g) { pre = new int[g.V]; post = new int[g.V]; postorder = new Queue <int>(); preorder = new Queue <int>(); marked = new bool[g.V]; for (int v = 0; v < g.V; v++) { if (!marked[v]) { dfs(g, v); } } }
/// <summary> /// by finding a cycle in predecessor graph /// </summary> private void findNegativeCycle() { int v = edgeTo.Length; EdgeWeightedDigraph spt = new EdgeWeightedDigraph(v); for (int w = 0; w < v; w++) { if (edgeTo[v] != null) { spt.AddEdge(edgeTo[v]); } } EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt); cycle = finder.Cycle(); }
/// <summary> /// copy constructor /// </summary> /// <param name="g"></param> public EdgeWeightedDigraph(EdgeWeightedDigraph g) : this(g.V) { this.e = g.e; for (int v = 0; v < g.V; v++) { // reverse so that adjacency list is in same order as original Stack <DirectedEdge> reverse = new Stack <DirectedEdge>(); foreach (DirectedEdge directedEdge in g.adj[v]) { reverse.Push(directedEdge); } foreach (DirectedEdge directedEdge in reverse) { adj[v].Add(directedEdge); } } }
/// <summary> /// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorder /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void dfs(EdgeWeightedDigraph g, int v) { if (marked[v]) { return; } marked[v] = true; pre[v] = preCounter++; preorder.Enqueue(v); foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); if (!marked[w]) { dfs(g, w); } } postorder.Enqueue(v); post[v] = postCounter++; }
public AcyclicSP(EdgeWeightedDigraph g, int s) { distTo = new double[g.V]; edgeTo = new DirectedEdge[g.V]; for (int v = 0; v < g.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; //visit vertices in toplogical order Topological topological = new Topological(g); foreach (int v in topological.Order()) { foreach (DirectedEdge e in g.Adj(v)) { relax(e); } } }
/// <summary> /// relax vertex v and put other endpoints on queue if changed /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void relax(EdgeWeightedDigraph g, int v) { foreach (DirectedEdge e in g.Adj(v)) { int w = e.To(); if (distTo[w] > distTo[v] + e.Weight()) { distTo[w] = distTo[v] + e.Weight(); edgeTo[w] = e; if (!onQueue[w]) { queue.Enqueue(w); onQueue[w] = true; } } if (cost++ % g.V == 0) { findNegativeCycle(); } } }
public BellmanFordSP(EdgeWeightedDigraph g, int s) { distTo = new double[g.V]; edgeTo = new DirectedEdge[g.V]; onQueue = new bool[g.V]; for (int v = 0; v < g.V; v++) { distTo[v] = double.PositiveInfinity; } distTo[s] = 0.0; //bellman-ford algorithm queue = new Queue <int>(); queue.Enqueue(s); onQueue[s] = true; while (!(queue.Count == 0) && !HasNegativeCycle()) { int v = queue.Dequeue(); onQueue[v] = false; relax(g, v); } }
/// <summary> /// check optimality conditions /// (1)for all edge e: distTo[e.to()] <= distTo[e.from()] + e.weight() /// (2) for all edge e on the SPT: distTo[e.to()] == distTo[e.from()] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { //check that edge weights are nonnegative foreach (DirectedEdge e in g.Adj(s)) { int w = e.To(); if (e.Weight() < 0) { return(false); } } //check that distTo[v] and edgeTo[v] are consistent if (System.Math.Abs(distTo[s] - 0.0) > EPSILON || edgeTo[s] != null) { return(false); } for (int v = 0; v < g.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { return(false); } } //check all edges e = v-->w statisfy distTo[w] <= distTo[v] + e.weight() for (int v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { int w = e.To(); if (distTo[v] == double.PositiveInfinity || distTo[w] == double.PositiveInfinity) { continue; } if (distTo[v] + e.Weight() < distTo[w]) { return(false); } } } //check that all edge e = v-->w on spt satisfy distTo[w] = distTo[v] + e.weight() for (int w = 0; w < g.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From(); if (w != e.To()) { return(false); } if (distTo[v] + e.Weight() != distTo[w]) { return(false); } } return(true); }
/// <summary> /// check optimality conditions:either /// (1) there exists a negative cycle reachable from s /// (2) for all edges e = v-->w: distTo[w] <= distTo[v] + e.weight() /// (3) for all edges e = v-->w on the SPT: distTo[w] == distTo[v] + e.weight() /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public bool Check(EdgeWeightedDigraph g, int s) { //has a negative cycle if (HasNegativeCycle()) { double weight = 0.0; foreach (DirectedEdge e in NegativeCycle()) { weight += e.Weight(); } if (weight >= 0) { return(false); } } else { //no negative cycle reachable from s if (distTo[s] != 0.0 || edgeTo[s] != null) { return(false); } for (int v = 0; v < g.V; v++) { if (v == s) { continue; } if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity) { return(false); } } //check that all edges e=v-->w satisfy distTo[w]<=distTo[v]+e.weight() for (int v = 0; v < g.V; v++) { foreach (var e in g.Adj(v)) { int w = e.To(); if (distTo[v] + e.Weight() < distTo[w]) { return(false); } } } //check that all edges e = v-->w on spt satisfy distTo[w] == distTo[v] + e.weight() for (int w = 0; w < g.V; w++) { if (edgeTo[w] == null) { continue; } DirectedEdge e = edgeTo[w]; int v = e.From(); if (w != e.To()) { return(false); } if (distTo[v] + e.Weight() != distTo[w]) { return(false); } } } return(true); }