#[cfg(test)]
mod tests {
use rand::{rngs::StdRng, Rng, SeedableRng};
use failure::Fallible;
use crate::arc::Arc;
use crate::fst_impls::VectorFst;
use crate::fst_traits::{
ArcIterator, CoreFst, ExpandedFst, FinalStatesIterator, Fst, MutableArcIterator,
MutableFst, SerializableFst, StateIterator,
};
use crate::semirings::{ProbabilityWeight, Semiring, TropicalWeight};
use crate::SymbolTable;
use std::rc::Rc;
#[test]
fn test_small_fst() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s1)?;
let arc_1 = Arc::new(3, 5, 10.0, s2);
fst.add_arc(s1, arc_1.clone())?;
assert_eq!(fst.num_arcs(s1).unwrap(), 1);
let arc_2 = Arc::new(5, 7, 18.0, s2);
fst.add_arc(s1, arc_2.clone())?;
assert_eq!(fst.num_arcs(s1).unwrap(), 2);
assert_eq!(fst.arcs_iter(s1)?.count(), 2);
let mut it_s1 = fst.arcs_iter(s1)?;
let arc = it_s1.next().ok_or_else(|| format_err!("Missing arc"))?;
assert_eq!(arc_1, *arc);
let arc = it_s1.next().ok_or_else(|| format_err!("Missing arc"))?;
assert_eq!(arc_2, *arc);
let arc = it_s1.next();
assert!(arc.is_none());
let mut it_s2 = fst.arcs_iter(s2)?;
let d = it_s2.next();
assert!(d.is_none());
Ok(())
}
#[test]
fn test_mutable_iter_arcs_small() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s1)?;
let arc_1 = Arc::new(3, 5, 10.0, s2);
fst.add_arc(s1, arc_1.clone())?;
let arc_2 = Arc::new(5, 7, 18.0, s2);
fst.add_arc(s1, arc_2.clone())?;
let new_arc_1 = Arc::new(15, 29, 33.0, s2 + 55);
fst.arcs_iter_mut(s1)?
.next()
.ok_or_else(|| format_err!("Missing arc"))?
.set_value(&new_arc_1);
let mut it_s1 = fst.arcs_iter(s1)?;
let arc = it_s1.next().ok_or_else(|| format_err!("Missing arc"))?;
assert_eq!(new_arc_1, *arc);
let arc = it_s1.next().ok_or_else(|| format_err!("Missing arc"))?;
assert_eq!(arc_2, *arc);
assert!(it_s1.next().is_none());
Ok(())
}
#[test]
fn test_start_states() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let n_states = 1000;
let states: Vec<_> = (0..n_states).map(|_| fst.add_state()).collect();
assert_eq!(fst.start(), None);
fst.set_start(states[18])?;
assert_eq!(fst.start(), Some(states[18]));
fst.set_start(states[32])?;
assert_eq!(fst.start(), Some(states[32]));
Ok(())
}
#[test]
fn test_only_final_states() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let n_states = 1000;
let states: Vec<_> = (0..n_states).map(|_| fst.add_state()).collect();
assert_eq!(fst.final_states_iter().count(), 0);
states
.iter()
.for_each(|v| fst.set_final(*v, ProbabilityWeight::one()).unwrap());
assert_eq!(fst.final_states_iter().count(), n_states);
Ok(())
}
#[test]
fn test_final_weight() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let n_states = 1000;
let n_final_states = 300;
let mut states: Vec<_> = (0..n_states).map(|_| fst.add_state()).collect();
assert!(fst
.states_iter()
.map(|state_id| fst.final_weight(state_id).unwrap())
.all(|v| v.is_none()));
let mut rg = StdRng::from_seed([53; 32]);
rg.shuffle(&mut states);
let final_states: Vec<_> = states.into_iter().take(n_final_states).collect();
final_states.iter().enumerate().for_each(|(idx, state_id)| {
fst.set_final(*state_id, ProbabilityWeight::new(idx as f32))
.unwrap()
});
assert!(final_states
.iter()
.all(|state_id| fst.is_final(*state_id).unwrap()));
assert!(final_states
.iter()
.enumerate()
.all(|(idx, state_id)| fst.final_weight(*state_id).unwrap()
== Some(&ProbabilityWeight::new(idx as f32))));
Ok(())
}
#[test]
fn test_del_state_arcs() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.add_arc(s1, Arc::new(0, 0, ProbabilityWeight::one(), s2))?;
fst.add_arc(s2, Arc::new(0, 0, ProbabilityWeight::one(), s1))?;
fst.add_arc(s2, Arc::new(0, 0, ProbabilityWeight::one(), s2))?;
assert_eq!(fst.num_arcs(s1)?, 1);
assert_eq!(fst.num_arcs(s2)?, 2);
assert_eq!(fst.arcs_iter(s1)?.count(), 1);
assert_eq!(fst.arcs_iter(s2)?.count(), 2);
fst.del_state(s1)?;
assert_eq!(fst.num_arcs(0)?, 1);
let only_state = fst.states_iter().next().unwrap();
assert_eq!(fst.arcs_iter(only_state)?.count(), 1);
Ok(())
}
#[test]
fn test_deleting_twice_same_state() -> Fallible<()> {
let mut fst1 = VectorFst::<ProbabilityWeight>::new();
let s = fst1.add_state();
assert!(fst1.del_state(s).is_ok());
assert!(fst1.del_state(s).is_err());
Ok(())
}
#[test]
fn test_del_multiple_states() {
let mut fst1 = VectorFst::<ProbabilityWeight>::new();
let s1 = fst1.add_state();
let s2 = fst1.add_state();
let mut fst2 = fst1.clone();
assert!(fst1.del_state(s1).is_ok());
assert!(fst1.del_state(s2).is_err());
let states_to_remove = vec![s1, s2];
assert!(fst2.del_states(states_to_remove.into_iter()).is_ok());
}
#[test]
fn test_del_states_big() -> Fallible<()> {
let n_states = 1000;
let n_states_to_delete = 300;
let mut fst = VectorFst::<ProbabilityWeight>::new();
let mut states: Vec<_> = (0..n_states).map(|_| fst.add_state()).collect();
assert_eq!(fst.num_states(), n_states);
let mut rg = StdRng::from_seed([53; 32]);
rg.shuffle(&mut states);
let states_to_delete: Vec<_> = states.into_iter().take(n_states_to_delete).collect();
fst.del_states(states_to_delete)?;
assert_eq!(fst.num_states(), n_states - n_states_to_delete);
Ok(())
}
#[test]
fn test_parse_single_final_state() -> Fallible<()> {
let parsed_fst = VectorFst::<TropicalWeight>::from_text_string("0\tInfinity\n")?;
let mut fst_ref: VectorFst<TropicalWeight> = VectorFst::new();
fst_ref.add_state();
fst_ref.set_start(0)?;
assert_eq!(parsed_fst, fst_ref);
Ok(())
}
#[test]
fn test_del_all_states() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.add_arc(s1, Arc::new(0, 0, ProbabilityWeight::one(), s2))?;
fst.add_arc(s2, Arc::new(0, 0, ProbabilityWeight::one(), s1))?;
fst.add_arc(s2, Arc::new(0, 0, ProbabilityWeight::one(), s2))?;
fst.set_start(s1)?;
fst.set_final(s2, ProbabilityWeight::one())?;
assert_eq!(fst.num_states(), 2);
fst.del_all_states();
assert_eq!(fst.num_states(), 0);
Ok(())
}
#[test]
fn test_attach_symt() -> Fallible<()> {
let mut fst = VectorFst::<ProbabilityWeight>::new();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.add_arc(s1, Arc::new(1, 0, ProbabilityWeight::one(), s2))?;
fst.add_arc(s2, Arc::new(2, 0, ProbabilityWeight::one(), s1))?;
fst.add_arc(s2, Arc::new(3, 0, ProbabilityWeight::one(), s2))?;
fst.set_start(s1)?;
fst.set_final(s2, ProbabilityWeight::one())?;
{
let mut symt = SymbolTable::new();
symt.add_symbol("a"); symt.add_symbol("b"); symt.add_symbol("c");
fst.set_input_symbols(Rc::new(symt));
}
{
let symt = fst.input_symbols();
assert!(symt.is_some());
let symt = symt.unwrap();
assert_eq!(symt.len(), 4);
}
{
let symt = SymbolTable::new();
fst.set_output_symbols(Rc::new(symt));
}
{
let symt = fst.output_symbols();
assert!(symt.is_some());
let symt = symt.unwrap();
assert_eq!(symt.len(), 1);
}
Ok(())
}
}