use arcweight::prelude::*;
use arcweight::utils::PathIterExt;
#[test]
fn test_paths_iter_empty_fst() {
let fst = VectorFst::<TropicalWeight>::new();
let mut iter = fst.paths_iter();
assert!(iter.next().is_none());
}
#[test]
fn test_paths_iter_single_path() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::new(0.5));
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(1.0), s1));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 1);
assert_eq!(paths[0].states, vec![0, 1]);
assert_eq!(paths[0].arcs.len(), 1);
assert_eq!(paths[0].input_labels(), vec![1]);
assert_eq!(paths[0].output_labels(), vec![1]);
}
#[test]
fn test_paths_iter_multiple_paths() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::new(0.5));
fst.set_final(s2, TropicalWeight::new(0.3));
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(1.0), s1));
fst.add_arc(s0, Arc::new(2, 2, TropicalWeight::new(2.0), s2));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 2);
}
#[test]
fn test_paths_iter_with_cycles() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::new(0.5));
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(1.0), s1));
fst.add_arc(s1, Arc::new(2, 2, TropicalWeight::new(0.5), s1));
let paths: Vec<_> = fst.paths_iter().with_max_paths(10).collect();
assert!(!paths.is_empty());
assert!(paths.len() <= 10);
}
#[test]
fn test_paths_iter_weight_threshold() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::new(0.5));
fst.set_final(s2, TropicalWeight::new(10.0)); fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(1.0), s1));
fst.add_arc(s0, Arc::new(2, 2, TropicalWeight::new(1.0), s2));
let threshold = TropicalWeight::new(5.0);
let paths: Vec<_> = fst.paths_iter().with_weight_threshold(threshold).collect();
assert_eq!(paths.len(), 1);
assert_eq!(paths[0].final_state, s1);
}
#[test]
fn test_string_paths_iter() {
let mut fst = VectorFst::<TropicalWeight>::new();
let mut symbols = SymbolTable::new();
let hello_id = symbols.add_symbol("hello");
let _world_id = symbols.add_symbol("world");
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::one());
fst.add_arc(s0, Arc::new(hello_id, hello_id, TropicalWeight::one(), s1));
let paths: Vec<_> = fst
.string_paths_iter(Some(&symbols), Some(&symbols))
.collect();
assert_eq!(paths.len(), 1);
assert_eq!(paths[0].input, "hello");
assert_eq!(paths[0].output, "hello");
}
#[test]
fn test_string_paths_iter_no_symbols() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::one());
fst.add_arc(s0, Arc::new(1, 2, TropicalWeight::one(), s1));
let paths: Vec<_> = fst.string_paths_iter(None, None).collect();
assert_eq!(paths.len(), 1);
assert_eq!(paths[0].input, "1");
assert_eq!(paths[0].output, "2");
}
#[test]
fn test_fst_path_io_pairs() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s0);
fst.set_final(s2, TropicalWeight::one());
fst.add_arc(s0, Arc::new(1, 10, TropicalWeight::one(), s1));
fst.add_arc(s1, Arc::new(2, 20, TropicalWeight::one(), s2));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 1);
let pairs = paths[0].io_pairs();
assert_eq!(pairs, vec![(1, 10), (2, 20)]);
}
#[test]
fn test_paths_iter_complex_fst() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
let s2 = fst.add_state();
let s3 = fst.add_state();
fst.set_start(s0);
fst.set_final(s2, TropicalWeight::new(0.5));
fst.set_final(s3, TropicalWeight::new(0.3));
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::new(1.0), s1));
fst.add_arc(s1, Arc::new(2, 2, TropicalWeight::new(1.0), s2));
fst.add_arc(s0, Arc::new(3, 3, TropicalWeight::new(2.0), s3));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 2);
let path1 = paths.iter().find(|p| p.final_state == s2).unwrap();
assert_eq!(path1.states.len(), 3);
assert_eq!(path1.arcs.len(), 2);
let path2 = paths.iter().find(|p| p.final_state == s3).unwrap();
assert_eq!(path2.states.len(), 2);
assert_eq!(path2.arcs.len(), 1);
}
#[test]
fn test_paths_iter_epsilon_transitions() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
let s2 = fst.add_state();
fst.set_start(s0);
fst.set_final(s2, TropicalWeight::one());
fst.add_arc(s0, Arc::new(0, 0, TropicalWeight::one(), s1)); fst.add_arc(s1, Arc::new(1, 1, TropicalWeight::one(), s2));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 1);
assert_eq!(paths[0].input_labels(), vec![0, 1]);
}
#[test]
fn test_paths_iter_max_paths_limit() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
fst.set_start(s0);
for i in 0..20 {
let s = fst.add_state();
fst.set_final(s, TropicalWeight::one());
fst.add_arc(s0, Arc::new(i, i, TropicalWeight::one(), s));
}
let paths: Vec<_> = fst.paths_iter().with_max_paths(5).collect();
assert_eq!(paths.len(), 5);
}
#[test]
fn test_paths_iter_no_start_state() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
fst.set_final(s0, TropicalWeight::one());
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 0);
}
#[test]
fn test_paths_iter_no_final_states() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::one(), s1));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 0);
}
#[test]
fn test_fst_path_clone() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, TropicalWeight::one());
fst.add_arc(s0, Arc::new(1, 1, TropicalWeight::one(), s1));
let path = fst.paths_iter().next().unwrap();
let cloned = path.clone();
assert_eq!(path.states, cloned.states);
assert_eq!(path.arcs, cloned.arcs);
assert_eq!(path.weight, cloned.weight);
}
#[test]
fn test_paths_iter_different_semirings() {
let mut fst = VectorFst::<LogWeight>::new();
let s0 = fst.add_state();
let s1 = fst.add_state();
fst.set_start(s0);
fst.set_final(s1, LogWeight::new(-0.693)); fst.add_arc(s0, Arc::new(1, 1, LogWeight::new(-0.693), s1));
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 1);
}
#[test]
fn test_paths_iter_large_fst() {
let mut fst = VectorFst::<TropicalWeight>::new();
let s0 = fst.add_state();
fst.set_start(s0);
for i in 0..100 {
let s = fst.add_state();
fst.set_final(s, TropicalWeight::one());
fst.add_arc(s0, Arc::new(i, i, TropicalWeight::one(), s));
}
let paths: Vec<_> = fst.paths_iter().collect();
assert_eq!(paths.len(), 100);
}