horokai_network/
create.rs

1//!
2//! Constructors for struct Network.
3//!
4
5use super::Network;
6
7use rand::prelude::*;
8
9impl Network {
10    /// Create square lattice.
11    pub fn make_square_lattice(length: u32) -> Network {
12        let n = length * length;
13        let mut edge_list = Vec::new();
14
15        for i in 0..n {
16            let first = i;
17            let second = (i / length) * length + (i + 1) % length;
18            let third = (i + length) % n;
19            edge_list.push((first, second));
20            edge_list.push((first, third));
21        }
22
23        Network { n, edge_list }
24    }
25
26    /// Create regular lattice
27    pub fn make_regular_lattice(dim: u32, length: u32) -> Network {
28        let n = length.pow(dim);
29        let mut edge_list = Vec::new();
30
31        // index = x_0 + x_1 L + x_2 L^2 + ... + x_(d-1) L^(d-1) for regular lattice
32        // Lattice point is expressed as (x_0, x_1, ... x_(d-1))
33        let mut x = vec![0u32; dim as usize];
34
35        for index in 0..n {
36            // Get x = [x_0, x_1, ... ,  x_(d-1)]
37            let mut buff = index;
38            for i in 0..dim {
39                x[(dim - 1 - i) as usize] = buff / length.pow(dim - 1 - i);
40                buff = index % length.pow(dim - 1 - i);
41            }
42
43            // Make edge_list : each index has 2d links
44            for i in 0..dim {
45                let first = index;
46                let mut second = 0;
47                for j in 0..dim {
48                    if i != j {
49                        second += x[j as usize] * length.pow(j);
50                    } else {
51                        second += ((x[j as usize] + 1) % length) * length.pow(j);
52                    }
53                }
54                edge_list.push((first, second));
55            }
56        }
57
58        Network { n, edge_list }
59    }
60
61    /// create regular random graph
62    pub fn make_regular_random_graph(n: u32, frac: f64, rng: &mut StdRng) -> Network {
63        let mut edge_list = Vec::<(u32, u32)>::new();
64
65        // First  : Create edge list of perfect graph
66        // Second : Choose frac * n_e links
67        let mut perfect_list = Vec::<(u32, u32)>::new();
68        for i in 0..(n - 1) {
69            for j in (i + 1)..n {
70                perfect_list.push((i, j));
71            }
72        }
73        let n_e = n * (n - 1) / 2;
74
75        let e = (frac * n_e as f64).round() as u32;
76
77        for i in 0..e {
78            let index = rng.gen::<u32>() % (n_e - i);
79            let choosed = perfect_list[(i + index) as usize];
80            edge_list.push(choosed);
81            perfect_list[(i + index) as usize] = perfect_list[i as usize];
82            perfect_list[i as usize] = choosed;
83        }
84
85        Network { n, edge_list }
86    }
87
88    /// Check of the self loop
89    /// Calculation time is O(L).
90    pub fn exist_self_loop(&self) -> bool {
91        let length = self.edge_list.len();
92        for i in 0..length {
93            if self.edge_list[i].0 == self.edge_list[i].1 {
94                return true;
95            }
96        }
97        false
98    }
99
100    /// Check of the multi loop
101    /// Caution : Calculation time is O(L^2), it can be vast time. Be careful.
102    pub fn exist_multi_loop(&self) -> bool {
103        let mut target = self.clone();
104        target.make_acsending_order();
105        let length = target.edge_list.len();
106
107        for i in 0..length {
108            let speciman = target.edge_list[i];
109            for j in (i + 1)..length {
110                let target = target.edge_list[j];
111                if target == speciman {
112                    return true;
113                }
114            }
115        }
116
117        false
118    }
119
120    /// Make edge (v1, v2) be v1 <= v2
121    /// This procedure is not elemental for edge_list, but sometimes useful.
122    fn make_acsending_order(&mut self) {
123        for i in 0..self.edge_list.len() {
124            if self.edge_list[i].0 > self.edge_list[i].1 {
125                let temp = self.edge_list[i].0;
126                self.edge_list[i].0 = self.edge_list[i].1;
127                self.edge_list[i].1 = temp;
128            }
129        }
130    }
131
132    pub fn show_network(&self) {
133        println!("n = {}", self.n);
134        for i in 0..self.edge_list.len() {
135            println!(
136                "edge_list[{}] = ({},{})",
137                i, self.edge_list[i].0, self.edge_list[i].1
138            );
139        }
140    }
141}
142
143#[test]
144fn test_self_multi() {
145    let target1 = Network::make_square_lattice(2);
146    let target2 = Network::make_square_lattice(3);
147
148    let n = 3;
149    let edge_list = vec![(0, 1), (1, 1), (1, 2)];
150    let target3 = Network { n, edge_list };
151
152    assert_eq!(target1.exist_multi_loop(), true);
153    assert_eq!(target2.exist_multi_loop(), false);
154    assert_eq!(target3.exist_multi_loop(), false);
155
156    assert_eq!(target1.exist_self_loop(), false);
157    assert_eq!(target2.exist_self_loop(), false);
158    assert_eq!(target3.exist_self_loop(), true);
159}
160
161/// Check of the RRG is difficult, so we do the self loop check and multi loop check.N
162#[test]
163fn test_make_regular_random_graph() {
164    let mut rng: StdRng = SeedableRng::seed_from_u64(100u64);
165    let n = 100u32;
166    let frac = 0.5;
167
168    let target = Network::make_regular_random_graph(n, frac, &mut rng);
169
170    assert_eq!(target.exist_multi_loop(), false);
171    assert_eq!(target.exist_self_loop(), false);
172    assert_eq!(target.get_n(), 100u32);
173    assert_eq!(target.get_edge_list().len(), 25 * 99);
174}