arcweight 0.3.0

A high-performance, modular library for weighted finite state transducers with comprehensive examples and benchmarks
Documentation
//! Tests for streaming algorithms

use arcweight::algorithms::{compose_bounded, StreamingShortestPath};
use arcweight::prelude::*;

#[test]
fn test_compose_bounded() {
    let mut fst1 = VectorFst::<TropicalWeight>::new();
    let s0 = fst1.add_state();
    let s1 = fst1.add_state();
    fst1.set_start(s0);
    fst1.set_final(s1, TropicalWeight::one());
    fst1.add_arc(s0, Arc::new(1, 1, TropicalWeight::one(), s1));

    let mut fst2 = VectorFst::<TropicalWeight>::new();
    let s0 = fst2.add_state();
    let s1 = fst2.add_state();
    fst2.set_start(s0);
    fst2.set_final(s1, TropicalWeight::one());
    fst2.add_arc(s0, Arc::new(1, 2, TropicalWeight::one(), s1));

    let result = compose_bounded(&fst1, &fst2, 1000).unwrap();
    assert!(result.num_states() > 0);
    assert!(result.num_states() <= 1000); // Should respect bound
}

#[test]
fn test_compose_bounded_small_limit() {
    let mut fst1 = VectorFst::<TropicalWeight>::new();
    let s0 = fst1.add_state();
    let s1 = fst1.add_state();
    fst1.set_start(s0);
    fst1.set_final(s1, TropicalWeight::one());
    fst1.add_arc(s0, Arc::new(1, 1, TropicalWeight::one(), s1));

    let mut fst2 = VectorFst::<TropicalWeight>::new();
    let s0 = fst2.add_state();
    let s1 = fst2.add_state();
    fst2.set_start(s0);
    fst2.set_final(s1, TropicalWeight::one());
    fst2.add_arc(s0, Arc::new(1, 2, TropicalWeight::one(), s1));

    // Even with small limit, should work for small FSTs
    let result: VectorFst<TropicalWeight> = compose_bounded(&fst1, &fst2, 10).unwrap();
    assert!(result.num_states() > 0);
}

#[test]
fn test_streaming_shortest_path_new() {
    let processor = StreamingShortestPath::<TropicalWeight>::new(None);
    // Just test it can be created
    assert!(processor.max_states.is_none());

    let processor2 = StreamingShortestPath::<TropicalWeight>::new(Some(100));
    assert_eq!(processor2.max_states, Some(100));
}

#[test]
fn test_streaming_shortest_path_with_limit() {
    let processor = StreamingShortestPath::<TropicalWeight>::new(Some(50));
    assert_eq!(processor.max_states, Some(50));
}

#[test]
fn test_compose_bounded_empty_fsts() {
    let fst1 = VectorFst::<TropicalWeight>::new();
    let fst2 = VectorFst::<TropicalWeight>::new();

    // Empty FSTs cannot be composed (no start state)
    let result: Result<VectorFst<TropicalWeight>> = compose_bounded(&fst1, &fst2, 100);
    assert!(result.is_err()); // Should error because no start state
}

#[test]
fn test_compose_bounded_identity() {
    let mut fst = VectorFst::<TropicalWeight>::new();
    let s0 = fst.add_state();
    fst.set_start(s0);
    fst.set_final(s0, TropicalWeight::one());

    // Compose with itself (identity)
    let result: VectorFst<TropicalWeight> = compose_bounded(&fst, &fst, 100).unwrap();
    assert!(result.num_states() > 0);
}

#[test]
fn test_compose_bounded_different_semirings() {
    let mut fst1 = VectorFst::<LogWeight>::new();
    let s0 = fst1.add_state();
    let s1 = fst1.add_state();
    fst1.set_start(s0);
    fst1.set_final(s1, LogWeight::one());
    fst1.add_arc(s0, Arc::new(1, 1, LogWeight::one(), s1));

    let mut fst2 = VectorFst::<LogWeight>::new();
    let s0 = fst2.add_state();
    let s1 = fst2.add_state();
    fst2.set_start(s0);
    fst2.set_final(s1, LogWeight::one());
    fst2.add_arc(s0, Arc::new(1, 2, LogWeight::one(), s1));

    let result = compose_bounded(&fst1, &fst2, 100).unwrap();
    assert!(result.num_states() > 0);
}