CSC403 Oct31

slide version

single file version

Contents

  1. Graphs and Algorithms
  2. Shortest Paths in Digraphs
  3. Optimality Conditions
  4. Necessity of the Condition
  5. Relaxing an Edge
  6. Indexed minPriorityQueue
  7. Index minPriorityQueue Methods
  8. DijkstraSP
  9. AcyclicSP
  10. Longest Paths
  11. Critical Path Method

Graphs and Algorithms[1] [top]

Classes
Undirected Graph Algorithms
Digraph Algorithms

Shortest Paths in Digraphs[2] [top]

Assumptions

A necessary and sufficient condition for shortest path from a source vertex s to all reachable vertices w in a digraph applies to the array distTo no matter how it is calculated, provided it has these properties:

 distTo[v] = length of some path from s to v, or
 distTo[v] = Infinity if there is no directed path from s to v
    

Optimality Conditions[3] [top]

A necessary and sufficient condition for distTo[u] to be the shortest distance from s to u for every vertex u is

For every vertex v and every edge e

 distTo[w] <= distTo[v] + e.weight()   (where v = e.from() and w = e.to())
    

Necessity of the Condition[4] [top]

The optimality condition is necessary for distTo[u] to be the minimal length of paths from s to u.

If

      distTo[w] > distTo[v] + e.weight() for some v, w, and edge
      v-> w
    

The path from s to v followed by the edge from v to w would have total length

      distTo[v] + e.weight()
    

And so dist[w] would not be a minimal length for a path from s to w.

Relaxing an Edge[5] [top]

Suppose e is an edge from v to a vertex w.

distTo[v] is the length of some path from s to v

distTo[w] is the length of some path from s to w

We may be able to relax (i.e., decrease distTo[w]) by considering a different path from s to w:

      s to v, followed by the edge from v to w.
    

whose length is

      distTo[v] + e.weight()    // where e is the edge from v to w
    
 void relax(DirectedEdge e)
 {
   int v = e.from();
   int w = e.to();

   if (distTo[w] > distTo[v] + e.weight()) {
      distTo[w] = distTo[v] + e.weight();
      edgeTo[w] = v;
   }
 }
    

Indexed minPriorityQueue[6] [top]

Shortest Path from a single source vertex in a weighted digraph with no negative weights

For the graph algorithm to solve this problem, we needed to pick a vertex of minimum distance to the source from the vertices that are connected by an edge to "known" vertices.

The distTo[v] array will keep track of the best distance so far from the source to vertex v.

But this distance might decrease by using a path through a vertex chosen later!

What data structure? We want to know what vertex to add next to the ones with known shortest distance.

A minPriorityQueue seems a possibly good choice with (vertex, distance) pairs, where the distance is the priority.

But there is a problem. How do we update the distance for some vertex that is already in the priority queue.

Example in class

Index minPriorityQueue Methods[7] [top]

IndexMinPQ<Key>
(private members)
insert(int v, Key k): void
delMin(): int
change(int v, Key k): void
contains(int v): boolean
...

DijkstraSP[8] [top]

Shortest directed paths from a source vertex s.

public DijkstraSP(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.POSITIVE_INFINITY;
    }
    distTo[s] = 0.0;                             
                                                 
    // relax vertices in order of distance from s
    pq = new IndexMinPQ<Double>(G.V());    
    pq.insert(s, distTo[s]);                     
    while (!pq.isEmpty()) {                      
       int v = pq.delMin();                      
       for (DirectedEdge e : G.adj(v))           
          relax(e);                              
       }
    }
}
private void relax(DirectedEdge e) {
  int v = e.from(), w = e.to();
  if (distTo[w] > distTo[v] + e.weight()) {
    distTo[w] = distTo[v] + e.weight();
    edgeTo[w] = e;
    if (pq.contains(w)) {
      pq.change(w, distTo[w]);
    } else {
      pq.insert(w, distTo[w]);
    }
  }
}

AcyclicSP[9] [top]

Find the shortest path in an edge weighted DAG (no cycles), but allow negative weights.

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.POSITIVE_INFINITY;
  distTo[s] = 0.0;

  // visit vertices in toplogical order
  Topological topological = new Topological(G);
  for (int v : topological.order()) {
    for (DirectedEdge e : G.adj(v))
      relax(e);
  }
}

Longest Paths[10] [top]

How do you find longest paths from a source vertex in an edge weighted graph?

DijkstraSP doesn't help.

AcyclicSP does with a simple observation.

Switch to a copy of the graph, but with all the edge weights negated.

Find the shortest path in the copy.

The same sequence of vertices will be a longest path in the original graph!

AcyclicSP - finds shortest paths

AcyclicLP - finds longest paths

Critical Path Method[11] [top]


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++) {
  double duration = StdIn.readDouble();
  G.addEdge(new DirectedEdge(source, i, 0.0));
  G.addEdge(new DirectedEdge(i+N, sink, 0.0));
  G.addEdge(new DirectedEdge(i, i+N,    duration));

  // precedence constraints
  int M = StdIn.readInt();
  for (int j = 0; j < M; j++) {
    int precedent = StdIn.readInt();
    G.addEdge(new DirectedEdge(N+i, precedent, 0.0));
  }
}

// compute longest path
AcyclicLP lp = new AcyclicLP(G, source);

// print results
System.out.println(" job   start  finish");
System.out.println("--------------------");
for (int i = 0; i < N; i++) {
  System.out.printf("%4d %7.1f %7.1f\n", i, lp.distTo(i), lp.distTo(i+N));
}