1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use anyhow::Result;
use crate::algorithms::dfs_visit::dfs_visit;
use crate::algorithms::tr_filters::AnyTrFilter;
use crate::algorithms::visitors::SccVisitor;
use crate::fst_traits::{ExpandedFst, Fst, MutableFst};
use crate::semirings::Semiring;
use crate::Trs;
pub fn condense<W: Semiring, FI: Fst<W> + ExpandedFst<W>, FO: MutableFst<W>>(
ifst: &FI,
) -> Result<(Vec<i32>, FO)> {
let mut visitor = SccVisitor::new(ifst, true, false);
dfs_visit(ifst, &mut visitor, &AnyTrFilter {}, false);
let scc = visitor.scc.unwrap();
let mut ofst = FO::new();
if let Some(max) = scc.iter().max() {
let num_condensed_states = *max as usize + 1;
ofst.add_states(num_condensed_states);
unsafe {
for (s, &c) in scc.iter().enumerate() {
let c = c as usize;
if s == ifst.start().unwrap() {
ofst.set_start_unchecked(c);
}
if let Some(final_weight) = ifst.final_weight_unchecked(s) {
let final_weight_ofst = match ofst.final_weight_unchecked(c) {
Some(w) => w.plus(final_weight)?,
None => final_weight,
};
ofst.set_final_unchecked(c, final_weight_ofst);
}
for tr in ifst.get_trs_unchecked(s).trs() {
let nextc = scc[tr.nextstate] as usize;
if nextc != c {
let mut condensed_tr = tr.clone();
condensed_tr.nextstate = nextc;
ofst.add_tr_unchecked(c, condensed_tr);
}
}
}
}
}
Ok((scc, ofst))
}