sr_rcd/
rmp.rs

1use crate::point::Point;
2use crate::tmspace::TimetricSpace;
3
4fn norm(p: &Point, pwr: f64) -> f64 {
5    p.cs.iter().map(|&c| c.abs().powf(pwr)).sum::<f64>().powf(1.0 / pwr)
6}
7
8fn make_unit_cover_anchors(dim: usize, pwr: f64, rad: f64, n: usize) -> Vec<Point> {
9    let mut index = vec![0usize; dim];
10
11    let step = 2.0 * rad / (n as f64);
12    let mut anchors: Vec<Point> = Vec::with_capacity((n+1).pow(dim as u32));
13
14    loop {
15        let anchor = Point::new(
16            index.iter().map(|&i| -rad + (i as f64) * step).collect::<Vec<f64>>()
17        );
18        if norm(&anchor, pwr) <= 1.5 * rad {
19            anchors.push(anchor);
20        }
21        let mut carry = true;
22        let mut i: usize = 0;
23        while carry && (i < dim) {
24            index[i] += 1;
25            if index[i] > n {
26                index[i] = 0;
27                i += 1;
28            } else {
29                carry = false;
30            }
31        }
32        if i == dim {
33            break
34        }
35    }
36
37    anchors
38}
39
40/// Normed space ℝ^m_p with periodically shifting atmosphere.
41pub struct RMPAtmo {
42    dim: usize,
43    pwr: f64,
44    atmosph_shift_vec: Point,
45    atmosph_shift_tmp: f64,
46    tau_precision: f64,
47
48    alpha: f64,
49    beta: f64,
50    unit_cover_anchors: Vec<Point>
51}
52
53impl RMPAtmo {
54    pub fn new(dim: usize, pwr: f64, atmosph_shift_vec: &Point, atmosph_shift_tmp: f64, tau_precision: f64) -> Self {
55        let alpha: f64 = 1.0 / (1.0 + atmosph_shift_tmp * norm(atmosph_shift_vec, pwr));
56        let beta: f64 = 1.0 / (1.0 - atmosph_shift_tmp * norm(atmosph_shift_vec, pwr));
57        let n = (2.0 * beta / alpha * (dim as f64).powf(1.0 / pwr)).ceil() as usize;
58        let unit_cover_anchors = make_unit_cover_anchors(dim, pwr, 1.0 / alpha, n);
59        Self{dim, pwr, atmosph_shift_vec: atmosph_shift_vec.clone(), atmosph_shift_tmp, tau_precision, alpha, beta, unit_cover_anchors}
60    }
61   
62}
63
64impl TimetricSpace for RMPAtmo {
65    fn dim(&self) -> usize {
66        self.dim
67    }
68
69    fn ftau(&self, t_from: f64, p_from: &Point, p_to: &Point) -> f64 {
70        let mut t: f64 = t_from;
71        loop {
72            let tn = t_from + norm(& p_to.sub(p_from).sub(& self.atmosph_shift_vec.mul(
73                (self.atmosph_shift_tmp * t).sin() - (self.atmosph_shift_tmp * t_from).sin()
74            )), self.pwr);
75            if (t - tn).abs() < self.tau_precision {
76                break tn - t_from;
77            }
78            t = tn;
79        }
80    }
81
82    fn btau(&self, t_to: f64, p_from: &Point, p_to: &Point) -> f64 {
83        let mut t: f64 = t_to;
84        loop {
85            let tn = t_to - norm(& p_to.sub(p_from).sub(& self.atmosph_shift_vec.mul(
86                (self.atmosph_shift_tmp * t_to).sin() - (self.atmosph_shift_tmp * t).sin()
87            )), self.pwr);
88            if (t - tn).abs() < self.tau_precision {
89                break t_to - tn;
90            }
91            t = tn;
92        }
93    }
94
95    fn rho(&self, p1: &Point, p2: &Point) -> f64 {
96        norm(& p1.sub(p2), self.pwr)
97    }
98
99    fn alpha(&self) -> f64 {
100        self.alpha
101    }
102
103    fn beta(&self) -> f64 {
104        self.beta
105    }
106    
107    fn make_rc_anchors(&self, anchor: &Point, radius: f64) -> Vec<Point> {
108        self.unit_cover_anchors.iter().map(|a| a.mul(radius).add(&anchor)).collect::<Vec<Point>>()
109    }
110
111}
112
113/// Normed space ℝ^m_p with constant wind.
114pub struct RMPWind {
115    dim: usize,
116    pwr: f64,
117    wind: Point,
118    tau_precision: f64,
119
120    alpha: f64,
121    beta: f64,
122    unit_cover_anchors: Vec<Point>
123}
124
125impl RMPWind {
126    pub fn new(dim: usize, pwr: f64, wind: &Point, tau_precision: f64) -> Self {
127        let alpha: f64 = 1.0 / (1.0 + norm(wind, pwr));
128        let beta: f64 = 1.0 / (1.0 - norm(wind, pwr));
129        let n = (2.0 * beta / alpha * (dim as f64).powf(1.0 / pwr)).ceil() as usize;
130        let unit_cover_anchors = make_unit_cover_anchors(dim, pwr, 1.0 / alpha, n);
131        Self{dim, pwr, wind: wind.clone(), tau_precision, alpha, beta, unit_cover_anchors}
132    }
133   
134}
135
136impl TimetricSpace for RMPWind {
137    fn dim(&self) -> usize {
138        self.dim
139    }
140
141    fn ftau(&self, _t_from: f64, p_from: &Point, p_to: &Point) -> f64 {
142        let mut t = 0f64;
143        loop {
144            let tn = norm(& p_from.sub(p_to).add(& self.wind.mul(t)), self.pwr);
145            if (t - tn).abs() < self.tau_precision {
146                break tn;
147            }
148            t = tn;
149        }
150    }
151
152    fn btau(&self, _t_to: f64, p_from: &Point, p_to: &Point) -> f64 {
153        self.ftau(0.0, p_from, p_to)
154    }
155
156    fn rho(&self, p1: &Point, p2: &Point) -> f64 {
157        norm(& p1.sub(p2), self.pwr)
158    }
159
160    fn alpha(&self) -> f64 {
161        self.alpha
162    }
163
164    fn beta(&self) -> f64 {
165        self.beta
166    }
167    
168    fn make_rc_anchors(&self, anchor: &Point, radius: f64) -> Vec<Point> {
169        self.unit_cover_anchors.iter().map(|a| a.mul(radius).add(&anchor)).collect::<Vec<Point>>()
170    }
171
172}