External memory graph traversal

Last updated

External memory graph traversal is a type of graph traversal optimized for accessing externally stored memory.

Contents

Background

Graph traversal is a subroutine in most graph algorithms. The goal of a graph traversal algorithm is to visit (and / or process) every node of a graph. Graph traversal algorithms, like breadth-first search and depth-first search, are analyzed using the von Neumann model, which assumes uniform memory access cost. This view neglects the fact, that for huge instances part of the graph resides on disk rather than internal memory. Since accessing the disk is magnitudes slower than accessing internal memory, the need for efficient traversal of external memory exists.

External memory model

For external memory algorithms the external memory model by Aggarwal and Vitter [1] is used for analysis. A machine is specified by three parameters: M, B and D. M is the size of the internal memory, B is the block size of a disk and D is the number of parallel disks. The measure of performance for an external memory algorithm is the number of I/Os it performs.

The breadth-first search algorithm starts at a root node and traverses every node with depth one. If there are no more unvisited nodes at the current depth, nodes at a higher depth are traversed. Eventually, every node of the graph has been visited.

Munagala and Ranade

Visualization for the computation of L(t) in the Munagala-Ranade-breadth-first search algorithm. Mr alg.gif
Visualization for the computation of L(t) in the Munagala-Ranade-breadth-first search algorithm.

For an undirected graph , Munagala and Ranade [2] proposed the following external memory algorithm:

Let denote the nodes in breadth-first search level t and let be the multi-set of neighbors of level t-1. For every t, can be constructed from by transforming it into a set and excluding previously visited nodes from it.

  1. Create by accessing the adjacency list of every vertex in . This step requires I/Os.
  2. Next is created from by removing duplicates. This can be achieved via sorting of , followed by a scan and compaction phase needing I/Os.
  3. is calculated by a parallel scan over and and requires I/Os.

The overall number of I/Os of this algorithm follows with consideration that and and is .

A visualization of the three described steps necessary to compute L(t) is depicted in the figure on the right.

Mehlhorn and Meyer

Mehlhorn and Meyer [3] proposed an algorithm that is based on the algorithm of Munagala and Ranade (MR) and improves their result.

It consists of two phases. In the first phase the graph is preprocessed, the second phase performs a breadth-first search using the information gathered in phase one.

During the preprocessing phase the graph is partitioned into disjointed subgraphs with small diameter. It further partitions the adjacency lists accordingly, by constructing an external file , where contains the adjacency list for all nodes in .

The breadth-first search phase is similar to the MR algorithm. In addition the algorithm maintains a sorted external file H. This file is initialized with . Further, the nodes of any created breadth-first search level carry identifiers for the files of their respective subgraphs . Instead of using random accesses to construct the file H is used.

  1. Perform a parallel scan of sorted list and H. Extract the adjacency lists for nodes , that can be found in H.
  2. The adjacency lists for the remaining nodes that could not be found in H need to be fetched. A scan over yields the partition identifiers. After sorting and deletion of duplicates, the respective files can be concatenated into a temporary file F'.
  3. The missing adjacency lists can be extracted from F' with a scan. Next, the remaining adjacency lists are merged into H with a single pass.
  4. is created by a simple scan. The partition information is attached to each node in .
  5. The algorithm proceeds like the MR algorithm.

Edges might be scanned more often in H, but unstructured I/Os in order to fetch adjacency lists are reduced.

The overall number of I/Os for this algorithm is

The depth-first search algorithm explores a graph along each branch as deep as possible, before backtracing.

For directed graphs Buchsbaum, Goldwasser, Venkatasubramanian and Westbrook [4] proposed an algorithm with I/Os.

This algorithm is based on a data structure called buffered repository tree (BRT). It stores a multi-set of items from an ordered universe. Items are identified by key. A BTR offers two operations:

The algorithm simulates an internal depth-first search algorithm. A stack S of nodes is hold. During an iteration for the node v on top of S push an unvisited neighbor onto S and iterate. If there are no unvisited neighbors pop v.

The difficulty is to determine whether a node is unvisited without doing I/Os per edge. To do this for a node v incoming edges are put into a BRT D, when v is first discovered. Further, outgoing edges (v,x) are put into a priority queue P(v), keyed by the rank in the adjacency list.

For vertex u on top of S all edges (u,x) are extracted from D. Such edges only exist if x has been discovered since the last time u was on top of S (or since the start of the algorithm if u is the first time on top of S). For every edge (u,x) a delete(x) operation is performed on P(u). Finally a delete-min operation on yields the next unvisited node. If P(u) is empty, u is popped from S.

Pseudocode for this algorithm is given below.

1  procedure BGVW-depth-first-search(G, v): 2      letS be a stack, P[] a priority queue for each node and D a BRT 3      S.push(v) 4      whileSis not empty: 5          v := S.top() 6          ifvis not marked: 7              mark(v) 8          extract all edges (v, x) from D, x: P[v].delete(x) 9          if (u := P[v].delete-min()) is not null: 10             S.push(u) 11         else: 12             S.pop()  13  procedure mark(v) 14      put all edges (x, v) into D 15       (v, x): put x into P[v]

Related Research Articles

<span class="mw-page-title-main">Binary search tree</span> Rooted binary tree data structure

In computer science, a binary search tree (BST), also called an ordered or sorted binary tree, is a rooted binary tree data structure with the key of each internal node being greater than all the keys in the respective node's left subtree and less than the ones in its right subtree. The time complexity of operations on the binary search tree is linear with respect to the height of the tree.

<span class="mw-page-title-main">Dijkstra's algorithm</span> Graph search algorithm

Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in a weighted graph, which may represent, for example, road networks. It was conceived by computer scientist Edsger W. Dijkstra in 1956 and published three years later.

The Ford–Fulkerson method or Ford–Fulkerson algorithm (FFA) is a greedy algorithm that computes the maximum flow in a flow network. It is sometimes called a "method" instead of an "algorithm" as the approach to finding augmenting paths in a residual graph is not fully specified or it is specified in several implementations with different running times. It was published in 1956 by L. R. Ford Jr. and D. R. Fulkerson. The name "Ford–Fulkerson" is often also used for the Edmonds–Karp algorithm, which is a fully defined implementation of the Ford–Fulkerson method.

<span class="mw-page-title-main">Breadth-first search</span> Algorithm to search the nodes of a graph

Breadth-first search (BFS) is an algorithm for searching a tree data structure for a node that satisfies a given property. It starts at the tree root and explores all nodes at the present depth prior to moving on to the nodes at the next depth level. Extra memory, usually a queue, is needed to keep track of the child nodes that were encountered but not yet explored.

<span class="mw-page-title-main">Depth-first search</span> Search algorithm

Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. The algorithm starts at the root node and explores as far as possible along each branch before backtracking. Extra memory, usually a stack, is needed to keep track of the nodes discovered so far along a specified branch which helps in backtracking of the graph.

A* is a graph traversal and pathfinding algorithm, which is used in many fields of computer science due to its completeness, optimality, and optimal efficiency. Given a weighted graph, a source node and a goal node, the algorithm finds the shortest path from source to goal.

In computer science, the Edmonds–Karp algorithm is an implementation of the Ford–Fulkerson method for computing the maximum flow in a flow network in time. The algorithm was first published by Yefim Dinitz in 1970, and independently published by Jack Edmonds and Richard Karp in 1972. Dinitz's algorithm includes additional techniques that reduce the running time to .

In computer science, iterative deepening search or more specifically iterative deepening depth-first search is a state space/graph search strategy in which a depth-limited version of depth-first search is run repeatedly with increasing depth limits until the goal is found. IDDFS is optimal, meaning that it finds the shallowest goal. Since it visits all the nodes in the search tree down to depth before visiting any nodes at depth , the cumulative order in which nodes are first visited is effectively the same as in breadth-first search. However, IDDFS uses much less memory.

<span class="mw-page-title-main">Graph (abstract data type)</span> Abstract data type in computer science

In computer science, a graph is an abstract data type that is meant to implement the undirected graph and directed graph concepts from the field of graph theory within mathematics.

In computer science, a topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge (u,v) from vertex u to vertex v, u comes before v in the ordering. For instance, the vertices of the graph may represent tasks to be performed, and the edges may represent constraints that one task must be performed before another; in this application, a topological ordering is just a valid sequence for the tasks. Precisely, a topological sort is a graph traversal in which each node v is visited only after all its dependencies are visited. A topological ordering is possible if and only if the graph has no directed cycles, that is, if it is a directed acyclic graph (DAG). Any DAG has at least one topological ordering, and algorithms are known for constructing a topological ordering of any DAG in linear time. Topological sorting has many applications, especially in ranking problems such as feedback arc set. Topological sorting is possible even when the DAG has disconnected components.

In computer science, corecursion is a type of operation that is dual to recursion. Whereas recursion works analytically, starting on data further from a base case and breaking it down into smaller data and repeating until one reaches a base case, corecursion works synthetically, starting from a base case and building it up, iteratively producing data further removed from a base case. Put simply, corecursive algorithms use the data that they themselves produce, bit by bit, as they become available, and needed, to produce further bits of data. A similar but distinct concept is generative recursion which may lack a definite "direction" inherent in corecursion and recursion.

<span class="mw-page-title-main">Centrality</span> Degree of connectedness within a graph

In graph theory and network analysis, indicators of centrality assign numbers or rankings to nodes within a graph corresponding to their network position. Applications include identifying the most influential person(s) in a social network, key infrastructure nodes in the Internet or urban networks, super-spreaders of disease, and brain networks. Centrality concepts were first developed in social network analysis, and many of the terms used to measure centrality reflect their sociological origin.

In graph theory, reachability refers to the ability to get from one vertex to another within a graph. A vertex can reach a vertex if there exists a sequence of adjacent vertices which starts with and ends with .

In mathematical optimization, the push–relabel algorithm is an algorithm for computing maximum flows in a flow network. The name "push–relabel" comes from the two basic operations used in the algorithm. Throughout its execution, the algorithm maintains a "preflow" and gradually converts it into a maximum flow by moving flow locally between neighboring nodes using push operations under the guidance of an admissible network maintained by relabel operations. In comparison, the Ford–Fulkerson algorithm performs global augmentations that send flow following paths from the source all the way to the sink.

In computer science, Kosaraju-Sharir's algorithm is a linear time algorithm to find the strongly connected components of a directed graph. Aho, Hopcroft and Ullman credit it to S. Rao Kosaraju and Micha Sharir. Kosaraju suggested it in 1978 but did not publish it, while Sharir independently discovered it and published it in 1981. It makes use of the fact that the transpose graph has exactly the same strongly connected components as the original graph.

In computer science, graph traversal refers to the process of visiting each vertex in a graph. Such traversals are classified by the order in which the vertices are visited. Tree traversal is a special case of graph traversal.

<span class="mw-page-title-main">Euler tour technique</span>

The Euler tour technique (ETT), named after Leonhard Euler, is a method in graph theory for representing trees. The tree is viewed as a directed graph that contains two directed edges for each edge in the tree. The tree can then be represented as a Eulerian circuit of the directed graph, known as the Euler tour representation (ETR) of the tree. The ETT allows for efficient, parallel computation of solutions to common problems in algorithmic graph theory. It was introduced by Tarjan and Vishkin in 1984.

Skip graphs are a kind of distributed data structure based on skip lists. They were invented in 2003 by James Aspnes and Gauri Shah. A nearly identical data structure called SkipNet was independently invented by Nicholas Harvey, Michael Jones, Stefan Saroiu, Marvin Theimer and Alec Wolman, also in 2003.

In computer science, a fractal tree index is a tree data structure that keeps data sorted and allows searches and sequential access in the same time as a B-tree but with insertions and deletions that are asymptotically faster than a B-tree. Like a B-tree, a fractal tree index is a generalization of a binary search tree in that a node can have more than two children. Furthermore, unlike a B-tree, a fractal tree index has buffers at each node, which allow insertions, deletions and other changes to be stored in intermediate locations. The goal of the buffers is to schedule disk writes so that each write performs a large amount of useful work, thereby avoiding the worst-case performance of B-trees, in which each disk write may change a small amount of data on disk. Like a B-tree, fractal tree indexes are optimized for systems that read and write large blocks of data. The fractal tree index has been commercialized in databases by Tokutek. Originally, it was implemented as a cache-oblivious lookahead array, but the current implementation is an extension of the Bε tree. The Bε is related to the Buffered Repository Tree. The Buffered Repository Tree has degree 2, whereas the Bε tree has degree Bε. The fractal tree index has also been used in a prototype filesystem. An open source implementation of the fractal tree index is available, which demonstrates the implementation details outlined below.

A central problem in algorithmic graph theory is the shortest path problem. One of the generalizations of the shortest path problem is known as the single-source-shortest-paths (SSSP) problem, which consists of finding the shortest paths from a source vertex to all other vertices in the graph. There are classical sequential algorithms which solve this problem, such as Dijkstra's algorithm. In this article, however, we present two parallel algorithms solving this problem.

References

  1. Aggarwal, Alok; Vitter, Jeffrey (1988). "The input/output complexity of sorting and related problems". Communications of the ACM . 31 (9): 1116–1127. doi: 10.1145/48529.48535 .
  2. Munagala, Kameshwar; Ranade, Abhiram (1999). "I/O-complexity of Graph Algorithms". Proceedings of the Tenth Annual ACM-SIAM Symposium on Discrete Algorithms. SODA '99. Baltimore, Maryland, USA: Society for Industrial and Applied Mathematics. pp. 687–694.
  3. Mehlhorn, Kurt; Meyer, Ulrich (2002). "External-Memory Breadth-First Search with Sublinear I/O". Algorithms -- ESA 2002. ESA 2002. Rome, Italy: Springer Berlin Heidelberg. pp. 723–735.
  4. Buchsbaum, Adam L.; Goldwasser, Michael; Venkatasubramanian, Michael; Westbrook, Suresh (2000). "On External Memory Graph Traversal". Proceedings of the Eleventh Annual ACM-SIAM Symposium on Discrete Algorithms. SODA '00. San Francisco, California, USA: Society for Industrial and Applied Mathematics. pp. 859–860.