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