use crate::Buildable;
use minidx_core::layers::{
Activation, Bias1d, Conv1d as Conv1dL, Dense as DenseL, Diag, RMSDiv, ScalarScale,
Softmax as SoftmaxL, Swish as SwishL, GLU as GLUL, LR,
};
use minidx_core::matmul::MatMulImpl;
use minidx_core::{Const, Dtype, Float};
#[derive(Clone, Copy, Debug, Default)]
pub struct Dense<const I: usize, const O: usize> {}
impl<const I: usize, const O: usize, E: Dtype + MatMulImpl> Buildable<E> for Dense<I, O> {
type Built = DenseL<E, I, O>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(DenseL::default())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Linear<const I: usize, const O: usize> {}
impl<const I: usize, const O: usize, E: Dtype + MatMulImpl> Buildable<E> for Linear<I, O> {
type Built = (DenseL<E, I, O>, Bias1d<E, O>);
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok((DenseL::default(), Bias1d::default()))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Relu;
impl<E: Dtype + Float> Buildable<E> for Relu {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Relu)
}
}
#[derive(Clone, Copy, Debug)]
pub struct LeakyRelu(pub f32);
impl Default for LeakyRelu {
fn default() -> Self {
Self(0.5)
}
}
impl<E: Dtype + Float> Buildable<E> for LeakyRelu {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::LeakyRelu(E::from_f32(self.0).unwrap()))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Sigmoid;
impl<E: Dtype + Float> Buildable<E> for Sigmoid {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Sigmoid)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Tanh;
impl<E: Dtype + Float> Buildable<E> for Tanh {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Tanh)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SiLU;
impl<E: Dtype + Float> Buildable<E> for SiLU {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::SiLU)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Softmax(pub f32);
impl Default for Softmax {
fn default() -> Self {
Self(1.0)
}
}
impl<E: Dtype + Float> Buildable<E> for Softmax {
type Built = SoftmaxL;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(SoftmaxL(self.0))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct GLU<const I: usize, const O: usize> {}
impl<const I: usize, const O: usize, E: Dtype + Float + MatMulImpl> Buildable<E> for GLU<I, O> {
type Built = GLUL<E, I, O, Activation<E>>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(GLUL::sigmoid())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SwiGLU<const I: usize, const O: usize> {}
impl<const I: usize, const O: usize, E: Dtype + Float + MatMulImpl> Buildable<E> for SwiGLU<I, O> {
type Built = GLUL<E, I, O, SwishL<E, O>>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(GLUL::swish())
}
}
#[derive(Clone, Copy, Debug)]
pub struct GLULeakyRelu<const I: usize, const O: usize>(pub f32);
impl<const I: usize, const O: usize> Default for GLULeakyRelu<I, O> {
fn default() -> Self {
Self(0.5)
}
}
impl<const I: usize, const O: usize, E: Dtype + Float + MatMulImpl> Buildable<E>
for GLULeakyRelu<I, O>
{
type Built = GLUL<E, I, O, Activation<E>>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(GLUL::leaky_relu(self.0))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct TanhGLU<const I: usize, const O: usize> {}
impl<const I: usize, const O: usize, E: Dtype + Float + MatMulImpl> Buildable<E> for TanhGLU<I, O> {
type Built = GLUL<E, I, O, Activation<E>>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(GLUL::tanh())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Conv1d<const I: usize, const O: usize, const F: usize> {}
impl<const I: usize, const O: usize, const F: usize, E: Dtype + Float + MatMulImpl> Buildable<E>
for Conv1d<I, O, F>
where
Const<F>: minidx_core::layers::Conv1dKernel<E, Const<I>, Const<O>>,
{
type Built = Conv1dL<E, I, O, Const<F>>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Conv1dL::default())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Swish<const I: usize> {}
impl<const I: usize, E: Dtype + Float> Buildable<E> for Swish<I> {
type Built = SwishL<E, I>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(SwishL::default())
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct LRDiv<E: Dtype, const I: usize, const D: usize, B: Buildable<E>> {
module: B,
pd: std::marker::PhantomData<E>,
}
impl<
E: Dtype,
const I: usize,
const D: usize,
B: crate::Buildable<E, Built = M>,
M: Clone + Default + std::fmt::Debug + minidx_core::Module<[E; I]>,
> Buildable<E> for LRDiv<E, I, D, B>
{
type Built = LR<E, I, M>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(LR {
module: self.module.try_build()?,
update_multiplier: (D as f32).recip(),
..Default::default()
})
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct DyT<const I: usize> {}
impl<const I: usize, E: Float> Buildable<E> for DyT<I> {
type Built = (ScalarScale<E>, Activation<E>, Diag<E, I>, Bias1d<E, I>);
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok((
ScalarScale::<E>::default(),
Activation::<E>::Tanh,
Diag::<E, I>::default(),
Bias1d::default(),
))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct RMSNorm<const I: usize> {}
impl<const I: usize, E: Float + MatMulImpl> Buildable<E> for RMSNorm<I> {
type Built = (RMSDiv<E, I>, Diag<E, I>);
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok((RMSDiv::<E, I>::default(), Diag::<E, I>::default()))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Softplus;
impl<E: Dtype + Float> Buildable<E> for Softplus {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Softplus)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Sine;
impl<E: Dtype + Float> Buildable<E> for Sine {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Sine)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Cosine;
impl<E: Dtype + Float> Buildable<E> for Cosine {
type Built = Activation<E>;
fn try_build(&self) -> Result<Self::Built, crate::Error> {
Ok(Activation::<E>::Cosine)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_composition() {
let network = (
(Linear::<1, 3> {}, Relu),
(Linear::<1, 3> {}, Relu),
Dense::<3, 3> {},
LeakyRelu(0.5),
Softmax::default(),
);
use crate::Buildable;
let _realized = Buildable::<f32>::build(&network);
let _realized = Buildable::<f32>::build(&(GLU::<3, 2>::default(),));
let _realized = Buildable::<f32>::build(&(Conv1d::<4, 2, 3>::default(),));
}
#[test]
fn test_basic_typed_composition() {
type NetType = ((Linear<1, 3>, Relu), LeakyRelu);
let network = NetType::default();
use crate::Buildable;
let _realized = Buildable::<f32>::build(&network);
}
}