| 2 Traits for mathematical functions. |
2 Traits for mathematical functions. |
| 3 */ |
3 */ |
| 4 |
4 |
| 5 use crate::error::DynResult; |
5 use crate::error::DynResult; |
| 6 use crate::instance::MyCow; |
6 use crate::instance::MyCow; |
| 7 pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space}; |
7 pub use crate::instance::{BasicDecomposition, ClosedSpace, Decomposition, Instance, Space}; |
| 8 use crate::loc::Loc; |
8 use crate::loc::Loc; |
| 9 use crate::norms::{Norm, NormExponent}; |
9 use crate::norms::{Norm, NormExponent}; |
| 10 use crate::operator_arithmetic::{Constant, Weighted}; |
10 use crate::operator_arithmetic::{Constant, Weighted}; |
| 11 use crate::types::{ClosedMul, Float, Num}; |
11 use crate::types::{ClosedMul, Float, Num}; |
| 12 use std::marker::PhantomData; |
12 use std::marker::PhantomData; |
| 13 use std::ops::Mul; |
13 use std::ops::Mul; |
| 14 |
14 |
| 15 /// A mapping from `Domain` to `Self::Codomain`. |
15 /// A mapping from `Domain` to `Self::Codomain`. |
| 16 pub trait Mapping<Domain: Space> { |
16 pub trait Mapping<Domain: Space> { |
| 17 type Codomain: Space; |
17 type Codomain: ClosedSpace; |
| 18 |
18 |
| 19 /// Compute the value of `self` at `x`. |
19 /// Compute the value of `self` at `x`. |
| 20 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain; |
20 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain; |
| 21 |
21 |
| 22 #[inline] |
22 #[inline] |
| 23 /// Form the composition `self ∘ other` |
23 /// Form the composition `self ∘ other` |
| 24 fn compose<X: Space, T: Mapping<X, Codomain = Domain>>(self, other: T) -> Composition<Self, T> |
24 fn compose<X: Space, T: Mapping<X, Codomain = Domain>>(self, other: T) -> Composition<Self, T> |
| 25 where |
25 where |
| 26 Self: Sized, |
26 Self: Sized, |
| 27 { |
27 { |
| 28 Composition { |
28 Composition { outer: self, inner: other, intermediate_norm_exponent: () } |
| 29 outer: self, |
|
| 30 inner: other, |
|
| 31 intermediate_norm_exponent: (), |
|
| 32 } |
|
| 33 } |
29 } |
| 34 |
30 |
| 35 #[inline] |
31 #[inline] |
| 36 /// Form the composition `self ∘ other`, assigning a norm to the inermediate space |
32 /// Form the composition `self ∘ other`, assigning a norm to the inermediate space |
| 37 fn compose_with_norm<F, X, T, E>(self, other: T, norm: E) -> Composition<Self, T, E> |
33 fn compose_with_norm<F, X, T, E>(self, other: T, norm: E) -> Composition<Self, T, E> |
| 41 T: Mapping<X, Codomain = Domain>, |
37 T: Mapping<X, Codomain = Domain>, |
| 42 E: NormExponent, |
38 E: NormExponent, |
| 43 Domain: Norm<E, F>, |
39 Domain: Norm<E, F>, |
| 44 F: Num, |
40 F: Num, |
| 45 { |
41 { |
| 46 Composition { |
42 Composition { outer: self, inner: other, intermediate_norm_exponent: norm } |
| 47 outer: self, |
|
| 48 inner: other, |
|
| 49 intermediate_norm_exponent: norm, |
|
| 50 } |
|
| 51 } |
43 } |
| 52 |
44 |
| 53 /// Multiply `self` by the scalar `a`. |
45 /// Multiply `self` by the scalar `a`. |
| 54 #[inline] |
46 #[inline] |
| 55 fn weigh<C>(self, a: C) -> Weighted<Self, C> |
47 fn weigh<C>(self, a: C) -> Weighted<Self, C> |
| 56 where |
48 where |
| 57 Self: Sized, |
49 Self: Sized, |
| 58 C: Constant, |
50 C: Constant, |
| 59 Self::Codomain: ClosedMul<C::Type>, |
51 Self::Codomain: ClosedMul<C::Type>, |
| 60 { |
52 { |
| 61 Weighted { |
53 Weighted { weight: a, base_fn: self } |
| 62 weight: a, |
|
| 63 base_fn: self, |
|
| 64 } |
|
| 65 } |
54 } |
| 66 } |
55 } |
| 67 |
56 |
| 68 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<N, F>`] to `F`. |
57 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<N, F>`] to `F`. |
| 69 pub trait RealMapping<const N: usize, F: Float = f64>: Mapping<Loc<N, F>, Codomain = F> {} |
58 pub trait RealMapping<const N: usize, F: Float = f64>: Mapping<Loc<N, F>, Codomain = F> {} |
| 84 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
73 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
| 85 /// `Differential`. |
74 /// `Differential`. |
| 86 /// |
75 /// |
| 87 /// This is automatically implemented when [`DifferentiableImpl`] is. |
76 /// This is automatically implemented when [`DifferentiableImpl`] is. |
| 88 pub trait DifferentiableMapping<Domain: Space>: Mapping<Domain> { |
77 pub trait DifferentiableMapping<Domain: Space>: Mapping<Domain> { |
| 89 type DerivativeDomain: Space; |
78 type DerivativeDomain: ClosedSpace; |
| 90 type Differential<'b>: Mapping<Domain, Codomain = Self::DerivativeDomain> |
79 type Differential<'b>: Mapping<Domain, Codomain = Self::DerivativeDomain> |
| 91 where |
80 where |
| 92 Self: 'b; |
81 Self: 'b; |
| 93 |
82 |
| 94 /// Calculate differential at `x` |
83 /// Calculate differential at `x` |
| 113 { |
102 { |
| 114 } |
103 } |
| 115 |
104 |
| 116 /// Helper trait for implementing [`DifferentiableMapping`] |
105 /// Helper trait for implementing [`DifferentiableMapping`] |
| 117 pub trait DifferentiableImpl<X: Space>: Sized { |
106 pub trait DifferentiableImpl<X: Space>: Sized { |
| 118 type Derivative: Space; |
107 type Derivative: ClosedSpace; |
| 119 |
108 |
| 120 /// Compute the differential of `self` at `x`, consuming the input. |
109 /// Compute the differential of `self` at `x`, consuming the input. |
| 121 fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative; |
110 fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative; |
| 122 } |
111 } |
| 123 |
112 |
| 136 fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain { |
125 fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain { |
| 137 self.differential_impl(x) |
126 self.differential_impl(x) |
| 138 } |
127 } |
| 139 |
128 |
| 140 fn diff(self) -> Differential<'static, Domain, Self> { |
129 fn diff(self) -> Differential<'static, Domain, Self> { |
| 141 Differential { |
130 Differential { g: MyCow::Owned(self), _space: PhantomData } |
| 142 g: MyCow::Owned(self), |
|
| 143 _space: PhantomData, |
|
| 144 } |
|
| 145 } |
131 } |
| 146 |
132 |
| 147 fn diff_ref(&self) -> Differential<'_, Domain, Self> { |
133 fn diff_ref(&self) -> Differential<'_, Domain, Self> { |
| 148 Differential { |
134 Differential { g: MyCow::Borrowed(self), _space: PhantomData } |
| 149 g: MyCow::Borrowed(self), |
|
| 150 _space: PhantomData, |
|
| 151 } |
|
| 152 } |
135 } |
| 153 } |
136 } |
| 154 |
137 |
| 155 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`]. |
138 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`]. |
| 156 pub struct Differential<'a, X, G> { |
139 pub struct Differential<'a, X, G> { |
| 199 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
182 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
| 200 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
183 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
| 201 pub trait FlattenCodomain<X: Space, F>: Mapping<X, Codomain = Loc<1, F>> + Sized { |
184 pub trait FlattenCodomain<X: Space, F>: Mapping<X, Codomain = Loc<1, F>> + Sized { |
| 202 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
185 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 203 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { |
186 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { |
| 204 FlattenedCodomain { |
187 FlattenedCodomain { g: self, _phantoms: PhantomData } |
| 205 g: self, |
|
| 206 _phantoms: PhantomData, |
|
| 207 } |
|
| 208 } |
188 } |
| 209 } |
189 } |
| 210 |
190 |
| 211 impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<1, F>>> FlattenCodomain<X, F> for G {} |
191 impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<1, F>>> FlattenCodomain<X, F> for G {} |
| 212 |
192 |
| 239 Mapping<X, Codomain = Loc<N, F>> + Sized |
219 Mapping<X, Codomain = Loc<N, F>> + Sized |
| 240 { |
220 { |
| 241 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
221 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 242 fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> { |
222 fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> { |
| 243 assert!(slice < N); |
223 assert!(slice < N); |
| 244 SlicedCodomain { |
224 SlicedCodomain { g: MyCow::Owned(self), slice, _phantoms: PhantomData } |
| 245 g: MyCow::Owned(self), |
|
| 246 slice, |
|
| 247 _phantoms: PhantomData, |
|
| 248 } |
|
| 249 } |
225 } |
| 250 |
226 |
| 251 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
227 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 252 fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> { |
228 fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> { |
| 253 assert!(slice < N); |
229 assert!(slice < N); |
| 254 SlicedCodomain { |
230 SlicedCodomain { g: MyCow::Borrowed(self), slice, _phantoms: PhantomData } |
| 255 g: MyCow::Borrowed(self), |
|
| 256 slice, |
|
| 257 _phantoms: PhantomData, |
|
| 258 } |
|
| 259 } |
231 } |
| 260 } |
232 } |
| 261 |
233 |
| 262 impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<N, F>>, const N: usize> |
234 impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<N, F>>, const N: usize> |
| 263 SliceCodomain<X, N, F> for G |
235 SliceCodomain<X, N, F> for G |
| 292 T: DifferentiableImpl<X> + Mapping<X>, |
264 T: DifferentiableImpl<X> + Mapping<X>, |
| 293 S: DifferentiableImpl<T::Codomain>, |
265 S: DifferentiableImpl<T::Codomain>, |
| 294 E: Copy, |
266 E: Copy, |
| 295 //Composition<S::Derivative, T::Derivative, E>: Space, |
267 //Composition<S::Derivative, T::Derivative, E>: Space, |
| 296 S::Derivative: Mul<T::Derivative, Output = Y>, |
268 S::Derivative: Mul<T::Derivative, Output = Y>, |
| 297 Y: Space, |
269 Y: ClosedSpace, |
| 298 { |
270 { |
| 299 //type Derivative = Composition<S::Derivative, T::Derivative, E>; |
271 //type Derivative = Composition<S::Derivative, T::Derivative, E>; |
| 300 type Derivative = Y; |
272 type Derivative = Y; |
| 301 |
273 |
| 302 /// Compute the differential of `self` at `x`, consuming the input. |
274 /// Compute the differential of `self` at `x`, consuming the input. |