Hi all! I was wondering if I could get some help on the following issue I've encountered. I'm learning rust and the project I'm working on is writing a library that involves something like the following:
#[derive(Debug, PartialEq)]
pub enum TensorType {
ScalarT(f64),
VectorT(Vec<f64>),
MatrixT(Vec<Vec<f64>>),
}
#[derive(Debug, Clone)]
pub struct Matrix {
// Forward pass computations
pub data: TensorType,
pub shape: (usize, usize),
// Used to determine if we should apply a pullback or stop going back through the chain here
pub trainable: bool,
pub index: usize, // this current matrix's place in the gradient tape
// the parent(s) if any. Source nodes do not have parents and some nodes only have one parent
// such as in the case of a unary op
pub parents: [Option<usize>; 2],
pub pullbacks: [Option<Pullback>; 2]
pub gradient_tape: Vec<Matrix>
}
This is related to automatic differentiation. Basically, each time we create a matrix we want to "store" it on some chain of data, which allows us to know about a matrix's parents so that we can pass variables back through the chain. The issue I'm running into now is the following:
impl Matrix{
pub fn from_scalar(v: f64) -> Self {
let res = Self {
data: ScalarT(v),
shape: (1, 1),
trainable: true,
index: ??
parents: [None, None]
pullbacks: [None, None]
gradient_tape: ??
};
res
}
}
and the ??
sections highlight my problem. Ideally, all created instances would have access to the shared chain so that I could do something like
index: gradient_tape.len()
gradient_tape: persistent_gradient_tape
but I can't. Could a refcell address my issue? Sorry, I'm still relatively new to all of this. Ideally an end-user would have a workflow that looks something like
let m1 = Matrix::from_scalar(5.0);
let m2 = Matrix::from_vector(vec![1.0, 2.0, 3.0]);
let m3 = m2 * m1;
such that all 3 matrices, m1, m2, m3
all have access to the same gradient_tape
which is now of length 3.
I'm happy to restructure the program with your insights. Thank you!