icentral-rbfs 0.1.0

A Rust crate for calculating and updating betweenness centrality scores in graphs using Recursive Breit-First Search strategies, optimized for dynamic and static networks.
Documentation
crate::ix!();

pub fn rbfs_graph(
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    info!(
        "running rbfs from source: {}, op: {:?}", 
        source, 
        op
    );

    while let Some(w) = workspace.stack_pop() {

        debug!("rbfs_graph, processing item popped from stack, {}", w);

        rbfs_graph_step(
            w, 
            delta_bc_of_vertices, 
            source, 
            workspace, 
            op
        )?;
    }

    debug!(
        "updated delta_bc_of_vertices: {:?}",
        delta_bc_of_vertices
    );

    Ok(())
}

fn rbfs_graph_step(
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    rbfs_graph_step_parents(
        w, 
        delta_bc_of_vertices, 
        source, 
        workspace, 
        op
    )?;

    debug!("workspace.deltas: {:?}", workspace.deltas());

    rbfs_graph_step_tail(
        w, 
        delta_bc_of_vertices, 
        source, 
        workspace, 
        op
    )?;

    Ok(())
}

//------------------------------------------------
fn rbfs_graph_step_parents(
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    let parents = workspace.parents_for_node(w);

    debug!("found parents for {}: {:?}", w, parents);

    for &v in parents.iter() {

        debug!("rbfs_graph_step_parents, processing parent={}", v);

        rbfs_graph_step_parent(
            v, 
            w, 
            delta_bc_of_vertices, 
            source, 
            workspace, 
            op
        )?;
    }

    Ok(())
}

fn rbfs_graph_step_parent(
    v:                    NodeId,
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    let p0 = workspace.sigma_value_for_node(v) as f64;
    let p1 = workspace.sigma_value_for_node(w) as f64;

    let t0 = p0 / p1;

    let t1 = workspace.delta_value_for_node(w);

    let res = t0 * (1.0 + t1);

    debug!(
        "updating deltas[v] with {} -- inputs: v={}, w={}, p0={}, p1={}, t1={}", 
        res,
        v, 
        w, 
        p0, 
        p1, 
        t1
    );

    workspace.increment_delta_value_for_node(v, res);

    Ok(())
}

//------------------------------------------------
fn rbfs_graph_step_tail(
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    if w != source {

        match op {

            Some(RbfsOperation::Addition) 
                => rbfs_graph_step_tail_add(
                    w, 
                    delta_bc_of_vertices, 
                    source, 
                    workspace, 
                    op
                )?,

            Some(RbfsOperation::Subtraction) 
                => rbfs_graph_step_tail_subtract(
                    w, 
                    delta_bc_of_vertices, 
                    source, 
                    workspace, 
                    op
                )?,

            _ => {
                warn!("rbfs_graph_step_tail, found noop={:?} ", op);
                warn!("This may not actually be a problem, but we still ought to know why it is happening and where it is coming from");
            }
        }
    } else {

        debug!(
            "rbfs_graph_step_tail, found that w={} equals source={}", 
            w, 
            source
        );
    }

    Ok(())
}

fn rbfs_graph_step_tail_add(
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    let addend = workspace.delta_value_for_node(w) / 2.0;

    debug!("increasing delta_bc_of_vertices.score_for_node w={} by {}", w, addend);

    delta_bc_of_vertices.increase_score_for_node(
        w, 
        addend
    ); 

    Ok(())
}

fn rbfs_graph_step_tail_subtract(
    w:                    NodeId,
    delta_bc_of_vertices: &mut BetweennessScores,
    source:               NodeId,
    workspace:            &mut ICentralWorkspace,
    op:                   &Option<RbfsOperation>) 
-> Result<(),BetweennessCentralityError> 
{
    let subtrahend = workspace.delta_value_for_node(w) / 2.0;

    debug!(
        "decreasing delta_bc_of_vertices.score_for_node w={} by {}", 
        w, 
        subtrahend
    );

    delta_bc_of_vertices.decrease_score_for_node(
        w, 
        subtrahend
    );

    Ok(())
}