use candle_core::Var;
use crate::{
error::KohoError,
math::{sheaf::CellularSheaf, tensors::Matrix},
nn::activate::Activations,
Parameterized,
};
pub struct DiffusionLayer {
weights: Var,
activation: Activations,
}
impl DiffusionLayer {
pub fn new(
k: usize,
activation: Activations,
sheaf: &CellularSheaf,
) -> Result<Self, KohoError> {
let device = sheaf.device.clone();
let dtype = sheaf.dtype;
let dim = sheaf.section_spaces[k][0].0.dimension();
let weights = Matrix::rand(dim, dim, device, dtype).map_err(KohoError::Candle)?;
let weights = Var::from_tensor(weights.inner()).map_err(KohoError::Candle)?;
Ok(Self {
weights,
activation,
})
}
pub fn diffuse(
&self,
sheaf: &CellularSheaf,
k: usize,
k_features: Matrix,
down_included: bool,
) -> Result<Matrix, KohoError> {
let diff = sheaf.k_hodge_laplacian(k, k_features, down_included)?;
let weighted = self
.weights
.matmul(diff.inner())
.map_err(KohoError::Candle)?;
self.activation
.activate(weighted)
.map_err(KohoError::Candle)
}
pub fn update_weights(&mut self, weights: Var) {
self.weights = weights
}
}
impl Parameterized for DiffusionLayer {
fn parameters(&self) -> Vec<Var> {
vec![self.weights.clone()]
}
fn parameters_mut(&mut self) -> Vec<&mut Var> {
vec![&mut self.weights]
}
}