crate::ix!();
pub fn insertion_test_fuad_max_iter<GH>(
graph: &mut Graph<GH>,
num_edges_to_insert: usize,
num_iter: usize,
time_to_run_all_iter: Option<Duration>,
rand_edge_vec: Option<Vec<Edge>>)
-> Result<(),BetweennessCentralityError>
where
GH
: NumNodes
+ NumEdges
+ GraphHashMucInterface
+ GetEdges
+ InsertEdge
+ CreateNamedEmpty
+ GraphHashMucInterface
+ ResetWith<GH>
+ RemoveEdge
+ FindSingleSourceShortestPaths
+ GetNodeIdRange
+ GetNeighborsForNode
+ ParentsForNode
+ InitDebugIteration
+ DebugIterationStep
+ FindPruningCounts
+ HasEdge
+ PathCountForNode
+ PairDependencyForNode
+ SetPairDependencyForNode
+ SetSigmaValueForNode
+ GetSigmaValueForNode
, Graph<GH>
: MappedNodes
+ GetLimitedNodeIdRange
+ NumNodes
+ HasEdge
{
let time_to_run_all_iter: Duration = time_to_run_all_iter.unwrap_or(Duration::from_secs(0));
let mut rand_edge_vec: Vec<Edge> = rand_edge_vec.unwrap_or(vec![]);
graph.print_header();
let mut brandes_time = Duration::from_secs(0);
let mut tm: Timer = default!();
debug!("Brandes runtime: ");
tm.start();
let scores: BetweennessScores = brandes_bc_hash_out(
graph,
Some(num_iter)
)?;
tm.stop();
brandes_time = tm.interval() * graph.num_nodes() as u32 / num_iter as u32;
let mut do_all_iter: bool = false;
if brandes_time < time_to_run_all_iter {
do_all_iter = true;
}
if do_all_iter {
tm.start();
let scores: BetweennessScores = brandes_bc_hash_out(
graph,
None
)?;
tm.stop();
brandes_time = tm.interval();
debug!("{:?}", brandes_time);
debug!("Brandes avg iter time: {:?}", tm.interval() / graph.num_nodes() as u32);
debug!("WILL DO ALL ITERATIONS...");
} else {
debug!("{:?}", brandes_time);
debug!("Brandes avg iter time: {:?}", tm.interval() / num_iter as u32);
}
if rand_edge_vec.len() == 0 {
debug!("Generating edges...");
let mut rng = WyRand::default();
rand_edge_vec = gen_rand_edges(
&mut rng,
num_edges_to_insert,
graph
)?;
}
let mut tot_fuad_time = Duration::from_secs(0);
let mut tot_speedup: f64 = 0.0;
let mut tot_ideal_speedup_perfect: f64 = 0.0;
let mut tot_ideal_speedup: f64 = 0.0;
let mut bcc_stat_vec: Vec<BiconnectedComponentsStat> = default!();
let mut speedup_vec: Vec<f64> = default!();
for i in 0..rand_edge_vec.len() {
let mut bcc_stat: BiconnectedComponentsStat = BiconnectedComponentsStat::default();
let rand_edge: Edge = rand_edge_vec[i];
let mut est_time = Duration::from_secs(0);
debug!(
"Inserting edge ({}, {}) and updating bc...",
rand_edge.src,
rand_edge.dst
);
tm.start();
graph.insert_edge_update_bc_experimental(
&rand_edge,
&mut bcc_stat,
Some(num_iter),
Some(num_iter)
);
tm.stop();
if do_all_iter {
est_time = bcc_stat.bc_update_time + bcc_stat.bcc_find_time;
}
let mut avg_iter_time_naive = Duration::from_secs(0);
graph.approx_bcc_iter_tm(
rand_edge.src,
rand_edge.dst,
&mut avg_iter_time_naive,
Some(num_iter)
);
tot_fuad_time += tm.interval();
if bcc_stat.num_d0_iter == 0 {
bcc_stat.num_d0_iter = 1;
bcc_stat.tot_d0_tm = Duration::from_secs(0);
}
if bcc_stat.num_d1_iter == 0 {
bcc_stat.num_d1_iter = 1;
bcc_stat.tot_d1_tm = Duration::from_secs(0);
}
if bcc_stat.num_d2_iter == 0 {
bcc_stat.num_d2_iter = 1;
bcc_stat.tot_d2_tm = Duration::from_secs(0);
}
if !do_all_iter {
est_time += {
bcc_stat.tot_d1_tm * bcc_stat.tot_d1_iter as u32 / bcc_stat.num_d1_iter as u32
};
est_time += {
bcc_stat.tot_d2_tm * bcc_stat.tot_d2_iter as u32 / bcc_stat.num_d2_iter as u32
};
}
tot_speedup += brandes_time.div_duration_f64(est_time);
speedup_vec.push(brandes_time.div_duration_f64(est_time));
let mut ideal_speedup_perfect: f64 = 0.0;
let mut ideal_speedup: f64 = 0.0;
let g_n: f64 = graph.num_nodes() as f64;
let g_m: f64 = graph.num_edges() as f64;
let bcc_n: f64 = bcc_stat.bcc_num_nodes as f64;
let bcc_m: f64 = bcc_stat.bcc_num_edges as f64;
let inc_iter_ratio: f64 = 150.0;
let iter_frac: f64 = 1.0 - (bcc_stat.tot_d0_iter as f64 / bcc_n);
ideal_speedup_perfect = fuad_ideal_speedup(
iter_frac,
bcc_n,
bcc_m,
g_n,
g_m,
100.0
);
ideal_speedup = fuad_ideal_speedup(
iter_frac,
bcc_n,
bcc_m,
g_n,
g_m,
inc_iter_ratio
);
tot_ideal_speedup_perfect += ideal_speedup_perfect;
tot_ideal_speedup += ideal_speedup;
let mut in_mem_speedup: f64 = 0.0;
let mut in_mem_time = Duration::from_secs(0);
in_mem_time += {
let t0 = bcc_stat.tot_d1_tm / bcc_stat.num_d1_iter as u32 - avg_iter_time_naive;
t0 * bcc_stat.tot_d1_iter as u32
};
in_mem_time += {
let t0 = bcc_stat.tot_d2_tm / bcc_stat.num_d2_iter as u32 - avg_iter_time_naive;
t0 * bcc_stat.tot_d2_iter as u32
};
in_mem_speedup = brandes_time.div_duration_f64(in_mem_time);
debug!(
"Stored DAGS ideal speedup: {}",
in_mem_speedup
);
debug!(
"BiconnectedComponents num nodes: {} ({} G_n)",
bcc_stat.bcc_num_nodes,
bcc_stat.bcc_num_nodes as f64 / graph.num_nodes() as f64
);
debug!(
"BiconnectedComponents num edges: {} ({} G_m)",
bcc_stat.bcc_num_edges,
bcc_stat.bcc_num_edges as f64 / graph.num_edges() as f64
);
debug!("");
debug!("Time to update BC: {:?}", est_time);
debug!(
"Speedup: {} (Ideal: {} - {})",
brandes_time.div_duration_f64(est_time),
ideal_speedup,
ideal_speedup_perfect
);
debug!("");
debug!(
"BiconnectedComponents d1 time: {:?} ({:?} to naive iter)",
bcc_stat.tot_d1_tm / bcc_stat.num_d1_iter as u32,
(bcc_stat.tot_d1_tm / bcc_stat.num_d1_iter as u32).div_duration_f64(avg_iter_time_naive)
);
debug!(
"BiconnectedComponents d2 time: {:?} ({:?} to naive iter)",
bcc_stat.tot_d2_tm / bcc_stat.num_d2_iter as u32,
(bcc_stat.tot_d2_tm / bcc_stat.num_d2_iter as u32).div_duration_f64(avg_iter_time_naive)
);
debug!(
"avg iter time naive: {:?} ({:?} to naive iter)",
avg_iter_time_naive,
avg_iter_time_naive.div_duration_f64(avg_iter_time_naive)
);
debug!("");
debug!(
"BiconnectedComponents num/tot d0 BFS: {:8}/{:8} ({} to BiconnectedComponents_n)",
bcc_stat.num_d0_iter,
bcc_stat.tot_d0_iter,
bcc_stat.tot_d0_iter as f64 / bcc_stat.bcc_num_nodes as f64
);
debug!(
"BiconnectedComponents num/tot d1 BFS: {:8}/{:8} ({} to BiconnectedComponents_n)",
bcc_stat.num_d1_iter,
bcc_stat.tot_d1_iter,
bcc_stat.tot_d1_iter as f64 / bcc_stat.bcc_num_nodes as f64
);
debug!(
"BiconnectedComponents num/tot d2 BFS: {:8}/{:8} ({} to BiconnectedComponents_n)",
bcc_stat.num_d2_iter,
bcc_stat.tot_d2_iter,
bcc_stat.tot_d2_iter as f64 / bcc_stat.bcc_num_nodes as f64
);
debug!("");
debug!("BiconnectedComponents bcc find time: {:?}", bcc_stat.bcc_find_time);
debug!("BiconnectedComponents single_source_shortest_paths time: {:?}", bcc_stat.single_source_shortest_paths_tm);
bcc_stat_vec.push(bcc_stat);
}
let avg_speedup: f64 = tot_speedup / num_edges_to_insert as f64;
let avg_ideal_speedup_perfect: f64 = tot_ideal_speedup_perfect / num_edges_to_insert as f64;
let avg_ideal_speedup: f64 = tot_ideal_speedup / num_edges_to_insert as f64;
debug!(
"[[Average speedup: {} (Ideal: {} - {})]]",
avg_speedup,
avg_ideal_speedup,
avg_ideal_speedup_perfect
);
let stats = SpeedupStats::from(&mut speedup_vec);
let diff: f64 = 1.96 * stats.stddev / num_edges_to_insert.sqrt() as f64;
let v1: f64 = stats.mean - diff;
let v2: f64 = stats.mean + diff;
debug!("[[Speedup 95 CI: {} - {}]]", v1, v2);
Ok(())
}