@@ -11,11 +11,12 @@ import std::map::hashmap;
11
11
import std:: deque;
12
12
import std:: deque:: t;
13
13
import io:: writer_util;
14
- import vec:: extensions;
15
14
import comm:: * ;
15
+ import int:: abs;
16
16
17
17
type node_id = i64 ;
18
18
type graph = [ map:: set < node_id > ] ;
19
+ type bfs_result = [ node_id ] ;
19
20
20
21
iface queue<T : send> {
21
22
fn add_back ( T ) ;
@@ -118,7 +119,7 @@ fn make_graph(N: uint, edges: [(node_id, node_id)]) -> graph {
118
119
#[ doc="Returns a vector of all the parents in the BFS tree rooted at key.
119
120
120
121
Nodes that are unreachable have a parent of -1." ]
121
- fn bfs ( graph : graph , key : node_id ) -> [ node_id ] {
122
+ fn bfs ( graph : graph , key : node_id ) -> bfs_result {
122
123
let marks : [ mut node_id ]
123
124
= vec:: to_mut ( vec:: from_elem ( vec:: len ( graph) , -1 ) ) ;
124
125
@@ -142,6 +143,101 @@ fn bfs(graph: graph, key: node_id) -> [node_id] {
142
143
vec:: from_mut ( marks)
143
144
}
144
145
146
+ #[ doc="Performs at least some of the validation in the Graph500 spec." ]
147
+ fn validate ( edges : [ ( node_id , node_id ) ] ,
148
+ root : node_id , tree : bfs_result ) -> bool {
149
+ // There are 5 things to test. Below is code for each of them.
150
+
151
+ // 1. The BFS tree is a tree and does not contain cycles.
152
+ //
153
+ // We do this by iterating over the tree, and tracing each of the
154
+ // parent chains back to the root. While we do this, we also
155
+ // compute the levels for each node.
156
+
157
+ log ( info, "Verifying tree structure..." ) ;
158
+
159
+ let mut status = true ;
160
+ let level = tree. map ( ) { |parent|
161
+ let mut parent = parent;
162
+ let mut path = [ ] ;
163
+
164
+ if parent == -1 {
165
+ // This node was not in the tree.
166
+ -1
167
+ }
168
+ else {
169
+ while parent != root {
170
+ if vec:: contains ( path, parent) {
171
+ status = false ;
172
+ }
173
+
174
+ path += [ parent] ;
175
+ parent = tree[ parent] ;
176
+ }
177
+
178
+ // The length of the path back to the root is the current
179
+ // level.
180
+ path. len ( ) as int
181
+ }
182
+ } ;
183
+
184
+ if !status { ret status }
185
+
186
+ // 2. Each tree edge connects vertices whose BFS levels differ by
187
+ // exactly one.
188
+
189
+ log ( info, "Verifying tree edges..." ) ;
190
+
191
+ let status = tree. alli ( ) { |k, parent|
192
+ if parent != root && parent != -1 {
193
+ level[ parent] == level[ k] - 1
194
+ }
195
+ else {
196
+ true
197
+ }
198
+ } ;
199
+
200
+ if !status { ret status }
201
+
202
+ // 3. Every edge in the input list has vertices with levels that
203
+ // differ by at most one or that both are not in the BFS tree.
204
+
205
+ log ( info, "Verifying graph edges..." ) ;
206
+
207
+ let status = edges. all ( ) { |e|
208
+ let ( u, v) = e;
209
+
210
+ abs ( level[ u] - level[ v] ) <= 1
211
+ } ;
212
+
213
+ if !status { ret status }
214
+
215
+ // 4. The BFS tree spans an entire connected component's vertices.
216
+
217
+ // This is harder. We'll skip it for now...
218
+
219
+ // 5. A node and its parent are joined by an edge of the original
220
+ // graph.
221
+
222
+ log ( info, "Verifying tree and graph edges..." ) ;
223
+
224
+ let status = tree. alli ( ) { |u, v|
225
+ if v == -1 || u as int == root {
226
+ true
227
+ }
228
+ else {
229
+ log ( info, #fmt ( "Checking for %? or %?" ,
230
+ ( u, v) , ( v, u) ) ) ;
231
+ edges. contains ( ( u as int , v) ) || edges. contains ( ( v, u as int ) )
232
+ }
233
+ } ;
234
+
235
+ if !status { ret status }
236
+
237
+ // If we get through here, all the tests passed!
238
+ true
239
+ }
240
+
145
241
fn main ( ) {
146
242
let scale = 14 u;
147
243
@@ -162,11 +258,20 @@ fn main() {
162
258
io:: stdout ( ) . write_line ( #fmt ( "Generated graph with %? edges in %? seconds." ,
163
259
total_edges / 2 u,
164
260
stop - start) ) ;
261
+
262
+ let root = 0 ;
165
263
166
264
let start = time:: precise_time_s ( ) ;
167
- let bfs_tree = bfs ( graph, 0 ) ;
265
+ let bfs_tree = bfs ( graph, root ) ;
168
266
let stop = time:: precise_time_s ( ) ;
169
267
170
268
io:: stdout ( ) . write_line ( #fmt ( "BFS completed in %? seconds." ,
171
269
stop - start) ) ;
172
- }
270
+
271
+ let start = time:: precise_time_s ( ) ;
272
+ assert ( validate ( graph, edges, root, bfs_tree) ) ;
273
+ let stop = time:: precise_time_s ( ) ;
274
+
275
+ io:: stdout ( ) . write_line ( #fmt ( "Validation completed in %? seconds." ,
276
+ stop - start) ) ;
277
+ }
0 commit comments