| 44 |
44 |
| 45 fn insert_and_reweigh<I>( |
45 fn insert_and_reweigh<I>( |
| 46 &self, |
46 &self, |
| 47 μ: &mut DiscreteMeasure<Domain, F>, |
47 μ: &mut DiscreteMeasure<Domain, F>, |
| 48 τv: &mut M, |
48 τv: &mut M, |
| 49 μ_base: &DiscreteMeasure<Domain, F>, |
|
| 50 ν_delta: Option<&DiscreteMeasure<Domain, F>>, |
|
| 51 τ: F, |
49 τ: F, |
| 52 ε: F, |
50 ε: F, |
| 53 config: &InsertionConfig<F>, |
51 config: &InsertionConfig<F>, |
| 54 reg: &Reg, |
52 reg: &Reg, |
| 55 state: &AlgIteratorIteration<I>, |
53 state: &AlgIteratorIteration<I>, |
| 65 match (state.iteration(), config.bootstrap_insertions) { |
63 match (state.iteration(), config.bootstrap_insertions) { |
| 66 (i, Some((l, k))) if i <= l => (k, false), |
64 (i, Some((l, k))) if i <= l => (k, false), |
| 67 _ => (config.max_insertions, !state.is_quiet()), |
65 _ => (config.max_insertions, !state.is_quiet()), |
| 68 }; |
66 }; |
| 69 |
67 |
| 70 let ω0 = match ν_delta { |
68 let μ_base = μ.clone(); |
| 71 None => self.apply(μ_base), |
69 let ω0 = self.apply(&μ_base); |
| 72 Some(ν) => self.apply(μ_base + ν), |
|
| 73 }; |
|
| 74 |
70 |
| 75 // Add points to support until within error tolerance or maximum insertion count reached. |
71 // Add points to support until within error tolerance or maximum insertion count reached. |
| 76 let mut count = 0; |
72 let mut count = 0; |
| 77 let (within_tolerances, d) = 'insertion: loop { |
73 let (within_tolerances, d) = 'insertion: loop { |
| 78 if μ.len() > 0 { |
74 if μ.len() > 0 { |
| 103 μ.set_masses_dvector(&x); |
99 μ.set_masses_dvector(&x); |
| 104 } |
100 } |
| 105 |
101 |
| 106 // Form d = τv + 𝒟μ - ω0 = τv + 𝒟(μ - μ^k) for checking the proximate optimality |
102 // Form d = τv + 𝒟μ - ω0 = τv + 𝒟(μ - μ^k) for checking the proximate optimality |
| 107 // conditions in the predual space, and finding new points for insertion, if necessary. |
103 // conditions in the predual space, and finding new points for insertion, if necessary. |
| 108 let mut d = &*τv |
104 let mut d = &*τv + self.preapply(μ.sub_matching(&μ_base)); |
| 109 + match ν_delta { |
|
| 110 None => self.preapply(μ.sub_matching(μ_base)), |
|
| 111 Some(ν) => self.preapply(μ.sub_matching(μ_base) - ν), |
|
| 112 }; |
|
| 113 |
105 |
| 114 // If no merging heuristic is used, let's be more conservative about spike insertion, |
106 // If no merging heuristic is used, let's be more conservative about spike insertion, |
| 115 // and skip it after first round. If merging is done, being more greedy about spike |
107 // and skip it after first round. If merging is done, being more greedy about spike |
| 116 // insertion also seems to improve performance. |
108 // insertion also seems to improve performance. |
| 117 let skip_by_rough_check = if config.merging.enabled { |
109 let skip_by_rough_check = if config.merging.enabled { |
| 133 } |
125 } |
| 134 |
126 |
| 135 // No point in optimising the weight here; the finite-dimensional algorithm is fast. |
127 // No point in optimising the weight here; the finite-dimensional algorithm is fast. |
| 136 *μ += DeltaMeasure { x: ξ, α: 0.0 }; |
128 *μ += DeltaMeasure { x: ξ, α: 0.0 }; |
| 137 count += 1; |
129 count += 1; |
| 138 stats.inserted += 1; |
|
| 139 }; |
130 }; |
| 140 |
131 |
| 141 if !within_tolerances && warn_insertions { |
132 if !within_tolerances && warn_insertions { |
| 142 // Complain (but continue) if we failed to get within tolerances |
133 // Complain (but continue) if we failed to get within tolerances |
| 143 // by inserting more points. |
134 // by inserting more points. |
| 154 fn merge_spikes( |
145 fn merge_spikes( |
| 155 &self, |
146 &self, |
| 156 μ: &mut DiscreteMeasure<Domain, F>, |
147 μ: &mut DiscreteMeasure<Domain, F>, |
| 157 τv: &mut M, |
148 τv: &mut M, |
| 158 μ_base: &DiscreteMeasure<Domain, F>, |
149 μ_base: &DiscreteMeasure<Domain, F>, |
| 159 ν_delta: Option<&DiscreteMeasure<Domain, F>>, |
|
| 160 τ: F, |
150 τ: F, |
| 161 ε: F, |
151 ε: F, |
| 162 config: &InsertionConfig<F>, |
152 config: &InsertionConfig<F>, |
| 163 reg: &Reg, |
153 reg: &Reg, |
| 164 fitness: Option<impl Fn(&DiscreteMeasure<Domain, F>) -> F>, |
154 fitness: Option<impl Fn(&DiscreteMeasure<Domain, F>) -> F>, |
| 167 if let Some(f) = fitness { |
157 if let Some(f) = fitness { |
| 168 return μ.merge_spikes_fitness(config.merging, f, |&v| v).1; |
158 return μ.merge_spikes_fitness(config.merging, f, |&v| v).1; |
| 169 } |
159 } |
| 170 } |
160 } |
| 171 μ.merge_spikes(config.merging, |μ_candidate| { |
161 μ.merge_spikes(config.merging, |μ_candidate| { |
| 172 let mut d = &*τv |
162 let mut d = &*τv + self.preapply(μ_candidate.sub_matching(μ_base)); |
| 173 + self.preapply(match ν_delta { |
|
| 174 None => μ_candidate.sub_matching(μ_base), |
|
| 175 Some(ν) => μ_candidate.sub_matching(μ_base) - ν, |
|
| 176 }); |
|
| 177 reg.verify_merge_candidate(&mut d, μ_candidate, τ, ε, config) |
163 reg.verify_merge_candidate(&mut d, μ_candidate, τ, ε, config) |
| 178 }) |
164 }) |
| 179 } |
165 } |
| 180 } |
166 } |
| 181 |
167 |