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; |
4 use std::marker::PhantomData; |
5 use std::sync::Arc; |
5 use std::sync::Arc; |
6 use crate::types::Float; |
6 use crate::types::Float; |
7 use crate::mapping::{Apply, Mapping}; |
7 use crate::mapping::{ |
|
8 Instance, Mapping, DifferentiableImpl, DifferentiableMapping, Space, |
|
9 BasicDecomposition, |
|
10 }; |
8 //use crate::linops::{Apply, Linear}; |
11 //use crate::linops::{Apply, Linear}; |
9 use crate::sets::Set; |
12 use crate::sets::Set; |
10 use crate::sets::Cube; |
13 use crate::sets::Cube; |
11 use crate::loc::Loc; |
14 use crate::loc::Loc; |
12 use super::support::*; |
15 use super::support::*; |
38 generator : Arc<G>, |
41 generator : Arc<G>, |
39 _phantoms : PhantomData<F>, |
42 _phantoms : PhantomData<F>, |
40 } |
43 } |
41 |
44 |
42 impl<F : Float, G, BT, const N : usize> |
45 impl<F : Float, G, BT, const N : usize> |
|
46 Space for BTFN<F, G, BT, N> |
|
47 where |
|
48 G : SupportGenerator<F, N, Id=BT::Data>, |
|
49 G::SupportType : LocalAnalysis<F, BT::Agg, N>, |
|
50 BT : BTImpl<F, N> |
|
51 { |
|
52 type Decomp = BasicDecomposition; |
|
53 } |
|
54 |
|
55 impl<F : Float, G, BT, const N : usize> |
43 BTFN<F, G, BT, N> |
56 BTFN<F, G, BT, N> |
44 where G : SupportGenerator<F, N, Id=BT::Data>, |
57 where |
45 G::SupportType : LocalAnalysis<F, BT::Agg, N>, |
58 G : SupportGenerator<F, N, Id=BT::Data>, |
46 BT : BTImpl<F, N> { |
59 G::SupportType : LocalAnalysis<F, BT::Agg, N>, |
|
60 BT : BTImpl<F, N> |
|
61 { |
47 |
62 |
48 /// Create a new BTFN from a support generator and a pre-initialised bisection tree. |
63 /// Create a new BTFN from a support generator and a pre-initialised bisection tree. |
49 /// |
64 /// |
50 /// The bisection tree `bt` should be pre-initialised to correspond to the `generator`. |
65 /// 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`] |
66 /// Use [`Self::construct`] if no preinitialised tree is available. Use [`Self::new_refresh`] |
384 } |
399 } |
385 } |
400 } |
386 |
401 |
387 make_btfn_unaryop!(Neg, neg); |
402 make_btfn_unaryop!(Neg, neg); |
388 |
403 |
389 |
|
390 |
|
391 // |
404 // |
392 // Mapping |
405 // Apply, Mapping, Differentiate |
393 // |
406 // |
394 |
407 |
395 impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>> |
408 impl<F : Float, G, BT, V, const N : usize> Mapping<Loc<F, N>> |
396 for BTFN<F, G, BT, N> |
409 for BTFN<F, G, BT, N> |
397 where BT : BTImpl<F, N>, |
410 where |
398 G : SupportGenerator<F, N, Id=BT::Data>, |
411 BT : BTImpl<F, N>, |
399 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<&'a Loc<F, N>, Output = V>, |
412 G : SupportGenerator<F, N, Id=BT::Data>, |
400 V : Sum { |
413 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Mapping<Loc<F, N>, Codomain = V>, |
401 |
414 V : Sum + Space, |
402 type Output = V; |
415 { |
403 |
416 |
404 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { |
417 type Codomain = V; |
405 self.bt.iter_at(x) |
418 |
406 .map(|&d| self.generator.support_for(d).apply(x)).sum() |
419 fn apply<I : Instance<Loc<F,N>>>(&self, x : I) -> Self::Codomain { |
407 } |
420 let xc = x.cow(); |
408 } |
421 self.bt.iter_at(&*xc) |
409 |
422 .map(|&d| self.generator.support_for(d).apply(&*xc)).sum() |
410 impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>> |
423 } |
|
424 } |
|
425 |
|
426 impl<F : Float, G, BT, V, const N : usize> DifferentiableImpl<Loc<F, N>> |
411 for BTFN<F, G, BT, N> |
427 for BTFN<F, G, BT, N> |
412 where BT : BTImpl<F, N>, |
428 where |
413 G : SupportGenerator<F, N, Id=BT::Data>, |
429 BT : BTImpl<F, N>, |
414 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<Loc<F, N>, Output = V>, |
430 G : SupportGenerator<F, N, Id=BT::Data>, |
415 V : Sum { |
431 G::SupportType : LocalAnalysis<F, BT::Agg, N> |
416 |
432 + DifferentiableMapping<Loc<F, N>, DerivativeDomain = V>, |
417 type Output = V; |
433 V : Sum + Space, |
418 |
434 { |
419 fn apply(&self, x : Loc<F, N>) -> Self::Output { |
435 |
420 self.bt.iter_at(&x) |
436 type Derivative = V; |
421 .map(|&d| self.generator.support_for(d).apply(x)).sum() |
437 |
422 } |
438 fn differential_impl<I : Instance<Loc<F, N>>>(&self, x :I) -> Self::Derivative { |
423 } |
439 let xc = x.cow(); |
|
440 self.bt.iter_at(&*xc) |
|
441 .map(|&d| self.generator.support_for(d).differential(&*xc)) |
|
442 .sum() |
|
443 } |
|
444 } |
|
445 |
|
446 // |
|
447 // GlobalAnalysis |
|
448 // |
424 |
449 |
425 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg> |
450 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg> |
426 for BTFN<F, G, BT, N> |
451 for BTFN<F, G, BT, N> |
427 where BT : BTImpl<F, N>, |
452 where BT : BTImpl<F, N>, |
428 G : SupportGenerator<F, N, Id=BT::Data>, |
453 G : SupportGenerator<F, N, Id=BT::Data>, |
478 |
503 |
479 /// Helper trait for performing approximate minimisation using P2 elements. |
504 /// Helper trait for performing approximate minimisation using P2 elements. |
480 /// |
505 /// |
481 /// `U` is the domain, generally [`Loc`]`<F, N>`, and `F` the type of floating point numbers. |
506 /// `U` is the domain, generally [`Loc`]`<F, N>`, and `F` the type of floating point numbers. |
482 /// `Self` is generally a set of `U`, for example, [`Cube`]`<F, N>`. |
507 /// `Self` is generally a set of `U`, for example, [`Cube`]`<F, N>`. |
483 pub trait P2Minimise<U, F : Float> : Set<U> { |
508 pub trait P2Minimise<U : Space, F : Float> : Set<U> { |
484 /// Minimise `g` over the set presented by `Self`. |
509 /// Minimise `g` over the set presented by `Self`. |
485 /// |
510 /// |
486 /// The function returns `(x, v)` where `x` is the minimiser `v` an approximation of `g(x)`. |
511 /// The function returns `(x, v)` where `x` is the minimiser `v` an approximation of `g(x)`. |
487 fn p2_minimise<G : Fn(&U) -> F>(&self, g : G) -> (U, F); |
512 fn p2_minimise<G : Fn(&U) -> F>(&self, g : G) -> (U, F); |
488 |
513 |
804 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, |
829 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, |
805 // the queue may run out, and we get “Refiner failure”. |
830 // the queue may run out, and we get “Refiner failure”. |
806 impl<F : Float, G, BT, const N : usize> BTFN<F, G, BT, N> |
831 impl<F : Float, G, BT, const N : usize> BTFN<F, G, BT, N> |
807 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
832 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
808 G : SupportGenerator<F, N, Id=BT::Data>, |
833 G : SupportGenerator<F, N, Id=BT::Data>, |
809 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
834 G::SupportType : Mapping<Loc<F, N>, Codomain=F> |
810 + LocalAnalysis<F, Bounds<F>, N>, |
835 + LocalAnalysis<F, Bounds<F>, N>, |
811 Cube<F, N> : P2Minimise<Loc<F, N>, F> { |
836 Cube<F, N> : P2Minimise<Loc<F, N>, F> { |
812 |
837 |
813 /// Maximise the `BTFN` within stated value `tolerance`. |
838 /// Maximise the `BTFN` within stated value `tolerance`. |
814 /// |
839 /// |