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