use std::{
cell::RefCell,
collections::{HashMap, VecDeque}
};
use crate::{EvaluationError, Evaluator, Function};
use super::{CanBuildHistogram, CanIterate, EvaluationState, Histogram};
#[derive(Debug, Clone)]
pub struct HistogramBuilder
{
function: Function,
environment: HashMap<usize, i32>
}
fn increment(histogram: &mut Histogram, outcome: i32)
{
histogram
.entry(outcome)
.and_modify(|count| *count += 1)
.or_insert(1);
}
impl<'inst> super::HistogramBuilder<'inst, EvaluationStateIterator<'inst>>
for HistogramBuilder
{
#[inline]
fn new(evaluator: Evaluator) -> Self
{
HistogramBuilder {
function: evaluator.function,
environment: evaluator.environment
}
}
fn build_while(
&self,
args: impl IntoIterator<Item = i32>,
condition: impl Fn(&i32) -> bool
) -> Result<Histogram, EvaluationError<'_>>
{
let mut histogram = Histogram::default();
super::HistogramBuilder::iter(self, args)?
.flat_map(|state| state.result)
.take_while(condition)
.for_each(|outcome| increment(&mut histogram, outcome));
Ok(histogram)
}
#[inline]
fn iter(
&'inst self,
args: impl IntoIterator<Item = i32>
) -> Result<EvaluationStateIterator<'inst>, EvaluationError<'inst>>
{
CanBuildHistogram::iter(self, args)
}
}
impl<'inst> CanBuildHistogram<'inst, EvaluationStateIterator<'inst>>
for HistogramBuilder
{
#[inline]
fn function(&self) -> &Function { &self.function }
#[inline]
fn environment(&self) -> &HashMap<usize, i32> { &self.environment }
fn create_iterator(
&'inst self,
initial_state: EvaluationState<'inst>
) -> EvaluationStateIterator<'inst>
{
EvaluationStateIterator {
states: RefCell::new([initial_state].into())
}
}
}
#[derive(Debug)]
pub struct EvaluationStateIterator<'inst>
{
states: RefCell<VecDeque<EvaluationState<'inst>>>
}
impl<'inst> CanIterate<'inst> for EvaluationStateIterator<'inst>
{
fn next_state(&mut self) -> Option<EvaluationState<'inst>>
{
self.states.borrow_mut().pop_front()
}
fn inject_successors(&mut self, state: &mut EvaluationState<'inst>)
{
if let Some(ref mut successors) = state.successors
{
self.states.borrow_mut().extend(successors.drain(..))
}
}
}
impl<'inst> Iterator for EvaluationStateIterator<'inst>
{
type Item = EvaluationState<'inst>;
fn next(&mut self) -> Option<Self::Item>
{
match self.next_state()
{
Some(mut state) =>
{
state.evaluate();
self.inject_successors(&mut state);
Some(state)
},
None => None
}
}
}