[lab4] Removed const size from Layer trait

This commit is contained in:
Andrew Golovashevich 2026-02-08 18:48:28 +03:00
parent d4bcef5160
commit 491baf2bfb
5 changed files with 109 additions and 104 deletions

View File

@ -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;
} }

View File

@ -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);
} }
} }

View 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);
}
}

View File

@ -1,3 +1,3 @@
mod layer; mod layer;
mod net; mod layers_union;
mod layer_impl; mod layer_impl;

View File

@ -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)
}
}