rlu/dfs.rs
1use crate::debug::debug;
2use crate::traits::{Int, Scalar};
3use crate::Matrix;
4
5// Depth-first-search workspace.
6pub struct DFS {
7 root_list: Vec<usize>,
8 // ptr_list: Vec<usize>,
9 ptr_list2: Vec<(usize, usize)>,
10 flag: Vec<bool>,
11}
12
13impl DFS {
14 pub fn new(n: usize) -> Self {
15 Self {
16 root_list: vec![0; n],
17 // ptr_list: vec![0; n],
18 ptr_list2: vec![(0, 0); n],
19 flag: vec![false; n],
20 }
21 }
22
23 pub fn ludfs<I: Int, S: Scalar>(
24 &mut self,
25 l_mat: &Matrix<I, S>,
26 b_rowidx: &[I],
27 rperm: &[Option<usize>],
28 ) -> &[usize] {
29 debug!("b = {:?}", b_rowidx);
30
31 // let csgraph = matrix_to_csc(l_mat);
32 // debug!("L =\n{}", csgraph.to_table());
33
34 let n = l_mat.len();
35 // let n = csgraph.cols();
36 // let indices = csgraph.rowidx();
37 // let indptr = csgraph.colptr();
38 // let n = l_mat.cols();
39 // let indices = l_mat.rowidx();
40 // let indptr = l_mat.colptr();
41
42 // println!("\nindices = {:?}", indices);
43 // println!("indptr = {:?}", indptr);
44
45 let mut i_rl_start = n;
46
47 for &e0 in b_rowidx {
48 // The depth-first search must mark the vertices it
49 // has reached, to avoid repeating parts of the search.
50 if self.flag[e0.to_index()] {
51 continue;
52 }
53
54 // self.dfs(e0, indices, indptr, &mut i_rl_start, rperm);
55 self.dfs(
56 e0.to_index(),
57 /*indices, indptr,*/ l_mat,
58 &mut i_rl_start,
59 rperm,
60 );
61 }
62
63 let found = &self.root_list[i_rl_start..];
64 debug!(
65 "found = {:?} {} {:?}",
66 found.to_vec(),
67 i_rl_start,
68 self.root_list
69 );
70
71 // debug!("flag = {:?}", self.flag);
72 found.iter().for_each(|i| self.flag[*i] = false);
73
74 found
75 }
76
77 // Based on `depth_first_directed` from SciPy v1.11.
78 // Modified to support repeated calls with different start nodes
79 // and the same permuted input matrix.
80 //
81 // Author: Jake Vanderplas -- <vanderplas@astro.washington.edu>
82 // License: BSD, (C) 2012
83 pub(crate) fn dfs<I: Int, S: Scalar>(
84 &mut self,
85 head_node: usize,
86 // indices: &[usize],
87 // indptr: &[usize],
88 l_mat: &Matrix<I, S>,
89 i_rl_start: &mut usize,
90 rperm: &[Option<usize>],
91 ) {
92 // let n = node_list.len();
93
94 // node_list[0] = head_node;
95 self.root_list[0] = head_node;
96 let mut i_root_opt: Option<usize> = Some(0);
97 // let mut i_nl_end = 1;
98 // flag[head_node] = true;
99
100 while let Some(mut i_root) = i_root_opt {
101 let pnode = self.root_list[i_root];
102 let pnode_p = rperm[pnode];
103
104 if !self.flag[pnode] {
105 self.flag[pnode] = true;
106 match pnode_p {
107 Some(pnode_p) => {
108 // self.ptr_list[i_root] = indptr[pnode_p];
109 self.ptr_list2[i_root] = (pnode_p, 0);
110 }
111 None => {
112 // self.ptr_list[i_root] = 0;
113 self.ptr_list2[i_root] = (0, 0);
114 }
115 }
116 }
117
118 let mut no_children = true;
119
120 // let indptr1 = self.ptr_list[i_root];
121 // let indptr2 = match pnode_p {
122 // Some(pnode_p) => indptr[pnode_p + 1],
123 // None => 0,
124 // };
125 // println!(
126 // "\nind[{}..{}] = {:?}",
127 // indptr1,
128 // indptr2,
129 // indices[indptr1..indptr2].to_vec()
130 // );
131
132 if pnode_p.is_some() {
133 let (lcolind, lrow_offset) = self.ptr_list2[i_root];
134 let lcol = &l_mat[lcolind];
135 // println!(
136 // "col = {} {} ({}) - {:?}",
137 // lcolind,
138 // lrow_offset,
139 // pnode_p.is_none(),
140 // lcol
141 // );
142
143 // debug!(
144 // "pnode = {}, pnode_p = {:?}, p1 = {}, p2 = {}",
145 // pnode, pnode_p, indptr1, indptr2
146 // );
147 let mut k = 0;
148 // for i in indptr1..indptr2 {
149 for j in lrow_offset..lcol.len() {
150 k += 1;
151 let (cnode, _) = &lcol[j];
152 // let cnode = indices[i];
153 // let cnode = l_mat[indptr1.0][j].0;
154 if self.flag[cnode.to_index()] {
155 continue;
156 } else {
157 // self.ptr_list[i_root] = i;
158 self.ptr_list2[i_root] = (lcolind, k - 1);
159
160 i_root += 1;
161 i_root_opt = Some(i_root);
162 self.root_list[i_root] = cnode.to_index();
163 // node_list[i_nl_end] = cnode;
164 // flag[cnode] = true;
165 // i_nl_end += 1;
166
167 // debug!("i_root = {}, cnode = {}", i_root, cnode);
168 no_children = false;
169 break;
170 }
171 }
172 }
173
174 if *i_rl_start == 0 {
175 break;
176 }
177
178 if no_children {
179 i_root_opt = if i_root > 0 { Some(i_root - 1) } else { None };
180
181 *i_rl_start -= 1;
182 self.root_list[*i_rl_start] = pnode;
183 // debug!("i_rl_start = {}, pnode = {}", *i_rl_start, pnode);
184 }
185 }
186 }
187}