1use serde::{Deserialize, Serialize};
16
17#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
24pub struct TrustVector(pub u8);
25
26impl TrustVector {
27 pub const COUNT: usize = 48;
28
29 pub fn all_directions() -> [(i16, i16, i16, i16); 48] {
31 [
32 (1, 1, 0, 1), (-1, 1, 0, 1), (0, 1, 1, 1), (0, 1, -1, 1),
34 (3, 5, 4, 5), (-3, 5, 4, 5), (3, 5, -4, 5), (-3, 5, -4, 5),
36 (4, 5, 3, 5), (-4, 5, 3, 5), (4, 5, -3, 5), (-4, 5, -3, 5),
37 (5, 13, 12, 13), (-5, 13, 12, 13), (5, 13, -12, 13), (-5, 13, -12, 13),
39 (12, 13, 5, 13), (-12, 13, 5, 13), (12, 13, -5, 13), (-12, 13, -5, 13),
40 (7, 25, 24, 25), (-7, 25, 24, 25), (7, 25, -24, 25), (-7, 25, -24, 25),
42 (24, 25, 7, 25), (-24, 25, 7, 25), (24, 25, -7, 25), (-24, 25, -7, 25),
43 (8, 17, 15, 17), (-8, 17, 15, 17), (8, 17, -15, 17), (-8, 17, -15, 17),
45 (15, 17, 8, 17), (-15, 17, 8, 17), (15, 17, -8, 17), (-15, 17, -8, 17),
46 (9, 41, 40, 41), (-9, 41, 40, 41), (9, 41, -40, 41), (-9, 41, -40, 41),
48 (40, 41, 9, 41), (-40, 41, 9, 41), (40, 41, -9, 41), (-40, 41, -9, 41),
49 (15, 17, -8, 17), (-15, 17, -8, 17), (15, 17, 8, 17), (-15, 17, 8, 17),
51 ]
52 }
53
54 pub fn to_f32(&self) -> (f32, f32) {
56 let (xn, xd, yn, yd) = Self::all_directions()[self.0 as usize];
57 (xn as f32 / xd as f32, yn as f32 / yd as f32)
58 }
59
60 pub fn from_f32(x: f32, y: f32) -> Self {
62 let mut best = 0;
63 let mut best_dist = f32::MAX;
64 for (i, (xn, xd, yn, yd)) in Self::all_directions().iter().enumerate() {
65 let dx = x - (*xn as f32 / *xd as f32);
66 let dy = y - (*yn as f32 / *yd as f32);
67 let dist = dx * dx + dy * dy;
68 if dist < best_dist {
69 best_dist = dist;
70 best = i;
71 }
72 }
73 TrustVector(best as u8)
74 }
75
76 pub fn bits(&self) -> f64 {
78 5.58496
79 }
80}
81
82#[derive(Clone)]
84pub struct TrustTopology {
85 }
87
88impl TrustTopology {
89 pub fn new() -> Self {
90 Self {}
91 }
92
93 pub fn encode(&self, x: f32, y: f32) -> TrustVector {
95 TrustVector::from_f32(x, y)
96 }
97
98 pub fn decode(&self, v: TrustVector) -> (f32, f32) {
100 v.to_f32()
101 }
102
103 pub fn encode_batch(&self, vectors: &[[f32; 2]]) -> Vec<TrustVector> {
105 vectors.iter().map(|v| self.encode(v[0], v[1])).collect()
106 }
107
108 pub const BITS_PER_VECTOR: f64 = 5.58496;
110
111 pub const MAX_NEIGHBORS: usize = 12;
113}
114
115impl Default for TrustTopology {
116 fn default() -> Self {
117 Self::new()
118 }
119}
120
121pub fn build_trust_topology(
126 _agents: &[u64],
127 neighbor_pairs: &[(usize, usize)],
128 positions: &[[f32; 2]],
129) -> Vec<TrustVector> {
130 let mut trust_vectors = Vec::new();
131 for &(i, j) in neighbor_pairs {
132 let (x, y) = (positions[j][0] - positions[i][0], positions[j][1] - positions[i][1]);
133 let mag = (x * x + y * y).sqrt();
134 let (nx, ny) = if mag > 1e-6 { (x / mag, y / mag) } else { (0.0, 1.0) };
135 trust_vectors.push(TrustVector::from_f32(nx, ny));
136 }
137 trust_vectors
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_no_drift() {
146 let original = (0.6_f32, 0.8_f32);
148 let encoded = TrustVector::from_f32(original.0, original.1);
149 let (dx, dy) = encoded.to_f32();
150 assert!((dx - original.0).abs() < 0.01);
151 assert!((dy - original.1).abs() < 0.01);
152 }
153
154 #[test]
155 fn test_all_48_directions_on_circle() {
156 for i in 0..48 {
157 let v = TrustVector(i as u8);
158 let (x, y) = v.to_f32();
159 let mag = (x * x + y * y).sqrt();
160 assert!((mag - 1.0).abs() < 0.001, "direction {i} not on unit circle");
161 }
162 }
163
164 #[test]
165 fn test_bits_per_vector() {
166 assert!((TrustTopology::BITS_PER_VECTOR - 5.58496).abs() < 0.0001);
167 }
168
169 #[test]
170 fn test_trust_topology_encode_decode() {
171 let topology = TrustTopology::new();
172 let v = topology.encode(0.6, 0.8);
173 let (x, y) = topology.decode(v);
174 assert!((x - 0.6).abs() < 0.01);
175 assert!((y - 0.8).abs() < 0.01);
176 }
177}