block_graph/builtin/
math.rs

1bicop_like!(AddLayer,Add);
2bicop_like!(MulLayer,Mul);
3bicop_like!(SquaredErrorLayer,SquaredError);
4impl AI<(Vec<f32>,Vec<f32>),Vec<f32>> for SquaredErrorLayer{// TODO some kind of namable map iter might make some of these compose better
5	fn forward(&self,(output,target):(Vec<f32>,Vec<f32>))->Vec<f32>{
6		let (ol,tl)=(output.len(),target.len());
7		assert!(ol==tl,"output len {ol} should match target len {tl}");
8
9		output.into_iter().zip(target).map(|(o,t)|o-t).map(|x|x*x).collect()
10	}
11}
12impl AI<(Vec<f32>,Vec<f32>),f32> for SquaredErrorLayer{
13	fn forward(&self,(output,target):(Vec<f32>,Vec<f32>))->f32{
14		let (ol,tl)=(output.len(),target.len());
15		assert!(ol==tl,"output len {ol} should match target len {tl}");
16
17		output.into_iter().zip(target).map(|(o,t)|o-t).map(|x|x*x).sum::<f32>()/ol as f32
18	}
19}
20impl AI<Vec<f32>,f32> for MeanLayer{
21	fn forward(&self,input:Vec<f32>)->f32{
22		let sum:f32=input.iter().sum();
23
24		sum/input.len() as f32
25	}
26}
27impl AI<Vec<f32>,f32> for SumLayer{
28	fn forward(&self,input:Vec<f32>)->f32{input.into_iter().sum()}//TODO check dim
29}
30impl AI<f32,f32> for MeanLayer{
31	fn forward(&self,input:f32)->f32{input}
32}
33impl AI<f32,f32> for SumLayer{
34	fn forward(&self,input:f32)->f32{input}
35}
36impl<L:OpsAdd<R>,R,Y> AI<(L,R),Y> for AddLayer where L::Output:Into<Y>{
37	fn forward(&self,(left,right):(L,R))->Y{(left+right).into()}
38}
39impl<L:OpsMul<R>,R,Y> AI<(L,R),Y> for MulLayer where L::Output:Into<Y>{
40	fn forward(&self,(left,right):(L,R))->Y{(left*right).into()}
41}
42impl<X:OpsAbs,Y> AI<X,Y> for AbsLayer where X::Output:Into<Y>{
43	fn forward(&self,input:X)->Y{input.abs().into()}
44}
45impl<X:OpsNeg,Y> AI<X,Y> for NegLayer where X::Output:Into<Y>{
46	fn forward(&self,input:X)->Y{input.neg().into()}
47}
48/// declares layer and wrapper structs and implements accessor functions, decompose and op for binary componentwise operations. ai will still have to be externally implemented for the layer stuct
49macro_rules! bicop_like{// TODO separate parts of this like in one of the other likes and make squared error specifically have vec output
50	($layer:ident,$wrap:ident)=>{
51		impl $layer{
52			/// creates a new layer
53			pub fn new()->Self{Self::default()}
54		}
55		impl<A:AI<X,L>+Op<Output=L>,L,R,X,Y> AI<(X,R),Y> for $wrap<A> where $layer:AI<(L,R),Y>{
56			fn forward(&self,(input,right):(X,R))->Y{self.layer.forward((self.inner.forward(input),right))}// TODO swap operation
57			fn forward_mut(&mut self,(input,right):(X,R))->Y{self.layer.forward_mut((self.inner.forward_mut(input),right))}
58		}
59		impl<A:Decompose> Decompose for $wrap<A>{
60			fn compose(inner:Self::Decomposition)->Self{
61				Self{inner:A::compose(inner),layer:Default::default()}
62			}
63			fn decompose(self)->Self::Decomposition{self.inner.decompose()}
64			fn decompose_cloned(&self)->Self::Decomposition{self.inner.decompose_cloned()}
65			type Decomposition=A::Decomposition;
66		}
67		impl<A:IntoSequence<M>,M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $wrap<A> where $layer:Into<M>{
68			fn into_sequence(self)->Sequential<Vec<M>>{self.inner.into_sequence().with_next(self.layer)}
69		}
70		impl<A:UnwrapInner> UnwrapInner for $wrap<A>{
71			fn unwrap_inner(self)->A::Inner{self.into_inner().unwrap_inner()}
72			type Inner=A::Inner;
73		}
74		impl<A:Op<Output=Y>,Y> Op for $wrap<A> where $layer:AI<(Y,Y),Y>{
75			type Output=Y;
76		}
77		impl<A> $wrap<A>{/// references the inner value
78			pub fn inner(&self)->&A{&self.inner}
79			/// references the inner value
80			pub fn inner_mut(&mut self)->&mut A{&mut self.inner}
81			/// converts into the inner value
82			pub fn into_inner(self)->A{self.inner}
83			/// creates a new layer
84			pub fn new(inner:A)->Self where Self:Op{
85				Self{inner,layer:$layer::new()}
86			}
87			/// sets the inner module
88			pub fn with_inner<B>(self,inner:B)->$wrap<B> where $wrap<B>:Op{
89				$wrap{inner,layer:self.layer}
90			}
91		}
92		impl<M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $layer where $layer:Into<M>{
93			fn into_sequence(self)->Sequential<Vec<M>>{vec![self.into()].sequential()}
94		}
95		impl Decompose for $layer{
96			fn compose(_decomposition:Self::Decomposition)->Self{Self::new()}
97			fn decompose(self){}
98			fn decompose_cloned(&self){}
99			type Decomposition=();
100		}
101		impl Op for $layer{
102			type Output=Vec<f32>;
103		}
104		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
105		/// layer to apply an operation
106		pub struct $layer{seal:PhantomData<()>}
107		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
108		/// wrapper to apply an operation
109		pub struct $wrap<A>{inner:A,layer:$layer}
110	}
111}
112/// declares layer and wrapper structs and implements accessor functions, decompose and op for reduction operations that have a reduction mode as configuration fields. ai will still have to be externally implemented for the layer stuct
113macro_rules! sum_like{
114	($layer:ident,$wrap:ident)=>{
115		impl $layer{
116			/// gets the reduction mode
117			pub fn get_reduction_mode(&self)->ReductionMode{self.reductionmode}
118			/// creates a new layer
119			pub fn new()->Self{Self::default()}
120			/// sets the reduction mode
121			pub fn set_reduction_mode(&mut self,mode:ReductionMode){self.reductionmode=mode}
122			/// sets the reduction mode
123			pub fn with_reduction_mode(mut self,mode:ReductionMode)->Self{
124				self.reductionmode=mode;
125				self
126			}
127		}
128		impl<A:AI<X,Y>+Op<Output=Y>,X,Y,Z> AI<X,Z> for $wrap<A> where $layer:AI<Y,Z>{
129			fn forward(&self,input:X)->Z{self.layer.forward(self.inner.forward(input))}
130			fn forward_mut(&mut self,input:X)->Z{self.layer.forward_mut(self.inner.forward_mut(input))}
131		}
132		impl<A:Decompose> Decompose for $wrap<A>{
133			fn compose((inner,layer):Self::Decomposition)->Self{
134				Self{inner:A::compose(inner),layer:$layer::compose(layer)}
135			}
136			fn decompose(self)->Self::Decomposition{(self.inner.decompose(),self.layer.decompose())}
137			fn decompose_cloned(&self)->Self::Decomposition{(self.inner.decompose_cloned(),self.layer.decompose_cloned())}
138			type Decomposition=(A::Decomposition,<$layer as Decompose>::Decomposition);
139		}
140		impl<A:IntoSequence<M>,M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $wrap<A> where $layer:Into<M>{
141			fn into_sequence(self)->Sequential<Vec<M>>{self.inner.into_sequence().with_next(self.layer)}
142		}
143		impl<A:UnwrapInner> UnwrapInner for $wrap<A>{
144			fn unwrap_inner(self)->A::Inner{self.into_inner().unwrap_inner()}
145			type Inner=A::Inner;
146		}
147		impl<A:Op<Output=Y>,Y> Op for $wrap<A> where $layer:AI<Y,f32>{
148			type Output=f32;
149		}
150		impl<A> $wrap<A>{
151			/// gets the reduction mode
152			pub fn get_reduction_mode(&self)->ReductionMode{self.layer.reductionmode}
153			/// references the inner value
154			pub fn inner(&self)->&A{&self.inner}
155			/// references the inner value
156			pub fn inner_mut(&mut self)->&mut A{&mut self.inner}
157			/// converts into the inner value
158			pub fn into_inner(self)->A{self.inner}
159			/// creates a new layer
160			pub fn new(inner:A)->Self where Self:Op{
161				Self{inner,layer:$layer::new()}
162			}
163			/// sets the reduction mode
164			pub fn set_reduction_mode(&mut self,mode:ReductionMode){self.layer.reductionmode=mode}
165			/// sets the dimension
166			pub fn with_dim(mut self,dim:i32)->Self{
167				self.layer.dim=dim;
168				self
169			}
170			/// sets the inner module
171			pub fn with_inner<B>(self,inner:B)->$wrap<B> where $wrap<B>:Op{
172				$wrap{inner,layer:self.layer}
173			}
174			/// sets the reduction mode
175			pub fn with_reduction_mode(mut self,mode:ReductionMode)->Self{
176				self.layer.reductionmode=mode;
177				self
178			}
179		}
180		impl Decompose for $layer{
181			fn compose((dim,reductionmode):Self::Decomposition)->Self{
182				Self{dim,reductionmode:ReductionMode::compose(reductionmode)}
183			}
184			fn decompose(self)->Self::Decomposition{(self.dim,self.reductionmode.decompose())}
185			fn decompose_cloned(&self)->Self::Decomposition{(self.dim,self.reductionmode.decompose_cloned())}
186			type Decomposition=(i32,u64);
187		}
188		impl Op for $layer{
189			type Output=f32;
190		}
191		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
192		/// layer to apply an operation
193		pub struct $layer{dim:i32,reductionmode:ReductionMode}
194		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
195		/// wrapper to apply an operation
196		pub struct $wrap<A>{inner:A,layer:$layer}
197	}
198}
199/// declares layer and wrapper structs and implements accessor functions, decompose and op for unary componentwise operations. ai will still have to be externally implemented for the layer stuct
200macro_rules! uncop_like{
201	($layer:ident,$wrap:ident)=>{
202		impl $layer{
203			/// creates a new layer
204			pub fn new()->Self{Self::default()}
205		}
206		impl<A:AI<X,Y>+Op<Output=Y>,X,Y,Z> AI<X,Z> for $wrap<A> where $layer:AI<Y,Z>{
207			fn forward(&self,input:X)->Z{self.layer.forward(self.inner.forward(input))}
208			fn forward_mut(&mut self,input:X)->Z{self.layer.forward_mut(self.inner.forward_mut(input))}
209		}
210		impl<A:Decompose> Decompose for $wrap<A>{
211			fn compose(inner:Self::Decomposition)->Self{
212				Self{inner:A::compose(inner),layer:Default::default()}
213			}
214			fn decompose(self)->Self::Decomposition{self.inner.decompose()}
215			fn decompose_cloned(&self)->Self::Decomposition{self.inner.decompose_cloned()}
216			type Decomposition=A::Decomposition;
217		}
218		impl<A:IntoSequence<M>,M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $wrap<A> where $layer:Into<M>{
219			fn into_sequence(self)->Sequential<Vec<M>>{self.inner.into_sequence().with_next(self.layer)}
220		}
221		impl<A:UnwrapInner> UnwrapInner for $wrap<A>{
222			fn unwrap_inner(self)->A::Inner{self.into_inner().unwrap_inner()}
223			type Inner=A::Inner;
224		}
225		impl<A:Op<Output=Y>,Y> Op for $wrap<A> where $layer:AI<Y,Y>{
226			type Output=Y;
227		}
228		impl<A> $wrap<A>{/// references the inner value
229			pub fn inner(&self)->&A{&self.inner}
230			/// references the inner value
231			pub fn inner_mut(&mut self)->&mut A{&mut self.inner}
232			/// converts into the inner value
233			pub fn into_inner(self)->A{self.inner}
234			/// creates a new layer
235			pub fn new(inner:A)->Self where Self:Op{
236				Self{inner,layer:$layer::new()}
237			}
238			/// sets the inner module
239			pub fn with_inner<B>(self,inner:B)->$wrap<B> where $wrap<B>:Op{
240				$wrap{inner,layer:self.layer}
241			}
242		}
243		impl<M:AI<M::Output,M::Output>+Op> IntoSequence<M> for $layer where $layer:Into<M>{
244			fn into_sequence(self)->Sequential<Vec<M>>{vec![self.into()].sequential()}
245		}
246		impl Decompose for $layer{
247			fn compose(_decomposition:Self::Decomposition)->Self{Self::new()}
248			fn decompose(self){}
249			fn decompose_cloned(&self){}
250			type Decomposition=();
251		}
252		impl Op for $layer{
253			type Output=Vec<f32>;
254		}
255		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
256		/// layer to apply an operation
257		pub struct $layer{seal:PhantomData<()>}
258		#[derive(Clone,Copy,Debug,Default,Deserialize,Eq,Hash,PartialEq,Serialize)]
259		/// wrapper to apply an operation
260		pub struct $wrap<A>{inner:A,layer:$layer}
261	}
262}
263sum_like!(MeanLayer,Mean);
264sum_like!(SumLayer,Sum);
265uncop_like!(AbsLayer,Abs);
266uncop_like!(NegLayer,Neg);
267use {bicop_like,sum_like};
268use crate::{
269	AI,Decompose,IntoSequence,Op,UnwrapInner,ops::Abs as OpsAbs
270};
271use serde::{Deserialize,Serialize};
272use std::{
273	marker::PhantomData,ops::{Add as OpsAdd,Mul as OpsMul,Neg as OpsNeg}
274};
275use super::{ReductionMode,Sequential};