use std::collections::HashMap;
use crate::motif::Motif;
use crate::sign::ResidualSign;
use crate::grammar::GrammarState;
#[derive(Debug, Clone)]
pub struct MotifPattern {
pub name: String,
pub min_persistence: usize,
pub requires_violation: bool,
pub min_drift: f64,
}
#[derive(Debug, Clone, Default)]
pub struct HeuristicsBank {
patterns: HashMap<String, Vec<MotifPattern>>,
}
impl HeuristicsBank {
pub fn new() -> Self { Self::default() }
pub fn augment(&mut self, name: impl Into<String>, pattern: MotifPattern) {
self.patterns.entry(name.into()).or_default().push(pattern);
}
pub fn motif_count(&self) -> usize { self.patterns.len() }
pub fn is_empty(&self) -> bool { self.patterns.is_empty() }
pub fn match_episode(
&self,
signs: &[ResidualSign],
grammar_path: &[GrammarState],
persistence: usize,
) -> Motif {
for (name, patterns) in &self.patterns {
for p in patterns {
if persistence >= p.min_persistence
&& (!p.requires_violation
|| grammar_path.iter().any(|g| g.is_violation()))
&& signs.iter().any(|s| s.drift >= p.min_drift)
{
return Motif::named(name.clone());
}
}
}
Motif::Unknown
}
}