src/bisection_tree/btfn.rs

branch
dev
changeset 81
d2acaaddd9af
parent 47
a0db98c16ab5
equal deleted inserted replaced
49:edb95d2b83cc 81:d2acaaddd9af
1 1
2 use numeric_literals::replace_float_literals; 2 use numeric_literals::replace_float_literals;
3 use std::iter::Sum; 3 use std::iter::Sum;
4 use std::marker::PhantomData;
5 use std::sync::Arc; 4 use std::sync::Arc;
6 use crate::types::Float; 5 use crate::types::{Float, HasScalarField, HasRealField};
7 use crate::mapping::{Apply, Mapping, Differentiable}; 6 use crate::mapping::{Apply, Mapping, Differentiable};
8 //use crate::linops::{Apply, Linear}; 7 //use crate::linops::{Apply, Linear};
9 use crate::sets::Set; 8 use crate::sets::Set;
10 use crate::sets::Cube; 9 use crate::sets::Cube;
11 use crate::loc::Loc; 10 use crate::loc::Loc;
27 /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored 26 /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored
28 /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()` 27 /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()`
29 /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. 28 /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`].
30 #[derive(Clone,Debug)] 29 #[derive(Clone,Debug)]
31 pub struct BTFN< 30 pub struct BTFN<
32 F : Float, 31 G : SupportGenerator<N>,
33 G : SupportGenerator<F, N>,
34 BT /*: BTImpl<F, N>*/, 32 BT /*: BTImpl<F, N>*/,
35 const N : usize 33 const N : usize
36 > /*where G::SupportType : LocalAnalysis<F, A, N>*/ { 34 > {
37 bt : BT, 35 bt : BT,
38 generator : Arc<G>, 36 generator : Arc<G>,
39 _phantoms : PhantomData<F>, 37 }
38
39 impl<G : SupportGenerator<N>, BT, const N : usize> HasScalarField for BTFN<G, BT, N> {
40 type Field = G::Field;
40 } 41 }
41 42
42 impl<F : Float, G, BT, const N : usize> 43 impl<F : Float, G, BT, const N : usize>
43 BTFN<F, G, BT, N> 44 BTFN<G, BT, N>
44 where G : SupportGenerator<F, N, Id=BT::Data>, 45 where G : SupportGenerator<N, RealField = F>,
45 G::SupportType : LocalAnalysis<F, BT::Agg, N>, 46 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>,
46 BT : BTImpl<F, N> { 47 BT : BTImpl<F, N, Data=G::Id> {
47 48
48 /// Create a new BTFN from a support generator and a pre-initialised bisection tree. 49 /// Create a new BTFN from a support generator and a pre-initialised bisection tree.
49 /// 50 ///
50 /// The bisection tree `bt` should be pre-initialised to correspond to the `generator`. 51 /// The bisection tree `bt` should be pre-initialised to correspond to the `generator`.
51 /// Use [`Self::construct`] if no preinitialised tree is available. Use [`Self::new_refresh`] 52 /// Use [`Self::construct`] if no preinitialised tree is available. Use [`Self::new_refresh`]
58 59
59 fn new_arc(bt : BT, generator : Arc<G>) -> Self { 60 fn new_arc(bt : BT, generator : Arc<G>) -> Self {
60 BTFN { 61 BTFN {
61 bt : bt, 62 bt : bt,
62 generator : generator, 63 generator : generator,
63 _phantoms : std::marker::PhantomData,
64 } 64 }
65 } 65 }
66 66
67 /// Create a new BTFN support generator and a pre-initialised bisection tree, 67 /// Create a new BTFN support generator and a pre-initialised bisection tree,
68 /// cloning the tree and refreshing aggregators. 68 /// cloning the tree and refreshing aggregators.
83 /// Create a new BTFN from a support generator, domain, and depth for a new [`BT`]. 83 /// Create a new BTFN from a support generator, domain, and depth for a new [`BT`].
84 /// 84 ///
85 /// The top node of the created [`BT`] will have the given `domain`. 85 /// The top node of the created [`BT`] will have the given `domain`.
86 /// 86 ///
87 /// See the documentation for [`BTFN`] on the role of the `generator`. 87 /// See the documentation for [`BTFN`] on the role of the `generator`.
88 pub fn construct(domain : Cube<F, N>, depth : BT::Depth, generator : G) -> Self { 88 pub fn construct(domain : Cube<G::Field, N>, depth : BT::Depth, generator : G) -> Self {
89 Self::construct_arc(domain, depth, Arc::new(generator)) 89 Self::construct_arc(domain, depth, Arc::new(generator))
90 } 90 }
91 91
92 fn construct_arc(domain : Cube<F, N>, depth : BT::Depth, generator : Arc<G>) -> Self { 92 fn construct_arc(domain : Cube<G::Field, N>, depth : BT::Depth, generator : Arc<G>) -> Self {
93 let mut bt = BT::new(domain, depth); 93 let mut bt = BT::new(domain, depth);
94 for (d, support) in generator.all_data() { 94 for (d, support) in generator.all_data() {
95 bt.insert(d, &support); 95 bt.insert(d, &support);
96 } 96 }
97 Self::new_arc(bt, generator) 97 Self::new_arc(bt, generator)
99 99
100 /// Convert the aggregator of the [`BTFN`] to a different one. 100 /// Convert the aggregator of the [`BTFN`] to a different one.
101 /// 101 ///
102 /// This will construct a [`BTFN`] with the same components and generator as the (consumed) 102 /// This will construct a [`BTFN`] with the same components and generator as the (consumed)
103 /// `self`, but a new `BT` with [`Aggregator`]s of type `ANew`. 103 /// `self`, but a new `BT` with [`Aggregator`]s of type `ANew`.
104 pub fn convert_aggregator<ANew>(self) -> BTFN<F, G, BT::Converted<ANew>, N> 104 pub fn convert_aggregator<ANew>(self) -> BTFN<G, BT::Converted<ANew>, N>
105 where ANew : Aggregator, 105 where ANew : Aggregator,
106 G : SupportGenerator<F, N, Id=BT::Data>, 106 G : SupportGenerator<N>,
107 G::SupportType : LocalAnalysis<F, ANew, N> { 107 G::SupportType : LocalAnalysis<ANew, Cube<G::RealField, N>> {
108 BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) 108 BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator)
109 } 109 }
110 110
111 /// Change the generator (after, e.g., a scaling of the latter). 111 /// Change the generator (after, e.g., a scaling of the latter).
112 fn new_generator(&self, generator : G) -> Self { 112 fn new_generator(&self, generator : G) -> Self {
119 } 119 }
120 120
121 } 121 }
122 122
123 impl<F : Float, G, BT, const N : usize> 123 impl<F : Float, G, BT, const N : usize>
124 BTFN<F, G, BT, N> 124 BTFN<G, BT, N>
125 where G : SupportGenerator<F, N> { 125 where G : SupportGenerator<N, RealField = F> {
126 /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one. 126 /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one.
127 /// 127 ///
128 /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change 128 /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change
129 /// the aggreagator; see also [`self.convert_aggregator`]. 129 /// the aggreagator; see also [`self.convert_aggregator`].
130 pub fn instantiate< 130 pub fn instantiate<
131 BTNew : BTImpl<F, N, Data=G::Id>, 131 BTNew : BTImpl<F, N, Data=G::Id>,
132 > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<F, G, BTNew, N> 132 > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<G, BTNew, N>
133 where G::SupportType : LocalAnalysis<F, BTNew::Agg, N> { 133 where G::SupportType : LocalAnalysis<BTNew::Agg, Cube<F, N>> {
134 BTFN::construct_arc(domain, depth, self.generator) 134 BTFN::construct_arc(domain, depth, self.generator)
135 } 135 }
136 } 136 }
137 137
138 /// A BTFN with no bisection tree. 138 /// A BTFN with no bisection tree.
139 /// 139 ///
140 /// Most BTFN methods are not available, but if a BTFN is going to be summed with another 140 /// Most BTFN methods are not available, but if a BTFN is going to be summed with another
141 /// before other use, it will be more efficient to not construct an unnecessary bisection tree 141 /// before other use, it will be more efficient to not construct an unnecessary bisection tree
142 /// that would be shortly dropped. 142 /// that would be shortly dropped.
143 pub type PreBTFN<F, G, const N : usize> = BTFN<F, G, (), N>; 143 pub type PreBTFN<G, const N : usize> = BTFN<G, (), N>;
144 144
145 impl<F : Float, G, const N : usize> PreBTFN<F, G, N> where G : SupportGenerator<F, N> { 145 impl<G, const N : usize> PreBTFN<G, N> where G : SupportGenerator<N> {
146 146
147 /// Create a new [`PreBTFN`] with no bisection tree. 147 /// Create a new [`PreBTFN`] with no bisection tree.
148 pub fn new_pre(generator : G) -> Self { 148 pub fn new_pre(generator : G) -> Self {
149 BTFN { 149 BTFN {
150 bt : (), 150 bt : (),
151 generator : Arc::new(generator), 151 generator : Arc::new(generator),
152 _phantoms : std::marker::PhantomData,
153 } 152 }
154 } 153 }
155 } 154 }
156 155
157 impl<F : Float, G, BT, const N : usize> 156 impl<F : Float, G, BT, const N : usize>
158 BTFN<F, G, BT, N> 157 BTFN<G, BT, N>
159 where G : SupportGenerator<F, N, Id=usize>, 158 where G : SupportGenerator<N, Id=usize, RealField = F>,
160 G::SupportType : LocalAnalysis<F, BT::Agg, N>, 159 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>,
161 BT : BTImpl<F, N, Data=usize> { 160 BT : BTImpl<F, N, Data=usize> {
162 161
163 /// Helper function for implementing [`std::ops::Add`]. 162 /// Helper function for implementing [`std::ops::Add`].
164 fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<F, BothGenerators<G, G2>, BT, N> 163 fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<BothGenerators<G, G2>, BT, N>
165 where G2 : SupportGenerator<F, N, Id=usize>, 164 where G2 : SupportGenerator<N, Id=usize, RealField = F>,
166 G2::SupportType : LocalAnalysis<F, BT::Agg, N> { 165 G2::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> {
167 166
168 let mut bt = self.bt.clone(); 167 let mut bt = self.bt.clone();
169 let both = BothGenerators(Arc::clone(&self.generator), g2); 168 let both = BothGenerators(Arc::clone(&self.generator), g2);
170 169
171 for (d, support) in both.all_right_data() { 170 for (d, support) in both.all_right_data() {
173 } 172 }
174 173
175 BTFN { 174 BTFN {
176 bt : bt, 175 bt : bt,
177 generator : Arc::new(both), 176 generator : Arc::new(both),
178 _phantoms : std::marker::PhantomData,
179 } 177 }
180 } 178 }
181 } 179 }
182 180
183 macro_rules! make_btfn_add { 181 macro_rules! make_btfn_add {
184 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { 182 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => {
185 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> 183 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize>
186 std::ops::Add<BTFN<F, G2, BT2, N>> for 184 std::ops::Add<BTFN<G2, BT2, N>> for
187 $lhs 185 $lhs
188 where BT1 : BTImpl<F, N, Data=usize>, 186 where BT1 : BTImpl<F, N, Data=usize>,
189 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, 187 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?,
190 G2 : SupportGenerator<F, N, Id=usize>, 188 G2 : SupportGenerator<N, Id=usize, RealField = F>,
191 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, 189 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>,
192 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { 190 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> {
193 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; 191 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>;
194 #[inline] 192 #[inline]
195 fn add(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { 193 fn add(self, other : BTFN<G2, BT2, N>) -> Self::Output {
196 $preprocess(self).add_another(other.generator) 194 $preprocess(self).add_another(other.generator)
197 } 195 }
198 } 196 }
199 197
200 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> 198 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize>
201 std::ops::Add<&'b BTFN<F, G2, BT2, N>> for 199 std::ops::Add<&'b BTFN<G2, BT2, N>> for
202 $lhs 200 $lhs
203 where BT1 : BTImpl<F, N, Data=usize>, 201 where BT1 : BTImpl<F, N, Data=usize>,
204 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, 202 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?,
205 G2 : SupportGenerator<F, N, Id=usize>, 203 G2 : SupportGenerator<N, Id=usize, RealField = F>,
206 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, 204 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>,
207 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { 205 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> {
208 206
209 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; 207 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>;
210 #[inline] 208 #[inline]
211 fn add(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { 209 fn add(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output {
212 $preprocess(self).add_another(other.generator.clone()) 210 $preprocess(self).add_another(other.generator.clone())
213 } 211 }
214 } 212 }
215 } 213 }
216 } 214 }
217 215
218 make_btfn_add!(BTFN<F, G1, BT1, N>, std::convert::identity, ); 216 make_btfn_add!(BTFN<G1, BT1, N>, std::convert::identity, );
219 make_btfn_add!(&'a BTFN<F, G1, BT1, N>, Clone::clone, ); 217 make_btfn_add!(&'a BTFN<G1, BT1, N>, Clone::clone, );
220 218
221 macro_rules! make_btfn_sub { 219 macro_rules! make_btfn_sub {
222 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { 220 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => {
223 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> 221 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize>
224 std::ops::Sub<BTFN<F, G2, BT2, N>> for 222 std::ops::Sub<BTFN<G2, BT2, N>> for
225 $lhs 223 $lhs
226 where BT1 : BTImpl<F, N, Data=usize>, 224 where BT1 : BTImpl<F, N, Data=usize>,
227 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, 225 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?,
228 G2 : SupportGenerator<F, N, Id=usize>, 226 G2 : SupportGenerator<N, Id=usize, RealField = F>,
229 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, 227 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>,
230 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { 228 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> {
231 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; 229 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>;
232 #[inline] 230 #[inline]
233 fn sub(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { 231 fn sub(self, other : BTFN<G2, BT2, N>) -> Self::Output {
234 $preprocess(self).add_another(Arc::new( 232 $preprocess(self).add_another(Arc::new(
235 Arc::try_unwrap(other.generator) 233 Arc::try_unwrap(other.generator)
236 .unwrap_or_else(|arc| (*arc).clone()) 234 .unwrap_or_else(|arc| (*arc).clone())
237 .neg() 235 .neg()
238 )) 236 ))
239 } 237 }
240 } 238 }
241 239
242 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> 240 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize>
243 std::ops::Sub<&'b BTFN<F, G2, BT2, N>> for 241 std::ops::Sub<&'b BTFN<G2, BT2, N>> for
244 $lhs 242 $lhs
245 where BT1 : BTImpl<F, N, Data=usize>, 243 where BT1 : BTImpl<F, N, Data=usize>,
246 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, 244 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?,
247 G2 : SupportGenerator<F, N, Id=usize> + Clone, 245 G2 : SupportGenerator<N, Id=usize, RealField = F> + Clone,
248 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, 246 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>,
249 G2::SupportType : LocalAnalysis<F, BT1::Agg, N>, 247 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>,
250 &'b G2 : std::ops::Neg<Output=G2> { 248 &'b G2 : std::ops::Neg<Output=G2> {
251 249
252 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; 250 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>;
253 #[inline] 251 #[inline]
254 fn sub(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { 252 fn sub(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output {
255 $preprocess(self).add_another(Arc::new((*other.generator).clone().neg())) 253 $preprocess(self).add_another(Arc::new((*other.generator).clone().neg()))
256 } 254 }
257 } 255 }
258 } 256 }
259 } 257 }
260 258
261 make_btfn_sub!(BTFN<F, G1, BT1, N>, std::convert::identity, ); 259 make_btfn_sub!(BTFN<G1, BT1, N>, std::convert::identity, );
262 make_btfn_sub!(&'a BTFN<F, G1, BT1, N>, std::convert::identity, ); 260 make_btfn_sub!(&'a BTFN<G1, BT1, N>, std::convert::identity, );
263 261
264 macro_rules! make_btfn_scalarop_rhs { 262 macro_rules! make_btfn_scalarop_rhs {
265 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { 263 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => {
266 impl<F : Float, G, BT, const N : usize> 264 impl<F : Float, G, BT, const N : usize>
267 std::ops::$trait_assign<F> 265 std::ops::$trait_assign<F>
268 for BTFN<F, G, BT, N> 266 for BTFN<G, BT, N>
269 where BT : BTImpl<F, N>, 267 where BT : BTImpl<F, N>,
270 G : SupportGenerator<F, N, Id=BT::Data>, 268 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
271 G::SupportType : LocalAnalysis<F, BT::Agg, N> { 269 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> {
272 #[inline] 270 #[inline]
273 fn $fn_assign(&mut self, t : F) { 271 fn $fn_assign(&mut self, t : F) {
274 Arc::make_mut(&mut self.generator).$fn_assign(t); 272 Arc::make_mut(&mut self.generator).$fn_assign(t);
275 self.refresh_aggregator(); 273 self.refresh_aggregator();
276 } 274 }
277 } 275 }
278 276
279 impl<F : Float, G, BT, const N : usize> 277 impl<F : Float, G, BT, const N : usize>
280 std::ops::$trait<F> 278 std::ops::$trait<F>
281 for BTFN<F, G, BT, N> 279 for BTFN<G, BT, N>
282 where BT : BTImpl<F, N>, 280 where BT : BTImpl<F, N>,
283 G : SupportGenerator<F, N, Id=BT::Data>, 281 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
284 G::SupportType : LocalAnalysis<F, BT::Agg, N> { 282 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> {
285 type Output = Self; 283 type Output = Self;
286 #[inline] 284 #[inline]
287 fn $fn(mut self, t : F) -> Self::Output { 285 fn $fn(mut self, t : F) -> Self::Output {
288 Arc::make_mut(&mut self.generator).$fn_assign(t); 286 Arc::make_mut(&mut self.generator).$fn_assign(t);
289 self.refresh_aggregator(); 287 self.refresh_aggregator();
291 } 289 }
292 } 290 }
293 291
294 impl<'a, F : Float, G, BT, const N : usize> 292 impl<'a, F : Float, G, BT, const N : usize>
295 std::ops::$trait<F> 293 std::ops::$trait<F>
296 for &'a BTFN<F, G, BT, N> 294 for &'a BTFN<G, BT, N>
297 where BT : BTImpl<F, N>, 295 where BT : BTImpl<F, N>,
298 G : SupportGenerator<F, N, Id=BT::Data>, 296 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
299 G::SupportType : LocalAnalysis<F, BT::Agg, N>, 297 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>,
300 &'a G : std::ops::$trait<F,Output=G> { 298 &'a G : std::ops::$trait<F,Output=G> {
301 type Output = BTFN<F, G, BT, N>; 299 type Output = BTFN<G, BT, N>;
302 #[inline] 300 #[inline]
303 fn $fn(self, t : F) -> Self::Output { 301 fn $fn(self, t : F) -> Self::Output {
304 self.new_generator(self.generator.$fn(t)) 302 self.new_generator(self.generator.$fn(t))
305 } 303 }
306 } 304 }
311 make_btfn_scalarop_rhs!(Div, div, DivAssign, div_assign); 309 make_btfn_scalarop_rhs!(Div, div, DivAssign, div_assign);
312 310
313 macro_rules! make_btfn_scalarop_lhs { 311 macro_rules! make_btfn_scalarop_lhs {
314 ($trait:ident, $fn:ident, $fn_assign:ident, $($f:ident)+) => { $( 312 ($trait:ident, $fn:ident, $fn_assign:ident, $($f:ident)+) => { $(
315 impl<G, BT, const N : usize> 313 impl<G, BT, const N : usize>
316 std::ops::$trait<BTFN<$f, G, BT, N>> 314 std::ops::$trait<BTFN<G, BT, N>>
317 for $f 315 for $f
318 where BT : BTImpl<$f, N>, 316 where BT : BTImpl<$f, N>,
319 G : SupportGenerator<$f, N, Id=BT::Data>, 317 G : SupportGenerator<N, Id=BT::Data, RealField = $f>,
320 G::SupportType : LocalAnalysis<$f, BT::Agg, N> { 318 G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>> {
321 type Output = BTFN<$f, G, BT, N>; 319 type Output = BTFN<G, BT, N>;
322 #[inline] 320 #[inline]
323 fn $fn(self, mut a : BTFN<$f, G, BT, N>) -> Self::Output { 321 fn $fn(self, mut a : BTFN<G, BT, N>) -> Self::Output {
324 Arc::make_mut(&mut a.generator).$fn_assign(self); 322 Arc::make_mut(&mut a.generator).$fn_assign(self);
325 a.refresh_aggregator(); 323 a.refresh_aggregator();
326 a 324 a
327 } 325 }
328 } 326 }
329 327
330 impl<'a, G, BT, const N : usize> 328 impl<'a, G, BT, const N : usize>
331 std::ops::$trait<&'a BTFN<$f, G, BT, N>> 329 std::ops::$trait<&'a BTFN<G, BT, N>>
332 for $f 330 for $f
333 where BT : BTImpl<$f, N>, 331 where BT : BTImpl<$f, N>,
334 G : SupportGenerator<$f, N, Id=BT::Data> + Clone, 332 G : SupportGenerator<N, Id=BT::Data, RealField = $f> + Clone,
335 G::SupportType : LocalAnalysis<$f, BT::Agg, N>, 333 G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>>,
336 // FIXME: This causes compiler overflow 334 // FIXME: This causes compiler overflow
337 /*&'a G : std::ops::$trait<$f,Output=G>*/ { 335 /*&'a G : std::ops::$trait<$f,Output=G>*/ {
338 type Output = BTFN<$f, G, BT, N>; 336 type Output = BTFN<G, BT, N>;
339 #[inline] 337 #[inline]
340 fn $fn(self, a : &'a BTFN<$f, G, BT, N>) -> Self::Output { 338 fn $fn(self, a : &'a BTFN<G, BT, N>) -> Self::Output {
341 let mut tmp = (*a.generator).clone(); 339 let mut tmp = (*a.generator).clone();
342 tmp.$fn_assign(self); 340 tmp.$fn_assign(self);
343 a.new_generator(tmp) 341 a.new_generator(tmp)
344 // FIXME: Prevented by the compiler overflow above. 342 // FIXME: Prevented by the compiler overflow above.
345 //a.new_generator(a.generator.$fn(a)) 343 //a.new_generator(a.generator.$fn(a))
353 351
354 macro_rules! make_btfn_unaryop { 352 macro_rules! make_btfn_unaryop {
355 ($trait:ident, $fn:ident) => { 353 ($trait:ident, $fn:ident) => {
356 impl<F : Float, G, BT, const N : usize> 354 impl<F : Float, G, BT, const N : usize>
357 std::ops::$trait 355 std::ops::$trait
358 for BTFN<F, G, BT, N> 356 for BTFN<G, BT, N>
359 where BT : BTImpl<F, N>, 357 where BT : BTImpl<F, N>,
360 G : SupportGenerator<F, N, Id=BT::Data>, 358 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
361 G::SupportType : LocalAnalysis<F, BT::Agg, N> { 359 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> {
362 type Output = Self; 360 type Output = Self;
363 #[inline] 361 #[inline]
364 fn $fn(mut self) -> Self::Output { 362 fn $fn(mut self) -> Self::Output {
365 self.generator = Arc::new(Arc::unwrap_or_clone(self.generator).$fn()); 363 self.generator = Arc::new(Arc::unwrap_or_clone(self.generator).$fn());
366 self.refresh_aggregator(); 364 self.refresh_aggregator();
389 // 387 //
390 // Apply, Mapping, Differentiate 388 // Apply, Mapping, Differentiate
391 // 389 //
392 390
393 impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>> 391 impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>>
394 for BTFN<F, G, BT, N> 392 for BTFN<G, BT, N>
395 where BT : BTImpl<F, N>, 393 where BT : BTImpl<F, N>,
396 G : SupportGenerator<F, N, Id=BT::Data>, 394 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
397 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<&'a Loc<F, N>, Output = V>, 395 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>
396 + Apply<&'a Loc<F, N>, Output = V>,
398 V : Sum { 397 V : Sum {
399 398
400 type Output = V; 399 type Output = V;
401 400
402 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { 401 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output {
404 .map(|&d| self.generator.support_for(d).apply(x)).sum() 403 .map(|&d| self.generator.support_for(d).apply(x)).sum()
405 } 404 }
406 } 405 }
407 406
408 impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>> 407 impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>>
409 for BTFN<F, G, BT, N> 408 for BTFN<G, BT, N>
410 where BT : BTImpl<F, N>, 409 where BT : BTImpl<F, N>,
411 G : SupportGenerator<F, N, Id=BT::Data>, 410 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
412 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<Loc<F, N>, Output = V>, 411 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>
412 + Apply<Loc<F, N>, Output = V>,
413 V : Sum { 413 V : Sum {
414 414
415 type Output = V; 415 type Output = V;
416 416
417 fn apply(&self, x : Loc<F, N>) -> Self::Output { 417 fn apply(&self, x : Loc<F, N>) -> Self::Output {
418 self.bt.iter_at(&x) 418 self.bt.iter_at(&x)
419 .map(|&d| self.generator.support_for(d).apply(x)).sum() 419 .map(|&d| self.generator.support_for(d).apply(x)).sum()
420 } 420 }
421 } 421 }
422 422
423 impl<'a, F : Float, G, BT, V, const N : usize> Differentiable<&'a Loc<F, N>> 423 impl<'a, F : Float, G, BT, V : HasRealField<RealField=F>, const N : usize>
424 for BTFN<F, G, BT, N> 424 Differentiable<&'a Loc<F, N>>
425 for BTFN<G, BT, N>
425 where BT : BTImpl<F, N>, 426 where BT : BTImpl<F, N>,
426 G : SupportGenerator<F, N, Id=BT::Data>, 427 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
427 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<&'a Loc<F, N>, Derivative = V>, 428 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>
429 + Differentiable<&'a Loc<F, N>, Derivative = V>,
428 V : Sum { 430 V : Sum {
429 431
430 type Derivative = V; 432 type Derivative = V;
431 433
432 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative { 434 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative {
435 .sum() 437 .sum()
436 } 438 }
437 } 439 }
438 440
439 impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>> 441 impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>>
440 for BTFN<F, G, BT, N> 442 for BTFN<G, BT, N>
441 where BT : BTImpl<F, N>, 443 where BT : BTImpl<F, N>,
442 G : SupportGenerator<F, N, Id=BT::Data>, 444 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
443 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<Loc<F, N>, Derivative = V>, 445 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>
444 V : Sum { 446 + Differentiable<Loc<F, N>, Derivative = V>,
447 V : Sum + HasRealField<RealField=F> {
445 448
446 type Derivative = V; 449 type Derivative = V;
447 450
448 fn differential(&self, x : Loc<F, N>) -> Self::Derivative { 451 fn differential(&self, x : Loc<F, N>) -> Self::Derivative {
449 self.bt.iter_at(&x) 452 self.bt.iter_at(&x)
454 457
455 // 458 //
456 // GlobalAnalysis 459 // GlobalAnalysis
457 // 460 //
458 461
459 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg> 462 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<BT::Agg>
460 for BTFN<F, G, BT, N> 463 for BTFN<G, BT, N>
461 where BT : BTImpl<F, N>, 464 where BT : BTImpl<F, N>,
462 G : SupportGenerator<F, N, Id=BT::Data>, 465 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
463 G::SupportType : LocalAnalysis<F, BT::Agg, N> { 466 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> {
464 467
465 #[inline] 468 #[inline]
466 fn global_analysis(&self) -> BT::Agg { 469 fn global_analysis(&self) -> BT::Agg {
467 self.bt.global_analysis() 470 self.bt.global_analysis()
468 } 471 }
615 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. 618 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes.
616 #[allow(dead_code)] // `how` is just for type system purposes. 619 #[allow(dead_code)] // `how` is just for type system purposes.
617 how : T, 620 how : T,
618 } 621 }
619 622
620 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> 623 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N>
621 for P2Refiner<F, RefineMax> 624 for P2Refiner<F, RefineMax>
622 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, 625 where Cube<F, N> : P2Minimise<Loc<F, N>, F>,
623 G : SupportGenerator<F, N>, 626 G : SupportGenerator<N, RealField = F>,
624 G::SupportType : Mapping<Loc<F, N>, Codomain=F> 627 G::SupportType : Mapping<Loc<F, N>, Codomain=F>
625 + LocalAnalysis<F, Bounds<F>, N> { 628 + LocalAnalysis<Bounds<F>, Cube<F, N>> {
626 type Result = Option<(Loc<F, N>, F)>; 629 type Result = Option<(Loc<F, N>, F)>;
627 type Sorting = UpperBoundSorting<F>; 630 type Sorting = UpperBoundSorting<F>;
628 631
629 fn refine( 632 fn refine(
630 &self, 633 &self,
672 } 675 }
673 } 676 }
674 } 677 }
675 678
676 679
677 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> 680 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N>
678 for P2Refiner<F, RefineMin> 681 for P2Refiner<F, RefineMin>
679 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, 682 where Cube<F, N> : P2Minimise<Loc<F, N>, F>,
680 G : SupportGenerator<F, N>, 683 G : SupportGenerator<N, RealField = F>,
681 G::SupportType : Mapping<Loc<F, N>, Codomain=F> 684 G::SupportType : Mapping<Loc<F, N>, Codomain=F>
682 + LocalAnalysis<F, Bounds<F>, N> { 685 + LocalAnalysis<Bounds<F>, Cube<F, N>> {
683 type Result = Option<(Loc<F, N>, F)>; 686 type Result = Option<(Loc<F, N>, F)>;
684 type Sorting = LowerBoundSorting<F>; 687 type Sorting = LowerBoundSorting<F>;
685 688
686 fn refine( 689 fn refine(
687 &self, 690 &self,
752 #[allow(dead_code)] // `how` is just for type system purposes. 755 #[allow(dead_code)] // `how` is just for type system purposes.
753 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. 756 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes.
754 how : T, 757 how : T,
755 } 758 }
756 759
757 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> 760 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N>
758 for BoundRefiner<F, RefineMax> 761 for BoundRefiner<F, RefineMax>
759 where G : SupportGenerator<F, N> { 762 where G : SupportGenerator<N, RealField = F> {
760 type Result = bool; 763 type Result = bool;
761 type Sorting = UpperBoundSorting<F>; 764 type Sorting = UpperBoundSorting<F>;
762 765
763 fn refine( 766 fn refine(
764 &self, 767 &self,
786 fn fuse_results(r1 : &mut Self::Result, r2 : Self::Result) { 789 fn fuse_results(r1 : &mut Self::Result, r2 : Self::Result) {
787 *r1 = *r1 && r2; 790 *r1 = *r1 && r2;
788 } 791 }
789 } 792 }
790 793
791 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> 794 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N>
792 for BoundRefiner<F, RefineMin> 795 for BoundRefiner<F, RefineMin>
793 where G : SupportGenerator<F, N> { 796 where G : SupportGenerator<N, RealField = F> {
794 type Result = bool; 797 type Result = bool;
795 type Sorting = UpperBoundSorting<F>; 798 type Sorting = UpperBoundSorting<F>;
796 799
797 fn refine( 800 fn refine(
798 &self, 801 &self,
835 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads 838 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads
836 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually 839 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually
837 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting 840 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting
838 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, 841 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`,
839 // the queue may run out, and we get “Refiner failure”. 842 // the queue may run out, and we get “Refiner failure”.
840 impl<F : Float, G, BT, const N : usize> BTFN<F, G, BT, N> 843 impl<F : Float, G, BT, const N : usize> BTFN<G, BT, N>
841 where BT : BTSearch<F, N, Agg=Bounds<F>>, 844 where BT : BTSearch<F, N, Agg=Bounds<F>>,
842 G : SupportGenerator<F, N, Id=BT::Data>, 845 G : SupportGenerator<N, Id=BT::Data, RealField = F>,
843 G::SupportType : Mapping<Loc<F, N>,Codomain=F> 846 G::SupportType : Mapping<Loc<F, N>,Codomain=F>
844 + LocalAnalysis<F, Bounds<F>, N>, 847 + LocalAnalysis<Bounds<F>, Cube<F, N>>,
845 Cube<F, N> : P2Minimise<Loc<F, N>, F> { 848 Cube<F, N> : P2Minimise<Loc<F, N>, F> {
846 849
847 /// Maximise the `BTFN` within stated value `tolerance`. 850 /// Maximise the `BTFN` within stated value `tolerance`.
848 /// 851 ///
849 /// At most `max_steps` refinement steps are taken. 852 /// At most `max_steps` refinement steps are taken.

mercurial