1use anomaly_grid::*;
8use std::time::Instant;
9
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 println!("š Industrial IoT Monitoring with Anomaly Grid");
12 println!("Predictive maintenance and equipment failure detection\n");
13
14 let normal_operations = generate_industrial_data(365); println!(
17 "Generated {} sensor readings (1 year)",
18 normal_operations.len()
19 );
20
21 let mut detector = AnomalyDetector::new(4)?; detector.train(&normal_operations)?;
26
27 println!("\nš§ Equipment Health Monitoring");
29
30 let equipment_scenarios = vec![
31 ("Bearing Wear", generate_bearing_wear_pattern()),
32 ("Vibration Anomaly", generate_vibration_anomaly()),
33 ("Temperature Drift", generate_temperature_drift()),
34 ("Pressure Fluctuation", generate_pressure_fluctuation()),
35 ("Lubrication Failure", generate_lubrication_failure()),
36 ("Motor Imbalance", generate_motor_imbalance()),
37 ("Seal Degradation", generate_seal_degradation()),
38 ];
39
40 let mut maintenance_alerts = 0;
41 let mut critical_failures_prevented = 0;
42
43 for (equipment_issue, sensor_sequence) in equipment_scenarios {
44 println!("\nMonitoring: {equipment_issue}");
45
46 let detect_start = Instant::now();
47 let anomalies = detector.detect_anomalies(&sensor_sequence, 0.005)?; let detect_time = detect_start.elapsed();
49
50 if !anomalies.is_empty() {
51 maintenance_alerts += 1;
52
53 let severity = calculate_severity(&anomalies);
54 let time_to_failure = estimate_time_to_failure(&sensor_sequence);
55 let maintenance_cost = estimate_maintenance_cost(equipment_issue);
56
57 println!(" ā ļø MAINTENANCE ALERT");
58 println!(" š Anomalies detected: {}", anomalies.len());
59 println!(" Severity: {severity}");
60 println!(" Time to failure: {time_to_failure} hours");
61 println!(" Estimated maintenance cost: ${maintenance_cost:.0}");
62 println!(" Detection time: {detect_time:?}");
63
64 if severity == "CRITICAL" {
65 critical_failures_prevented += 1;
66 println!(" šØ IMMEDIATE SHUTDOWN RECOMMENDED");
67 }
68
69 generate_maintenance_recommendation(equipment_issue, &severity, time_to_failure);
70 } else {
71 println!(" ā
Equipment operating normally");
72 }
73 }
74
75 println!("\nš Production Line Monitoring");
77 let production_data = generate_production_line_data();
78
79 let line_start = Instant::now();
80 let line_anomalies = detector.detect_anomalies(&production_data, 0.01)?;
81 let line_time = line_start.elapsed();
82
83 if !line_anomalies.is_empty() {
84 let efficiency_impact = calculate_efficiency_impact(&line_anomalies);
85 println!("Production anomalies detected: {}", line_anomalies.len());
86 println!("Efficiency impact: {efficiency_impact:.1}%");
87 println!("Detection time: {line_time:?}");
88 } else {
89 println!("Production line operating normally");
90 }
91
92 println!("\nā” Energy Consumption Monitoring");
94 let energy_data = generate_energy_consumption_data();
95
96 let energy_start = Instant::now();
97 let energy_anomalies = detector.detect_anomalies(&energy_data, 0.02)?;
98 let energy_time = energy_start.elapsed();
99
100 if !energy_anomalies.is_empty() {
101 let energy_waste = calculate_energy_waste(&energy_anomalies);
102 println!("Energy anomalies detected: {}", energy_anomalies.len());
103 println!("Estimated energy waste: {energy_waste:.0} kWh");
104 println!("Cost impact: ${:.2}", energy_waste * 0.12); println!("Detection time: {energy_time:?}");
106 } else {
107 println!("Energy consumption within normal parameters");
108 }
109
110 println!("\nš¦ Multi-Machine Batch Processing");
112 let machine_data = vec![
113 generate_machine_data("CNC_001"),
114 generate_machine_data("PRESS_002"),
115 generate_machine_data("ROBOT_003"),
116 generate_machine_data("CONVEYOR_004"),
117 generate_machine_data("WELDER_005"),
118 ];
119
120 let batch_start = Instant::now();
121 let config = AnomalyGridConfig::default().with_max_order(6)?;
122 let batch_results = batch_process_sequences(&machine_data, &config, 0.01)?;
123 let batch_time = batch_start.elapsed();
124
125 println!(
126 "Processed {} machines in {:?}",
127 machine_data.len(),
128 batch_time
129 );
130 for (i, results) in batch_results.iter().enumerate() {
131 let machine_names = [
132 "CNC_001",
133 "PRESS_002",
134 "ROBOT_003",
135 "CONVEYOR_004",
136 "WELDER_005",
137 ];
138 println!(
139 " {}: {} anomalies detected",
140 machine_names[i],
141 results.len()
142 );
143 }
144
145 println!("\nš Predictive Maintenance Summary");
147 println!("Maintenance alerts generated: {maintenance_alerts}");
148 println!("Critical failures prevented: {critical_failures_prevented}");
149
150 let downtime_prevented = critical_failures_prevented * 8; let cost_savings = downtime_prevented as f64 * 5000.0; let maintenance_costs = maintenance_alerts as f64 * 2000.0; let net_savings = cost_savings - maintenance_costs;
154
155 println!("Downtime prevented: {downtime_prevented} hours");
156 println!("Cost savings: ${cost_savings:.0}");
157 println!("Maintenance costs: ${maintenance_costs:.0}");
158 println!("Net savings: ${net_savings:.0}");
159 println!("ROI: {:.1}%", (net_savings / maintenance_costs) * 100.0);
160
161 Ok(())
162}
163
164fn generate_industrial_data(days: usize) -> Vec<String> {
165 let mut data = Vec::new();
166 let readings_per_day = 1440; let normal_patterns = vec![
169 vec!["TEMP_NORMAL", "TEMP_STABLE", "TEMP_WITHIN_RANGE"],
171 vec!["TEMP_STARTUP", "TEMP_RISING", "TEMP_NORMAL", "TEMP_STABLE"],
172 vec!["PRESSURE_NORMAL", "PRESSURE_STABLE", "PRESSURE_OPTIMAL"],
174 vec!["PRESSURE_STARTUP", "PRESSURE_BUILDING", "PRESSURE_NORMAL"],
175 vec!["VIBRATION_LOW", "VIBRATION_NORMAL", "VIBRATION_STABLE"],
177 vec![
178 "VIBRATION_STARTUP",
179 "VIBRATION_SETTLING",
180 "VIBRATION_NORMAL",
181 ],
182 vec!["FLOW_NORMAL", "FLOW_STABLE", "FLOW_OPTIMAL"],
184 vec!["FLOW_STARTUP", "FLOW_RAMPING", "FLOW_NORMAL"],
185 vec!["POWER_NORMAL", "POWER_EFFICIENT", "POWER_STABLE"],
187 vec!["POWER_STARTUP", "POWER_RAMPING", "POWER_NORMAL"],
188 vec!["LUBE_PRESSURE_OK", "LUBE_FLOW_NORMAL", "LUBE_TEMP_OK"],
190 vec!["LUBE_CYCLE_START", "LUBE_DISPENSING", "LUBE_CYCLE_COMPLETE"],
191 ];
192
193 for _ in 0..days {
194 for _ in 0..readings_per_day {
195 let pattern = &normal_patterns[data.len() % normal_patterns.len()];
196 data.extend(pattern.iter().map(|s| s.to_string()));
197 }
198 }
199
200 data
201}
202
203fn generate_bearing_wear_pattern() -> Vec<String> {
204 vec![
205 "VIBRATION_NORMAL",
207 "TEMP_NORMAL",
208 "SOUND_NORMAL",
209 "VIBRATION_SLIGHT_INCREASE",
211 "TEMP_SLIGHT_RISE",
212 "SOUND_CHANGE",
213 "VIBRATION_IRREGULAR",
214 "TEMP_FLUCTUATION",
215 "SOUND_GRINDING",
216 "VIBRATION_HIGH",
218 "TEMP_HIGH",
219 "SOUND_LOUD_GRINDING",
220 "VIBRATION_SEVERE",
221 "TEMP_CRITICAL",
222 "SOUND_METAL_ON_METAL",
223 "VIBRATION_EXTREME",
225 "TEMP_OVERHEATING",
226 "SOUND_CATASTROPHIC",
227 ]
228 .into_iter()
229 .map(String::from)
230 .collect()
231}
232
233fn generate_vibration_anomaly() -> Vec<String> {
234 vec![
235 "VIBRATION_NORMAL",
236 "VIBRATION_NORMAL",
237 "VIBRATION_NORMAL",
238 "VIBRATION_SPIKE",
239 "VIBRATION_HIGH",
240 "VIBRATION_OSCILLATING",
241 "VIBRATION_HARMONIC",
242 "VIBRATION_RESONANCE",
243 "VIBRATION_UNSTABLE",
244 "VIBRATION_CRITICAL",
245 "VIBRATION_SHUTDOWN_REQUIRED",
246 ]
247 .into_iter()
248 .map(String::from)
249 .collect()
250}
251
252fn generate_temperature_drift() -> Vec<String> {
253 vec![
254 "TEMP_NORMAL",
255 "TEMP_NORMAL",
256 "TEMP_SLIGHT_RISE",
257 "TEMP_GRADUAL_INCREASE",
258 "TEMP_ABOVE_NORMAL",
259 "TEMP_TRENDING_UP",
260 "TEMP_HIGH",
261 "TEMP_VERY_HIGH",
262 "TEMP_CRITICAL",
263 "TEMP_OVERHEATING",
264 "TEMP_SHUTDOWN_THRESHOLD",
265 ]
266 .into_iter()
267 .map(String::from)
268 .collect()
269}
270
271fn generate_pressure_fluctuation() -> Vec<String> {
272 vec![
273 "PRESSURE_NORMAL",
274 "PRESSURE_STABLE",
275 "PRESSURE_SLIGHT_DROP",
276 "PRESSURE_FLUCTUATING",
277 "PRESSURE_UNSTABLE",
278 "PRESSURE_CYCLING",
279 "PRESSURE_LOW",
280 "PRESSURE_VERY_LOW",
281 "PRESSURE_CRITICAL_LOW",
282 "PRESSURE_SYSTEM_FAILURE",
283 "PRESSURE_EMERGENCY_STOP",
284 ]
285 .into_iter()
286 .map(String::from)
287 .collect()
288}
289
290fn generate_lubrication_failure() -> Vec<String> {
291 vec![
292 "LUBE_PRESSURE_OK",
293 "LUBE_FLOW_NORMAL",
294 "LUBE_TEMP_OK",
295 "LUBE_PRESSURE_DROP",
296 "LUBE_FLOW_REDUCED",
297 "LUBE_TEMP_RISE",
298 "LUBE_PRESSURE_LOW",
299 "LUBE_FLOW_INSUFFICIENT",
300 "LUBE_TEMP_HIGH",
301 "LUBE_SYSTEM_FAILURE",
302 "LUBE_STARVATION",
303 "LUBE_EMERGENCY",
304 ]
305 .into_iter()
306 .map(String::from)
307 .collect()
308}
309
310fn generate_motor_imbalance() -> Vec<String> {
311 vec![
312 "MOTOR_BALANCED",
313 "CURRENT_NORMAL",
314 "TORQUE_STABLE",
315 "MOTOR_SLIGHT_IMBALANCE",
316 "CURRENT_FLUCTUATION",
317 "TORQUE_VARIATION",
318 "MOTOR_IMBALANCED",
319 "CURRENT_SPIKES",
320 "TORQUE_IRREGULAR",
321 "MOTOR_SEVERE_IMBALANCE",
322 "CURRENT_OVERLOAD",
323 "TORQUE_UNSTABLE",
324 ]
325 .into_iter()
326 .map(String::from)
327 .collect()
328}
329
330fn generate_seal_degradation() -> Vec<String> {
331 vec![
332 "SEAL_INTACT",
333 "PRESSURE_STABLE",
334 "NO_LEAKAGE",
335 "SEAL_WEAR_INITIAL",
336 "PRESSURE_SLIGHT_DROP",
337 "MINOR_SEEPAGE",
338 "SEAL_DEGRADED",
339 "PRESSURE_LOSS",
340 "VISIBLE_LEAK",
341 "SEAL_FAILURE",
342 "PRESSURE_CRITICAL",
343 "MAJOR_LEAK",
344 ]
345 .into_iter()
346 .map(String::from)
347 .collect()
348}
349
350fn generate_production_line_data() -> Vec<String> {
351 vec![
352 "CONVEYOR_NORMAL",
354 "ROBOT_CYCLE_COMPLETE",
355 "QUALITY_PASS",
356 "CONVEYOR_NORMAL",
357 "ROBOT_CYCLE_COMPLETE",
358 "QUALITY_PASS",
359 "CONVEYOR_SLOW",
361 "ROBOT_CYCLE_DELAYED",
362 "QUALITY_FAIL",
363 "CONVEYOR_JAM",
364 "ROBOT_ERROR",
365 "QUALITY_REJECT",
366 "PRODUCTION_STOP",
367 "MAINTENANCE_REQUIRED",
368 ]
369 .into_iter()
370 .map(String::from)
371 .collect()
372}
373
374fn generate_energy_consumption_data() -> Vec<String> {
375 vec![
376 "POWER_BASELINE",
377 "EFFICIENCY_NORMAL",
378 "CONSUMPTION_OPTIMAL",
379 "POWER_BASELINE",
380 "EFFICIENCY_NORMAL",
381 "CONSUMPTION_OPTIMAL",
382 "POWER_SPIKE",
384 "EFFICIENCY_DROP",
385 "CONSUMPTION_HIGH",
386 "POWER_EXCESSIVE",
387 "EFFICIENCY_POOR",
388 "CONSUMPTION_WASTEFUL",
389 "POWER_CRITICAL",
390 "EFFICIENCY_FAILURE",
391 "CONSUMPTION_EXTREME",
392 ]
393 .into_iter()
394 .map(String::from)
395 .collect()
396}
397
398fn generate_machine_data(machine_id: &str) -> Vec<String> {
399 vec![
400 format!("{}_STARTUP", machine_id),
401 format!("{}_NORMAL_OPERATION", machine_id),
402 format!("{}_CYCLE_COMPLETE", machine_id),
403 format!("{}_NORMAL_OPERATION", machine_id),
404 format!("{}_MAINTENANCE_DUE", machine_id),
405 ]
406}
407
408fn calculate_severity(anomalies: &[AnomalyScore]) -> String {
409 let max_strength = anomalies
410 .iter()
411 .map(|a| a.anomaly_strength)
412 .fold(0.0, f64::max);
413
414 if max_strength > 0.9 {
415 "CRITICAL".to_string()
416 } else if max_strength > 0.7 {
417 "HIGH".to_string()
418 } else if max_strength > 0.5 {
419 "MEDIUM".to_string()
420 } else {
421 "LOW".to_string()
422 }
423}
424
425fn estimate_time_to_failure(sequence: &[String]) -> u32 {
426 let critical_indicators = sequence
428 .iter()
429 .filter(|s| s.contains("CRITICAL") || s.contains("SEVERE") || s.contains("EXTREME"))
430 .count();
431
432 if critical_indicators > 3 {
433 2 } else if critical_indicators > 1 {
435 24 } else {
437 168 }
439}
440
441fn estimate_maintenance_cost(equipment_issue: &str) -> f64 {
442 match equipment_issue {
443 "Bearing Wear" => 5000.0,
444 "Vibration Anomaly" => 3000.0,
445 "Temperature Drift" => 2000.0,
446 "Pressure Fluctuation" => 4000.0,
447 "Lubrication Failure" => 1500.0,
448 "Motor Imbalance" => 8000.0,
449 "Seal Degradation" => 2500.0,
450 _ => 3000.0,
451 }
452}
453
454fn calculate_efficiency_impact(anomalies: &[AnomalyScore]) -> f64 {
455 let avg_strength =
456 anomalies.iter().map(|a| a.anomaly_strength).sum::<f64>() / anomalies.len() as f64;
457
458 avg_strength * 15.0 }
460
461fn calculate_energy_waste(anomalies: &[AnomalyScore]) -> f64 {
462 let total_strength = anomalies.iter().map(|a| a.anomaly_strength).sum::<f64>();
463
464 total_strength * 100.0 }
466
467fn generate_maintenance_recommendation(
468 equipment_issue: &str,
469 severity: &str,
470 time_to_failure: u32,
471) {
472 println!(" š MAINTENANCE RECOMMENDATION");
473
474 let action = match severity {
475 "CRITICAL" => "IMMEDIATE SHUTDOWN AND REPAIR",
476 "HIGH" => "SCHEDULE URGENT MAINTENANCE",
477 "MEDIUM" => "PLAN MAINTENANCE WITHIN 48 HOURS",
478 _ => "MONITOR AND SCHEDULE ROUTINE MAINTENANCE",
479 };
480
481 println!(" Issue: {equipment_issue}");
482 println!(" Action: {action}");
483 println!(" Timeline: {time_to_failure} hours");
484
485 let parts_needed = match equipment_issue {
486 "Bearing Wear" => "Replacement bearings, lubricant",
487 "Vibration Anomaly" => "Balancing weights, alignment tools",
488 "Temperature Drift" => "Cooling system components, sensors",
489 "Pressure Fluctuation" => "Seals, pressure regulators",
490 "Lubrication Failure" => "Lubricant, filters, pumps",
491 "Motor Imbalance" => "Motor components, alignment equipment",
492 "Seal Degradation" => "Replacement seals, gaskets",
493 _ => "Standard maintenance kit",
494 };
495
496 println!(" Parts needed: {parts_needed}");
497}