@@ -4,114 +4,149 @@ struct
4
4
5
5
structure G = AdjacencyGraph(Int)
6
6
structure AS = ArraySlice
7
- structure DS = DelayedSeq
7
+ open G.VertexSubset
8
8
9
-
10
- (* fun sumOfOutDegrees frontier =
11
- SeqBasis.reduce 10000 op+ 0 (0, Seq.length frontier) (degree o Seq.nth frontier)
12
- (* DS.reduce op+ 0 (DS.map degree (DS.fromArraySeq frontier)) *)
13
-
14
- fun shouldProcessDense frontier =
15
- let
16
- val n = Seq.length frontier
17
- val m = sumOfOutDegrees frontier
18
- in
19
- n + m > denseThreshold
20
- end *)
21
-
22
- fun should_process_sparse g V =
9
+ fun should_process_sparse g n =
23
10
let
24
11
val denseThreshold = G.numEdges g div 20
25
- val totalOutDegree =
26
- SeqBasis.reduce 10000 op + 0 (0 , Seq.length V) (G.degree g o Seq.nth V)
27
- val n = Seq.length V
28
- val m = totalOutDegree
12
+ val deg = Int.div (G.numEdges g, G.numVertices g)
13
+ val count = (1 + deg) * n
29
14
in
30
- n + m <= denseThreshold
15
+ count <= denseThreshold
31
16
end
32
17
33
-
34
18
fun edge_map_dense g vertices f h =
35
19
let
36
- val inFrontier = Seq.tabulate ( fn _ => false ) (G.numVertices g)
37
- val _ = Seq.foreach vertices ( fn (_, v) =>
38
- ArraySlice.update (inFrontier, v, true ))
20
+ val inFrontier = vertices
21
+ val n = Seq.length vertices
22
+ val res = Seq.tabulate ( fn _ => 0 ) n
39
23
40
24
fun processVertex v =
41
- if not (h v) then NONE
25
+ if not (h v) then 0
42
26
else
43
27
let
44
28
val neighbors = G.neighbors g v
45
29
fun loop i =
46
- if i >= Seq.length neighbors then NONE else
30
+ if i >= Seq.length neighbors then 0 else
47
31
let val u = Seq.nth neighbors i
48
32
in
49
- if not (Seq.nth inFrontier u) then
33
+ if not (Seq.nth inFrontier u = 1 ) then
50
34
loop (i+1 )
51
35
else
52
- case f (u, v) of
53
- NONE => loop (i+1 )
54
- | SOME x => SOME x
36
+ case f (u, v) of
37
+ NONE => loop (i+1 )
38
+ | SOME x => (AS.update (res, x, 1 ); 1 )
55
39
end
56
40
in
57
41
loop 0
58
42
end
43
+ val count = SeqBasis.reduce 1000 op + 0 (0 , n) processVertex
59
44
in
60
- AS.full (SeqBasis.tabFilter 100 ( 0 , G.numVertices g) processVertex )
45
+ (res, count )
61
46
end
62
47
63
-
64
48
fun edge_map_sparse g vertices f h =
65
49
let
66
- fun app_vertex u =
50
+ val n = Seq.length vertices
51
+ fun ui uidx = Seq.nth vertices uidx
52
+ val r =
53
+ SeqBasis.scan 1000 op + 0 (0 , n) (G.degree g o ui)
54
+ val (offsets, totalOutDegree) = (AS.full r, Array.sub (r, n))
55
+ val store = ForkJoin.alloc totalOutDegree
56
+ val k = 100
57
+ val numBlocks = 1 + (totalOutDegree-1 ) div k
58
+ fun map_block i =
67
59
let
68
- val all_ngbrs = (G.neighbors g u)
69
- fun ds i = let
70
- val v = Seq.nth all_ngbrs i
71
- in
72
- if h (v) then f (u, v)
73
- else NONE
74
- end
75
- val m = SeqBasis.tabFilter 10000 (0 , Seq.length all_ngbrs) ds
60
+ val lo = i*k
61
+ val hi = Int.min((i+1 )*k, totalOutDegree)
62
+ val ulo =
63
+ let
64
+ val a = BinarySearch.search (Int.compare) offsets lo
65
+ in
66
+ if (Seq.nth offsets a) > lo then a - 1
67
+ else a
68
+ end
69
+ fun map_seq idx (u, uidx) count =
70
+ if idx >= hi then count
71
+ else if idx >= (Seq.nth offsets (uidx + 1 )) then map_seq idx (ui (uidx + 1 ), uidx + 1 ) count
72
+ else
73
+ let
74
+ val v = Seq.nth (G.neighbors g u) (idx - (Seq.nth offsets uidx))
75
+ in
76
+ if (h v) then
77
+ case f (u, v) of
78
+ SOME x => (Array.update (store, lo + count, x); map_seq (idx + 1 ) (u, uidx) (count + 1 ))
79
+ | NONE => (map_seq (idx + 1 ) (u, uidx) count)
80
+ else
81
+ (map_seq (idx + 1 ) (u, uidx) count)
82
+ end
76
83
in
77
- DS.fromArraySeq (AS.full m)
84
+ map_seq lo (ui ulo, ulo) 0
78
85
end
86
+ val counts = SeqBasis.tabulate 1 (0 , numBlocks) map_block
87
+ val outOff = SeqBasis.scan 10000 op + 0 (0 , numBlocks) (fn i => Array.sub (counts, i))
88
+ val outSize = Array.sub (outOff, numBlocks)
89
+ val result = ForkJoin.alloc outSize
79
90
in
80
- DS.toArraySeq (DS.flatten (DS.map app_vertex (DS.fromArraySeq vertices)))
91
+ ForkJoin.parfor (totalOutDegree div (Int.max (outSize, 1 ))) (0 , numBlocks) (fn i =>
92
+ let
93
+ val soff = i * k
94
+ val doff = Array.sub (outOff, i)
95
+ val size = Array.sub (outOff, i+1 ) - doff
96
+ in
97
+ Util.for (0 , size) (fn j =>
98
+ Array.update (result, doff+j, Array.sub (store, soff+j)))
99
+ end );
100
+ (AS.full result)
81
101
end
82
102
83
- fun edge_map g V f h =
84
- if should_process_sparse g V then
85
- edge_map_sparse g V f h
86
- else
87
- edge_map_dense g V f h
103
+ fun edge_map g (vs, threshold) (fpar, f) h =
104
+ case vs of
105
+ SPARSE s =>
106
+ from_sparse_rep (edge_map_sparse g s fpar h) threshold (G.numVertices g)
107
+ | DENSE s =>
108
+ let
109
+ val (res, count) = edge_map_dense g s f h
110
+ in
111
+ from_dense_rep res (SOME count) threshold
112
+ end
88
113
89
- fun contract clusters g =
90
- let
91
- val n = G.numVertices g
92
- val vertices = Seq.tabulate (fn u => u) n
93
- val has_neighbor = Seq.tabulate (fn i => 0 ) n
114
+ fun vertex_foreach g (vs, threshold) f =
115
+ case vs of
116
+ SPARSE s =>
117
+ Seq.foreach s (fn (i, u) => f u)
118
+ | DENSE s =>
119
+ Seq.foreach s (fn (i, b) => if (b = 1 ) then (f i) else ())
94
120
95
- fun upd (u, v) =
121
+ fun vertex_map_ g (vs, threshold) f =
122
+ case vs of
123
+ SPARSE s =>
96
124
let
97
- val (cu, cv) = ((Seq.nth clusters u), (Seq.nth clusters v))
125
+ val s' =
126
+ AS.full (SeqBasis.tabFilter 1000 (0 , Seq.length s)
127
+ (fn i =>
128
+ let
129
+ val u = Seq.nth s i
130
+ val b = f u
131
+ in
132
+ if b then SOME u
133
+ else NONE
134
+ end
135
+ ))
98
136
in
99
- if cu = cv then NONE
100
- else (AS.update (has_neighbor, cu, 1 ); SOME (cu, cv))
137
+ (from_sparse_rep s' threshold (G.numVertices g))
101
138
end
102
- val sorted_edges = G.dedupEdges (edge_map g vertices upd (fn _ => true ))
103
- val (vmap, num_taken) = Seq.scan Int.+ 0 has_neighbor
104
- val new_sorted_edges = Seq.map (fn (x, y) => (Seq.nth vmap x, Seq.nth vmap y)) sorted_edges
105
-
106
- fun new_label c =
139
+ | DENSE s =>
107
140
let
108
- val is_taken = (Seq.nth has_neighbor c) = 1
109
- val num_taken_left = Seq.nth vmap c
141
+ val res =
142
+ Seq.map ( fn i => if ( Seq.nth s i = 1 ) andalso f i then 1 else 0 ) s
110
143
in
111
- if is_taken then num_taken_left
112
- else num_taken + (c - num_taken_left)
144
+ from_dense_rep res NONE threshold
113
145
end
114
- in
115
- (G.fromSortedEdges new_sorted_edges, new_label)
116
- end
146
+
147
+
148
+ fun vertex_map g vs f needOut =
149
+ if needOut then vertex_map_ g vs f
150
+ else (vertex_foreach g vs; vs)
151
+
117
152
end
0 commit comments