/// /// Initializes a new instance of the class. /// explicit basic_neighbor_joining( const matrix_type & distances) ///< The distance matrix. : _children () , _lengths () , _names () , _root (invalid_id) { // // Allow empty matrices even though no tree will be produced from // the write method. // if (distances.is_empty()) return; // // Allow just one node even though the tree produced from the write // method will consist on only the node name ("0"). // assert(distances.is_square()); auto n = distances.get_height(); id_type next_id = 0; if (n == 1) { _root = _add_leaf(next_id); return; } // // Prepare a list of ids for the initial set of nodes. // typedef std::vector<id_type> vector_type; vector_type x; for (size_t i = 0; i < n; i++) x.push_back(_add_leaf(next_id)); // // Prepare the distance matrix that will be reduced by the // algorithm. // matrix_type d (distances); // // Loop until there are only two nodes remaining in the distance // matrix. // while (n > 2) { // // Find the minimum Q value in the matrix, and use it to find // the two nodes that will be joined. Join them by creating a // new parent node. // const q_data q (d); const id_type id (next_id++); _add_parent(id, x[q.i], q.d_ik); _add_parent(id, x[q.j], q.d_jk); // // Prepare the new, reduced distance matrix as well as the // corresponding id vector. // matrix_type dd (n - 1, n - 1); vector_type xx { id }; for (size_t r = 0, rr = 1; r < n; r++) { if (r == q.i || r == q.j) continue; xx.push_back(x[r]); dd(rr, 0) = value_type(0.5) * (d(r, q.i) + d(r, q.j) - q.d_ij); for (size_t c = 0, cc = 1; c < r; c++) if (c != q.i && c != q.j) dd(rr, cc++) = d(r, c); rr++; } // // Copy the lower triangle to the upper triangle so the data // in the next Q matrix matches the expected values. // dd.copy_lower_to_upper(); d.swap(dd); x.swap(xx); n--; } // // Connect the last two nodes; note the loop above places new nodes // at index zero, so here it is known that the leaf node must be at // index 1, and so the root note must be at index 0. // _root = x[0]; _add_parent(_root, x[1], d(1, 0)); }