#![allow(dead_code)]
use rayon::prelude::*;
use std::sync::Arc;
use crate::graph::graph_structures::graph_from_strings;
use crate::graph::page_rank::*;
use crate::prelude::BixverseFloat;
#[derive(Clone, Debug, Default)]
pub enum TiedSumType {
#[default]
Min,
Max,
Avg,
}
pub fn parse_tied_sum(s: &str) -> Option<TiedSumType> {
match s.to_lowercase().as_str() {
"max" => Some(TiedSumType::Max),
"min" => Some(TiedSumType::Min),
"mean" => Some(TiedSumType::Avg),
_ => None,
}
}
#[allow(clippy::too_many_arguments)]
pub fn tied_diffusion_parallel<T>(
node_names: Vec<String>,
from: Vec<String>,
to: Vec<String>,
weights: Option<&[T]>,
summarisation_fun: String,
personalise_vecs_1: &[Vec<T>],
personalise_vecs_2: &[Vec<T>],
undirected: bool,
damping_factor: T,
max_iter: usize,
tol: T,
) -> Vec<Vec<T>>
where
T: BixverseFloat + std::iter::Sum,
{
let summarisation_type: TiedSumType = parse_tied_sum(&summarisation_fun).unwrap();
let graph_1 = graph_from_strings(&node_names, &from, &to, weights, undirected);
let graph_2 = if !undirected {
graph_from_strings(&node_names, &to, &from, weights, undirected)
} else {
graph_from_strings(&node_names, &from, &to, weights, undirected)
};
let half = T::from_f64(0.5).unwrap();
let pagerank_graph_1 = Arc::new(PageRankGraph::from_petgraph(graph_1));
let pagerank_graph_2 = Arc::new(PageRankGraph::from_petgraph(graph_2));
let tied_res: Vec<Vec<T>> = personalise_vecs_1
.into_par_iter()
.zip(personalise_vecs_2.into_par_iter())
.map_init(
|| (PageRankWorkingMemory::new(), PageRankWorkingMemory::new()),
|(working_mem1, working_mem2), (diff1, diff2)| {
let pr1 = personalised_page_rank_optimised(
&pagerank_graph_1,
damping_factor,
diff1,
max_iter,
tol,
working_mem1,
);
let pr2 = personalised_page_rank_optimised(
&pagerank_graph_2,
damping_factor,
diff2,
max_iter,
tol,
working_mem2,
);
pr1.iter()
.zip(pr2.iter())
.map(|(&v1, &v2)| match summarisation_type {
TiedSumType::Max => v1.max(v2),
TiedSumType::Min => v1.min(v2),
TiedSumType::Avg => (v1 + v2) * half, })
.collect()
},
)
.collect();
tied_res
}