|
| 1 | +use std::io::Write; |
| 2 | + |
| 3 | +use crate::variable::{Variable, VariableTrait}; |
| 4 | + |
| 5 | +/// An iterative context for recursive evaluation. |
| 6 | +/// |
| 7 | +/// An `Iteration` tracks monotonic variables, and monitors their progress. |
| 8 | +/// It can inform the user if they have ceased changing, at which point the |
| 9 | +/// computation should be done. |
| 10 | +#[derive(Default)] |
| 11 | +pub struct Iteration { |
| 12 | + variables: Vec<Box<dyn VariableTrait>>, |
| 13 | + round: u32, |
| 14 | + debug_stats: Option<Box<dyn Write>>, |
| 15 | +} |
| 16 | + |
| 17 | +impl Iteration { |
| 18 | + /// Create a new iterative context. |
| 19 | + pub fn new() -> Self { |
| 20 | + Self::default() |
| 21 | + } |
| 22 | + /// Reports whether any of the monitored variables have changed since |
| 23 | + /// the most recent call. |
| 24 | + pub fn changed(&mut self) -> bool { |
| 25 | + self.round += 1; |
| 26 | + |
| 27 | + let mut result = false; |
| 28 | + for variable in self.variables.iter_mut() { |
| 29 | + if variable.changed() { |
| 30 | + result = true; |
| 31 | + } |
| 32 | + |
| 33 | + if let Some(ref mut stats_writer) = self.debug_stats { |
| 34 | + variable.dump_stats(self.round, stats_writer); |
| 35 | + } |
| 36 | + } |
| 37 | + result |
| 38 | + } |
| 39 | + /// Creates a new named variable associated with the iterative context. |
| 40 | + pub fn variable<Tuple: Ord + 'static>(&mut self, name: &str) -> Variable<Tuple> { |
| 41 | + let variable = Variable::new(name); |
| 42 | + self.variables.push(Box::new(variable.clone())); |
| 43 | + variable |
| 44 | + } |
| 45 | + /// Creates a new named variable associated with the iterative context. |
| 46 | + /// |
| 47 | + /// This variable will not be maintained distinctly, and may advertise tuples as |
| 48 | + /// recent multiple times (perhaps unboundedly many times). |
| 49 | + pub fn variable_indistinct<Tuple: Ord + 'static>(&mut self, name: &str) -> Variable<Tuple> { |
| 50 | + let mut variable = Variable::new(name); |
| 51 | + variable.distinct = false; |
| 52 | + self.variables.push(Box::new(variable.clone())); |
| 53 | + variable |
| 54 | + } |
| 55 | + |
| 56 | + /// Set up this Iteration to write debug statistics about each variable, |
| 57 | + /// for each round of the computation. |
| 58 | + pub fn record_stats_to(&mut self, mut w: Box<dyn Write>) { |
| 59 | + // print column names header |
| 60 | + writeln!(w, "Variable,Round,Stable count,Recent count") |
| 61 | + .expect("Couldn't write debug stats CSV header"); |
| 62 | + |
| 63 | + self.debug_stats = Some(w); |
| 64 | + } |
| 65 | +} |
0 commit comments