use crate::{
distances::DistanceMatrix, naive_nj::DataNaiveNJ, rapid_nj::DataRapidNJ, ResultBox, Tree,
};
pub fn neighbor_joining(
dist: DistanceMatrix,
naive_iters: usize,
chunk_size: usize,
) -> ResultBox<Tree> {
if dist.size() < 4 || naive_iters >= dist.size() {
return crate::naive_nj::canonical_neighbor_joining(dist);
}
if naive_iters < 4 {
return crate::rapid_nj::rapid_nj(dist, chunk_size);
}
let mut q = crate::rapid_nj::QMatrix::from(&dist);
let mut t = crate::rapid_nj::PhyloTree::build(&dist.names);
q.set_chunk_size(chunk_size);
while q.n_leaves() > naive_iters {
let (i, j) = q.find_neighbors();
let (dist_ui, dist_uj) = q.new_node_distances(i, j);
t.merge_neighbors(i, j, dist_ui, dist_uj);
q.update(i, j);
}
let data = DataNaiveNJ::from(DataRapidNJ::new(q, t));
let mut q = data.qmatrix;
let mut t = data.phylo_tree;
while q.n_leaves() > 3 {
let (i, j) = q.find_neighbors();
let (dist_ui, dist_uj) = q.new_node_distances(i, j);
t.merge_neighbors(i, j, dist_ui, dist_uj);
q.update_distance_matrix(i, j);
}
Ok(crate::naive_nj::terminate_nj(t, q))
}