Basic Graph Terminology A graph consists of a nonempty set of points or vertices, and a set of edges...

49

Transcript of Basic Graph Terminology A graph consists of a nonempty set of points or vertices, and a set of edges...

Basic Graph Terminology A graph consists of a nonempty set of points or vertices, and a

set of edges that link together the vertices.  A simple real world example of a graph would be your house and the corner store. Where the house and the store are the vertices and the road between them is the edge connecting the two vertices. A graph can take on many forms: directed or undirected. A directed graph is one in which the direction of any given edge is defined. Conversely, in an undirected graph you can move in both directions between vertices. The edges can also be weighted or unweighted. Using the previous example, weights can be thought of as the number of blocks between your house and the corner store.

Examples The type of graph largely depends upon the features of its components,

namely the attributes of the vertices and edges.  A vertex within a graph may or may not have a label assigned to it.  Similarly, an edge may have a label, weight, and/or direction associated with it.  As an example, a mixed graph is one that contains both directed and undirected edges, while a null graph is one that contains only isolated vertices (ie. no edges)

Graph cont. An edge in a graph that joins two vertices is said to be incident to both

vertices.  Furthermore, the degree of a vertex is determined by the number of distinct edges that are incident to it.  More specifically, the indegree and outdegree of a vertex represent the number of edges that terminate in and

originate from a vertex, respectively. Two edges in a graph are termed adjacent if they connect to the

same vertex.  Similarly, two vertices are termed adjacent if they are connected by the same edge.  A loop is an edge that links a vertex to itself.  A simple graph is one that contains no loops or parallel edges, where more than one edge connects two given vertices, whereas a multigraph is a graph that contains multiple edges.  Finally, a complete graph is a simple graph in which every pair of

vertices is adjacent

Path

A path through a graph is a traversal of consecutive vertices along a sequence of edges.  By this definition, the vertex at the end of one edge in the sequence must also be the vertex at the beginning of the next edge in the sequence.  The vertices that begin and end the path are termed the initial vertex and terminal vertex, respectively.  With the exception of these initial and terminal vertices, each vertex within the path has two neighbouring vertices that must also be adjacent to the vertex.  The length of the path is the number of edges that are traversed along the path.

Path cont

To make this definition more understandable, consider a road map between Saskatoon and Calgary. All of the towns and cities would be the vertices of a graph, including the starting city of Saskatoon (initial vertex) and the destination city  (terminal vertex), Calgary. The highway route used to drive from Saskatoon to Calgary would be the path. The

length of the path in this example is 5.

Path cont.

Repeated edges or vertices within the path are permissible. When there are no repeated edges in the path of a directed graph, then the path is called a simple path.  On the other hand, an elementary path in a directed graph is one in which there are no repeated vertices within the path.  The path in our road map example is considered a simple path and also an elementary path

A cycle is a path in which the initial vertex of the path is also the terminal vertex of the path.  So by removing all the cycles, the path can be considered an elementary path since there will no longer be any repeated vertices.  This means that if a path exists between any two vertices, an elementary path must also exist between these two vertices. When a simple directed graph does not contain any cycles is

termed acyclic.

Examlpe

Directed Graph

Example An edge in an undirected graph is

formed by connecting a pair of vertices but no direction is stipulated for the edge. Therefore, for a path in an undirected graph, either vertex may be considered as the initial or terminal vertex of the path and the traversal of the vertices along the path can occur in either direction.  However, a cycle in a simple undirected graph is slightly different from the definition of a cycle for a directed graph due to the lack of direction on the edges.  For undirected graphs, the traversal of a set of vertices forward and then backward can not be considered a cycle.  Rather, a simple cycle for an undirected graph must contain at least three different edges and no repeated vertices, with the exception of the initial and terminal vertex.

Example An edge in an undirected graph is

formed by connecting a pair of vertices but no direction is stipulated for the edge. Therefore, for a path in an undirected graph, either vertex may be considered as the initial or terminal vertex of the path and the traversal of the vertices along the path can occur in either direction.  However, a cycle in a simple undirected graph is slightly different from the definition of a cycle for a directed graph due to the lack of direction on the edges.  For undirected graphs, the traversal of a set of vertices forward and then backward can not be considered a cycle.  Rather, a simple cycle for an undirected graph must contain at least three different edges and no repeated vertices, with the exception of the initial and terminal vertex.

Reachability     If a vertex is reachable from

another vertex then a path exists from the one vertex to the other vertex.  It is assumed that every vertex is reachable from itself.  Also, if vertex b is reachable from vertex a and vertex c is reachable from vertex b, then it follows that vertex c is reachable from vertex a.  The definition of reachability holds true for both directed and undirected graphs.  In the road map example, a driver can reach Kindersley from Saskatoon, and the same driver can reach Calgary from Kindersley.  Therefore, Calgary is considered by the driver to be reachable from Saskatoon.

Connectedness An undirected graph is considered to be connected if a path exists between all

pairs of vertices thus making each of the vertices in a pair reachable from the other.  An unconnected graph may be subdivided into what are termed connected subgraphs or connected components of the graph.

    The connectedness of a simple directed graph becomes more complex because direction must be considered.  For instance, if vertex a is reachable from vertex b, vertex a may not be reachable from vertex b.  For the road map example when the map is considered to be a directed graph, it can not be considered a connected graph, because while Calgary is reachable from Saskatoon, Saskatoon is not reachable from Calgary.

   Because of the added complexity, there are three distinct forms of connectedness in simple directed graphs: weakly connected, unilaterally connected and strongly connected.  A weakly connected graph is where the direction of the graph is ignored and the connectedness is defined as if the graph was undirected.  A unilaterally connected graph is defined as a graph for which at least one vertex of any pair of vertices is reachable from the other. A strongly connected graph is one in which for all pairs of vertices, both vertices are reachable from the other.

Examples

The three kinds

Adjacency Matrices

There are several different ways to represent a graph in a computer.  Although graphs are usually shown diagrammatically, this is only possible when the number of vertices and edges is reasonably small.

    Graphs can also be represented in the form of matrices.  The major advantage of matrix representation is that the calculation of paths and cycles can easily be performed using well known operations of matrices. However, the disadvantage is that this form of representation takes away from the visual aspect of graphs.  It would be difficult to illustrate in a matrix, properties that are easily illustrated graphically

Matrix representation of a graph

Consider the following directed graph G (in which the vertices are ordered as v1, v2, v3, v4, and v5), and its equivalent adjacency matrix representation on the right:

v1 v2 v3 v4 v5 v1 0 1 0 1 1 v2 0 0 0 1 0 v3 0 0 0 0 1 v4 0 0 0 0 0 v5 0 1 0 0 0

Matrix representation of a graph

As you can see from the above graph, if a path of length 1 exists from one vertex to another (ie. the two vertices are adjacent), there must be an entry of 1 in the corresponding position in the matrix.  For example, from the vertex v1, we can reach vertices v2, v4, and v5. Therefore, we have a corresponding entry of 1 in the matrix in the first row and the second, fourth and fifth columns.

    In general, the number of 1's in the ith row, corresponds to the number of edges leaving the vertex vi, and the number of 1's in the jth column, corresponds to the number of edges entering the vertex vj.

Definition of an Adjacency Matrix

An adjacency matrix is defined as follows:  Let G be a graph with "n" vertices that are assumed to be ordered from v1 to vn. The n x n matrix A, in which

aij= 1        if there exists a path from vi to vj             aij = 0        otherwise

is called an adjacency matrix.

Calculating A Path Between Vertices

As shown in the previous example, the existence of an edge between two vertices vi and vj is shown by an entry of 1 in the ith row and jth column of the adjacency matrix.  This entry represents a path of length 1 from vi to vj.

    To compute a path of length 2, the matrix of length 1 must be multiplied by itself, and the product matrix is the matrix representation of path of length 2.

Example:  Computing A Matrix Representation of

Path of Length 2 Using the matrix from the

previous example and multiplying it by itself, we obtain the following new matrix:

Matrix representation of path of length 2

v1 v2 v3 v4 v5

v1 0 1 0 1 0

v2 0 0 0 0 0

v3 0 1 0 0 0

v4 0 0 0 0 0

v5 0 0 0 1 0

Dijkstra's Algorithm

There are many different operations that can be done on graphs. Methods such as Kruskal's algorithm and Prim's algorithm find the most efficient way to traverse an entire graph. However, if the distance (cost) between two given vertices needed to be calculated, an alternate method would be required. Dijkstra's algorithm determines the distances (costs) between a given vertex and all other vertices in a graph. This may be useful to determine alternatives in decision making. For example, a telephone company may forgo the decision to install a new telephone cable in a rural area when presented with the option of installing the same cable in a city, reaching twice the people at half the cost.

Dijkstra's Algorithm Cont’s

 Dijkstra's algorithm is almost identical to that of Prim's. The algorithm begins at a specific vertex and extends outward within the graph, until all vertices have been reached. The only distinction is that Prim's algorithm stores a minimum cost edge whereas Dijkstra's algorithm stores the total cost from a source vertex to the current vertex. More simply, Dijkstra's algorithm stores a summation of minimum cost edges whereas Prim's algorithm stores at most one minimum cost edge.

Dijkstra's Algorithm Cont’s Dijkstra's algorithm creates labels associated with vertices.  These

labels represent the distance (cost) from the source vertex to that particular vertex. Within the graph, there exists two kinds of labels: temporary and permanent. The temporary labels are given to vertices that have not been reached. The value given to these temporary labels can vary. Permanent labels are given to vertices that have been reached and their distance (cost) to the source vertex is known. The value given to these labels is the distance (cost) of that vertex to the source vertex. For any given vertex, there must be a permanent label or a temporary label, but not both.   

                                                                               Vertex A has a

temporary label with a distance of 0       Vertex B has a permanent label with a distance of 5

Dijkstra's Algorithm Cont’s   The algorithm begins by initializing any vertex in the graph (vertex

A, for example) a permanent label with the value of 0, and all other vertices a temporary label with the value of 0.

Dijkstra's Algorithm Cont’s  The algorithm then proceeds to select the least cost edge connecting a

vertex with a permanent label (currently vertex A) to a vertex with a temporary label (vertex B, for example).   Vertex B's label is then updated from a temporary to a permanent label. Vertex B's value is then determined by the addition of the cost of the edge with vertex A's value.

Dijkstra's Algorithm Cont’s

The next step is to find the next least cost edge extending to a vertex with a temporary label from either vertex A or vertex B (vertex C, for example), change vertex C's label to permanent, and determine its distance to vertex A.

Dijkstra's Algorithm Cont’s

This process is repeated until the labels of all vertices in the graph are permanent.

A formal definition of Dijkstra's Algorithm

Dijkstra's algorithm can be expressed formally as follows:

G    - arbitrary connected graph v0   - is the initial beginning vertex V    - is the set of all vertices in the graph G S    - set of all vertices with permanent labels n     - number of vertices in G D    - set of distances to v0 C    - set of edges in G

Dijkstra Algorithm (graph G, vertex v0) {    S={v0}    For i = 1 to n         D[i] = C[v0,i]

   For i = 1 to n-1         Choose a vertex w in V-S such that D[w] is minimum

        Add w to S         For each vertex v in V-S                 D[v] = min(D[v], D[w] + C[w,v]) }

Test questions Two edges in a graph that connect to the same

vertex are said to be ___________. A. adjacent B. incident C. weighted

A graph that consists of isolated nodes and no edges is termed a ____________.

A. multigraph B. null graph C. mixed graph

A cycle is: A. a traversal of consecutive vertices along a

sequence of distinct edges. B. a path which begins and terminates in the same

vertex. C. a path through a graph in which there are no

repeated vertices.

In a graph, a path that contains no repeated vertices is termed a/an _______________ path.

A. simple B. complex C. elementary

A simple graph may contain loops but not parallel edges. A. true B. false

Which one of the following statements is true about a directed graph?

A. If vertex a is reachable from vertex b, then it follows that vertex b is reachable from vertex a.

B. If vertex a is reachable from both vertices b and c, then it follows that vertex b is reachable from vertex c.

C. If vertex a is reachable from vertex b, and vertex b is reachable from vertex c, then it follows that vertex a is reachable from vertex c.

A graph in which at least one vertex of any pair of vertices is reachable from the other is termed

A. weakly-connected B. unilaterally-connected C. strongly-connected

The number of edges that are traversed along a given path is termed the ___________ of the path.

A. degree B. length C. connectedness

1) Consider the graph represented by this adjacency matrix, where the numbers in a given position indicate edge weights.

0 1 2 3 0 [0 1 0 3] 1 [2 0 4 0] 2 [0 1 0 1] 3 [2 0 0 0]

a) Is this a directed or undirected graph?

ans: directed

b) Give two pieces of specific evidence to support your answer. [Note that the same condition affecting more than one pair of nodes does not count as more than one piece of evidence.]

ans: (i) There is a differently-weighted edge in each direction between some nodes (i.e. 1 and 2).

(ii) There is only an edge in one direction between nodes 3 and 2.

Test questions cont.

Test questions cont. c) Explain, in general, how we can tell by

inspection whether or not a graph is directed by looking solely at its

adjacency matrix.

ans: This adjacency matrix is not symmetric along its diagonal. An undirected graph has an adjacency matrix that is symmetric.

d) Supposing we encounter an algorithm that works on weighted graphs, but we want to run it on an unweighted graph. How do we do this?

ans: Set the weight of every unweighted edge to the same value.

e) Supposing we encounter an algorithm that works on directed graphs, but we want to run it on an undirected graph. How do we do this?

ans: Change each undirected node into two directed nodes, pointing in opposite directions.

2) Can an adjacency matrix for a directed graph ever not be square in shape? Why or why not?

ans: No. since we want to describe the relationship between each node and each other node, we need precisely n^2 matrix entries.

Test questions

Find the shortest part a to f on the graph below.

Test questions

Consider the following graph:

Test questions

(a) List the nodes in the order they would be discovered by depth .rst search, starting at node a (order neighbors alphabetically when necessary to break ties).

Ans: a b d e c f. (b) (5 points) List the nodes in the order they would be discovered by

breadth .rst search, again starting at a and ordering neighbors alphabetically.

Ans: a b c f d e. (c) (Extra credit, up to 6 points) Give two di.erent topological

sorts of this graph. Ans: There are eight possibilities: a b c e f d a c b e f d a f b c e d a b c f e d a c b f e d a f c b e d a b f c e d a c f b e d

Test question

Find the shortest path between the nodes s and t in the graph below:

Graph path code import java.io.FileReader; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; import java.util.StringTokenizer;

import java.util.Collection; import java.util.List; import java.util.Map; import java.util.LinkedList; import java.util.HashMap; import java.util.Iterator; import java.util.NoSuchElementException;

import weiss.nonstandard.PriorityQueue; import weiss.nonstandard.PairingHeap; import weiss.nonstandard.BinaryHeap;

Graph path code cont. // Used to signal violations of preconditions for // various shortest path algorithms. class GraphException extends RuntimeException { public GraphException( String name ) { super( name ); } }

// Represents an edge in the graph. class Edge { public Vertex dest; // Second vertex in Edge public double cost; // Edge cost public Edge( Vertex d, double c )

Graph path code cont. { dest = d; cost = c; } }

// Represents an entry in the priority queue for Dijkstra's algorithm. class Path implements Comparable { public Vertex dest; // w public double cost; // d(w) public Path( Vertex d, double c ) { dest = d; cost = c; } public int compareTo( Object rhs ) {

Graph path code cont. double otherCost = ((Path)rhs).cost; return cost < otherCost ? -1 : cost > otherCost ? 1 : 0; } }

// Represents a vertex in the graph. class Vertex { public String name; // Vertex name public List adj; // Adjacent vertices public double dist; // Cost public Vertex prev; // Previous vertex on shortest path public int scratch;// Extra variable used in algorithm

public Vertex( String nm ) { name = nm; adj = new LinkedList( ); reset( ); }

public void reset( ) { dist = Graph.INFINITY; prev = null; pos = null; scratch = 0; }

Graph path code cont. public PriorityQueue.Position pos; // Used for dijkstra2 (Chapter 23) }

// Graph class: evaluate shortest paths. // // CONSTRUCTION: with no parameters. // // ******************PUBLIC OPERATIONS********************** // void addEdge( String v, String w, double cvw ) // --> Add additional edge // void printPath( String w ) --> Print path after alg is run // void unweighted( String s ) --> Single-source unweighted // void dijkstra( String s ) --> Single-source weighted // void negative( String s ) --> Single-source negative weighted // void acyclic( String s ) --> Single-source acyclic // ******************ERRORS********************************* // Some error checking is performed to make sure graph is ok, // and to make sure graph satisfies properties needed by each // algorithm. Exceptions are thrown if errors are detected.

Graph path code cont. public class Graph { public static final double INFINITY = Double.MAX_VALUE; private Map vertexMap = new HashMap( ); // Maps String to Vertex

/** * Add a new edge to the graph. */ public void addEdge( String sourceName, String destName, double cost ) { Vertex v = getVertex( sourceName ); Vertex w = getVertex( destName ); v.adj.add( new Edge( w, cost ) ); }

/** * Driver routine to handle unreachables and print total cost. * It calls recursive routine to print shortest path to * destNode after a shortest path algorithm has run. */ public void printPath( String destName ) {

Graph path code cont Vertex w = (Vertex) vertexMap.get( destName ); if( w == null ) throw new NoSuchElementException( "Destination vertex not found" ); else if( w.dist == INFINITY ) System.out.println( destName + " is unreachable" ); else { System.out.print( "(Cost is: " + w.dist + ") " ); printPath( w ); System.out.println( ); } }

/** * If vertexName is not present, add it to vertexMap. * In either case, return the Vertex. */ private Vertex getVertex( String vertexName ) {

Graph path code cont Vertex v = (Vertex) vertexMap.get( vertexName ); if( v == null ) { v = new Vertex( vertexName ); vertexMap.put( vertexName, v ); } return v; }

/** * Recursive routine to print shortest path to dest * after running shortest path algorithm. The path * is known to exist. */ private void printPath( Vertex dest ) { if( dest.prev != null ) { printPath( dest.prev ); System.out.print( " to " ); } System.out.print( dest.name ); }

Graph path code cont /** * Initializes the vertex output info prior to running * any shortest path algorithm. */ private void clearAll( ) { for( Iterator itr = vertexMap.values( ).iterator( ); itr.hasNext( ); ) ( (Vertex)itr.next( ) ).reset( ); }

/** * Single-source weighted shortest-path algorithm. */ public void dijkstra( String startName ) { PriorityQueue pq = new BinaryHeap( );

Vertex start = (Vertex) vertexMap.get( startName ); if( start == null ) throw new NoSuchElementException( "Start vertex not found" );

clearAll( ); pq.insert( new Path( start, 0 ) ); start.dist = 0;

Graph path code cont int nodesSeen = 0; while( !pq.isEmpty( ) && nodesSeen < vertexMap.size( ) ) { Path vrec = (Path) pq.deleteMin( ); Vertex v = vrec.dest; if( v.scratch != 0 ) // already processed v continue; v.scratch = 1; nodesSeen++;

for( Iterator itr = v.adj.iterator( ); itr.hasNext( ); ) { Edge e = (Edge) itr.next( ); Vertex w = e.dest; double cvw = e.cost; if( cvw < 0 ) throw new GraphException( "Graph has negative edges" ); if( w.dist > v.dist + cvw ) {

Graph path code cont w.dist = v.dist +cvw; w.prev = v; pq.insert( new Path( w, w.dist ) ); } } } } /** * Process a request; return false if end of file. */ public static boolean processRequest( BufferedReader in, Graph g ) { String startName = null; String destName = null; String alg = null;

try { System.out.print( "Enter start node:" ); if( ( startName = in.readLine( ) ) == null ) return false; System.out.print( "Enter destination node:" ); if( ( destName = in.readLine( ) ) == null ) return false;

Graph path code cont System.out.print( " Enter algorithm d for dijkstra(d): " ); if( ( alg = in.readLine( ) ) == null ) return false; if( alg.equals( "d" ) ) { g.dijkstra( startName ); g.printPath( destName ); } } catch( IOException e ) { System.err.println( e ); } catch( NoSuchElementException e ) { System.err.println( e ); } catch( GraphException e ) { System.err.println( e ); } return true; }

Graph path code cont /** * A main routine that: * 1. Reads a file containing edges (supplied as a command-line parameter); * 2. Forms the graph; * 3. Repeatedly prompts for two vertices and * runs the shortest path algorithm. * The data file is a sequence of lines of the format * source destination. */ public static void main( String [ ] args ) { Graph g = new Graph( ); try { FileReader fin = new FileReader( args[0] ); BufferedReader graphFile = new BufferedReader( fin );

// Read the edges and insert String line; while( ( line = graphFile.readLine( ) ) != null ) { StringTokenizer st = new StringTokenizer( line );

try

Graph path code cont { if( st.countTokens( ) != 3 ) { System.err.println( "Skipping ill-formatted line " + line ); continue; } String source = st.nextToken( ); String dest = st.nextToken( ); int cost = Integer.parseInt( st.nextToken( ) ); g.addEdge( source, dest, cost ); } catch( NumberFormatException e ) { System.err.println( "Skipping ill-formatted line " + line ); } } } catch( IOException e ) { System.err.println( e ); }

System.out.println( g.vertexMap.size( ) + " vertices" );

BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) ); while( processRequest( in, g ) ) ; } }

Input

Boston -> NewYork :250 LA -> Baltimore :200 Boston -> Baltimore :300 LA -> Boston :100 Virginia -> Boston :450 Baltimore -> Virginia :50 NewYork -> LA :1000