comparison src/DLD-FUNCTIONS/symrcm.cc @ 11586:12df7854fa7c

strip trailing whitespace from source files
author John W. Eaton <jwe@octave.org>
date Thu, 20 Jan 2011 17:24:59 -0500
parents 01f703952eff
children 72c96de7a403
comparison
equal deleted inserted replaced
11585:1473d0cf86d2 11586:12df7854fa7c
81 // Queues Q have a fixed maximum size N (rows,cols of the matrix) and are 81 // Queues Q have a fixed maximum size N (rows,cols of the matrix) and are
82 // stored in an array. qh and qt point to queue head and tail. 82 // stored in an array. qh and qt point to queue head and tail.
83 83
84 // Enqueue operation (adds a node "o" at the tail) 84 // Enqueue operation (adds a node "o" at the tail)
85 85
86 inline static void 86 inline static void
87 Q_enq (CMK_Node *Q, octave_idx_type N, octave_idx_type& qt, const CMK_Node& o) 87 Q_enq (CMK_Node *Q, octave_idx_type N, octave_idx_type& qt, const CMK_Node& o)
88 { 88 {
89 Q[qt] = o; 89 Q[qt] = o;
90 qt = (qt + 1) % (N + 1); 90 qt = (qt + 1) % (N + 1);
91 } 91 }
92 92
93 // Dequeue operation (removes a node from the head) 93 // Dequeue operation (removes a node from the head)
94 94
95 inline static CMK_Node 95 inline static CMK_Node
96 Q_deq (CMK_Node * Q, octave_idx_type N, octave_idx_type& qh) 96 Q_deq (CMK_Node * Q, octave_idx_type N, octave_idx_type& qh)
97 { 97 {
98 CMK_Node r = Q[qh]; 98 CMK_Node r = Q[qh];
99 qh = (qh + 1) % (N + 1); 99 qh = (qh + 1) % (N + 1);
100 return r; 100 return r;
113 #define PARENT(i) (((i) - 1) >> 1) // = floor(((i)-1)/2) 113 #define PARENT(i) (((i) - 1) >> 1) // = floor(((i)-1)/2)
114 114
115 // Builds a min-heap (the root contains the smallest element). A is an array 115 // Builds a min-heap (the root contains the smallest element). A is an array
116 // with the graph's nodes, i is a starting position, size is the length of A. 116 // with the graph's nodes, i is a starting position, size is the length of A.
117 117
118 static void 118 static void
119 H_heapify_min (CMK_Node *A, octave_idx_type i, octave_idx_type size) 119 H_heapify_min (CMK_Node *A, octave_idx_type i, octave_idx_type size)
120 { 120 {
121 octave_idx_type j = i; 121 octave_idx_type j = i;
122 for (;;) 122 for (;;)
123 { 123 {
138 CMK_Node tmp = A[j]; 138 CMK_Node tmp = A[j];
139 A[j] = A[smallest]; 139 A[j] = A[smallest];
140 A[smallest] = tmp; 140 A[smallest] = tmp;
141 j = smallest; 141 j = smallest;
142 } 142 }
143 else 143 else
144 break; 144 break;
145 } 145 }
146 } 146 }
147 147
148 // Heap operation insert. Running time is O(log(n)) 148 // Heap operation insert. Running time is O(log(n))
149 149
150 static void 150 static void
151 H_insert (CMK_Node *H, octave_idx_type& h, const CMK_Node& o) 151 H_insert (CMK_Node *H, octave_idx_type& h, const CMK_Node& o)
152 { 152 {
153 octave_idx_type i = h++; 153 octave_idx_type i = h++;
154 154
155 H[i] = o; 155 H[i] = o;
156 156
157 if (i == 0) 157 if (i == 0)
158 return; 158 return;
159 do 159 do
160 { 160 {
161 octave_idx_type p = PARENT(i); 161 octave_idx_type p = PARENT(i);
162 if (H[i].deg < H[p].deg) 162 if (H[i].deg < H[p].deg)
165 H[i] = H[p]; 165 H[i] = H[p];
166 H[p] = tmp; 166 H[p] = tmp;
167 167
168 i = p; 168 i = p;
169 } 169 }
170 else 170 else
171 break; 171 break;
172 } 172 }
173 while (i > 0); 173 while (i > 0);
174 } 174 }
175 175
176 // Heap operation remove-min. Removes the smalles element in O(1) and 176 // Heap operation remove-min. Removes the smalles element in O(1) and
177 // reorganizes the heap optionally in O(log(n)) 177 // reorganizes the heap optionally in O(log(n))
178 178
179 inline static CMK_Node 179 inline static CMK_Node
180 H_remove_min (CMK_Node *H, octave_idx_type& h, int reorg/*=1*/) 180 H_remove_min (CMK_Node *H, octave_idx_type& h, int reorg/*=1*/)
181 { 181 {
182 CMK_Node r = H[0]; 182 CMK_Node r = H[0];
183 H[0] = H[--h]; 183 H[0] = H[--h];
184 if (reorg) 184 if (reorg)
185 H_heapify_min(H, 0, h); 185 H_heapify_min(H, 0, h);
186 return r; 186 return r;
187 } 187 }
188 188
189 // Predicate (heap empty) 189 // Predicate (heap empty)
190 #define H_empty(H, h) ((h) == 0) 190 #define H_empty(H, h) ((h) == 0)
191 191
192 // Helper function for the Cuthill-McKee algorithm. Tries to determine a 192 // Helper function for the Cuthill-McKee algorithm. Tries to determine a
193 // pseudo-peripheral node of the graph as starting node. 193 // pseudo-peripheral node of the graph as starting node.
194 194
195 static octave_idx_type 195 static octave_idx_type
196 find_starting_node (octave_idx_type N, const octave_idx_type *ridx, 196 find_starting_node (octave_idx_type N, const octave_idx_type *ridx,
197 const octave_idx_type *cidx, const octave_idx_type *ridx2, 197 const octave_idx_type *cidx, const octave_idx_type *ridx2,
198 const octave_idx_type *cidx2, octave_idx_type *D, 198 const octave_idx_type *cidx2, octave_idx_type *D,
199 octave_idx_type start) 199 octave_idx_type start)
200 { 200 {
201 CMK_Node w; 201 CMK_Node w;
202 202
203 OCTAVE_LOCAL_BUFFER (CMK_Node, Q, N+1); 203 OCTAVE_LOCAL_BUFFER (CMK_Node, Q, N+1);
325 } 325 }
326 return x.id; 326 return x.id;
327 } 327 }
328 328
329 // Calculates the node's degrees. This means counting the non-zero elements 329 // Calculates the node's degrees. This means counting the non-zero elements
330 // in the symmetric matrix' rows. This works for non-symmetric matrices 330 // in the symmetric matrix' rows. This works for non-symmetric matrices
331 // as well. 331 // as well.
332 332
333 static octave_idx_type 333 static octave_idx_type
334 calc_degrees (octave_idx_type N, const octave_idx_type *ridx, 334 calc_degrees (octave_idx_type N, const octave_idx_type *ridx,
335 const octave_idx_type *cidx, octave_idx_type *D) 335 const octave_idx_type *cidx, octave_idx_type *D)
336 { 336 {
337 octave_idx_type max_deg = 0; 337 octave_idx_type max_deg = 0;
338 338
339 for (octave_idx_type i = 0; i < N; i++) 339 for (octave_idx_type i = 0; i < N; i++)
340 D[i] = 0; 340 D[i] = 0;
341 341
342 for (octave_idx_type j = 0; j < N; j++) 342 for (octave_idx_type j = 0; j < N; j++)
343 { 343 {
344 for (octave_idx_type i = cidx[j]; i < cidx[j+1]; i++) 344 for (octave_idx_type i = cidx[j]; i < cidx[j+1]; i++)
345 { 345 {
346 OCTAVE_QUIT; 346 OCTAVE_QUIT;
347 octave_idx_type k = ridx[i]; 347 octave_idx_type k = ridx[i];
348 // there is a non-zero element (k,j) 348 // there is a non-zero element (k,j)
349 D[k]++; 349 D[k]++;
350 if (D[k] > max_deg) 350 if (D[k] > max_deg)
351 max_deg = D[k]; 351 max_deg = D[k];
352 // if there is no element (j,k) there is one in 352 // if there is no element (j,k) there is one in
353 // the symmetric matrix: 353 // the symmetric matrix:
354 if (k != j) 354 if (k != j)
355 { 355 {
369 369
370 if (! found) 370 if (! found)
371 { 371 {
372 // A(j,k) == 0 372 // A(j,k) == 0
373 D[j]++; 373 D[j]++;
374 if (D[j] > max_deg) 374 if (D[j] > max_deg)
375 max_deg = D[j]; 375 max_deg = D[j];
376 } 376 }
377 } 377 }
378 } 378 }
379 } 379 }
381 } 381 }
382 382
383 // Transpose of the structure of a square sparse matrix 383 // Transpose of the structure of a square sparse matrix
384 384
385 static void 385 static void
386 transpose (octave_idx_type N, const octave_idx_type *ridx, 386 transpose (octave_idx_type N, const octave_idx_type *ridx,
387 const octave_idx_type *cidx, octave_idx_type *ridx2, 387 const octave_idx_type *cidx, octave_idx_type *ridx2,
388 octave_idx_type *cidx2) 388 octave_idx_type *cidx2)
389 { 389 {
390 octave_idx_type nz = cidx[N]; 390 octave_idx_type nz = cidx[N];
391 391
392 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, N + 1); 392 OCTAVE_LOCAL_BUFFER (octave_idx_type, w, N + 1);
449 return retval; 449 return retval;
450 } 450 }
451 451
452 octave_value arg = args(0); 452 octave_value arg = args(0);
453 453
454 // the parameter of the matrix is converted into a sparse matrix 454 // the parameter of the matrix is converted into a sparse matrix
455 //(if necessary) 455 //(if necessary)
456 octave_idx_type *cidx; 456 octave_idx_type *cidx;
457 octave_idx_type *ridx; 457 octave_idx_type *ridx;
458 SparseMatrix Ar; 458 SparseMatrix Ar;
459 SparseComplexMatrix Ac; 459 SparseComplexMatrix Ac;
509 509
510 // if none of the nodes has a degree > 0 (a matrix of zeros) 510 // if none of the nodes has a degree > 0 (a matrix of zeros)
511 // the return value corresponds to the identity permutation 511 // the return value corresponds to the identity permutation
512 if (max_deg == 0) 512 if (max_deg == 0)
513 { 513 {
514 for (octave_idx_type i = 0; i < N; i++) 514 for (octave_idx_type i = 0; i < N; i++)
515 P(i) = i; 515 P(i) = i;
516 return octave_value (P); 516 return octave_value (P);
517 } 517 }
518 518
519 // a heap for the a node's neighbors. The number of neighbors is 519 // a heap for the a node's neighbors. The number of neighbors is
533 // bandwidths. 533 // bandwidths.
534 octave_idx_type B = 0; 534 octave_idx_type B = 0;
535 535
536 // mark all nodes as unvisited; with the exception of the nodes 536 // mark all nodes as unvisited; with the exception of the nodes
537 // that have degree==0 and build a CC of the graph. 537 // that have degree==0 and build a CC of the graph.
538 538
539 boolNDArray btmp (dim_vector (1, N), false); 539 boolNDArray btmp (dim_vector (1, N), false);
540 bool *visit = btmp.fortran_vec (); 540 bool *visit = btmp.fortran_vec ();
541 541
542 do 542 do
543 { 543 {
544 // locate an unvisited starting node of the graph 544 // locate an unvisited starting node of the graph
545 octave_idx_type i; 545 octave_idx_type i;
546 for (i = 0; i < N; i++) 546 for (i = 0; i < N; i++)
547 if (! visit[i]) 547 if (! visit[i])
548 break; 548 break;
549 549
550 // locate a probably better starting node 550 // locate a probably better starting node
551 v.id = find_starting_node (N, ridx, cidx, ridx2, cidx2, D, i); 551 v.id = find_starting_node (N, ridx, cidx, ridx2, cidx2, D, i);
552 552
553 // mark the node as visited and enqueue it (a starting node 553 // mark the node as visited and enqueue it (a starting node
554 // for the BFS). Since the node will be a root of a spanning 554 // for the BFS). Since the node will be a root of a spanning
555 // tree, its dist is 0. 555 // tree, its dist is 0.
556 v.deg = D[v.id]; 556 v.deg = D[v.id];
557 v.dist = 0; 557 v.dist = 0;
565 octave_idx_type Bsub = 0; 565 octave_idx_type Bsub = 0;
566 // min. dist. to the root is 0 566 // min. dist. to the root is 0
567 octave_idx_type level = 0; 567 octave_idx_type level = 0;
568 // the root is the first/only node on level 0 568 // the root is the first/only node on level 0
569 octave_idx_type level_N = 1; 569 octave_idx_type level_N = 1;
570 570
571 while (! Q_empty (Q, N, qh, qt)) 571 while (! Q_empty (Q, N, qh, qt))
572 { 572 {
573 v = Q_deq (Q, N, qh); 573 v = Q_deq (Q, N, qh);
574 i = v.id; 574 i = v.id;
575 575
576 c++; 576 c++;
577 577
578 // for computing the inverse permutation P where 578 // for computing the inverse permutation P where
579 // A(inv(P),inv(P)) or P'*A*P is banded 579 // A(inv(P),inv(P)) or P'*A*P is banded
580 // P(i) = c; 580 // P(i) = c;
581 581
582 // for computing permutation P where 582 // for computing permutation P where
583 // A(P(i),P(j)) or P*A*P' is banded 583 // A(P(i),P(j)) or P*A*P' is banded
584 P(c) = i; 584 P(c) = i;
585 585
586 // put all unvisited neighbors j of node i on the heap 586 // put all unvisited neighbors j of node i on the heap
655 { 655 {
656 OCTAVE_QUIT; 656 OCTAVE_QUIT;
657 657
658 // locate a neighbor of i with minimal degree in O(log(N)) 658 // locate a neighbor of i with minimal degree in O(log(N))
659 v = H_remove_min(S, s, 1); 659 v = H_remove_min(S, s, 1);
660 660
661 // entered the BFS a new level? 661 // entered the BFS a new level?
662 if (v.dist > level) 662 if (v.dist > level)
663 { 663 {
664 // adjustment of bandwith: 664 // adjustment of bandwith:
665 // "[...] the minimum bandwidth that 665 // "[...] the minimum bandwidth that
666 // can be obtained [...] is the 666 // can be obtained [...] is the
667 // maximum number of nodes per level" 667 // maximum number of nodes per level"
668 if (Bsub < level_N) 668 if (Bsub < level_N)
669 Bsub = level_N; 669 Bsub = level_N;
670 670
671 level = v.dist; 671 level = v.dist;
672 // v is the first node on the new level 672 // v is the first node on the new level
673 level_N = 1; 673 level_N = 1;
674 } 674 }
675 else 675 else
676 { 676 {
677 // there is no new level but another node on 677 // there is no new level but another node on
678 // this level: 678 // this level:
679 level_N++; 679 level_N++;
680 } 680 }
681 681
682 // enqueue v in O(1) 682 // enqueue v in O(1)
683 Q_enq (Q, N, qt, v); 683 Q_enq (Q, N, qt, v);
684 } 684 }
685 685
686 // synchronize the bandwidth with level_N once again: 686 // synchronize the bandwidth with level_N once again:
687 if (Bsub < level_N) 687 if (Bsub < level_N)
688 Bsub = level_N; 688 Bsub = level_N;
689 } 689 }
690 // finish of BFS. If there are still unvisited nodes in the graph 690 // finish of BFS. If there are still unvisited nodes in the graph