icentral_subgraph/
subgraph.rs

1crate::ix!();
2
3/**
4  | all functions here assume the given
5  | node ids are proper ones from 0 to n-1
6  | so, the caller must use
7  |
8  */
9pub struct SubGraph {
10
11    pub(crate) name:                   String,
12    pub(crate) nodes_map:              NeighborsMap,
13    pub(crate) edges:                  Edges,
14
15    pub(crate) label_map:              LabelMap,
16
17    /**
18      | structures to be used by algorithms
19      | they are here so they are built once
20      |
21      */
22    pub(crate) parents:                ParentsMap,
23
24    pub(crate) path_counts:            PathCounts,
25    pub(crate) new_path_counts:        PathCounts,
26    pub(crate) inc_path_counts:        PathCounts,
27
28    pub(crate) distances:              DistanceMap,
29
30    pub(crate) pair_dependencies:      PairDependencies,
31    pub(crate) new_pair_dependencies:  PairDependencies,
32
33    pub(crate) sigmas:                 SigmaMap,
34    pub(crate) new_sigmas:             SigmaMap,
35
36    pub(crate) visit_markers:          VisitMarkers,
37    pub(crate) stack:                  NodeIdStack,
38    pub(crate) queue:                  NodeIdQueue,
39}
40
41delegate_to_bfs_stack![SubGraph];
42delegate_to_bfs_queue![SubGraph];
43delegate_to_parents![SubGraph];
44delegate_to_visit_markers![SubGraph];
45delegate_to_label_map![SubGraph];
46delegate_to_distances![SubGraph];
47
48delegate_to_sigmas![SubGraph];
49delegate_to_sigmas![SubGraph; new_sigmas];
50
51delegate_to_pair_dependencies![SubGraph];
52delegate_to_pair_dependencies![SubGraph; new_pair_dependencies];
53
54delegate_to_path_counts![SubGraph];
55delegate_to_path_counts![SubGraph; new_path_counts];
56delegate_to_path_counts![SubGraph; inc_path_counts];
57
58//-------------------------------------------[icentral/src/subgraph_t.cc]
59impl SubGraph {
60
61    delegate_to_neighbors_map!{}
62    delegate_to_edges!{}
63
64    pub fn iteration1_build_stack(
65        &mut self,
66        src:   NodeId,
67        dst:   NodeId,
68        stack: &mut Stack<NodeId>)
69    -> Result<(),BetweennessCentralityError>
70    {
71        while let Some(v_i) = self.queue.dequeue() {
72
73            stack.push(v_i);
74
75            if v_i == dst {
76
77                self.new_path_counts_increment_path_count_for_node(
78                    v_i,
79                    self.path_count_for_node(src)
80                );
81            }
82
83            let nbrs = self.nodes_map.neighbors(v_i);
84
85            for &v_n in nbrs.iter() {
86
87                if self.distances.is_infinite(v_n) {
88
89                    self.enqueue(v_n);
90
91                    self.distances.set_distance_for_node(
92                        v_n, 
93                        self.distance(v_i) + 1.0
94                    );
95                }
96
97                if self.distance(v_n) == self.distance(v_i) + 1.0 {
98
99                    self.increment_path_count_for_node_from(
100                        v_n, 
101                        v_i
102                    );
103
104                    self.new_path_counts_increment_path_count_for_node_from(
105                        v_n,
106                        v_i,
107                    );
108
109                    self.add_parent(v_n, v_i);
110                }
111            }
112        }
113
114        Ok(())
115    }
116
117    pub fn iteration2_build_stack(&mut self, 
118        s:     NodeId, 
119        stack: &mut Vec<NodeId>)
120    -> Result<(),BetweennessCentralityError> 
121    {
122        while let Some(v_i) = self.queue.dequeue() {
123
124            stack.push(v_i);
125
126            let neighbors = self.nodes_map.neighbors(v_i);
127
128            for &v_n in neighbors.iter() {
129
130                if self.distances.is_infinite(v_n) {
131
132                    self.enqueue(v_n);
133
134                    self.distances.set_distance_for_node(
135                        v_n, 
136                        self.distance(v_i) + 1.0
137                    );
138                }
139
140                if self.distance_is_one_step_away(v_n, v_i) {
141
142                    self.increment_path_count_for_node_from(
143                        v_n, 
144                        v_i
145                    );
146
147                    self.add_parent(v_n, v_i);
148                }
149            }
150        }
151
152        Ok(())
153    }
154
155    pub fn init_iteration1(&mut self, source: NodeId)
156    {
157        self.reinit_maps();
158
159        self.set_path_count_to_one(source);
160        self.new_path_counts.set_path_count_to_one(source);
161
162        self.distances.set_zero_distance(source);
163
164        self.enqueue(source);
165    }
166
167    pub fn iteration1_step1_process_nodes(
168        &mut self, 
169        v_i:   NodeId,
170        stack: &mut Stack<NodeId>, 
171        src:   NodeId, 
172        dst:   NodeId)
173    {
174        let neighbors = self.nodes_map.neighbors(v_i);
175
176        for &node in neighbors.iter() {
177
178            if self.distances.is_infinite(node) {
179
180                self.enqueue(node);
181
182                self.distances.set_distance_for_node(
183                    node,
184                    self.distance(v_i) + 1.0
185                );
186            }
187
188            if self.distances.is_one_step_away(node,v_i) {
189
190                self.increment_path_count_for_node_from(
191                    node, 
192                    v_i
193                );
194
195                self.new_path_counts_increment_path_count_for_node_from(
196                    node, 
197                    v_i
198                );
199
200                self.parents.add_parent(node,v_i);
201            }
202        }
203    }
204
205    pub fn iteration1_fill_stack(
206        &mut self, 
207        stack: &mut Stack<NodeId>, 
208        src:   NodeId, 
209        dst:   NodeId)
210    -> Result<(),BetweennessCentralityError> 
211    {
212        while let Some(v_i) = self.queue.dequeue() {
213
214            stack.push(v_i);
215
216            if v_i == dst {
217
218                let src_paths = self.path_count_for_node(src);
219
220                self.new_path_counts_increment_path_count_for_node(
221                    v_i, 
222                    src_paths
223                );
224            }
225
226            self.iteration1_step1_process_nodes(
227                v_i, 
228                stack, 
229                src, 
230                dst
231            );
232        }
233
234        Ok(())
235    }
236
237    pub fn init_iteration2(&mut self, source: NodeId)
238    {
239        self.reinit_maps();
240
241        self.set_path_count_to_one(source);
242
243        self.set_distance_zero(source);
244
245        self.enqueue(source);
246    }
247
248    pub fn adjust_stack(&self, stack: &mut Vec<NodeId>) {
249
250        // fix order of stack
251        // IMP::THIS CAN BE MADE much BETTER!
252        // HEAP FOR EXAMPLE
253        // EVEN THE SWAPPING CAN BE DONE MORE EFFICIENTLY
254        // for now it's not a bottleneck
255        for i in 1..stack.len() {
256
257            if self.distance_is_farther_away(stack[i - 1], stack[i]) {
258
259                let mut j: usize = i;
260
261                while self.distance_is_farther_away(stack[j - 1], stack[j]) {
262
263                    let tmp: NodeId = stack[j - 1];
264
265                    stack[j - 1] = stack[j];
266
267                    stack[j] = tmp;
268
269                    j -= 1;
270                }
271            }
272        }
273    }
274
275    pub fn resize_pair_dependencies_and_sigma_based_on_map_len(&mut self) {
276
277        let map_len = self.nodes_map.len();
278
279        self.pair_dependencies.reinit(map_len);
280        self.reinit_sigmas(map_len);
281    }
282
283    pub fn iteration2_update1(&mut self, stack: &mut Vec<NodeId>) 
284    -> Result<(),BetweennessCentralityError>
285    {
286        while let Some(v_i) = self.dequeue() {
287
288            stack.push(v_i);
289
290            let neighbors = self.nodes_map.neighbors(v_i);
291
292            for &node in neighbors.iter() {
293
294                if self.distance_is_infinite(node) {
295
296                    self.enqueue(node);
297
298                    self.set_distance_one_step_away(node,v_i);
299                }
300
301                if self.distance_is_one_step_away(node,v_i) {
302
303                    self.increment_path_count_for_node_from(node,v_i);
304
305                    self.add_parent(node,v_i);
306                }
307            }
308        }
309
310        Ok(())
311    }
312
313    pub fn iteration2_update2_process_neighbor(&mut self, v: NodeId, nbr: NodeId) 
314    {
315        if self.distance_is_farther_than_one_away(nbr, v) {
316
317            self.set_distance_one_step_away(nbr, v);
318
319            self.set_single_parent(nbr, v);
320
321            self.set_path_count_to_zero(nbr);
322
323            self.inc_path_counts_update_path_counts(nbr,v);
324
325            let nbr_inc_paths = self.inc_path_counts_path_count_for_node(nbr);
326
327            self.increment_path_count_for_node(
328                nbr, 
329                nbr_inc_paths 
330            );
331
332            self.bfs_maybe_visit(nbr);
333
334        } else if self.distance_is_one_step_away(nbr,v) {
335
336            self.inc_path_counts_increment_path_count_for_node_from(nbr,v);
337
338            self.increment_path_count_for_node(
339                nbr, 
340                self.inc_path_counts_path_count_for_node(v)
341            );
342
343            self.add_parent(nbr,v);
344
345            self.bfs_maybe_visit(nbr);
346        }
347    }
348
349    pub fn iteration2_update2(&mut self) 
350    -> Result<(),BetweennessCentralityError>
351    {
352        while let Some(v) = self.dequeue() {
353
354            let neighbors = self.neighbors(v);
355
356            for &nbr in neighbors.iter() {
357
358                self.iteration2_update2_process_neighbor(
359                    v, 
360                    nbr
361                );
362            }
363        }
364
365        Ok(())
366    }
367
368    pub fn bfs_maybe_visit(&mut self, node: NodeId) {
369
370        if self.unvisited(node) {
371
372            self.visit(node);
373
374            self.enqueue(node);
375        }
376    }
377
378    pub fn maybe_augment_bc_value_for_node(&self, 
379        source: NodeId, 
380        v_n:    NodeId, 
381        scores: &mut BetweennessScores)
382    {
383        if source != v_n {
384
385            let remapped: NodeId = self.label_map_inout(v_n);
386
387            let val = scores.score_for_node(remapped) + self.pair_dependency_for_node(v_n) / 2.0;
388
389            scores.set_score_for_node(
390                remapped, 
391                val
392            );
393        }
394    }
395
396    pub fn maybe_attenuate_bc_value_for_node(&self, 
397        source: NodeId, 
398        v_n:    NodeId, 
399        scores: &mut BetweennessScores)
400    {
401        if source != v_n {
402
403            let remapped: NodeId = self.label_map_inout(v_n);
404
405            let val = scores.score_for_node(remapped) - self.pair_dependency_for_node(v_n) / 2.0;
406
407            scores.set_score_for_node(
408                remapped, 
409                val
410            );
411        }
412    }
413
414    pub fn maybe_attenuate_bc_value_for_node_using_vertex_map<GH: NumNodes>(
415        &self, 
416        source:              NodeId, 
417        v_n:                 NodeId, 
418        scores:              &mut BetweennessScores,
419        tmp_subgraph_map:    &SubGraphMap<GH>,
420        tmp_conn_vertex_map: &ConnVertexMap)
421    {
422        if tmp_conn_vertex_map.has_mapping_for_node(source) {
423
424            let vg_s: f64 = tmp_subgraph_map.subgraph_for_node(source).num_nodes() as f64;
425
426            let new_v_n: NodeId = self.label_map_inout(v_n);
427
428            scores.set_score_for_node(
429                new_v_n, 
430                scores.score_for_node(new_v_n) - self.pair_dependency_for_node(v_n) * vg_s
431            );
432        }
433    }
434
435    pub fn maybe_augment_bc_value_for_node_using_vertex_map<GH: NumNodes>(
436        &self, 
437        source:              NodeId, 
438        v_n:                 NodeId, 
439        scores:              &mut BetweennessScores,
440        tmp_subgraph_map:    &SubGraphMap<GH>,
441        tmp_conn_vertex_map: &ConnVertexMap)
442    {
443        if tmp_conn_vertex_map.has_mapping_for_node(source) {
444
445            let vg_s: f64 = tmp_subgraph_map.subgraph_for_node(source).num_nodes() as f64;
446
447            let new_v_n: NodeId = self.label_map_inout(v_n);
448
449            let val = scores.score_for_node(new_v_n) + self.pair_dependency_for_node(v_n) * vg_s;
450
451            scores.set_score_for_node(
452                new_v_n, 
453                val
454            );
455        }
456    }
457
458    pub fn rbfs1_to_add_the_new_pair_dependencies_step<GH: NumNodes>(
459        &mut self,
460        v_n:                 NodeId,
461        source:              NodeId,
462        stack:               &Vec<NodeId>,
463        tmp_subgraph_map:    &SubGraphMap<GH>,
464        tmp_conn_vertex_map: &ConnVertexMap,
465        scores:              &mut BetweennessScores) 
466    {
467        self.maybe_update_all_sigmas(
468            v_n,
469            source,
470            tmp_subgraph_map,
471            tmp_conn_vertex_map
472        );
473
474        self.muc_attenuate_no_new(
475            v_n,
476            source,
477            tmp_conn_vertex_map, 
478            scores
479        );
480
481        self.maybe_attenuate_bc_value_for_node(
482            source,
483            v_n,
484            scores
485        );
486
487        self.maybe_attenuate_bc_value_for_node_using_vertex_map(
488            source,
489            v_n,
490            scores,
491            tmp_subgraph_map,
492            tmp_conn_vertex_map,
493        );
494    }
495
496    pub fn rbfs1_to_add_the_new_pair_dependencies<GH: NumNodes>(
497        &mut self,
498        source:              NodeId,
499        stack:               &Vec<NodeId>,
500        tmp_subgraph_map:    &SubGraphMap<GH>,
501        tmp_conn_vertex_map: &ConnVertexMap,
502        scores:              &mut BetweennessScores) 
503    -> Result<(),BetweennessCentralityError>
504    {
505        for i in (0..=stack.len() - 1).rev() {
506
507            // RBFS to subtract old pair dependency
508            let v_n: NodeId = stack[i];;
509
510            self.rbfs1_to_add_the_new_pair_dependencies_step(
511                v_n, 
512                source, 
513                stack, 
514                tmp_subgraph_map, 
515                tmp_conn_vertex_map, 
516                scores
517            );
518        }
519
520        Ok(())
521    }
522
523    pub fn rbfs2_to_add_the_new_pair_dependencies_step<GH: NumNodes>(
524        &mut self,
525        v_n:                 NodeId,
526        source:              NodeId,
527        stack:               &Vec<NodeId>,
528        tmp_subgraph_map:    &SubGraphMap<GH>,
529        tmp_conn_vertex_map: &ConnVertexMap,
530        scores:              &mut BetweennessScores) 
531    -> Result<(),BetweennessCentralityError>
532    {
533        self.maybe_update_all_sigmas(
534            v_n,
535            source,
536            tmp_subgraph_map,
537            tmp_conn_vertex_map
538        )?;
539
540        self.muc_augment_no_new(
541            v_n,
542            source,
543            tmp_conn_vertex_map, 
544            scores
545        );
546
547        self.maybe_augment_bc_value_for_node(
548            source,
549            v_n,
550            scores
551        );
552
553        self.maybe_augment_bc_value_for_node_using_vertex_map(
554            source,
555            v_n,
556            scores,
557            tmp_subgraph_map,
558            tmp_conn_vertex_map
559        );
560
561        Ok(())
562    }
563
564    pub fn rbfs2_to_add_the_new_pair_dependencies<GH: NumNodes>(
565        &mut self,
566        source:              NodeId,
567        stack:               &Vec<NodeId>,
568        tmp_subgraph_map:    &SubGraphMap<GH>,
569        tmp_conn_vertex_map: &ConnVertexMap,
570        scores:              &mut BetweennessScores) 
571    {
572        // RBFS to add the new pair dependencies
573        for i in (0..=stack.len() - 1).rev() {
574
575            let v_n: NodeId = stack[i];
576
577            self.rbfs2_to_add_the_new_pair_dependencies_step(
578                v_n, 
579                source, 
580                stack, 
581                tmp_subgraph_map, 
582                tmp_conn_vertex_map, 
583                scores
584            );
585        }
586    }
587
588    pub fn src_dist_is_greater_than_dst_plus_one(
589        &self, 
590        src: NodeId, 
591        dst: NodeId) -> bool
592    {
593        self.distance(src) > (self.distance(dst) + 1.0)
594    }
595
596    pub fn src_dist_equals_dst_plus_one(
597        &self, 
598        src: NodeId, 
599        dst: NodeId) -> bool
600    {
601        self.distance(src) == (self.distance(dst) + 1.0)
602    }
603    
604    // |src_distance-dst_distance| >= 2 (the difficult case)
605    //
606    pub fn iteration_2<GH: NumNodes>(
607        &mut self, 
608        tmp_subgraph_map:    &SubGraphMap<GH>,
609        tmp_conn_vertex_map: &ConnVertexMap,
610        source:              NodeId,
611        src:                 NodeId,
612        dst:                 NodeId,
613        src_distance:        f64,
614        dst_distance:        f64,
615        scores:              &mut BetweennessScores) 
616    -> Result<(),BetweennessCentralityError> 
617    {
618        let mut stack: Vec<NodeId> = default!();
619
620        self.init_iteration2(source);
621
622        self.iteration2_update1(&mut stack)?;
623
624        /*
625        * steps:
626        * 1. do the reverse BFS and subtract the olds
627        * 2. compute the new counts
628        * 3. fix the order of stack
629        * 4. add the new increments
630        */
631        self.rbfs1_to_add_the_new_pair_dependencies(
632            source,
633            &stack,
634            tmp_subgraph_map,
635            tmp_conn_vertex_map,
636            scores,
637        );
638
639        self.compute_new_path_counts_and_paths(src,dst);
640
641        self.iteration2_update2();
642
643        self.adjust_stack(&mut stack);
644
645        self.resize_pair_dependencies_and_sigma_based_on_map_len();
646
647        self.rbfs2_to_add_the_new_pair_dependencies(
648            source,
649            &stack,
650            tmp_subgraph_map,
651            tmp_conn_vertex_map,
652            scores,
653        );
654
655        Ok(())
656    }
657
658    pub fn iteration2_step3_when_src_dist_is_greater_than_dst_plus_one(
659        &mut self, 
660        w: NodeId, 
661        v: NodeId)
662    -> Result<(),BetweennessCentralityError>
663    {
664        self.distances.set_distance_for_node(
665            w, 
666            self.distance(v) + 1.0
667        );
668
669        self.set_single_parent(w,v);
670
671        self.set_path_count_for_node(w,0);
672
673        let v_inc_paths = self.inc_path_counts_path_count_for_node(v);
674
675        self.inc_path_counts_set_path_count_for_node(
676            w, 
677            v_inc_paths 
678        );
679
680        let w_inc_paths = self.inc_path_counts_path_count_for_node(w);
681
682        self.increment_path_count_for_node(
683            w, 
684            w_inc_paths 
685        );
686
687        self.bfs_maybe_visit(w);
688
689        Ok(())
690    }
691
692    pub fn iteration2_step3_when_src_dist_equals_dst_plus_one(
693        &mut self, 
694        w: NodeId, 
695        v: NodeId)
696    -> Result<(),BetweennessCentralityError>
697    {
698        self.inc_path_counts_increment_path_count_for_node(
699            w, 
700            self.inc_path_counts_path_count_for_node(v)
701        );
702
703        self.increment_path_count_for_node(
704            w, 
705            self.inc_path_counts_path_count_for_node(v)
706        );
707
708        if !self.has_parent(w,v) {
709
710            self.add_parent(w,v);
711        }
712
713        self.bfs_maybe_visit(w);
714
715        Ok(())
716    }
717
718    pub fn iteration2_step3_process_neighbor(&mut self, v: NodeId, nbr: NodeId)
719    -> Result<(),BetweennessCentralityError>
720    {
721        if self.src_dist_is_greater_than_dst_plus_one(nbr,v) {
722
723            self.iteration2_step3_when_src_dist_is_greater_than_dst_plus_one(nbr,v)?;
724
725        } else if self.src_dist_equals_dst_plus_one(nbr, v) {
726
727            self.iteration2_step3_when_src_dist_equals_dst_plus_one(nbr, v)?;
728        }
729
730        Ok(())
731    }
732
733    pub fn iteration2_step3_process(&mut self, v: NodeId)
734    {
735        let nbrs = self.neighbors(v);
736
737        for &nbr in nbrs.iter() {
738
739            self.iteration2_step3_process_neighbor(v,nbr);
740        }
741    }
742
743    pub fn iteration2_step3(&mut self)
744    {
745        while let Some(v) = self.queue.dequeue() {
746
747            self.iteration2_step3_process(v);
748        }
749    }
750}