Added most of the Graph500 validation routine. It's very slow.

This commit is contained in:
Eric Holk 2012-05-15 15:21:35 -07:00
parent f5b9ebffa0
commit d485f23a1a

View file

@ -11,11 +11,12 @@ import std::map::hashmap;
import std::deque;
import std::deque::t;
import io::writer_util;
import vec::extensions;
import comm::*;
import int::abs;
type node_id = i64;
type graph = [map::set<node_id>];
type bfs_result = [node_id];
iface queue<T: send> {
fn add_back(T);
@ -118,7 +119,7 @@ fn make_graph(N: uint, edges: [(node_id, node_id)]) -> graph {
#[doc="Returns a vector of all the parents in the BFS tree rooted at key.
Nodes that are unreachable have a parent of -1."]
fn bfs(graph: graph, key: node_id) -> [node_id] {
fn bfs(graph: graph, key: node_id) -> bfs_result {
let marks : [mut node_id]
= vec::to_mut(vec::from_elem(vec::len(graph), -1));
@ -142,6 +143,101 @@ fn bfs(graph: graph, key: node_id) -> [node_id] {
vec::from_mut(marks)
}
#[doc="Performs at least some of the validation in the Graph500 spec."]
fn validate(edges: [(node_id, node_id)],
root: node_id, tree: bfs_result) -> bool {
// There are 5 things to test. Below is code for each of them.
// 1. The BFS tree is a tree and does not contain cycles.
//
// We do this by iterating over the tree, and tracing each of the
// parent chains back to the root. While we do this, we also
// compute the levels for each node.
log(info, "Verifying tree structure...");
let mut status = true;
let level = tree.map() {|parent|
let mut parent = parent;
let mut path = [];
if parent == -1 {
// This node was not in the tree.
-1
}
else {
while parent != root {
if vec::contains(path, parent) {
status = false;
}
path += [parent];
parent = tree[parent];
}
// The length of the path back to the root is the current
// level.
path.len() as int
}
};
if !status { ret status }
// 2. Each tree edge connects vertices whose BFS levels differ by
// exactly one.
log(info, "Verifying tree edges...");
let status = tree.alli() {|k, parent|
if parent != root && parent != -1 {
level[parent] == level[k] - 1
}
else {
true
}
};
if !status { ret status }
// 3. Every edge in the input list has vertices with levels that
// differ by at most one or that both are not in the BFS tree.
log(info, "Verifying graph edges...");
let status = edges.all() {|e|
let (u, v) = e;
abs(level[u] - level[v]) <= 1
};
if !status { ret status }
// 4. The BFS tree spans an entire connected component's vertices.
// This is harder. We'll skip it for now...
// 5. A node and its parent are joined by an edge of the original
// graph.
log(info, "Verifying tree and graph edges...");
let status = tree.alli() {|u, v|
if v == -1 || u as int == root {
true
}
else {
log(info, #fmt("Checking for %? or %?",
(u, v), (v, u)));
edges.contains((u as int, v)) || edges.contains((v, u as int))
}
};
if !status { ret status }
// If we get through here, all the tests passed!
true
}
fn main() {
let scale = 14u;
@ -162,11 +258,20 @@ fn main() {
io::stdout().write_line(#fmt("Generated graph with %? edges in %? seconds.",
total_edges / 2u,
stop - start));
let root = 0;
let start = time::precise_time_s();
let bfs_tree = bfs(graph, 0);
let bfs_tree = bfs(graph, root);
let stop = time::precise_time_s();
io::stdout().write_line(#fmt("BFS completed in %? seconds.",
stop - start));
}
let start = time::precise_time_s();
assert(validate(graph, edges, root, bfs_tree));
let stop = time::precise_time_s();
io::stdout().write_line(#fmt("Validation completed in %? seconds.",
stop - start));
}