Skip to main content

icentral_scratch/
scratch.rs

1crate::ix!();
2
3pub trait FindEdgeBccWithScratch<GH> {
4
5    fn find_edge_bcc_with_scratch(&mut self, 
6        bcc:  &mut BiconnectedComponentsScratch<GH>,
7        edge: &Edge)
8    -> Result<(),BetweennessCentralityError>;
9
10    fn find_edge_bcc_with_scratch_step(&mut self, 
11        v:    NodeId,
12        bcc:  &mut BiconnectedComponentsScratch<GH>,
13        edge: &Edge)
14    -> Result<(),BetweennessCentralityError>;
15}
16
17pub struct BiconnectedComponentsScratch<GH> {
18    name:                   String,
19    articulation_point_map: ArticulationPointMap,
20    bcc_subgraph:           GH,
21    bcc_fast_subgraph:      SubGraph,
22}
23
24impl<GH> fmt::Debug for BiconnectedComponentsScratch<GH> 
25
26where GH: GetPrintNodes + SetPrintNodes + Debug {
27
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29
30        let old = self.bcc_subgraph.get_print_nodes();
31
32        self.bcc_subgraph.set_print_nodes(false);
33
34        let res = f.debug_struct("BiconnectedComponentsScratch")
35            .field("bcc_subgraph",&self.bcc_subgraph)
36            .field("articulation_point_map", &self.articulation_point_map)
37            .finish();
38
39        self.bcc_subgraph.set_print_nodes(old);
40
41        res
42    }
43}
44
45impl<GH> CreateNamedEmpty for BiconnectedComponentsScratch<GH> 
46
47where GH: CreateNamedEmpty {
48
49    fn empty(name: &str) -> Self {
50
51        let bcc_fast_subgraph_name      = name![name, "bcc_fast_subgraph"];
52        let bcc_subgraph_name           = name![name, "bcc_subgraph"];
53        let articulation_point_map_name = name![name, "articulation_point_map"];
54
55        Self {
56            name:                   name.to_owned(),
57            articulation_point_map: ArticulationPointMap::empty_mapped(articulation_point_map_name),
58            bcc_subgraph:           GH::empty(bcc_subgraph_name),
59            bcc_fast_subgraph:      SubGraph::empty(bcc_fast_subgraph_name),
60        }
61    }
62}
63
64impl<GH> BiconnectedComponentsScratch<GH> 
65
66where GH
67: DebugIterationStep 
68+ FindPruningCounts
69+ GetEdges
70+ GetNeighborsForNode
71+ GetNodeIdRange
72+ GetSigmaValueForNode
73+ HasEdge
74+ InitDebugIteration 
75+ InsertEdge 
76+ MappedNodes
77+ NumEdges
78+ NumNodes
79+ PairDependencyForNode
80+ ParentsForNode 
81+ RemoveEdge 
82{
83
84    delegate_to_subgraph!{bcc_fast_subgraph}
85
86    delegate_to_graphhash!{bcc_subgraph}
87
88    delegate_to_articulation_point_map!{}
89
90    pub fn bcc_fast_subgraph_reset_with_graphhash(&mut self) {
91        self.bcc_fast_subgraph.reset_with(&mut self.bcc_subgraph);
92    }
93
94    pub fn set_articulation_point_map(
95        &mut self, 
96        other: ArticulationPointMap) 
97    {
98        self.articulation_point_map = other;
99    }
100
101    pub fn bcc_subgraph(&self) -> &GH {
102        &self.bcc_subgraph
103    }
104
105    pub fn bcc_subgraph_mut(&mut self) -> &mut GH {
106        &mut self.bcc_subgraph
107    }
108    
109    // This compute_bc DOES NOT return correct bc
110    // values for articulation points
111    //
112    pub fn compute_bc(&mut self, 
113        mut scores: &mut BetweennessScores,
114        max_iter:   Option<usize>) 
115    -> Result<(),BetweennessCentralityError> 
116    {
117        // scores will have for each vertex in the
118        // muc it's betweenness centrality init bc
119        // of all nodes to zero
120        //
121        // XXX why fill this scores? Should have
122        // all vertices in the graph, here we
123        // increment/decrement
124        //
125        for node in self.bcc_subgraph_mapped_nodes() {
126            scores.set_score_for_node(node, 0.0);
127        }
128
129        // do BFS's from the nodes in the bcc
130        match max_iter {
131
132            Some(max_iter) => {
133
134
135                for node in self.bcc_fast_subgraph.limited_nodeid_range(Some(max_iter)) {
136
137                    self.bc_iter(node, scores);
138                }
139            }
140
141            None => {
142
143                for node in self.bcc_fast_subgraph.nodeid_range() {
144
145                    self.bc_iter(node, scores);
146                }
147
148                for (k,size_vec) in self.articulation_point_map.iter() {
149
150                    if size_vec.len() > 1 {
151
152                        let mut sub: usize = 0;
153
154                        for i in 0..size_vec.len() {
155                            sub += size_vec[i] * size_vec[i];
156                        }
157
158                        let vg_i: f64 = size_vec.iter().sum::<usize>() as f64;
159
160                        scores.set_score_for_node(
161                            *k, 
162                            scores.score_for_node(*k) + vg_i * vg_i - sub as f64
163                        );
164                    }
165                }
166
167                scores.halve();
168            }
169        }
170
171        Ok(())
172    }
173    
174    pub fn bc_iter(&mut self, 
175        s:          NodeId,
176        mut scores: &mut BetweennessScores) 
177    -> Result<(),BetweennessCentralityError> 
178    {
179        let mut stack: Stack<NodeId> = default!();
180
181        self.bcc_fast_subgraph.reinit_maps();
182
183        self.bcc_fast_subgraph.set_path_count_for_node(s,1);
184        self.bcc_fast_subgraph.set_distance_for_node(s,0.0);
185
186        self.bcc_fast_subgraph.enqueue(s);
187
188        while let Some(v_i) = self.bcc_fast_subgraph.dequeue() {
189
190            stack.push(v_i);
191
192            let neighbors = self.bcc_fast_subgraph.neighbors(v_i);
193
194            for &v_n in neighbors.iter() {
195
196                if self.bcc_fast_subgraph.distance_is_infinite(v_n) {
197
198                    self.bcc_fast_subgraph.enqueue(v_n);
199
200                    self.bcc_fast_subgraph.set_distance_one_step_away(v_n,v_i);
201                }
202
203                if self.bcc_fast_subgraph.distance_is_one_step_away(v_n, v_i) {
204
205                    self.bcc_fast_subgraph.increment_path_count_for_node_from(
206                        v_n, 
207                        v_i
208                    );
209
210                    self.bcc_fast_subgraph.parents_for_node(v_n).push(v_i);
211                }
212            }
213        }
214
215        while let Some(v_n) = stack.pop() {
216
217            if self.has_both_articulation_points(s, v_n) 
218            && s != v_n 
219            {
220                let c_t: f64 = self.subgraphs_product_through_articulation_points(s, v_n);
221
222                self.bcc_fast_subgraph.increment_sigma_value_for_node(v_n, c_t);
223
224                let new_v_n: NodeId = self.bcc_fast_subgraph.label_map_inout(v_n);
225
226                scores.set_score_for_node(
227                    new_v_n, 
228                    scores.score_for_node(new_v_n) + c_t
229                );
230            }
231
232            for i in 0..self.bcc_fast_subgraph.parents_for_node(v_n).len() {
233
234                let v_p: NodeId = self.bcc_fast_subgraph.parents_for_node(v_n)[i];
235
236                let sp_sn = self.bcc_fast_subgraph.path_count_ratio(v_p, v_n);
237
238                self.bcc_fast_subgraph.increment_pair_dependency_for_node(
239                    v_p,
240                    {
241                        let pdn = self.bcc_fast_subgraph.pair_dependency_for_node(v_n);
242                        sp_sn * (1.0 + pdn)
243                    }
244                );
245
246                if self.has_articulation_point(s) {
247
248                    self.bcc_fast_subgraph.set_sigma_value_for_node(
249                        v_p, 
250                        {
251                            let t0 = self.bcc_fast_subgraph.sigma_value_for_node(v_p);
252                            let t1 = self.bcc_fast_subgraph.sigma_value_for_node(v_n);
253                            t0 + t1 * sp_sn
254                        }
255                    );
256
257                    let new_v_p: NodeId = self.bcc_fast_subgraph.label_map_inout(v_p);
258
259                    scores.set_score_for_node(
260                        new_v_p, 
261                        scores.score_for_node(new_v_p) + self.bcc_fast_subgraph.sigma_value_for_node(v_n) * sp_sn
262                    );
263                }
264            }
265
266            if s != v_n {
267
268                let new_v_n: NodeId = self.bcc_fast_subgraph.label_map_inout(v_n);
269
270                scores.set_score_for_node(
271                    new_v_n, 
272                    scores.score_for_node(new_v_n) + self.bcc_fast_subgraph.pair_dependency_for_node(v_n)
273                );
274            }
275
276            if self.has_articulation_point(s) {
277
278                let vg_s: f64 = self.subgraph_micentraltude_through_articulation_point(s);
279
280                let new_v_n: NodeId = self.bcc_fast_subgraph.label_map_inout(v_n);
281
282                scores.set_score_for_node(
283                    new_v_n, 
284                    scores.score_for_node(new_v_n) + self.bcc_fast_subgraph.pair_dependency_for_node(v_n) * (vg_s as f64) * 2.0
285                );
286            }
287        }
288
289        Ok(())
290    }
291}