icentral_muc/
muc.rs

1crate::ix!();
2
3pub trait NodeIdToMucId {
4
5    fn nodeid_to_mucid(&self, idx: NodeId) -> MinimumUnionCycleId;
6}
7
8#[derive(Debug)]
9pub struct ConnectionVertexDescriptor {
10    id:                 NodeId,
11    subgraph_micentraltude: usize,
12}
13
14/**
15  | not sure yet TODO
16  |
17  */
18pub struct MinimumUnionCycle<GH> {
19    
20    conn_vertex_map:     Arc<Mutex<ConnVertexMap>>,
21    subgraph_map:        SubGraphMap<GH>,
22    muc_subgraph:        GH,
23    id:                  MinimumUnionCycleId,
24
25    /**
26      | flag to tell if the muc was deleted or
27      | not
28      |
29      */
30    valid:               bool,
31
32
33    /**
34      | these are used to facilitate fast computation
35      | where iterations are done in a fast graph,
36      | not hash based one
37      |
38      */
39    muc_fast_subgraph:   SubGraph,
40
41    tmp_conn_vertex_map: ConnVertexMap,
42    tmp_subgraph_map:    SubGraphMap<GH>,
43    print_nodes:         AtomicBool,
44}
45
46impl<GH: SetPrintNodes + Debug> fmt::Debug for MinimumUnionCycle<GH> 
47where GH: ExtendWith<GH> 
48        + GetConnectedComponentSizes
49        + GetEdges 
50        + GetNeighborsForNode
51        + GetNodeIdRange
52        + HasMapForNode 
53        + InsertEdge 
54        + InsertNode 
55        + MappedNodes 
56        + NumEdges 
57        + NumNodes
58{
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60
61        let binding = f.debug_struct("MinimumUnionCycle");
62
63        let mut builder = binding;
64
65        if !self.valid {
66
67            builder.field("invalid_muc", &true);
68
69        } else {
70
71            builder.field("connection_vertices", &self.connection_vertices());
72            builder.field("bridges",             &self.bridges());
73
74            self.muc_subgraph.set_print_nodes(self.get_print_nodes());
75
76            builder.field("subgraph",            &self.muc_subgraph);
77        }
78
79        builder.finish()
80    }
81}
82    
83impl<GH> Default for MinimumUnionCycle<GH> {
84
85    fn default() -> Self {
86        Self {
87            valid: true,
88            ..Default::default()
89        }
90    }
91}
92
93impl<GH> Named for MinimumUnionCycle<GH> {
94
95    fn name(&self) -> Cow<'_,str> {
96        Cow::Owned(format!("muc_with_id{}", self.id))
97    }
98}
99
100impl<GH> GetPrintNodes for MinimumUnionCycle<GH> 
101where GH: GraphHashMucInterface
102{
103    fn get_print_nodes(&self) -> bool 
104    {
105        self.print_nodes.load(atomic::Ordering::SeqCst)
106    }
107}
108
109impl<GH> SetPrintNodes for MinimumUnionCycle<GH> 
110where GH: GraphHashMucInterface
111{
112    fn set_print_nodes(&self, val: bool) 
113    {
114        debug!("in muc with id={}, toggling print functionality for nodes, {}", self.id, val);
115
116        self.print_nodes.store(val, atomic::Ordering::SeqCst);
117    }
118}
119
120impl<GH> NumNodes for MinimumUnionCycle<GH> 
121where GH: GraphHashMucInterface
122{
123    delegate!{
124        to self.muc_subgraph {
125            fn num_nodes(&self) -> usize;
126        }
127    }
128}
129
130impl<GH> NumEdges for MinimumUnionCycle<GH> 
131where GH: GraphHashMucInterface
132{
133    delegate!{
134        to self.muc_subgraph {
135            fn num_edges(&self) -> usize;
136        }
137    }
138}
139
140impl<GH> InsertNode for MinimumUnionCycle<GH> 
141where GH: GraphHashMucInterface
142{
143    delegate!{
144        to self.muc_subgraph {
145            fn insert_node(&mut self, n: NodeId);
146        }
147    }
148}
149
150impl<GH> InsertEdge for MinimumUnionCycle<GH> 
151where GH: GraphHashMucInterface
152{
153    delegate!{
154        to self.muc_subgraph {
155            fn insert_edge(&mut self, edge: &Edge)
156                -> Result<(),BetweennessCentralityError>;
157        }
158    }
159}
160
161impl<GH> HasMapForNode for MinimumUnionCycle<GH> 
162where GH: GraphHashMucInterface
163{
164    delegate!{
165        to self.muc_subgraph {
166            fn has_map_for_node(&self, n: NodeId) -> bool;
167        }
168    }
169}
170
171impl<GH> GetEdges for MinimumUnionCycle<GH> 
172where GH: GraphHashMucInterface
173{
174    delegate!{
175        to self.muc_subgraph {
176            fn edges(&self) -> &Edges;
177        }
178    }
179}
180
181impl<GH> MappedNodes for MinimumUnionCycle<GH> 
182where GH: GraphHashMucInterface
183{
184    delegate!{
185        to self.muc_subgraph {
186            fn mapped_nodes(&self) -> Vec<NodeId>;
187        }
188    }
189}
190
191impl<GH> ExtendWith<MinimumUnionCycle<GH>> for MinimumUnionCycle<GH> 
192where GH: GetConnectedComponentSizes 
193        + ExtendWith<GH, Error=BetweennessCentralityError> 
194        + GetEdges 
195        + GetNeighborsForNode 
196        + GetNodeIdRange 
197        + HasMapForNode 
198        + InsertEdge 
199        + InsertNode
200        + MappedNodes 
201        + NumEdges 
202        + NumNodes
203{
204    type Error = BetweennessCentralityError;
205
206    /// muc1 = muc1 U muc2
207    ///
208    /// 1. copy the graph of muc2 into muc1
209    ///
210    /// 2. for each bridge edge, if the other end
211    ///    becomes in the graph, add the edge
212    ///
213    fn extend_with(&mut self, other: &MinimumUnionCycle<GH>)
214        -> Result<(),Self::Error>
215    {
216        debug!("extending muc with id={}, via muc with id={}", self.id, other.id);
217
218        debug!("copying graph of muc2 into muc1");
219
220        self.muc_subgraph.extend_with(
221            &other.muc_subgraph
222        )?;
223
224        debug!("for each bridge edge, if the other end becomes in the graph, add the edge");
225
226        let mut to_insert = vec![];
227
228        if let conn_vertex_map = other.conn_vertex_map.lock()? {
229
230            for (conn_vert,v) in conn_vertex_map.iter() {
231
232                for i in 0..v.len() {
233
234                    if self.muc_subgraph.has_map_for_node(v[i]) {
235
236                        to_insert.push((conn_vert,v[i]));
237                    }
238                }
239            }
240        }
241
242        for (src,dst) in to_insert.iter() {
243            self.muc_subgraph.insert_edge(&Edge::new(*src, *dst));
244        }
245
246        Ok(())
247    }
248}
249
250impl<GH> IsValid for MinimumUnionCycle<GH> 
251{
252    fn is_valid(&self) -> bool 
253    {
254        self.valid
255    }
256}
257    
258impl<GH> MinimumUnionCycle<GH> 
259where GH: GetConnectedComponentSizes 
260        + ExtendWith<GH> 
261        + GetEdges 
262        + GetNeighborsForNode 
263        + GetNodeIdRange 
264        + HasMapForNode 
265        + InsertEdge 
266        + InsertNode
267        + MappedNodes 
268        + NumEdges 
269        + NumNodes 
270{
271    pub fn vertex_map(&self) -> LockResult<MutexGuard<'_,ConnVertexMap>> {
272        self.conn_vertex_map.lock()
273    }
274
275    pub fn set_muc_subgraph(&mut self, gh: GH) 
276    {
277        debug!("in muc with id={}, setting muc_subgraph", self.id);
278
279        self.muc_subgraph = gh;
280    }
281
282    pub fn insert_subgraph(&mut self, idx: NodeId, g: Arc<GH>) 
283    {
284        debug!("in muc with id={}, inserting subgraph at index={}", self.id, idx);
285
286        self.subgraph_map.set_subgraph_map_for_node(idx,g);
287    }
288
289    pub fn clear_conn_vertex_map(&mut self) 
290    {
291        debug!("in muc with id={}, clearing conn_vertex_map", self.id);
292
293        self.conn_vertex_map.lock().unwrap().clear();
294    }
295
296    pub fn id(&self) -> MinimumUnionCycleId 
297    {
298        self.id
299    }
300
301    pub fn set_id(&mut self, new: usize) 
302    {
303        debug!("setting muc id -- old={}, new={}", self.id, new);
304
305        self.id = mucid![new];
306    }
307
308    pub fn clear_subgraph_map(&mut self) 
309    {
310        debug!("in muc with id={}, clearing subgraph_map", self.id);
311
312        self.subgraph_map.clear();
313    }
314
315    pub fn invalidate(&mut self) 
316    {
317        debug!("invalidating muc, id={}", self.id);
318
319        self.valid = false;
320    }
321
322    pub fn connection_vertices(&self)
323    -> Result<Vec<ConnectionVertexDescriptor>,BetweennessCentralityError> 
324    {
325        debug!("in muc with id={}, scanning conn_vertex_map for connection_vertices", self.id); 
326
327        let mut result = vec![];
328
329        if let conn_vertex_map = self.conn_vertex_map.lock()? {
330
331            for (id,ids) in conn_vertex_map.iter() {
332
333                result.push(ConnectionVertexDescriptor {
334                    id,
335                    subgraph_micentraltude: self.subgraph_map.subgraph_for_node(id).num_nodes(),
336                });
337            }
338        }
339
340        Ok(result)
341    }
342
343    pub fn bridges(&self) 
344    -> Result<Vec<Edge>,BetweennessCentralityError> 
345    {
346        debug!("in muc with id={}, scanning conn_vertex_map for bridges", self.id); 
347
348        let mut res = vec![];
349
350        if let conn_vertex_map = self.conn_vertex_map.lock()? {
351
352            for (id1,ids) in conn_vertex_map.iter() {
353
354                for id2 in ids.iter() {
355
356                    res.push(Edge::new(id1,*id2));
357                }
358            }
359        }
360
361        Ok(res)
362    }
363
364    /**
365      | make sure the node with @id exists in
366      | the muc! this function will blindly
367      | insert it
368      |
369      */
370    pub fn insert_conn_vertex(&mut self, 
371        id:  NodeId,
372        nbr: NodeId) 
373    -> Result<(),BetweennessCentralityError> 
374    {
375        warn!("make sure the node with id={} exists in the muc with id={}! this function will blindly insert it!", id, self.id);
376
377        if let mut conn_vertex_map = self.conn_vertex_map.lock()? {
378
379            if let Some(v) = conn_vertex_map.vertices_for_node_mut(id) {
380
381                v.push(nbr);
382
383            } else {
384
385                let mut vec: Vec<NodeId> = vec![];
386
387                vec.push(nbr);
388
389                conn_vertex_map.set_vertex_map_for_node(id,vec);
390            }
391        }
392
393        Ok(())
394    }
395
396    pub fn compute_bc_initialize(&mut self) 
397    {
398        debug!("muc with id={}, initializing betweenness centrality computation", self.id);
399
400        self.muc_fast_subgraph.reset_with(&self.muc_subgraph);
401
402        self.tmp_conn_vertex_map.clear();
403
404        self.tmp_subgraph_map.clear();
405    }
406    
407    pub fn compute_bc_initialize_tmp_conn_vertex_map(&mut self) 
408    -> Result<(),BetweennessCentralityError> 
409    {
410        if let conn_vertex_map = self.conn_vertex_map.lock()? {
411
412            for (k,v) in conn_vertex_map.iter() {
413
414                let new_v: NodeId = self.muc_fast_subgraph.label_map_outin(k);
415
416                self.tmp_conn_vertex_map.set_vertex_map_for_node(new_v,v.to_vec());
417            }
418        }
419
420        Ok(())
421    }
422
423    pub fn compute_bc_initialize_tmp_subgraph_map(&mut self) 
424    -> Result<(),BetweennessCentralityError> 
425    {
426        for (k,v) in self.subgraph_map.iter() {
427
428            let new_v: NodeId = self.muc_fast_subgraph.label_map_outin(k);
429
430            self.tmp_subgraph_map.set_subgraph_map_for_node(new_v,v.clone());
431        }
432
433        Ok(())
434    }
435
436    pub fn initialize_scores_for_muc_subgraph(&self, scores: &mut BetweennessScores) 
437    {
438        for node in self.muc_subgraph.mapped_nodes() {
439            scores.set_score_for_node(node, 0.0);
440        }
441    }
442
443    pub fn adjust_max_iter(&self, max_iter: Option<usize>) -> usize {
444
445        let max_iter = match max_iter {
446            Some(max_iter) => {
447                min(
448                    max_iter,
449                    self.muc_fast_subgraph.num_nodes()
450                )
451            }
452            None => self.muc_fast_subgraph.num_nodes(),
453        };
454
455        max_iter
456    }
457
458    pub fn initialize_bfs_for_node_in_the_muc(&mut self, source: NodeId)
459    {
460        self.muc_fast_subgraph.reinit_maps();
461
462        self.muc_fast_subgraph.increment_path_count_for_node(source,1);
463
464        self.muc_fast_subgraph.set_distance_for_node(source, 0.0);
465
466        self.muc_fast_subgraph.enqueue(source);
467    }
468
469    pub fn build_stack_for_bfs(&mut self) -> NodeIdStack {
470
471        let stack_name = name![self.name(), "build_stack_for_bfs::stack"];
472
473        let mut stack = NodeIdStack::empty(stack_name);
474
475        while let Some(v_i) = self.muc_fast_subgraph.dequeue() {
476
477            stack.push(v_i);
478
479            let nbrs = self.muc_fast_subgraph.neighbors(v_i);
480
481            for &v_n in nbrs.iter() {
482
483                if self.muc_fast_subgraph.distance(v_n) < 0.0 {
484
485                    self.muc_fast_subgraph.enqueue(v_n);
486
487                    self.muc_fast_subgraph.set_distance_one_step_away(
488                        v_n, 
489                        v_i,
490                    );
491                }
492
493                if self.muc_fast_subgraph.distance_is_one_step_away(v_n, v_i) {
494
495                    self.muc_fast_subgraph.increment_path_count_for_node(
496                        v_n,
497                        self.muc_fast_subgraph.path_count_for_node(v_i)
498                    );
499
500                    self.muc_fast_subgraph.parents_for_node(v_n).push(v_i);
501                }
502            }
503        }
504
505        stack
506    }
507
508    pub fn bfs_process_stack_item(
509        &mut self, 
510        v_n:    NodeId, 
511        source: NodeId, 
512        scores: &mut BetweennessScores)
513    {
514        if self.tmp_conn_vertex_map.has_mapping_for_node(source)
515        && self.tmp_conn_vertex_map.has_mapping_for_node(v_n)
516        && source != v_n 
517        {
518            let mut vg_s: usize = 0;
519            let mut vg_n: usize = 0;
520
521            vg_s = self.tmp_subgraph_map.subgraph_for_node(source).num_nodes();
522            vg_n = self.tmp_subgraph_map.subgraph_for_node(v_n).num_nodes();
523
524            let c_t: usize = vg_s * vg_n;
525
526            self.muc_fast_subgraph.increment_sigma_value_for_node(v_n, c_t as f64);
527
528            let new_v_n: NodeId = self.muc_fast_subgraph.label_map_inout(v_n);
529
530            scores.set_score_for_node(
531                new_v_n, 
532                scores.score_for_node(new_v_n) + c_t as f64
533            );
534        }
535
536        for i in 0..self.muc_fast_subgraph.parents_for_node(v_n).len() {
537
538            let v_p: NodeId = self.muc_fast_subgraph.parents_for_node(v_n)[i];
539
540            let sp_sn = self.muc_fast_subgraph.path_count_ratio(v_p, v_n);
541
542            self.muc_fast_subgraph.increment_pair_dependency_for_node(
543                v_p, 
544                sp_sn * (1.0 + self.muc_fast_subgraph.pair_dependency_for_node(v_n))
545            );
546
547            if self.tmp_conn_vertex_map.has_mapping_for_node(source) {
548
549                self.muc_fast_subgraph.increment_sigma_value_for_node(
550                    v_p, 
551                    self.muc_fast_subgraph.sigma_value_for_node(v_n) * sp_sn
552                );
553
554                let new_v_p: NodeId = self.muc_fast_subgraph.label_map_inout(v_p);
555
556                scores.set_score_for_node(
557                    new_v_p,
558                    scores.score_for_node(new_v_p) + self.muc_fast_subgraph.sigma_value_for_node(v_n) * sp_sn
559                );
560            }
561        }
562
563        if source != v_n {
564
565            let new_v_n: NodeId = self.muc_fast_subgraph.label_map_inout(v_n);
566
567            scores.set_score_for_node(
568                new_v_n, 
569                scores.score_for_node(new_v_n) + self.muc_fast_subgraph.pair_dependency_for_node(v_n)
570            );
571        }
572
573        if self.tmp_conn_vertex_map.has_mapping_for_node(source) {
574
575            let vg_s: f64 = self.tmp_subgraph_map.subgraph_for_node(source).num_nodes() as f64;
576
577            let new_v_n: NodeId = self.muc_fast_subgraph.label_map_inout(v_n);
578
579            scores.set_score_for_node(
580                new_v_n, 
581                scores.score_for_node(new_v_n) + self.muc_fast_subgraph.pair_dependency_for_node(v_n) * vg_s * 2.0
582            );
583        }
584    }
585
586    pub fn do_bfs_for_node_in_the_muc(
587        &mut self, 
588        source: NodeId, 
589        scores: &mut BetweennessScores)
590    {
591        self.initialize_bfs_for_node_in_the_muc(source);
592
593        let mut stack = self.build_stack_for_bfs();
594
595        while let Some(v_n) = stack.pop() {
596            self.bfs_process_stack_item(v_n, source, scores);
597        }
598    }
599
600    pub fn do_bf_searches_from_the_nodes_in_the_muc(
601        &mut self, 
602        max_iter: usize, 
603        scores:   &mut BetweennessScores)
604    {
605        for source in NodeIdRange::new(0,max_iter) {
606            self.do_bfs_for_node_in_the_muc(source,scores);
607        }
608    }
609
610    pub fn update_scores_after_bfs(&self, scores: &mut BetweennessScores) 
611        -> Result<(),BetweennessCentralityError> 
612    {
613        for (k,v) in self.tmp_subgraph_map.iter() {
614
615            let size_vec = v.conn_comp_sizes()?;
616
617            if size_vec.len() > 1 {
618
619                let mut sub: i32 = 0;
620
621                for i in 0..size_vec.len() {
622                    sub += size_vec[i] * size_vec[i];
623                }
624
625                let vg_i: f64 = v.num_nodes() as f64;
626
627                let new_node_id: NodeId = self.muc_fast_subgraph.label_map_inout(k);
628
629                scores.set_score_for_node(
630                    new_node_id, 
631                    scores.score_for_node(new_node_id) + vg_i * vg_i - (sub as f64)
632                );
633            }
634        }
635
636        scores.halve();
637
638        Ok(())
639    }
640
641    pub fn compute_bc(&mut self, 
642        scores:   &mut BetweennessScores,
643        max_iter: Option<usize>) 
644    -> Result<(),BetweennessCentralityError> 
645    {
646        debug!("computing betweenness centrality for muc with id={}", self.id);
647
648        // scores will have for each vertex in the
649        // muc it's betweenness centrality init bc
650        // of all nodes to zero
651        //
652        scores.clear();
653
654        if !self.valid {
655
656            warn!("tried to compute betweenness centrality on an invalid muc! may want to investigate this!");
657
658            return Ok(());
659        }
660
661        self.compute_bc_initialize();
662
663        self.compute_bc_initialize_tmp_conn_vertex_map()?;
664
665        self.compute_bc_initialize_tmp_subgraph_map()?;
666
667        self.initialize_scores_for_muc_subgraph(scores);
668
669        // do BFS's from the nodes in the muc
670
671        let max_iter = self.adjust_max_iter(max_iter);
672
673        self.do_bf_searches_from_the_nodes_in_the_muc(max_iter, scores);
674
675        self.update_scores_after_bfs(scores);
676
677        Ok(())
678    }
679
680    /* ------- Incremental algorithm on top of MinimumUnionCycle  ------- */
681    
682    //////////////////////////////////////////////////
683    //IMP:: FOR NOW THIS GUY DOESN'T USE fast_subgraph
684    //////////////////////////////////////////////////
685    //void muc_t::compute_bc_inc(tr1_map_t(double)& scores,
686    //                        node_id_t src,
687    //                        node_id_t dst)
688    //{
689    //    if(!valid)
690    //        return;
691    //
692    //    //scores will have for each vertex in the muc it's betweenness centrality
693    //    muc_subgraph.remove_edge(src, dst);
694    //    tr1_map_t(int) src_distances, dst_distances;
695    //    muc_subgraph.find_single_source_shortest_paths(src, src_distances);
696    //    muc_subgraph.find_single_source_shortest_paths(dst, dst_distances);
697    //    
698    //    //this must be commented in general.. if it's there it makes scores contain deltas
699    //    //bcc_subgraph.i_fill_map<double>(scores, 0);
700    //    
701    //    for(graph_hash_t::nodes_map_t::iterator
702    //                        it =  muc_subgraph.nodes_map.begin();
703    //                        it != muc_subgraph.nodes_map.end();
704    //                        ++it) {
705    //        node_id_t source = it->first;
706    //        if(src_distances[source] != dst_distances[source]) {
707    //            i_iteration(source, 
708    //                    src, 
709    //                    dst, 
710    //                    src_distances[source], 
711    //                    dst_distances[source], 
712    //                    scores);
713    //        }
714    //    }
715    //    muc_subgraph.insert_edge(src, dst);
716    //}
717    pub fn compute_bc_inc(&mut self, 
718        scores:   &mut BetweennessScores,
719        mut src:  NodeId,
720        mut dst:  NodeId,
721        max_iter: Option<usize>) 
722    -> Result<(),BetweennessCentralityError> 
723    {
724        if !self.valid {
725            return Ok(());
726        }
727
728        self.muc_fast_subgraph.reset_with(&self.muc_subgraph);
729
730        self.tmp_conn_vertex_map.clear();
731
732        self.tmp_subgraph_map.clear();
733
734        if let conn_vertex_map = self.conn_vertex_map.lock()? {
735
736            for (k,v) in conn_vertex_map.iter() {
737
738                let new_v: NodeId = self.muc_fast_subgraph.label_map_outin(k);
739
740                self.tmp_conn_vertex_map.set_vertex_map_for_node(new_v,v.clone());
741            }
742        }
743
744        for (k,v) in self.subgraph_map.iter() {
745
746            let new_v: NodeId = self.muc_fast_subgraph.label_map_outin(k);
747
748            self.tmp_subgraph_map.set_subgraph_map_for_node(new_v,v.clone());
749        }
750
751        src = self.muc_fast_subgraph.label_map_outin(src);
752        dst = self.muc_fast_subgraph.label_map_outin(dst);
753
754        // scores will have for each vertex in the
755        // muc it's betweenness centrality
756        //
757        self.muc_fast_subgraph.remove_edge_between_nodes(src, dst);
758
759        let src_distances = self.muc_fast_subgraph.find_single_source_shortest_paths(src)?;
760        let dst_distances = self.muc_fast_subgraph.find_single_source_shortest_paths(dst)?;
761
762        // this must be commented in general.. if
763        // it's there it makes scores contain
764        // deltas
765        //
766        // bcc_subgraph.i_fill_map<double>(scores, 0);
767
768        let max_iter = match max_iter {
769            Some(max_iter) => min(max_iter,self.muc_fast_subgraph.num_nodes()),
770            None           => self.muc_fast_subgraph.num_nodes(),
771        };
772
773        for source in NodeIdRange::new(0,max_iter) {
774
775            if src_distances.distance(source) != dst_distances.distance(source) {
776
777                self.iteration(
778                    source, 
779                    src, 
780                    dst, 
781                    src_distances.distance(source), 
782                    dst_distances.distance(source), 
783                    scores
784                );
785            }
786        }
787
788        self.muc_fast_subgraph.insert_edge_between_nodes(src, dst);
789
790        Ok(())
791    }
792    
793    pub fn iteration(&mut self, 
794        source:      NodeId,
795        mut src:    NodeId,
796        mut dst:    NodeId,
797        mut src_distance:  f64,
798        mut dst_distance:  f64,
799        scores: &mut BetweennessScores)  
800    {
801        make_sure_src_is_the_closer_to_source_node(
802            &mut src, 
803            &mut dst, 
804            &mut src_distance, 
805            &mut dst_distance
806        );
807
808        if dst_distance - src_distance == 1.0 {
809
810            // dbg_iteration(source, src, dst, src_distance, dst_distance, scores);
811            self.iteration_1(source, src, dst, src_distance, dst_distance, scores);;
812
813        } else {
814
815            // dbg_iteration(source, src, dst, src_distance, dst_distance, scores);
816            self.iteration_2(source, src, dst, src_distance, dst_distance, scores);;
817        }
818    }
819
820    pub fn iteration_1_process(&mut self, 
821        v_n:    NodeId,
822        source: NodeId,
823        src:    NodeId,
824        dst:    NodeId,
825        src_distance:  f64,
826        dst_distance:  f64,
827        scores: &mut BetweennessScores) 
828    -> Result<(),BetweennessCentralityError> 
829    {
830        self.muc_fast_subgraph.maybe_update_all_sigmas_and_do_new(
831            v_n,
832            source,
833            &self.tmp_subgraph_map,
834            &self.tmp_conn_vertex_map,
835        )?;
836
837        self.muc_fast_subgraph.muc_update(
838            v_n,
839            source,
840            &self.tmp_conn_vertex_map, 
841            scores
842        );
843
844        // IMP: this is the only change that
845        // happens to
846        // self.muc_fast_subgraph.parents,
847        // @src should be added as parent for
848        // dst
849        //
850        if v_n == dst {
851
852            let v_p: NodeId = src;
853
854            let new_sp_sn = self.muc_fast_subgraph.new_path_counts_path_count_ratio(
855                v_p, 
856                v_n
857            );
858
859            self.muc_fast_subgraph.new_pair_dependencies_increment_pair_dependency_for_node(
860                v_p,
861                new_sp_sn * (1.0 + self.muc_fast_subgraph.new_pair_dependencies_pair_dependency_for_node(v_n))
862            );
863
864            if self.tmp_conn_vertex_map.has_mapping_for_node(source) {
865
866                self.muc_fast_subgraph.new_sigmas_increment_sigma_value_for_node(
867                    v_p,
868                    self.muc_fast_subgraph.new_sigmas_sigma_value_for_node(v_n) * new_sp_sn
869                );
870
871                let new_v_p: NodeId = self.muc_fast_subgraph.label_map_inout(v_p);
872
873                scores.set_score_for_node(
874                    new_v_p, 
875                    scores.score_for_node(new_v_p) + self.muc_fast_subgraph.new_sigmas_sigma_value_for_node(v_n) * new_sp_sn / 2.0
876                );
877            }
878        }
879
880        if source != v_n {
881
882            let new_v_n: NodeId = self.muc_fast_subgraph.label_map_inout(v_n);
883
884            scores.set_score_for_node(
885                new_v_n, 
886                scores.score_for_node(new_v_n) - self.muc_fast_subgraph.pair_dependency_for_node(v_n) / 2.0
887            );
888
889            scores.set_score_for_node(
890                new_v_n, 
891                scores.score_for_node(new_v_n) + self.muc_fast_subgraph.new_pair_dependencies_pair_dependency_for_node(v_n) / 2.0
892            );
893        }
894
895        if self.tmp_conn_vertex_map.has_mapping_for_node(source) {
896
897            let vg_s: i32 = self.tmp_subgraph_map.subgraph_for_node(source).num_nodes().try_into()?;
898
899            let new_v_n: NodeId = self.muc_fast_subgraph.label_map_inout(v_n);
900
901            scores.set_score_for_node(
902                new_v_n, 
903                scores.score_for_node(new_v_n) - self.muc_fast_subgraph.pair_dependency_for_node(v_n) * vg_s as f64
904            );
905
906            scores.set_score_for_node(
907                new_v_n, 
908                scores.score_for_node(new_v_n) + self.muc_fast_subgraph.new_pair_dependencies_pair_dependency_for_node(v_n) * vg_s as f64
909            );
910        }
911
912        Ok(())
913    }
914    
915    // |src_distance-dst_distance| = 1 (the easy case) 
916    //
917    pub fn iteration_1(&mut self, 
918        source:      NodeId,
919        src:    NodeId,
920        dst:    NodeId,
921        src_distance:  f64,
922        dst_distance:  f64,
923        scores: &mut BetweennessScores) 
924    -> Result<(),BetweennessCentralityError> 
925    {
926        let mut stack: Stack<NodeId> = default!();
927
928        self.muc_fast_subgraph.init_iteration1(source);
929
930        self.muc_fast_subgraph.iteration1_fill_stack(
931            &mut stack, 
932            src, 
933            dst
934        )?;
935
936        while let Some(v_n) = stack.pop() {
937
938            self.iteration_1_process(
939                v_n,
940                source,
941                src,
942                dst,
943                src_distance,
944                dst_distance,
945                scores
946            )?;
947        }
948
949        Ok(())
950    }
951    
952    // |src_distance-dst_distance| >= 2 (the difficult case)
953    //
954    pub fn iteration_2(&mut self, 
955        source:   NodeId,
956        src:      NodeId,
957        dst:      NodeId,
958        src_distance:    f64,
959        dst_distance:    f64,
960        scores:   &mut BetweennessScores) 
961    -> Result<(),BetweennessCentralityError> 
962    {
963        self.muc_fast_subgraph.iteration_2(
964            &self.tmp_subgraph_map, 
965            &self.tmp_conn_vertex_map, 
966            source, 
967            src, 
968            dst, 
969            src_distance, 
970            dst_distance, 
971            scores
972        );
973
974        Ok(())
975    }
976}