use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug, Default)]
pub struct Entropy<T> {
frequencies: HashMap<T, u64>,
count: u64,
}
impl<T: Eq + Hash> Entropy<T> {
pub fn new() -> Self {
Self {
frequencies: HashMap::new(),
count: 0,
}
}
pub fn add(&mut self, item: T) {
*self.frequencies.entry(item).or_insert(0) += 1;
self.count += 1;
}
pub fn add_all<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
for item in iter {
self.add(item);
}
}
pub fn total_entropy(&self) -> f64 {
if self.count == 0 {
return 0.0;
}
self.frequencies
.values()
.map(|&count| {
let probability = count as f64 / self.count as f64;
if probability > 0.0 {
-probability * probability.log2()
} else {
0.0
}
})
.sum()
}
}
pub fn calculate_path_entropy(sequence_of_angles: Vec<f64>) -> f64 {
if sequence_of_angles.is_empty() {
return 0.0;
}
let mut counts: HashMap<String, i32> = HashMap::new();
for angle in sequence_of_angles.iter() {
let key = format_float_to_string(*angle);
*counts.entry(key).or_insert(0) += 1;
}
let total_steps = sequence_of_angles.len();
let mut entropy = 0.0;
for count in counts.iter() {
let probability = *count.1 as f64 / total_steps as f64;
if probability > 0.0 {
entropy = entropy - (probability * probability.log2());
}
}
entropy
}
pub fn format_float_to_string(n: f64) -> String {
let n_str = format!("{n:.3}");
n_str
}