1
+ /**
2
+
3
+ An implementation of the Graph500 Bread First Search problem in Rust.
4
+
5
+ */
6
+
7
+ use std;
8
+ import std:: time;
9
+ import std:: map;
10
+ import std:: map:: hashmap;
11
+ import std:: deque;
12
+ import std:: deque:: t;
13
+ import io:: writer_util;
14
+ import vec:: extensions;
15
+ import comm:: * ;
16
+
17
+ type node_id = i64 ;
18
+ type graph = [ map:: set < node_id > ] ;
19
+
20
+ iface queue<T : send> {
21
+ fn add_back ( T ) ;
22
+ fn pop_front ( ) -> T ;
23
+ fn size ( ) -> uint ;
24
+ }
25
+
26
+ #[ doc="Creates a queue based on ports and channels.
27
+
28
+ This is admittedly not ideal, but it will help us work around the deque
29
+ bugs for the time being." ]
30
+ fn create_queue < T : send > ( ) -> queue < T > {
31
+ type repr < T : send > = {
32
+ p : port < T > ,
33
+ c : chan < T > ,
34
+ mut s : uint ,
35
+ } ;
36
+
37
+ let p = port ( ) ;
38
+ let c = chan ( p) ;
39
+
40
+ impl < T : send > of queue < T > for repr < T > {
41
+ fn add_back ( x : T ) {
42
+ let x = x;
43
+ send ( self . c , x) ;
44
+ self . s += 1 u;
45
+ }
46
+
47
+ fn pop_front ( ) -> T {
48
+ self . s -= 1 u;
49
+ recv ( self . p )
50
+ }
51
+
52
+ fn size ( ) -> uint { self . s }
53
+ }
54
+
55
+ let Q : repr < T > = { p : p, c : c, mut s : 0 u } ;
56
+ Q as queue :: < T >
57
+ }
58
+
59
+ fn make_edges ( scale : uint , edgefactor : uint ) -> [ ( node_id , node_id ) ] {
60
+ let r = rand:: rng ( ) ;
61
+
62
+ fn choose_edge ( i : node_id , j : node_id , scale : uint , r : rand:: rng )
63
+ -> ( node_id , node_id ) {
64
+
65
+ let A = 0.57 ;
66
+ let B = 0.19 ;
67
+ let C = 0.19 ;
68
+
69
+ if scale == 0 u {
70
+ ( i, j)
71
+ }
72
+ else {
73
+ let i = i * 2 ;
74
+ let j = j * 2 ;
75
+ let scale = scale - 1 u;
76
+
77
+ let x = r. next_float ( ) ;
78
+
79
+ if x < A {
80
+ choose_edge ( i, j, scale, r)
81
+ }
82
+ else {
83
+ let x = x - A ;
84
+ if x < B {
85
+ choose_edge ( i + 1 , j, scale, r)
86
+ }
87
+ else {
88
+ let x = x - B ;
89
+ if x < C {
90
+ choose_edge ( i, j + 1 , scale, r)
91
+ }
92
+ else {
93
+ choose_edge ( i + 1 , j + 1 , scale, r)
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ vec:: from_fn ( ( 1 u << scale) * edgefactor) { |_i|
101
+ choose_edge ( 0 , 0 , scale, r)
102
+ }
103
+ }
104
+
105
+ fn make_graph ( N : uint , edges : [ ( node_id , node_id ) ] ) -> graph {
106
+ let graph = vec:: from_fn ( N ) { |_i| map:: int_hash ( ) } ;
107
+
108
+ vec:: each ( edges) { |e|
109
+ let ( i, j) = e;
110
+ map:: set_add ( graph[ i] , j) ;
111
+ map:: set_add ( graph[ j] , i) ;
112
+ true
113
+ }
114
+
115
+ graph
116
+ }
117
+
118
+ #[ doc="Returns a vector of all the parents in the BFS tree rooted at key.
119
+
120
+ Nodes that are unreachable have a parent of -1." ]
121
+ fn bfs ( graph : graph , key : node_id ) -> [ node_id ] {
122
+ let marks : [ mut node_id ]
123
+ = vec:: to_mut ( vec:: from_elem ( vec:: len ( graph) , -1 ) ) ;
124
+
125
+ let Q = create_queue ( ) ;
126
+
127
+ Q . add_back ( key) ;
128
+ marks[ key] = key;
129
+
130
+ while Q . size ( ) > 0 u {
131
+ let t = Q . pop_front ( ) ;
132
+
133
+ graph[ t] . each_key ( ) { |k|
134
+ if marks[ k] == -1 {
135
+ marks[ k] = t;
136
+ Q . add_back ( k) ;
137
+ }
138
+ true
139
+ } ;
140
+ }
141
+
142
+ vec:: from_mut ( marks)
143
+ }
144
+
145
+ fn main ( ) {
146
+ let scale = 14 u;
147
+
148
+ let start = time:: precise_time_s ( ) ;
149
+ let edges = make_edges ( scale, 16 u) ;
150
+ let stop = time:: precise_time_s ( ) ;
151
+
152
+ io:: stdout ( ) . write_line ( #fmt ( "Generated %? edges in %? seconds." ,
153
+ vec:: len ( edges) , stop - start) ) ;
154
+
155
+ let start = time:: precise_time_s ( ) ;
156
+ let graph = make_graph ( 1 u << scale, edges) ;
157
+ let stop = time:: precise_time_s ( ) ;
158
+
159
+ let mut total_edges = 0 u;
160
+ vec:: each ( graph) { |edges| total_edges += edges. size ( ) ; true } ;
161
+
162
+ io:: stdout ( ) . write_line ( #fmt ( "Generated graph with %? edges in %? seconds." ,
163
+ total_edges / 2 u,
164
+ stop - start) ) ;
165
+
166
+ let start = time:: precise_time_s ( ) ;
167
+ let bfs_tree = bfs ( graph, 0 ) ;
168
+ let stop = time:: precise_time_s ( ) ;
169
+
170
+ io:: stdout ( ) . write_line ( #fmt ( "BFS completed in %? seconds." ,
171
+ stop - start) ) ;
172
+ }
0 commit comments