use crate::sign::ResidualSign;
use crate::grammar::GrammarFsm;
use crate::envelope::AdmissibilityEnvelope;
use crate::bank::HeuristicsBank;
use crate::enduce::{Enduce, DefaultEnduce};
use crate::episode::Episode;
use crate::grammar::GrammarState;
pub struct Observer<E: Enduce = DefaultEnduce> {
envelope: AdmissibilityEnvelope,
bank: HeuristicsBank,
enduce: E,
fsm: GrammarFsm,
window_signs: Vec<ResidualSign>,
window_grammar: Vec<GrammarState>,
window_start: usize,
add_descriptor: String,
}
impl Observer<DefaultEnduce> {
pub fn new(envelope: AdmissibilityEnvelope, bank: HeuristicsBank) -> Self {
Self::with_enduce(envelope, bank, DefaultEnduce)
}
}
impl<E: Enduce> Observer<E> {
pub fn with_enduce(envelope: AdmissibilityEnvelope, bank: HeuristicsBank, enduce: E) -> Self {
Self {
envelope,
bank,
enduce,
fsm: GrammarFsm::new(),
window_signs: Vec::new(),
window_grammar: Vec::new(),
window_start: 0,
add_descriptor: String::new(),
}
}
pub fn set_add_descriptor(&mut self, desc: impl Into<String>) {
self.add_descriptor = desc.into();
}
pub fn observe_step(
&mut self,
magnitude: f64,
prev: f64,
prev2: f64,
k: usize,
) -> Option<Episode> {
let sign = ResidualSign::from_scalar(magnitude, prev, prev2);
let state = self.fsm.step(&sign, &self.envelope);
self.window_signs.push(sign);
self.window_grammar.push(state);
if state == GrammarState::Violation {
let episode = self.enduce.enduce(
&self.window_signs,
&self.window_grammar,
&self.bank,
(self.window_start, k),
&self.add_descriptor,
);
self.window_signs.clear();
self.window_grammar.clear();
self.window_start = k + 1;
self.add_descriptor.clear();
return Some(episode);
}
if state == GrammarState::Admissible && self.window_signs.len() > 1 {
self.window_signs.clear();
self.window_grammar.clear();
self.window_start = k + 1;
self.add_descriptor.clear();
}
None
}
pub fn observe_trajectory(&mut self, residuals: &[f64]) -> Vec<Episode> {
let mut episodes = Vec::new();
let mut prev = 0.0_f64;
let mut prev2 = 0.0_f64;
for (k, &r) in residuals.iter().enumerate() {
if let Some(ep) = self.observe_step(r, prev, prev2, k) {
episodes.push(ep);
}
prev2 = prev;
prev = r;
}
episodes
}
}