sr_rcd/
rcd.rs

1extern crate rayon;
2
3use rayon::prelude::*;
4
5use std::{
6    fs::File,
7    io::Write
8};
9
10use crate::{
11    point::Point,
12    tmspace::TimetricSpace
13};
14
15pub struct Sensor {
16    p: Point,
17    t: f64
18}
19
20impl Sensor {
21    pub fn make(p: &Point, t: f64) -> Self {
22        Self{p: p.clone(), t}
23    }
24}
25
26/// Measures "spread" of *backward instants*
27/// when the sound should be emitted by this point in order to reach each sensor at its activation instant,
28/// and compares it with threshold.
29/// At the source point this spread is 0.
30fn defect_compare_le(tmsp: &impl TimetricSpace, sensorium: &Vec<Sensor>, x: &Point, thres: f64) -> bool {
31    let mut bt_min = f64::MAX;
32    let mut bt_max = f64::MIN;
33    for r in sensorium.iter() {
34        let bt = r.t - tmsp.btau(r.t, x, & r.p);
35        bt_min = bt_min.min(bt);
36        bt_max = bt_max.max(bt);
37        if (bt_max - bt_min) > thres {
38            return false
39        }
40    }
41    true
42}
43
44/// Refining-Cover-by-Defect approximation.
45pub fn rcd(tmsp: &impl TimetricSpace, sensorium: &Vec<Sensor>, anchor0: &Point, radius0: f64, precision: f64, dup_thres: f64, log: bool) -> Result<Point, String> {
46    // Step 0
47    let mut k: usize = 0;
48    let mut r: f64 = radius0;
49    let mut cover_anchors = vec![anchor0.clone()];
50    let mut z: Point;
51    loop {
52        // Step 1
53        let next_cover_anchors = cover_anchors.par_iter().map(|a| tmsp.make_rc_anchors(a, r).into_par_iter()).flatten()
54            .filter(|a| defect_compare_le(tmsp, sensorium, a, r)).collect::<Vec<Point>>();
55        if next_cover_anchors.len() == 0 {
56            break Err(format!("cover became empty"));
57        }
58
59        // Step 1.5
60        cover_anchors.clear();
61        for c in next_cover_anchors.iter() {
62            let mut dup: bool = false;
63            for uc in cover_anchors.iter() {
64                if tmsp.rho(c, uc) < dup_thres / tmsp.beta() {
65                    dup = true;
66                    break;
67                }
68            }
69            if !dup {
70                cover_anchors.push(c.clone());
71            }
72        }
73
74        // Step 2
75        z = cover_anchors[cover_anchors.len() >> 1].clone();
76
77        // Step 3
78        k += 1;
79        r *= 0.5;        
80
81        let d = r + tmsp.beta() * cover_anchors.iter().fold(0f64, |max, a| max.max(tmsp.rho(&z, a)));
82        println!("Iteration {}: {} coverands, d = {:.4}", k, cover_anchors.len(), d);
83
84        if log {
85            let mut logfile = File::create(format!("iter_{}.log", k)).map_err(|e| e.to_string())?;
86            write!(&mut logfile, "{}\n{}\n{}\n{}\n", d, tmsp.dim(), r, cover_anchors.len()).map_err(|e| e.to_string())?;
87            for a in cover_anchors.iter() {
88                for c in a.coords().iter() {
89                    writeln!(&mut logfile, "{}", c).map_err(|e| e.to_string())?;
90                }
91            }
92            logfile.flush().map_err(|e| e.to_string())?;
93        }
94
95        if d < precision {
96            break Ok(z);
97        }
98    }
99}