pub(crate) type CommonPatterns<T = usize> = Vec<(Vec<T>, T)>;
pub(crate) type AverageImportance<T = f32> = std::collections::HashMap<usize, T>;
pub(crate) type FeatureCountMap<T = usize> = std::collections::HashMap<T, T>;
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde_derive::Deserialize, serde_derive::Serialize),
serde(default, rename_all = "snake_case")
)]
#[repr(C)]
pub struct MemoryStatistics<T = f32> {
pub(crate) feature_counts: FeatureCountMap<usize>,
pub(crate) average_importance: AverageImportance<T>,
pub(crate) common_patterns: CommonPatterns<usize>,
pub(crate) active_features: usize,
pub(crate) memory_time: usize,
pub(crate) pattern_count: usize,
pub(crate) relationship_count: usize,
pub(crate) total_features: usize,
}
impl<T> MemoryStatistics<T> {
pub fn new() -> Self {
Self {
active_features: 0,
memory_time: 0,
pattern_count: 0,
relationship_count: 0,
total_features: 0,
average_importance: AverageImportance::new(),
common_patterns: CommonPatterns::new(),
feature_counts: FeatureCountMap::new(),
}
}
pub const fn active_features(&self) -> usize {
self.active_features
}
pub const fn active_features_mut(&mut self) -> &mut usize {
&mut self.active_features
}
pub const fn avg_importance_by_dimension(&self) -> &AverageImportance<T> {
&self.average_importance
}
pub const fn avg_importance_by_dimension_mut(&mut self) -> &mut AverageImportance<T> {
&mut self.average_importance
}
pub const fn feature_counts_by_dimension(&self) -> &FeatureCountMap<usize> {
&self.feature_counts
}
pub const fn feature_counts_by_dimension_mut(&mut self) -> &mut FeatureCountMap<usize> {
&mut self.feature_counts
}
pub const fn memory_time(&self) -> usize {
self.memory_time
}
pub const fn memory_time_mut(&mut self) -> &mut usize {
&mut self.memory_time
}
pub const fn most_common_patterns(&self) -> &CommonPatterns<usize> {
&self.common_patterns
}
pub const fn most_common_patterns_mut(&mut self) -> &mut CommonPatterns<usize> {
&mut self.common_patterns
}
pub const fn pattern_count(&self) -> usize {
self.pattern_count
}
pub const fn pattern_count_mut(&mut self) -> &mut usize {
&mut self.pattern_count
}
pub const fn relationship_count(&self) -> usize {
self.relationship_count
}
pub const fn relationship_count_mut(&mut self) -> &mut usize {
&mut self.relationship_count
}
pub const fn total_features(&self) -> usize {
self.total_features
}
pub const fn total_features_mut(&mut self) -> &mut usize {
&mut self.total_features
}
pub fn set_active_features(&mut self, count: usize) -> &mut Self {
self.active_features = count;
self
}
pub fn set_avg_importance_by_dimension(
&mut self,
avg_importance: AverageImportance<T>,
) -> &mut Self {
self.average_importance = avg_importance;
self
}
pub fn set_feature_counts_by_dimension(
&mut self,
feature_counts: FeatureCountMap<usize>,
) -> &mut Self {
self.feature_counts = feature_counts;
self
}
pub fn set_memory_time(&mut self, time: usize) -> &mut Self {
self.memory_time = time;
self
}
pub fn set_most_common_patterns(&mut self, patterns: CommonPatterns<usize>) -> &mut Self {
self.common_patterns = patterns;
self
}
pub fn set_pattern_count(&mut self, count: usize) -> &mut Self {
self.pattern_count = count;
self
}
pub fn set_relationship_count(&mut self, count: usize) -> &mut Self {
self.relationship_count = count;
self
}
pub fn set_total_features(&mut self, count: usize) -> &mut Self {
self.total_features = count;
self
}
pub fn with_active_features(self, active_features: usize) -> Self {
Self {
active_features,
..self
}
}
pub fn with_avg_importance_by_dimension(self, avg_importance: AverageImportance<T>) -> Self {
Self {
average_importance: avg_importance,
..self
}
}
pub fn with_feature_counts_by_dimension(self, feature_counts: FeatureCountMap<usize>) -> Self {
Self {
feature_counts,
..self
}
}
pub fn with_memory_time(self, time: usize) -> Self {
Self {
memory_time: time,
..self
}
}
pub fn with_most_common_patterns(self, patterns: CommonPatterns<usize>) -> Self {
Self {
common_patterns: patterns,
..self
}
}
pub fn with_pattern_count(self, count: usize) -> Self {
Self {
pattern_count: count,
..self
}
}
pub fn with_relationship_count(self, count: usize) -> Self {
Self {
relationship_count: count,
..self
}
}
pub fn with_total_features(self, count: usize) -> Self {
Self {
total_features: count,
..self
}
}
pub fn generate_report(&self) -> String
where
T: core::fmt::Debug,
{
use rstmt::nrt::LPR;
let mut lines = Vec::new();
lines.push(format!("Memory time: {}", self.memory_time()));
lines.push(format!(
"Features (active / total): {} / {}",
self.active_features(),
self.total_features()
));
lines.push(format!("Patterns: {}", self.pattern_count()));
lines.push(format!("Relationships: {}", self.relationship_count()));
lines.push(format!(
"Average importance by dimension: {:?}",
self.avg_importance_by_dimension()
));
if self.pattern_count() > 0 {
lines.push("Most common patterns:".to_string());
for (i, (pattern, count)) in self.most_common_patterns().iter().enumerate() {
let pattern_names = pattern.iter().copied().map(LPR::from).collect::<Vec<_>>();
let tmp = format!(
"\tPattern {}: {} occurrences - {:?}",
i + 1,
count,
pattern_names
);
lines.push(tmp);
}
}
lines.join("\n")
}
}
impl<T> core::fmt::Display for MemoryStatistics<T>
where
T: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{report}", report = self.generate_report())
}
}