temporal_neural_solver/baselines/
rust_standard.rs1use std::time::{Duration, Instant};
7
8#[derive(Clone)]
10pub struct RustStandardNetwork {
11 layer1: LinearLayer,
12 layer2: LinearLayer,
13}
14
15#[derive(Clone)]
16struct LinearLayer {
17 weights: Vec<Vec<f32>>,
18 bias: Vec<f32>,
19 input_size: usize,
20 output_size: usize,
21}
22
23impl LinearLayer {
24 fn new(input_size: usize, output_size: usize) -> Self {
25 use rand::Rng;
26 let mut rng = rand::thread_rng();
27
28 let std_dev = (2.0 / input_size as f32).sqrt();
30
31 let mut weights = Vec::with_capacity(output_size);
32 for _ in 0..output_size {
33 let mut row = Vec::with_capacity(input_size);
34 for _ in 0..input_size {
35 let val: f32 = rng.gen::<f32>() * 2.0 - 1.0; row.push(val * std_dev);
37 }
38 weights.push(row);
39 }
40
41 Self {
42 weights,
43 bias: vec![0.0; output_size],
44 input_size,
45 output_size,
46 }
47 }
48
49 fn forward(&self, input: &[f32]) -> Vec<f32> {
50 assert_eq!(input.len(), self.input_size);
51
52 let mut output = Vec::with_capacity(self.output_size);
53
54 for i in 0..self.output_size {
55 let mut sum = self.bias[i];
56
57 for j in 0..self.input_size {
58 sum += self.weights[i][j] * input[j];
59 }
60
61 output.push(sum);
62 }
63
64 output
65 }
66
67 fn forward_relu(&self, input: &[f32]) -> Vec<f32> {
68 let z = self.forward(input);
69 z.into_iter().map(|x| x.max(0.0)).collect()
70 }
71}
72
73impl RustStandardNetwork {
74 pub fn new_standard() -> Self {
75 let layer1 = LinearLayer::new(128, 32);
76 let layer2 = LinearLayer::new(32, 4);
77
78 Self { layer1, layer2 }
79 }
80
81 pub fn forward(&self, input: &[f32; 128]) -> Vec<f32> {
83 let hidden = self.layer1.forward_relu(input);
85
86 self.layer2.forward(&hidden)
88 }
89
90 pub fn predict_timed(&self, input: &[f32; 128]) -> (Vec<f32>, Duration) {
92 let start = Instant::now();
93 let output = self.forward(input);
94 let duration = start.elapsed();
95 (output, duration)
96 }
97
98 pub fn predict_batch(&self, inputs: &[[f32; 128]]) -> Vec<Vec<f32>> {
100 inputs.iter().map(|input| self.forward(input)).collect()
101 }
102
103 pub fn predict_batch_timed(&self, inputs: &[[f32; 128]]) -> (Vec<Vec<f32>>, Duration) {
104 let start = Instant::now();
105 let outputs = self.predict_batch(inputs);
106 let duration = start.elapsed();
107 (outputs, duration)
108 }
109}
110
111pub struct OptimizedRustNetwork {
113 w1: Vec<f32>, b1: Vec<f32>, w2: Vec<f32>, b2: Vec<f32>, hidden_buffer: Vec<f32>,
121}
122
123impl OptimizedRustNetwork {
124 pub fn new_standard() -> Self {
125 use rand::Rng;
126 let mut rng = rand::thread_rng();
127
128 let std1 = (2.0 / 128.0_f32).sqrt();
129 let std2 = (2.0 / 32.0_f32).sqrt();
130
131 let w1: Vec<f32> = (0..32*128)
132 .map(|_| (rng.gen::<f32>() * 2.0 - 1.0) * std1)
133 .collect();
134
135 let w2: Vec<f32> = (0..4*32)
136 .map(|_| (rng.gen::<f32>() * 2.0 - 1.0) * std2)
137 .collect();
138
139 Self {
140 w1,
141 b1: vec![0.0; 32],
142 w2,
143 b2: vec![0.0; 4],
144 hidden_buffer: vec![0.0; 32],
145 }
146 }
147
148 pub fn forward(&mut self, input: &[f32; 128]) -> [f32; 4] {
149 for i in 0..32 {
151 let mut sum = self.b1[i];
152
153 for j in 0..128 {
155 sum += self.w1[i * 128 + j] * input[j];
156 }
157
158 self.hidden_buffer[i] = sum.max(0.0);
160 }
161
162 let mut output = [0.0f32; 4];
164 for i in 0..4 {
165 let mut sum = self.b2[i];
166
167 for j in 0..32 {
168 sum += self.w2[i * 32 + j] * self.hidden_buffer[j];
169 }
170
171 output[i] = sum;
172 }
173
174 output
175 }
176
177 pub fn predict_timed(&mut self, input: &[f32; 128]) -> ([f32; 4], Duration) {
178 let start = Instant::now();
179 let output = self.forward(input);
180 let duration = start.elapsed();
181 (output, duration)
182 }
183}
184
185pub struct FunctionalRustNetwork {
187 weights1: Vec<Vec<f32>>,
188 bias1: Vec<f32>,
189 weights2: Vec<Vec<f32>>,
190 bias2: Vec<f32>,
191}
192
193impl FunctionalRustNetwork {
194 pub fn new_standard() -> Self {
195 use rand::Rng;
196 let mut rng = rand::thread_rng();
197
198 let std1 = (2.0 / 128.0_f32).sqrt();
199 let std2 = (2.0 / 32.0_f32).sqrt();
200
201 let weights1 = (0..32).map(|_| {
202 (0..128).map(|_| rng.gen::<f32>() * std1 * 2.0 - std1).collect()
203 }).collect();
204
205 let weights2 = (0..4).map(|_| {
206 (0..32).map(|_| rng.gen::<f32>() * std2 * 2.0 - std2).collect()
207 }).collect();
208
209 Self {
210 weights1,
211 bias1: vec![0.0; 32],
212 weights2,
213 bias2: vec![0.0; 4],
214 }
215 }
216
217 pub fn forward(&self, input: &[f32; 128]) -> Vec<f32> {
218 let hidden: Vec<f32> = self.weights1
220 .iter()
221 .zip(self.bias1.iter())
222 .map(|(weights, &bias)| {
223 let sum = weights
224 .iter()
225 .zip(input.iter())
226 .map(|(&w, &x)| w * x)
227 .sum::<f32>() + bias;
228 sum.max(0.0) })
230 .collect();
231
232 self.weights2
234 .iter()
235 .zip(self.bias2.iter())
236 .map(|(weights, &bias)| {
237 weights
238 .iter()
239 .zip(hidden.iter())
240 .map(|(&w, &h)| w * h)
241 .sum::<f32>() + bias
242 })
243 .collect()
244 }
245
246 pub fn predict_timed(&self, input: &[f32; 128]) -> (Vec<f32>, Duration) {
247 let start = Instant::now();
248 let output = self.forward(input);
249 let duration = start.elapsed();
250 (output, duration)
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[test]
259 fn test_rust_standard_network() {
260 let network = RustStandardNetwork::new_standard();
261 let input = [0.1f32; 128];
262 let (output, duration) = network.predict_timed(&input);
263
264 assert_eq!(output.len(), 4);
265 println!("Rust standard latency: {:?}", duration);
266 }
267
268 #[test]
269 fn test_optimized_rust_network() {
270 let mut network = OptimizedRustNetwork::new_standard();
271 let input = [0.1f32; 128];
272 let (output, duration) = network.predict_timed(&input);
273
274 assert_eq!(output.len(), 4);
275 println!("Optimized Rust latency: {:?}", duration);
276 }
277
278 #[test]
279 fn test_functional_rust_network() {
280 let network = FunctionalRustNetwork::new_standard();
281 let input = [0.1f32; 128];
282 let (output, duration) = network.predict_timed(&input);
283
284 assert_eq!(output.len(), 4);
285 println!("Functional Rust latency: {:?}", duration);
286 }
287
288 #[test]
289 fn test_batch_processing() {
290 let network = RustStandardNetwork::new_standard();
291 let inputs = vec![[0.1f32; 128]; 10];
292 let (outputs, duration) = network.predict_batch_timed(&inputs);
293
294 assert_eq!(outputs.len(), 10);
295 assert_eq!(outputs[0].len(), 4);
296 println!("Batch processing latency: {:?}", duration);
297 }
298}