csDfs.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { csMarked } from './csMarked.js';
  2. import { csMark } from './csMark.js';
  3. import { csUnflip } from './csUnflip.js';
  4. /**
  5. * Depth-first search computes the nonzero pattern xi of the directed graph G (Matrix) starting
  6. * at nodes in B (see csReach()).
  7. *
  8. * @param {Number} j The starting node for the DFS algorithm
  9. * @param {Matrix} g The G matrix to search, ptr array modified, then restored
  10. * @param {Number} top Start index in stack xi[top..n-1]
  11. * @param {Number} k The kth column in B
  12. * @param {Array} xi The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
  13. * The first n entries is the nonzero pattern, the last n entries is the stack
  14. * @param {Array} pinv The inverse row permutation vector, must be null for L * x = b
  15. *
  16. * @return {Number} New value of top
  17. *
  18. * Reference: http://faculty.cse.tamu.edu/davis/publications.html
  19. */
  20. export function csDfs(j, g, top, xi, pinv) {
  21. // g arrays
  22. var index = g._index;
  23. var ptr = g._ptr;
  24. var size = g._size;
  25. // columns
  26. var n = size[1];
  27. // vars
  28. var i, p, p2;
  29. // initialize head
  30. var head = 0;
  31. // initialize the recursion stack
  32. xi[0] = j;
  33. // loop
  34. while (head >= 0) {
  35. // get j from the top of the recursion stack
  36. j = xi[head];
  37. // apply permutation vector
  38. var jnew = pinv ? pinv[j] : j;
  39. // check node j is marked
  40. if (!csMarked(ptr, j)) {
  41. // mark node j as visited
  42. csMark(ptr, j);
  43. // update stack (last n entries in xi)
  44. xi[n + head] = jnew < 0 ? 0 : csUnflip(ptr[jnew]);
  45. }
  46. // node j done if no unvisited neighbors
  47. var done = 1;
  48. // examine all neighbors of j, stack (last n entries in xi)
  49. for (p = xi[n + head], p2 = jnew < 0 ? 0 : csUnflip(ptr[jnew + 1]); p < p2; p++) {
  50. // consider neighbor node i
  51. i = index[p];
  52. // check we have visited node i, skip it
  53. if (csMarked(ptr, i)) {
  54. continue;
  55. }
  56. // pause depth-first search of node j, update stack (last n entries in xi)
  57. xi[n + head] = p;
  58. // start dfs at node i
  59. xi[++head] = i;
  60. // node j is not done
  61. done = 0;
  62. // break, to start dfs(i)
  63. break;
  64. }
  65. // check depth-first search at node j is done
  66. if (done) {
  67. // remove j from the recursion stack
  68. head--;
  69. // and place in the output stack
  70. xi[--top] = j;
  71. }
  72. }
  73. return top;
  74. }