[lab4] Removed const size from Layer trait
This commit is contained in:
parent
d4bcef5160
commit
491baf2bfb
@ -1,9 +1,9 @@
|
|||||||
pub trait Layer<const PrevLayerSize: usize, const CurrentLayerSize: usize> {
|
pub trait Layer {
|
||||||
type InputType;
|
type InputType;
|
||||||
type OutputType;
|
type OutputType;
|
||||||
|
|
||||||
fn compute(
|
fn compute(&self, input_data: &[Self::InputType], output_data: &mut [Self::OutputType]);
|
||||||
&self,
|
|
||||||
input_data: &[Self::InputType; PrevLayerSize],
|
fn input_size(&self) -> usize;
|
||||||
) -> [Self::OutputType; CurrentLayerSize];
|
fn output_size(&self) -> usize;
|
||||||
}
|
}
|
||||||
@ -1,43 +1,51 @@
|
|||||||
use crate::algo::layer::Layer;
|
use crate::algo::layer::Layer;
|
||||||
use crate::algo::net::LayersConnect;
|
use crate::algo::layers_union::LayersUnion;
|
||||||
use std::iter::Sum;
|
use std::iter::Sum;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::Add;
|
||||||
|
|
||||||
struct Neuron<const PrevLayerSize: usize> {
|
struct Neuron<const PrevLayerSize: usize> {
|
||||||
input_weights: [f64; PrevLayerSize],
|
input_weights: [f64; PrevLayerSize],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ApplyWeight {
|
pub trait ApplyWeight<Output> {
|
||||||
type Output;
|
fn apply_weight(&self, w: f64) -> Output;
|
||||||
fn apply_weight(&self, w: f64) -> Self::Output;
|
}
|
||||||
|
|
||||||
|
impl ApplyWeight<f64> for f64 {
|
||||||
|
fn apply_weight(&self, w: f64) -> f64 {
|
||||||
|
return *self * w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LayerImpl<
|
pub struct LayerImpl<
|
||||||
const PrevLayerSize: usize,
|
const PrevLayerSize: usize,
|
||||||
const CurrentLayerSize: usize,
|
const CurrentLayerSize: usize,
|
||||||
InputType: ApplyWeight,
|
InputType: ApplyWeight<WeightedType>,
|
||||||
ActivationType: Sum<<InputType as ApplyWeight>::Output>,
|
WeightedType,
|
||||||
|
ActivationType: Sum<WeightedType>,
|
||||||
ActivationFunction: Fn(ActivationType) -> OutputType,
|
ActivationFunction: Fn(ActivationType) -> OutputType,
|
||||||
OutputType,
|
OutputType,
|
||||||
> {
|
> {
|
||||||
neurons: [Neuron<PrevLayerSize>; CurrentLayerSize],
|
neurons: [Neuron<PrevLayerSize>; CurrentLayerSize],
|
||||||
activation_function: ActivationFunction,
|
activation_function: ActivationFunction,
|
||||||
__phantom: PhantomData<(InputType, ActivationType, OutputType)>,
|
__phantom: PhantomData<(InputType, WeightedType, ActivationType, OutputType)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
const PrevLayerSize: usize,
|
const PrevLayerSize: usize,
|
||||||
const CurrentLayerSize: usize,
|
const CurrentLayerSize: usize,
|
||||||
InputType: ApplyWeight,
|
InputType: ApplyWeight<WeightedType>,
|
||||||
ActivationType: Sum<<InputType as ApplyWeight>::Output>,
|
WeightedType,
|
||||||
|
ActivationType: Sum<WeightedType>,
|
||||||
ActivationFunction: Fn(ActivationType) -> OutputType,
|
ActivationFunction: Fn(ActivationType) -> OutputType,
|
||||||
OutputType,
|
OutputType,
|
||||||
> Layer<PrevLayerSize, CurrentLayerSize>
|
> Layer
|
||||||
for LayerImpl<
|
for LayerImpl<
|
||||||
PrevLayerSize,
|
PrevLayerSize,
|
||||||
CurrentLayerSize,
|
CurrentLayerSize,
|
||||||
InputType,
|
InputType,
|
||||||
|
WeightedType,
|
||||||
ActivationType,
|
ActivationType,
|
||||||
ActivationFunction,
|
ActivationFunction,
|
||||||
OutputType,
|
OutputType,
|
||||||
@ -46,45 +54,49 @@ impl<
|
|||||||
type InputType = InputType;
|
type InputType = InputType;
|
||||||
type OutputType = OutputType;
|
type OutputType = OutputType;
|
||||||
|
|
||||||
fn compute(&self, input_data: &[InputType; PrevLayerSize]) -> [OutputType; CurrentLayerSize] {
|
fn compute(&self, input_data: &[InputType], output_data: &mut [OutputType]) {
|
||||||
let mut output: [OutputType; CurrentLayerSize] =
|
|
||||||
std::array::from_fn(|_| unsafe { std::mem::uninitialized::<OutputType>() });
|
|
||||||
for (i, n) in self.neurons.iter().enumerate() {
|
for (i, n) in self.neurons.iter().enumerate() {
|
||||||
let P = input_data
|
let P = input_data
|
||||||
.iter()
|
.iter()
|
||||||
.zip(n.input_weights)
|
.zip(n.input_weights)
|
||||||
.map(|(x, w)| x.apply_weight(w))
|
.map(|(x, w)| x.apply_weight(w))
|
||||||
.sum();
|
.sum();
|
||||||
output[i] = (self.activation_function)(P);
|
output_data[i] = (self.activation_function)(P);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
fn input_size(&self) -> usize {
|
||||||
|
return PrevLayerSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_size(&self) -> usize {
|
||||||
|
return CurrentLayerSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
const PrevPrevLayerSize: usize,
|
const PrevPrevLayerSize: usize,
|
||||||
const PrevLayerSize: usize,
|
const PrevLayerSize: usize,
|
||||||
const CurrentLayerSize: usize,
|
PrevLayerInputType: ApplyWeight<PrevLayerWeightedType>,
|
||||||
PrevLayerInputType: ApplyWeight,
|
PrevLayerWeightedType,
|
||||||
PrevLayerActivationType: Sum<<PrevLayerInputType as ApplyWeight>::Output>,
|
PrevLayerActivationType: Sum<PrevLayerWeightedType>,
|
||||||
PrevLayerActivationFunction: Fn(PrevLayerActivationType) -> PrevLayerOutputType,
|
PrevLayerActivationFunction: Fn(PrevLayerActivationType) -> PrevLayerOutputType,
|
||||||
PrevLayerOutputType,
|
PrevLayerOutputType,
|
||||||
CurrentLayer: Layer<PrevLayerSize, CurrentLayerSize, InputType = PrevLayerOutputType>,
|
CurrentLayer: Layer<InputType = PrevLayerOutputType>,
|
||||||
> Add<CurrentLayer>
|
> Add<CurrentLayer>
|
||||||
for LayerImpl<
|
for LayerImpl<
|
||||||
PrevPrevLayerSize,
|
PrevPrevLayerSize,
|
||||||
PrevLayerSize,
|
PrevLayerSize,
|
||||||
PrevLayerInputType,
|
PrevLayerInputType,
|
||||||
|
PrevLayerWeightedType,
|
||||||
PrevLayerActivationType,
|
PrevLayerActivationType,
|
||||||
PrevLayerActivationFunction,
|
PrevLayerActivationFunction,
|
||||||
PrevLayerOutputType,
|
PrevLayerOutputType,
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
type Output =
|
type Output = LayersUnion<Self, CurrentLayer>;
|
||||||
LayersConnect<PrevPrevLayerSize, PrevLayerSize, CurrentLayerSize, Self, CurrentLayer>;
|
|
||||||
|
|
||||||
fn add(self, rhs: CurrentLayer) -> Self::Output {
|
fn add(self, rhs: CurrentLayer) -> Self::Output {
|
||||||
return LayersConnect::join(self, rhs);
|
return LayersUnion::join(self, rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
lab4/src/algo/layers_union.rs
Normal file
67
lab4/src/algo/layers_union.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use crate::algo::layer::Layer;
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
pub struct LayersUnion<
|
||||||
|
PrevLayer: Layer,
|
||||||
|
CurrentLayer: Layer<InputType = PrevLayer::OutputType>,
|
||||||
|
> {
|
||||||
|
prev_layer: PrevLayer,
|
||||||
|
current_layer: CurrentLayer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<PrevLayer: Layer, CurrentLayer: Layer<InputType = PrevLayer::OutputType>>
|
||||||
|
LayersUnion<PrevLayer, CurrentLayer>
|
||||||
|
{
|
||||||
|
pub fn join(l1: PrevLayer, l2: CurrentLayer) -> Self {
|
||||||
|
assert_eq!(l1.output_size(), l2.input_size());
|
||||||
|
return Self {
|
||||||
|
prev_layer: l1,
|
||||||
|
current_layer: l2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<PrevLayer: Layer, CurrentLayer: Layer<InputType = PrevLayer::OutputType>> Layer
|
||||||
|
for LayersUnion<PrevLayer, CurrentLayer>
|
||||||
|
{
|
||||||
|
type InputType = PrevLayer::InputType;
|
||||||
|
type OutputType = CurrentLayer::OutputType;
|
||||||
|
|
||||||
|
fn compute(&self, input_data: &[Self::InputType], output_data: &mut [Self::OutputType]) {
|
||||||
|
let mut intermediate_data_s =
|
||||||
|
vec![0u8; self.prev_layer.output_size() * size_of::<PrevLayer::OutputType>()]
|
||||||
|
.into_boxed_slice();
|
||||||
|
|
||||||
|
let intermediate_data;
|
||||||
|
unsafe {
|
||||||
|
intermediate_data = std::slice::from_raw_parts_mut(
|
||||||
|
intermediate_data_s.as_mut_ptr().cast::<PrevLayer::OutputType>(),
|
||||||
|
self.prev_layer.output_size(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
self.prev_layer.compute(input_data, intermediate_data);
|
||||||
|
self.current_layer.compute(intermediate_data, output_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_size(&self) -> usize {
|
||||||
|
return self.prev_layer.input_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_size(&self) -> usize {
|
||||||
|
return self.current_layer.output_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
PrevLayer: Layer,
|
||||||
|
CurrentLayer: Layer<InputType = PrevLayer::OutputType>,
|
||||||
|
NextLayer: Layer<InputType = CurrentLayer::OutputType>,
|
||||||
|
> Add<NextLayer>
|
||||||
|
for LayersUnion<PrevLayer, CurrentLayer>
|
||||||
|
{
|
||||||
|
type Output = LayersUnion<Self, NextLayer>;
|
||||||
|
|
||||||
|
fn add(self, rhs: NextLayer) -> Self::Output {
|
||||||
|
return LayersUnion::join(self, rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
mod layer;
|
mod layer;
|
||||||
mod net;
|
mod layers_union;
|
||||||
mod layer_impl;
|
mod layer_impl;
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
use crate::algo::layer::Layer;
|
|
||||||
use std::ops::{Add};
|
|
||||||
|
|
||||||
pub(super) struct LayersConnect<
|
|
||||||
const PrevPrevLayerSize: usize,
|
|
||||||
const PrevLayerSize: usize,
|
|
||||||
const CurrentLayerSize: usize,
|
|
||||||
PrevLayer: Layer<PrevPrevLayerSize, PrevLayerSize>,
|
|
||||||
CurrentLayer: Layer<PrevLayerSize, CurrentLayerSize, InputType = PrevLayer::OutputType>,
|
|
||||||
> {
|
|
||||||
prev_layer: PrevLayer,
|
|
||||||
current_layer: CurrentLayer,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
const PrevPrevLayerSize: usize,
|
|
||||||
const PrevLayerSize: usize,
|
|
||||||
const CurrentLayerSize: usize,
|
|
||||||
PrevLayer: Layer<PrevPrevLayerSize, PrevLayerSize>,
|
|
||||||
CurrentLayer: Layer<PrevLayerSize, CurrentLayerSize, InputType = PrevLayer::OutputType>,
|
|
||||||
> LayersConnect<PrevPrevLayerSize, PrevLayerSize, CurrentLayerSize, PrevLayer, CurrentLayer>
|
|
||||||
{
|
|
||||||
pub fn join(l1: PrevLayer, l2: CurrentLayer) -> Self {
|
|
||||||
return Self {
|
|
||||||
prev_layer: l1,
|
|
||||||
current_layer: l2,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
const PrevPrevLayerSize: usize,
|
|
||||||
const PrevLayerSize: usize,
|
|
||||||
const CurrentLayerSize: usize,
|
|
||||||
PrevLayer: Layer<PrevPrevLayerSize, PrevLayerSize>,
|
|
||||||
CurrentLayer: Layer<PrevLayerSize, CurrentLayerSize, InputType = PrevLayer::OutputType>,
|
|
||||||
> Layer<PrevPrevLayerSize, CurrentLayerSize>
|
|
||||||
for LayersConnect<PrevPrevLayerSize, PrevLayerSize, CurrentLayerSize, PrevLayer, CurrentLayer>
|
|
||||||
{
|
|
||||||
type InputType = PrevLayer::InputType;
|
|
||||||
type OutputType = CurrentLayer::OutputType;
|
|
||||||
|
|
||||||
fn compute(
|
|
||||||
&self,
|
|
||||||
input_data: &[Self::InputType; PrevPrevLayerSize],
|
|
||||||
) -> [Self::OutputType; CurrentLayerSize] {
|
|
||||||
let intermediate_data = self.prev_layer.compute(input_data);
|
|
||||||
return self.current_layer.compute(&intermediate_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
const PrevPrevLayerSize: usize,
|
|
||||||
const PrevLayerSize: usize,
|
|
||||||
const CurrentLayerSize: usize,
|
|
||||||
const NextLayerSize: usize,
|
|
||||||
PrevLayer: Layer<PrevPrevLayerSize, PrevLayerSize>,
|
|
||||||
CurrentLayer: Layer<PrevLayerSize, CurrentLayerSize, InputType = PrevLayer::OutputType>,
|
|
||||||
NextLayer: Layer<CurrentLayerSize, NextLayerSize, InputType = CurrentLayer::OutputType>,
|
|
||||||
> Add<NextLayer>
|
|
||||||
for LayersConnect<
|
|
||||||
PrevPrevLayerSize,
|
|
||||||
PrevLayerSize,
|
|
||||||
CurrentLayerSize,
|
|
||||||
PrevLayer,
|
|
||||||
CurrentLayer,
|
|
||||||
>
|
|
||||||
{
|
|
||||||
type Output = LayersConnect<PrevPrevLayerSize, CurrentLayerSize, NextLayerSize, Self, NextLayer>;
|
|
||||||
|
|
||||||
fn add(self, rhs: NextLayer) -> Self::Output {
|
|
||||||
return LayersConnect::join(self, rhs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user