dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
use crate::{
    adjacency_list_graph_old::AdjacencyList,
    dijkstra_sparse_queue::DijkstraSparseQueue,
    negative_cycle::NegativeCycleError,
    shortest_path_potential::{
        shortest_path_potential,
        ShortestPathPotentialEdge,
    },
    sssp_dijkstra_sparse_with_general::dijkstra_sparse,
};

pub fn johnson_sparse<E, Q>(
    v_size: usize,
    directed_edges: Vec<E>,
) -> Result<Vec<Vec<Option<i64>>>, NegativeCycleError>
where
    E: ShortestPathPotentialEdge + Clone,
    Q: DijkstraSparseQueue,
{
    let p = shortest_path_potential::<E>(v_size, directed_edges.clone())?;

    type E2 = (usize, usize, u64);

    let edges = directed_edges
        .into_iter()
        .map(|e| {
            let u = *e.from();

            let v = *e.to();

            let w: u64 = (e.weight() - p[v] + p[u]) as u64;

            (u, v, w)
        })
        .collect::<Vec<E2>>();

    let g = AdjacencyList::<E2>::from((v_size, edges));

    let mut results = vec![];

    for i in 0..v_size {
        let dist = dijkstra_sparse::<E2, Q>(g.edges(), i)
            .into_iter()
            .enumerate()
            .map(|(j, d)| d.map(|x| x as i64 + p[j] - p[i]))
            .collect();

        results.push(dist);
    }

    Ok(results)
}

#[cfg(test)]

mod tests {

    use super::*;
    use crate::dijkstra_queue_binary_heap_std::DijkstraQueueBinaryHeapStd as Q;

    #[test]

    fn test_positive() {
        let edges = vec![
            (0, 1, 1),
            (0, 2, 5),
            (1, 2, 2),
            (1, 3, 4),
            (2, 3, 1),
            (3, 2, 7),
        ];

        assert_eq!(
            johnson_sparse::<_, Q>(4, edges),
            Ok(vec![
                vec![Some(0), Some(1), Some(3), Some(4)],
                vec![None, Some(0), Some(2), Some(3)],
                vec![None, None, Some(0), Some(1)],
                vec![None, None, Some(7), Some(0)],
            ]),
        )
    }

    #[test]

    fn test_negative() {
        let edges = vec![
            (0, 1, 1),
            (0, 2, -5),
            (1, 2, 2),
            (1, 3, 4),
            (2, 3, 1),
            (3, 2, 7),
        ];

        assert_eq!(
            johnson_sparse::<_, Q>(4, edges),
            Ok(vec![
                vec![Some(0), Some(1), Some(-5), Some(-4)],
                vec![None, Some(0), Some(2), Some(3)],
                vec![None, None, Some(0), Some(1)],
                vec![None, None, Some(7), Some(0)],
            ]),
        )
    }

    #[test]

    fn test_negative_cycle() {
        let edges = vec![
            (0, 1, 1),
            (0, 2, 5),
            (1, 2, 2),
            (1, 3, 4),
            (2, 3, 1),
            (3, 2, -7),
        ];

        assert_eq!(
            johnson_sparse::<_, Q>(4, edges),
            Err(NegativeCycleError::new()),
        )
    }
}