1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#[cfg(test)]
#[path = "../../../tests/unit/algorithms/gsom/state_test.rs"]
mod state_test;
use super::{Input, Network, Storage};
use crate::algorithms::gsom::Coordinate;
use std::fmt::{Display, Formatter, Result, Write};
use std::i32::{MAX, MIN};
use std::ops::Range;
pub struct NetworkState {
pub shape: (Range<i32>, Range<i32>, usize),
pub nodes: Vec<NodeState>,
}
pub struct NodeState {
pub coordinate: (i32, i32),
pub unified_distance: f64,
pub weights: Vec<f64>,
pub total_hits: usize,
pub last_hits: usize,
pub dump: String,
}
pub fn get_network_state<I: Input, S: Storage<Item = I>>(network: &Network<I, S>) -> NetworkState {
let ((x_min, x_max), (y_min, y_max)) = network.get_coordinates().fold(
((MAX, MIN), (MAX, MIN)),
|((x_min, x_max), (y_min, y_max)), Coordinate(x, y)| {
((x_min.min(x), x_max.max(x)), (y_min.min(y), y_max.max(y)))
},
);
let nodes = network
.get_nodes()
.map(|node| {
let node = node.read().unwrap();
let (sum, count) = node.topology.neighbours().fold((0., 0), |(sum, count), nn| {
let distance = node.storage.distance(node.weights.as_slice(), nn.read().unwrap().weights.as_slice());
(sum + distance, count + 1)
});
let mut dump = String::new();
write!(dump, "{}", node.storage).unwrap();
NodeState {
coordinate: (node.coordinate.0, node.coordinate.1),
unified_distance: if count > 0 { sum / count as f64 } else { 0. },
weights: node.weights.clone(),
total_hits: node.total_hits,
last_hits: node.last_hits.iter().filter(|hit| !node.is_old(**hit)).count(),
dump,
}
})
.collect::<Vec<_>>();
let dim = nodes.first().map_or(0, |node| node.weights.len());
NetworkState { shape: (x_min..x_max, y_min..y_max, dim), nodes }
}
impl Display for NetworkState {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let nodes = self.nodes.iter().fold(String::new(), |mut res, n| {
let (x, y) = n.coordinate;
let weights = n.weights.iter().map(|w| format!("{:.7}", w)).collect::<Vec<_>>().join(",");
write!(
&mut res,
"({},{},{:.7},{},{},[{}],{}),",
x, y, n.unified_distance, n.total_hits, n.last_hits, weights, n.dump
)
.unwrap();
res
});
write!(
f,
"({},{},{},{},{},[{}])",
self.shape.0.start, self.shape.0.end, self.shape.1.start, self.shape.1.end, self.shape.2, nodes
)
}
}