SenK
SenK is a C++ library for high-performance linear solvers.
senk_graph.hpp
Go to the documentation of this file.
1
7#ifndef SENK_GRAPH_HPP
8#define SENK_GRAPH_HPP
9
10#include "senk_utils.hpp"
11
12namespace senk {
16namespace graph {
27static void SimpleBlocking( // Simple Blocking
28 int *cind, int *rptr,
29 int **b_cind, int **b_rptr, int **block,
30 int N, int bsize)
31{
32 *block = utils::SafeMalloc<int>(N);
33 for(int i=0; i<N; i++) { (*block)[i] = i; }
34
35 *b_rptr = utils::SafeMalloc<int>(N/bsize+1);
36 *b_cind = utils::SafeMalloc<int>(rptr[N]); // At most rptr[N]
37 int cnt = 0;
38 (*b_rptr)[0] = 0;
39 int *ptr = utils::SafeMalloc<int>(bsize);
40 for(int i=0; i<N; i+=bsize) {
41 // Initialize "ptr"
42 for(int j=0; j<bsize; j++) { ptr[j] = rptr[(*block)[i+j]]; }
43 while(true) {
44 // Find minimum col index
45 int min = N;
46 for(int j=0; j<bsize; j++) {
47 if(ptr[j] != -1 && cind[ptr[j]] < min) {
48 min = cind[ptr[j]];
49 }
50 }
51 if(min == N) break;
52 (*b_cind)[cnt] = min/bsize;
53 for(int j=0; j<bsize; j++) {
54 if(ptr[j] == -1) continue;
55 while(cind[ptr[j]]/bsize == min/bsize) {
56 ptr[j]++;
57 if(ptr[j] >= rptr[(*block)[i+j]+1]) {
58 ptr[j] = -1; break;
59 }
60 }
61 }
62 cnt++;
63 }
64 (*b_rptr)[i/bsize+1] = cnt;
65 }
66}
77static void ConnectedBlocking( // Connected Blocking
78 int *cind, int *rptr,
79 int **b_cind, int **b_rptr, int **block,
80 int N, int bsize)
81{
82 *block = utils::SafeCalloc<int>(N);
83 int *inv_block = utils::SafeCalloc<int>(N);
84 int *visited = utils::SafeCalloc<int>(N);
85 int *queue = utils::SafeCalloc<int>(bsize+1);
86 int qs, qe;
87 int count = 0, tcnt = 0;
88 for(int i=0; i<N; i++) {
89 if(visited[i]) continue;
90 qs = 0; qe = 0; // Clear
91 (*block)[count] = i; count++; tcnt++;
92 inv_block[i] = (count-1) / bsize;
93 visited[i] = 1;
94 if(tcnt == bsize) { tcnt = 0; continue; }
95 queue[qe] = i; qe++; // Enqueue
96 bool isFull = false;
97 while(!isFull) {
98 int q = queue[qs]; qs++; // Dequeue
99 for(int j=rptr[q]; j<rptr[q+1]; j++) {
100 if(visited[cind[j]]) continue;
101 (*block)[count] = cind[j]; count++; tcnt++;
102 inv_block[cind[j]] = (count-1) / bsize;
103 visited[cind[j]] = 1;
104 if(tcnt == bsize) { tcnt = 0; isFull=true; break; }
105 queue[qe] = cind[j]; qe++; // Enqueue
106 }
107 if(qs > qe) { exit(1); }
108 if(qs == qe) { break; }
109 }
110 }
111 for(int i=0; i<N; i+=bsize) senk::helper::QuickSort<int>(*block, i, i+bsize-1);
112
113 *b_rptr = utils::SafeMalloc<int>(N/bsize+1);
114 *b_cind = utils::SafeMalloc<int>(rptr[N]); // At most rptr[N]
115 int *temp = utils::SafeMalloc<int>(rptr[N]); // At most rptr[N]
116 int cnt = 0;
117 (*b_rptr)[0] = 0;
118 for(int i=0; i<N; i+=bsize) {
119 int len = 0;
120 for(int j=0; j<bsize; j++) {
121 for(int k=rptr[(*block)[i+j]]; k<rptr[(*block)[i+j]+1]; k++) {
122 temp[len] = inv_block[cind[k]]; len++;
123 }
124 }
125 helper::QuickSort<int>(temp, 0, len-1);
126 (*b_cind)[cnt] = temp[0]; cnt++;
127 int prev = temp[0];
128 for(int j=1; j<len; j++) {
129 if(temp[j] == prev) continue;
130 (*b_cind)[cnt] = temp[j]; cnt++;
131 prev = temp[j];
132 }
133 (*b_rptr)[i/bsize+1] = cnt;
134 }
135 free(visited);
136 free(queue);
137 free(inv_block);
138 free(temp);
139}
140
150static void GetAdjacency(
151 int *cind, int *rptr,
152 int **am_cind, int **am_rptr,
153 int N, bool isSym)
154{
155 if(isSym) {
156 *am_cind = utils::SafeMalloc<int>(rptr[N]);
157 *am_rptr = utils::SafeMalloc<int>(N+1);
158 utils::Copy<int>(cind, *am_cind, rptr[N]);
159 utils::Copy<int>(rptr, *am_rptr, N+1);
160 }else {
161 int *rind = utils::SafeMalloc<int>(rptr[N]);
162 int *cptr = utils::SafeMalloc<int>(N+1);
163 int *len = utils::SafeCalloc<int>(N);
164 for(int i=0; i<N; i++) {
165 for(int j=rptr[i]; j<rptr[i+1]; j++) {
166 len[cind[j]]++;
167 }
168 }
169 cptr[0] = 0;
170 for(int i=0; i<N; i++) {
171 cptr[i+1] = cptr[i] + len[i];
172 len[i] = 0;
173 }
174 for(int i=0; i<N; i++) {
175 for(int j=rptr[i]; j<rptr[i+1]; j++) {
176 rind[cptr[cind[j]]+len[cind[j]]] = i;
177 len[cind[j]]++;
178 }
179 }
180 *am_cind = utils::SafeMalloc<int>(rptr[N]*2);
181 *am_rptr = utils::SafeMalloc<int>(N+1);
182 (*am_rptr)[0] = 0;
183 int cnt = 0;
184 for(int i=0; i<N; i++) {
185 int csr_ptr = rptr[i];
186 int csc_ptr = cptr[i];
187 while(csr_ptr < rptr[i+1] || csc_ptr < cptr[i+1]) {
188 int csr_idx = (csr_ptr < rptr[i+1])? cind[csr_ptr] : N;
189 int csc_idx = (csc_ptr < cptr[i+1])? rind[csc_ptr] : N;
190 if(csr_idx < csc_idx) {
191 (*am_cind)[cnt] = csr_idx;
192 csr_ptr++;
193 }else if(csr_idx == csc_idx){
194 (*am_cind)[cnt] = csr_idx;
195 csr_ptr++;
196 csc_ptr++;
197 }else {
198 (*am_cind)[cnt] = csc_idx;
199 csc_ptr++;
200 }
201 cnt++;
202 }
203 (*am_rptr)[i+1] = cnt;
204 }
205 free(rind);
206 free(cptr);
207 free(len);
208 }
209}
218static void Coloring( // Greedy Coloring
219 int *cind, int *rptr, int **color, int *num_color, int N)
220{
221 *color = utils::SafeCalloc<int>(N);
222 int *visit = utils::SafeCalloc<int>(N);
223 int now = 1;
224 int cnt = 0;
225 while(cnt < N) {
226 for(int i=0; i<N; i++) {
227 if(visit[i] == now || (*color)[i] != 0) continue;
228 (*color)[i] = now;
229 cnt++;
230 for(int j=rptr[i]; j<rptr[i+1]; j++) {
231 visit[cind[j]] = now;
232 }
233 }
234 now++;
235 }
236 *num_color = now - 1;
237 free(visit);
238}
251 int *cind, int *rptr,
252 int *num_color, int **size_color, int **LP, int **RP,
253 int N, bool isSym)
254{
255 int *am_cind;
256 int *am_rptr;
257 GetAdjacency(cind, rptr, &am_cind, &am_rptr, N, isSym);
258 int *color;
259 // Greedy Coloring
260 Coloring(am_cind, am_rptr, &color, num_color, N);
261 *LP = utils::SafeMalloc<int>(N);
262 *size_color = utils::SafeMalloc<int>(*num_color+1);
263 (*size_color)[0] = 0;
264 int cnt = 0;
265 for(int i=0; i<*num_color; i++) {
266 int temp_cnt = 0;
267 for(int j=0; j<N; j++) {
268 if(color[j]-1 != i) continue;
269 (*LP)[cnt] = j;
270 cnt++;
271 temp_cnt++;
272 }
273 (*size_color)[i+1] = (*size_color)[i] + temp_cnt;
274 }
275 *RP = utils::SafeMalloc<int>(N);
276 for(int i=0; i<N; i++) {(*RP)[(*LP)[i]] = i;}
277}
292 int *cind, int *rptr,
293 int *num_color, int **size_color, int **LP, int **RP,
294 int N, int bsize, bool isSym, const char *bmethod)
295{
296 if(N%bsize) {
297 printf("Error: GetABMCPermutation\n");
298 exit(1);
299 }
300 int *b_cind;
301 int *b_rptr;
302 int *block;
303 if(std::strcmp(bmethod, "simple") == 0) {
304 SimpleBlocking(cind, rptr, &b_cind, &b_rptr, &block, N, bsize);
305 }else if(std::strcmp(bmethod, "connect") == 0) {
306 ConnectedBlocking(cind, rptr, &b_cind, &b_rptr, &block, N, bsize);
307 }else {
308 printf("Error: GetABMCPermutation\n");
309 printf("The blocking method is invalid\n");
310 exit(1);
311 }
312 int *am_cind;
313 int *am_rptr;
314 GetAdjacency(b_cind, b_rptr, &am_cind, &am_rptr, N/bsize, isSym);
315 int *color;
316 // Greedy Coloring
317 Coloring(am_cind, am_rptr, &color, num_color, N/bsize);
318 *LP = utils::SafeMalloc<int>(N);
319 *size_color = utils::SafeMalloc<int>(*num_color+1);
320 (*size_color)[0] = 0;
321 int cnt = 0;
322 for(int i=0; i<*num_color; i++) {
323 for(int j=0; j<N/bsize; j++) {
324 if(color[j]-1 != i) continue;
325 for(int k=0; k<bsize; k++) {
326 (*LP)[cnt] = block[j*bsize+k];
327 cnt++;
328 }
329 }
330 (*size_color)[i+1] = cnt/bsize;
331 }
332 *RP = utils::SafeMalloc<int>(N);
333 for(int i=0; i<N; i++) {(*RP)[(*LP)[i]] = i;}
334}
335
336
337} // namespace graph
338
339} // namespace senk
340
341#endif
void GetAMCPermutation(int *cind, int *rptr, int *num_color, int **size_color, int **LP, int **RP, int N, bool isSym)
Create an permutation matrix based on the AMC ordering technique.
Definition: senk_graph.hpp:250
void GetABMCPermutation(int *cind, int *rptr, int *num_color, int **size_color, int **LP, int **RP, int N, int bsize, bool isSym, const char *bmethod)
Create an permutation matrix based on the ABMC ordering technique, .
Definition: senk_graph.hpp:291
The top-level namespace of SenK.
Utility functions are defined.