Upload
hilary-kristin-boyd
View
233
Download
2
Embed Size (px)
Citation preview
Graphs - according to the mathematicians
An undirected graph is 2-tuple: G=(V,E) • a set of vertices • a set of edges
Vertices = {A, B, C, D, E}Edges = { {A,B}, {A,C}, {A,D}, {B,D} }
Vertices =Edges =
Can a graph ...contain an edge from A to A?
...contain two edge from A to B?
Graphs - more definitionsAn edge is a pair (v,w), where v, w V
Path: is a walk in which all vertices are unique
A walk is an alternating sequence of vertices and edges (starting and endingwith vertices) in which each edge is incident to the vertices that precede and follow it in the sequence.
e1
e2
e3
e4
Graphs - still more definitions
e1
e2
e3
e4
Directed Graph (digraphs)
Undirected Graph
An undirected graph is connected if there is a path from every vertex to every other vertex
Designing GraphsAn undirected graph is 2-tuple: • a set of vertices • a set of edges
Graph<VertexKey>
constructor» + Graph()
«query» + boolean containsVertex( VertexKey v ) + boolean containsEdge(VertexKey v1, VertexKey v2 ) «update» + void insertVertex( VertexKey v ) + void insertEdge( VertexKey v1, VertexKey v2 ) + void removeVertex( VertexKey v ) + void removeEdge( VertexKey v1, VertexKey v2 )
Graph<VertexKey>
constructor» + Graph()
«query» + boolean containsVertex( VertexKey v ) + boolean containsEdge(VertexKey v1, VertexKey v2 ) «update» + void insertVertex( VertexKey v ) + void insertEdge( VertexKey v1, VertexKey v2 ) + void removeVertex( VertexKey v ) + void removeEdge( VertexKey v1, VertexKey v2 )
Graph ADTGraph<VertexKey> ADT Specifications
Domain A Graph consists of two parts
• VERTICES -- a set of VertexKey
• EDGES -- a set of <VertexKey, VertexKey>
Invariant (ForAll <v1, v2> EDGES : v1VERTICES and v2VERTICES and v1 ≠ v2 ) and (ForAll <v1,v2> EDGES and <v3,v4> EDGES and <v1,v2> ≠ <v3,v4> :
(v1 = v4) (v2 ≠ v3)
no loops
no reversed edges
Graph ADT Methods
Graph<VertexKey> ADT Specifications(continued)
Constructor Methods public Graph() post: VERTICES == {} and EDGES == {} Query Methods public boolean containsVertex(VertexKey v) post: result == (v VERTICES )
public boolean containsEdge(VertexKey v1, VertexKey v2) post: result == (ThereIs ed EDGES : ed == <v1,v2> or ed == <v2,v1>)
Graph ADT Methods
Graph<VertexKey> ADT Specifications(continued)
Update Methods public void insertVertex(VertexKey v) post: VERTICES == VERTICES@pre {v }
public void insertEdge(VertexKey v1, VertexKey v2) pre: v1 VERTICES and v2 VERTICES and not containsEdge(v1,v2) post: EDGES = EDGES@pre { <v1,v2> }
public void removeVertex(VertexKey v) post: VERTICES == VERTICES@pre {v }
and EDGES = EDGES@pre - { e | e EDGES@pre and ( e = <v, vs> or e = < vs,v > for some vertex vs
)
public void removeEdge(VertexKey v1, VertexKey v2) post: EDGES == EDGES@pre - { <v1,v2>, <v2,v1> }
What is different about a digraph ADT?
Digraph ADTDigraph<VertexKey> ADT Specifications
Domain A Digraph consists of two parts
• VERTICES -- a set of VertexKey
• ARCS -- a set of <VertexKey, VertexKey>
Invariant ( ForAll <fromV, toV> ARCS : fromV VERTICES and toV VERTICES )
Digraph ADT Methods
Digraph<VertexKey> ADT Specifications(continued)
Constructor Methods public Digraph() post: VERTICES == {} and ARCS == {} Query Methods public boolean containsVertex(VertexKey v) post: result == (v VERTICES )
public boolean containsArc(VertexKey fromV, VertexKey toV) post: result == (ThereIs arc ARCS : arc == <fromV,toV>)
Digraph ADT Methods
Digraph<VertexKey> ADT Specifications(continued)
Update Methods public void insertVertex(VertexKey v) post: VERTICES == VERTICES@pre {v }
public void insertArc(VertexKey fromV, VertexKey toV) pre: v1 VERTICES and v2 VERTICES post: ARCS = ARCS@pre { <fromV,toV> }
public void removeVertex(VertexKey v) pre: ForAll a == <fromV,toV> ARCS : (fromV v and toV v ) post: VERTICES == VERTICES@pre {v } public void removeArc(VertexKey fromV, VertexKey toV) post: ARCS == ARCS@pre - { <fromV,toV> }
Digraph ImplementationsDigraph<VertexKey> ADT Specifications
Domain A Digraph consists of two parts
• VERTICES -- a set of VertexKey
• ARCS -- a set of <VertexKey, VertexKey>Invariant ( ForAll <fromV, toV> ARCS : fromV VERTICES and toV VERTICES )
Implementation?
Using Integers as “Keys”Digraph<VertexKey>
constructor» + Digraph()
«query» + boolean containsVertex( VertexKey v ) + boolean containsArc(VertexKey fromV, VertexKey toV) «update» + void insertVertex( VertexKey v ) + void insertArc( VertexKey fromV, VertexKey toV ) + void removeVertex( VertexKey v ) + void removeArc( VertexKey fromV, VertexKey toV )
Digraph<VertexKey>
constructor» + Digraph()
«query» + boolean containsVertex( VertexKey v ) + boolean containsArc(VertexKey fromV, VertexKey toV) «update» + void insertVertex( VertexKey v ) + void insertArc( VertexKey fromV, VertexKey toV ) + void removeVertex( VertexKey v ) + void removeArc( VertexKey fromV, VertexKey toV )
Digraph
constructor» + Digraph()
«query» + boolean containsVertex( int v ) + boolean containsArc( int fromV, int toV ) «update» + void insertVertex( int v ) + void insertArc( int fromV, VertexKey toV ) + void removeVertex( int v ) + void removeArc( int fromV, int toV )
Digraph
constructor» + Digraph()
«query» + boolean containsVertex( int v ) + boolean containsArc( int fromV, int toV ) «update» + void insertVertex( int v ) + void insertArc( int fromV, VertexKey toV ) + void removeVertex( int v ) + void removeArc( int fromV, int toV )
Using Integers as “Keys”
Question: How would you implement such numbering?
Answer:
Why does this eliminate theneed to store vertices?
Graph • Breadth-first search
• Depth-first search
• Topological ordering: an ordering of vertices in a directed acyclic graph
A
DEB
C
Adjacency ListsConsider storing outgoing arcs “in” their vertices.
Performance?
[0]
[1]
[2]
[3]
[4]
[5]
[6]
...insertArc
...containsArc
...removeVertex
Path Finder MethodsDigraph
constructor» + Digraph()
«query» + boolean containsVertex( int v ) + boolean containsArc( int fromV, int toV ) + boolean pathExists( int fromV, int toV ) + int distance( int fromV, int toV ) «update» + void insertVertex( int v ) + void insertArc( int fromV, VertexKey toV ) + void removeVertex( int v ) + void removeArc( int fromV, int toV )
Digraph
constructor» + Digraph()
«query» + boolean containsVertex( int v ) + boolean containsArc( int fromV, int toV ) + boolean pathExists( int fromV, int toV ) + int distance( int fromV, int toV ) «update» + void insertVertex( int v ) + void insertArc( int fromV, VertexKey toV ) + void removeVertex( int v ) + void removeArc( int fromV, int toV )
pathExistspublic boolean pathExists(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return true; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for (int v=0; v<=vertexCount; v++) if ( containsArc(reachedVertex, v) ) if (v == toV) return true; else reachedQ.addLast( v ); } } } return false;}
public boolean pathExists(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return true; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for (int v=0; v<=vertexCount; v++) if ( containsArc(reachedVertex, v) ) if (v == toV) return true; else reachedQ.addLast( v ); } } } return false;}
How could performancebe improved for an adjacencylist representation?
This is an example of a Depth-first algorithm
pathExists (for adjacency lists)public boolean pathExists(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return true; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) if (v == toV) return true; else reachedQ.addLast( v ); } } return false;}
public boolean pathExists(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return true; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) if (v == toV) return true; else reachedQ.addLast( v ); } } return false;}
distance
public int distance(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return 0; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) if (v == toV) return step; else reachedQ.addLast( v ); } } } return -1;}
public int distance(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ;
if (fromV == toV) // path of length zero return 0; else { reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV );
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) if (v == toV) return step; else reachedQ.addLast( v ); } } } return -1;}
How does the method change for distance( int fromV, int toV )
distance - for a weighted digraphA common variant of distance is called shortest path.
This algorithm begins with a labeled digraph in which arcs arelabeled with numeric weights.
Our first algorithm, known as Dijkstra’s Algorithm, assumes that all arc weights are positive.
Modifications to prior algorithm:
1) must check all possible paths.
2) must compare each total path weight to shortest thus far.
3) must store total path weight along with each queued vertex.
Shortest Pathpublic double shortestWeightedPath(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ; int shortestPathSoFar = maxPossiblePath+1;
if (fromV == toV) // path of length zero shortestPathSoFar = getArcWeight(fromV, toV); reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV ); reachedQ.addLast(getArcWeight(fromV, toV)); // if there is no Arc, weight: 0
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); int pathLen = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) { lastQ.addLast( v ); lastQ.addLast( pathLen + getArcWeight(reachedVertex,v) ); if ( v == toV &&
&& pathLen+getArcWeight(reachedVertex,v) < shortestPathSoFar ) shortestPathSoFar = pathLen+getArcWeight(reachedVertex,v); } } } return shortestPathSoFar;}
public double shortestWeightedPath(int fromV, int toV) { java.util.LinkedList<Integer> reachedQ, lastQ; int shortestPathSoFar = maxPossiblePath+1;
if (fromV == toV) // path of length zero shortestPathSoFar = getArcWeight(fromV, toV); reachedQ = new java.util.LinkedList<Integer>(); reachedQ.addLast( fromV ); reachedQ.addLast(getArcWeight(fromV, toV)); // if there is no Arc, weight: 0
for (int step=1; step<=vertexCount-1; step++) { lastQ = reachedQ; reachedQ = new java.util.LinkedList<Integer>(); while (lastQ.size() != 0) { int reachedVertex = lastQ.removeFirst(); int pathLen = lastQ.removeFirst(); for each (vertex, v, in the adjacency list of reachedVertex) { lastQ.addLast( v ); lastQ.addLast( pathLen + getArcWeight(reachedVertex,v) ); if ( v == toV &&
&& pathLen+getArcWeight(reachedVertex,v) < shortestPathSoFar ) shortestPathSoFar = pathLen+getArcWeight(reachedVertex,v); } } } return shortestPathSoFar;}
...with Negative Weights
Question: What must change to allow for negative weights?
Answer: Dijkstra’s algorithm does not work
A B
C
2
3 -2
MultilistA multilist implementation:
(1) stores vertices in a list.
Example
(2) stores arcs in adjacency lists, but using pointers back to from vertices.
Adjacency MatricesYet another representation - one bit per potential arc.
Performance?
boolean[][] digraph = boolean[maxV][maxV];
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[0] [1] [2] [3] [4] [5] [6]
Trees & Forests
How would you define a tree (from an undirected graph)?
A forest is an undirected graph consisting of zero or moreunconnected components such that each component is a tree.
Spanning Tree
A spanning tree for a particular graph is a tree that
(1)includes all of the graph’s vertices and(2) includes a subset of the graph’s edges.
Suggest example spanning trees.
Minimum Weight Spanning Tree
A minimum weight spanning tree for a particular weighted graph is a spanning tree with total of all edge weights less than or equal to that of all other spanning trees for the graph.
Applications?
Kruskal’s Algorithm
Construct a sequence of forests (F0, F1, ... Fn) using only vertices and edges from an original digraph D, such that(a) F0 is the empty forest.(b) Fj+1 is formed by adding an edge and incident vertices to Fj. This edge must have minimum weight among D’s edges that are not in Fj.
Prim’s AlgorithmConstruct a sequence of trees (T1, T2, ... Tn) using
only vertices and edges from an original digraph D, such that(a) T1 consists of any single vertex of D.(b) Tj+1 is formed by adding an edge and vertex to Tj.
This edge must be have minimum weight among D ’s edges that are not in Tj and are incident to one
of Tj’s vertices.