src/mapping.rs

branch
dev
changeset 99
9e5b9fc81c52
parent 75
e9f4550cfa18
child 102
aead46a19767
equal deleted inserted replaced
98:2e4517b55442 99:9e5b9fc81c52
1 /*! 1 /*!
2 Traits for mathematical functions. 2 Traits for mathematical functions.
3 */ 3 */
4 4
5 pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space};
6 use crate::loc::Loc;
7 use crate::norms::{Norm, NormExponent};
8 use crate::operator_arithmetic::{Constant, Weighted};
9 use crate::types::{ClosedMul, Float, Num};
10 use std::borrow::Cow;
5 use std::marker::PhantomData; 11 use std::marker::PhantomData;
6 use std::borrow::Cow;
7 use crate::types::{Num, Float, ClosedMul};
8 use crate::loc::Loc;
9 pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space};
10 use crate::norms::{Norm, NormExponent};
11 use crate::operator_arithmetic::{Weighted, Constant};
12 12
13 /// A mapping from `Domain` to `Self::Codomain`. 13 /// A mapping from `Domain` to `Self::Codomain`.
14 pub trait Mapping<Domain : Space> { 14 pub trait Mapping<Domain: Space> {
15 type Codomain : Space; 15 type Codomain: Space;
16 16
17 /// Compute the value of `self` at `x`. 17 /// Compute the value of `self` at `x`.
18 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain; 18 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain;
19 19
20 #[inline] 20 #[inline]
21 /// Form the composition `self ∘ other` 21 /// Form the composition `self ∘ other`
22 fn compose<X : Space, T : Mapping<X, Codomain=Domain>>(self, other : T) 22 fn compose<X: Space, T: Mapping<X, Codomain = Domain>>(self, other: T) -> Composition<Self, T>
23 -> Composition<Self, T> 23 where
24 where 24 Self: Sized,
25 Self : Sized
26 { 25 {
27 Composition{ outer : self, inner : other, intermediate_norm_exponent : () } 26 Composition {
28 } 27 outer: self,
29 28 inner: other,
29 intermediate_norm_exponent: (),
30 }
31 }
30 32
31 #[inline] 33 #[inline]
32 /// Form the composition `self ∘ other`, assigning a norm to the inermediate space 34 /// Form the composition `self ∘ other`, assigning a norm to the inermediate space
33 fn compose_with_norm<F, X, T, E>( 35 fn compose_with_norm<F, X, T, E>(self, other: T, norm: E) -> Composition<Self, T, E>
34 self, other : T, norm : E 36 where
35 ) -> Composition<Self, T, E> 37 Self: Sized,
36 where 38 X: Space,
37 Self : Sized, 39 T: Mapping<X, Codomain = Domain>,
38 X : Space, 40 E: NormExponent,
39 T : Mapping<X, Codomain=Domain>, 41 Domain: Norm<F, E>,
40 E : NormExponent, 42 F: Num,
41 Domain : Norm<F, E>,
42 F : Num
43 { 43 {
44 Composition{ outer : self, inner : other, intermediate_norm_exponent : norm } 44 Composition {
45 outer: self,
46 inner: other,
47 intermediate_norm_exponent: norm,
48 }
45 } 49 }
46 50
47 /// Multiply `self` by the scalar `a`. 51 /// Multiply `self` by the scalar `a`.
48 #[inline] 52 #[inline]
49 fn weigh<C>(self, a : C) -> Weighted<Self, C> 53 fn weigh<C>(self, a: C) -> Weighted<Self, C>
50 where 54 where
51 Self : Sized, 55 Self: Sized,
52 C : Constant, 56 C: Constant,
53 Self::Codomain : ClosedMul<C::Type>, 57 Self::Codomain: ClosedMul<C::Type>,
54 { 58 {
55 Weighted { weight : a, base_fn : self } 59 Weighted {
60 weight: a,
61 base_fn: self,
62 }
56 } 63 }
57 } 64 }
58 65
59 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. 66 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`.
60 pub trait RealMapping<F : Float, const N : usize> 67 pub trait RealMapping<F: Float, const N: usize>: Mapping<Loc<F, N>, Codomain = F> {}
61 : Mapping<Loc<F, N>, Codomain = F> {} 68
62 69 impl<F: Float, T, const N: usize> RealMapping<F, N> for T where T: Mapping<Loc<F, N>, Codomain = F> {}
63 impl<F : Float, T, const N : usize> RealMapping<F, N> for T
64 where T : Mapping<Loc<F, N>, Codomain = F> {}
65 70
66 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`]. 71 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`].
67 pub trait RealVectorField<F : Float, const N : usize, const M : usize> 72 pub trait RealVectorField<F: Float, const N: usize, const M: usize>:
68 : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} 73 Mapping<Loc<F, N>, Codomain = Loc<F, M>>
69 74 {
70 impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T 75 }
71 where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} 76
77 impl<F: Float, T, const N: usize, const M: usize> RealVectorField<F, N, M> for T where
78 T: Mapping<Loc<F, N>, Codomain = Loc<F, M>>
79 {
80 }
72 81
73 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials 82 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials
74 /// `Differential`. 83 /// `Differential`.
75 /// 84 ///
76 /// This is automatically implemented when [`DifferentiableImpl`] is. 85 /// This is automatically implemented when [`DifferentiableImpl`] is.
77 pub trait DifferentiableMapping<Domain : Space> : Mapping<Domain> { 86 pub trait DifferentiableMapping<Domain: Space>: Mapping<Domain> {
78 type DerivativeDomain : Space; 87 type DerivativeDomain: Space;
79 type Differential<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b; 88 type Differential<'b>: Mapping<Domain, Codomain = Self::DerivativeDomain>
89 where
90 Self: 'b;
80 91
81 /// Calculate differential at `x` 92 /// Calculate differential at `x`
82 fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain; 93 fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain;
83 94
84 /// Form the differential mapping of `self`. 95 /// Form the differential mapping of `self`.
85 fn diff(self) -> Self::Differential<'static>; 96 fn diff(self) -> Self::Differential<'static>;
86 97
87 /// Form the differential mapping of `self`. 98 /// Form the differential mapping of `self`.
88 fn diff_ref(&self) -> Self::Differential<'_>; 99 fn diff_ref(&self) -> Self::Differential<'_>;
89 } 100 }
90 101
91 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from 102 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from
92 /// [`Loc<F, N>`] to `F`. 103 /// [`Loc<F, N>`] to `F`.
93 pub trait DifferentiableRealMapping<F : Float, const N : usize> 104 pub trait DifferentiableRealMapping<F: Float, const N: usize>:
94 : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {} 105 DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>>
95 106 {
96 impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T 107 }
97 where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {} 108
109 impl<F: Float, T, const N: usize> DifferentiableRealMapping<F, N> for T where
110 T: DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>>
111 {
112 }
98 113
99 /// Helper trait for implementing [`DifferentiableMapping`] 114 /// Helper trait for implementing [`DifferentiableMapping`]
100 pub trait DifferentiableImpl<X : Space> : Sized { 115 pub trait DifferentiableImpl<X: Space>: Sized {
101 type Derivative : Space; 116 type Derivative: Space;
102 117
103 /// Compute the differential of `self` at `x`, consuming the input. 118 /// Compute the differential of `self` at `x`, consuming the input.
104 fn differential_impl<I : Instance<X>>(&self, x : I) -> Self::Derivative; 119 fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative;
105 } 120 }
106 121
107 impl<T, Domain> DifferentiableMapping<Domain> for T 122 impl<T, Domain> DifferentiableMapping<Domain> for T
108 where 123 where
109 Domain : Space, 124 Domain: Space,
110 T : Clone + Mapping<Domain> + DifferentiableImpl<Domain> 125 T: Clone + Mapping<Domain> + DifferentiableImpl<Domain>,
111 { 126 {
112 type DerivativeDomain = T::Derivative; 127 type DerivativeDomain = T::Derivative;
113 type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b; 128 type Differential<'b>
114 129 = Differential<'b, Domain, Self>
115 #[inline] 130 where
116 fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain { 131 Self: 'b;
132
133 #[inline]
134 fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain {
117 self.differential_impl(x) 135 self.differential_impl(x)
118 } 136 }
119 137
120 fn diff(self) -> Differential<'static, Domain, Self> { 138 fn diff(self) -> Differential<'static, Domain, Self> {
121 Differential{ g : Cow::Owned(self), _space : PhantomData } 139 Differential {
140 g: Cow::Owned(self),
141 _space: PhantomData,
142 }
122 } 143 }
123 144
124 fn diff_ref(&self) -> Differential<'_, Domain, Self> { 145 fn diff_ref(&self) -> Differential<'_, Domain, Self> {
125 Differential{ g : Cow::Borrowed(self), _space : PhantomData } 146 Differential {
126 } 147 g: Cow::Borrowed(self),
127 } 148 _space: PhantomData,
128 149 }
150 }
151 }
129 152
130 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`]. 153 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`].
131 pub struct Differential<'a, X, G : Clone> { 154 pub struct Differential<'a, X, G: Clone> {
132 g : Cow<'a, G>, 155 g: Cow<'a, G>,
133 _space : PhantomData<X> 156 _space: PhantomData<X>,
134 } 157 }
135 158
136 impl<'a, X, G : Clone> Differential<'a, X, G> { 159 impl<'a, X, G: Clone> Differential<'a, X, G> {
137 pub fn base_fn(&self) -> &G { 160 pub fn base_fn(&self) -> &G {
138 &self.g 161 &self.g
139 } 162 }
140 } 163 }
141 164
142 impl<'a, X, G> Mapping<X> for Differential<'a, X, G> 165 impl<'a, X, G> Mapping<X> for Differential<'a, X, G>
143 where 166 where
144 X : Space, 167 X: Space,
145 G : Clone + DifferentiableMapping<X> 168 G: Clone + DifferentiableMapping<X>,
146 { 169 {
147 type Codomain = G::DerivativeDomain; 170 type Codomain = G::DerivativeDomain;
148 171
149 #[inline] 172 #[inline]
150 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { 173 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
151 (*self.g).differential(x) 174 (*self.g).differential(x)
152 } 175 }
153 } 176 }
154 177
155 /// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`. 178 /// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`.
156 pub struct FlattenedCodomain<X, F, G> { 179 pub struct FlattenedCodomain<X, F, G> {
157 g : G, 180 g: G,
158 _phantoms : PhantomData<(X, F)> 181 _phantoms: PhantomData<(X, F)>,
159 } 182 }
160 183
161 impl<F : Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G> 184 impl<F: Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G>
162 where 185 where
163 X : Space, 186 X: Space,
164 G: Mapping<X, Codomain=Loc<F, 1>> 187 G: Mapping<X, Codomain = Loc<F, 1>>,
165 { 188 {
166 type Codomain = F; 189 type Codomain = F;
167 190
168 #[inline] 191 #[inline]
169 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { 192 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
170 self.g.apply(x).flatten1d() 193 self.g.apply(x).flatten1d()
171 } 194 }
172 } 195 }
173 196
174 /// An auto-trait for constructing a [`FlattenCodomain`] structure for 197 /// An auto-trait for constructing a [`FlattenCodomain`] structure for
175 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. 198 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`.
176 pub trait FlattenCodomain<X : Space, F> : Mapping<X, Codomain=Loc<F, 1>> + Sized { 199 pub trait FlattenCodomain<X: Space, F>: Mapping<X, Codomain = Loc<F, 1>> + Sized {
177 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. 200 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
178 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { 201 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> {
179 FlattenedCodomain{ g : self, _phantoms : PhantomData } 202 FlattenedCodomain {
180 } 203 g: self,
181 } 204 _phantoms: PhantomData,
182 205 }
183 impl<X : Space, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {} 206 }
207 }
208
209 impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<F, 1>>> FlattenCodomain<X, F> for G {}
184 210
185 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`. 211 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`.
186 pub struct SlicedCodomain<'a, X, F, G : Clone, const N : usize> { 212 pub struct SlicedCodomain<'a, X, F, G: Clone, const N: usize> {
187 g : Cow<'a, G>, 213 g: Cow<'a, G>,
188 slice : usize, 214 slice: usize,
189 _phantoms : PhantomData<(X, F)> 215 _phantoms: PhantomData<(X, F)>,
190 } 216 }
191 217
192 impl<'a, X, F, G, const N : usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N> 218 impl<'a, X, F, G, const N: usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N>
193 where 219 where
194 X : Space, 220 X: Space,
195 F : Copy + Space, 221 F: Copy + Space,
196 G : Mapping<X, Codomain=Loc<F, N>> + Clone, 222 G: Mapping<X, Codomain = Loc<F, N>> + Clone,
197 { 223 {
198 type Codomain = F; 224 type Codomain = F;
199 225
200 #[inline] 226 #[inline]
201 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { 227 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
202 let tmp : [F; N] = (*self.g).apply(x).into(); 228 let tmp: [F; N] = (*self.g).apply(x).into();
203 // Safety: `slice_codomain` below checks the range. 229 // Safety: `slice_codomain` below checks the range.
204 unsafe { *tmp.get_unchecked(self.slice) } 230 unsafe { *tmp.get_unchecked(self.slice) }
205 } 231 }
206 } 232 }
207 233
208 /// An auto-trait for constructing a [`FlattenCodomain`] structure for 234 /// An auto-trait for constructing a [`FlattenCodomain`] structure for
209 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. 235 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`.
210 pub trait SliceCodomain<X : Space, F : Copy, const N : usize> 236 pub trait SliceCodomain<X: Space, F: Copy, const N: usize>:
211 : Mapping<X, Codomain=Loc<F, N>> + Clone + Sized 237 Mapping<X, Codomain = Loc<F, N>> + Clone + Sized
212 { 238 {
213 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. 239 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
214 fn slice_codomain(self, slice : usize) -> SlicedCodomain<'static, X, F, Self, N> { 240 fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> {
215 assert!(slice < N); 241 assert!(slice < N);
216 SlicedCodomain{ g : Cow::Owned(self), slice, _phantoms : PhantomData } 242 SlicedCodomain {
243 g: Cow::Owned(self),
244 slice,
245 _phantoms: PhantomData,
246 }
217 } 247 }
218 248
219 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. 249 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
220 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<'_, X, F, Self, N> { 250 fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> {
221 assert!(slice < N); 251 assert!(slice < N);
222 SlicedCodomain{ g : Cow::Borrowed(self), slice, _phantoms : PhantomData } 252 SlicedCodomain {
223 } 253 g: Cow::Borrowed(self),
224 } 254 slice,
225 255 _phantoms: PhantomData,
226 impl<X : Space, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> 256 }
227 SliceCodomain<X, F, N> 257 }
228 for G {} 258 }
229 259
260 impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<F, N>> + Clone, const N: usize>
261 SliceCodomain<X, F, N> for G
262 {
263 }
230 264
231 /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space. 265 /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space.
232 pub struct Composition<S, T, E = ()> { 266 pub struct Composition<S, T, E = ()> {
233 pub outer : S, 267 pub outer: S,
234 pub inner : T, 268 pub inner: T,
235 pub intermediate_norm_exponent : E 269 pub intermediate_norm_exponent: E,
236 } 270 }
237 271
238 impl<S, T, X, E> Mapping<X> for Composition<S, T, E> 272 impl<S, T, X, E> Mapping<X> for Composition<S, T, E>
239 where 273 where
240 X : Space, 274 X: Space,
241 T : Mapping<X>, 275 T: Mapping<X>,
242 S : Mapping<T::Codomain> 276 S: Mapping<T::Codomain>,
243 { 277 {
244 type Codomain = S::Codomain; 278 type Codomain = S::Codomain;
245 279
246 #[inline] 280 #[inline]
247 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { 281 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
248 self.outer.apply(self.inner.apply(x)) 282 self.outer.apply(self.inner.apply(x))
249 } 283 }
250 } 284 }
285
286 mod quadratic;
287 pub use quadratic::Quadratic;
288
289 /// Trait for indicating that `Self` is Lipschitz with respect to the (semi)norm `D`.
290 pub trait Lipschitz<M> {
291 /// The type of floats
292 type FloatType: Float;
293
294 /// Returns the Lipschitz factor of `self` with respect to the (semi)norm `D`.
295 fn lipschitz_factor(&self, seminorm: M) -> Option<Self::FloatType>;
296 }

mercurial