| 1 | 1 | 
| 2 /*! | 2 /*! | 
| 3 Traits for representing the support of a [`Apply`], and analysing the mapping on a [`Cube`]. | 3 Traits for representing the support of a [`Mapping`], and analysing the mapping on a [`Cube`]. | 
| 4 */ | 4 */ | 
| 5 use serde::Serialize; | 5 use serde::Serialize; | 
| 6 use std::ops::{MulAssign,DivAssign,Neg}; | 6 use std::ops::{MulAssign,DivAssign,Neg}; | 
| 7 use crate::types::{Float, Num}; | 7 use crate::types::{Float, Num}; | 
| 8 use crate::maputil::map2; | 8 use crate::maputil::map2; | 
| 13 use crate::loc::Loc; | 13 use crate::loc::Loc; | 
| 14 use super::aggregator::Bounds; | 14 use super::aggregator::Bounds; | 
| 15 use crate::norms::{Norm, L1, L2, Linfinity}; | 15 use crate::norms::{Norm, L1, L2, Linfinity}; | 
| 16 pub use crate::operator_arithmetic::{Weighted, Constant}; | 16 pub use crate::operator_arithmetic::{Weighted, Constant}; | 
| 17 | 17 | 
| 18 /// A trait for working with the supports of [`Apply`]s. | 18 /// A trait for working with the supports of [`Mapping`]s. | 
| 19 /// | 19 /// | 
| 20 /// Apply is not a super-trait to allow more general use. | 20 /// `Mapping` is not a super-trait to allow more general use. | 
| 21 pub trait Support<F : Num, const N : usize> : Sized + Sync + Send + 'static { | 21 pub trait Support<F : Num, const N : usize> : Sized + Sync + Send + 'static { | 
| 22     /// Return a cube containing the support of the function represented by `self`. | 22     /// Return a cube containing the support of the function represented by `self`. | 
| 23     /// | 23     /// | 
| 24     /// The hint may be larger than the actual support, but must contain it. | 24     /// The hint may be larger than the actual support, but must contain it. | 
| 25     fn support_hint(&self) -> Cube<F,N>; | 25     fn support_hint(&self) -> Cube<F,N>; | 
| 50     fn shift(self, x : Loc<F, N>) -> Shift<Self, F, N> { | 50     fn shift(self, x : Loc<F, N>) -> Shift<Self, F, N> { | 
| 51         Shift { shift : x, base_fn : self } | 51         Shift { shift : x, base_fn : self } | 
| 52     } | 52     } | 
| 53 } | 53 } | 
| 54 | 54 | 
| 55 /// Trait for globally analysing a property `A` of a [`Apply`]. | 55 /// Trait for globally analysing a property `A` of a [`Mapping`]. | 
| 56 /// | 56 /// | 
| 57 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as | 57 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as | 
| 58 /// [`Bounds`][super::aggregator::Bounds]. | 58 /// [`Bounds`][super::aggregator::Bounds]. | 
| 59 pub trait GlobalAnalysis<F : Num, A> { | 59 pub trait GlobalAnalysis<F : Num, A> { | 
| 60     /// Perform global analysis of the property `A` of `Self`. | 60     /// Perform global analysis of the property `A` of `Self`. | 
| 71 //     fn global_analysis(&self) -> Bounds<F> { | 71 //     fn global_analysis(&self) -> Bounds<F> { | 
| 72 //         self.local_analysis(&self.support_hint()) | 72 //         self.local_analysis(&self.support_hint()) | 
| 73 //     } | 73 //     } | 
| 74 // } | 74 // } | 
| 75 | 75 | 
| 76 /// Trait for locally analysing a property `A` of a [`Apply`] (implementing [`Support`]) | 76 /// Trait for locally analysing a property `A` of a [`Mapping`] (implementing [`Support`]) | 
| 77 /// within a [`Cube`]. | 77 /// within a [`Cube`]. | 
| 78 /// | 78 /// | 
| 79 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as | 79 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as | 
| 80 /// [`Bounds`][super::aggregator::Bounds]. | 80 /// [`Bounds`][super::aggregator::Bounds]. | 
| 81 pub trait LocalAnalysis<F : Num, A, const N : usize> : GlobalAnalysis<F, A> + Support<F, N> { | 81 pub trait LocalAnalysis<F : Num, A, const N : usize> : GlobalAnalysis<F, A> + Support<F, N> { | 
| 85     /// this function will return upper and lower bounds within `cube` for the mapping | 85     /// this function will return upper and lower bounds within `cube` for the mapping | 
| 86     /// represented by `self`. | 86     /// represented by `self`. | 
| 87     fn local_analysis(&self, cube : &Cube<F, N>) -> A; | 87     fn local_analysis(&self, cube : &Cube<F, N>) -> A; | 
| 88 } | 88 } | 
| 89 | 89 | 
| 90 /// Trait for determining the upper and lower bounds of an float-valued [`Apply`]. | 90 /// Trait for determining the upper and lower bounds of an float-valued [`Mapping`]. | 
| 91 /// | 91 /// | 
| 92 /// This is a blanket-implemented alias for [`GlobalAnalysis`]`<F, Bounds<F>>` | 92 /// This is a blanket-implemented alias for [`GlobalAnalysis`]`<F, Bounds<F>>` | 
| 93 /// [`Apply`] is not a supertrait to allow flexibility in the implementation of either | 93 /// [`Mapping`] is not a supertrait to allow flexibility in the implementation of either | 
| 94 /// reference or non-reference arguments. | 94 /// reference or non-reference arguments. | 
| 95 pub trait Bounded<F : Float> : GlobalAnalysis<F, Bounds<F>> { | 95 pub trait Bounded<F : Float> : GlobalAnalysis<F, Bounds<F>> { | 
| 96     /// Return lower and upper bounds for the values of of `self`. | 96     /// Return lower and upper bounds for the values of of `self`. | 
| 97     #[inline] | 97     #[inline] | 
| 98     fn bounds(&self) -> Bounds<F> { | 98     fn bounds(&self) -> Bounds<F> { | 
| 100     } | 100     } | 
| 101 } | 101 } | 
| 102 | 102 | 
| 103 impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { } | 103 impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { } | 
| 104 | 104 | 
| 105 /// Shift of [`Support`] and [`Apply`]; output of [`Support::shift`]. | 105 /// Shift of [`Support`] and [`Mapping`]; output of [`Support::shift`]. | 
| 106 #[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc. | 106 #[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc. | 
| 107 pub struct Shift<T, F, const N : usize> { | 107 pub struct Shift<T, F, const N : usize> { | 
| 108     shift : Loc<F, N>, | 108     shift : Loc<F, N>, | 
| 109     base_fn : T, | 109     base_fn : T, | 
| 110 } | 110 } | 
| 281 } | 281 } | 
| 282 | 282 | 
| 283 impl_weighted_norm!(L1 L2 Linfinity); | 283 impl_weighted_norm!(L1 L2 Linfinity); | 
| 284 | 284 | 
| 285 | 285 | 
| 286 /// Normalisation of [`Support`] and [`Apply`] to L¹ norm 1. | 286 /// Normalisation of [`Support`] and [`Mapping`] to L¹ norm 1. | 
| 287 /// | 287 /// | 
| 288 /// Currently only scalar-valued functions are supported. | 288 /// Currently only scalar-valued functions are supported. | 
| 289 #[derive(Copy, Clone, Debug, Serialize, PartialEq)] | 289 #[derive(Copy, Clone, Debug, Serialize, PartialEq)] | 
| 290 pub struct Normalised<T>( | 290 pub struct Normalised<T>( | 
| 291     /// The base [`Support`] or [`Apply`]. | 291     /// The base [`Support`] or [`Mapping`]. | 
| 292     pub T | 292     pub T | 
| 293 ); | 293 ); | 
| 294 | 294 | 
| 295 impl<'a, T, F : Float, const N : usize> Mapping<Loc<F, N>> for Normalised<T> | 295 impl<'a, T, F : Float, const N : usize> Mapping<Loc<F, N>> for Normalised<T> | 
| 296 where T : Norm<F, L1> + Mapping<Loc<F,N>, Codomain=F> { | 296 where T : Norm<F, L1> + Mapping<Loc<F,N>, Codomain=F> { | 
| 390 /// [ids][`Self::Id`]. | 390 /// [ids][`Self::Id`]. | 
| 391 pub trait SupportGenerator<F : Float, const N : usize> | 391 pub trait SupportGenerator<F : Float, const N : usize> | 
| 392 : MulAssign<F> + DivAssign<F> + Neg<Output=Self> + Clone + Sync + Send + 'static { | 392 : MulAssign<F> + DivAssign<F> + Neg<Output=Self> + Clone + Sync + Send + 'static { | 
| 393     /// The identification type | 393     /// The identification type | 
| 394     type Id : 'static + Copy; | 394     type Id : 'static + Copy; | 
| 395     /// The type of the [`Support`] (often also a [`Apply`]). | 395     /// The type of the [`Support`] (often also a [`Mapping`]). | 
| 396     type SupportType : 'static + Support<F, N>; | 396     type SupportType : 'static + Support<F, N>; | 
| 397     /// An iterator over all the [`Support`]s of the generator. | 397     /// An iterator over all the [`Support`]s of the generator. | 
| 398     type AllDataIter<'a> : Iterator<Item=(Self::Id, Self::SupportType)> where Self : 'a; | 398     type AllDataIter<'a> : Iterator<Item=(Self::Id, Self::SupportType)> where Self : 'a; | 
| 399 | 399 | 
| 400     /// Returns the component identified by `id`. | 400     /// Returns the component identified by `id`. |