icentral_workspace/
icentral_workspace.rs

1crate::ix!();
2
3/**
4  | Stores the information used in one iteration
5  | of iCentral
6  | 
7  | Namely, \sigma \parents \delta \D \S both before
8  | edge insertion and after edge insertion
9  | 
10  | TODO study the effectiveness of storing
11  | old/new
12  | 
13  | TODO reconsider what to store and what
14  | not to (after the iCentral is implemented)
15  | 
16  | TODO reconsider the names of the structures
17  |
18  */
19#[derive(Clone)]
20pub struct ICentralWorkspace {
21    parents:            ParentsMap,
22    distances:          DistanceMap,
23    deltas:             DeltaMap,
24    new_deltas:         DeltaMap,
25    capital_deltas:     DeltaMap,
26    new_capital_deltas: DeltaMap,
27    sigmas:             SigmaMap,
28    new_sigmas:         SigmaMap,
29    inc_sigmas:         SigmaMap,
30    visit_markers:      VisitMarkers,
31    stack:              NodeIdStack,
32}
33
34impl Default for ICentralWorkspace {
35
36    fn default() -> Self {
37        Self::empty("default_icentral_workspace")
38    }
39}
40
41delegate_to_parents![ICentralWorkspace];
42delegate_to_visit_markers![ICentralWorkspace];
43delegate_to_bfs_stack![ICentralWorkspace];
44
45delegate_to_distances![ICentralWorkspace];
46
47delegate_to_sigmas![ICentralWorkspace];
48delegate_to_sigmas![ICentralWorkspace; new_sigmas];
49delegate_to_sigmas![ICentralWorkspace; inc_sigmas];
50
51delegate_to_deltas![ICentralWorkspace];
52delegate_to_deltas![ICentralWorkspace; new_deltas];
53delegate_to_deltas![ICentralWorkspace; capital_deltas];
54delegate_to_deltas![ICentralWorkspace; new_capital_deltas];
55
56impl ICentralWorkspace {
57
58    pub fn new_sigmas(&self) -> &SigmaMap {
59        &self.new_sigmas
60    }
61
62    pub fn sigmas(&self) -> &SigmaMap {
63        &self.sigmas
64    }
65
66    pub fn set_new_sigmas_from(&mut self, other: &SigmaMap) {
67        self.new_sigmas = other.clone();
68    }
69
70    /// fix order of workspace.stack
71    ///
72    /// IMP::THIS CAN BE MADE much BETTER!
73    ///
74    /// HEAP FOR EXAMPLE
75    ///
76    /// EVEN THE SWAPPING CAN BE DONE MORE EFFICIENTLY
77    ///
78    /// for now it's not a bottleneck
79    ///
80    pub fn fix_order_of_workspace_stack(&mut self) 
81    {
82        for i in 1..self.stack.len() {
83
84            let im1 = self.stack_node_at_index(i - 1);
85            let i0  = self.stack_node_at_index(i);
86
87            if self.distance(im1) > self.distance(i0) {
88
89                let mut j: usize = i;
90
91                let jm1 = self.stack_node_at_index(j - 1);
92                let j0  = self.stack_node_at_index(j);
93
94                while self.distance(jm1) > self.distance(j0) {
95
96                    let tmp: NodeId = self.stack_node_at_index(j - 1);
97
98                    self.stack_set_node_at_index(
99                        j - 1, 
100                        self.stack_node_at_index(j)
101                    );
102
103                    self.stack_set_node_at_index(j, tmp);
104
105                    j -= 1;
106                }
107            }
108        }
109    }
110
111    pub fn compute_new_path_counts_and_paths(
112        &mut self, 
113        src: NodeId, 
114        dst: NodeId)
115    {
116        if !self.distance_is_one_step_away(dst,src) {
117
118            self.clear_node_parents(dst);
119
120            self.add_parent(dst,src);
121
122            self.set_sigma_value_for_node(
123                dst,
124                self.sigma_value_for_node(src)
125            );
126
127        } else {
128
129            self.add_parent(dst,src);
130
131            self.increment_sigma_value_for_node(
132                dst, 
133                self.sigma_value_for_node(src)
134            );
135        }
136    }
137
138    pub fn update_for_partial_bbfs_addition(&mut self, 
139        queue: &mut NodeIdQueue, 
140        w:     NodeId, 
141        v:     NodeId) 
142    {
143        if self.distance_is_farther_than_one_away(w,v) {
144
145            self.set_distance_one_step_away(w,v);
146
147            self.clear_node_parents(w);
148
149            self.add_parent(w,v);
150
151            self.sigma_set_node_to_zero(w);
152
153            self.inc_sigmas_set_sigma_value_for_node(
154                w, 
155                self.inc_sigmas_sigma_value_for_node(v)
156            );
157
158            self.increment_sigma_value_for_node(
159                w, 
160                self.inc_sigmas_sigma_value_for_node(w)
161            );
162
163            if self.unvisited(w) {
164
165                self.visit(w);
166
167                queue.enqueue(w);
168            }
169
170        } else {
171
172            if self.distance_is_one_step_away(w,v) {
173
174                self.inc_sigmas_set_sigma_value_for_node(
175                    w, 
176                    self.inc_sigmas_sigma_value_for_node(v)
177                );
178
179                self.increment_sigma_value_for_node(
180                    w, 
181                    self.inc_sigmas_sigma_value_for_node(v)
182                );
183
184                if !self.has_parent(w,v) {
185                    self.add_parent(w,v);
186                }
187
188                if self.unvisited(w) {
189                    self.visit(w);
190                    queue.enqueue(w);
191                }
192            }
193        }
194    }
195
196    pub fn deltas(&self) -> &DeltaMap {
197        &self.deltas
198    }
199
200    pub fn get_new_delta_ratio(&self, 
201        v_p: NodeId, 
202        v_n: NodeId) -> f64 
203    {
204        self.new_deltas_delta_ratio(v_p, v_n)
205    }
206
207    pub fn set_deltas_from_new_deltas(&mut self) {
208        self.deltas = self.new_deltas.clone();
209    }
210
211    pub fn set_sigmas_from_other(&mut self, new: &SigmaMap) {
212        self.sigmas = new.clone();
213    }
214
215    pub fn get_sigma_ratio(&self, 
216        v_p: NodeId, 
217        v_n: NodeId) -> f64 
218    {
219        self.sigma_ratio(v_p, v_n)
220    }
221
222    pub fn get_new_sigma_ratio(&self, 
223        v_p: NodeId, 
224        v_n: NodeId) -> f64 
225    {
226        self.new_sigmas_sigma_ratio(v_p, v_n)
227    }
228
229    pub fn update_new_capital_deltas_with_new_delta_ratio(
230        &mut self, 
231        v_p: NodeId, 
232        v_n: NodeId) 
233    {
234        let new_sp_sn = self.get_new_delta_ratio(v_p,v_n);
235
236        let t0 = self.new_capital_deltas_delta_value_for_node(v_p);
237        let t1 = self.new_capital_deltas_delta_value_for_node(v_n);
238
239        self.new_capital_deltas_set_delta_value_for_node(
240            v_p, 
241            t0 + t1 * new_sp_sn
242        );
243    }
244
245    pub fn update_new_capital_deltas_with_new_sigma_ratio(
246        &mut self, 
247        v_p: NodeId,
248        v_n: NodeId) 
249    {
250        let sp_sn = self.get_new_sigma_ratio(v_p,v_n);
251
252        let ndp   = self.new_capital_deltas_delta_value_for_node(v_p);
253        let ndn   = self.new_capital_deltas_delta_value_for_node(v_n);
254
255        self.new_capital_deltas_set_delta_value_for_node(
256            v_p, 
257            ndp + ndn * sp_sn
258        );
259    }
260
261    pub fn update_new_deltas_with_new_delta_ratio(
262        &mut self, 
263        v_p: NodeId, 
264        v_n: NodeId) 
265    {
266        let new_sp_sn = self.get_new_delta_ratio(v_p,v_n);
267
268        let ndp = self.new_deltas_delta_value_for_node(v_p);
269        let ndn = self.new_deltas_delta_value_for_node(v_n);
270        let one_p_ndn = 1.0 + ndn;
271
272        self.new_deltas_set_delta_value_for_node(
273            v_p, 
274            ndp + new_sp_sn * one_p_ndn
275        );
276    }
277
278    pub fn update_new_deltas_with_new_sigma_ratio(
279        &mut self, 
280        v_p: NodeId, 
281        v_n: NodeId) 
282    {
283        let sp_sn     = self.get_new_sigma_ratio(v_p, v_n);
284        let ndp       = self.new_deltas_delta_value_for_node(v_p);
285        let ndn       = self.new_deltas_delta_value_for_node(v_n);
286        let one_p_ndn = 1.0 + ndn;
287
288        self.new_deltas_set_delta_value_for_node(
289            v_p, 
290            ndp + sp_sn * one_p_ndn
291        );
292    }
293
294    pub fn maybe_update_capital_deltas(&mut self, 
295        component: &Component, 
296        source:    NodeId, 
297        v_p:       NodeId, 
298        v_n:       NodeId) 
299    {
300        if component.has_articulation_point(source) {
301
302            self.update_capital_deltas(v_p,v_n);
303        }
304    }
305
306    pub fn maybe_update_new_capital_deltas(&mut self, 
307        component:  &Component, 
308        source:     NodeId,
309        v_p:        NodeId,
310        v_n:        NodeId) 
311    {
312        if component.has_articulation_point(source) {
313
314            ///TODO: is this sigma or delta ratio?
315            self.update_new_capital_deltas_with_new_sigma_ratio(v_p,v_n);
316        }
317    }
318
319    pub fn update_capital_deltas(&mut self, v_p: NodeId, v_n: NodeId) {
320
321        let sp_sn = self.get_sigma_ratio(v_p,v_n);
322
323        let dp = self.capital_deltas_delta_value_for_node(v_p);
324        let dn = self.capital_deltas_delta_value_for_node(v_n);
325
326        let dn_by_sp_sn = dn * sp_sn;
327
328        self.capital_deltas_set_delta_value_for_node(
329            v_p, 
330            dp + dn_by_sp_sn
331        );
332    }
333
334    pub fn update_deltas_for_each_p(
335        &mut self, 
336        component: &Component, 
337        source:    NodeId, 
338        v_n:       NodeId)
339    {
340        for &v_p in self.parents_for_node(v_n).iter() {
341
342            self.update_all_deltas_for_component(
343                component,
344                source,
345                v_p,
346                v_n
347            );
348        }
349    }
350
351    pub fn update_all_deltas_for_component(
352        &mut self, 
353        component: &Component, 
354        source:    NodeId, 
355        v_p:       NodeId, 
356        v_n:       NodeId)
357    {
358        self.update_deltas(v_p,v_n);
359
360        self.maybe_update_capital_deltas(component,source,v_p,v_n);
361
362        self.update_new_deltas_with_new_sigma_ratio(v_p,v_n);
363
364        self.maybe_update_new_capital_deltas(component, source, v_p, v_n);
365    }
366
367    pub fn update_deltas(&mut self, v_p: NodeId, v_n: NodeId) {
368
369        let sp_sn    = self.get_sigma_ratio(v_p,v_n);
370        let dn       = self.delta_value_for_node(v_n);
371        let dp       = self.delta_value_for_node(v_p);
372        let one_p_dn = 1.0 + dn;
373
374        self.set_delta_value_for_node(
375            v_p, 
376            dp + sp_sn * one_p_dn
377        );
378    }
379
380    pub fn maybe_update_capital_deltas_for_component(
381        &mut self, 
382        component: &Component, 
383        source:    NodeId, 
384        v_n:       NodeId) 
385    {
386        if component.has_both_articulation_points(source, v_n)
387        {
388            self.update_both_capital_deltas_for_component(
389                component,
390                source,
391                v_n
392            );
393        }
394    }
395
396    pub fn update_both_capital_deltas_for_component(
397        &mut self, 
398        component: &Component, 
399        source:    NodeId, 
400        v_n:       NodeId) 
401    {
402        let c_t = component
403            .subgraphs_product_through_articulation_points(
404                source,
405                v_n
406            );
407
408        self.capital_deltas_increment_delta_value_for_node(
409            v_n, 
410            c_t
411        );
412
413        self.new_capital_deltas_increment_delta_value_for_node(
414            v_n, 
415            c_t
416        );
417    }
418
419    pub fn process_outer_layer_neighbor(&mut self,
420        bc_mem:    &mut BcMemWorkspace,
421        neighbor:  NodeId,
422        queue:     &mut NodeIdQueue,
423        v:         NodeId) 
424    -> Result<(), BetweennessCentralityError>  
425    {
426        self.set_distance_one_step_away(neighbor,v);
427
428        // lost_parents[neighbor] = parents[neighbor];
429        bc_mem.new_parents_add_parent(neighbor, v);
430
431        let parents = self.parents_for_node(neighbor);
432
433        for &parent in parents.iter() {
434
435            self.attenuate_deltas(
436                parent,
437                neighbor
438            );
439        }
440
441        self.clear_node_parents(neighbor);
442
443        // parents[neighbor].push_back(v);
444        bc_mem.new_sigmas_sigma_set_node_to_zero(neighbor);
445
446        self.inc_sigmas_set_sigma_value_for_node(
447            neighbor, 
448            self.inc_sigmas_sigma_value_for_node(v)
449        );
450
451        bc_mem.new_sigmas_increment_sigma_value_for_node(
452            neighbor, 
453            self.inc_sigmas_sigma_value_for_node(neighbor)
454        );
455
456        if self.unvisited(neighbor) {
457
458            self.visit(neighbor);
459
460            // if(new_sigmas_sigma_value_for_node(&neighbor) != self.sigma_value_for_node(&neighbor))
461            queue.enqueue(neighbor);
462        }
463
464        Ok(())
465    }
466
467    pub fn process_first_layer_neighbor(&mut self,
468        bc_mem:    &mut BcMemWorkspace,
469        neighbor:  NodeId,
470        queue:     &mut NodeIdQueue,
471        v:         NodeId) 
472    -> Result<(), BetweennessCentralityError>  
473    {
474        self.inc_sigmas_increment_sigma_value_for_node(
475            neighbor, 
476            self.inc_sigmas_sigma_value_for_node(v)
477        );
478
479        bc_mem.new_sigmas_increment_sigma_value_for_node(
480            neighbor, 
481            self.inc_sigmas_sigma_value_for_node(v)
482        );
483
484        if !self.has_parent(neighbor, v) {
485
486            bc_mem.new_parents_add_parent(neighbor, v);
487        }
488
489        if self.unvisited(neighbor) {
490
491            self.visit(neighbor);
492
493            // if(new_sigmas_sigma_value_for_node(&neighbor) != sigma_value_for_node(&neighbor))
494            queue.enqueue(neighbor);
495        }
496
497        Ok(())
498    }
499
500    pub fn attenuate_deltas(&mut self, src: NodeId, dst: NodeId)
501    {
502        let sigma_ratio = self.sigma_ratio(src, dst);
503
504        let t1 = 1.0 + self.delta_value_for_node(dst);
505
506        let attenuation = sigma_ratio * t1;
507
508        self.attenuate_delta_value_for_node(
509            src, 
510            attenuation
511        );
512    }
513
514    pub fn calculate_deltas_step_with_sigma_ratio(
515        &self, 
516        sigma_ratio: f64,
517        w:           NodeId) -> f64 
518    {
519        let one_p_delta_w = 1.0 + self.delta_value_for_node(w);
520
521        let step = sigma_ratio * one_p_delta_w;
522
523        step
524    }
525
526    pub fn calculate_deltas_step(
527        &self, 
528        v: NodeId, 
529        w: NodeId) -> f64 
530    {
531        let sigma_ratio = self.sigma_ratio(v,w);
532
533        self.calculate_deltas_step_with_sigma_ratio(
534            sigma_ratio,
535            w
536        )
537    }
538
539    pub fn update_delta_bc_of_vertices_for_node(
540        &self,
541        w:                    NodeId,
542        delta_bc_of_vertices: &mut BetweennessScores)
543    {
544        delta_bc_of_vertices.decrease_score_for_node(
545            w, 
546            self.delta_value_for_node(w) / 2.0
547        );
548
549        delta_bc_of_vertices.increase_score_for_node(
550            w, 
551            self.new_deltas_delta_value_for_node(w) / 2.0
552        );
553    }
554
555    pub fn refill_deltass(&mut self, len: usize) {
556        self.deltas.reinit(len);
557        self.capital_deltas.reinit(len);
558        self.new_capital_deltas.reinit(len);
559        self.new_deltas.reinit(len);
560    }
561}
562
563impl fmt::Debug for ICentralWorkspace {
564
565    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
566        fmt.debug_struct("ICentralWorkspace")
567            .field("capital_deltas",      &self.capital_deltas)
568            .field("capital_deltas_len",  &self.capital_deltas.len())
569            .field("deltas",              &self.deltas)
570            .field("deltas_len",          &self.deltas.len())
571            .field("distances",           &self.distances)
572            .field("distances_len",       &self.distances.len())
573            .field("new_capital_deltas",  &self.new_capital_deltas)
574            .field("new_deltas",          &self.new_deltas)
575            .field("new_sigmas",          &self.new_sigmas)
576            .field("new_sigmas_len",      &self.new_sigmas.len())
577            .field("parents",             &self.parents)
578            .field("parents_len",         &self.parents.len())
579            .field("inc_sigmas",          &self.inc_sigmas)
580            .field("sigmas_len",          &self.sigmas.len())
581            .field("stack",               &self.stack)
582            .field("visit_markers",       &self.visit_markers)
583            .finish_non_exhaustive()
584    }
585}
586
587impl CreateNamedEmpty for ICentralWorkspace {
588
589    /// TODO: try to eliminate this if possible
590    fn empty(name: &str) -> Self  {
591
592        let parents_name            = name![name, "parents"];
593        let distances_name          = name![name, "distances"];
594        let deltas_name             = name![name, "deltas"];
595        let new_deltas_name         = name![name, "new_deltas"];
596        let capital_deltas_name     = name![name, "capital_deltas"];
597        let new_capital_deltas_name = name![name, "new_capital_deltas"];
598        let sigmas_name             = name![name, "sigmas"];
599        let new_sigmas_name         = name![name, "new_sigmas"];
600        let inc_sigmas_name         = name![name, "inc_sigmas"];
601        let visit_markers_name      = name![name, "visit_markers"];
602        let stack_name              = name![name, "stack"];
603
604        Self {
605            parents:            ParentsMap::empty_mapped(parents_name),
606            distances:          DistanceMap::empty_mapped(distances_name),
607            deltas:             DeltaMap::empty_mapped(deltas_name),
608            new_deltas:         DeltaMap::empty_mapped(new_deltas_name),
609            capital_deltas:     DeltaMap::empty_mapped(capital_deltas_name),
610            new_capital_deltas: DeltaMap::empty_mapped(new_capital_deltas_name),
611            sigmas:             SigmaMap::empty_mapped(sigmas_name),
612            new_sigmas:         SigmaMap::empty_mapped(new_sigmas_name),
613            inc_sigmas:         SigmaMap::empty_mapped(inc_sigmas_name),
614            visit_markers:      VisitMarkers::empty_mapped(visit_markers_name),
615            stack:              NodeIdStack::empty(stack_name),
616        }
617    }
618}
619
620impl ICentralWorkspace {
621    
622    pub fn new_init_all(n: usize, name: &str) -> Self  {
623
624        let parents_name            = name![name, "parents"];
625        let distances_name          = name![name, "distances"];
626        let deltas_name             = name![name, "deltas"];
627        let new_deltas_name         = name![name, "new_deltas"];
628        let capital_deltas_name     = name![name, "capital_deltas"];
629        let new_capital_deltas_name = name![name, "new_capital_deltas"];
630        let sigmas_name             = name![name, "sigmas"];
631        let new_sigmas_name         = name![name, "new_sigmas"];
632        let inc_sigmas_name         = name![name, "inc_sigmas"];
633        let visit_markers_name      = name![name, "visit_markers"];
634        let stack_name              = name![name, "stack"];
635
636        Self {
637            parents:            ParentsMap::new(n,parents_name),
638            distances:          DistanceMap::new(n,distances_name),
639            deltas:             DeltaMap::new(n,deltas_name),
640            new_deltas:         DeltaMap::new(n,new_deltas_name),
641            capital_deltas:     DeltaMap::new(n,capital_deltas_name),
642            new_capital_deltas: DeltaMap::new(n,new_capital_deltas_name),
643            sigmas:             SigmaMap::new(n,sigmas_name),
644            new_sigmas:         SigmaMap::new(n,new_sigmas_name),
645            inc_sigmas:         SigmaMap::new(n,inc_sigmas_name),
646            visit_markers:      VisitMarkers::new(n,visit_markers_name),
647            stack:              NodeIdStack::empty(stack_name),
648        }
649    }
650
651    pub fn init_all(&mut self, n: usize) {
652        debug!("ICentralWorkspace init_all!, n={}", n);
653
654        self.parents.reinit(n);
655        self.sigmas.reinit(n);
656        self.distances.reinit(n);
657        self.inc_sigmas.reinit(n);
658        self.deltas.reinit(n);
659        self.capital_deltas.reinit(n);
660        self.visit_markers.reinit(n);
661
662        self.stack.clear();
663
664        debug!("workspace initialization *complete*");
665
666        //    fill_vec<int>(new_sigmas, N, 0);
667        //    fill_vec<double>(new_deltas, N, 0);
668        //    fill_vec<double>(new_capital_deltas, N, 0);
669            
670        //    fill_vec<vector<node_id_t> >(old_P, N, vector<node_id_t>());
671        //    fill_vec<int>(old_sigmas, N, 0);
672        //    fill_vec<int>(old_distances, N, -1);
673        //    fill_vec<double>(old_deltas, N, 0);
674        //    fill_vec<double>(old_capital_deltas, N, 0);
675    }
676
677    /**
678      | needed for d=1 only
679      |
680      */
681    pub fn init_new(&mut self, n: usize)  {
682        self.new_sigmas.reinit(n);
683        self.new_deltas.reinit(n);
684        self.new_capital_deltas.reinit(n);
685    }
686}