use failure::Fallible;
use crate::fst_traits::CoreFst;
use crate::fst_traits::ExpandedFst;
use crate::fst_traits::Fst;
use crate::semirings::{Semiring, StarSemiring};
pub fn all_pairs_shortest_distance<F>(fst: &F) -> Fallible<Vec<Vec<F::W>>>
where
F: Fst + ExpandedFst,
F::W: StarSemiring,
{
let num_states = fst.num_states();
let mut d = vec![vec![<F as CoreFst>::W::zero(); num_states]; num_states];
for state_id in fst.states_iter() {
for arc in fst.arcs_iter(state_id)? {
let nextstate = arc.nextstate;
let weight = &arc.weight;
d[state_id][nextstate].plus_assign(weight)?;
}
}
for k in fst.states_iter() {
let closure_d_k_k = d[k][k].closure();
for i in fst.states_iter().filter(|s| *s != k) {
for j in fst.states_iter().filter(|s| *s != k) {
let a = (d[i][k].times(&closure_d_k_k)?).times(&d[k][j])?;
d[i][j].plus_assign(a)?;
}
}
for i in fst.states_iter().filter(|s| *s != k) {
d[k][i] = closure_d_k_k.times(&d[k][i])?;
d[i][k] = d[i][k].times(&closure_d_k_k)?;
}
d[k][k] = closure_d_k_k;
}
Ok(d)
}