use std::collections::HashMap;
use crate::{Element, Parameters, Symbol, Tensor};
use super::module::{Module, Path, named_parameters, parameters};
pub fn snapshot<E: Element, M: Module<E> + ?Sized>(
state: &Parameters<E>,
module: &M,
) -> Vec<Tensor<E>> {
parameters(module)
.into_iter()
.map(|symbol| state.of(symbol).clone())
.collect()
}
pub fn restore<E: Element, M: Module<E> + ?Sized>(
state: &Parameters<E>,
module: &M,
payloads: Vec<Tensor<E>>,
) -> Parameters<E> {
let symbols = parameters(module);
assert_eq!(
payloads.len(),
symbols.len(),
"the checkpoint holds {} payloads but the module has {} parameters",
payloads.len(),
symbols.len(),
);
state.with_payloads(symbols.into_iter().zip(payloads))
}
pub fn named_snapshot<E: Element, M: Module<E> + ?Sized>(
state: &Parameters<E>,
module: &M,
) -> Vec<(Path, Tensor<E>)> {
named_parameters(module)
.into_iter()
.map(|(path, symbol)| (path, state.of(symbol).clone()))
.collect()
}
pub fn named_restore<E: Element, M: Module<E> + ?Sized>(
state: &Parameters<E>,
module: &M,
entries: impl IntoIterator<Item = (Path, Tensor<E>)>,
) -> Parameters<E> {
let mut entries: HashMap<Path, Tensor<E>> = entries.into_iter().collect();
let mut replacements: Vec<(Symbol, Tensor<E>)> = Vec::new();
let mut missing: Vec<String> = Vec::new();
for (path, symbol) in named_parameters(module) {
match entries.remove(&path) {
Some(payload) => replacements.push((symbol, payload)),
None => missing.push(path.to_string()),
}
}
assert!(
missing.is_empty(),
"the checkpoint is missing entries for: {}",
missing.join(", "),
);
assert!(
entries.is_empty(),
"the checkpoint holds entries no parameter matches: {}",
entries
.keys()
.map(Path::to_string)
.collect::<Vec<_>>()
.join(", "),
);
state.with_payloads(replacements)
}
#[cfg(test)]
#[path = "tests/checkpoint_tests.rs"]
mod tests;