src/measures/merging.rs

Tue, 31 Dec 2024 09:25:45 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 31 Dec 2024 09:25:45 -0500
branch
dev
changeset 35
b087e3eab191
parent 34
efa60bc4f743
child 39
6316d68b58af
permissions
-rw-r--r--

New version of sliding.

0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Spike merging heuristics for [`DiscreteMeasure`]s.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 This module primarily provides the [`SpikeMerging`] trait, and within it,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 the [`SpikeMerging::merge_spikes`] method. The trait is implemented on
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 [`DiscreteMeasure<Loc<F, N>, F>`]s in dimensions `N=1` and `N=2`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 */
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 use numeric_literals::replace_float_literals;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 use std::cmp::Ordering;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11 use serde::{Serialize, Deserialize};
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 //use clap::builder::{PossibleValuesParser, PossibleValue};
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 use alg_tools::nanleast::NaNLeast;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 use crate::types::*;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 use super::delta::*;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 use super::discrete::*;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 /// Spike merging heuristic selection
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 #[allow(dead_code)]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 pub enum SpikeMergingMethod<F> {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
23 /// Try to merge spikes within a given radius of each other, averaging the location
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 HeuristicRadius(F),
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
25 /// Try to merge spikes within a given radius of each other, attempting original locations
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
26 HeuristicRadiusNoInterp(F),
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 /// No merging
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 None,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 // impl<F : Float> SpikeMergingMethod<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 // /// This is for [`clap`] to display command line help.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 // pub fn value_parser() -> PossibleValuesParser {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34 // PossibleValuesParser::new([
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 // PossibleValue::new("none").help("No merging"),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 // PossibleValue::new("<radius>").help("Heuristic merging within indicated radius")
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 // ])
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 // }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 // }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 impl<F : ClapFloat> std::fmt::Display for SpikeMergingMethod<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 match self {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 Self::None => write!(f, "none"),
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
45 Self::HeuristicRadius(r) => write!(f, "i:{}", r),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
46 Self::HeuristicRadiusNoInterp(r) => write!(f, "n:{}", r),
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 impl<F : ClapFloat> std::str::FromStr for SpikeMergingMethod<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 type Err = F::Err;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 if s == "none" {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 Ok(Self::None)
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 } else {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
58 let mut subs = s.split(':');
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
59 match subs.next() {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
60 None => Ok(Self::HeuristicRadius(F::from_str(s)?)),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
61 Some(t) if t == "n" => match subs.next() {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
62 None => Err(core::num::dec2flt::pfe_invalid()),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
63 Some(v) => Ok(Self::HeuristicRadiusNoInterp(F::from_str(v)?))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
64 },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
65 Some(t) if t == "i" => match subs.next() {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
66 None => Err(core::num::dec2flt::pfe_invalid()),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
67 Some(v) => Ok(Self::HeuristicRadius(F::from_str(v)?))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
68 },
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
69 Some(v) => Ok(Self::HeuristicRadius(F::from_str(v)?))
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
70 }
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 impl<F : Float> Default for SpikeMergingMethod<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 fn default() -> Self {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 SpikeMergingMethod::HeuristicRadius(0.02)
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 /// Trait for dimension-dependent implementation of heuristic peak merging strategies.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 pub trait SpikeMerging<F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 /// Attempt spike merging according to [`SpikeMerging`] method.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 /// Returns the last [`Some`] returned by the merging candidate acceptance decision closure
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 /// `accept` if any merging is performed. The closure should accept as its only parameter a
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 /// new candidate measure (it will generally be internally mutated `self`, although this is
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 /// not guaranteed), and return [`None`] if the merge is accepted, and otherwise a [`Some`] of
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 /// an arbitrary value. This method will return that value for the *last* accepted merge, or
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 /// [`None`] if no merge was accepted.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 /// This method is stable with respect to spike locations: on merge, the weight of existing
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94 /// spikes is set to zero, and a new one inserted at the end of the spike vector.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
95 fn merge_spikes<G>(&mut self, method : SpikeMergingMethod<F>, accept : G) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
96 where G : FnMut(&'_ Self) -> bool {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 match method {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
98 SpikeMergingMethod::HeuristicRadius(ρ) =>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
99 self.do_merge_spikes_radius(ρ, true, accept),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
100 SpikeMergingMethod::HeuristicRadiusNoInterp(ρ) =>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
101 self.do_merge_spikes_radius(ρ, false, accept),
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
102 SpikeMergingMethod::None => 0,
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 /// Attempt to merge spikes based on a value and a fitness function.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 /// Calls [`SpikeMerging::merge_spikes`] with `accept` constructed from the composition of
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 /// `value` and `fitness`, compared to initial fitness. Returns the last return value of `value`
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 // for a merge accepted by `fitness`. If no merge was accepted, `value` applied to the initial
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
111 /// `self` is returned. also the number of merges is returned;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 fn merge_spikes_fitness<G, H, V, O>(
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113 &mut self,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 method : SpikeMergingMethod<F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 value : G,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 fitness : H
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
117 ) -> (V, usize)
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 where G : Fn(&'_ Self) -> V,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 H : Fn(&'_ V) -> O,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 O : PartialOrd {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
121 let mut res = value(self);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
122 let initial_fitness = fitness(&res);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
123 let count = self.merge_spikes(method, |μ| {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
124 res = value(μ);
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
125 fitness(&res) <= initial_fitness
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
126 });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
127 (res, count)
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 /// Attempt to merge spikes that are within radius $ρ$ of each other (unspecified norm).
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 /// This method implements [`SpikeMerging::merge_spikes`] for
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 /// [`SpikeMergingMethod::HeuristicRadius`]. The closure `accept` and the return value are
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 /// as for that method.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
135 fn do_merge_spikes_radius<G>(&mut self, ρ : F, interp : bool, accept : G) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
136 where G : FnMut(&'_ Self) -> bool;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
137 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 impl<F : Float, const N : usize> DiscreteMeasure<Loc<F, N>, F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 /// Attempts to merge spikes with indices `i` and `j`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 /// This assumes that the weights of the two spikes have already been checked not to be zero.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 /// The parameter `res` points to the current “result” for [`SpikeMerging::merge_spikes`].
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 /// If the merge is accepted by `accept` returning a [`Some`], `res` will be replaced by its
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 /// return value.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
148 ///
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
149 /// Returns the index of `self.spikes` storing the new spike.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
150 fn attempt_merge<G>(
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 &mut self,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152 i : usize,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 j : usize,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
154 interp : bool,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
155 accept : &mut G
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
156 ) -> Option<usize>
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
157 where G : FnMut(&'_ Self) -> bool {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 let &DeltaMeasure{ x : xi, α : αi } = &self.spikes[i];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159 let &DeltaMeasure{ x : xj, α : αj } = &self.spikes[j];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
161 if interp {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
162 // Merge inplace
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
163 self.spikes[i].α = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
164 self.spikes[j].α = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
165 let αia = αi.abs();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
166 let αja = αj.abs();
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
167 self.spikes.push(DeltaMeasure{ α : αi + αj, x : (xi * αia + xj * αja) / (αia + αja) });
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
168 if accept(self) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
169 Some(self.spikes.len()-1)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
170 } else {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 // Merge not accepted, restore modification
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 self.spikes[i].α = αi;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 self.spikes[j].α = αj;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 self.spikes.pop();
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
175 None
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
176 }
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
177 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
178 // Attempt merge inplace, first combination
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
179 self.spikes[i].α = αi + αj;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
180 self.spikes[j].α = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
181 if accept(self) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
182 // Merge accepted
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
183 Some(i)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
184 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
185 // Attempt merge inplace, second combination
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
186 self.spikes[i].α = 0.0;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
187 self.spikes[j].α = αi + αj;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
188 if accept(self) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
189 // Merge accepted
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
190 Some(j)
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
191 } else {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
192 // Merge not accepted, restore modification
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
193 self.spikes[i].α = αi;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
194 self.spikes[j].α = αj;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
195 None
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
196 }
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 /// Sorts a vector of indices into `slice` by `compare`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 ///
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 /// The closure `compare` operators on references to elements of `slice`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 /// Returns the sorted vector of indices into `slice`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 pub fn sort_indices_by<V, F>(slice : &[V], mut compare : F) -> Vec<usize>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 where F : FnMut(&V, &V) -> Ordering
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 let mut indices = Vec::from_iter(0..slice.len());
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 indices.sort_by(|&i, &j| compare(&slice[i], &slice[j]));
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 indices
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 impl<F : Float> SpikeMerging<F> for DiscreteMeasure<Loc<F, 1>, F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
217 fn do_merge_spikes_radius<G>(
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 &mut self,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 ρ : F,
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
220 interp : bool,
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
221 mut accept : G
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
222 ) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
223 where G : FnMut(&'_ Self) -> bool {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 // Sort by coordinate into an indexing array.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 let mut indices = sort_indices_by(&self.spikes, |&δ1, &δ2| {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 let &Loc([x1]) = &δ1.x;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 let &Loc([x2]) = &δ2.x;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 // nan-ignoring ordering of floats
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 NaNLeast(x1).cmp(&NaNLeast(x2))
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 });
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232 // Initialise result
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
233 let mut count = 0;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
234
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 // Scan consecutive pairs and merge if close enough and accepted by `accept`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 if indices.len() == 0 {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
237 return count
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
239 for k in 0..(indices.len()-1) {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 let i = indices[k];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
241 let j = indices[k+1];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
242 let &DeltaMeasure{ x : Loc([xi]), α : αi } = &self.spikes[i];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
243 let &DeltaMeasure{ x : Loc([xj]), α : αj } = &self.spikes[j];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 debug_assert!(xi <= xj);
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 // If close enough, attempt merging
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246 if αi != 0.0 && αj != 0.0 && xj <= xi + ρ {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
247 if let Some(l) = self.attempt_merge(i, j, interp, &mut accept) {
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
248 // For this to work (the debug_assert! to not trigger above), the new
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
249 // coordinate produced by attempt_merge has to be at most xj.
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
250 indices[k+1] = l;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
251 count += 1
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
253 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
254 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
256 count
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
257 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
258 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
259
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
260 /// Orders `δ1` and `δ1` according to the first coordinate.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
261 fn compare_first_coordinate<F : Float>(
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262 δ1 : &DeltaMeasure<Loc<F, 2>, F>,
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263 δ2 : &DeltaMeasure<Loc<F, 2>, F>
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
264 ) -> Ordering {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
265 let &Loc([x11, ..]) = &δ1.x;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 let &Loc([x21, ..]) = &δ2.x;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
267 // nan-ignoring ordering of floats
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
268 NaNLeast(x11).cmp(&NaNLeast(x21))
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
270
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 #[replace_float_literals(F::cast_from(literal))]
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272 impl<F : Float> SpikeMerging<F> for DiscreteMeasure<Loc<F, 2>, F> {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
274 fn do_merge_spikes_radius<G>(&mut self, ρ : F, interp : bool, mut accept : G) -> usize
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
275 where G : FnMut(&'_ Self) -> bool {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 // Sort by first coordinate into an indexing array.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
277 let mut indices = sort_indices_by(&self.spikes, compare_first_coordinate);
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
278
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279 // Initialise result
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
280 let mut count = 0;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
281 let mut start_scan_2nd = 0;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
282
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283 // Scan in order
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
284 if indices.len() == 0 {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
285 return count
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287 for k in 0..indices.len()-1 {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 let i = indices[k];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 let &DeltaMeasure{ x : Loc([xi1, xi2]), α : αi } = &self[i];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
291 if αi == 0.0 {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292 // Nothin to be done if the weight is already zero
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
293 continue
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
294 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 let mut closest = None;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
297
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
298 // Scan for second spike. We start from `start_scan_2nd + 1` with `start_scan_2nd`
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 // the smallest invalid merging index on the previous loop iteration, because a
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
300 // the _closest_ mergeable spike might have index less than `k` in `indices`, and a
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301 // merge with it might have not been attempted with this spike if a different closer
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 // spike was discovered based on the second coordinate.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303 'scan_2nd: for l in (start_scan_2nd+1)..indices.len() {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
304 if l == k {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
305 // Do not attempt to merge a spike with itself
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306 continue
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
307 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
308 let j = indices[l];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309 let &DeltaMeasure{ x : Loc([xj1, xj2]), α : αj } = &self[j];
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
310
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 if xj1 < xi1 - ρ {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 // Spike `j = indices[l]` has too low first coordinate. Update starting index
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313 // for next iteration, and continue scanning.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314 start_scan_2nd = l;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315 continue 'scan_2nd
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 } else if xj1 > xi1 + ρ {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 // Break out: spike `j = indices[l]` has already too high first coordinate, no
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 // more close enough spikes can be found due to the sorting of `indices`.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
319 break 'scan_2nd
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
322 // If also second coordinate is close enough, attempt merging if closer than
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 // previously discovered mergeable spikes.
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
324 let d2 = (xi2-xj2).abs();
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 if αj != 0.0 && d2 <= ρ {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 let r1 = xi1-xj1;
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 let d = (d2*d2 + r1*r1).sqrt();
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
328 match closest {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 None => closest = Some((l, j, d)),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330 Some((_, _, r)) if r > d => closest = Some((l, j, d)),
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
331 _ => {},
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
333 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
334 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 // Attempt merging closest close-enough spike
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
337 if let Some((l, j, _)) = closest {
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
338 if let Some(n) = self.attempt_merge(i, j, interp, &mut accept) {
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
339 // If merge was succesfull, make new spike candidate for merging.
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
340 indices[l] = n;
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
341 count += 1;
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
342 let compare = |i, j| compare_first_coordinate(&self.spikes[i],
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
343 &self.spikes[j]);
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
344 // Re-sort relevant range of indices
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
345 if l < k {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
346 indices[l..k].sort_by(|&i, &j| compare(i, j));
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
347 } else {
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
348 indices[k+1..=l].sort_by(|&i, &j| compare(i, j));
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
349 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
350 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
351 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
352 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
353
34
efa60bc4f743 Radon FB + sliding improvements
Tuomo Valkonen <tuomov@iki.fi>
parents: 0
diff changeset
354 count
0
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
355 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
356 }
eb3c7813b67a Initial version
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
357

mercurial