| 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 /// |