1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::LFA;
use crate::approximators::Approximator;
use crate::basis::{Projection, composition::*};
use crate::geometry::Space;
pub trait Composable: Sized {
fn lfa<A: Approximator<Projection>>(self, approximator: A) -> LFA<Self, A> {
LFA::new(self, approximator)
}
fn stack<P>(self, p: P) -> Stack<Self, P> { Stack::new(self, p) }
fn add<P: Space>(self, p: P) -> Sum<Self, P>
where Self: Space {
Sum::new(self, p)
}
fn subtract<P: Space>(self, p: P) -> Sum<Self, Negate<P>>
where Self: Space {
Sum::new(self, Negate::new(p))
}
fn shift(self, offset: f64) -> Shift<Self> { Shift::new(self, offset) }
fn multiply<P: Space>(self, p: P) -> Product<Self, P>
where Self: Space {
Product::new(self, p)
}
fn divide<P: Space>(self, p: P) -> Product<Self, Reciprocal<P>>
where Self: Space {
Product::new(self, Reciprocal::new(p))
}
fn scale(self, factor: f64) -> Scale<Self> { Scale::new(self, factor) }
fn normalise_l1(self) -> L1Normalise<Self> { L1Normalise::new(self) }
fn normalise_l2(self) -> L2Normalise<Self> { L2Normalise::new(self) }
fn normalise_lp(self, p: u8) -> LpNormalise<Self> { LpNormalise::new(self, p) }
fn normalise_linf(self) -> LinfNormalise<Self> { LinfNormalise::new(self) }
}
#[cfg(test)]
mod tests {
use super::Composable;
use crate::basis::{composition::Stack, fixed::Constant, Projector};
use quickcheck::quickcheck;
#[test]
fn test_stack_constant() {
fn prop_equivalency(input: Vec<f64>) -> bool {
let p1 = Stack::new(Constant::zeros(10), Constant::ones(10));
let p2 = Constant::zeros(10).stack(Constant::ones(10));
p1.project(&input) == p2.project(&input)
}
quickcheck(prop_equivalency as fn(Vec<f64>) -> bool);
}
}