Skip to content

Commit 35e47d7

Browse files
committed
Numeric Stability and Readme
1 parent 732853c commit 35e47d7

File tree

16 files changed

+55
-195
lines changed

16 files changed

+55
-195
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,29 @@ By default, Fred will automatically determine the number of threads to use. If y
2929
- signature: `fred.discrete_frechet(curve1, curve2)`
3030
- returns: `fred.Discrete_Frechet_Result` with members `value` and `time`
3131

32+
### Curve Simplification
33+
34+
#### weak minimum error simplification
35+
- graph approach from [**Polygonal Approximations of a Curve — Formulations and Algorithms**](https://www.sciencedirect.com/science/article/pii/B9780444704672500114)
36+
- signature: `fred.weak_minimum_error_simplification(fred.Curve, int complexity)`
37+
- returns: `fred.Curve`that uses input curves vertices, with `complexity` number of vertices and that has minimum distance to input curve
38+
39+
#### approximate weak minimum link simplification
40+
- algorithm "FS" from [**Near-Linear Time Approximation Algorithms for Curve Simplification**](https://link.springer.com/article/10.1007/s00453-005-1165-y)
41+
- signature: `fred.approximate_weak_minimum_error_simplification(fred.Curve, double error)`
42+
- returns: `fred.Curve` that uses input curves vertices, is of small complexity and with distance to input curve at most `error`
43+
44+
#### approximate weak minimum error simplification
45+
- binary search on `fred.approximate_weak_minimum_link_simplification`
46+
- signature: `fred.approximate_weak_minimum_error_simplification(fred.Curve, int complexity)`
47+
- returns: `fred.Curve`that uses input curves vertices, with `complexity` number of vertices and that has small distance to input curve
48+
3249
### Clustering
3350

3451
##### Distance_Matrix
3552

3653
A `fred.Distance_Matrix()` can be used to speed up consecutive calls of `fred.discrete_klcenter` and `fred.discrete_klmedian`. As the name suggests, it stores the distances already computed.
3754

38-
3955
#### discrete (k,l)-center clustering (continuous Fréchet) -- multiple calls
4056
- from [**Approximating (k,l)-center clustering for curves**](https://dl.acm.org/doi/10.5555/3310435.3310616)
4157
- signature: `fred.discrete_klcenter_multi(k, l, curves, distances, center_domain, random_first_center)` with parameters

experiments/dtw_mislead_i.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

experiments/dtw_mislead_m.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

experiments/dtw_normal.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

experiments/dtw_old.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

experiments/dtw_zigzag.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

include/curve.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class Curve : private Points {
125125
np::dtype dt = np::dtype::get_builtin<coordinate_t>();
126126
p::list l;
127127
np::ndarray result = np::array(l, dt);
128-
for (const auto &elem : *this) {
128+
for (const Point &elem : *this) {
129129
l.append(elem.as_ndarray());
130130
}
131131
result = np::array(l, dt);

include/interval.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Interval {
2020
parameter_t beg, en;
2121

2222
public:
23-
Interval() : beg{1}, en{0} {}
23+
Interval() : beg{1.L}, en{0.L} {}
2424

2525
Interval(const parameter_t begin, const parameter_t end) : beg{begin}, en{end} {}
2626

@@ -29,7 +29,8 @@ class Interval {
2929
}
3030

3131
inline bool is_empty() const {
32-
return beg > en;
32+
if (en - beg >= std::numeric_limits<parameter_t>::epsilon()) return beg > en;
33+
else return true;
3334
}
3435

3536
inline bool intersects(const Interval &other) const {
@@ -49,8 +50,8 @@ class Interval {
4950
}
5051

5152
inline void reset() {
52-
beg = 1;
53-
en = 0;
53+
beg = 1.L;
54+
en = 0.L;
5455
}
5556
};
5657

include/point.hpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class Point : public Coordinates {
7272
}
7373

7474
inline Point operator+(const Point &point) const {
75-
auto result = *this;
75+
Point result = *this;
7676
#pragma omp simd
7777
for (dimensions_t i = 0; i < dimensions(); ++i){
7878
result.operator[](i) += point[i];
@@ -81,7 +81,7 @@ class Point : public Coordinates {
8181
}
8282

8383
inline Point operator-(const Point &point) const {
84-
auto result = *this;
84+
Point result = *this;
8585
#pragma omp simd
8686
for (dimensions_t i = 0; i < dimensions(); ++i){
8787
result.operator[](i) -= point[i];
@@ -145,32 +145,32 @@ class Point : public Coordinates {
145145

146146
inline Interval intersection_interval(const distance_t distance_sqr, const Point &line_start, const Point &line_end) const {
147147
const Vector u = line_end-line_start, v = *this - line_start;
148-
const distance_t ulen_sqr = u.length_sqr(), vlen_sqr = v.length_sqr();
148+
const parameter_t ulen_sqr = u.length_sqr(), vlen_sqr = v.length_sqr();
149149

150150
if (ulen_sqr == 0) {
151151
if (vlen_sqr <= distance_sqr) return Interval(0, 1);
152152
else return Interval();
153153
}
154154

155-
const distance_t p = -2. / ulen_sqr * (u * v), q = (vlen_sqr - distance_sqr) / ulen_sqr;
155+
const parameter_t p = -2. * ((u * v) / ulen_sqr), q = vlen_sqr / ulen_sqr - distance_sqr / ulen_sqr;
156156

157-
const distance_t phalf_sqr = p * p / 4., discriminant = phalf_sqr - q;
157+
const parameter_t phalf_sqr = p * p / 4., discriminant = phalf_sqr - q;
158158

159159
if (discriminant < 0) return Interval();
160160

161-
const distance_t discriminant_sqrt = std::sqrt(discriminant);
161+
const parameter_t discriminant_sqrt = std::sqrt(discriminant);
162162

163-
const distance_t minus_p_h = - p / 2., r1 = minus_p_h + discriminant_sqrt, r2 = minus_p_h - discriminant_sqrt;
164-
const distance_t lambda1 = std::min(r1, r2), lambda2 = std::max(r1, r2);
163+
const parameter_t minus_p_h = - p / 2., r1 = minus_p_h + discriminant_sqrt, r2 = minus_p_h - discriminant_sqrt;
164+
const parameter_t lambda1 = std::min(r1, r2), lambda2 = std::max(r1, r2);
165165

166-
return Interval(std::max(0., lambda1), std::min(1., lambda2));
166+
return Interval(std::max(0.L, lambda1), std::min(1.L, lambda2));
167167
}
168168

169169
inline auto as_ndarray() const {
170170
np::dtype dt = np::dtype::get_builtin<coordinate_t>();
171171
p::list l;
172172
np::ndarray result = np::array(l, dt);
173-
for (const auto &elem : *this) {
173+
for (const coordinate_t &elem : *this) {
174174
l.append(elem);
175175
}
176176
result = np::array(l, dt);
@@ -223,7 +223,7 @@ class Points : public std::vector<Point> {
223223

224224
inline auto as_ndarray() const {
225225
p::list l;
226-
for (const auto &elem : *this) {
226+
for (const Point &elem : *this) {
227227
l.append(elem.as_ndarray());
228228
}
229229
auto result = np::array(l);

include/random.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ class Custom_Probability_Generator {
7575
}
7676

7777
inline T get() {
78-
const auto n = cumulative_probabilities.size();
79-
const auto r = uform_gen.get();
78+
const std::size_t n = cumulative_probabilities.size();
79+
const T r = uform_gen.get();
8080
const auto upper = std::upper_bound(cumulative_probabilities.cbegin(), cumulative_probabilities.cend(), r);
8181
assert(upper != cumulative_probabilities.cend());
82-
const auto result = std::distance(cumulative_probabilities.cbegin(), upper);
82+
const std::size_t result = std::distance(cumulative_probabilities.cbegin(), upper);
8383
return result;
8484
}
8585

0 commit comments

Comments
 (0)