use std::collections::{HashMap, HashSet};
use crate::term::syntax::{LanguageTerm, RewritableLanguageOperatorSymbol};
pub fn tree_size<LOS: RewritableLanguageOperatorSymbol>(term: &LanguageTerm<LOS>) -> usize {
1 + term.sub_terms.iter().map(tree_size).sum::<usize>()
}
pub fn dag_size<LOS: RewritableLanguageOperatorSymbol>(term: &LanguageTerm<LOS>) -> usize {
let mut seen: HashSet<&LanguageTerm<LOS>> = HashSet::new();
collect_distinct(term, &mut seen);
seen.len()
}
fn collect_distinct<'a, LOS: RewritableLanguageOperatorSymbol>(
term: &'a LanguageTerm<LOS>,
seen: &mut HashSet<&'a LanguageTerm<LOS>>,
) {
if seen.insert(term) {
for sub in &term.sub_terms {
collect_distinct(sub, seen);
}
}
}
pub fn term_depth<LOS: RewritableLanguageOperatorSymbol>(term: &LanguageTerm<LOS>) -> usize {
if term.sub_terms.is_empty() {
1
} else {
1 + term.sub_terms.iter().map(term_depth).max().unwrap()
}
}
pub fn operator_count_by_symbol<LOS: RewritableLanguageOperatorSymbol>(
term: &LanguageTerm<LOS>,
) -> HashMap<LOS, usize> {
let mut counts = HashMap::new();
count_operators(term, &mut counts);
counts
}
fn count_operators<LOS: RewritableLanguageOperatorSymbol>(
term: &LanguageTerm<LOS>,
counts: &mut HashMap<LOS, usize>,
) {
*counts.entry(term.operator.clone()).or_insert(0) += 1;
for sub in &term.sub_terms {
count_operators(sub, counts);
}
}