From 0e535ad809ee1e45a474c46b8734eeae8e224496 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 29 Feb 2020 21:42:39 +0000 Subject: [PATCH 01/57] Add union operation on k2 tree --- include/sdsl/k2_tree.hpp | 979 ++++++++++++++++++++++----------------- test/k2_tree_test.cpp | 68 +++ 2 files changed, 612 insertions(+), 435 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index f8b8f6e78..bf574060f 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -46,71 +46,76 @@ namespace sdsl */ template + typename t_bv=bit_vector, + typename t_rank=typename t_bv::rank_1_type> class k2_tree { - public: - typedef k2_tree_ns::idx_type idx_type; - typedef k2_tree_ns::size_type size_type; - - private: - //! Bit array to store all the bits of the tree, except those in the - //! last level. - t_bv k_t; - //! Bit array to store the last level of the tree. - t_bv k_l; - - t_rank k_t_rank; - - uint8_t k_k; - uint16_t k_height; - - protected: - - void build_from_matrix(const std::vector>& matrix) - { - // Makes the size a power of k. - int simulated_size = std::pow(k, k_height); - std::vector> acc(k_height + 1); - - k2_tree_ns::_build_from_matrix(matrix, k, - simulated_size, k_height, - 1, 0, 0, acc); - - size_type t_size = 0; - size_type l_size = 0; - for (int i = 1; i < k_height; i++) - for (auto it = acc[i].begin(); it != acc[i].end(); it++) - t_size += (*it).size(); - - for (auto it = acc[k_height].begin(); it != acc[k_height].end(); it++) - l_size += (*it).size(); - - bit_vector k_t_(t_size, 0); - bit_vector k_l_(l_size, 0); - - int n = 0; - for (int j = 1; j < k_height; j++) - for (auto it = acc[j].begin(); it != acc[j].end(); it++) - for (unsigned i = 0; i < (*it).size(); i++) { - // TODO there should be a better way to do this - k_t_.set_int(n, (*it).get_int(i, 1), 1); - n++; - } - n = 0; - for (auto it = acc[k_height].begin(); it != acc[k_height].end(); it++) +public: + typedef k2_tree_ns::idx_type idx_type; + typedef k2_tree_ns::size_type size_type; + +private: + //! Bit array to store all the bits of the tree, except those in the + //! last level. + t_bv k_t; + //! Bit array to store the last level of the tree. + t_bv k_l; + + size_t k_t_size; + size_t k_l_size; + + t_rank k_t_rank; + + uint8_t k_k; + uint16_t k_height; + +protected: + + void build_from_matrix(const std::vector>& matrix) + { + // Makes the size a power of k. + int simulated_size = std::pow(k, k_height); + std::vector> acc(k_height + 1); + + k2_tree_ns::_build_from_matrix(matrix, k, + simulated_size, k_height, + 1, 0, 0, acc); + + size_type t_size = 0; + size_type l_size = 0; + for (int i = 1; i < k_height; i++) + for (auto it = acc[i].begin(); it != acc[i].end(); it++) + t_size += (*it).size(); + + for (auto it = acc[k_height].begin(); it != acc[k_height].end(); it++) + l_size += (*it).size(); + + bit_vector k_t_(t_size, 0); + bit_vector k_l_(l_size, 0); + k_t_size = t_size; + k_l_size = l_size; + + int n = 0; + for (int j = 1; j < k_height; j++) + for (auto it = acc[j].begin(); it != acc[j].end(); it++) for (unsigned i = 0; i < (*it).size(); i++) { // TODO there should be a better way to do this - k_l_.set_int(n * 1, (*it).get_int(i, 1), 1); + k_t_.set_int(n, (*it).get_int(i, 1), 1); n++; } + n = 0; + for (auto it = acc[k_height].begin(); it != acc[k_height].end(); it++) + for (unsigned i = 0; i < (*it).size(); i++) { + // TODO there should be a better way to do this + k_l_.set_int(n * 1, (*it).get_int(i, 1), 1); + n++; + } - k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); - } + k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); + } - /*! Recursive function to retrieve list of neighbors. + /*! Recursive function to retrieve list of neighbors. * * \param n Size of the submatrix in the next recursive step. * \param row Row of interest in the current submatrix, this is the @@ -121,24 +126,24 @@ class k2_tree * or leaf being processed at this step. * \param acc Accumulator to store the neighbors found. */ - void _neigh(size_type n, idx_type row, idx_type col, size_type level, - std::vector& acc) const - { - if (level >= k_t.size()) { // Last level - if (k_l[level - k_t.size()] == 1) - acc.push_back(col); - return; - } + void _neigh(size_type n, idx_type row, idx_type col, size_type level, + std::vector& acc) const + { + if (level >= k_t.size()) { // Last level + if (k_l[level - k_t.size()] == 1) + acc.push_back(col); + return; + } - if (k_t[level] == 1) { - idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + - k_k * std::floor(row/static_cast(n)); - for (unsigned j = 0; j < k_k; j++) - _neigh(n/k_k, row % n, col + n * j, y + j, acc); - } + if (k_t[level] == 1) { + idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + + k_k * std::floor(row/static_cast(n)); + for (unsigned j = 0; j < k_k; j++) + _neigh(n/k_k, row % n, col + n * j, y + j, acc); } + } - /*! Recursive function to retrieve list of reverse neighbors. + /*! Recursive function to retrieve list of reverse neighbors. * * \param n Size of the submatrix in the next recursive step. * \param row Row offset of the current submatrix in the global matrix. @@ -149,27 +154,27 @@ class k2_tree * or leaf being processed at this step. * \param acc Accumulator to store the neighbors found. */ - void _reverse_neigh(size_type n, idx_type row, idx_type col, - size_type level, std::vector& acc) const - { - if (level >= k_t.size()) { // Last level - if (k_l[level - k_t.size()] == 1) { - acc.push_back(row); - } - return; + void _reverse_neigh(size_type n, idx_type row, idx_type col, + size_type level, std::vector& acc) const + { + if (level >= k_t.size()) { // Last level + if (k_l[level - k_t.size()] == 1) { + acc.push_back(row); } + return; + } - if (k_t[level] == 1) { - idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + - std::floor(col/static_cast(n)); - for (unsigned j = 0; j < k_k; j++) - _reverse_neigh(n/k_k, row + n * j, col % n, - y + j * k_k, acc); - } + if (k_t[level] == 1) { + idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + + std::floor(col/static_cast(n)); + for (unsigned j = 0; j < k_k; j++) + _reverse_neigh(n/k_k, row + n * j, col % n, + y + j * k_k, acc); } + } - //! Build a tree from an edges collection - /*! This method takes a vector of edges describing the graph + //! Build a tree from an edges collection + /*! This method takes a vector of edges describing the graph * and the graph size. And takes linear time over the amount of * edges to build the k_2 representation. * \param edges A vector with all the edges of the graph, it can @@ -177,128 +182,128 @@ class k2_tree * \param size Size of the graph, all the nodes in edges must be * within 0 and size ([0, size[). */ - void build_from_edges(std::vector>& edges, - const size_type size) - { - - typedef std::tuple t_part_tuple; - - k_k = k; - k_height = std::ceil(std::log(size)/std::log(k_k)); - k_height = k_height > 1 ? k_height : 1; // If size == 0 - size_type k_2 = std::pow(k_k, 2); - bit_vector k_t_ = bit_vector(k_2 * k_height * edges.size(), 0); - bit_vector k_l_; - - std::queue q; - idx_type t = 0, last_level = 0; - idx_type i, j, r_0, c_0, it, c, r; - size_type l = std::pow(k_k, k_height - 1); - std::vector pos_by_chunk(k_2 + 1, 0); - - q.push(t_part_tuple(0, edges.size(), l, 0, 0)); - - while (!q.empty()) { - std::vector amount_by_chunk(k_2, 0); - std::tie(i, j, l, r_0, c_0) = q.front(); - q.pop(); - // Get size for each chunk - for (it = i; it < j; it++) - amount_by_chunk[k2_tree_ns::get_chunk_idx( - std::get<0>(edges[it]), std::get<1>(edges[it]), - c_0, r_0, l, k_k)] += 1; - if (l == 1) { - if (last_level == 0) { - last_level = t; - k_l_ = bit_vector(k_t_.size() - last_level, 0); - k_t_.resize(last_level); - last_level = 1; // if t was 0 - t = 0; // Restart counter as we're storing at k_l_ now. - } - for (it = 0; it < k_2; it++,t++) - if (amount_by_chunk[it] != 0) - k_l_[t] = 1; - // At l == 1 we do not put new elements at the queue. - continue; + void build_from_edges(std::vector>& edges, + const size_type size) + { + + typedef std::tuple t_part_tuple; + + k_k = k; + k_height = std::ceil(std::log(size)/std::log(k_k)); + k_height = k_height > 1 ? k_height : 1; // If size == 0 + size_type k_2 = std::pow(k_k, 2); + bit_vector k_t_ = bit_vector(k_2 * k_height * edges.size(), 0); + bit_vector k_l_; + + std::queue q; + idx_type t = 0, last_level = 0; + idx_type i, j, r_0, c_0, it, c, r; + size_type l = std::pow(k_k, k_height - 1); + std::vector pos_by_chunk(k_2 + 1, 0); + + q.push(t_part_tuple(0, edges.size(), l, 0, 0)); + + while (!q.empty()) { + std::vector amount_by_chunk(k_2, 0); + std::tie(i, j, l, r_0, c_0) = q.front(); + q.pop(); + // Get size for each chunk + for (it = i; it < j; it++) + amount_by_chunk[k2_tree_ns::get_chunk_idx( + std::get<0>(edges[it]), std::get<1>(edges[it]), + c_0, r_0, l, k_k)] += 1; + if (l == 1) { + if (last_level == 0) { + last_level = t; + k_l_ = bit_vector(k_t_.size() - last_level, 0); + k_t_.resize(last_level); + last_level = 1; // if t was 0 + t = 0; // Restart counter as we're storing at k_l_ now. } - - // Set starting position in the vector for each chunk - pos_by_chunk[0] = i; - for (it = 1; it < k_2; it++) - pos_by_chunk[it] = - pos_by_chunk[it - 1] + amount_by_chunk[it - 1]; - // To handle the last case when it = k_2 - 1 - pos_by_chunk[k_2] = j; - // Push to the queue every non zero elements chunk for (it = 0; it < k_2; it++,t++) - // If not empty chunk, set bit to 1 - if (amount_by_chunk[it] != 0) { - r = it / k_k; - c = it % k_k; - k_t_[t] = 1; - q.push(t_part_tuple(pos_by_chunk[it], - pos_by_chunk[it + 1], - l/k_k, - r_0 + r * l, - c_0 + c * l)); - } - idx_type chunk; - - // Sort edges' vector - for (unsigned ch = 0; ch < k_2; ch++) { - idx_type be = ch == 0 ? i : pos_by_chunk[ch - 1]; - for (it = pos_by_chunk[ch]; it < be + amount_by_chunk[ch];) { - chunk = k2_tree_ns::get_chunk_idx( - std::get<0>(edges[it]), std::get<1>(edges[it]), - c_0, r_0, l, k_k); - - if (pos_by_chunk[chunk] != it) - std::iter_swap(edges.begin() + it, - edges.begin() + pos_by_chunk[chunk]); - else - it++; - pos_by_chunk[chunk]++; - } + if (amount_by_chunk[it] != 0) + k_l_[t] = 1; + // At l == 1 we do not put new elements at the queue. + continue; + } + + // Set starting position in the vector for each chunk + pos_by_chunk[0] = i; + for (it = 1; it < k_2; it++) + pos_by_chunk[it] = + pos_by_chunk[it - 1] + amount_by_chunk[it - 1]; + // To handle the last case when it = k_2 - 1 + pos_by_chunk[k_2] = j; + // Push to the queue every non zero elements chunk + for (it = 0; it < k_2; it++,t++) + // If not empty chunk, set bit to 1 + if (amount_by_chunk[it] != 0) { + r = it / k_k; + c = it % k_k; + k_t_[t] = 1; + q.push(t_part_tuple(pos_by_chunk[it], + pos_by_chunk[it + 1], + l/k_k, + r_0 + r * l, + c_0 + c * l)); + } + idx_type chunk; + + // Sort edges' vector + for (unsigned ch = 0; ch < k_2; ch++) { + idx_type be = ch == 0 ? i : pos_by_chunk[ch - 1]; + for (it = pos_by_chunk[ch]; it < be + amount_by_chunk[ch];) { + chunk = k2_tree_ns::get_chunk_idx( + std::get<0>(edges[it]), std::get<1>(edges[it]), + c_0, r_0, l, k_k); + + if (pos_by_chunk[chunk] != it) + std::iter_swap(edges.begin() + it, + edges.begin() + pos_by_chunk[chunk]); + else + it++; + pos_by_chunk[chunk]++; } } - k_l_.resize(t); - k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); + } + k_l_.resize(t); + k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); - k_t_rank = t_rank(&k_t); + k_t_rank = t_rank(&k_t); - } + } - public: +public: - k2_tree() = default; + k2_tree() = default; - //! Constructor - /*! This constructos takes the graph adjacency matrix. + //! Constructor + /*! This constructos takes the graph adjacency matrix. * The time complexity for this constructor is linear in the matrix * size * \param matrix Adjacency matrix of the graph. It must be a binary * square matrix. */ - k2_tree(const std::vector> &matrix) - { - if (matrix.size() < 1) { - throw std::logic_error("Matrix has no elements"); - } - std::vector t; - k_k = k; - if (matrix.size() < k_k) - k_height = 1; - else // height = log_k n - k_height = std::ceil(std::log(matrix.size())/std::log(k_k)); + k2_tree(const std::vector> &matrix) + { + if (matrix.size() < 1) { + throw std::logic_error("Matrix has no elements"); + } + std::vector t; + k_k = k; + if (matrix.size() < k_k) + k_height = 1; + else // height = log_k n + k_height = std::ceil(std::log(matrix.size())/std::log(k_k)); - build_from_matrix(matrix); + build_from_matrix(matrix); - k_t_rank = t_rank(&k_t); - } + k_t_rank = t_rank(&k_t); + } - //! Constructor - /*! This constructos takes a vector of edges describing the graph + //! Constructor + /*! This constructos takes a vector of edges describing the graph * and the graph size. And takes linear time over the amount of * edges to build the k_2 representation. * \param edges A vector with all the edges of the graph, it can @@ -306,17 +311,17 @@ class k2_tree * \param size Size of the graph, all the nodes in edges must be * within 0 and size ([0, size[). */ - k2_tree(std::vector>& edges, - const size_type size) - { - assert(size > 0); - assert(edges.size() > 0); + k2_tree(std::vector>& edges, + const size_type size) + { + assert(size > 0); + assert(edges.size() > 0); - build_from_edges(edges, size); - } + build_from_edges(edges, size); + } - //! Constructor - /*! This constructos expects a filename prefix. Two serialized + //! Constructor + /*! This constructos expects a filename prefix. Two serialized * int_vectors have to be present at filename.x and filename.y. * Each pair x,y describes an edge of the graph, from the node x * to the node y. @@ -328,283 +333,387 @@ class k2_tree * size==0, the size will be taken as the max node * in the edges. */ - k2_tree(std::string filename, size_type size=0) - { - int_vector_buffer<> buf_x(filename + ".x", std::ios::in); - int_vector_buffer<> buf_y(filename + ".y", std::ios::in); - - assert(buf_x.size() == buf_y.size()); - assert(buf_x.size() > 0); - - std::vector>edges; - edges.reserve(buf_x.size()); - - if(size==0) { - size_type max = 0; - for(auto v : buf_x) - max = std::max(static_cast(v), max); - for(auto v : buf_y) - max = std::max(static_cast(v), max); - size = max + 1; - } - - for(uint64_t i = 0; i < buf_x.size(); i++) - edges.push_back( - std::tuple {buf_x[i], buf_y[i]}); - - build_from_edges(edges, size); - } - - - k2_tree(const k2_tree& tr) - { - *this = tr; + k2_tree(std::string filename, size_type size=0) + { + int_vector_buffer<> buf_x(filename + ".x", std::ios::in); + int_vector_buffer<> buf_y(filename + ".y", std::ios::in); + + assert(buf_x.size() == buf_y.size()); + assert(buf_x.size() > 0); + + std::vector>edges; + edges.reserve(buf_x.size()); + + if(size==0) { + size_type max = 0; + for(auto v : buf_x) + max = std::max(static_cast(v), max); + for(auto v : buf_y) + max = std::max(static_cast(v), max); + size = max + 1; } - k2_tree(k2_tree&& tr) - { - *this = std::move(tr); - } + for(uint64_t i = 0; i < buf_x.size(); i++) + edges.push_back( + std::tuple {buf_x[i], buf_y[i]}); + + build_from_edges(edges, size); + } + + + k2_tree(const k2_tree& tr) + { + *this = tr; + } + + k2_tree(k2_tree&& tr) + { + *this = std::move(tr); + } + + k2_tree(t_bv t, t_bv l, uint16_t height, uint8_t k_branch) : k_k(k_branch), k_height(height) + { + k_t = std::move(t); + k_l = std::move(l); + k_t_rank = t_rank(&k_t); + } + + //! Union Operation + /*! Performs the union operation between two tree. This operations requires both + * trees to have the same number of nodes. + * \param k2_B a k2_tree with the same number of nodes + * \par References + * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over + * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. + */ + k2_tree unionOp(k2_tree& k2_B) + { + + assert(this->k_k == k2_B.k_k); + if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) + throw std::logic_error("Trees must have the same number of nodes."); + + size_t t_size_A = this->get_t().size(); + size_t t_size_B = k2_B.get_t().size(); + + // C Initialization + const size_t max_height = this->get_height() > k2_B.get_height() ? this->get_height() : k2_B.get_height(); + std::deque> C(max_height); + //////// + + // Q Initialization + std::deque> Q; + Q.push_back({0, 1, 1}); + //////// + + std::array next; + uint pA, pB; + pA = 0; + pB = 0; + + while (!Q.empty()) { + next = Q.front(); + Q.pop_front(); + + uint l = next[0]; + uint rA = next[1]; + uint rB = next[2]; + + for (size_t i = 0; i < k_k * k_k; ++i) + { + uint bA, bB; + bA = 0; + bB = 0; + if (rA == 1) + { + if (l + 1 < this->get_height()) + bA = this->get_t()[pA]; + else + bA = this->get_l()[pA - t_size_A]; + pA++; + } + if (rB == 1) + { + if (l + 1 < k2_B.get_height()) + bB = k2_B.get_t()[pB]; + else + bB = k2_B.get_l()[pB - t_size_B]; + pB++; + } - //! Move assignment operator - k2_tree& operator=(k2_tree&& tr) - { - if (this != &tr) { - k_t = std::move(tr.k_t); - k_l = std::move(tr.k_l); - k_k = std::move(tr.k_k); - k_height = std::move(tr.k_height); - k_t_rank = std::move(tr.k_t_rank); - k_t_rank.set_vector(&k_t); - } - return *this; - } + C[l].push_back(bA || bB); - //! Assignment operator - k2_tree& operator=(k2_tree& tr) - { - if (this != &tr) { - k_t = tr.k_t; - k_l = tr.k_l; - k_t_rank = tr.k_t_rank; - k_t_rank.set_vector(&k_t); - k_k = tr.k_k; - k_height = tr.k_height; + if ((l + 1 < this->k_height || l + 1 < k2_B.get_height())&& (bA || bB)) + Q.push_back({l + 1, bA, bB}); } - return *this; } - //! Swap operator - void swap(k2_tree& tr) - { - if (this != &tr) { - std::swap(k_t, tr.k_t); - std::swap(k_l, tr.k_l); - util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t)); - std::swap(k_k, tr.k_k); - std::swap(k_height, tr.k_height); + // Create new K2 tree from union operation + size_t t_size = 0; + for (size_t l = 0; l < max_height - 1; l++) + t_size += C[l].size(); + + bit_vector t(t_size, 0); + bit_vector l(C[max_height - 1].size(), 0); + + size_t p = 0; + for (size_t l = 0; l < max_height - 1; l++) + for (size_t bit = 0; bit < C[l].size(); bit++) + { + t.set_int(p, C[l][bit]); + ++p; } - } - //! Equal operator - bool operator==(const k2_tree& tr) const - { - // TODO check the rank support equality? - if (k_k != tr.k_k || k_height != tr.k_height) - return false; - if (k_t.size() != tr.k_t.size() || k_l.size() != tr.k_l.size()) - return false; - for (unsigned i = 0; i < k_t.size(); i++) - if (k_t[i] != tr.k_t[i]) - return false; - for (unsigned i = 0; i < k_l.size(); i++) - if (k_l[i] != tr.k_l[i]) - return false; - return true; + for (size_t bit = 0; bit < C[max_height - 1].size(); bit++) + l.set_int(bit, C[max_height - 1][bit]); + + return k2_tree(t, l, max_height, k_k); + } + + //! Move assignment operator + k2_tree& operator=(k2_tree&& tr) + { + if (this != &tr) { + k_t = std::move(tr.k_t); + k_l = std::move(tr.k_l); + k_k = std::move(tr.k_k); + k_height = std::move(tr.k_height); + k_t_rank = std::move(tr.k_t_rank); + k_t_rank.set_vector(&k_t); } - - t_bv get_t() - { - return k_t; + return *this; + } + + //! Assignment operator + k2_tree& operator=(k2_tree& tr) + { + if (this != &tr) { + k_t = tr.k_t; + k_l = tr.k_l; + k_t_rank = tr.k_t_rank; + k_t_rank.set_vector(&k_t); + k_k = tr.k_k; + k_height = tr.k_height; } - - t_bv get_l() - { - return k_l; + return *this; + } + + //! Swap operator + void swap(k2_tree& tr) + { + if (this != &tr) { + std::swap(k_t, tr.k_t); + std::swap(k_l, tr.k_l); + util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t)); + std::swap(k_k, tr.k_k); + std::swap(k_height, tr.k_height); } - - //! Indicates whether node j is adjacent to node i or not. - /*! + } + + //! Equal operator + bool operator==(const k2_tree& tr) const + { + // TODO check the rank support equality? + if (k_k != tr.k_k || k_height != tr.k_height) + return false; + if (k_t.size() != tr.k_t.size() || k_l.size() != tr.k_l.size()) + return false; + for (unsigned i = 0; i < k_t.size(); i++) + if (k_t[i] != tr.k_t[i]) + return false; + for (unsigned i = 0; i < k_l.size(); i++) + if (k_l[i] != tr.k_l[i]) + return false; + return true; + } + + t_bv get_t() + { + return k_t; + } + + t_bv get_l() + { + return k_l; + } + + size_t get_height() + { + return k_height; + } + + //! Indicates whether node j is adjacent to node i or not. + /*! * \param i Node i. * \param j Node j. * \returns true if there is an edge going from node i to node j, * false otherwise. */ - bool adj(idx_type i, idx_type j) const - { - if (k_t.size() == 0 && k_l.size() == 0) + bool adj(idx_type i, idx_type j) const + { + if (k_t.size() == 0 && k_l.size() == 0) + return false; + size_type n = std::pow(k_k, k_height - 1); + size_type k_2 = std::pow(k_k, 2); + idx_type col, row; + + // This is duplicated to avoid an extra if at the loop. As idx_type + // is unsigned and rank has an offset of one, is not possible to run + // k_t_rank with zero as parameter at the first iteration. + row = std::floor(i/static_cast(n)); + col = std::floor(j/static_cast(n)); + i = i % n; + j = j % n; + idx_type level = k_k * row + col; + n = n/k_k; + + while (level < k_t.size()) { + if (k_t[level] == 0) return false; - size_type n = std::pow(k_k, k_height - 1); - size_type k_2 = std::pow(k_k, 2); - idx_type col, row; - - // This is duplicated to avoid an extra if at the loop. As idx_type - // is unsigned and rank has an offset of one, is not possible to run - // k_t_rank with zero as parameter at the first iteration. row = std::floor(i/static_cast(n)); col = std::floor(j/static_cast(n)); i = i % n; j = j % n; - idx_type level = k_k * row + col; + level = k_t_rank(level + 1) * k_2 + k_k * row + col; n = n/k_k; - - while (level < k_t.size()) { - if (k_t[level] == 0) - return false; - row = std::floor(i/static_cast(n)); - col = std::floor(j/static_cast(n)); - i = i % n; - j = j % n; - level = k_t_rank(level + 1) * k_2 + k_k * row + col; - n = n/k_k; - } - - return k_l[level - k_t.size()] == 1; } - //! Returns a list of neighbors of node i. - /*! + return k_l[level - k_t.size()] == 1; + } + + //! Returns a list of neighbors of node i. + /*! * \param i Node to get neighbors from. * \returns A list of neighbors of node i. */ - std::vector neigh(idx_type i) const - { - std::vector acc{}; - if (k_l.size() == 0 && k_t.size() == 0) - return acc; - // n = k^h / k - // k^h - dimension n of matrix nxn - // /k - to calculate div only once and not for for all parameter again, always (n/k) - size_type n = - static_cast(std::pow(k_k, k_height)) / k_k; - // y = k * i/n - idx_type y = k_k * std::floor(i/static_cast(n)); - for (unsigned j = 0; j < k_k; j++) - _neigh(n/k_k, i % n, n * j, y + j, acc); + std::vector neigh(idx_type i) const + { + std::vector acc{}; + if (k_l.size() == 0 && k_t.size() == 0) return acc; - } - - //! Returns a list of reverse neighbors of node i. - /*! + // n = k^h / k + // k^h - dimension n of matrix nxn + // /k - to calculate div only once and not for for all parameter again, always (n/k) + size_type n = + static_cast(std::pow(k_k, k_height)) / k_k; + // y = k * i/n + idx_type y = k_k * std::floor(i/static_cast(n)); + for (unsigned j = 0; j < k_k; j++) + _neigh(n/k_k, i % n, n * j, y + j, acc); + return acc; + } + + //! Returns a list of reverse neighbors of node i. + /*! * \param i Node to get reverse neighbors from. * \returns A list of reverse neighbors of node i. */ - std::vector reverse_neigh(idx_type i) const - { - std::vector acc{}; - if (k_l.size() == 0 && k_t.size() == 0) - return acc; - // Size of the first square division - size_type n = - static_cast(std::pow(k_k, k_height)) / k_k; - idx_type y = std::floor(i/static_cast(n)); - for (unsigned j = 0; j < k_k; j++) - _reverse_neigh(n/k_k, n * j, i % n, y + j * k_k, acc); - + std::vector reverse_neigh(idx_type i) const + { + std::vector acc{}; + if (k_l.size() == 0 && k_t.size() == 0) return acc; + // Size of the first square division + size_type n = + static_cast(std::pow(k_k, k_height)) / k_k; + idx_type y = std::floor(i/static_cast(n)); + for (unsigned j = 0; j < k_k; j++) + _reverse_neigh(n/k_k, n * j, i % n, y + j * k_k, acc); + + return acc; + } + + std::vector> range( + idx_type row1, idx_type row2, + idx_type col1, idx_type col2 + ) const { + std::vector> res; + + size_type n = static_cast(std::pow(k_k, k_height)) / k_k; + struct state{ + idx_type n, row1, row2, col1, col2, dr, dc, z; + state(idx_type n, idx_type row1, idx_type row2, idx_type col1, idx_type col2, + idx_type dr, idx_type dc, idx_type z) + : n(n), row1(row1), row2(row2), col1(col1), col2(col2), dr(dr), dc(dc), z(z) {} + }; + std::vector states; + states.reserve(k_height); // minimum + states.emplace_back(n, row1, row2, col1, col2, 0, 0, std::numeric_limits::max()); + + while(!states.empty()){ + state s = states.back(); + states.pop_back(); + + //TODO: peel first loop where z==-1 atm + if(s.z!=std::numeric_limits::max() && s.z >= k_t.size()){ // Last level + if(k_l[s.z - k_t.size()] == 1){ + res.emplace_back(s.dr, s.dc); + } + }else if(s.z==std::numeric_limits::max() || k_t[s.z]==1){ + + auto y = k_t_rank(s.z+1) * k_k * k_k; + + for(idx_type i=s.row1/s.n; i<=s.row2/s.n; ++i){ + idx_type row1new, row2new; + //TODO: loop peeling, first iteration and last iteration special + if(i==s.row1/s.n) row1new = s.row1 % s.n; else row1new = 0; + if(i==s.row2/s.n) row2new = s.row2 % s.n; else row2new = s.n - 1; + + for(idx_type j=s.col1/s.n; j<=s.col2/s.n; ++j){ + idx_type col1new, col2new; + //TODO: loop peeling, first iteration and last iteration special + if(j==s.col1/s.n) col1new = s.col1 % s.n; else col1new = 0; + if(j==s.col2/s.n) col2new = s.col2 % s.n; else col2new = s.n - 1; + + states.emplace_back(s.n/k_k, row1new, row2new, col1new, col2new, + s.dr + s.n*i, s.dc + s.n*j, y + k_k*i+j); + } + } + } } - std::vector> range( - idx_type row1, idx_type row2, - idx_type col1, idx_type col2 - ) const { - std::vector> res; - - size_type n = static_cast(std::pow(k_k, k_height)) / k_k; - struct state{ - idx_type n, row1, row2, col1, col2, dr, dc, z; - state(idx_type n, idx_type row1, idx_type row2, idx_type col1, idx_type col2, - idx_type dr, idx_type dc, idx_type z) - : n(n), row1(row1), row2(row2), col1(col1), col2(col2), dr(dr), dc(dc), z(z) {} - }; - std::vector states; - states.reserve(k_height); // minimum - states.emplace_back(n, row1, row2, col1, col2, 0, 0, std::numeric_limits::max()); - - while(!states.empty()){ - state s = states.back(); - states.pop_back(); - - //TODO: peel first loop where z==-1 atm - if(s.z!=std::numeric_limits::max() && s.z >= k_t.size()){ // Last level - if(k_l[s.z - k_t.size()] == 1){ - res.emplace_back(s.dr, s.dc); - } - }else if(s.z==std::numeric_limits::max() || k_t[s.z]==1){ - - auto y = k_t_rank(s.z+1) * k_k * k_k; - - for(idx_type i=s.row1/s.n; i<=s.row2/s.n; ++i){ - idx_type row1new, row2new; - //TODO: loop peeling, first iteration and last iteration special - if(i==s.row1/s.n) row1new = s.row1 % s.n; else row1new = 0; - if(i==s.row2/s.n) row2new = s.row2 % s.n; else row2new = s.n - 1; - - for(idx_type j=s.col1/s.n; j<=s.col2/s.n; ++j){ - idx_type col1new, col2new; - //TODO: loop peeling, first iteration and last iteration special - if(j==s.col1/s.n) col1new = s.col1 % s.n; else col1new = 0; - if(j==s.col2/s.n) col2new = s.col2 % s.n; else col2new = s.n - 1; - - states.emplace_back(s.n/k_k, row1new, row2new, col1new, col2new, - s.dr + s.n*i, s.dc + s.n*j, y + k_k*i+j); - } - } - } - } - - return res; - }; + return res; + }; - //! Serialize to a stream - /*! Serialize the k2_tree data structure + //! Serialize to a stream + /*! Serialize the k2_tree data structure * \param out Outstream to write the k2_tree. * \param v * \param string_name * \returns The number of written bytes. */ - size_type serialize(std::ostream& out, structure_tree_node* v=nullptr, - std::string name="") const - { - structure_tree_node* child = structure_tree::add_child( - v, name, util::class_name(*this)); - size_type written_bytes = 0; - - written_bytes += k_t.serialize(out, child, "t"); - written_bytes += k_l.serialize(out, child, "l"); - written_bytes += k_t_rank.serialize(out, child, "t_rank"); - written_bytes += write_member(k_k, out, child, "k"); - written_bytes += write_member(k_height, out, child, "height"); - structure_tree::add_size(child, written_bytes); - return written_bytes; - } - - - //! Load from istream - /*! Serialize the k2_tree from the given istream. + size_type serialize(std::ostream& out, structure_tree_node* v=nullptr, + std::string name="") const + { + structure_tree_node* child = structure_tree::add_child( + v, name, util::class_name(*this)); + size_type written_bytes = 0; + + written_bytes += k_t.serialize(out, child, "t"); + written_bytes += k_l.serialize(out, child, "l"); + written_bytes += k_t_rank.serialize(out, child, "t_rank"); + written_bytes += write_member(k_k, out, child, "k"); + written_bytes += write_member(k_height, out, child, "height"); + structure_tree::add_size(child, written_bytes); + return written_bytes; + } + + + //! Load from istream + /*! Serialize the k2_tree from the given istream. * \param istream Stream to load the k2_tree from. */ - void load(std::istream& in) - { - k_t.load(in); - k_l.load(in); - k_t_rank.load(in); - k_t_rank.set_vector(&k_t); - read_member(k_k, in); - read_member(k_height, in); - } + void load(std::istream& in) + { + k_t.load(in); + k_l.load(in); + k_t_rank.load(in); + k_t_rank.set_vector(&k_t); + read_member(k_k, in); + read_member(k_height, in); + } }; -} +} // namespace sdsl #endif diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 35358c752..fc5a765da 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -151,6 +151,51 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); } +TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) +{ + vector> mat({ + {1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0} + }); + // T 1 0 0 1 + // L 1 1 0 1 1 1 1 0 + TypeParam tree_A(mat); + + mat = vector> ({ + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1} + }); + // T 0 0 0 1 + // L 0 0 0 1 + TypeParam tree_B(mat); + + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); +} + +TYPED_TEST(k2_tree_test_k_2, union_operation_test) +{ + vector> mat({ + {1, 1}, + {0, 1} + }); + TypeParam tree_A(mat); + + mat = vector> ({ + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1} + }); + TypeParam tree_B(mat); + + ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); +} + TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) { typedef std::tuple> mat({ + {1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0} + }); + + TypeParam tree_A(mat); + + mat = vector> ({ + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1} + }); + TypeParam tree_B(mat); + + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1,1,0,1,1,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}); +} + TYPED_TEST_CASE(k2_tree_test, Implementations); TYPED_TEST(k2_tree_test, edges_array_exhaustive) From e96d42b1c4527614bbb58b21918d2db91db35050 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 15 Mar 2020 01:16:42 +0000 Subject: [PATCH 02/57] add number of edges --- include/sdsl/k2_tree.hpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index bf574060f..c754358da 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -47,7 +47,8 @@ namespace sdsl template + typename t_rank=typename t_bv::rank_1_type, + typename l_rank=typename t_bv::rank_1_type> class k2_tree { public: @@ -65,7 +66,8 @@ class k2_tree size_t k_l_size; t_rank k_t_rank; - + l_rank k_l_rank; + uint8_t k_k; uint16_t k_height; @@ -271,6 +273,7 @@ class k2_tree k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } @@ -300,6 +303,7 @@ class k2_tree build_from_matrix(matrix); k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } //! Constructor @@ -376,6 +380,7 @@ class k2_tree k_t = std::move(t); k_l = std::move(l); k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } //! Union Operation @@ -492,6 +497,8 @@ class k2_tree k_l = tr.k_l; k_t_rank = tr.k_t_rank; k_t_rank.set_vector(&k_t); + k_l_rank = tr.k_l_rank; + k_l_rank.set_vector(&k_l); k_k = tr.k_k; k_height = tr.k_height; } @@ -505,6 +512,7 @@ class k2_tree std::swap(k_t, tr.k_t); std::swap(k_l, tr.k_l); util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t)); + util::swap_support(k_l_rank, tr.k_l_rank, &k_l, &(tr.k_l)); std::swap(k_k, tr.k_k); std::swap(k_height, tr.k_height); } @@ -542,6 +550,11 @@ class k2_tree return k_height; } + int get_number_edges() + { + return k_l_rank(k_l.size()); + } + //! Indicates whether node j is adjacent to node i or not. /*! * \param i Node i. @@ -692,6 +705,7 @@ class k2_tree written_bytes += k_t.serialize(out, child, "t"); written_bytes += k_l.serialize(out, child, "l"); written_bytes += k_t_rank.serialize(out, child, "t_rank"); + written_bytes += k_l_rank.serialize(out, child, "l_rank"); written_bytes += write_member(k_k, out, child, "k"); written_bytes += write_member(k_height, out, child, "height"); structure_tree::add_size(child, written_bytes); @@ -709,6 +723,8 @@ class k2_tree k_l.load(in); k_t_rank.load(in); k_t_rank.set_vector(&k_t); + k_l_rank.load(in); + k_l_rank.set_vector(&k_l); read_member(k_k, in); read_member(k_height, in); } From 1aa9ff6dd31b4f13b13dc20224ca699590524f4d Mon Sep 17 00:00:00 2001 From: Joana H Date: Mon, 16 Mar 2020 08:19:55 +0000 Subject: [PATCH 03/57] change signature of union opertaion --- include/sdsl/k2_tree.hpp | 6 +++--- test/k2_tree_test.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index c754358da..19ef4c649 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -365,7 +365,7 @@ class k2_tree } - k2_tree(const k2_tree& tr) + k2_tree(k2_tree& tr) { *this = tr; } @@ -391,7 +391,7 @@ class k2_tree * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ - k2_tree unionOp(k2_tree& k2_B) + k2_tree* unionOp(k2_tree& k2_B) { assert(this->k_k == k2_B.k_k); @@ -472,7 +472,7 @@ class k2_tree for (size_t bit = 0; bit < C[max_height - 1].size(); bit++) l.set_int(bit, C[max_height - 1][bit]); - return k2_tree(t, l, max_height, k_k); + return new k2_tree(t, l, max_height, k_k); } //! Move assignment operator diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index fc5a765da..377933989 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -173,7 +173,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) // L 0 0 0 1 TypeParam tree_B(mat); - TypeParam unionTree = tree_A.unionOp(tree_B); + TypeParam unionTree = *(tree_A.unionOp(tree_B)); k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); } @@ -396,7 +396,7 @@ TYPED_TEST(k2_tree_test_k_3, union_operation_test) }); TypeParam tree_B(mat); - TypeParam unionTree = tree_A.unionOp(tree_B); + TypeParam unionTree = *(tree_A.unionOp(tree_B)); k2_tree_test_nm::check_t_l(unionTree, {1,1,0,1,1,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}); } From 76b105a8856a75fc5bb07ddee567cc21d6950606 Mon Sep 17 00:00:00 2001 From: Joana H Date: Fri, 20 Mar 2020 00:37:54 +0000 Subject: [PATCH 04/57] solved no problem should check this --- include/sdsl/k2_tree.hpp | 10 ++++++---- test/k2_tree_test.cpp | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 19ef4c649..d1521cdbc 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -274,7 +274,6 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - } public: @@ -392,8 +391,11 @@ class k2_tree * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ k2_tree* unionOp(k2_tree& k2_B) - { - + { + std::cout << "haha" << std::endl; + if(k2_B.get_number_edges() == 0) + return this; + assert(this->k_k == k2_B.k_k); if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) throw std::logic_error("Trees must have the same number of nodes."); @@ -552,7 +554,7 @@ class k2_tree int get_number_edges() { - return k_l_rank(k_l.size()); + return k_l.size() == 0? 0 : k_l_rank(k_l.size()); } //! Indicates whether node j is adjacent to node i or not. diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 377933989..232186e40 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -115,6 +115,8 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) }); tree = TypeParam(mat); expected_l = {0,0,0,1,1,0,0,0,0,1,0,0}; + + ASSERT_EQ(tree.get_number_edges(),3); k2_tree_test_nm::check_t_l(tree, {1, 1, 1 ,0}, expected_l); mat = vector>({{0, 0, 0}, @@ -177,6 +179,25 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); } +// TYPED_TEST(k2_tree_test_k_2, empty_union_operation) +// { +// vector> mat({ +// {1, 1, 0, 0}, +// {0, 1, 0, 0}, +// {0, 0, 1, 1}, +// {0, 0, 1, 0} +// }); + +// TypeParam tree_A(mat); +// TypeParam tree_B(); + +// TypeParam* unionTree = tree_A.unionOp(tree_B); +// // k2_tree_test_nm::check_t_l(*unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + +// // TypeParam unionTree = *(tree_B.unionOp(tree_A)); +// // k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); +// } + TYPED_TEST(k2_tree_test_k_2, union_operation_test) { vector> mat({ From f275bccfee062c577130c2daf8479c8c9cd4524c Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 22 Mar 2020 18:21:42 +0000 Subject: [PATCH 05/57] Add empty union tests --- include/sdsl/k2_tree.hpp | 18 +- test/k2_tree_test.cpp | 637 ++++++++++++++++++++------------------- 2 files changed, 338 insertions(+), 317 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index d1521cdbc..8933e12f7 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -390,13 +390,19 @@ class k2_tree * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ - k2_tree* unionOp(k2_tree& k2_B) + k2_tree unionOp(k2_tree& k2_B) { - std::cout << "haha" << std::endl; - if(k2_B.get_number_edges() == 0) - return this; - assert(this->k_k == k2_B.k_k); + k2_tree res; + if(k2_B.get_number_edges() == 0) { + res = *this; + return res; + } + if(this->get_number_edges() == 0) { + res = k2_B; + return res; + } + if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) throw std::logic_error("Trees must have the same number of nodes."); @@ -474,7 +480,7 @@ class k2_tree for (size_t bit = 0; bit < C[max_height - 1].size(); bit++) l.set_int(bit, C[max_height - 1][bit]); - return new k2_tree(t, l, max_height, k_k); + return k2_tree(t, l, max_height, k_k); } //! Move assignment operator diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 232186e40..4dfc19f7f 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -13,21 +13,27 @@ using namespace std; typedef int_vector<>::size_type size_type; -template -class k2_tree_test_k_2 : public ::testing::Test { }; +template +class k2_tree_test_k_2 : public ::testing::Test +{ +}; -template -class k2_tree_test_k_3 : public ::testing::Test { }; +template +class k2_tree_test_k_3 : public ::testing::Test +{ +}; -template -class k2_tree_test : public ::testing::Test { }; +template +class k2_tree_test : public ::testing::Test +{ +}; using testing::Types; namespace k2_tree_test_nm { -template -void check_t_l(t_tree& tree, vector expected_t, +template +void check_t_l(t_tree &tree, vector expected_t, vector expected_l) { ASSERT_EQ(expected_t.size(), tree.get_t().size()); @@ -38,8 +44,24 @@ void check_t_l(t_tree& tree, vector expected_t, ASSERT_EQ(expected_l[i], tree.get_l().get_int(i, 1)); } -template -void check_serialize_load(t_tree& tree) +template +void assert_eq_tree(t_tree &tree1, t_tree &tree2) +{ + ASSERT_EQ(tree1.get_t().size(), tree2.get_t().size()); + ASSERT_EQ(tree1.get_l().size(), tree2.get_l().size()); + for (unsigned i = 0; i < tree1.get_t().size(); i++) + { + std::cout << tree1.get_t().get_int(i, 1) << std::endl; + std::cout << tree2.get_t().get_int(i, 1) << std::endl; + + ASSERT_EQ(tree1.get_t().get_int(i, 1), tree2.get_t().get_int(i, 1)); + } + for (unsigned i = 0; i < tree1.get_l().size(); i++) + ASSERT_EQ(tree1.get_l().get_int(i, 1), tree2.get_l().get_int(i, 1)); +} + +template +void check_serialize_load(t_tree &tree) { auto unserialized_tree = t_tree(); std::stringstream ss; @@ -47,53 +69,50 @@ void check_serialize_load(t_tree& tree) unserialized_tree.load(ss); ASSERT_EQ(tree, unserialized_tree); } -}; +}; // namespace k2_tree_test_nm typedef Types< -k2_tree<2, bit_vector, rank_support_v<>>, - k2_tree<2, bit_vector> - > k_2_implementations; + k2_tree<2, bit_vector, rank_support_v<>>, + k2_tree<2, bit_vector>> + k_2_implementations; typedef Types< -k2_tree<3, bit_vector, rank_support_v<>>, - k2_tree<3, bit_vector> - > k_3_implementations; + k2_tree<3, bit_vector, rank_support_v<>>, + k2_tree<3, bit_vector>> + k_3_implementations; typedef Types< -k2_tree<2, bit_vector>, - k2_tree<3, bit_vector>, - k2_tree<7, bit_vector>, - k2_tree<2, rrr_vector<63>>, - k2_tree<3, rrr_vector<63>>, - k2_tree<5, bit_vector, rank_support_v<>>, - k2_tree<4, bit_vector, rank_support_v<>> - > Implementations; + k2_tree<2, bit_vector>, + k2_tree<3, bit_vector>, + k2_tree<7, bit_vector>, + k2_tree<2, rrr_vector<63>>, + k2_tree<3, rrr_vector<63>>, + k2_tree<5, bit_vector, rank_support_v<>>, + k2_tree<4, bit_vector, rank_support_v<>>> + Implementations; TYPED_TEST_CASE(k2_tree_test_k_2, k_2_implementations); TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) { - vector> mat({{1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0} - }); + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); TypeParam tree(mat); - vector expected_l = {1,1,0,1,1,1,1,0}; - k2_tree_test_nm::check_t_l(tree, {1, 0, 0 ,1}, expected_l); - - mat = vector> ({{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - }); + vector expected_l = {1, 1, 0, 1, 1, 1, 1, 0}; + k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, expected_l); + + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}); tree = TypeParam(mat); k2_tree_test_nm::check_t_l(tree, {}, {}); mat = vector>({{0, 0}, - {0, 0} - }); + {0, 0}}); tree = TypeParam(mat); ASSERT_TRUE(tree.get_t().empty()); ASSERT_TRUE(tree.get_l().empty()); @@ -107,111 +126,98 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) tree = TypeParam(mat); k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); - // Size is non a power of k: mat = vector>({{0, 0, 1}, - {0, 1, 0}, - {0, 1, 0} - }); + {0, 1, 0}, + {0, 1, 0}}); tree = TypeParam(mat); - expected_l = {0,0,0,1,1,0,0,0,0,1,0,0}; - - ASSERT_EQ(tree.get_number_edges(),3); - k2_tree_test_nm::check_t_l(tree, {1, 1, 1 ,0}, expected_l); - - mat = vector>({{0, 0, 0}, - {1, 0, 1}, - {0, 1, 1} - }); + expected_l = {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0}; + + ASSERT_EQ(tree.get_number_edges(), 3); + k2_tree_test_nm::check_t_l(tree, {1, 1, 1, 0}, expected_l); + + mat = vector>({{0, 0, 0}, + {1, 0, 1}, + {0, 1, 1}}); tree = TypeParam(mat); - expected_l = {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0}; - k2_tree_test_nm::check_t_l(tree, {1, 1, 1 ,1}, expected_l); + expected_l = {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0}; + k2_tree_test_nm::check_t_l(tree, {1, 1, 1, 1}, expected_l); // Sample from 'k^2 trees for compact web graph representation' paper mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0} - }); + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); tree = TypeParam(mat); - vector expected_t = {1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, - 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0 - }; - - expected_l = {0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0 - }; + vector expected_t = {1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, + 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0}; + + expected_l = {0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0}; k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); } TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) { - vector> mat({ - {1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0} - }); + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); // T 1 0 0 1 // L 1 1 0 1 1 1 1 0 TypeParam tree_A(mat); - mat = vector> ({ - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 1} - }); + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1}}); // T 0 0 0 1 // L 0 0 0 1 TypeParam tree_B(mat); - TypeParam unionTree = *(tree_A.unionOp(tree_B)); + TypeParam unionTree = tree_A.unionOp(tree_B); k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); } -// TYPED_TEST(k2_tree_test_k_2, empty_union_operation) -// { -// vector> mat({ -// {1, 1, 0, 0}, -// {0, 1, 0, 0}, -// {0, 0, 1, 1}, -// {0, 0, 1, 0} -// }); +TYPED_TEST(k2_tree_test_k_2, empty_union_operation) +{ + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); + + TypeParam tree_A(mat); + TypeParam tree_B; -// TypeParam tree_A(mat); -// TypeParam tree_B(); + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); -// TypeParam* unionTree = tree_A.unionOp(tree_B); -// // k2_tree_test_nm::check_t_l(*unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + unionTree = tree_B.unionOp(tree_A); + k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); -// // TypeParam unionTree = *(tree_B.unionOp(tree_A)); -// // k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); -// } + unionTree = tree_B.unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); +} TYPED_TEST(k2_tree_test_k_2, union_operation_test) { - vector> mat({ - {1, 1}, - {0, 1} - }); + vector> mat({{1, 1}, + {0, 1}}); TypeParam tree_A(mat); - mat = vector> ({ - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 1} - }); + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1}}); TypeParam tree_B(mat); ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); @@ -220,80 +226,76 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) { typedef std::tuple t_tuple; + typename TypeParam::idx_type> + t_tuple; vector> e; + typename TypeParam::idx_type>> + e; t_tuple a{0, 0}; t_tuple b{0, 1}; t_tuple c{1, 0}; t_tuple d{1, 1}; - e.push_back(t_tuple {1, 2}); + e.push_back(t_tuple{1, 2}); TypeParam tree(e, 4); - k2_tree_test_nm::check_t_l(tree, {0, 1, 0 ,0}, {0, 0, 1, 0}); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {0, 1, 0 ,0}, {0, 0, 1, 0}); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); - e.push_back(t_tuple {1, 2}); + e.push_back(t_tuple{1, 2}); tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {0, 1, 0 ,0}, {0, 0, 1, 0}); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); e.clear(); - e.push_back(t_tuple {0, 0}); + e.push_back(t_tuple{0, 0}); tree = TypeParam(e, 1); k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); - e.push_back(t_tuple {0, 1}); - e.push_back(t_tuple {1, 0}); - e.push_back(t_tuple {1, 1}); + e.push_back(t_tuple{0, 1}); + e.push_back(t_tuple{1, 0}); + e.push_back(t_tuple{1, 1}); tree = TypeParam(e, 2); k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 1, 1}); - e.push_back(t_tuple {2, 2}); + e.push_back(t_tuple{2, 2}); tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); + k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); } - TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) { - vector> mat({{1, 1, 0, 0, 1}, - {0, 1, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {1, 1, 0, 1, 0}, - {0, 0, 1, 0, 0} - }); + vector> mat({{1, 1, 0, 0, 1}, + {0, 1, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {1, 1, 0, 1, 0}, + {0, 0, 1, 0, 0}}); TypeParam tree(mat); vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0 - }; + 1, 0, 0, 0, 0, 0, 0, 0, 0}; k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); mat = vector>({{1, 1, 1, 0}, - {1, 0, 0, 0}, - {0, 0, 0, 0}, - {1, 1, 0, 0} - }); + {1, 0, 0, 0}, + {0, 0, 0, 0}, + {1, 1, 0, 0}}); tree = TypeParam(mat); expected_t = {1, 0, 0, 1, 0, 0, 0, 0, 0}; expected_l = {1, 1, 1, 1, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0 - }; + 1, 1, 0, 0, 0, 0, 0, 0, 0}; k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); mat = vector>({{0, 0, 0}, - {0, 0, 0}, - {0, 0, 0} - }); + {0, 0, 0}, + {0, 0, 0}}); tree = TypeParam(mat); k2_tree_test_nm::check_t_l(tree, {}, {}); @@ -304,121 +306,138 @@ TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) mat = vector>({{1}}); tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0 ,0}); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); mat = vector>({{1, 0}, - {0, 1} - }); + {0, 1}}); tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0 ,0}); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0, 0}); // Size is a power of k: mat = vector>({{0, 0, 1, 0, 0, 0, 0, 0, 0}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 0, 0, 0} - }); + {1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0}}); tree = TypeParam(mat); expected_t = {1, 0, 0, 0, 0, 0, 1, 0, 0}; expected_l = {0, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1 - }; + 0, 0, 0, 0, 0, 0, 0, 0, 1}; k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0} - }); + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); tree = TypeParam(mat); expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0 - }; + 1, 0, 0, 0, 0, 0, 0, 0, 0}; expected_l = {0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, 0, 0, 0, 0 - }; + 0, 1, 0, 1, 0, 0, 0, 0, 0}; k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); } - TYPED_TEST(k2_tree_test_k_3, build_from_edges_array) { typedef std::tuple t_tuple; + typename TypeParam::idx_type> + t_tuple; vector> e; + typename TypeParam::idx_type>> + e; - e.push_back(t_tuple {1, 2}); + e.push_back(t_tuple{1, 2}); TypeParam tree(e, 4); k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 0, 0, 0}); + {0, 0, 0, 0, 0, 1, 0, 0, 0}); tree = TypeParam(e, 3); k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); - e.push_back(t_tuple {1, 2}); + e.push_back(t_tuple{1, 2}); tree = TypeParam(e, 3); k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); e.clear(); - e.push_back(t_tuple {0, 0}); + e.push_back(t_tuple{0, 0}); tree = TypeParam(e, 1); k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - e.push_back(t_tuple {0, 1}); - e.push_back(t_tuple {1, 0}); - e.push_back(t_tuple {1, 1}); + e.push_back(t_tuple{0, 1}); + e.push_back(t_tuple{1, 0}); + e.push_back(t_tuple{1, 1}); tree = TypeParam(e, 2); k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 0, 1, 1, 0, 0, 0, 0}); e.clear(); - e.push_back(t_tuple {2, 2}); + e.push_back(t_tuple{2, 2}); tree = TypeParam(e, 3); k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 0, 0, 0, 1}); } TYPED_TEST(k2_tree_test_k_3, union_operation_test) { - vector> mat({ - {1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0} - }); + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); TypeParam tree_A(mat); - mat = vector> ({ - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 1} - }); + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1}}); TypeParam tree_B(mat); - TypeParam unionTree = *(tree_A.unionOp(tree_B)); - k2_tree_test_nm::check_t_l(unionTree, {1,1,0,1,1,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}); + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); +} + +TYPED_TEST(k2_tree_test_k_3, empty_union_operation) +{ + vector> mat({{1, 1, 0, 0, 1}, + {0, 1, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {1, 1, 0, 1, 0}, + {0, 0, 1, 0, 0}}); + + vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; + vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0}; + TypeParam tree_A(mat); + TypeParam tree_B; + + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + + unionTree = tree_B.unionOp(tree_A); + k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + + unionTree = tree_B.unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); } TYPED_TEST_CASE(k2_tree_test, Implementations); @@ -426,19 +445,21 @@ TYPED_TEST_CASE(k2_tree_test, Implementations); TYPED_TEST(k2_tree_test, edges_array_exhaustive) { typedef std::tuple t_tuple; + typename TypeParam::idx_type> + t_tuple; vector> e; - e.push_back(t_tuple {5, 7}); - e.push_back(t_tuple {1, 2}); - e.push_back(t_tuple {3, 9}); - e.push_back(t_tuple {2, 2}); - e.push_back(t_tuple {3, 2}); - e.push_back(t_tuple {7, 5}); - e.push_back(t_tuple {1, 6}); - e.push_back(t_tuple {4, 8}); - e.push_back(t_tuple {4, 1}); - e.push_back(t_tuple {5, 2}); + typename TypeParam::idx_type>> + e; + e.push_back(t_tuple{5, 7}); + e.push_back(t_tuple{1, 2}); + e.push_back(t_tuple{3, 9}); + e.push_back(t_tuple{2, 2}); + e.push_back(t_tuple{3, 2}); + e.push_back(t_tuple{7, 5}); + e.push_back(t_tuple{1, 6}); + e.push_back(t_tuple{4, 8}); + e.push_back(t_tuple{4, 1}); + e.push_back(t_tuple{5, 2}); TypeParam tree(e, 10); auto expected_neighbors = vector>(10); @@ -452,7 +473,8 @@ TYPED_TEST(k2_tree_test, edges_array_exhaustive) expected_neighbors[7] = vector({5}); expected_neighbors[8] = vector({}); expected_neighbors[9] = vector({}); - for (unsigned i = 0; i < 10; i++) { + for (unsigned i = 0; i < 10; i++) + { auto actual_neighbors = tree.neigh(i); ASSERT_EQ(expected_neighbors[i].size(), actual_neighbors.size()); for (unsigned j = 0; i < expected_neighbors[i].size(); i++) @@ -468,35 +490,33 @@ TYPED_TEST(k2_tree_test, edges_array_exhaustive) TYPED_TEST(k2_tree_test, neighbors_test) { - vector> mat({{1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0} - }); + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); TypeParam tree(mat); auto neigh_0 = tree.neigh(0); - vectorexpected_neigh_0({0, 1}); + vector expected_neigh_0({0, 1}); ASSERT_EQ(expected_neigh_0.size(), neigh_0.size()); for (unsigned i = 0; i < neigh_0.size(); i++) ASSERT_EQ(expected_neigh_0[i], neigh_0[i]); auto neigh_3 = tree.neigh(3); - vectorexpected_neigh_3({2}); + vector expected_neigh_3({2}); ASSERT_EQ(expected_neigh_3.size(), neigh_3.size()); for (unsigned i = 0; i < neigh_3.size(); i++) ASSERT_EQ(expected_neigh_3[i], neigh_3[i]); - mat = vector>({{1}}); + mat = vector>({{1}}); tree = TypeParam(mat); neigh_0 = tree.neigh(0); ASSERT_EQ(0u, neigh_0[0]); ASSERT_EQ(1u, neigh_0.size()); - mat = vector>({{0, 0, 0}, - {1, 0, 1}, - {0, 1, 1} - }); + mat = vector>({{0, 0, 0}, + {1, 0, 1}, + {0, 1, 1}}); tree = TypeParam(mat); neigh_0 = tree.neigh(0); ASSERT_EQ(0u, neigh_0.size()); @@ -507,9 +527,8 @@ TYPED_TEST(k2_tree_test, neighbors_test) for (unsigned i = 0; i < neigh_1.size(); i++) ASSERT_EQ(expected_neigh_1[i], neigh_1[i]); - mat = vector>({{0, 0}, - {0, 0} - }); + mat = vector>({{0, 0}, + {0, 0}}); tree = TypeParam(mat); neigh_0 = tree.neigh(0); ASSERT_EQ(0u, neigh_0.size()); @@ -517,12 +536,11 @@ TYPED_TEST(k2_tree_test, neighbors_test) TYPED_TEST(k2_tree_test, reverse_neighbors_test) { - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1} - }); + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); auto tree = TypeParam(mat); auto r_neigh_0 = tree.reverse_neigh(0); @@ -540,19 +558,16 @@ TYPED_TEST(k2_tree_test, reverse_neighbors_test) for (unsigned i = 0; i < r_neigh_2.size(); i++) ASSERT_EQ(expected_r_neigh_2[i], r_neigh_2[i]); - mat = vector>({{0, 0}, - {0, 0} - }); + mat = vector>({{0, 0}, + {0, 0}}); tree = TypeParam(mat); r_neigh_0 = tree.reverse_neigh(0); r_neigh_1 = tree.reverse_neigh(1); ASSERT_EQ(0u, r_neigh_0.size()); ASSERT_EQ(0u, r_neigh_1.size()); - - mat = vector>({{0, 1}, - {1, 0} - }); + mat = vector>({{0, 1}, + {1, 0}}); tree = TypeParam(mat); r_neigh_0 = tree.reverse_neigh(0); expected_r_neigh_0 = vector({1}); @@ -570,64 +585,68 @@ TYPED_TEST(k2_tree_test, reverse_neighbors_test) TYPED_TEST(k2_tree_test, range_test) { - static const vector> mat{ - // 0 1 2 3 4 5 6 7 8 9 10 - /* 0*/{0,1,0,0, 0,0,0,0, 0,0,0}, - /* 1*/{0,0,1,1, 1,0,0,0, 0,0,0}, - /* 2*/{0,0,0,0, 0,0,0,0, 0,0,0}, - /* 3*/{0,0,0,0, 0,0,0,0, 0,0,0}, - - /* 4*/{0,0,0,0, 0,0,0,0, 0,0,0}, - /* 5*/{0,0,0,0, 0,0,0,0, 0,0,0}, - /* 6*/{0,0,0,0, 0,0,0,0, 0,0,0}, - /* 7*/{0,0,0,0, 0,0,1,0, 0,0,0}, - - /* 8*/{0,0,0,0, 0,0,1,0, 0,1,0}, - /* 9*/{0,0,0,0, 0,0,1,0, 1,0,1}, - /*10*/{0,0,0,0, 0,0,1,0, 0,1,0}, - }; - TypeParam tree(mat); - - auto result = tree.range(7,9, 5,9); - static const decltype(result) expected{ - {7,6}, - {8,6}, {8,9}, - {9,6}, {9,8} - }; - sort(result.begin(), result.end()); - ASSERT_EQ(expected, result); - - auto all = tree.range(0,10, 0,10); - static const decltype(all) expectedAll{ - {0,1}, - {1,2}, {1,3}, {1,4}, - {7,6}, - {8,6}, {8,9}, - {9,6}, {9,8}, {9,10}, - {10,6},{10,9} - }; - sort(all.begin(), all.end()); - ASSERT_EQ(expectedAll, all); - - auto single = tree.range(1,1, 3,3); - static const decltype(single) expectedSingle{ - {1,3} - }; - ASSERT_EQ(expectedSingle, single); - - auto empty = tree.range(0,6, 5,10); - static const decltype(empty) expectedEmpty{}; - ASSERT_EQ(expectedEmpty, empty); + static const vector> mat{ + // 0 1 2 3 4 5 6 7 8 9 10 + /* 0*/ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 1*/ {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + /* 2*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 3*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + /* 4*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 5*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 6*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 7*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + + /* 8*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + /* 9*/ {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + /*10*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + }; + TypeParam tree(mat); + + auto result = tree.range(7, 9, 5, 9); + static const decltype(result) expected{ + {7, 6}, + {8, 6}, + {8, 9}, + {9, 6}, + {9, 8}}; + sort(result.begin(), result.end()); + ASSERT_EQ(expected, result); + + auto all = tree.range(0, 10, 0, 10); + static const decltype(all) expectedAll{ + {0, 1}, + {1, 2}, + {1, 3}, + {1, 4}, + {7, 6}, + {8, 6}, + {8, 9}, + {9, 6}, + {9, 8}, + {9, 10}, + {10, 6}, + {10, 9}}; + sort(all.begin(), all.end()); + ASSERT_EQ(expectedAll, all); + + auto single = tree.range(1, 1, 3, 3); + static const decltype(single) expectedSingle{ + {1, 3}}; + ASSERT_EQ(expectedSingle, single); + + auto empty = tree.range(0, 6, 5, 10); + static const decltype(empty) expectedEmpty{}; + ASSERT_EQ(expectedEmpty, empty); } TYPED_TEST(k2_tree_test, adj_test) { - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1} - }); + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); auto tree = TypeParam(mat); ASSERT_TRUE(tree.adj(0, 0)); @@ -638,22 +657,21 @@ TYPED_TEST(k2_tree_test, adj_test) ASSERT_TRUE(tree.adj(2, 2)); ASSERT_TRUE(tree.adj(2, 3)); - mat = vector>({{0}}); + mat = vector>({{0}}); tree = TypeParam(mat); - ASSERT_FALSE(tree.adj(0,0)); - mat = vector>({{1}}); + ASSERT_FALSE(tree.adj(0, 0)); + mat = vector>({{1}}); tree = TypeParam(mat); - ASSERT_TRUE(tree.adj(0,0)); + ASSERT_TRUE(tree.adj(0, 0)); } TYPED_TEST(k2_tree_test, serialize_test) { - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1} - }); + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); auto tree = TypeParam(mat); k2_tree_test_nm::check_serialize_load(tree); @@ -666,22 +684,19 @@ TYPED_TEST(k2_tree_test, serialize_test) k2_tree_test_nm::check_serialize_load(tree); mat = vector>({{0, 0}, - {0, 0} - }); + {0, 0}}); tree = TypeParam(mat); k2_tree_test_nm::check_serialize_load(tree); mat = vector>({{1, 1}, - {1, 1} - }); + {1, 1}}); tree = TypeParam(mat); k2_tree_test_nm::check_serialize_load(tree); - } -} // namespace +} // namespace -int main(int argc, char** argv) +int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); From 587fb02c43b7548a7b72e56b62fe2339a5a0be0f Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 22 Mar 2020 21:02:27 +0000 Subject: [PATCH 06/57] Fix empty initialization --- include/sdsl/k2_tree.hpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 8933e12f7..491de88ee 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -62,14 +62,14 @@ class k2_tree //! Bit array to store the last level of the tree. t_bv k_l; - size_t k_t_size; - size_t k_l_size; + size_t k_t_size = 0; + size_t k_l_size = 0; t_rank k_t_rank; l_rank k_l_rank; - uint8_t k_k; - uint16_t k_height; + uint8_t k_k = k; + uint16_t k_height = 0; protected: @@ -114,6 +114,8 @@ class k2_tree } k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } @@ -278,7 +280,12 @@ class k2_tree public: - k2_tree() = default; + k2_tree() { + k_t = bit_vector(0,0); + k_l = bit_vector(0,0); + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); + } //! Constructor /*! This constructos takes the graph adjacency matrix. @@ -301,8 +308,6 @@ class k2_tree build_from_matrix(matrix); - k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); } //! Constructor @@ -393,14 +398,12 @@ class k2_tree k2_tree unionOp(k2_tree& k2_B) { assert(this->k_k == k2_B.k_k); - k2_tree res; + if(k2_B.get_number_edges() == 0) { - res = *this; - return res; + return *this; } if(this->get_number_edges() == 0) { - res = k2_B; - return res; + return k2_B; } if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) @@ -491,8 +494,8 @@ class k2_tree k_l = std::move(tr.k_l); k_k = std::move(tr.k_k); k_height = std::move(tr.k_height); - k_t_rank = std::move(tr.k_t_rank); - k_t_rank.set_vector(&k_t); + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } return *this; } @@ -503,12 +506,10 @@ class k2_tree if (this != &tr) { k_t = tr.k_t; k_l = tr.k_l; - k_t_rank = tr.k_t_rank; - k_t_rank.set_vector(&k_t); - k_l_rank = tr.k_l_rank; - k_l_rank.set_vector(&k_l); k_k = tr.k_k; k_height = tr.k_height; + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); } return *this; } From 1f08c928f069dc57960a907fb7a8cfb5e5c6626f Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 24 Mar 2020 00:14:48 +0000 Subject: [PATCH 07/57] identation --- include/sdsl/k2_tree.hpp | 265 +++++++++++++++++++++++---------------- 1 file changed, 156 insertions(+), 109 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 491de88ee..9c8d68f17 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -29,7 +29,6 @@ #include "sdsl/k2_tree_helper.hpp" #include "sdsl/int_vector_buffer.hpp" - //! Namespace for the succint data structure library namespace sdsl { @@ -58,22 +57,21 @@ class k2_tree private: //! Bit array to store all the bits of the tree, except those in the //! last level. - t_bv k_t; + t_bv k_t; //! Bit array to store the last level of the tree. - t_bv k_l; + t_bv k_l; - size_t k_t_size = 0; - size_t k_l_size = 0; + size_t k_t_size = 0; + size_t k_l_size = 0; - t_rank k_t_rank; - l_rank k_l_rank; - - uint8_t k_k = k; - uint16_t k_height = 0; + t_rank k_t_rank; + l_rank k_l_rank; -protected: + uint8_t k_k; + uint16_t k_height = 0; - void build_from_matrix(const std::vector>& matrix) +protected: + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. int simulated_size = std::pow(k, k_height); @@ -100,14 +98,16 @@ class k2_tree int n = 0; for (int j = 1; j < k_height; j++) for (auto it = acc[j].begin(); it != acc[j].end(); it++) - for (unsigned i = 0; i < (*it).size(); i++) { + for (unsigned i = 0; i < (*it).size(); i++) + { // TODO there should be a better way to do this k_t_.set_int(n, (*it).get_int(i, 1), 1); n++; } n = 0; for (auto it = acc[k_height].begin(); it != acc[k_height].end(); it++) - for (unsigned i = 0; i < (*it).size(); i++) { + for (unsigned i = 0; i < (*it).size(); i++) + { // TODO there should be a better way to do this k_l_.set_int(n * 1, (*it).get_int(i, 1), 1); n++; @@ -118,7 +118,6 @@ class k2_tree k_l_rank = l_rank(&k_l); } - /*! Recursive function to retrieve list of neighbors. * * \param n Size of the submatrix in the next recursive step. @@ -131,19 +130,21 @@ class k2_tree * \param acc Accumulator to store the neighbors found. */ void _neigh(size_type n, idx_type row, idx_type col, size_type level, - std::vector& acc) const + std::vector &acc) const { - if (level >= k_t.size()) { // Last level + if (level >= k_t.size()) + { // Last level if (k_l[level - k_t.size()] == 1) acc.push_back(col); return; } - if (k_t[level] == 1) { + if (k_t[level] == 1) + { idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + - k_k * std::floor(row/static_cast(n)); + k_k * std::floor(row / static_cast(n)); for (unsigned j = 0; j < k_k; j++) - _neigh(n/k_k, row % n, col + n * j, y + j, acc); + _neigh(n / k_k, row % n, col + n * j, y + j, acc); } } @@ -159,20 +160,23 @@ class k2_tree * \param acc Accumulator to store the neighbors found. */ void _reverse_neigh(size_type n, idx_type row, idx_type col, - size_type level, std::vector& acc) const + size_type level, std::vector &acc) const { - if (level >= k_t.size()) { // Last level - if (k_l[level - k_t.size()] == 1) { + if (level >= k_t.size()) + { // Last level + if (k_l[level - k_t.size()] == 1) + { acc.push_back(row); } return; } - if (k_t[level] == 1) { + if (k_t[level] == 1) + { idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + - std::floor(col/static_cast(n)); + std::floor(col / static_cast(n)); for (unsigned j = 0; j < k_k; j++) - _reverse_neigh(n/k_k, row + n * j, col % n, + _reverse_neigh(n / k_k, row + n * j, col % n, y + j * k_k, acc); } } @@ -186,15 +190,16 @@ class k2_tree * \param size Size of the graph, all the nodes in edges must be * within 0 and size ([0, size[). */ - void build_from_edges(std::vector>& edges, + void build_from_edges(std::vector> &edges, const size_type size) { typedef std::tuple t_part_tuple; + idx_type> + t_part_tuple; k_k = k; - k_height = std::ceil(std::log(size)/std::log(k_k)); + k_height = std::ceil(std::log(size) / std::log(k_k)); k_height = k_height > 1 ? k_height : 1; // If size == 0 size_type k_2 = std::pow(k_k, 2); bit_vector k_t_ = bit_vector(k_2 * k_height * edges.size(), 0); @@ -208,7 +213,8 @@ class k2_tree q.push(t_part_tuple(0, edges.size(), l, 0, 0)); - while (!q.empty()) { + while (!q.empty()) + { std::vector amount_by_chunk(k_2, 0); std::tie(i, j, l, r_0, c_0) = q.front(); q.pop(); @@ -217,15 +223,17 @@ class k2_tree amount_by_chunk[k2_tree_ns::get_chunk_idx( std::get<0>(edges[it]), std::get<1>(edges[it]), c_0, r_0, l, k_k)] += 1; - if (l == 1) { - if (last_level == 0) { + if (l == 1) + { + if (last_level == 0) + { last_level = t; k_l_ = bit_vector(k_t_.size() - last_level, 0); k_t_.resize(last_level); last_level = 1; // if t was 0 - t = 0; // Restart counter as we're storing at k_l_ now. + t = 0; // Restart counter as we're storing at k_l_ now. } - for (it = 0; it < k_2; it++,t++) + for (it = 0; it < k_2; it++, t++) if (amount_by_chunk[it] != 0) k_l_[t] = 1; // At l == 1 we do not put new elements at the queue. @@ -240,24 +248,27 @@ class k2_tree // To handle the last case when it = k_2 - 1 pos_by_chunk[k_2] = j; // Push to the queue every non zero elements chunk - for (it = 0; it < k_2; it++,t++) + for (it = 0; it < k_2; it++, t++) // If not empty chunk, set bit to 1 - if (amount_by_chunk[it] != 0) { + if (amount_by_chunk[it] != 0) + { r = it / k_k; c = it % k_k; k_t_[t] = 1; q.push(t_part_tuple(pos_by_chunk[it], pos_by_chunk[it + 1], - l/k_k, + l / k_k, r_0 + r * l, c_0 + c * l)); } idx_type chunk; // Sort edges' vector - for (unsigned ch = 0; ch < k_2; ch++) { + for (unsigned ch = 0; ch < k_2; ch++) + { idx_type be = ch == 0 ? i : pos_by_chunk[ch - 1]; - for (it = pos_by_chunk[ch]; it < be + amount_by_chunk[ch];) { + for (it = pos_by_chunk[ch]; it < be + amount_by_chunk[ch];) + { chunk = k2_tree_ns::get_chunk_idx( std::get<0>(edges[it]), std::get<1>(edges[it]), c_0, r_0, l, k_k); @@ -279,10 +290,11 @@ class k2_tree } public: - - k2_tree() { - k_t = bit_vector(0,0); - k_l = bit_vector(0,0); + k2_tree() + { + k_k = k; + k_t = bit_vector(0, 0); + k_l = bit_vector(0, 0); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); } @@ -296,7 +308,8 @@ class k2_tree */ k2_tree(const std::vector> &matrix) { - if (matrix.size() < 1) { + if (matrix.size() < 1) + { throw std::logic_error("Matrix has no elements"); } std::vector t; @@ -304,10 +317,9 @@ class k2_tree if (matrix.size() < k_k) k_height = 1; else // height = log_k n - k_height = std::ceil(std::log(matrix.size())/std::log(k_k)); + k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); - } //! Constructor @@ -319,7 +331,7 @@ class k2_tree * \param size Size of the graph, all the nodes in edges must be * within 0 and size ([0, size[). */ - k2_tree(std::vector>& edges, + k2_tree(std::vector> &edges, const size_type size) { assert(size > 0); @@ -341,7 +353,7 @@ class k2_tree * size==0, the size will be taken as the max node * in the edges. */ - k2_tree(std::string filename, size_type size=0) + k2_tree(std::string filename, size_type size = 0) { int_vector_buffer<> buf_x(filename + ".x", std::ios::in); int_vector_buffer<> buf_y(filename + ".y", std::ios::in); @@ -349,32 +361,42 @@ class k2_tree assert(buf_x.size() == buf_y.size()); assert(buf_x.size() > 0); - std::vector>edges; + std::vector> edges; edges.reserve(buf_x.size()); - if(size==0) { + if (size == 0) + { size_type max = 0; - for(auto v : buf_x) + for (auto v : buf_x) max = std::max(static_cast(v), max); - for(auto v : buf_y) + for (auto v : buf_y) max = std::max(static_cast(v), max); size = max + 1; } - for(uint64_t i = 0; i < buf_x.size(); i++) + for (uint64_t i = 0; i < buf_x.size(); i++) edges.push_back( - std::tuple {buf_x[i], buf_y[i]}); + std::tuple{buf_x[i], buf_y[i]}); build_from_edges(edges, size); } + void print() + { + std::cout << "####################" << std::endl; + std::cout << "k_k:" << k_k << std::endl; + std::cout << "k_height:" << k_height << std::endl; + std::cout << "k_t_size:" << k_t.size() << std::endl; + std::cout << "k_l_size:" << k_l.size() << std::endl; + std::cout << "####################" << std::endl; + } - k2_tree(k2_tree& tr) + k2_tree(k2_tree &tr) { *this = tr; } - k2_tree(k2_tree&& tr) + k2_tree(k2_tree &&tr) { *this = std::move(tr); } @@ -395,17 +417,19 @@ class k2_tree * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ - k2_tree unionOp(k2_tree& k2_B) - { + k2_tree unionOp(k2_tree &k2_B) + { assert(this->k_k == k2_B.k_k); - if(k2_B.get_number_edges() == 0) { - return *this; + if (k2_B.get_number_edges() == 0) + { + return *this; } - if(this->get_number_edges() == 0) { + if (this->get_number_edges() == 0) + { return k2_B; } - + if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) throw std::logic_error("Trees must have the same number of nodes."); @@ -427,7 +451,8 @@ class k2_tree pA = 0; pB = 0; - while (!Q.empty()) { + while (!Q.empty()) + { next = Q.front(); Q.pop_front(); @@ -459,7 +484,7 @@ class k2_tree C[l].push_back(bA || bB); - if ((l + 1 < this->k_height || l + 1 < k2_B.get_height())&& (bA || bB)) + if ((l + 1 < this->k_height || l + 1 < k2_B.get_height()) && (bA || bB)) Q.push_back({l + 1, bA, bB}); } } @@ -487,9 +512,10 @@ class k2_tree } //! Move assignment operator - k2_tree& operator=(k2_tree&& tr) + k2_tree &operator=(k2_tree &&tr) { - if (this != &tr) { + if (this != &tr) + { k_t = std::move(tr.k_t); k_l = std::move(tr.k_l); k_k = std::move(tr.k_k); @@ -501,9 +527,10 @@ class k2_tree } //! Assignment operator - k2_tree& operator=(k2_tree& tr) + k2_tree &operator=(k2_tree &tr) { - if (this != &tr) { + if (this != &tr) + { k_t = tr.k_t; k_l = tr.k_l; k_k = tr.k_k; @@ -515,9 +542,10 @@ class k2_tree } //! Swap operator - void swap(k2_tree& tr) + void swap(k2_tree &tr) { - if (this != &tr) { + if (this != &tr) + { std::swap(k_t, tr.k_t); std::swap(k_l, tr.k_l); util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t)); @@ -528,7 +556,7 @@ class k2_tree } //! Equal operator - bool operator==(const k2_tree& tr) const + bool operator==(const k2_tree &tr) const { // TODO check the rank support equality? if (k_k != tr.k_k || k_height != tr.k_height) @@ -559,9 +587,9 @@ class k2_tree return k_height; } - int get_number_edges() + int get_number_edges() { - return k_l.size() == 0? 0 : k_l_rank(k_l.size()); + return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } //! Indicates whether node j is adjacent to node i or not. @@ -582,22 +610,23 @@ class k2_tree // This is duplicated to avoid an extra if at the loop. As idx_type // is unsigned and rank has an offset of one, is not possible to run // k_t_rank with zero as parameter at the first iteration. - row = std::floor(i/static_cast(n)); - col = std::floor(j/static_cast(n)); + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); i = i % n; j = j % n; idx_type level = k_k * row + col; - n = n/k_k; + n = n / k_k; - while (level < k_t.size()) { + while (level < k_t.size()) + { if (k_t[level] == 0) return false; - row = std::floor(i/static_cast(n)); - col = std::floor(j/static_cast(n)); + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); i = i % n; j = j % n; level = k_t_rank(level + 1) * k_2 + k_k * row + col; - n = n/k_k; + n = n / k_k; } return k_l[level - k_t.size()] == 1; @@ -619,9 +648,9 @@ class k2_tree size_type n = static_cast(std::pow(k_k, k_height)) / k_k; // y = k * i/n - idx_type y = k_k * std::floor(i/static_cast(n)); + idx_type y = k_k * std::floor(i / static_cast(n)); for (unsigned j = 0; j < k_k; j++) - _neigh(n/k_k, i % n, n * j, y + j, acc); + _neigh(n / k_k, i % n, n * j, y + j, acc); return acc; } @@ -638,21 +667,22 @@ class k2_tree // Size of the first square division size_type n = static_cast(std::pow(k_k, k_height)) / k_k; - idx_type y = std::floor(i/static_cast(n)); + idx_type y = std::floor(i / static_cast(n)); for (unsigned j = 0; j < k_k; j++) - _reverse_neigh(n/k_k, n * j, i % n, y + j * k_k, acc); + _reverse_neigh(n / k_k, n * j, i % n, y + j * k_k, acc); return acc; } - std::vector> range( + std::vector> range( idx_type row1, idx_type row2, - idx_type col1, idx_type col2 - ) const { - std::vector> res; + idx_type col1, idx_type col2) const + { + std::vector> res; size_type n = static_cast(std::pow(k_k, k_height)) / k_k; - struct state{ + struct state + { idx_type n, row1, row2, col1, col2, dr, dc, z; state(idx_type n, idx_type row1, idx_type row2, idx_type col1, idx_type col2, idx_type dr, idx_type dc, idx_type z) @@ -662,33 +692,52 @@ class k2_tree states.reserve(k_height); // minimum states.emplace_back(n, row1, row2, col1, col2, 0, 0, std::numeric_limits::max()); - while(!states.empty()){ + while (!states.empty()) + { state s = states.back(); states.pop_back(); //TODO: peel first loop where z==-1 atm - if(s.z!=std::numeric_limits::max() && s.z >= k_t.size()){ // Last level - if(k_l[s.z - k_t.size()] == 1){ + if (s.z != std::numeric_limits::max() && s.z >= k_t.size()) + { // Last level + if (k_l[s.z - k_t.size()] == 1) + { res.emplace_back(s.dr, s.dc); } - }else if(s.z==std::numeric_limits::max() || k_t[s.z]==1){ + } + else if (s.z == std::numeric_limits::max() || k_t[s.z] == 1) + { - auto y = k_t_rank(s.z+1) * k_k * k_k; + auto y = k_t_rank(s.z + 1) * k_k * k_k; - for(idx_type i=s.row1/s.n; i<=s.row2/s.n; ++i){ + for (idx_type i = s.row1 / s.n; i <= s.row2 / s.n; ++i) + { idx_type row1new, row2new; //TODO: loop peeling, first iteration and last iteration special - if(i==s.row1/s.n) row1new = s.row1 % s.n; else row1new = 0; - if(i==s.row2/s.n) row2new = s.row2 % s.n; else row2new = s.n - 1; + if (i == s.row1 / s.n) + row1new = s.row1 % s.n; + else + row1new = 0; + if (i == s.row2 / s.n) + row2new = s.row2 % s.n; + else + row2new = s.n - 1; - for(idx_type j=s.col1/s.n; j<=s.col2/s.n; ++j){ + for (idx_type j = s.col1 / s.n; j <= s.col2 / s.n; ++j) + { idx_type col1new, col2new; //TODO: loop peeling, first iteration and last iteration special - if(j==s.col1/s.n) col1new = s.col1 % s.n; else col1new = 0; - if(j==s.col2/s.n) col2new = s.col2 % s.n; else col2new = s.n - 1; - - states.emplace_back(s.n/k_k, row1new, row2new, col1new, col2new, - s.dr + s.n*i, s.dc + s.n*j, y + k_k*i+j); + if (j == s.col1 / s.n) + col1new = s.col1 % s.n; + else + col1new = 0; + if (j == s.col2 / s.n) + col2new = s.col2 % s.n; + else + col2new = s.n - 1; + + states.emplace_back(s.n / k_k, row1new, row2new, col1new, col2new, + s.dr + s.n * i, s.dc + s.n * j, y + k_k * i + j); } } } @@ -704,10 +753,10 @@ class k2_tree * \param string_name * \returns The number of written bytes. */ - size_type serialize(std::ostream& out, structure_tree_node* v=nullptr, - std::string name="") const + size_type serialize(std::ostream &out, structure_tree_node *v = nullptr, + std::string name = "") const { - structure_tree_node* child = structure_tree::add_child( + structure_tree_node *child = structure_tree::add_child( v, name, util::class_name(*this)); size_type written_bytes = 0; @@ -721,12 +770,11 @@ class k2_tree return written_bytes; } - //! Load from istream /*! Serialize the k2_tree from the given istream. * \param istream Stream to load the k2_tree from. */ - void load(std::istream& in) + void load(std::istream &in) { k_t.load(in); k_l.load(in); @@ -737,7 +785,6 @@ class k2_tree read_member(k_k, in); read_member(k_height, in); } - }; } // namespace sdsl From 79b6e5028801e9e1321de9755a937de7b946a72f Mon Sep 17 00:00:00 2001 From: Joana H Date: Mon, 30 Mar 2020 00:13:11 +0100 Subject: [PATCH 08/57] changed to protected --- include/sdsl/k2_tree.hpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 9c8d68f17..096a5f0b8 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "sdsl/bit_vectors.hpp" #include "sdsl/k2_tree_helper.hpp" #include "sdsl/int_vector_buffer.hpp" @@ -44,17 +45,17 @@ namespace sdsl * (pp. 18-30). Springer Berlin Heidelberg. */ -template +template class k2_tree { public: typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; -private: +protected: //! Bit array to store all the bits of the tree, except those in the //! last level. t_bv k_t; @@ -592,6 +593,22 @@ class k2_tree return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } + uint get_k() + { + return k_k; + } + + uint get_rank_l(int e) + { + return k_l_rank(e); + } + + //TODO: remove me + void clean_l_bit(uint i) + { + k_l[i] = 0; + } + //! Indicates whether node j is adjacent to node i or not. /*! * \param i Node i. From bcc03bfbe5d0ddd22db0f6d798812cd0a4faaa72 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 15 Apr 2020 23:47:13 +0100 Subject: [PATCH 09/57] Add remove edges --- .idea/.gitignore | 2 + include/sdsl/k2_tree.hpp | 116 ++++++++++++++++++--------------- test/k2_tree_test.cpp | 136 +++++++++++++++++++++++++-------------- 3 files changed, 152 insertions(+), 102 deletions(-) create mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..5c98b4288 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 096a5f0b8..ff59f9872 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -62,14 +62,13 @@ class k2_tree //! Bit array to store the last level of the tree. t_bv k_l; - size_t k_t_size = 0; - size_t k_l_size = 0; - t_rank k_t_rank; l_rank k_l_rank; uint8_t k_k; uint16_t k_height = 0; + + uint16_t n_marked_edges = 0; protected: void build_from_matrix(const std::vector> &matrix) @@ -93,8 +92,6 @@ class k2_tree bit_vector k_t_(t_size, 0); bit_vector k_l_(l_size, 0); - k_t_size = t_size; - k_l_size = l_size; int n = 0; for (int j = 1; j < k_height; j++) @@ -382,16 +379,6 @@ class k2_tree build_from_edges(edges, size); } - void print() - { - std::cout << "####################" << std::endl; - std::cout << "k_k:" << k_k << std::endl; - std::cout << "k_height:" << k_height << std::endl; - std::cout << "k_t_size:" << k_t.size() << std::endl; - std::cout << "k_l_size:" << k_l.size() << std::endl; - std::cout << "####################" << std::endl; - } - k2_tree(k2_tree &tr) { *this = tr; @@ -410,6 +397,21 @@ class k2_tree k_l_rank = l_rank(&k_l); } + t_bv get_t() + { + return k_t; + } + + t_bv get_l() + { + return k_l; + } + + uint8_t get_marked_edges() + { + return n_marked_edges; + } + //! Union Operation /*! Performs the union operation between two tree. This operations requires both * trees to have the same number of nodes. @@ -431,14 +433,14 @@ class k2_tree return k2_B; } - if (pow(this->k_k, this->get_height()) != pow(this->k_k, k2_B.get_height())) + if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); size_t t_size_A = this->get_t().size(); size_t t_size_B = k2_B.get_t().size(); // C Initialization - const size_t max_height = this->get_height() > k2_B.get_height() ? this->get_height() : k2_B.get_height(); + const size_t max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; std::deque> C(max_height); //////// @@ -468,7 +470,7 @@ class k2_tree bB = 0; if (rA == 1) { - if (l + 1 < this->get_height()) + if (l + 1 < this->k_height) bA = this->get_t()[pA]; else bA = this->get_l()[pA - t_size_A]; @@ -476,8 +478,8 @@ class k2_tree } if (rB == 1) { - if (l + 1 < k2_B.get_height()) - bB = k2_B.get_t()[pB]; + if (l + 1 < k2_B.k_height) + bB = k2_B.k_t[pB]; else bB = k2_B.get_l()[pB - t_size_B]; pB++; @@ -485,7 +487,7 @@ class k2_tree C[l].push_back(bA || bB); - if ((l + 1 < this->k_height || l + 1 < k2_B.get_height()) && (bA || bB)) + if ((l + 1 < this->k_height || l + 1 < k2_B.k_height) && (bA || bB)) Q.push_back({l + 1, bA, bB}); } } @@ -573,40 +575,10 @@ class k2_tree return true; } - t_bv get_t() - { - return k_t; - } - - t_bv get_l() - { - return k_l; - } - - size_t get_height() - { - return k_height; - } int get_number_edges() { - return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); - } - - uint get_k() - { - return k_k; - } - - uint get_rank_l(int e) - { - return k_l_rank(e); - } - - //TODO: remove me - void clean_l_bit(uint i) - { - k_l[i] = 0; + return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } //! Indicates whether node j is adjacent to node i or not. @@ -802,6 +774,46 @@ class k2_tree read_member(k_k, in); read_member(k_height, in); } + + bool erase(idx_type i, idx_type j) + { + if (k_t.size() == 0 && k_l.size() == 0) + return false; + size_type n = std::pow(k_k, k_height - 1); + size_type k_2 = std::pow(k_k, 2); + idx_type col, row; + + // This is duplicated to avoid an extra if at the loop. As idx_type + // is unsigned and rank has an offset of one, is not possible to run + // k_t_rank with zero as parameter at the first iteration. + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); + i = i % n; + j = j % n; + idx_type level = k_k * row + col; + n = n / k_k; + + while (level < k_t.size()) + { + if (k_t[level] == 0) + return false; + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); + i = i % n; + j = j % n; + level = k_t_rank(level + 1) * k_2 + k_k * row + col; + n = n / k_k; + } + + if (k_l[level - k_t.size()] == 1) + { + k_l[level - k_t.size()] = 0; + k_l_rank = l_rank(&k_l); + n_marked_edges++; + return true; + } + return false; + } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 4dfc19f7f..935a3eed9 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -14,19 +14,16 @@ using namespace std; typedef int_vector<>::size_type size_type; template -class k2_tree_test_k_2 : public ::testing::Test -{ -}; +class k2_tree_test_k_2 : public ::testing::Test {}; template -class k2_tree_test_k_3 : public ::testing::Test -{ -}; +class k2_tree_test_k_3 : public ::testing::Test {}; template -class k2_tree_test : public ::testing::Test -{ -}; +class k2_tree_test : public ::testing::Test {}; + +template +class k2_tree_test_marked : public ::testing::Test {}; using testing::Types; @@ -91,6 +88,14 @@ typedef Types< k2_tree<4, bit_vector, rank_support_v<>>> Implementations; +typedef Types< + k2_tree<2, bit_vector>, + k2_tree<3, bit_vector>, + k2_tree<7, bit_vector>, + k2_tree<5, bit_vector, rank_support_v<>>, + k2_tree<4, bit_vector, rank_support_v<>>> + Implementations_bit_vector; + TYPED_TEST_CASE(k2_tree_test_k_2, k_2_implementations); TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) @@ -166,6 +171,47 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); } +TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) +{ +typedef std::tuple + t_tuple; +vector> + e; + +t_tuple a{0, 0}; +t_tuple b{0, 1}; +t_tuple c{1, 0}; +t_tuple d{1, 1}; +e.push_back(t_tuple{1, 2}); +TypeParam tree(e, 4); + +k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + +tree = TypeParam(e, 3); +k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + +e.push_back(t_tuple{1, 2}); +tree = TypeParam(e, 3); +k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + +e.clear(); +e.push_back(t_tuple{0, 0}); +tree = TypeParam(e, 1); +k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); + +e.push_back(t_tuple{0, 1}); +e.push_back(t_tuple{1, 0}); +e.push_back(t_tuple{1, 1}); +tree = TypeParam(e, 2); +k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 1, 1}); + +e.push_back(t_tuple{2, 2}); +tree = TypeParam(e, 3); +k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); +} + TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) { vector> mat({{1, 1, 0, 0}, @@ -223,47 +269,6 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); } -TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) -{ - typedef std::tuple - t_tuple; - vector> - e; - - t_tuple a{0, 0}; - t_tuple b{0, 1}; - t_tuple c{1, 0}; - t_tuple d{1, 1}; - e.push_back(t_tuple{1, 2}); - TypeParam tree(e, 4); - - k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); - - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); - - e.push_back(t_tuple{1, 2}); - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); - - e.clear(); - e.push_back(t_tuple{0, 0}); - tree = TypeParam(e, 1); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); - - e.push_back(t_tuple{0, 1}); - e.push_back(t_tuple{1, 0}); - e.push_back(t_tuple{1, 1}); - tree = TypeParam(e, 2); - k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 1, 1}); - - e.push_back(t_tuple{2, 2}); - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); -} - TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) @@ -694,6 +699,37 @@ TYPED_TEST(k2_tree_test, serialize_test) k2_tree_test_nm::check_serialize_load(tree); } + +TYPED_TEST_CASE(k2_tree_test_marked, Implementations_bit_vector); +TYPED_TEST(k2_tree_test_marked, marked_edges) +{ + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + + ASSERT_EQ(tree.get_marked_edges(), 0); + ASSERT_EQ(tree.get_number_edges(), 6); + ASSERT_TRUE(tree.erase(0,0)); + ASSERT_EQ(tree.get_marked_edges(), 1); + ASSERT_EQ(tree.get_number_edges(), 5); + + ASSERT_TRUE(tree.erase(0,4)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); + + ASSERT_FALSE(tree.erase(0,4)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); + + ASSERT_FALSE(tree.erase(1,2)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); +} + } // namespace int main(int argc, char **argv) From 0c48d0f948eab83b9cc48505eb1873eccc3b4501 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 23 Apr 2020 00:21:25 +0100 Subject: [PATCH 10/57] edge iterator --- .gitignore | 1 + include/sdsl/k2_tree.hpp | 114 ++++- test/k2_tree_test.cpp | 1003 +++++++++++++++++++------------------- 3 files changed, 622 insertions(+), 496 deletions(-) diff --git a/.gitignore b/.gitignore index 658c4c6a4..b915d07d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ Make.helper +.vscode \ No newline at end of file diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index ff59f9872..65e860fae 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "sdsl/bit_vectors.hpp" #include "sdsl/k2_tree_helper.hpp" #include "sdsl/int_vector_buffer.hpp" @@ -67,10 +68,9 @@ class k2_tree uint8_t k_k; uint16_t k_height = 0; - + uint16_t n_marked_edges = 0; -protected: void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -575,10 +575,9 @@ class k2_tree return true; } - int get_number_edges() { - return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } //! Indicates whether node j is adjacent to node i or not. @@ -814,6 +813,113 @@ class k2_tree } return false; } + + using edge = std::tuple; + class edge_iterator + { + public: + using value_type = edge; + using difference_type = std::ptrdiff_t; + using pointer = edge *; + using reference = edge &; + using iterator_category = std::forward_iterator_tag; + + edge_iterator(t_bv &k_t, t_bv &k_l, t_rank &k_t_rank, uint16_t &k_height) : k_t(k_t), k_l(k_l), k_t_rank(k_t_rank), k_height(k_height) + { + _initialize(); + } + edge_iterator(pointer p) : _ptr(p) {} + edge operator*() + { + return *_ptr; + } + + private: + pointer _ptr; + + // container + t_bv &k_t; + t_bv &k_l; + t_rank &k_t_rank; + uint16_t &k_height; + const size_t size = std::pow(k, k_height); + // + + // iterator state // + idx_type curr_node, curr_neigh; + unsigned curr_row, curr_col; + const size_type _n = static_cast(std::pow(k, k_height)) / k; + // + + void _initialize() + { + // if (k_l.size() == 0 && k_t.size() == 0) + // return acc; + //TODO: Take care of this edge case + curr_node = 0; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + curr_row = 0; + curr_col = 0; + + edge first = _find_next(); + _ptr = &first; + } + + edge _find_next() + { + idx_type neigh; + if (curr_node < size) + { + for (; curr_row < k; curr_row++) + { + neigh = size; + _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh); + if (neigh < size) + { + std::cout << "return: (" << curr_node << "," << neigh << ")" << std::endl; + return edge(curr_node, neigh); + } + } + if (curr_row >= k) curr_row = 0; + curr_node++; + std::cout << "current node: " << curr_node << std::endl; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + curr_col = 0; + return _find_next(); + } + return edge(size, size); + } + + bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh) + { + if (level >= k_t.size()) + { // Last level + if (k_l[level - k_t.size()] == 1) + { + std::cout << "row: " << row << " col: " << col << std::endl; + neigh = col; + return false; + } + } + + if (k_t[level] == 1) + { + curr_neigh = k_t_rank(level + 1) * std::pow(k, 2) + + k * std::floor(row / static_cast(n)); + while(curr_col < k) { + if(_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) { + curr_col++; + } else + break; + } + if(curr_col < k) curr_col = 0; + } + // did not found + return true; + } + }; + + edge_iterator edge_begin() { return edge_iterator(k_t, k_l, k_t_rank, k_height); } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 935a3eed9..73b7fe024 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -10,20 +10,29 @@ namespace using namespace sdsl; using namespace std; +using namespace k2_tree_ns; typedef int_vector<>::size_type size_type; template -class k2_tree_test_k_2 : public ::testing::Test {}; +class k2_tree_test_k_2 : public ::testing::Test +{ +}; template -class k2_tree_test_k_3 : public ::testing::Test {}; +class k2_tree_test_k_3 : public ::testing::Test +{ +}; template -class k2_tree_test : public ::testing::Test {}; +class k2_tree_test : public ::testing::Test +{ +}; template -class k2_tree_test_marked : public ::testing::Test {}; +class k2_tree_test_marked : public ::testing::Test +{ +}; using testing::Types; @@ -47,12 +56,8 @@ void assert_eq_tree(t_tree &tree1, t_tree &tree2) ASSERT_EQ(tree1.get_t().size(), tree2.get_t().size()); ASSERT_EQ(tree1.get_l().size(), tree2.get_l().size()); for (unsigned i = 0; i < tree1.get_t().size(); i++) - { - std::cout << tree1.get_t().get_int(i, 1) << std::endl; - std::cout << tree2.get_t().get_int(i, 1) << std::endl; - ASSERT_EQ(tree1.get_t().get_int(i, 1), tree2.get_t().get_int(i, 1)); - } + for (unsigned i = 0; i < tree1.get_l().size(); i++) ASSERT_EQ(tree1.get_l().get_int(i, 1), tree2.get_l().get_int(i, 1)); } @@ -173,43 +178,43 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) { -typedef std::tuple + typedef std::tuple t_tuple; -vector> + vector> e; -t_tuple a{0, 0}; -t_tuple b{0, 1}; -t_tuple c{1, 0}; -t_tuple d{1, 1}; -e.push_back(t_tuple{1, 2}); -TypeParam tree(e, 4); + t_tuple a{0, 0}; + t_tuple b{0, 1}; + t_tuple c{1, 0}; + t_tuple d{1, 1}; + e.push_back(t_tuple{1, 2}); + TypeParam tree(e, 4); -k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); -tree = TypeParam(e, 3); -k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); -e.push_back(t_tuple{1, 2}); -tree = TypeParam(e, 3); -k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); + e.push_back(t_tuple{1, 2}); + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {0, 1, 0, 0}, {0, 0, 1, 0}); -e.clear(); -e.push_back(t_tuple{0, 0}); -tree = TypeParam(e, 1); -k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); + e.clear(); + e.push_back(t_tuple{0, 0}); + tree = TypeParam(e, 1); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0}); -e.push_back(t_tuple{0, 1}); -e.push_back(t_tuple{1, 0}); -e.push_back(t_tuple{1, 1}); -tree = TypeParam(e, 2); -k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 1, 1}); + e.push_back(t_tuple{0, 1}); + e.push_back(t_tuple{1, 0}); + e.push_back(t_tuple{1, 1}); + tree = TypeParam(e, 2); + k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 1, 1}); -e.push_back(t_tuple{2, 2}); -tree = TypeParam(e, 3); -k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); + e.push_back(t_tuple{2, 2}); + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); } TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) @@ -269,466 +274,480 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); } -TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); - -TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) -{ - vector> mat({{1, 1, 0, 0, 1}, - {0, 1, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {1, 1, 0, 1, 0}, - {0, 0, 1, 0, 0}}); - - TypeParam tree(mat); - vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; - vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, - 0, 1, 0, 0, 0, 0, 1, 0, 0, - 1, 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0}; - k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - - mat = vector>({{1, 1, 1, 0}, - {1, 0, 0, 0}, - {0, 0, 0, 0}, - {1, 1, 0, 0}}); - - tree = TypeParam(mat); - expected_t = {1, 0, 0, 1, 0, 0, 0, 0, 0}; - expected_l = {1, 1, 1, 1, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0}; - k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - - mat = vector>({{0, 0, 0}, - {0, 0, 0}, - {0, 0, 0}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {}); - - // Size is minor than k: - mat = vector>({{0}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {}); - - mat = vector>({{1}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - - mat = vector>({{1, 0}, - {0, 1}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0, 0}); - - // Size is a power of k: - mat = vector>({{0, 0, 1, 0, 0, 0, 0, 0, 0}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 1, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 0, 0, 0, 0, 0, 0}}); - tree = TypeParam(mat); - expected_t = {1, 0, 0, 0, 0, 0, 1, 0, 0}; - expected_l = {0, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1}; - k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - - mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, - {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, - {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); - tree = TypeParam(mat); - expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0}; - - expected_l = {0, 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, - 1, 0, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 0, 1, 0, 0, 0, 0, 0}; - k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); -} - -TYPED_TEST(k2_tree_test_k_3, build_from_edges_array) -{ - typedef std::tuple - t_tuple; - vector> - e; - - e.push_back(t_tuple{1, 2}); - TypeParam tree(e, 4); - - k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 1, 0, 0, 0}); - - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); - - e.push_back(t_tuple{1, 2}); - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); - - e.clear(); - e.push_back(t_tuple{0, 0}); - tree = TypeParam(e, 1); - k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - - e.push_back(t_tuple{0, 1}); - e.push_back(t_tuple{1, 0}); - e.push_back(t_tuple{1, 1}); - tree = TypeParam(e, 2); - k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 0, 1, 1, 0, 0, 0, 0}); - - e.clear(); - e.push_back(t_tuple{2, 2}); - tree = TypeParam(e, 3); - k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 0, 0, 0, 1}); -} - -TYPED_TEST(k2_tree_test_k_3, union_operation_test) +TYPED_TEST(k2_tree_test_k_2, edge_iterator) { vector> mat({{1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0}}); - - TypeParam tree_A(mat); - - mat = vector>({{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 1}}); - TypeParam tree_B(mat); - - TypeParam unionTree = tree_A.unionOp(tree_B); - k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); -} - -TYPED_TEST(k2_tree_test_k_3, empty_union_operation) -{ - vector> mat({{1, 1, 0, 0, 1}, - {0, 1, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {1, 1, 0, 1, 0}, - {0, 0, 1, 0, 0}}); - - vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; - vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, - 0, 1, 0, 0, 0, 0, 1, 0, 0, - 1, 1, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0}; - TypeParam tree_A(mat); - TypeParam tree_B; - - TypeParam unionTree = tree_A.unionOp(tree_B); - k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); - - unionTree = tree_B.unionOp(tree_A); - k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); - - unionTree = tree_B.unionOp(tree_B); - k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); -} - -TYPED_TEST_CASE(k2_tree_test, Implementations); - -TYPED_TEST(k2_tree_test, edges_array_exhaustive) -{ - typedef std::tuple - t_tuple; - vector> - e; - e.push_back(t_tuple{5, 7}); - e.push_back(t_tuple{1, 2}); - e.push_back(t_tuple{3, 9}); - e.push_back(t_tuple{2, 2}); - e.push_back(t_tuple{3, 2}); - e.push_back(t_tuple{7, 5}); - e.push_back(t_tuple{1, 6}); - e.push_back(t_tuple{4, 8}); - e.push_back(t_tuple{4, 1}); - e.push_back(t_tuple{5, 2}); - - TypeParam tree(e, 10); - auto expected_neighbors = vector>(10); - expected_neighbors[0] = vector({}); - expected_neighbors[1] = vector({2, 6}); - expected_neighbors[2] = vector({2}); - expected_neighbors[3] = vector({2, 9}); - expected_neighbors[4] = vector({1, 8}); - expected_neighbors[5] = vector({2, 7}); - expected_neighbors[6] = vector({}); - expected_neighbors[7] = vector({5}); - expected_neighbors[8] = vector({}); - expected_neighbors[9] = vector({}); - for (unsigned i = 0; i < 10; i++) - { - auto actual_neighbors = tree.neigh(i); - ASSERT_EQ(expected_neighbors[i].size(), actual_neighbors.size()); - for (unsigned j = 0; i < expected_neighbors[i].size(); i++) - ASSERT_EQ(expected_neighbors[i][j], actual_neighbors[j]); - } - - e.clear(); - e.push_back(t_tuple{0, 0}); - tree = TypeParam(e, 1); - ASSERT_EQ(1u, tree.neigh(0).size()); - ASSERT_EQ(0u, tree.neigh(0)[0]); -} - -TYPED_TEST(k2_tree_test, neighbors_test) -{ - vector> mat({{1, 1, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 1}, - {0, 0, 1, 0}}); - + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 0}}); TypeParam tree(mat); - auto neigh_0 = tree.neigh(0); - vector expected_neigh_0({0, 1}); - ASSERT_EQ(expected_neigh_0.size(), neigh_0.size()); - for (unsigned i = 0; i < neigh_0.size(); i++) - ASSERT_EQ(expected_neigh_0[i], neigh_0[i]); - - auto neigh_3 = tree.neigh(3); - vector expected_neigh_3({2}); - ASSERT_EQ(expected_neigh_3.size(), neigh_3.size()); - for (unsigned i = 0; i < neigh_3.size(); i++) - ASSERT_EQ(expected_neigh_3[i], neigh_3[i]); - - mat = vector>({{1}}); - tree = TypeParam(mat); - neigh_0 = tree.neigh(0); - ASSERT_EQ(0u, neigh_0[0]); - ASSERT_EQ(1u, neigh_0.size()); - - mat = vector>({{0, 0, 0}, - {1, 0, 1}, - {0, 1, 1}}); - tree = TypeParam(mat); - neigh_0 = tree.neigh(0); - ASSERT_EQ(0u, neigh_0.size()); - - auto neigh_1 = tree.neigh(1); - auto expected_neigh_1 = vector({0, 2}); - ASSERT_EQ(expected_neigh_1.size(), neigh_1.size()); - for (unsigned i = 0; i < neigh_1.size(); i++) - ASSERT_EQ(expected_neigh_1[i], neigh_1[i]); - - mat = vector>({{0, 0}, - {0, 0}}); - tree = TypeParam(mat); - neigh_0 = tree.neigh(0); - ASSERT_EQ(0u, neigh_0.size()); + std::tuple edge = *tree.edge_begin(); + cout << "x: " << std::get<0>(edge) << " y: " << std::get<1>(edge) << endl; } -TYPED_TEST(k2_tree_test, reverse_neighbors_test) -{ - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1}}); - - auto tree = TypeParam(mat); - auto r_neigh_0 = tree.reverse_neigh(0); - auto expected_r_neigh_0 = vector({0}); - auto r_neigh_1 = tree.reverse_neigh(1); - auto r_neigh_2 = tree.reverse_neigh(2); - auto expected_r_neigh_2 = vector({2, 4}); - ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); - ASSERT_EQ(0u, r_neigh_1.size()); - ASSERT_EQ(expected_r_neigh_2.size(), r_neigh_2.size()); - - for (unsigned i = 0; i < r_neigh_0.size(); i++) - ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); - - for (unsigned i = 0; i < r_neigh_2.size(); i++) - ASSERT_EQ(expected_r_neigh_2[i], r_neigh_2[i]); - - mat = vector>({{0, 0}, - {0, 0}}); - tree = TypeParam(mat); - r_neigh_0 = tree.reverse_neigh(0); - r_neigh_1 = tree.reverse_neigh(1); - ASSERT_EQ(0u, r_neigh_0.size()); - ASSERT_EQ(0u, r_neigh_1.size()); - - mat = vector>({{0, 1}, - {1, 0}}); - tree = TypeParam(mat); - r_neigh_0 = tree.reverse_neigh(0); - expected_r_neigh_0 = vector({1}); - r_neigh_1 = tree.reverse_neigh(1); - auto expected_r_neigh_1 = vector({0}); - - ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); - ASSERT_EQ(expected_r_neigh_1.size(), r_neigh_1.size()); - for (unsigned i = 0; i < r_neigh_0.size(); i++) - ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); - - for (unsigned i = 0; i < r_neigh_1.size(); i++) - ASSERT_EQ(expected_r_neigh_1[i], r_neigh_1[i]); -} - -TYPED_TEST(k2_tree_test, range_test) -{ - static const vector> mat{ - // 0 1 2 3 4 5 6 7 8 9 10 - /* 0*/ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* 1*/ {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, - /* 2*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* 3*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - - /* 4*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* 5*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* 6*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* 7*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, - - /* 8*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, - /* 9*/ {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, - /*10*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, - }; - TypeParam tree(mat); - - auto result = tree.range(7, 9, 5, 9); - static const decltype(result) expected{ - {7, 6}, - {8, 6}, - {8, 9}, - {9, 6}, - {9, 8}}; - sort(result.begin(), result.end()); - ASSERT_EQ(expected, result); - - auto all = tree.range(0, 10, 0, 10); - static const decltype(all) expectedAll{ - {0, 1}, - {1, 2}, - {1, 3}, - {1, 4}, - {7, 6}, - {8, 6}, - {8, 9}, - {9, 6}, - {9, 8}, - {9, 10}, - {10, 6}, - {10, 9}}; - sort(all.begin(), all.end()); - ASSERT_EQ(expectedAll, all); - - auto single = tree.range(1, 1, 3, 3); - static const decltype(single) expectedSingle{ - {1, 3}}; - ASSERT_EQ(expectedSingle, single); - - auto empty = tree.range(0, 6, 5, 10); - static const decltype(empty) expectedEmpty{}; - ASSERT_EQ(expectedEmpty, empty); -} - -TYPED_TEST(k2_tree_test, adj_test) -{ - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1}}); - - auto tree = TypeParam(mat); - ASSERT_TRUE(tree.adj(0, 0)); - ASSERT_TRUE(tree.adj(0, 4)); - ASSERT_FALSE(tree.adj(4, 0)); - ASSERT_TRUE(tree.adj(4, 4)); - ASSERT_FALSE(tree.adj(1, 1)); - ASSERT_TRUE(tree.adj(2, 2)); - ASSERT_TRUE(tree.adj(2, 3)); - - mat = vector>({{0}}); - tree = TypeParam(mat); - ASSERT_FALSE(tree.adj(0, 0)); - mat = vector>({{1}}); - tree = TypeParam(mat); - ASSERT_TRUE(tree.adj(0, 0)); -} - -TYPED_TEST(k2_tree_test, serialize_test) -{ - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1}}); - - auto tree = TypeParam(mat); - k2_tree_test_nm::check_serialize_load(tree); - - mat = vector>({{0}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_serialize_load(tree); - - tree = TypeParam(); - k2_tree_test_nm::check_serialize_load(tree); - - mat = vector>({{0, 0}, - {0, 0}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_serialize_load(tree); - - mat = vector>({{1, 1}, - {1, 1}}); - tree = TypeParam(mat); - k2_tree_test_nm::check_serialize_load(tree); -} - - -TYPED_TEST_CASE(k2_tree_test_marked, Implementations_bit_vector); -TYPED_TEST(k2_tree_test_marked, marked_edges) -{ - vector> mat({{1, 0, 0, 0, 1}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 1, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 1, 0, 1}}); - - auto tree = TypeParam(mat); - - ASSERT_EQ(tree.get_marked_edges(), 0); - ASSERT_EQ(tree.get_number_edges(), 6); - ASSERT_TRUE(tree.erase(0,0)); - ASSERT_EQ(tree.get_marked_edges(), 1); - ASSERT_EQ(tree.get_number_edges(), 5); - - ASSERT_TRUE(tree.erase(0,4)); - ASSERT_EQ(tree.get_marked_edges(), 2); - ASSERT_EQ(tree.get_number_edges(), 4); - - ASSERT_FALSE(tree.erase(0,4)); - ASSERT_EQ(tree.get_marked_edges(), 2); - ASSERT_EQ(tree.get_number_edges(), 4); - - ASSERT_FALSE(tree.erase(1,2)); - ASSERT_EQ(tree.get_marked_edges(), 2); - ASSERT_EQ(tree.get_number_edges(), 4); -} +// TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); + +// TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) +// { +// vector> mat({{1, 1, 0, 0, 1}, +// {0, 1, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {1, 1, 0, 1, 0}, +// {0, 0, 1, 0, 0}}); + +// TypeParam tree(mat); + +// cout << "ALGORIOTHM" << endl; +// cout << all_of(tree.get_l().begin(), tree.get_l().end(), [](int i) { return i % 2 == 0; }) << endl; + +// vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; +// vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, +// 0, 1, 0, 0, 0, 0, 1, 0, 0, +// 1, 1, 0, 0, 0, 1, 0, 0, 0, +// 1, 0, 0, 0, 0, 0, 0, 0, 0}; +// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); + +// mat = vector>({{1, 1, 1, 0}, +// {1, 0, 0, 0}, +// {0, 0, 0, 0}, +// {1, 1, 0, 0}}); + +// tree = TypeParam(mat); +// expected_t = {1, 0, 0, 1, 0, 0, 0, 0, 0}; +// expected_l = {1, 1, 1, 1, 0, 0, 0, 0, 0, +// 1, 1, 0, 0, 0, 0, 0, 0, 0}; +// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); + +// mat = vector>({{0, 0, 0}, +// {0, 0, 0}, +// {0, 0, 0}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_t_l(tree, {}, {}); + +// // Size is minor than k: +// mat = vector>({{0}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_t_l(tree, {}, {}); + +// mat = vector>({{1}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); + +// mat = vector>({{1, 0}, +// {0, 1}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0, 0}); + +// // Size is a power of k: +// mat = vector>({{0, 0, 1, 0, 0, 0, 0, 0, 0}, +// {1, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 1, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 1, 0, 0, 0, 0, 0, 0}}); +// tree = TypeParam(mat); +// expected_t = {1, 0, 0, 0, 0, 0, 1, 0, 0}; +// expected_l = {0, 0, 1, 1, 0, 0, 0, 1, 0, +// 0, 0, 0, 0, 0, 0, 0, 0, 1}; +// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); + +// mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, +// {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, +// {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); +// tree = TypeParam(mat); +// expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0, +// 1, 1, 0, 0, 0, 0, 0, 0, 1, +// 0, 0, 0, 0, 0, 0, 1, 0, 0, +// 0, 0, 1, 0, 0, 0, 0, 0, 0, +// 1, 0, 0, 0, 0, 0, 0, 0, 0}; + +// expected_l = {0, 1, 0, 0, 0, 1, 0, 0, 0, +// 0, 0, 0, 1, 1, 0, 0, 0, 0, +// 0, 0, 0, 1, 0, 0, 1, 0, 0, +// 0, 0, 0, 0, 0, 0, 1, 0, 0, +// 1, 0, 1, 1, 0, 0, 0, 0, 0, +// 0, 1, 0, 1, 0, 0, 0, 0, 0}; +// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); +// } + +// TYPED_TEST(k2_tree_test_k_3, build_from_edges_array) +// { +// typedef std::tuple +// t_tuple; +// vector> +// e; + +// e.push_back(t_tuple{1, 2}); +// TypeParam tree(e, 4); + +// k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 0, 0, 0, 0, 0, 0}, +// {0, 0, 0, 0, 0, 1, 0, 0, 0}); + +// tree = TypeParam(e, 3); +// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + +// e.push_back(t_tuple{1, 2}); +// tree = TypeParam(e, 3); +// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + +// e.clear(); +// e.push_back(t_tuple{0, 0}); +// tree = TypeParam(e, 1); +// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); + +// e.push_back(t_tuple{0, 1}); +// e.push_back(t_tuple{1, 0}); +// e.push_back(t_tuple{1, 1}); +// tree = TypeParam(e, 2); +// k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 0, 1, 1, 0, 0, 0, 0}); + +// e.clear(); +// e.push_back(t_tuple{2, 2}); +// tree = TypeParam(e, 3); +// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 0, 0, 0, 1}); +// } + +// TYPED_TEST(k2_tree_test_k_3, union_operation_test) +// { +// vector> mat({{1, 1, 0, 0}, +// {0, 1, 0, 0}, +// {0, 0, 1, 1}, +// {0, 0, 1, 0}}); + +// TypeParam tree_A(mat); + +// mat = vector>({{0, 0, 0, 0}, +// {0, 0, 0, 0}, +// {0, 0, 0, 0}, +// {0, 0, 0, 1}}); +// TypeParam tree_B(mat); + +// TypeParam unionTree = tree_A.unionOp(tree_B); +// k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); +// } + +// TYPED_TEST(k2_tree_test_k_3, empty_union_operation) +// { +// vector> mat({{1, 1, 0, 0, 1}, +// {0, 1, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {1, 1, 0, 1, 0}, +// {0, 0, 1, 0, 0}}); + +// vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; +// vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, +// 0, 1, 0, 0, 0, 0, 1, 0, 0, +// 1, 1, 0, 0, 0, 1, 0, 0, 0, +// 1, 0, 0, 0, 0, 0, 0, 0, 0}; +// TypeParam tree_A(mat); +// TypeParam tree_B; + +// TypeParam unionTree = tree_A.unionOp(tree_B); +// k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + +// unionTree = tree_B.unionOp(tree_A); +// k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + +// unionTree = tree_B.unionOp(tree_B); +// k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); +// } + +// TYPED_TEST_CASE(k2_tree_test, Implementations); + +// TYPED_TEST(k2_tree_test, edges_array_exhaustive) +// { +// typedef std::tuple +// t_tuple; +// vector> +// e; +// e.push_back(t_tuple{5, 7}); +// e.push_back(t_tuple{1, 2}); +// e.push_back(t_tuple{3, 9}); +// e.push_back(t_tuple{2, 2}); +// e.push_back(t_tuple{3, 2}); +// e.push_back(t_tuple{7, 5}); +// e.push_back(t_tuple{1, 6}); +// e.push_back(t_tuple{4, 8}); +// e.push_back(t_tuple{4, 1}); +// e.push_back(t_tuple{5, 2}); + +// TypeParam tree(e, 10); +// auto expected_neighbors = vector>(10); +// expected_neighbors[0] = vector({}); +// expected_neighbors[1] = vector({2, 6}); +// expected_neighbors[2] = vector({2}); +// expected_neighbors[3] = vector({2, 9}); +// expected_neighbors[4] = vector({1, 8}); +// expected_neighbors[5] = vector({2, 7}); +// expected_neighbors[6] = vector({}); +// expected_neighbors[7] = vector({5}); +// expected_neighbors[8] = vector({}); +// expected_neighbors[9] = vector({}); +// for (unsigned i = 0; i < 10; i++) +// { +// auto actual_neighbors = tree.neigh(i); +// ASSERT_EQ(expected_neighbors[i].size(), actual_neighbors.size()); +// for (unsigned j = 0; i < expected_neighbors[i].size(); i++) +// ASSERT_EQ(expected_neighbors[i][j], actual_neighbors[j]); +// } + +// e.clear(); +// e.push_back(t_tuple{0, 0}); +// tree = TypeParam(e, 1); +// ASSERT_EQ(1u, tree.neigh(0).size()); +// ASSERT_EQ(0u, tree.neigh(0)[0]); +// } + +// TYPED_TEST(k2_tree_test, neighbors_test) +// { +// vector> mat({{1, 1, 0, 0}, +// {0, 1, 0, 0}, +// {0, 0, 1, 1}, +// {0, 0, 1, 0}}); + +// TypeParam tree(mat); +// auto neigh_0 = tree.neigh(0); +// vector expected_neigh_0({0, 1}); +// ASSERT_EQ(expected_neigh_0.size(), neigh_0.size()); +// for (unsigned i = 0; i < neigh_0.size(); i++) +// ASSERT_EQ(expected_neigh_0[i], neigh_0[i]); + +// auto neigh_3 = tree.neigh(3); +// vector expected_neigh_3({2}); +// ASSERT_EQ(expected_neigh_3.size(), neigh_3.size()); +// for (unsigned i = 0; i < neigh_3.size(); i++) +// ASSERT_EQ(expected_neigh_3[i], neigh_3[i]); + +// mat = vector>({{1}}); +// tree = TypeParam(mat); +// neigh_0 = tree.neigh(0); +// ASSERT_EQ(0u, neigh_0[0]); +// ASSERT_EQ(1u, neigh_0.size()); + +// mat = vector>({{0, 0, 0}, +// {1, 0, 1}, +// {0, 1, 1}}); +// tree = TypeParam(mat); +// neigh_0 = tree.neigh(0); +// ASSERT_EQ(0u, neigh_0.size()); + +// auto neigh_1 = tree.neigh(1); +// auto expected_neigh_1 = vector({0, 2}); +// ASSERT_EQ(expected_neigh_1.size(), neigh_1.size()); +// for (unsigned i = 0; i < neigh_1.size(); i++) +// ASSERT_EQ(expected_neigh_1[i], neigh_1[i]); + +// mat = vector>({{0, 0}, +// {0, 0}}); +// tree = TypeParam(mat); +// neigh_0 = tree.neigh(0); +// ASSERT_EQ(0u, neigh_0.size()); +// } + +// TYPED_TEST(k2_tree_test, reverse_neighbors_test) +// { +// vector> mat({{1, 0, 0, 0, 1}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 0, 1}}); + +// auto tree = TypeParam(mat); +// auto r_neigh_0 = tree.reverse_neigh(0); +// auto expected_r_neigh_0 = vector({0}); +// auto r_neigh_1 = tree.reverse_neigh(1); +// auto r_neigh_2 = tree.reverse_neigh(2); +// auto expected_r_neigh_2 = vector({2, 4}); +// ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); +// ASSERT_EQ(0u, r_neigh_1.size()); +// ASSERT_EQ(expected_r_neigh_2.size(), r_neigh_2.size()); + +// for (unsigned i = 0; i < r_neigh_0.size(); i++) +// ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); + +// for (unsigned i = 0; i < r_neigh_2.size(); i++) +// ASSERT_EQ(expected_r_neigh_2[i], r_neigh_2[i]); + +// mat = vector>({{0, 0}, +// {0, 0}}); +// tree = TypeParam(mat); +// r_neigh_0 = tree.reverse_neigh(0); +// r_neigh_1 = tree.reverse_neigh(1); +// ASSERT_EQ(0u, r_neigh_0.size()); +// ASSERT_EQ(0u, r_neigh_1.size()); + +// mat = vector>({{0, 1}, +// {1, 0}}); +// tree = TypeParam(mat); +// r_neigh_0 = tree.reverse_neigh(0); +// expected_r_neigh_0 = vector({1}); +// r_neigh_1 = tree.reverse_neigh(1); +// auto expected_r_neigh_1 = vector({0}); + +// ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); +// ASSERT_EQ(expected_r_neigh_1.size(), r_neigh_1.size()); +// for (unsigned i = 0; i < r_neigh_0.size(); i++) +// ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); + +// for (unsigned i = 0; i < r_neigh_1.size(); i++) +// ASSERT_EQ(expected_r_neigh_1[i], r_neigh_1[i]); +// } + +// TYPED_TEST(k2_tree_test, range_test) +// { +// static const vector> mat{ +// // 0 1 2 3 4 5 6 7 8 9 10 +// /* 0*/ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// /* 1*/ {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, +// /* 2*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// /* 3*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + +// /* 4*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// /* 5*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// /* 6*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +// /* 7*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + +// /* 8*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, +// /* 9*/ {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, +// /*10*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, +// }; +// TypeParam tree(mat); + +// auto result = tree.range(7, 9, 5, 9); +// static const decltype(result) expected{ +// {7, 6}, +// {8, 6}, +// {8, 9}, +// {9, 6}, +// {9, 8}}; +// sort(result.begin(), result.end()); +// ASSERT_EQ(expected, result); + +// auto all = tree.range(0, 10, 0, 10); +// static const decltype(all) expectedAll{ +// {0, 1}, +// {1, 2}, +// {1, 3}, +// {1, 4}, +// {7, 6}, +// {8, 6}, +// {8, 9}, +// {9, 6}, +// {9, 8}, +// {9, 10}, +// {10, 6}, +// {10, 9}}; +// sort(all.begin(), all.end()); +// ASSERT_EQ(expectedAll, all); + +// auto single = tree.range(1, 1, 3, 3); +// static const decltype(single) expectedSingle{ +// {1, 3}}; +// ASSERT_EQ(expectedSingle, single); + +// auto empty = tree.range(0, 6, 5, 10); +// static const decltype(empty) expectedEmpty{}; +// ASSERT_EQ(expectedEmpty, empty); +// } + +// TYPED_TEST(k2_tree_test, adj_test) +// { +// vector> mat({{1, 0, 0, 0, 1}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 0, 1}}); + +// auto tree = TypeParam(mat); +// ASSERT_TRUE(tree.adj(0, 0)); +// ASSERT_TRUE(tree.adj(0, 4)); +// ASSERT_FALSE(tree.adj(4, 0)); +// ASSERT_TRUE(tree.adj(4, 4)); +// ASSERT_FALSE(tree.adj(1, 1)); +// ASSERT_TRUE(tree.adj(2, 2)); +// ASSERT_TRUE(tree.adj(2, 3)); + +// mat = vector>({{0}}); +// tree = TypeParam(mat); +// ASSERT_FALSE(tree.adj(0, 0)); +// mat = vector>({{1}}); +// tree = TypeParam(mat); +// ASSERT_TRUE(tree.adj(0, 0)); +// } + +// TYPED_TEST(k2_tree_test, serialize_test) +// { +// vector> mat({{1, 0, 0, 0, 1}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 0, 1}}); + +// auto tree = TypeParam(mat); +// k2_tree_test_nm::check_serialize_load(tree); + +// mat = vector>({{0}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_serialize_load(tree); + +// tree = TypeParam(); +// k2_tree_test_nm::check_serialize_load(tree); + +// mat = vector>({{0, 0}, +// {0, 0}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_serialize_load(tree); + +// mat = vector>({{1, 1}, +// {1, 1}}); +// tree = TypeParam(mat); +// k2_tree_test_nm::check_serialize_load(tree); +// } + +// TYPED_TEST_CASE(k2_tree_test_marked, Implementations_bit_vector); +// TYPED_TEST(k2_tree_test_marked, marked_edges) +// { +// vector> mat({{1, 0, 0, 0, 1}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 1, 0}, +// {0, 0, 0, 0, 0}, +// {0, 0, 1, 0, 1}}); + +// auto tree = TypeParam(mat); + +// ASSERT_EQ(tree.get_marked_edges(), 0); +// ASSERT_EQ(tree.get_number_edges(), 6); +// ASSERT_TRUE(tree.erase(0, 0)); +// ASSERT_EQ(tree.get_marked_edges(), 1); +// ASSERT_EQ(tree.get_number_edges(), 5); + +// ASSERT_TRUE(tree.erase(0, 4)); +// ASSERT_EQ(tree.get_marked_edges(), 2); +// ASSERT_EQ(tree.get_number_edges(), 4); + +// ASSERT_FALSE(tree.erase(0, 4)); +// ASSERT_EQ(tree.get_marked_edges(), 2); +// ASSERT_EQ(tree.get_number_edges(), 4); + +// ASSERT_FALSE(tree.erase(1, 2)); +// ASSERT_EQ(tree.get_marked_edges(), 2); +// ASSERT_EQ(tree.get_number_edges(), 4); +// } } // namespace From c13519a055bdcfd14ece4b2dfea23123b1dc3c84 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 23 Apr 2020 00:37:29 +0100 Subject: [PATCH 11/57] remove print --- include/sdsl/k2_tree.hpp | 19 +++++++++---------- test/k2_tree_test.cpp | 6 +++--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 65e860fae..2f87a7e21 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -871,18 +871,14 @@ class k2_tree if (curr_node < size) { for (; curr_row < k; curr_row++) - { + { neigh = size; _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh); if (neigh < size) - { - std::cout << "return: (" << curr_node << "," << neigh << ")" << std::endl; return edge(curr_node, neigh); - } } if (curr_row >= k) curr_row = 0; curr_node++; - std::cout << "current node: " << curr_node << std::endl; curr_neigh = k * std::floor(curr_node / static_cast(_n)); curr_col = 0; return _find_next(); @@ -896,7 +892,6 @@ class k2_tree { // Last level if (k_l[level - k_t.size()] == 1) { - std::cout << "row: " << row << " col: " << col << std::endl; neigh = col; return false; } @@ -906,13 +901,17 @@ class k2_tree { curr_neigh = k_t_rank(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); - while(curr_col < k) { - if(_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) { + while (curr_col < k) + { + if (_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) + { curr_col++; - } else + } + else break; } - if(curr_col < k) curr_col = 0; + if (curr_col < k) + curr_col = 0; } // did not found return true; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 73b7fe024..81a9ca6ff 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -276,10 +276,10 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) TYPED_TEST(k2_tree_test_k_2, edge_iterator) { - vector> mat({{1, 1, 0, 0}, + vector> mat({{0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 0}}); + {0, 0, 0, 1}}); TypeParam tree(mat); std::tuple edge = *tree.edge_begin(); cout << "x: " << std::get<0>(edge) << " y: " << std::get<1>(edge) << endl; From 24952d63265ee6cda0906889556b762182c5b2b4 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 23 Apr 2020 23:50:47 +0100 Subject: [PATCH 12/57] assignment operator --- include/sdsl/k2_tree.hpp | 113 ++------------------- include/sdsl/k2_tree_iterator.hpp | 157 ++++++++++++++++++++++++++++++ test/k2_tree_test.cpp | 32 +++--- 3 files changed, 181 insertions(+), 121 deletions(-) create mode 100644 include/sdsl/k2_tree_iterator.hpp diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 2f87a7e21..26285ac59 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -26,9 +26,9 @@ #include #include #include -#include #include "sdsl/bit_vectors.hpp" #include "sdsl/k2_tree_helper.hpp" +#include "sdsl/k2_tree_iterator.hpp" #include "sdsl/int_vector_buffer.hpp" //! Namespace for the succint data structure library @@ -55,6 +55,7 @@ class k2_tree public: typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; + using iterator = edge_iterator; protected: //! Bit array to store all the bits of the tree, except those in the @@ -814,111 +815,15 @@ class k2_tree return false; } - using edge = std::tuple; - class edge_iterator + iterator edge_begin() { - public: - using value_type = edge; - using difference_type = std::ptrdiff_t; - using pointer = edge *; - using reference = edge &; - using iterator_category = std::forward_iterator_tag; - - edge_iterator(t_bv &k_t, t_bv &k_l, t_rank &k_t_rank, uint16_t &k_height) : k_t(k_t), k_l(k_l), k_t_rank(k_t_rank), k_height(k_height) - { - _initialize(); - } - edge_iterator(pointer p) : _ptr(p) {} - edge operator*() - { - return *_ptr; - } - - private: - pointer _ptr; - - // container - t_bv &k_t; - t_bv &k_l; - t_rank &k_t_rank; - uint16_t &k_height; - const size_t size = std::pow(k, k_height); - // - - // iterator state // - idx_type curr_node, curr_neigh; - unsigned curr_row, curr_col; - const size_type _n = static_cast(std::pow(k, k_height)) / k; - // - - void _initialize() - { - // if (k_l.size() == 0 && k_t.size() == 0) - // return acc; - //TODO: Take care of this edge case - curr_node = 0; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - curr_row = 0; - curr_col = 0; - - edge first = _find_next(); - _ptr = &first; - } - - edge _find_next() - { - idx_type neigh; - if (curr_node < size) - { - for (; curr_row < k; curr_row++) - { - neigh = size; - _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh); - if (neigh < size) - return edge(curr_node, neigh); - } - if (curr_row >= k) curr_row = 0; - curr_node++; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - curr_col = 0; - return _find_next(); - } - return edge(size, size); - } - - bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh) - { - if (level >= k_t.size()) - { // Last level - if (k_l[level - k_t.size()] == 1) - { - neigh = col; - return false; - } - } - - if (k_t[level] == 1) - { - curr_neigh = k_t_rank(level + 1) * std::pow(k, 2) + - k * std::floor(row / static_cast(n)); - while (curr_col < k) - { - if (_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) - { - curr_col++; - } - else - break; - } - if (curr_col < k) - curr_col = 0; - } - // did not found - return true; - } - }; + iterator first(k_t, k_l, k_t_rank, k_height); + it = first; + return it; + } - edge_iterator edge_begin() { return edge_iterator(k_t, k_l, k_t_rank, k_height); } +private: + iterator it; }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp new file mode 100644 index 000000000..62651145e --- /dev/null +++ b/include/sdsl/k2_tree_iterator.hpp @@ -0,0 +1,157 @@ +#ifndef INCLUDED_SDSL_K2_TREE_ITERATOR +#define INCLUDED_SDSL_K2_TREE_ITERATOR + +#include +#include +#include + +#include + +using namespace std; + +namespace sdsl +{ + +template +class edge_iterator +{ + using idx_type = k2_tree_ns::idx_type; + using size_type = k2_tree_ns::size_type; + using edge = std::tuple; + // using k2_tree = k2_tree; + +public: + using value_type = edge; + // using difference_type = std::ptrdiff_t; + using pointer = edge *; + using reference = edge &; + using iterator_category = std::forward_iterator_tag; + + edge_iterator() {} + edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) + { + _initialize(); + } + + edge operator*() + { + return *_ptr; + } + + edge_iterator &operator=(const edge_iterator &other) + { + if (this != &other) + { + this->k_t = other.k_t; + this->k_l = other.k_l; + this->k_t_rank = other.k_t_rank; + this->k_height = other.k_height; + + this->_ptr = other._ptr; + this->size = other.size; + this->curr_node = other.curr_node; + this->curr_neigh = other.curr_neigh; + this->curr_row = other.curr_row; + this->curr_col = other.curr_col; + this->_n = other._n; + } + return *this; + } + + ~edge_iterator() {} + +protected: + pointer _ptr; + + // container TODO: pass the tree + const t_bv *k_t; + const t_bv *k_l; + const t_rank *k_t_rank; + uint16_t k_height; + // + + // iterator state // + size_t size; + idx_type curr_node, curr_neigh; + unsigned curr_row, curr_col; + size_type _n; + // + + void _initialize() + { + // if (k_l.size() == 0 && k_t.size() == 0) + // return acc; + //TODO: Take care of this edge case + _n = static_cast(std::pow(k, k_height)) / k; + curr_node = 0; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + curr_row = 0; + curr_col = 0; + + size = std::pow(k, k_height); + edge first = _find_next(); + + _ptr = new edge(std::get<0>(first), std::get<1>(first)); + } + + edge _find_next() + { + idx_type neigh; + if (curr_node < size) + { + for (; curr_row < k; curr_row++) + { + neigh = size; + _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh); + if (neigh < size) + { + // cout << "x: " << curr_node << " y: " << neigh << endl; + return edge(curr_node, neigh); + } + } + if (curr_row >= k) + curr_row = 0; + curr_node++; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + curr_col = 0; + return _find_next(); + } + return edge(size, size); + } + + bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh) + { + if (level >= k_t->size()) + { // Last level + if ((*k_l)[level - k_t->size()] == 1) + { + neigh = col; + return false; + } + } + + if ((*k_t)[level] == 1) + { + curr_neigh = (*k_t_rank)(level + 1) * std::pow(k, 2) + + k * std::floor(row / static_cast(n)); + while (curr_col < k) + { + if (_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) + { + curr_col++; + } + else + break; + } + if (curr_col < k) + curr_col = 0; + } + // did not found + return true; + } +}; +} // namespace sdsl + +#endif \ No newline at end of file diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 81a9ca6ff..ffb8d9bee 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -15,24 +15,16 @@ using namespace k2_tree_ns; typedef int_vector<>::size_type size_type; template -class k2_tree_test_k_2 : public ::testing::Test -{ -}; +class k2_tree_test_k_2 : public ::testing::Test{}; template -class k2_tree_test_k_3 : public ::testing::Test -{ -}; +class k2_tree_test_k_3 : public ::testing::Test{}; template -class k2_tree_test : public ::testing::Test -{ -}; +class k2_tree_test : public ::testing::Test{}; template -class k2_tree_test_marked : public ::testing::Test -{ -}; +class k2_tree_test_marked : public ::testing::Test{}; using testing::Types; @@ -274,15 +266,21 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); } -TYPED_TEST(k2_tree_test_k_2, edge_iterator) +TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) { - vector> mat({{0, 0, 0, 0}, - {0, 0, 0, 0}, + vector> mat({{1, 1, 0, 0}, {0, 0, 0, 0}, + {0, 0, 1, 0}, {0, 0, 0, 1}}); TypeParam tree(mat); - std::tuple edge = *tree.edge_begin(); - cout << "x: " << std::get<0>(edge) << " y: " << std::get<1>(edge) << endl; + + auto edge_iterator = tree.edge_begin(); + ASSERT_EQ(std::get<0>(*edge_iterator), 0); + ASSERT_EQ(std::get<1>(*edge_iterator), 0); + + // edge_iterator = tree.next(); + // ASSERT_EQ(std::get<0>(*edge_iterator), 0); + // ASSERT_EQ(std::get<1>(*edge_iterator), 1); } // TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From bfd74ff1d02176055d50458613fd63440f9999a2 Mon Sep 17 00:00:00 2001 From: Joana H Date: Fri, 24 Apr 2020 01:48:32 +0100 Subject: [PATCH 13/57] increment operator --- include/sdsl/k2_tree.hpp | 7 +---- include/sdsl/k2_tree_iterator.hpp | 49 +++++++++++++++++++------------ test/k2_tree_test.cpp | 16 ++++++---- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 26285ac59..9a422097c 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -817,13 +817,8 @@ class k2_tree iterator edge_begin() { - iterator first(k_t, k_l, k_t_rank, k_height); - it = first; - return it; + return iterator(k_t, k_l, k_t_rank, k_height); } - -private: - iterator it; }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 62651145e..a17da72a6 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -59,6 +59,24 @@ class edge_iterator } return *this; } + edge_iterator &operator++() + { + curr_col++; + if(curr_col >= k) { + curr_col = 0; + curr_row++; + } + edge e = _find_next(); + _ptr = new edge(std::get<0>(e), std::get<1>(e)); + return *this; + } + + edge_iterator &operator++(int) + { + edge_iterator tmp(*this); + operator++(); + return tmp; + } ~edge_iterator() {} @@ -89,10 +107,9 @@ class edge_iterator curr_neigh = k * std::floor(curr_node / static_cast(_n)); curr_row = 0; curr_col = 0; - size = std::pow(k, k_height); - edge first = _find_next(); + edge first = _find_next(); _ptr = new edge(std::get<0>(first), std::get<1>(first)); } @@ -104,52 +121,46 @@ class edge_iterator for (; curr_row < k; curr_row++) { neigh = size; - _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh); + _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); if (neigh < size) { // cout << "x: " << curr_node << " y: " << neigh << endl; return edge(curr_node, neigh); } } - if (curr_row >= k) - curr_row = 0; + curr_row = 0; + curr_col = 0; curr_node++; curr_neigh = k * std::floor(curr_node / static_cast(_n)); - curr_col = 0; return _find_next(); } return edge(size, size); } - bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh) + unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { if (level >= k_t->size()) { // Last level if ((*k_l)[level - k_t->size()] == 1) { neigh = col; - return false; + return true; } } if ((*k_t)[level] == 1) { - curr_neigh = (*k_t_rank)(level + 1) * std::pow(k, 2) + + size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); - while (curr_col < k) - { - if (_find_next_recursive(n / k, row % n, col + n * curr_col, curr_neigh + curr_col, neigh)) + for (unsigned j = initial_j; j < k; j++) { + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) { - curr_col++; + col_state = j; + return true; } - else - break; } - if (curr_col < k) - curr_col = 0; } - // did not found - return true; + return false; } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index ffb8d9bee..9c6384aca 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -268,7 +268,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) { - vector> mat({{1, 1, 0, 0}, + vector> mat({{0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}); @@ -276,11 +276,15 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) auto edge_iterator = tree.edge_begin(); ASSERT_EQ(std::get<0>(*edge_iterator), 0); - ASSERT_EQ(std::get<1>(*edge_iterator), 0); - - // edge_iterator = tree.next(); - // ASSERT_EQ(std::get<0>(*edge_iterator), 0); - // ASSERT_EQ(std::get<1>(*edge_iterator), 1); + ASSERT_EQ(std::get<1>(*edge_iterator), 1); + + auto another_edge_iterator = edge_iterator; + ASSERT_EQ(std::get<0>(*another_edge_iterator), 0); + ASSERT_EQ(std::get<1>(*another_edge_iterator), 1); + + edge_iterator++; + ASSERT_EQ(std::get<0>(*edge_iterator), 2); + ASSERT_EQ(std::get<1>(*edge_iterator), 2); } // TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From d67a35caaea48def4981fd6141612857fa6d1889 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 25 Apr 2020 20:27:30 +0100 Subject: [PATCH 14/57] equal operator --- include/sdsl/k2_tree_iterator.hpp | 25 ++++++++++++++++++++----- test/k2_tree_test.cpp | 8 ++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index a17da72a6..e32f91a42 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -62,7 +62,8 @@ class edge_iterator edge_iterator &operator++() { curr_col++; - if(curr_col >= k) { + if (curr_col >= k) + { curr_col = 0; curr_row++; } @@ -73,10 +74,23 @@ class edge_iterator edge_iterator &operator++(int) { - edge_iterator tmp(*this); - operator++(); + edge_iterator tmp(*this); + operator++(); return tmp; } + bool operator==(const edge_iterator &rhs) const + { + idx_type rhs_x = std::get<0>(*(rhs._ptr)); + idx_type rhs_y = std::get<1>(*(rhs._ptr)); + + idx_type self_x = std::get<0>(*(this->_ptr)); + idx_type self_y = std::get<1>(*(this->_ptr)); + return rhs_x == self_x && rhs_y == self_y; + } + bool operator!=(const edge_iterator &rhs) const + { + return !(*this == rhs); + } ~edge_iterator() {} @@ -151,8 +165,9 @@ class edge_iterator if ((*k_t)[level] == 1) { size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + - k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) { + k * std::floor(row / static_cast(n)); + for (unsigned j = initial_j; j < k; j++) + { if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) { col_state = j; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 9c6384aca..e9851b53c 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -278,13 +278,21 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(std::get<0>(*edge_iterator), 0); ASSERT_EQ(std::get<1>(*edge_iterator), 1); + // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; ASSERT_EQ(std::get<0>(*another_edge_iterator), 0); ASSERT_EQ(std::get<1>(*another_edge_iterator), 1); + // OPERATOR EQUALS + ASSERT_TRUE(another_edge_iterator == edge_iterator); + + //OPERATOR INCREMENT edge_iterator++; ASSERT_EQ(std::get<0>(*edge_iterator), 2); ASSERT_EQ(std::get<1>(*edge_iterator), 2); + + // OPERATOR INEQUALS + ASSERT_TRUE(another_edge_iterator != edge_iterator); } // TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 32242a67c671a56e97d7488d332b2961490af356 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 26 Apr 2020 17:07:58 +0100 Subject: [PATCH 15/57] end iterator --- include/sdsl/k2_tree.hpp | 10 +++++- include/sdsl/k2_tree_iterator.hpp | 52 +++++++++++++++++++++++-------- test/k2_tree_test.cpp | 8 ++++- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 9a422097c..827895af6 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -72,6 +72,8 @@ class k2_tree uint16_t n_marked_edges = 0; + iterator edge_it; + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -817,7 +819,13 @@ class k2_tree iterator edge_begin() { - return iterator(k_t, k_l, k_t_rank, k_height); + edge_it = iterator(k_t, k_l, k_t_rank, k_height); + return edge_it; + } + + iterator edge_end() + { + return edge_it.end(); } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index e32f91a42..f26fbf4e5 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -24,7 +24,6 @@ class edge_iterator public: using value_type = edge; - // using difference_type = std::ptrdiff_t; using pointer = edge *; using reference = edge &; using iterator_category = std::forward_iterator_tag; @@ -80,18 +79,37 @@ class edge_iterator } bool operator==(const edge_iterator &rhs) const { - idx_type rhs_x = std::get<0>(*(rhs._ptr)); - idx_type rhs_y = std::get<1>(*(rhs._ptr)); - - idx_type self_x = std::get<0>(*(this->_ptr)); - idx_type self_y = std::get<1>(*(this->_ptr)); - return rhs_x == self_x && rhs_y == self_y; + return equal_edge(*(rhs._ptr), *(this->_ptr)); } bool operator!=(const edge_iterator &rhs) const { return !(*this == rhs); } + edge_iterator end() + { //TODO: find out about backtrack the tree + idx_type old_curr_node = curr_node; + idx_type old_curr_neigh = curr_neigh; + unsigned old_curr_row = curr_row; + unsigned old_curr_col = curr_col; + pointer old_ptr = _ptr; + + edge last_edge = edge(size, size); + edge_iterator prev = *this; + while (!equal_edge(*_ptr, last_edge)) + { + prev = *this; + operator++(); + } + + curr_node = old_curr_node; + curr_neigh = old_curr_neigh; + curr_col = old_curr_col; + curr_row = old_curr_row; + _ptr = old_ptr; + return prev; + } + ~edge_iterator() {} protected: @@ -106,9 +124,9 @@ class edge_iterator // iterator state // size_t size; + size_type _n; idx_type curr_node, curr_neigh; unsigned curr_row, curr_col; - size_type _n; // void _initialize() @@ -153,30 +171,38 @@ class edge_iterator unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { - if (level >= k_t->size()) - { // Last level + if (level >= k_t->size()) // Last level if ((*k_l)[level - k_t->size()] == 1) { neigh = col; return true; } - } if ((*k_t)[level] == 1) { size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) - { if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) { col_state = j; return true; } - } } return false; } + +private: + bool equal_edge(const edge &e1, const edge &e2) const + { + idx_type e1_x = std::get<0>(e1); + idx_type e1_y = std::get<1>(e1); + + idx_type e2_x = std::get<0>(e2); + idx_type e2_y = std::get<1>(e2); + + return e1_x == e2_x && e1_y == e2_y; + } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index e9851b53c..2d99105f3 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -271,7 +271,7 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) vector> mat({{0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, - {0, 0, 0, 1}}); + {0, 0, 1, 0}}); TypeParam tree(mat); auto edge_iterator = tree.edge_begin(); @@ -288,11 +288,17 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) //OPERATOR INCREMENT edge_iterator++; + // ++edge_iterator; // also works ASSERT_EQ(std::get<0>(*edge_iterator), 2); ASSERT_EQ(std::get<1>(*edge_iterator), 2); // OPERATOR INEQUALS ASSERT_TRUE(another_edge_iterator != edge_iterator); + + auto last = tree.edge_end(); + //find last + ASSERT_EQ(std::get<0>(*last), 3); + ASSERT_EQ(std::get<1>(*last), 2); } // TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From cb2a8f27afba93c50a4745bf30a1862260b99fd9 Mon Sep 17 00:00:00 2001 From: Joana H Date: Mon, 4 May 2020 18:23:07 +0100 Subject: [PATCH 16/57] Uncomment tests and fix iterator --- include/sdsl/k2_tree.hpp | 31 +- include/sdsl/k2_tree_iterator.hpp | 35 +- test/k2_tree_test.cpp | 794 +++++++++++++++--------------- 3 files changed, 445 insertions(+), 415 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 827895af6..3597d596c 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -55,7 +55,7 @@ class k2_tree public: typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; - using iterator = edge_iterator; + using edg_iterator = edge_iterator; protected: //! Bit array to store all the bits of the tree, except those in the @@ -72,7 +72,8 @@ class k2_tree uint16_t n_marked_edges = 0; - iterator edge_it; + edg_iterator edge_it; + edg_iterator edge_it_end; void build_from_matrix(const std::vector> &matrix) { @@ -298,6 +299,9 @@ class k2_tree k_l = bit_vector(0, 0); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it_end = edge_it.end(); } //! Constructor @@ -321,6 +325,8 @@ class k2_tree k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it_end = edge_it.end(); } //! Constructor @@ -339,6 +345,8 @@ class k2_tree assert(edges.size() > 0); build_from_edges(edges, size); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it_end = edge_it.end(); } //! Constructor @@ -380,6 +388,8 @@ class k2_tree std::tuple{buf_x[i], buf_y[i]}); build_from_edges(edges, size); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it_end = edge_it.end(); } k2_tree(k2_tree &tr) @@ -398,6 +408,8 @@ class k2_tree k_l = std::move(l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it_end = edge_it.end(); } t_bv get_t() @@ -528,6 +540,8 @@ class k2_tree k_height = std::move(tr.k_height); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + edge_it = std::move(tr.edge_it); + edge_it_end = std::move(tr.edge_it_end); } return *this; } @@ -543,6 +557,8 @@ class k2_tree k_height = tr.k_height; k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + edge_it = tr.edge_it; + edge_it_end = tr.edge_it_end; } return *this; } @@ -558,6 +574,9 @@ class k2_tree util::swap_support(k_l_rank, tr.k_l_rank, &k_l, &(tr.k_l)); std::swap(k_k, tr.k_k); std::swap(k_height, tr.k_height); + std::swap(tr.edge_it); + std::swap(tr.edge_it_end); + } } @@ -817,15 +836,15 @@ class k2_tree return false; } - iterator edge_begin() + edg_iterator edge_begin() { - edge_it = iterator(k_t, k_l, k_t_rank, k_height); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); return edge_it; } - iterator edge_end() + edg_iterator edge_end() { - return edge_it.end(); + return edge_it_end; } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index f26fbf4e5..9cac2a83c 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -34,6 +34,7 @@ class edge_iterator _initialize(); } + //TODO: Change edge to value_type edge operator*() { return *_ptr; @@ -70,12 +71,12 @@ class edge_iterator _ptr = new edge(std::get<0>(e), std::get<1>(e)); return *this; } - edge_iterator &operator++(int) { - edge_iterator tmp(*this); + edge_iterator *tmp; + tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); operator++(); - return tmp; + return *tmp; } bool operator==(const edge_iterator &rhs) const { @@ -88,6 +89,10 @@ class edge_iterator edge_iterator end() { //TODO: find out about backtrack the tree + + if(k_l->size() == 0) { + return *this; + } idx_type old_curr_node = curr_node; idx_type old_curr_neigh = curr_neigh; unsigned old_curr_row = curr_row; @@ -115,7 +120,7 @@ class edge_iterator protected: pointer _ptr; - // container TODO: pass the tree + // container TODO: pass the tree (?) const t_bv *k_t; const t_bv *k_l; const t_rank *k_t_rank; @@ -129,20 +134,20 @@ class edge_iterator unsigned curr_row, curr_col; // - void _initialize() + void + _initialize() { - // if (k_l.size() == 0 && k_t.size() == 0) - // return acc; - //TODO: Take care of this edge case _n = static_cast(std::pow(k, k_height)) / k; curr_node = 0; curr_neigh = k * std::floor(curr_node / static_cast(_n)); curr_row = 0; curr_col = 0; size = std::pow(k, k_height); - - edge first = _find_next(); - _ptr = new edge(std::get<0>(first), std::get<1>(first)); + + if (k_l->size() > 0) { + edge first = _find_next(); + _ptr = new edge(std::get<0>(first), std::get<1>(first)); + } } edge _find_next() @@ -171,14 +176,18 @@ class edge_iterator unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { - if (level >= k_t->size()) // Last level + + if (level >= k_t->size()) // Last level + { if ((*k_l)[level - k_t->size()] == 1) { neigh = col; return true; } + return false; + } - if ((*k_t)[level] == 1) + if ((*k_t)[level] == 1 && n > 0) { size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 2d99105f3..14bfcd0df 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -245,6 +245,7 @@ TYPED_TEST(k2_tree_test_k_2, empty_union_operation) k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); unionTree = tree_B.unionOp(tree_A); + k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); unionTree = tree_B.unionOp(tree_B); @@ -268,6 +269,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) { + //forward iterator vector> mat({{0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, @@ -301,187 +303,187 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(std::get<1>(*last), 2); } -// TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); +TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); -// TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) -// { -// vector> mat({{1, 1, 0, 0, 1}, -// {0, 1, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {1, 1, 0, 1, 0}, -// {0, 0, 1, 0, 0}}); - -// TypeParam tree(mat); - -// cout << "ALGORIOTHM" << endl; -// cout << all_of(tree.get_l().begin(), tree.get_l().end(), [](int i) { return i % 2 == 0; }) << endl; - -// vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; -// vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, -// 0, 1, 0, 0, 0, 0, 1, 0, 0, -// 1, 1, 0, 0, 0, 1, 0, 0, 0, -// 1, 0, 0, 0, 0, 0, 0, 0, 0}; -// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - -// mat = vector>({{1, 1, 1, 0}, -// {1, 0, 0, 0}, -// {0, 0, 0, 0}, -// {1, 1, 0, 0}}); - -// tree = TypeParam(mat); -// expected_t = {1, 0, 0, 1, 0, 0, 0, 0, 0}; -// expected_l = {1, 1, 1, 1, 0, 0, 0, 0, 0, -// 1, 1, 0, 0, 0, 0, 0, 0, 0}; -// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - -// mat = vector>({{0, 0, 0}, -// {0, 0, 0}, -// {0, 0, 0}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_t_l(tree, {}, {}); - -// // Size is minor than k: -// mat = vector>({{0}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_t_l(tree, {}, {}); - -// mat = vector>({{1}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - -// mat = vector>({{1, 0}, -// {0, 1}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0, 0}); - -// // Size is a power of k: -// mat = vector>({{0, 0, 1, 0, 0, 0, 0, 0, 0}, -// {1, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 1, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 1, 0, 0, 0, 0, 0, 0}}); -// tree = TypeParam(mat); -// expected_t = {1, 0, 0, 0, 0, 0, 1, 0, 0}; -// expected_l = {0, 0, 1, 1, 0, 0, 0, 1, 0, -// 0, 0, 0, 0, 0, 0, 0, 0, 1}; -// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); - -// mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, -// {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, -// {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); -// tree = TypeParam(mat); -// expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0, -// 1, 1, 0, 0, 0, 0, 0, 0, 1, -// 0, 0, 0, 0, 0, 0, 1, 0, 0, -// 0, 0, 1, 0, 0, 0, 0, 0, 0, -// 1, 0, 0, 0, 0, 0, 0, 0, 0}; - -// expected_l = {0, 1, 0, 0, 0, 1, 0, 0, 0, -// 0, 0, 0, 1, 1, 0, 0, 0, 0, -// 0, 0, 0, 1, 0, 0, 1, 0, 0, -// 0, 0, 0, 0, 0, 0, 1, 0, 0, -// 1, 0, 1, 1, 0, 0, 0, 0, 0, -// 0, 1, 0, 1, 0, 0, 0, 0, 0}; -// k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); -// } +TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) +{ + vector> mat({{1, 1, 0, 0, 1}, + {0, 1, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {1, 1, 0, 1, 0}, + {0, 0, 1, 0, 0}}); -// TYPED_TEST(k2_tree_test_k_3, build_from_edges_array) -// { -// typedef std::tuple -// t_tuple; -// vector> -// e; + TypeParam tree(mat); -// e.push_back(t_tuple{1, 2}); -// TypeParam tree(e, 4); + // cout << "ALGORIOTHM" << endl; + // cout << all_of(tree.get_l().begin(), tree.get_l().end(), [](int i) { return i % 2 == 0; }) << endl; -// k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 0, 0, 0, 0, 0, 0}, -// {0, 0, 0, 0, 0, 1, 0, 0, 0}); + vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; + vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0}; + k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); -// tree = TypeParam(e, 3); -// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + mat = vector>({{1, 1, 1, 0}, + {1, 0, 0, 0}, + {0, 0, 0, 0}, + {1, 1, 0, 0}}); -// e.push_back(t_tuple{1, 2}); -// tree = TypeParam(e, 3); -// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + tree = TypeParam(mat); + expected_t = {1, 0, 0, 1, 0, 0, 0, 0, 0}; + expected_l = {1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0}; + k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); -// e.clear(); -// e.push_back(t_tuple{0, 0}); -// tree = TypeParam(e, 1); -// k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); + mat = vector>({{0, 0, 0}, + {0, 0, 0}, + {0, 0, 0}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_t_l(tree, {}, {}); -// e.push_back(t_tuple{0, 1}); -// e.push_back(t_tuple{1, 0}); -// e.push_back(t_tuple{1, 1}); -// tree = TypeParam(e, 2); -// k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 0, 1, 1, 0, 0, 0, 0}); + // Size is minor than k: + mat = vector>({{0}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_t_l(tree, {}, {}); -// e.clear(); -// e.push_back(t_tuple{2, 2}); -// tree = TypeParam(e, 3); -// k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 0, 0, 0, 1}); -// } + mat = vector>({{1}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); -// TYPED_TEST(k2_tree_test_k_3, union_operation_test) -// { -// vector> mat({{1, 1, 0, 0}, -// {0, 1, 0, 0}, -// {0, 0, 1, 1}, -// {0, 0, 1, 0}}); + mat = vector>({{1, 0}, + {0, 1}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 1, 0, 0, 0, 0}); + + // Size is a power of k: + mat = vector>({{0, 0, 1, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0}}); + tree = TypeParam(mat); + expected_t = {1, 0, 0, 0, 0, 0, 1, 0, 0}; + expected_l = {0, 0, 1, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1}; + k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); -// TypeParam tree_A(mat); + mat = vector>({{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}}); + tree = TypeParam(mat); + expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0}; + + expected_l = {0, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 0, 0, 0, 0, 0}; + k2_tree_test_nm::check_t_l(tree, expected_t, expected_l); +} + +TYPED_TEST(k2_tree_test_k_3, build_from_edges_array) +{ + typedef std::tuple + t_tuple; + vector> + e; -// mat = vector>({{0, 0, 0, 0}, -// {0, 0, 0, 0}, -// {0, 0, 0, 0}, -// {0, 0, 0, 1}}); -// TypeParam tree_B(mat); + e.push_back(t_tuple{1, 2}); + TypeParam tree(e, 4); -// TypeParam unionTree = tree_A.unionOp(tree_B); -// k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); -// } + k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0}); -// TYPED_TEST(k2_tree_test_k_3, empty_union_operation) -// { -// vector> mat({{1, 1, 0, 0, 1}, -// {0, 1, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {1, 1, 0, 1, 0}, -// {0, 0, 1, 0, 0}}); - -// vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; -// vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, -// 0, 1, 0, 0, 0, 0, 1, 0, 0, -// 1, 1, 0, 0, 0, 1, 0, 0, 0, -// 1, 0, 0, 0, 0, 0, 0, 0, 0}; -// TypeParam tree_A(mat); -// TypeParam tree_B; - -// TypeParam unionTree = tree_A.unionOp(tree_B); -// k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); - -// unionTree = tree_B.unionOp(tree_A); -// k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); - -// unionTree = tree_B.unionOp(tree_B); -// k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); -// } + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + + e.push_back(t_tuple{1, 2}); + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 1, 0, 0, 0}); + + e.clear(); + e.push_back(t_tuple{0, 0}); + tree = TypeParam(e, 1); + k2_tree_test_nm::check_t_l(tree, {}, {1, 0, 0, 0, 0, 0, 0, 0, 0}); + + e.push_back(t_tuple{0, 1}); + e.push_back(t_tuple{1, 0}); + e.push_back(t_tuple{1, 1}); + tree = TypeParam(e, 2); + k2_tree_test_nm::check_t_l(tree, {}, {1, 1, 0, 1, 1, 0, 0, 0, 0}); + + e.clear(); + e.push_back(t_tuple{2, 2}); + tree = TypeParam(e, 3); + k2_tree_test_nm::check_t_l(tree, {}, {0, 0, 0, 0, 0, 0, 0, 0, 1}); +} + +TYPED_TEST(k2_tree_test_k_3, union_operation_test) +{ + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); + + TypeParam tree_A(mat); + + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 1}}); + TypeParam tree_B(mat); -// TYPED_TEST_CASE(k2_tree_test, Implementations); + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); +} + +TYPED_TEST(k2_tree_test_k_3, empty_union_operation) +{ + vector> mat({{1, 1, 0, 0, 1}, + {0, 1, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {1, 1, 0, 1, 0}, + {0, 0, 1, 0, 0}}); + + vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; + vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0}; + TypeParam tree_A(mat); + TypeParam tree_B; + + TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + + unionTree = tree_B.unionOp(tree_A); + k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + + unionTree = tree_B.unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); +} + +TYPED_TEST_CASE(k2_tree_test, Implementations); // TYPED_TEST(k2_tree_test, edges_array_exhaustive) // { @@ -529,241 +531,241 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) // ASSERT_EQ(0u, tree.neigh(0)[0]); // } -// TYPED_TEST(k2_tree_test, neighbors_test) -// { -// vector> mat({{1, 1, 0, 0}, -// {0, 1, 0, 0}, -// {0, 0, 1, 1}, -// {0, 0, 1, 0}}); - -// TypeParam tree(mat); -// auto neigh_0 = tree.neigh(0); -// vector expected_neigh_0({0, 1}); -// ASSERT_EQ(expected_neigh_0.size(), neigh_0.size()); -// for (unsigned i = 0; i < neigh_0.size(); i++) -// ASSERT_EQ(expected_neigh_0[i], neigh_0[i]); - -// auto neigh_3 = tree.neigh(3); -// vector expected_neigh_3({2}); -// ASSERT_EQ(expected_neigh_3.size(), neigh_3.size()); -// for (unsigned i = 0; i < neigh_3.size(); i++) -// ASSERT_EQ(expected_neigh_3[i], neigh_3[i]); - -// mat = vector>({{1}}); -// tree = TypeParam(mat); -// neigh_0 = tree.neigh(0); -// ASSERT_EQ(0u, neigh_0[0]); -// ASSERT_EQ(1u, neigh_0.size()); - -// mat = vector>({{0, 0, 0}, -// {1, 0, 1}, -// {0, 1, 1}}); -// tree = TypeParam(mat); -// neigh_0 = tree.neigh(0); -// ASSERT_EQ(0u, neigh_0.size()); - -// auto neigh_1 = tree.neigh(1); -// auto expected_neigh_1 = vector({0, 2}); -// ASSERT_EQ(expected_neigh_1.size(), neigh_1.size()); -// for (unsigned i = 0; i < neigh_1.size(); i++) -// ASSERT_EQ(expected_neigh_1[i], neigh_1[i]); - -// mat = vector>({{0, 0}, -// {0, 0}}); -// tree = TypeParam(mat); -// neigh_0 = tree.neigh(0); -// ASSERT_EQ(0u, neigh_0.size()); -// } +TYPED_TEST(k2_tree_test, neighbors_test) +{ + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); -// TYPED_TEST(k2_tree_test, reverse_neighbors_test) -// { -// vector> mat({{1, 0, 0, 0, 1}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 0, 1}}); - -// auto tree = TypeParam(mat); -// auto r_neigh_0 = tree.reverse_neigh(0); -// auto expected_r_neigh_0 = vector({0}); -// auto r_neigh_1 = tree.reverse_neigh(1); -// auto r_neigh_2 = tree.reverse_neigh(2); -// auto expected_r_neigh_2 = vector({2, 4}); -// ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); -// ASSERT_EQ(0u, r_neigh_1.size()); -// ASSERT_EQ(expected_r_neigh_2.size(), r_neigh_2.size()); - -// for (unsigned i = 0; i < r_neigh_0.size(); i++) -// ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); - -// for (unsigned i = 0; i < r_neigh_2.size(); i++) -// ASSERT_EQ(expected_r_neigh_2[i], r_neigh_2[i]); - -// mat = vector>({{0, 0}, -// {0, 0}}); -// tree = TypeParam(mat); -// r_neigh_0 = tree.reverse_neigh(0); -// r_neigh_1 = tree.reverse_neigh(1); -// ASSERT_EQ(0u, r_neigh_0.size()); -// ASSERT_EQ(0u, r_neigh_1.size()); - -// mat = vector>({{0, 1}, -// {1, 0}}); -// tree = TypeParam(mat); -// r_neigh_0 = tree.reverse_neigh(0); -// expected_r_neigh_0 = vector({1}); -// r_neigh_1 = tree.reverse_neigh(1); -// auto expected_r_neigh_1 = vector({0}); - -// ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); -// ASSERT_EQ(expected_r_neigh_1.size(), r_neigh_1.size()); -// for (unsigned i = 0; i < r_neigh_0.size(); i++) -// ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); - -// for (unsigned i = 0; i < r_neigh_1.size(); i++) -// ASSERT_EQ(expected_r_neigh_1[i], r_neigh_1[i]); -// } + TypeParam tree(mat); + auto neigh_0 = tree.neigh(0); + vector expected_neigh_0({0, 1}); + ASSERT_EQ(expected_neigh_0.size(), neigh_0.size()); + for (unsigned i = 0; i < neigh_0.size(); i++) + ASSERT_EQ(expected_neigh_0[i], neigh_0[i]); + + auto neigh_3 = tree.neigh(3); + vector expected_neigh_3({2}); + ASSERT_EQ(expected_neigh_3.size(), neigh_3.size()); + for (unsigned i = 0; i < neigh_3.size(); i++) + ASSERT_EQ(expected_neigh_3[i], neigh_3[i]); -// TYPED_TEST(k2_tree_test, range_test) -// { -// static const vector> mat{ -// // 0 1 2 3 4 5 6 7 8 9 10 -// /* 0*/ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// /* 1*/ {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, -// /* 2*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// /* 3*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - -// /* 4*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// /* 5*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// /* 6*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -// /* 7*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, - -// /* 8*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, -// /* 9*/ {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, -// /*10*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, -// }; -// TypeParam tree(mat); - -// auto result = tree.range(7, 9, 5, 9); -// static const decltype(result) expected{ -// {7, 6}, -// {8, 6}, -// {8, 9}, -// {9, 6}, -// {9, 8}}; -// sort(result.begin(), result.end()); -// ASSERT_EQ(expected, result); - -// auto all = tree.range(0, 10, 0, 10); -// static const decltype(all) expectedAll{ -// {0, 1}, -// {1, 2}, -// {1, 3}, -// {1, 4}, -// {7, 6}, -// {8, 6}, -// {8, 9}, -// {9, 6}, -// {9, 8}, -// {9, 10}, -// {10, 6}, -// {10, 9}}; -// sort(all.begin(), all.end()); -// ASSERT_EQ(expectedAll, all); - -// auto single = tree.range(1, 1, 3, 3); -// static const decltype(single) expectedSingle{ -// {1, 3}}; -// ASSERT_EQ(expectedSingle, single); - -// auto empty = tree.range(0, 6, 5, 10); -// static const decltype(empty) expectedEmpty{}; -// ASSERT_EQ(expectedEmpty, empty); -// } + mat = vector>({{1}}); + tree = TypeParam(mat); + neigh_0 = tree.neigh(0); + ASSERT_EQ(0u, neigh_0[0]); + ASSERT_EQ(1u, neigh_0.size()); -// TYPED_TEST(k2_tree_test, adj_test) -// { -// vector> mat({{1, 0, 0, 0, 1}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 0, 1}}); - -// auto tree = TypeParam(mat); -// ASSERT_TRUE(tree.adj(0, 0)); -// ASSERT_TRUE(tree.adj(0, 4)); -// ASSERT_FALSE(tree.adj(4, 0)); -// ASSERT_TRUE(tree.adj(4, 4)); -// ASSERT_FALSE(tree.adj(1, 1)); -// ASSERT_TRUE(tree.adj(2, 2)); -// ASSERT_TRUE(tree.adj(2, 3)); - -// mat = vector>({{0}}); -// tree = TypeParam(mat); -// ASSERT_FALSE(tree.adj(0, 0)); -// mat = vector>({{1}}); -// tree = TypeParam(mat); -// ASSERT_TRUE(tree.adj(0, 0)); -// } + mat = vector>({{0, 0, 0}, + {1, 0, 1}, + {0, 1, 1}}); + tree = TypeParam(mat); + neigh_0 = tree.neigh(0); + ASSERT_EQ(0u, neigh_0.size()); -// TYPED_TEST(k2_tree_test, serialize_test) -// { -// vector> mat({{1, 0, 0, 0, 1}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 0, 1}}); - -// auto tree = TypeParam(mat); -// k2_tree_test_nm::check_serialize_load(tree); - -// mat = vector>({{0}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_serialize_load(tree); - -// tree = TypeParam(); -// k2_tree_test_nm::check_serialize_load(tree); - -// mat = vector>({{0, 0}, -// {0, 0}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_serialize_load(tree); - -// mat = vector>({{1, 1}, -// {1, 1}}); -// tree = TypeParam(mat); -// k2_tree_test_nm::check_serialize_load(tree); -// } + auto neigh_1 = tree.neigh(1); + auto expected_neigh_1 = vector({0, 2}); + ASSERT_EQ(expected_neigh_1.size(), neigh_1.size()); + for (unsigned i = 0; i < neigh_1.size(); i++) + ASSERT_EQ(expected_neigh_1[i], neigh_1[i]); -// TYPED_TEST_CASE(k2_tree_test_marked, Implementations_bit_vector); -// TYPED_TEST(k2_tree_test_marked, marked_edges) -// { -// vector> mat({{1, 0, 0, 0, 1}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 1, 0}, -// {0, 0, 0, 0, 0}, -// {0, 0, 1, 0, 1}}); - -// auto tree = TypeParam(mat); - -// ASSERT_EQ(tree.get_marked_edges(), 0); -// ASSERT_EQ(tree.get_number_edges(), 6); -// ASSERT_TRUE(tree.erase(0, 0)); -// ASSERT_EQ(tree.get_marked_edges(), 1); -// ASSERT_EQ(tree.get_number_edges(), 5); - -// ASSERT_TRUE(tree.erase(0, 4)); -// ASSERT_EQ(tree.get_marked_edges(), 2); -// ASSERT_EQ(tree.get_number_edges(), 4); - -// ASSERT_FALSE(tree.erase(0, 4)); -// ASSERT_EQ(tree.get_marked_edges(), 2); -// ASSERT_EQ(tree.get_number_edges(), 4); - -// ASSERT_FALSE(tree.erase(1, 2)); -// ASSERT_EQ(tree.get_marked_edges(), 2); -// ASSERT_EQ(tree.get_number_edges(), 4); -// } + mat = vector>({{0, 0}, + {0, 0}}); + tree = TypeParam(mat); + neigh_0 = tree.neigh(0); + ASSERT_EQ(0u, neigh_0.size()); +} + +TYPED_TEST(k2_tree_test, reverse_neighbors_test) +{ + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + auto r_neigh_0 = tree.reverse_neigh(0); + auto expected_r_neigh_0 = vector({0}); + auto r_neigh_1 = tree.reverse_neigh(1); + auto r_neigh_2 = tree.reverse_neigh(2); + auto expected_r_neigh_2 = vector({2, 4}); + ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); + ASSERT_EQ(0u, r_neigh_1.size()); + ASSERT_EQ(expected_r_neigh_2.size(), r_neigh_2.size()); + + for (unsigned i = 0; i < r_neigh_0.size(); i++) + ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); + + for (unsigned i = 0; i < r_neigh_2.size(); i++) + ASSERT_EQ(expected_r_neigh_2[i], r_neigh_2[i]); + + mat = vector>({{0, 0}, + {0, 0}}); + tree = TypeParam(mat); + r_neigh_0 = tree.reverse_neigh(0); + r_neigh_1 = tree.reverse_neigh(1); + ASSERT_EQ(0u, r_neigh_0.size()); + ASSERT_EQ(0u, r_neigh_1.size()); + + mat = vector>({{0, 1}, + {1, 0}}); + tree = TypeParam(mat); + r_neigh_0 = tree.reverse_neigh(0); + expected_r_neigh_0 = vector({1}); + r_neigh_1 = tree.reverse_neigh(1); + auto expected_r_neigh_1 = vector({0}); + + ASSERT_EQ(expected_r_neigh_0.size(), r_neigh_0.size()); + ASSERT_EQ(expected_r_neigh_1.size(), r_neigh_1.size()); + for (unsigned i = 0; i < r_neigh_0.size(); i++) + ASSERT_EQ(expected_r_neigh_0[i], r_neigh_0[i]); + + for (unsigned i = 0; i < r_neigh_1.size(); i++) + ASSERT_EQ(expected_r_neigh_1[i], r_neigh_1[i]); +} + +TYPED_TEST(k2_tree_test, range_test) +{ + static const vector> mat{ + // 0 1 2 3 4 5 6 7 8 9 10 + /* 0*/ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 1*/ {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + /* 2*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 3*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + /* 4*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 5*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 6*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* 7*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + + /* 8*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + /* 9*/ {0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, + /*10*/ {0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + }; + TypeParam tree(mat); + + auto result = tree.range(7, 9, 5, 9); + static const decltype(result) expected{ + {7, 6}, + {8, 6}, + {8, 9}, + {9, 6}, + {9, 8}}; + sort(result.begin(), result.end()); + ASSERT_EQ(expected, result); + + auto all = tree.range(0, 10, 0, 10); + static const decltype(all) expectedAll{ + {0, 1}, + {1, 2}, + {1, 3}, + {1, 4}, + {7, 6}, + {8, 6}, + {8, 9}, + {9, 6}, + {9, 8}, + {9, 10}, + {10, 6}, + {10, 9}}; + sort(all.begin(), all.end()); + ASSERT_EQ(expectedAll, all); + + auto single = tree.range(1, 1, 3, 3); + static const decltype(single) expectedSingle{ + {1, 3}}; + ASSERT_EQ(expectedSingle, single); + + auto empty = tree.range(0, 6, 5, 10); + static const decltype(empty) expectedEmpty{}; + ASSERT_EQ(expectedEmpty, empty); +} + +TYPED_TEST(k2_tree_test, adj_test) +{ + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + ASSERT_TRUE(tree.adj(0, 0)); + ASSERT_TRUE(tree.adj(0, 4)); + ASSERT_FALSE(tree.adj(4, 0)); + ASSERT_TRUE(tree.adj(4, 4)); + ASSERT_FALSE(tree.adj(1, 1)); + ASSERT_TRUE(tree.adj(2, 2)); + ASSERT_TRUE(tree.adj(2, 3)); + + mat = vector>({{0}}); + tree = TypeParam(mat); + ASSERT_FALSE(tree.adj(0, 0)); + mat = vector>({{1}}); + tree = TypeParam(mat); + ASSERT_TRUE(tree.adj(0, 0)); +} + +TYPED_TEST(k2_tree_test, serialize_test) +{ + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + k2_tree_test_nm::check_serialize_load(tree); + + mat = vector>({{0}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_serialize_load(tree); + + tree = TypeParam(); + k2_tree_test_nm::check_serialize_load(tree); + + mat = vector>({{0, 0}, + {0, 0}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_serialize_load(tree); + + mat = vector>({{1, 1}, + {1, 1}}); + tree = TypeParam(mat); + k2_tree_test_nm::check_serialize_load(tree); +} + +TYPED_TEST_CASE(k2_tree_test_marked, Implementations_bit_vector); +TYPED_TEST(k2_tree_test_marked, marked_edges) +{ + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + + ASSERT_EQ(tree.get_marked_edges(), 0); + ASSERT_EQ(tree.get_number_edges(), 6); + ASSERT_TRUE(tree.erase(0, 0)); + ASSERT_EQ(tree.get_marked_edges(), 1); + ASSERT_EQ(tree.get_number_edges(), 5); + + ASSERT_TRUE(tree.erase(0, 4)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); + + ASSERT_FALSE(tree.erase(0, 4)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); + + ASSERT_FALSE(tree.erase(1, 2)); + ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_number_edges(), 4); +} } // namespace From 5de076e597e8697ac9ff01cafd38b7e23151f103 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 7 May 2020 18:28:46 +0100 Subject: [PATCH 17/57] Fix end and begining in iterator --- include/sdsl/k2_tree.hpp | 6 +- include/sdsl/k2_tree_iterator.hpp | 443 +++++++++++++++++++----------- test/k2_tree_test.cpp | 119 ++++---- 3 files changed, 351 insertions(+), 217 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 3597d596c..342ed9a23 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -576,7 +576,6 @@ class k2_tree std::swap(k_height, tr.k_height); std::swap(tr.edge_it); std::swap(tr.edge_it_end); - } } @@ -844,8 +843,13 @@ class k2_tree edg_iterator edge_end() { + edge_it_end = edge_it.end(); return edge_it_end; } + + size_t size() { + return std::pow(k, k_height); + } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 9cac2a83c..4bdbcff33 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -12,207 +12,330 @@ using namespace std; namespace sdsl { -template -class edge_iterator -{ - using idx_type = k2_tree_ns::idx_type; - using size_type = k2_tree_ns::size_type; - using edge = std::tuple; - // using k2_tree = k2_tree; - -public: - using value_type = edge; - using pointer = edge *; - using reference = edge &; - using iterator_category = std::forward_iterator_tag; - - edge_iterator() {} - edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) + template + class edge_iterator { - _initialize(); - } + using idx_type = k2_tree_ns::idx_type; + using size_type = k2_tree_ns::size_type; + using edge = std::tuple; + // using k2_tree = k2_tree; - //TODO: Change edge to value_type - edge operator*() - { - return *_ptr; - } + public: + using value_type = edge; + using pointer = edge *; + using reference = edge &; + using iterator_category = std::forward_iterator_tag; - edge_iterator &operator=(const edge_iterator &other) - { - if (this != &other) + edge_iterator() {} + edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) { - this->k_t = other.k_t; - this->k_l = other.k_l; - this->k_t_rank = other.k_t_rank; - this->k_height = other.k_height; - - this->_ptr = other._ptr; - this->size = other.size; - this->curr_node = other.curr_node; - this->curr_neigh = other.curr_neigh; - this->curr_row = other.curr_row; - this->curr_col = other.curr_col; - this->_n = other._n; - } - return *this; - } - edge_iterator &operator++() - { - curr_col++; - if (curr_col >= k) + _initialize(); + } + + //TODO: Change edge to value_type + edge operator*() { - curr_col = 0; - curr_row++; + return *_ptr; } - edge e = _find_next(); - _ptr = new edge(std::get<0>(e), std::get<1>(e)); - return *this; - } - edge_iterator &operator++(int) - { - edge_iterator *tmp; - tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); - operator++(); - return *tmp; - } - bool operator==(const edge_iterator &rhs) const - { - return equal_edge(*(rhs._ptr), *(this->_ptr)); - } - bool operator!=(const edge_iterator &rhs) const - { - return !(*this == rhs); - } - edge_iterator end() - { //TODO: find out about backtrack the tree + edge_iterator &operator=(const edge_iterator &other) + { + if (this != &other) + { + this->k_t = other.k_t; + this->k_l = other.k_l; + this->k_t_rank = other.k_t_rank; + this->k_height = other.k_height; - if(k_l->size() == 0) { + this->_ptr = other._ptr; + this->size = other.size; + this->_n = other._n; + this->curr_node = other.curr_node; + this->curr_neigh = other.curr_neigh; + this->curr_row = other.curr_row; + this->curr_col = other.curr_col; + } return *this; } - idx_type old_curr_node = curr_node; - idx_type old_curr_neigh = curr_neigh; - unsigned old_curr_row = curr_row; - unsigned old_curr_col = curr_col; - pointer old_ptr = _ptr; - edge last_edge = edge(size, size); - edge_iterator prev = *this; - while (!equal_edge(*_ptr, last_edge)) + bool operator==(const edge_iterator &rhs) const + { + return equal_edge(*(rhs._ptr), *(this->_ptr)); + } + bool operator!=(const edge_iterator &rhs) const + { + return !(*this == rhs); + } + + + friend void swap(edge_iterator &rhs, edge_iterator &lhs) + { + if (lhs != rhs) + { + std::swap(lhs._ptr, rhs._ptr); + std::swap(lhs.k_t, rhs.k_t); + std::swap(lhs.k_l, rhs.k_l); + std::swap(lhs.k_t_rank, rhs.k_t_rank); + std::swap(lhs.size, rhs.size); + std::swap(lhs.curr_node, rhs.curr_node); + std::swap(lhs.curr_neigh, rhs.curr_neigh); + std::swap(lhs.curr_row, rhs.curr_row); + std::swap(lhs.curr_col, rhs.curr_col); + } + } + + edge_iterator &operator++() + { + curr_col++; + if (curr_col >= k) + { + curr_col = 0; + curr_row++; + } + edge e = _find_next(); + _ptr = new edge(std::get<0>(e), std::get<1>(e)); + return *this; + } + edge_iterator &operator++(int) { - prev = *this; + edge_iterator *tmp; + tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); operator++(); + return *tmp; } - curr_node = old_curr_node; - curr_neigh = old_curr_neigh; - curr_col = old_curr_col; - curr_row = old_curr_row; - _ptr = old_ptr; - return prev; - } + // edge_iterator &operator--() + // { + // // curr_col++; + // // if (curr_col >= k) + // // { + // // curr_col = 0; + // // curr_row++; + // // } + // // edge e = _find_next(); + // // _ptr = new edge(std::get<0>(e), std::get<1>(e)); + // // return *this; + // } + // edge_iterator &operator--(int) + // { + // edge_iterator *tmp; + // tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); + // operator--(); + // return *tmp; + // } - ~edge_iterator() {} + ~edge_iterator() {} -protected: - pointer _ptr; + edge_iterator end() + { //TODO: find out about backtrack the tree - // container TODO: pass the tree (?) - const t_bv *k_t; - const t_bv *k_l; - const t_rank *k_t_rank; - uint16_t k_height; - // + // if(k_l->size() == 0) { + // return *this; + // } + // idx_type old_curr_node = curr_node; + // idx_type old_curr_neigh = curr_neigh; + // unsigned old_curr_row = curr_row; + // unsigned old_curr_col = curr_col; + // pointer old_ptr = _ptr; - // iterator state // - size_t size; - size_type _n; - idx_type curr_node, curr_neigh; - unsigned curr_row, curr_col; - // + // edge last_edge = edge(size, size); + // edge_iterator prev = *this; + // while (!equal_edge(*_ptr, last_edge)) + // { + // prev = *this; + // operator++(); + // } - void - _initialize() - { - _n = static_cast(std::pow(k, k_height)) / k; - curr_node = 0; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - curr_row = 0; - curr_col = 0; - size = std::pow(k, k_height); - - if (k_l->size() > 0) { - edge first = _find_next(); - _ptr = new edge(std::get<0>(first), std::get<1>(first)); - } - } - - edge _find_next() - { - idx_type neigh; - if (curr_node < size) + // curr_node = old_curr_node; + // curr_neigh = old_curr_neigh; + // curr_col = old_curr_col; + // curr_row = old_curr_row; + // _ptr = old_ptr; + edge_iterator it; + it._ptr = new edge(size, size); //end node + return it; + } + friend ostream &operator<<(ostream &os, const edge_iterator &edg) { + os << " ==== ktree Edge Iterator ==== " << endl; + edge e = *edg._ptr; + os << " ptr (" << get<0>(e) << ", " << get<1>(e) << ")" << endl; + os << " CONTAINER " << endl; + os << " k_t "; + for(uint i = 0; i < edg.k_t->size(); i++) + os << (*edg.k_t)[i]; + os << endl; + os << " k_l "; + for(uint i = 0; i < edg.k_l->size(); i++) + os << (*edg.k_l)[i]; + os << endl; + os << " k_height " << edg.k_height << endl; + os << " STATE " << endl; + os << " size " << edg.size << endl; + os << " _n " << edg._n << endl; + os << " curr_node " << edg.curr_node << endl; + os << " curr_neigh " << edg.curr_neigh << endl; + os << " curr_row " << edg.curr_row << endl; + os << " curr_col " << edg.curr_col << endl; + os << " ============================ " << endl; + return os; + } + + protected: + pointer _ptr; + + // container TODO: pass the tree (?) + const t_bv *k_t; + const t_bv *k_l; + const t_rank *k_t_rank; + uint16_t k_height; + // + + // iterator state // + size_t size; + size_type _n; + idx_type curr_node, curr_neigh; + unsigned curr_row, curr_col; + // + + void + _initialize() { - for (; curr_row < k; curr_row++) + _n = static_cast(std::pow(k, k_height)) / k; + curr_node = 0; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + curr_row = 0; + curr_col = 0; + size = std::pow(k, k_height); + if (k_l->size() > 0) + { + edge first = _find_next(); + first_edge = new edge(std::get<0>(first), std::get<1>(first)); + _ptr = first_edge; + } + else + { + // if its empty the begin == end + first_edge = new edge(size, size); + _ptr = new edge(size, size); //end node + } + } + + edge _find_next() + { + idx_type neigh; + if (curr_node < size) { - neigh = size; - _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); - if (neigh < size) + for (; curr_row < k; curr_row++) { - // cout << "x: " << curr_node << " y: " << neigh << endl; - return edge(curr_node, neigh); + neigh = size; + _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); + if (neigh < size) + { + // cout << "x: " << curr_node << " y: " << neigh << endl; + return edge(curr_node, neigh); + } } + curr_row = 0; + curr_col = 0; + curr_node++; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + return _find_next(); } - curr_row = 0; - curr_col = 0; - curr_node++; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - return _find_next(); + return edge(size, size); // end node } - return edge(size, size); - } - unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) - { - - if (level >= k_t->size()) // Last level + unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { - if ((*k_l)[level - k_t->size()] == 1) + if (level >= k_t->size()) // Last level { - neigh = col; - return true; + if ((*k_l)[level - k_t->size()] == 1) + { + neigh = col; + return true; + } + return false; + } + + if ((*k_t)[level] == 1 && n > 0) + { + size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + + k * std::floor(row / static_cast(n)); + for (unsigned j = initial_j; j < k; j++) + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) + { + col_state = j; + return true; + } } return false; } - if ((*k_t)[level] == 1 && n > 0) + edge _find_prev() { - size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + - k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) + idx_type neigh; + if (curr_node > 0) + { + for (; curr_row > 0; curr_row--) + { + neigh = size; + _find_prev_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); + if (neigh < size) + { + // cout << "x: " << curr_node << " y: " << neigh << endl; + return edge(curr_node, neigh); + } + } + curr_row = 0; + curr_col = 0; + curr_node--; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + return _find_prev(); + } + return edge(size, size); // end node + } + + unsigned _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) + { + if (level >= k_t->size()) // Last level + { + if ((*k_l)[level - k_t->size()] == 1) { - col_state = j; + neigh = col; return true; } + return false; + } + + if ((*k_t)[level] == 1 && n > 0) + { + size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + + k * std::floor(row / static_cast(n)); + for (unsigned j = initial_j; j > 0; j--) + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) + { + col_state = j; + return true; + } + } + return false; } - return false; - } -private: - bool equal_edge(const edge &e1, const edge &e2) const - { - idx_type e1_x = std::get<0>(e1); - idx_type e1_y = std::get<1>(e1); + private: + edge *first_edge; + + bool equal_edge(const edge &e1, const edge &e2) const + { + idx_type e1_x = std::get<0>(e1); + idx_type e1_y = std::get<1>(e1); - idx_type e2_x = std::get<0>(e2); - idx_type e2_y = std::get<1>(e2); + idx_type e2_x = std::get<0>(e2); + idx_type e2_y = std::get<1>(e2); - return e1_x == e2_x && e1_y == e2_y; - } -}; + return e1_x == e2_x && e1_y == e2_y; + } + }; } // namespace sdsl #endif \ No newline at end of file diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 14bfcd0df..3d8d21169 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -218,7 +218,6 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) // T 1 0 0 1 // L 1 1 0 1 1 1 1 0 TypeParam tree_A(mat); - mat = vector>({{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, @@ -228,6 +227,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) TypeParam tree_B(mat); TypeParam unionTree = tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); } @@ -277,30 +277,37 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) TypeParam tree(mat); auto edge_iterator = tree.edge_begin(); - ASSERT_EQ(std::get<0>(*edge_iterator), 0); - ASSERT_EQ(std::get<1>(*edge_iterator), 1); + ASSERT_EQ(std::get<0>(*edge_iterator), (size_t)0); + ASSERT_EQ(std::get<1>(*edge_iterator), (size_t)1); // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; - ASSERT_EQ(std::get<0>(*another_edge_iterator), 0); - ASSERT_EQ(std::get<1>(*another_edge_iterator), 1); + ASSERT_EQ(std::get<0>(*another_edge_iterator), (size_t) 0); + ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 1); // OPERATOR EQUALS ASSERT_TRUE(another_edge_iterator == edge_iterator); //OPERATOR INCREMENT - edge_iterator++; // ++edge_iterator; // also works - ASSERT_EQ(std::get<0>(*edge_iterator), 2); - ASSERT_EQ(std::get<1>(*edge_iterator), 2); + edge_iterator++; + ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 2); + ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); // OPERATOR INEQUALS ASSERT_TRUE(another_edge_iterator != edge_iterator); - auto last = tree.edge_end(); //find last - ASSERT_EQ(std::get<0>(*last), 3); - ASSERT_EQ(std::get<1>(*last), 2); + auto last = tree.edge_end(); + ASSERT_EQ(std::get<0>(*last), tree.size()); + ASSERT_EQ(std::get<1>(*last), tree.size()); + + //OPERATION SWAP + swap(last, another_edge_iterator); + ASSERT_EQ(std::get<0>(*last), (size_t) 0); + ASSERT_EQ(std::get<1>(*last), (size_t) 1); + ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.size()); + ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.size()); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); @@ -485,51 +492,51 @@ TYPED_TEST(k2_tree_test_k_3, empty_union_operation) TYPED_TEST_CASE(k2_tree_test, Implementations); -// TYPED_TEST(k2_tree_test, edges_array_exhaustive) -// { -// typedef std::tuple -// t_tuple; -// vector> -// e; -// e.push_back(t_tuple{5, 7}); -// e.push_back(t_tuple{1, 2}); -// e.push_back(t_tuple{3, 9}); -// e.push_back(t_tuple{2, 2}); -// e.push_back(t_tuple{3, 2}); -// e.push_back(t_tuple{7, 5}); -// e.push_back(t_tuple{1, 6}); -// e.push_back(t_tuple{4, 8}); -// e.push_back(t_tuple{4, 1}); -// e.push_back(t_tuple{5, 2}); - -// TypeParam tree(e, 10); -// auto expected_neighbors = vector>(10); -// expected_neighbors[0] = vector({}); -// expected_neighbors[1] = vector({2, 6}); -// expected_neighbors[2] = vector({2}); -// expected_neighbors[3] = vector({2, 9}); -// expected_neighbors[4] = vector({1, 8}); -// expected_neighbors[5] = vector({2, 7}); -// expected_neighbors[6] = vector({}); -// expected_neighbors[7] = vector({5}); -// expected_neighbors[8] = vector({}); -// expected_neighbors[9] = vector({}); -// for (unsigned i = 0; i < 10; i++) -// { -// auto actual_neighbors = tree.neigh(i); -// ASSERT_EQ(expected_neighbors[i].size(), actual_neighbors.size()); -// for (unsigned j = 0; i < expected_neighbors[i].size(); i++) -// ASSERT_EQ(expected_neighbors[i][j], actual_neighbors[j]); -// } - -// e.clear(); -// e.push_back(t_tuple{0, 0}); -// tree = TypeParam(e, 1); -// ASSERT_EQ(1u, tree.neigh(0).size()); -// ASSERT_EQ(0u, tree.neigh(0)[0]); -// } +TYPED_TEST(k2_tree_test, edges_array_exhaustive) +{ + typedef std::tuple + t_tuple; + vector> + e; + e.push_back(t_tuple{5, 7}); + e.push_back(t_tuple{1, 2}); + e.push_back(t_tuple{3, 9}); + e.push_back(t_tuple{2, 2}); + e.push_back(t_tuple{3, 2}); + e.push_back(t_tuple{7, 5}); + e.push_back(t_tuple{1, 6}); + e.push_back(t_tuple{4, 8}); + e.push_back(t_tuple{4, 1}); + e.push_back(t_tuple{5, 2}); + + TypeParam tree(e, 10); + auto expected_neighbors = vector>(10); + expected_neighbors[0] = vector({}); + expected_neighbors[1] = vector({2, 6}); + expected_neighbors[2] = vector({2}); + expected_neighbors[3] = vector({2, 9}); + expected_neighbors[4] = vector({1, 8}); + expected_neighbors[5] = vector({2, 7}); + expected_neighbors[6] = vector({}); + expected_neighbors[7] = vector({5}); + expected_neighbors[8] = vector({}); + expected_neighbors[9] = vector({}); + for (unsigned i = 0; i < 10; i++) + { + auto actual_neighbors = tree.neigh(i); + ASSERT_EQ(expected_neighbors[i].size(), actual_neighbors.size()); + for (unsigned j = 0; i < expected_neighbors[i].size(); i++) + ASSERT_EQ(expected_neighbors[i][j], actual_neighbors[j]); + } + + e.clear(); + e.push_back(t_tuple{0, 0}); + tree = TypeParam(e, 1); + ASSERT_EQ(1u, tree.neigh(0).size()); + ASSERT_EQ(0u, tree.neigh(0)[0]); +} TYPED_TEST(k2_tree_test, neighbors_test) { From 2618a2f3ceb95843a48ecd1be7b2ca18d318a87c Mon Sep 17 00:00:00 2001 From: Joana H Date: Fri, 8 May 2020 00:26:49 +0100 Subject: [PATCH 18/57] Add bidirectional k2_tree iterator --- include/sdsl/k2_tree_iterator.hpp | 195 ++++++++++++++++-------------- test/k2_tree_test.cpp | 16 +++ 2 files changed, 122 insertions(+), 89 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 4bdbcff33..7b04edb46 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -26,7 +26,7 @@ namespace sdsl using value_type = edge; using pointer = edge *; using reference = edge &; - using iterator_category = std::forward_iterator_tag; + using iterator_category = std::bidirectional_iterator_tag; edge_iterator() {} edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) @@ -34,8 +34,7 @@ namespace sdsl _initialize(); } - //TODO: Change edge to value_type - edge operator*() + value_type operator*() { return *_ptr; } @@ -56,6 +55,8 @@ namespace sdsl this->curr_neigh = other.curr_neigh; this->curr_row = other.curr_row; this->curr_col = other.curr_col; + + this->first_edge = other.first_edge; } return *this; } @@ -69,7 +70,6 @@ namespace sdsl return !(*this == rhs); } - friend void swap(edge_iterator &rhs, edge_iterator &lhs) { if (lhs != rhs) @@ -106,70 +106,79 @@ namespace sdsl return *tmp; } - // edge_iterator &operator--() - // { - // // curr_col++; - // // if (curr_col >= k) - // // { - // // curr_col = 0; - // // curr_row++; - // // } - // // edge e = _find_next(); - // // _ptr = new edge(std::get<0>(e), std::get<1>(e)); - // // return *this; - // } - // edge_iterator &operator--(int) - // { - // edge_iterator *tmp; - // tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); - // operator--(); - // return *tmp; - // } + edge_iterator &operator--() + { + if (!equal_edge(*_ptr, *first_edge)) + { + curr_col--; + if (curr_col >= 0) + { + curr_col = k - 1; + curr_row--; + } + edge e = _find_prev(); + _ptr = new edge(std::get<0>(e), std::get<1>(e)); + } + return *this; + } + edge_iterator &operator--(int) + { + edge_iterator *tmp; + tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); + operator--(); + return *tmp; + } ~edge_iterator() {} edge_iterator end() - { //TODO: find out about backtrack the tree - - // if(k_l->size() == 0) { - // return *this; - // } - // idx_type old_curr_node = curr_node; - // idx_type old_curr_neigh = curr_neigh; - // unsigned old_curr_row = curr_row; - // unsigned old_curr_col = curr_col; - // pointer old_ptr = _ptr; - - // edge last_edge = edge(size, size); - // edge_iterator prev = *this; - // while (!equal_edge(*_ptr, last_edge)) - // { - // prev = *this; - // operator++(); - // } - - // curr_node = old_curr_node; - // curr_neigh = old_curr_neigh; - // curr_col = old_curr_col; - // curr_row = old_curr_row; - // _ptr = old_ptr; - edge_iterator it; + { + edge_iterator it = *this; it._ptr = new edge(size, size); //end node + + it.curr_node = size-1; + it.curr_neigh = k * std::floor(it.curr_node / static_cast(it._n)); + it.curr_row = k; + it.curr_col = k; + return it; } - friend ostream &operator<<(ostream &os, const edge_iterator &edg) { + + friend ostream &operator<<(ostream &os, const edge_iterator &edg) + { os << " ==== ktree Edge Iterator ==== " << endl; edge e = *edg._ptr; + if (get<0>(e) == edg.size && get<1>(e) == edg.size) + { + os << " END NODE" << endl; + // os << " ============================= " << endl; + // return os; + } + os << " ptr (" << get<0>(e) << ", " << get<1>(e) << ")" << endl; os << " CONTAINER " << endl; os << " k_t "; - for(uint i = 0; i < edg.k_t->size(); i++) - os << (*edg.k_t)[i]; - os << endl; + if (edg.k_t != NULL) + { + for (uint i = 0; i < edg.k_t->size(); i++) + os << (*edg.k_t)[i]; + os << endl; + } + else + { + os << "null" << endl; + } os << " k_l "; - for(uint i = 0; i < edg.k_l->size(); i++) - os << (*edg.k_l)[i]; - os << endl; + if (edg.k_l != NULL) + { + for (uint i = 0; i < edg.k_l->size(); i++) + os << (*edg.k_l)[i]; + os << endl; + } + else + { + os << "null" << endl; + } os << " k_height " << edg.k_height << endl; os << " STATE " << endl; os << " size " << edg.size << endl; @@ -178,17 +187,17 @@ namespace sdsl os << " curr_neigh " << edg.curr_neigh << endl; os << " curr_row " << edg.curr_row << endl; os << " curr_col " << edg.curr_col << endl; - os << " ============================ " << endl; + os << " ============================= " << endl; return os; } protected: pointer _ptr; - // container TODO: pass the tree (?) - const t_bv *k_t; - const t_bv *k_l; - const t_rank *k_t_rank; + // container + const t_bv *k_t = NULL; + const t_bv *k_l = NULL; + const t_rank *k_t_rank = NULL; uint16_t k_height; // @@ -196,7 +205,8 @@ namespace sdsl size_t size; size_type _n; idx_type curr_node, curr_neigh; - unsigned curr_row, curr_col; + unsigned curr_col; + int curr_row; // void @@ -222,7 +232,7 @@ namespace sdsl } } - edge _find_next() + value_type _find_next() { idx_type neigh; if (curr_node < size) @@ -272,31 +282,7 @@ namespace sdsl return false; } - edge _find_prev() - { - idx_type neigh; - if (curr_node > 0) - { - for (; curr_row > 0; curr_row--) - { - neigh = size; - _find_prev_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); - if (neigh < size) - { - // cout << "x: " << curr_node << " y: " << neigh << endl; - return edge(curr_node, neigh); - } - } - curr_row = 0; - curr_col = 0; - curr_node--; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - return _find_prev(); - } - return edge(size, size); // end node - } - - unsigned _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) + bool _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { if (level >= k_t->size()) // Last level { @@ -312,15 +298,46 @@ namespace sdsl { size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j > 0; j--) - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) + for (int j = initial_j; j >= 0; j--) { + cout <<"j " << j << endl; + if (_find_prev_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, k-1)) { col_state = j; return true; } + } } return false; } + value_type _find_prev() + { + idx_type neigh; + if (curr_node >= 0) + { + for (; curr_row >= 0; curr_row--) + { + neigh = size; + cout << "curr_row " << curr_row << endl; + cout << "curr_node " << curr_node << endl; + cout << endl; + _find_prev_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); + if (neigh < size) + { + // cout << "x: " << curr_node << " y: " << neigh << endl; + return edge(curr_node, neigh); + } + } + curr_row = k - 1; + curr_col = k - 1; + curr_node--; + curr_neigh = k * std::floor(curr_node / static_cast(_n)); + + + return _find_prev(); + } else { + return edge(size, size);//FIXME + } + } private: edge *first_edge; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 3d8d21169..11f56e56d 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -308,6 +308,22 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(std::get<1>(*last), (size_t) 1); ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.size()); ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.size()); + + //OPERATOR DECREMENT + last = tree.edge_end(); + cout << last << endl; + last--; + ASSERT_EQ(std::get<0>(*last), (size_t) 3); + ASSERT_EQ(std::get<1>(*last), (size_t) 2); + last--; + ASSERT_EQ(std::get<0>(*last), (size_t) 2); + ASSERT_EQ(std::get<1>(*last), (size_t) 2); + last--; + ASSERT_EQ(std::get<0>(*last), (size_t) 0); + ASSERT_EQ(std::get<1>(*last), (size_t) 1); + last--; // does not go beyong the begin + ASSERT_EQ(std::get<0>(*last), (size_t) 0); + ASSERT_EQ(std::get<1>(*last), (size_t) 1); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 5709da8bf202efa286898ddf49908ed1eb60de9f Mon Sep 17 00:00:00 2001 From: Joana H Date: Fri, 8 May 2020 00:29:55 +0100 Subject: [PATCH 19/57] Remove prints --- include/sdsl/k2_tree_iterator.hpp | 4 ---- test/k2_tree_test.cpp | 1 - 2 files changed, 5 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 7b04edb46..b5b9de034 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -299,7 +299,6 @@ namespace sdsl size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + k * std::floor(row / static_cast(n)); for (int j = initial_j; j >= 0; j--) { - cout <<"j " << j << endl; if (_find_prev_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, k-1)) { col_state = j; @@ -317,9 +316,6 @@ namespace sdsl for (; curr_row >= 0; curr_row--) { neigh = size; - cout << "curr_row " << curr_row << endl; - cout << "curr_node " << curr_node << endl; - cout << endl; _find_prev_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); if (neigh < size) { diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 11f56e56d..2709eeffe 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -311,7 +311,6 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) //OPERATOR DECREMENT last = tree.edge_end(); - cout << last << endl; last--; ASSERT_EQ(std::get<0>(*last), (size_t) 3); ASSERT_EQ(std::get<1>(*last), (size_t) 2); From 99017f75b11946d376f93a33edb46ac9cbf19f24 Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 12 May 2020 00:24:36 +0100 Subject: [PATCH 20/57] sick iterator --- include/sdsl/k2_tree.hpp | 30 ++++++-------------- include/sdsl/k2_tree_iterator.hpp | 46 +++++++++++++++++++------------ test/k2_tree_test.cpp | 45 ++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 40 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 342ed9a23..4dc644f0c 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -438,15 +438,11 @@ class k2_tree k2_tree unionOp(k2_tree &k2_B) { assert(this->k_k == k2_B.k_k); - if (k2_B.get_number_edges() == 0) - { return *this; - } + if (this->get_number_edges() == 0) - { return k2_B; - } if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); @@ -469,39 +465,32 @@ class k2_tree pA = 0; pB = 0; - while (!Q.empty()) - { + while (!Q.empty()) { next = Q.front(); Q.pop_front(); uint l = next[0]; uint rA = next[1]; uint rB = next[2]; - - for (size_t i = 0; i < k_k * k_k; ++i) - { + for (size_t i = 0; i < k_k * k_k; ++i) { uint bA, bB; bA = 0; bB = 0; - if (rA == 1) - { + if (rA == 1) { if (l + 1 < this->k_height) bA = this->get_t()[pA]; else bA = this->get_l()[pA - t_size_A]; pA++; } - if (rB == 1) - { + if (rB == 1) { if (l + 1 < k2_B.k_height) bB = k2_B.k_t[pB]; else bB = k2_B.get_l()[pB - t_size_B]; pB++; } - C[l].push_back(bA || bB); - if ((l + 1 < this->k_height || l + 1 < k2_B.k_height) && (bA || bB)) Q.push_back({l + 1, bA, bB}); } @@ -514,15 +503,12 @@ class k2_tree bit_vector t(t_size, 0); bit_vector l(C[max_height - 1].size(), 0); - size_t p = 0; for (size_t l = 0; l < max_height - 1; l++) - for (size_t bit = 0; bit < C[l].size(); bit++) - { + for (size_t bit = 0; bit < C[l].size(); bit++) { t.set_int(p, C[l][bit]); ++p; } - for (size_t bit = 0; bit < C[max_height - 1].size(); bit++) l.set_int(bit, C[max_height - 1][bit]); @@ -835,13 +821,13 @@ class k2_tree return false; } - edg_iterator edge_begin() + edg_iterator &edge_begin() { edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); return edge_it; } - edg_iterator edge_end() + edg_iterator &edge_end() { edge_it_end = edge_it.end(); return edge_it_end; diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index b5b9de034..f5e4c8d88 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -88,13 +88,17 @@ namespace sdsl edge_iterator &operator++() { - curr_col++; - if (curr_col >= k) - { - curr_col = 0; - curr_row++; + if(last_neigh == size) { + cout << "last_neigh " << last_neigh << endl; + curr_col++; + if (curr_col >= k) + { + curr_col = 0; + curr_row++; + } } edge e = _find_next(); + _ptr = new edge(std::get<0>(e), std::get<1>(e)); return *this; } @@ -114,7 +118,7 @@ namespace sdsl if (curr_col >= 0) { curr_col = k - 1; - curr_row--; + curr_row = curr_row >= k ? 0 : (curr_row-1); } edge e = _find_prev(); _ptr = new edge(std::get<0>(e), std::get<1>(e)); @@ -207,8 +211,9 @@ namespace sdsl idx_type curr_node, curr_neigh; unsigned curr_col; int curr_row; + size_t last_neigh; //marks if there are still other children at the leaf to search // - + void _initialize() { @@ -218,6 +223,7 @@ namespace sdsl curr_row = 0; curr_col = 0; size = std::pow(k, k_height); + last_neigh = size; if (k_l->size() > 0) { edge first = _find_next(); @@ -246,6 +252,7 @@ namespace sdsl // cout << "x: " << curr_node << " y: " << neigh << endl; return edge(curr_node, neigh); } + last_neigh = size; } curr_row = 0; curr_col = 0; @@ -258,26 +265,30 @@ namespace sdsl unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) { - if (level >= k_t->size()) // Last level + if (level >= k_t->size()) // Last level { - if ((*k_l)[level - k_t->size()] == 1) - { + // cout << " level " << level << endl; + // cout << " index " << level - k_t->size() << endl; + if(last_neigh == col) + return false; + if ((*k_l)[level - k_t->size()] == 1 ) { neigh = col; + last_neigh = col; return true; } return false; } - if ((*k_t)[level] == 1 && n > 0) - { - size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + + if ((*k_t)[level] == 1) { + size_type y = (*k_t_rank)(level + 1) * k * k + k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) - { + + for (unsigned j = initial_j; j < k; j++) { + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) { col_state = j; return true; } + } } return false; } @@ -328,10 +339,9 @@ namespace sdsl curr_node--; curr_neigh = k * std::floor(curr_node / static_cast(_n)); - return _find_prev(); } else { - return edge(size, size);//FIXME + return *first_edge; } } diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 2709eeffe..0f0847e62 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -323,6 +323,51 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) last--; // does not go beyong the begin ASSERT_EQ(std::get<0>(*last), (size_t) 0); ASSERT_EQ(std::get<1>(*last), (size_t) 1); + + //Intensive test + vector> mat2({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 1, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}); + TypeParam treeIntensive(mat2); + + auto it = treeIntensive.edge_begin(); + + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 2); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 4); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 3); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 3); + ASSERT_EQ(std::get<1>(*it), (size_t) 4); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 3); + ASSERT_EQ(std::get<1>(*it), (size_t) 9); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 5); + ASSERT_EQ(std::get<1>(*it), (size_t) 0); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 5); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 6); + ASSERT_EQ(std::get<1>(*it), (size_t) 0); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 7); + ASSERT_EQ(std::get<1>(*it), (size_t) 0); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 9); + ASSERT_EQ(std::get<1>(*it), (size_t) 0); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From ca65210c9211c2d999aa4246600be2471bdf346b Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 12 May 2020 23:19:07 +0100 Subject: [PATCH 21/57] fixd iterator --- include/sdsl/k2_tree_iterator.hpp | 309 +++++++++++++++++------------- test/k2_tree_test.cpp | 79 ++++---- 2 files changed, 223 insertions(+), 165 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index f5e4c8d88..648581a4a 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -51,10 +51,10 @@ namespace sdsl this->_ptr = other._ptr; this->size = other.size; this->_n = other._n; - this->curr_node = other.curr_node; - this->curr_neigh = other.curr_neigh; - this->curr_row = other.curr_row; - this->curr_col = other.curr_col; + this->_node = other._node; + this->_level = other._level; + this->_row = other._row; + this->_col = other._col; this->first_edge = other.first_edge; } @@ -79,26 +79,36 @@ namespace sdsl std::swap(lhs.k_l, rhs.k_l); std::swap(lhs.k_t_rank, rhs.k_t_rank); std::swap(lhs.size, rhs.size); - std::swap(lhs.curr_node, rhs.curr_node); - std::swap(lhs.curr_neigh, rhs.curr_neigh); - std::swap(lhs.curr_row, rhs.curr_row); - std::swap(lhs.curr_col, rhs.curr_col); + std::swap(lhs._node, rhs._node); + std::swap(lhs._level, rhs._level); + std::swap(lhs._row, rhs._row); + std::swap(lhs._col, rhs._col); } } edge_iterator &operator++() { - if(last_neigh == size) { - cout << "last_neigh " << last_neigh << endl; - curr_col++; - if (curr_col >= k) + + if (st.valid) + { + st.j++; + if (st.j < k) { - curr_col = 0; - curr_row++; + edge e; + e = _find_next_middle(); + _ptr = new edge(std::get<0>(e), std::get<1>(e)); + return *this; } } - edge e = _find_next(); - + st.valid = false; + _col++; + if (_col >= k) + { + _col = 0; + _row++; + } + edge e; + e = _find_next(); _ptr = new edge(std::get<0>(e), std::get<1>(e)); return *this; } @@ -110,28 +120,28 @@ namespace sdsl return *tmp; } - edge_iterator &operator--() - { - if (!equal_edge(*_ptr, *first_edge)) - { - curr_col--; - if (curr_col >= 0) - { - curr_col = k - 1; - curr_row = curr_row >= k ? 0 : (curr_row-1); - } - edge e = _find_prev(); - _ptr = new edge(std::get<0>(e), std::get<1>(e)); - } - return *this; - } - edge_iterator &operator--(int) - { - edge_iterator *tmp; - tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); - operator--(); - return *tmp; - } + // edge_iterator &operator--() + // { + // if (!equal_edge(*_ptr, *first_edge)) + // { + // _col--; + // if (_col >= 0) + // { + // _col = k - 1; + // _row = _row >= k ? 0 : (_row-1); + // } + // edge e = _find_prev(); + // _ptr = new edge(std::get<0>(e), std::get<1>(e)); + // } + // return *this; + // } + // edge_iterator &operator--(int) + // { + // edge_iterator *tmp; + // tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); + // operator--(); + // return *tmp; + // } ~edge_iterator() {} @@ -140,10 +150,10 @@ namespace sdsl edge_iterator it = *this; it._ptr = new edge(size, size); //end node - it.curr_node = size-1; - it.curr_neigh = k * std::floor(it.curr_node / static_cast(it._n)); - it.curr_row = k; - it.curr_col = k; + it._node = size - 1; + it._level = k * std::floor(it._node / static_cast(it._n)); + it._row = k; + it._col = k; return it; } @@ -155,8 +165,8 @@ namespace sdsl if (get<0>(e) == edg.size && get<1>(e) == edg.size) { os << " END NODE" << endl; - // os << " ============================= " << endl; - // return os; + // os << " ============================= " << endl; + // return os; } os << " ptr (" << get<0>(e) << ", " << get<1>(e) << ")" << endl; @@ -187,10 +197,10 @@ namespace sdsl os << " STATE " << endl; os << " size " << edg.size << endl; os << " _n " << edg._n << endl; - os << " curr_node " << edg.curr_node << endl; - os << " curr_neigh " << edg.curr_neigh << endl; - os << " curr_row " << edg.curr_row << endl; - os << " curr_col " << edg.curr_col << endl; + os << " _node " << edg._node << endl; + os << " _level " << edg._level << endl; + os << " _row " << edg._row << endl; + os << " _col " << edg._col << endl; os << " ============================= " << endl; return os; } @@ -205,25 +215,44 @@ namespace sdsl uint16_t k_height; // + typedef struct state + { + unsigned node, row, col, n, level, j, y; + bool valid = false; + + void set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) + { + node = _node; + row = _row; + col = _col; + n = _n; + level = _level; + j = _j; + y = _y; + valid = true; + } + } state; + // iterator state // + state st; size_t size; size_type _n; - idx_type curr_node, curr_neigh; - unsigned curr_col; - int curr_row; - size_t last_neigh; //marks if there are still other children at the leaf to search + idx_type _node, _level; + unsigned _col; + int _row; + // size_t last_neigh; //marks if there are still other children at the leaf to search // - + void _initialize() { _n = static_cast(std::pow(k, k_height)) / k; - curr_node = 0; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - curr_row = 0; - curr_col = 0; + _node = 0; + _row = 0; + _col = 0; + _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, k_height); - last_neigh = size; + if (k_l->size() > 0) { edge first = _find_next(); @@ -238,62 +267,52 @@ namespace sdsl } } - value_type _find_next() + edge _find_next_middle() { - idx_type neigh; - if (curr_node < size) + if (st.valid) { - for (; curr_row < k; curr_row++) + idx_type neigh = size; + _find_next_recursive(st.n / k, st.row % st.n, st.col + st.n * st.j, st.y + st.j, neigh, st.j); + if (neigh != size) { - neigh = size; - _find_next_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); - if (neigh < size) - { - // cout << "x: " << curr_node << " y: " << neigh << endl; - return edge(curr_node, neigh); - } - last_neigh = size; + return edge(_node, neigh); } - curr_row = 0; - curr_col = 0; - curr_node++; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - return _find_next(); } - return edge(size, size); // end node - } - unsigned _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) - { - if (level >= k_t->size()) // Last level + st.valid = false; + _col++; + if (_col >= k) { - // cout << " level " << level << endl; - // cout << " index " << level - k_t->size() << endl; - if(last_neigh == col) - return false; - if ((*k_l)[level - k_t->size()] == 1 ) { - neigh = col; - last_neigh = col; - return true; - } - return false; + _col = 0; + _row++; } + return _find_next(); + } - if ((*k_t)[level] == 1) { - size_type y = (*k_t_rank)(level + 1) * k * k + - k * std::floor(row / static_cast(n)); - - for (unsigned j = initial_j; j < k; j++) { - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, 0)) { - col_state = j; - return true; + edge _find_next() + { + idx_type neigh; + if (_node < size) + { + for (; _row < k; _row++) + { + neigh = size; + _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); + if (neigh < size) + { + // cout << "x: " << _node << " y: " << neigh << endl; + return edge(_node, neigh); } } + _row = 0; _col = 0; _node++; + _level = k * std::floor(_node / static_cast(_n)); + st.valid = false; + return _find_next(); } - return false; + return edge(size, size); // end node } - bool _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) + bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned initial_j) { if (level >= k_t->size()) // Last level { @@ -305,45 +324,75 @@ namespace sdsl return false; } - if ((*k_t)[level] == 1 && n > 0) + if ((*k_t)[level] == 1) { - size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + + size_type y = (*k_t_rank)(level + 1) * k * k + k * std::floor(row / static_cast(n)); - for (int j = initial_j; j >= 0; j--) { - if (_find_prev_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, k-1)) + + for (unsigned j = initial_j; j < k; j++) + { + st.set(_node, n, row, col, level, j, y); + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) { - col_state = j; + _col = j; return true; } } } return false; } - value_type _find_prev() - { - idx_type neigh; - if (curr_node >= 0) - { - for (; curr_row >= 0; curr_row--) - { - neigh = size; - _find_prev_recursive(_n / k, curr_node % _n, _n * curr_row, curr_neigh + curr_row, neigh, curr_col, curr_col); - if (neigh < size) - { - // cout << "x: " << curr_node << " y: " << neigh << endl; - return edge(curr_node, neigh); - } - } - curr_row = k - 1; - curr_col = k - 1; - curr_node--; - curr_neigh = k * std::floor(curr_node / static_cast(_n)); - - return _find_prev(); - } else { - return *first_edge; - } - } + + // bool _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) + // { + // if (level >= k_t->size()) // Last level + // { + // if ((*k_l)[level - k_t->size()] == 1) + // { + // neigh = col; + // return true; + // } + // return false; + // } + + // if ((*k_t)[level] == 1 && n > 0) + // { + // size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + + // k * std::floor(row / static_cast(n)); + // for (int j = initial_j; j >= 0; j--) { + // if (_find_prev_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, k-1)) + // { + // col_state = j; + // return true; + // } + // } + // } + // return false; + // } + // value_type _find_prev() + // { + // idx_type neigh; + // if (_node >= 0) + // { + // for (; _row >= 0; _row--) + // { + // neigh = size; + // _find_prev_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col, _col); + // if (neigh < size) + // { + // // cout << "x: " << _node << " y: " << neigh << endl; + // return edge(_node, neigh); + // } + // } + // _row = k - 1; + // _col = k - 1; + // _node--; + // _level = k * std::floor(_node / static_cast(_n)); + + // return _find_prev(); + // } else { + // return *first_edge; + // } + // } private: edge *first_edge; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 0f0847e62..b5e0640c1 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -270,59 +270,42 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) { //forward iterator - vector> mat({{0, 1, 0, 0}, + vector> mat({{1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}}); TypeParam tree(mat); - auto edge_iterator = tree.edge_begin(); ASSERT_EQ(std::get<0>(*edge_iterator), (size_t)0); - ASSERT_EQ(std::get<1>(*edge_iterator), (size_t)1); - + ASSERT_EQ(std::get<1>(*edge_iterator), (size_t)0); + // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; ASSERT_EQ(std::get<0>(*another_edge_iterator), (size_t) 0); - ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 1); - - // OPERATOR EQUALS - ASSERT_TRUE(another_edge_iterator == edge_iterator); + ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 0); - //OPERATOR INCREMENT - // ++edge_iterator; // also works + // //OPERATOR INCREMENT + // // ++edge_iterator; // also works + edge_iterator++; + ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 0); + ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 1); edge_iterator++; ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 2); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); - - // OPERATOR INEQUALS - ASSERT_TRUE(another_edge_iterator != edge_iterator); - + edge_iterator++; + ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 3); + ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); + edge_iterator++; + //find last auto last = tree.edge_end(); ASSERT_EQ(std::get<0>(*last), tree.size()); ASSERT_EQ(std::get<1>(*last), tree.size()); - //OPERATION SWAP - swap(last, another_edge_iterator); - ASSERT_EQ(std::get<0>(*last), (size_t) 0); - ASSERT_EQ(std::get<1>(*last), (size_t) 1); - ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.size()); - ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.size()); - - //OPERATOR DECREMENT - last = tree.edge_end(); - last--; - ASSERT_EQ(std::get<0>(*last), (size_t) 3); - ASSERT_EQ(std::get<1>(*last), (size_t) 2); - last--; - ASSERT_EQ(std::get<0>(*last), (size_t) 2); - ASSERT_EQ(std::get<1>(*last), (size_t) 2); - last--; - ASSERT_EQ(std::get<0>(*last), (size_t) 0); - ASSERT_EQ(std::get<1>(*last), (size_t) 1); - last--; // does not go beyong the begin - ASSERT_EQ(std::get<0>(*last), (size_t) 0); - ASSERT_EQ(std::get<1>(*last), (size_t) 1); + // OPERATOR EQUALS + ASSERT_TRUE(edge_iterator == tree.edge_end()); + // OPERATOR INEQUALS + ASSERT_TRUE(edge_iterator != tree.edge_begin()); //Intensive test vector> mat2({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -368,8 +351,34 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) it++; ASSERT_EQ(std::get<0>(*it), (size_t) 9); ASSERT_EQ(std::get<1>(*it), (size_t) 0); + + //OPERATION SWAP + swap(last, another_edge_iterator); + ASSERT_EQ(std::get<0>(*last), (size_t) 0); + ASSERT_EQ(std::get<1>(*last), (size_t) 0); + ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.size()); + ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.size()); } + +// //OPERATOR DECREMENT +// last = tree.edge_end(); +// last--; +// ASSERT_EQ(std::get<0>(*last), (size_t) 3); +// ASSERT_EQ(std::get<1>(*last), (size_t) 2); +// last--; +// ASSERT_EQ(std::get<0>(*last), (size_t) 2); +// ASSERT_EQ(std::get<1>(*last), (size_t) 2); +// last--; +// ASSERT_EQ(std::get<0>(*last), (size_t) 0); +// ASSERT_EQ(std::get<1>(*last), (size_t) 1); +// last--; // does not go beyong the begin +// ASSERT_EQ(std::get<0>(*last), (size_t) 0); +// ASSERT_EQ(std::get<1>(*last), (size_t) 1); + + +// } + TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) From 71bcbf0f22c0144c49022a990c6c88410115c946 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 28 May 2020 17:26:33 +0100 Subject: [PATCH 22/57] Fix iterator --- .gitignore | 4 +++- include/sdsl/k2_tree_iterator.hpp | 15 +++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index b915d07d9..5bf21f149 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ Make.helper -.vscode \ No newline at end of file +.vscode +.idea/* +cmake-build-debug/ \ No newline at end of file diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 648581a4a..93e2a51c3 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -55,15 +55,17 @@ namespace sdsl this->_level = other._level; this->_row = other._row; this->_col = other._col; - - this->first_edge = other.first_edge; } return *this; } bool operator==(const edge_iterator &rhs) const { - return equal_edge(*(rhs._ptr), *(this->_ptr)); + if(rhs._ptr != NULL && this->_ptr != NULL) + return equal_edge(*(rhs._ptr), *(this->_ptr)); + else if(rhs._ptr == NULL && this->_ptr == NULL) + return true; + return false; } bool operator!=(const edge_iterator &rhs) const { @@ -206,7 +208,7 @@ namespace sdsl } protected: - pointer _ptr; + pointer _ptr = NULL; // container const t_bv *k_t = NULL; @@ -256,13 +258,11 @@ namespace sdsl if (k_l->size() > 0) { edge first = _find_next(); - first_edge = new edge(std::get<0>(first), std::get<1>(first)); - _ptr = first_edge; + _ptr = new edge(std::get<0>(first), std::get<1>(first));; } else { // if its empty the begin == end - first_edge = new edge(size, size); _ptr = new edge(size, size); //end node } } @@ -395,7 +395,6 @@ namespace sdsl // } private: - edge *first_edge; bool equal_edge(const edge &e1, const edge &e2) const { From 93cdb4c2fa1d482b75491072f2036f136071e89c Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 2 Jun 2020 08:58:43 +0100 Subject: [PATCH 23/57] Increment node iterator [#1] --- include/sdsl/k2_tree.hpp | 36 ++++++--- include/sdsl/k2_tree_iterator.hpp | 126 ++++++++++++++++++++++++++++-- test/k2_tree_test.cpp | 31 ++++++-- 3 files changed, 170 insertions(+), 23 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 4dc644f0c..47b79d90d 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -56,6 +56,7 @@ class k2_tree typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; using edg_iterator = edge_iterator; + using nod_iterator = node_iterator>; protected: //! Bit array to store all the bits of the tree, except those in the @@ -75,6 +76,9 @@ class k2_tree edg_iterator edge_it; edg_iterator edge_it_end; + nod_iterator node_it; + nod_iterator node_it_end; + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -325,6 +329,7 @@ class k2_tree k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); + edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); edge_it_end = edge_it.end(); } @@ -412,21 +417,30 @@ class k2_tree edge_it_end = edge_it.end(); } - t_bv get_t() + t_bv get_t() const { return k_t; } - t_bv get_l() + t_bv get_l() const { return k_l; } - uint8_t get_marked_edges() + uint8_t get_marked_edges() const { return n_marked_edges; } + int get_number_edges() const + { + return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + } + + idx_type get_number_nodes() const + { + return std::pow(k, k_height); + } //! Union Operation /*! Performs the union operation between two tree. This operations requires both * trees to have the same number of nodes. @@ -582,10 +596,6 @@ class k2_tree return true; } - int get_number_edges() - { - return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); - } //! Indicates whether node j is adjacent to node i or not. /*! @@ -833,8 +843,16 @@ class k2_tree return edge_it_end; } - size_t size() { - return std::pow(k, k_height); + nod_iterator &node_begin() + { + node_it = nod_iterator(this); + return node_it; + } + + nod_iterator &node_end() + { + node_it_end = node_it.end(); + return node_it_end; } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 93e2a51c3..f39aaa46f 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -26,7 +26,7 @@ namespace sdsl using value_type = edge; using pointer = edge *; using reference = edge &; - using iterator_category = std::bidirectional_iterator_tag; + using iterator_category = std::forward_iterator_tag; edge_iterator() {} edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) @@ -61,9 +61,9 @@ namespace sdsl bool operator==(const edge_iterator &rhs) const { - if(rhs._ptr != NULL && this->_ptr != NULL) + if (rhs._ptr != NULL && this->_ptr != NULL) return equal_edge(*(rhs._ptr), *(this->_ptr)); - else if(rhs._ptr == NULL && this->_ptr == NULL) + else if (rhs._ptr == NULL && this->_ptr == NULL) return true; return false; } @@ -90,7 +90,6 @@ namespace sdsl edge_iterator &operator++() { - if (st.valid) { st.j++; @@ -145,7 +144,10 @@ namespace sdsl // return *tmp; // } - ~edge_iterator() {} + ~edge_iterator() + { + // if(_ptr != NULL) delete _ptr; + } edge_iterator end() { @@ -258,7 +260,8 @@ namespace sdsl if (k_l->size() > 0) { edge first = _find_next(); - _ptr = new edge(std::get<0>(first), std::get<1>(first));; + _ptr = new edge(std::get<0>(first), std::get<1>(first)); + ; } else { @@ -304,7 +307,9 @@ namespace sdsl return edge(_node, neigh); } } - _row = 0; _col = 0; _node++; + _row = 0; + _col = 0; + _node++; _level = k * std::floor(_node / static_cast(_n)); st.valid = false; return _find_next(); @@ -395,7 +400,6 @@ namespace sdsl // } private: - bool equal_edge(const edge &e1, const edge &e2) const { idx_type e1_x = std::get<0>(e1); @@ -407,6 +411,112 @@ namespace sdsl return e1_x == e2_x && e1_y == e2_y; } }; + + template + class node_iterator + { + using node_type = k2_tree_ns::idx_type; + using size_type = k2_tree_ns::size_type; + + public: + using value_type = node_type; + using pointer = node_type *; + using reference = node_type &; + using iterator_category = std::forward_iterator_tag; + + node_iterator() {} + node_iterator(const k2_tree *k_tree) + { + this->tree = k_tree; + for(value_type i = 0; i < tree->get_number_nodes(); i++) + for(value_type j = 0; j < tree->get_number_nodes(); j++) + if(tree->adj(i,j)) { + _ptr = &i; + curr_i = i; + curr_j = j; + return; + } + } + + node_iterator(node_iterator *other) { + this->_ptr = other->_ptr; + this->tree = other->tree; + this->curr_i = other->curr_i; + this->curr_j = other->curr_j; + } + + ~node_iterator() + {} + + value_type operator*() const + { + return *_ptr; + } + + bool operator==(const node_iterator &rhs) const + { + if (rhs._ptr != NULL && this->_ptr != NULL) + return rhs._ptr == this->_ptr; + else if (rhs._ptr == NULL && this->_ptr == NULL) + return true; + return false; + } + + bool operator!=(const node_iterator &rhs) const + { + return !(*this == rhs); + } + + node_iterator &operator++() + { + size_t num_nodes = tree->get_number_nodes(); + + for(value_type i = curr_i; i < num_nodes; i++) { + for(value_type j = curr_j+1; j < num_nodes; j++) { + if(tree->adj(i, j)) { + if(i > j) + _ptr = &i; + else + _ptr = &j; + + curr_i = i; + curr_j = j; + return *this; + } + } + curr_j = -1; + } + return *this; + } + + node_iterator &operator++(int) + { + node_iterator *tmp; + tmp = new node_iterator(this); + operator++(); + return *tmp; + } + + // node_iterator end() + // { + // node_iterator it = *this; + // value_type num_nodes = it.tree->get_number_nodes(); + // it._ptr = &it.tree->get_number_nodes(); //end node + // it.curr_i = num_nodes; + // it.curr_j = num_nodes; + // return it; + // } + + // friend void swap(node_iterator &rhs, node_iterator &lhs) + // { + // } + + private: + pointer _ptr = NULL; + const k2_tree* tree = NULL; + value_type curr_i, curr_j; + }; + } // namespace sdsl #endif \ No newline at end of file diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index b5e0640c1..3764c5f81 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -299,8 +299,8 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) //find last auto last = tree.edge_end(); - ASSERT_EQ(std::get<0>(*last), tree.size()); - ASSERT_EQ(std::get<1>(*last), tree.size()); + ASSERT_EQ(std::get<0>(*last), tree.get_number_nodes()); + ASSERT_EQ(std::get<1>(*last), tree.get_number_nodes()); // OPERATOR EQUALS ASSERT_TRUE(edge_iterator == tree.edge_end()); @@ -356,11 +356,10 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) swap(last, another_edge_iterator); ASSERT_EQ(std::get<0>(*last), (size_t) 0); ASSERT_EQ(std::get<1>(*last), (size_t) 0); - ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.size()); - ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.size()); + ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.get_number_nodes()); + ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.get_number_nodes()); } - // //OPERATOR DECREMENT // last = tree.edge_end(); // last--; @@ -375,9 +374,29 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) // last--; // does not go beyong the begin // ASSERT_EQ(std::get<0>(*last), (size_t) 0); // ASSERT_EQ(std::get<1>(*last), (size_t) 1); +// } + +TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { + vector> mat({{1, 1, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}}); + TypeParam tree(mat); + auto node_iterator = tree.node_begin(); + ASSERT_EQ(*node_iterator, (size_t)0); + + node_iterator++; + ASSERT_EQ(*node_iterator, (size_t)1); + + node_iterator++; + ASSERT_EQ(*node_iterator, (size_t)2); + node_iterator++; + ASSERT_EQ(*node_iterator, (size_t)3); -// } + // node_iterator = tree.node_end(); + // ASSERT_EQ(*node_iterator, (size_t)4); +} TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 3255dc773589fa525a8fe2e38d255ddf487ab9c5 Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 2 Jun 2020 22:46:36 +0100 Subject: [PATCH 24/57] Fix test Add swap function to node iterator #1 --- include/sdsl/k2_tree_iterator.hpp | 28 ++++++++++++++++------------ test/k2_tree_test.cpp | 10 ++++++++-- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index f39aaa46f..7d0f04ccf 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -497,19 +497,23 @@ namespace sdsl return *tmp; } - // node_iterator end() - // { - // node_iterator it = *this; - // value_type num_nodes = it.tree->get_number_nodes(); - // it._ptr = &it.tree->get_number_nodes(); //end node - // it.curr_i = num_nodes; - // it.curr_j = num_nodes; - // return it; - // } + node_iterator end() + { + node_iterator it = *this; + value_type num_nodes = it.tree->get_number_nodes(); + *(it._ptr) = it.tree->get_number_nodes(); //end node + it.curr_i = num_nodes; + it.curr_j = num_nodes; + return it; + } - // friend void swap(node_iterator &rhs, node_iterator &lhs) - // { - // } + friend void swap(node_iterator &rhs, node_iterator &lhs) + { + std::swap(rhs._ptr, lhs._ptr); + std::swap(rhs.tree, lhs.tree); + std::swap(rhs.curr_i, lhs.curr_i); + std::swap(rhs.curr_j, lhs.curr_j); + } private: pointer _ptr = NULL; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 3764c5f81..95fa1244c 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -394,8 +394,14 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { node_iterator++; ASSERT_EQ(*node_iterator, (size_t)3); - // node_iterator = tree.node_end(); - // ASSERT_EQ(*node_iterator, (size_t)4); + node_iterator = tree.node_end(); + ASSERT_EQ(*node_iterator, (size_t)4); + + auto other_iterator = tree.node_begin(); + swap(other_iterator, node_iterator); + ASSERT_EQ(*other_iterator, *tree.node_end()); + ASSERT_EQ(*node_iterator, *tree.node_begin()); + } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 247051304ab32ef3bde884c1a157e8aa1eefd9a6 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 3 Jun 2020 00:03:29 +0100 Subject: [PATCH 25/57] Fix node iterator [#1] --- include/sdsl/k2_tree_iterator.hpp | 69 ++++++++++++++++++++----------- test/k2_tree_test.cpp | 6 +-- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 7d0f04ccf..e783216cc 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -428,17 +428,29 @@ namespace sdsl node_iterator(const k2_tree *k_tree) { this->tree = k_tree; - for(value_type i = 0; i < tree->get_number_nodes(); i++) - for(value_type j = 0; j < tree->get_number_nodes(); j++) - if(tree->adj(i,j)) { + for (value_type i = 0; i < tree->get_number_nodes(); i++) + { + for (value_type j = i; j < tree->get_number_nodes(); j++) + if (tree->adj(i, j)) + { _ptr = &i; curr_i = i; curr_j = j; return; } + for (value_type j = i; j < tree->get_number_nodes(); j++) + if (tree->adj(j, i)) + { + _ptr = &i; + curr_i = i + 1; + curr_j = i; + return; + } + } } - node_iterator(node_iterator *other) { + node_iterator(node_iterator *other) + { this->_ptr = other->_ptr; this->tree = other->tree; this->curr_i = other->curr_i; @@ -446,7 +458,8 @@ namespace sdsl } ~node_iterator() - {} + { + } value_type operator*() const { @@ -468,24 +481,25 @@ namespace sdsl } node_iterator &operator++() - { - size_t num_nodes = tree->get_number_nodes(); - - for(value_type i = curr_i; i < num_nodes; i++) { - for(value_type j = curr_j+1; j < num_nodes; j++) { - if(tree->adj(i, j)) { - if(i > j) - _ptr = &i; - else - _ptr = &j; - - curr_i = i; - curr_j = j; - return *this; + { + for (value_type i = curr_i; i < tree->get_number_nodes(); i++) + { + for (value_type j = curr_j; j < tree->get_number_nodes(); j++) + if (tree->adj(i, j)) + { + return update_state(i); + } + for (value_type j = 0; j < tree->get_number_nodes(); j++) + { + if (j == i) + continue; + if (tree->adj(j, i)) + { + return update_state(i); } } - curr_j = -1; - } + curr_j = 0; + } return *this; } @@ -497,7 +511,7 @@ namespace sdsl return *tmp; } - node_iterator end() + node_iterator end() { node_iterator it = *this; value_type num_nodes = it.tree->get_number_nodes(); @@ -517,8 +531,17 @@ namespace sdsl private: pointer _ptr = NULL; - const k2_tree* tree = NULL; + const k2_tree *tree = NULL; value_type curr_i, curr_j; + + node_iterator &update_state(int i) + { + *_ptr = i; + curr_i = i + 1; + curr_j = 0; + + return *this; + } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 95fa1244c..e8e53538c 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -377,17 +377,17 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) // } TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { - vector> mat({{1, 1, 0, 0}, + vector> mat({{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, - {0, 0, 1, 0}}); + {1, 1, 1, 0}}); TypeParam tree(mat); auto node_iterator = tree.node_begin(); ASSERT_EQ(*node_iterator, (size_t)0); node_iterator++; ASSERT_EQ(*node_iterator, (size_t)1); - + node_iterator++; ASSERT_EQ(*node_iterator, (size_t)2); From fa6ea84638ea73f62b0759bdaa93707d07120837 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 3 Jun 2020 00:58:25 +0100 Subject: [PATCH 26/57] Fix empty tree node iterator [#1] --- include/sdsl/k2_tree_iterator.hpp | 11 +++-------- test/k2_tree_test.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index e783216cc..56763c4c1 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -457,9 +457,7 @@ namespace sdsl this->curr_j = other->curr_j; } - ~node_iterator() - { - } + ~node_iterator() {} value_type operator*() const { @@ -486,17 +484,13 @@ namespace sdsl { for (value_type j = curr_j; j < tree->get_number_nodes(); j++) if (tree->adj(i, j)) - { return update_state(i); - } for (value_type j = 0; j < tree->get_number_nodes(); j++) { if (j == i) continue; if (tree->adj(j, i)) - { return update_state(i); - } } curr_j = 0; } @@ -513,6 +507,7 @@ namespace sdsl node_iterator end() { + if(tree == NULL) return *this; node_iterator it = *this; value_type num_nodes = it.tree->get_number_nodes(); *(it._ptr) = it.tree->get_number_nodes(); //end node @@ -542,7 +537,7 @@ namespace sdsl return *this; } - }; + }; // namespace sdsl } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index e8e53538c..f2e433ec8 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -394,14 +394,18 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { node_iterator++; ASSERT_EQ(*node_iterator, (size_t)3); - node_iterator = tree.node_end(); - ASSERT_EQ(*node_iterator, (size_t)4); + node_iterator++; + ASSERT_EQ(*node_iterator, *tree.node_end()); auto other_iterator = tree.node_begin(); swap(other_iterator, node_iterator); ASSERT_EQ(*other_iterator, *tree.node_end()); ASSERT_EQ(*node_iterator, *tree.node_begin()); +} +TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { + TypeParam empty_tree; + ASSERT_TRUE(empty_tree.node_begin() == empty_tree.node_end()); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 039448a19f1833bfff1c8e9b62b5a0df0dcfaa57 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 21 Jun 2020 20:14:11 +0100 Subject: [PATCH 27/57] Refactor k2tree edge iterator --- include/sdsl/k2_tree.hpp | 44 +++--- include/sdsl/k2_tree_iterator.hpp | 214 ++++++------------------------ test/k2_tree_test.cpp | 28 ++-- 3 files changed, 79 insertions(+), 207 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 47b79d90d..1697ca489 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -55,7 +55,7 @@ class k2_tree public: typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; - using edg_iterator = edge_iterator; + using edg_iterator = edge_iterator>; using nod_iterator = node_iterator>; protected: @@ -303,9 +303,6 @@ class k2_tree k_l = bit_vector(0, 0); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); - edge_it_end = edge_it.end(); } //! Constructor @@ -329,9 +326,6 @@ class k2_tree k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); - - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); - edge_it_end = edge_it.end(); } //! Constructor @@ -350,8 +344,6 @@ class k2_tree assert(edges.size() > 0); build_from_edges(edges, size); - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); - edge_it_end = edge_it.end(); } //! Constructor @@ -393,7 +385,7 @@ class k2_tree std::tuple{buf_x[i], buf_y[i]}); build_from_edges(edges, size); - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it = edg_iterator(this); edge_it_end = edge_it.end(); } @@ -413,20 +405,34 @@ class k2_tree k_l = std::move(l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it = edg_iterator(this); edge_it_end = edge_it.end(); } - t_bv get_t() const + t_bv t() const { return k_t; } - t_bv get_l() const + t_rank rank_t() const + { + return k_t_rank; + } + + t_bv l() const { return k_l; } + + uint8_t k_() const { + return k_k; + } + + uint16_t height() const { + return k_height; + } + uint8_t get_marked_edges() const { return n_marked_edges; @@ -461,8 +467,8 @@ class k2_tree if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); - size_t t_size_A = this->get_t().size(); - size_t t_size_B = k2_B.get_t().size(); + size_t t_size_A = this->t().size(); + size_t t_size_B = k2_B.t().size(); // C Initialization const size_t max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; @@ -492,16 +498,16 @@ class k2_tree bB = 0; if (rA == 1) { if (l + 1 < this->k_height) - bA = this->get_t()[pA]; + bA = this->t()[pA]; else - bA = this->get_l()[pA - t_size_A]; + bA = this->l()[pA - t_size_A]; pA++; } if (rB == 1) { if (l + 1 < k2_B.k_height) bB = k2_B.k_t[pB]; else - bB = k2_B.get_l()[pB - t_size_B]; + bB = k2_B.l()[pB - t_size_B]; pB++; } C[l].push_back(bA || bB); @@ -833,7 +839,7 @@ class k2_tree edg_iterator &edge_begin() { - edge_it = edg_iterator(k_t, k_l, k_t_rank, k_height); + edge_it = edg_iterator(this); return edge_it; } diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 56763c4c1..289c5b171 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -12,15 +12,12 @@ using namespace std; namespace sdsl { - template + template class edge_iterator { using idx_type = k2_tree_ns::idx_type; using size_type = k2_tree_ns::size_type; using edge = std::tuple; - // using k2_tree = k2_tree; public: using value_type = edge; @@ -29,8 +26,10 @@ namespace sdsl using iterator_category = std::forward_iterator_tag; edge_iterator() {} - edge_iterator(const t_bv &k_t, const t_bv &k_l, const t_rank &k_t_rank, const uint16_t &k_height) : k_t(&k_t), k_l(&k_l), k_t_rank(&k_t_rank), k_height(k_height) + edge_iterator(const k_tree *tree) { + this->tree = tree; + this->k = tree->k_(); _initialize(); } @@ -39,14 +38,12 @@ namespace sdsl return *_ptr; } - edge_iterator &operator=(const edge_iterator &other) + edge_iterator &operator=(const edge_iterator &other) { if (this != &other) { - this->k_t = other.k_t; - this->k_l = other.k_l; - this->k_t_rank = other.k_t_rank; - this->k_height = other.k_height; + this->tree = other.tree; + this->k = other.k; this->_ptr = other._ptr; this->size = other.size; @@ -59,7 +56,7 @@ namespace sdsl return *this; } - bool operator==(const edge_iterator &rhs) const + bool operator==(const edge_iterator &rhs) const { if (rhs._ptr != NULL && this->_ptr != NULL) return equal_edge(*(rhs._ptr), *(this->_ptr)); @@ -67,19 +64,19 @@ namespace sdsl return true; return false; } - bool operator!=(const edge_iterator &rhs) const + bool operator!=(const edge_iterator &rhs) const { return !(*this == rhs); } - friend void swap(edge_iterator &rhs, edge_iterator &lhs) + friend void swap(edge_iterator &rhs, edge_iterator &lhs) { if (lhs != rhs) { + std::swap(lhs.tree, rhs.tree); + std::swap(lhs.k, rhs.k); + std::swap(lhs._ptr, rhs._ptr); - std::swap(lhs.k_t, rhs.k_t); - std::swap(lhs.k_l, rhs.k_l); - std::swap(lhs.k_t_rank, rhs.k_t_rank); std::swap(lhs.size, rhs.size); std::swap(lhs._node, rhs._node); std::swap(lhs._level, rhs._level); @@ -88,7 +85,7 @@ namespace sdsl } } - edge_iterator &operator++() + edge_iterator &operator++() { if (st.valid) { @@ -113,45 +110,17 @@ namespace sdsl _ptr = new edge(std::get<0>(e), std::get<1>(e)); return *this; } - edge_iterator &operator++(int) + edge_iterator &operator++(int) { - edge_iterator *tmp; - tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); + edge_iterator *tmp; + tmp = new edge_iterator(this->tree); operator++(); return *tmp; } - // edge_iterator &operator--() - // { - // if (!equal_edge(*_ptr, *first_edge)) - // { - // _col--; - // if (_col >= 0) - // { - // _col = k - 1; - // _row = _row >= k ? 0 : (_row-1); - // } - // edge e = _find_prev(); - // _ptr = new edge(std::get<0>(e), std::get<1>(e)); - // } - // return *this; - // } - // edge_iterator &operator--(int) - // { - // edge_iterator *tmp; - // tmp = new edge_iterator(*(this->k_t), *(this->k_l), *(this->k_t_rank), this->k_height); - // operator--(); - // return *tmp; - // } - - ~edge_iterator() - { - // if(_ptr != NULL) delete _ptr; - } - - edge_iterator end() + edge_iterator end() { - edge_iterator it = *this; + edge_iterator it = *this; it._ptr = new edge(size, size); //end node it._node = size - 1; @@ -162,62 +131,17 @@ namespace sdsl return it; } - friend ostream &operator<<(ostream &os, const edge_iterator &edg) + private: + bool equal_edge(const edge &e1, const edge &e2) const { - os << " ==== ktree Edge Iterator ==== " << endl; - edge e = *edg._ptr; - if (get<0>(e) == edg.size && get<1>(e) == edg.size) - { - os << " END NODE" << endl; - // os << " ============================= " << endl; - // return os; - } - - os << " ptr (" << get<0>(e) << ", " << get<1>(e) << ")" << endl; - os << " CONTAINER " << endl; - os << " k_t "; - if (edg.k_t != NULL) - { - for (uint i = 0; i < edg.k_t->size(); i++) - os << (*edg.k_t)[i]; - os << endl; - } - else - { - os << "null" << endl; - } - os << " k_l "; - if (edg.k_l != NULL) - { - for (uint i = 0; i < edg.k_l->size(); i++) - os << (*edg.k_l)[i]; - os << endl; - } - else - { - os << "null" << endl; - } - os << " k_height " << edg.k_height << endl; - os << " STATE " << endl; - os << " size " << edg.size << endl; - os << " _n " << edg._n << endl; - os << " _node " << edg._node << endl; - os << " _level " << edg._level << endl; - os << " _row " << edg._row << endl; - os << " _col " << edg._col << endl; - os << " ============================= " << endl; - return os; - } + idx_type e1_x = std::get<0>(e1); + idx_type e1_y = std::get<1>(e1); - protected: - pointer _ptr = NULL; + idx_type e2_x = std::get<0>(e2); + idx_type e2_y = std::get<1>(e2); - // container - const t_bv *k_t = NULL; - const t_bv *k_l = NULL; - const t_rank *k_t_rank = NULL; - uint16_t k_height; - // + return e1_x == e2_x && e1_y == e2_y; + } typedef struct state { @@ -244,20 +168,19 @@ namespace sdsl idx_type _node, _level; unsigned _col; int _row; - // size_t last_neigh; //marks if there are still other children at the leaf to search // void _initialize() { - _n = static_cast(std::pow(k, k_height)) / k; + _n = static_cast(std::pow(k, tree->height())) / k; _node = 0; _row = 0; _col = 0; _level = k * std::floor(_node / static_cast(_n)); - size = std::pow(k, k_height); + size = std::pow(k, tree->height()); - if (k_l->size() > 0) + if (tree->l().size() > 0) { edge first = _find_next(); _ptr = new edge(std::get<0>(first), std::get<1>(first)); @@ -295,6 +218,7 @@ namespace sdsl edge _find_next() { idx_type neigh; + if (_node < size) { for (; _row < k; _row++) @@ -319,9 +243,9 @@ namespace sdsl bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned initial_j) { - if (level >= k_t->size()) // Last level + if (level >= tree->t().size()) // Last level { - if ((*k_l)[level - k_t->size()] == 1) + if (tree->l()[level - tree->t().size()] == 1) { neigh = col; return true; @@ -329,9 +253,9 @@ namespace sdsl return false; } - if ((*k_t)[level] == 1) + if (tree->t()[level] == 1) { - size_type y = (*k_t_rank)(level + 1) * k * k + + size_type y = tree->rank_t()(level + 1) * k * k + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) @@ -347,69 +271,11 @@ namespace sdsl return false; } - // bool _find_prev_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned &col_state, unsigned initial_j) - // { - // if (level >= k_t->size()) // Last level - // { - // if ((*k_l)[level - k_t->size()] == 1) - // { - // neigh = col; - // return true; - // } - // return false; - // } - - // if ((*k_t)[level] == 1 && n > 0) - // { - // size_type y = (*k_t_rank)(level + 1) * std::pow(k, 2) + - // k * std::floor(row / static_cast(n)); - // for (int j = initial_j; j >= 0; j--) { - // if (_find_prev_recursive(n / k, row % n, col + n * j, y + j, neigh, col_state, k-1)) - // { - // col_state = j; - // return true; - // } - // } - // } - // return false; - // } - // value_type _find_prev() - // { - // idx_type neigh; - // if (_node >= 0) - // { - // for (; _row >= 0; _row--) - // { - // neigh = size; - // _find_prev_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col, _col); - // if (neigh < size) - // { - // // cout << "x: " << _node << " y: " << neigh << endl; - // return edge(_node, neigh); - // } - // } - // _row = k - 1; - // _col = k - 1; - // _node--; - // _level = k * std::floor(_node / static_cast(_n)); - - // return _find_prev(); - // } else { - // return *first_edge; - // } - // } - - private: - bool equal_edge(const edge &e1, const edge &e2) const - { - idx_type e1_x = std::get<0>(e1); - idx_type e1_y = std::get<1>(e1); - - idx_type e2_x = std::get<0>(e2); - idx_type e2_y = std::get<1>(e2); - - return e1_x == e2_x && e1_y == e2_y; - } + pointer _ptr = NULL; + // container + const k_tree *tree = NULL; + uint8_t k = 2; + // }; template diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index f2e433ec8..d1f37eab2 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -34,24 +34,24 @@ template void check_t_l(t_tree &tree, vector expected_t, vector expected_l) { - ASSERT_EQ(expected_t.size(), tree.get_t().size()); - ASSERT_EQ(expected_l.size(), tree.get_l().size()); + ASSERT_EQ(expected_t.size(), tree.t().size()); + ASSERT_EQ(expected_l.size(), tree.l().size()); for (unsigned i = 0; i < expected_t.size(); i++) - ASSERT_EQ(expected_t[i], tree.get_t().get_int(i, 1)); + ASSERT_EQ(expected_t[i], tree.t().get_int(i, 1)); for (unsigned i = 0; i < expected_l.size(); i++) - ASSERT_EQ(expected_l[i], tree.get_l().get_int(i, 1)); + ASSERT_EQ(expected_l[i], tree.l().get_int(i, 1)); } template void assert_eq_tree(t_tree &tree1, t_tree &tree2) { - ASSERT_EQ(tree1.get_t().size(), tree2.get_t().size()); - ASSERT_EQ(tree1.get_l().size(), tree2.get_l().size()); - for (unsigned i = 0; i < tree1.get_t().size(); i++) - ASSERT_EQ(tree1.get_t().get_int(i, 1), tree2.get_t().get_int(i, 1)); + ASSERT_EQ(tree1.t().size(), tree2.t().size()); + ASSERT_EQ(tree1.l().size(), tree2.l().size()); + for (unsigned i = 0; i < tree1.t().size(); i++) + ASSERT_EQ(tree1.t().get_int(i, 1), tree2.t().get_int(i, 1)); - for (unsigned i = 0; i < tree1.get_l().size(); i++) - ASSERT_EQ(tree1.get_l().get_int(i, 1), tree2.get_l().get_int(i, 1)); + for (unsigned i = 0; i < tree1.l().size(); i++) + ASSERT_EQ(tree1.l().get_int(i, 1), tree2.l().get_int(i, 1)); } template @@ -116,8 +116,8 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) mat = vector>({{0, 0}, {0, 0}}); tree = TypeParam(mat); - ASSERT_TRUE(tree.get_t().empty()); - ASSERT_TRUE(tree.get_l().empty()); + ASSERT_TRUE(tree.t().empty()); + ASSERT_TRUE(tree.l().empty()); // Size is minor than k: mat = vector>({{0}}); @@ -405,7 +405,7 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { TypeParam empty_tree; - ASSERT_TRUE(empty_tree.node_begin() == empty_tree.node_end()); + ASSERT_EQ(empty_tree.node_begin(), empty_tree.node_end()); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); @@ -421,7 +421,7 @@ TYPED_TEST(k2_tree_test_k_3, build_from_matrix_test) TypeParam tree(mat); // cout << "ALGORIOTHM" << endl; - // cout << all_of(tree.get_l().begin(), tree.get_l().end(), [](int i) { return i % 2 == 0; }) << endl; + // cout << all_of(tree.l().begin(), tree.l().end(), [](int i) { return i % 2 == 0; }) << endl; vector expected_t = {1, 1, 0, 1, 1, 0, 0, 0, 0}; vector expected_l = {1, 1, 0, 0, 1, 0, 0, 0, 1, From 18d4498b0404d5fcbe8f48f8790bd98c76e168e6 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 21 Jun 2020 20:45:33 +0100 Subject: [PATCH 28/57] Add vertices attribute to k2tree --- include/sdsl/k2_tree.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 1697ca489..ee31f9a54 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -72,6 +72,7 @@ class k2_tree uint16_t k_height = 0; uint16_t n_marked_edges = 0; + size_t n_vertices = 0; edg_iterator edge_it; edg_iterator edge_it_end; @@ -79,6 +80,7 @@ class k2_tree nod_iterator node_it; nod_iterator node_it_end; + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -326,6 +328,7 @@ class k2_tree k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); + this->n_vertices = matrix.size(); } //! Constructor @@ -344,6 +347,7 @@ class k2_tree assert(edges.size() > 0); build_from_edges(edges, size); + this->n_vertices = size; } //! Constructor @@ -387,6 +391,7 @@ class k2_tree build_from_edges(edges, size); edge_it = edg_iterator(this); edge_it_end = edge_it.end(); + n_vertices = edges.size(); } k2_tree(k2_tree &tr) @@ -548,6 +553,7 @@ class k2_tree k_l_rank = l_rank(&k_l); edge_it = std::move(tr.edge_it); edge_it_end = std::move(tr.edge_it_end); + n_vertices = std::move(tr.n_vertices); } return *this; } @@ -565,6 +571,8 @@ class k2_tree k_l_rank = l_rank(&k_l); edge_it = tr.edge_it; edge_it_end = tr.edge_it_end; + n_vertices = tr.n_vertices; + } return *this; } @@ -580,8 +588,7 @@ class k2_tree util::swap_support(k_l_rank, tr.k_l_rank, &k_l, &(tr.k_l)); std::swap(k_k, tr.k_k); std::swap(k_height, tr.k_height); - std::swap(tr.edge_it); - std::swap(tr.edge_it_end); + std::swap(n_vertices, tr.n_vertices); } } From ce81fc551e54c77a1a825cbab1d83916d2f6fd88 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 25 Jun 2020 01:08:08 +0100 Subject: [PATCH 29/57] Clean memory leaks --- .gitignore | 4 +- include/sdsl/k2_tree.hpp | 14 +- include/sdsl/k2_tree_iterator.hpp | 214 +++++++++++++----------------- test/k2_tree_test.cpp | 10 +- 4 files changed, 108 insertions(+), 134 deletions(-) diff --git a/.gitignore b/.gitignore index 5bf21f149..3d96a4691 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ Make.helper .vscode .idea/* -cmake-build-debug/ \ No newline at end of file +cmake-build-debug/ +CMakeModules/* +*/.idea/* diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index ee31f9a54..13924dc22 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -392,6 +392,8 @@ class k2_tree edge_it = edg_iterator(this); edge_it_end = edge_it.end(); n_vertices = edges.size(); + node_it = nod_iterator(this); + node_it_end = node_it.end(); } k2_tree(k2_tree &tr) @@ -412,6 +414,8 @@ class k2_tree k_l_rank = l_rank(&k_l); edge_it = edg_iterator(this); edge_it_end = edge_it.end(); + node_it = nod_iterator(this); + node_it_end = node_it.end(); } t_bv t() const @@ -553,6 +557,8 @@ class k2_tree k_l_rank = l_rank(&k_l); edge_it = std::move(tr.edge_it); edge_it_end = std::move(tr.edge_it_end); + node_it = std::move(tr.node_it); + node_it_end = std::move(tr.node_it_end); n_vertices = std::move(tr.n_vertices); } return *this; @@ -571,6 +577,8 @@ class k2_tree k_l_rank = l_rank(&k_l); edge_it = tr.edge_it; edge_it_end = tr.edge_it_end; + node_it = tr.node_it; + node_it_end = tr.node_it_end; n_vertices = tr.n_vertices; } @@ -850,19 +858,19 @@ class k2_tree return edge_it; } - edg_iterator &edge_end() + edg_iterator &edge_end() { edge_it_end = edge_it.end(); return edge_it_end; } - nod_iterator &node_begin() + nod_iterator node_begin() { node_it = nod_iterator(this); return node_it; } - nod_iterator &node_end() + nod_iterator node_end() { node_it_end = node_it.end(); return node_it_end; diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 289c5b171..425f23e10 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -4,44 +4,40 @@ #include #include #include +#include #include using namespace std; -namespace sdsl -{ +namespace sdsl { - template - class edge_iterator - { + template + class edge_iterator { using idx_type = k2_tree_ns::idx_type; using size_type = k2_tree_ns::size_type; using edge = std::tuple; public: using value_type = edge; - using pointer = edge *; + using pointer = shared_ptr; using reference = edge &; using iterator_category = std::forward_iterator_tag; edge_iterator() {} - edge_iterator(const k_tree *tree) - { + + edge_iterator(const k_tree *tree) { this->tree = tree; this->k = tree->k_(); _initialize(); } - value_type operator*() - { + value_type operator*() { return *_ptr; } - edge_iterator &operator=(const edge_iterator &other) - { - if (this != &other) - { + edge_iterator &operator=(const edge_iterator &other) { + if (this != &other) { this->tree = other.tree; this->k = other.k; @@ -56,23 +52,20 @@ namespace sdsl return *this; } - bool operator==(const edge_iterator &rhs) const - { - if (rhs._ptr != NULL && this->_ptr != NULL) + bool operator==(const edge_iterator &rhs) const { + if (rhs._ptr != nullptr && this->_ptr != nullptr) return equal_edge(*(rhs._ptr), *(this->_ptr)); - else if (rhs._ptr == NULL && this->_ptr == NULL) + else if (rhs._ptr == nullptr && this->_ptr == nullptr) return true; return false; } - bool operator!=(const edge_iterator &rhs) const - { + + bool operator!=(const edge_iterator &rhs) const { return !(*this == rhs); } - friend void swap(edge_iterator &rhs, edge_iterator &lhs) - { - if (lhs != rhs) - { + friend void swap(edge_iterator &rhs, edge_iterator &lhs) { + if (lhs != rhs) { std::swap(lhs.tree, rhs.tree); std::swap(lhs.k, rhs.k); @@ -85,43 +78,37 @@ namespace sdsl } } - edge_iterator &operator++() - { - if (st.valid) - { + edge_iterator &operator++() { + if (st.valid) { st.j++; - if (st.j < k) - { + if (st.j < k) { edge e; e = _find_next_middle(); - _ptr = new edge(std::get<0>(e), std::get<1>(e)); + _ptr = make_shared(std::get<0>(e), std::get<1>(e)); return *this; } } st.valid = false; _col++; - if (_col >= k) - { + if (_col >= k) { _col = 0; _row++; } edge e; e = _find_next(); - _ptr = new edge(std::get<0>(e), std::get<1>(e)); + _ptr = make_shared(std::get<0>(e), std::get<1>(e)); return *this; } - edge_iterator &operator++(int) - { - edge_iterator *tmp; - tmp = new edge_iterator(this->tree); + + edge_iterator &operator++(int) { + shared_ptr> tmp = make_shared>(this->tree); operator++(); return *tmp; } - edge_iterator end() - { + edge_iterator end() { edge_iterator it = *this; - it._ptr = new edge(size, size); //end node + it._ptr = make_shared(size, size); //end node it._node = size - 1; it._level = k * std::floor(it._node / static_cast(it._n)); @@ -132,8 +119,7 @@ namespace sdsl } private: - bool equal_edge(const edge &e1, const edge &e2) const - { + bool equal_edge(const edge &e1, const edge &e2) const { idx_type e1_x = std::get<0>(e1); idx_type e1_y = std::get<1>(e1); @@ -143,13 +129,12 @@ namespace sdsl return e1_x == e2_x && e1_y == e2_y; } - typedef struct state - { + typedef struct state { unsigned node, row, col, n, level, j, y; bool valid = false; - void set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) - { + void + set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) { node = _node; row = _row; col = _col; @@ -171,8 +156,7 @@ namespace sdsl // void - _initialize() - { + _initialize() { _n = static_cast(std::pow(k, tree->height())) / k; _node = 0; _row = 0; @@ -180,53 +164,41 @@ namespace sdsl _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); - if (tree->l().size() > 0) - { + if (tree->l().size() > 0) { edge first = _find_next(); - _ptr = new edge(std::get<0>(first), std::get<1>(first)); - ; - } - else - { + _ptr = make_shared(std::get<0>(first), std::get<1>(first));; + } else { // if its empty the begin == end - _ptr = new edge(size, size); //end node + _ptr = make_shared(size, size); //end node } } - edge _find_next_middle() - { - if (st.valid) - { + edge _find_next_middle() { + if (st.valid) { idx_type neigh = size; _find_next_recursive(st.n / k, st.row % st.n, st.col + st.n * st.j, st.y + st.j, neigh, st.j); - if (neigh != size) - { + if (neigh != size) { return edge(_node, neigh); } } st.valid = false; _col++; - if (_col >= k) - { + if (_col >= k) { _col = 0; _row++; } return _find_next(); } - edge _find_next() - { + edge _find_next() { idx_type neigh; - if (_node < size) - { - for (; _row < k; _row++) - { + if (_node < size) { + for (; _row < k; _row++) { neigh = size; _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); - if (neigh < size) - { + if (neigh < size) { // cout << "x: " << _node << " y: " << neigh << endl; return edge(_node, neigh); } @@ -241,28 +213,24 @@ namespace sdsl return edge(size, size); // end node } - bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, unsigned initial_j) - { + bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, + unsigned initial_j) { if (level >= tree->t().size()) // Last level { - if (tree->l()[level - tree->t().size()] == 1) - { + if (tree->l()[level - tree->t().size()] == 1) { neigh = col; return true; } return false; } - if (tree->t()[level] == 1) - { + if (tree->t()[level] == 1) { size_type y = tree->rank_t()(level + 1) * k * k + k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) - { + for (unsigned j = initial_j; j < k; j++) { st.set(_node, n, row, col, level, j, y); - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) - { + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) { _col = j; return true; } @@ -271,43 +239,39 @@ namespace sdsl return false; } - pointer _ptr = NULL; + pointer _ptr; // container - const k_tree *tree = NULL; + const k_tree *tree; uint8_t k = 2; // }; - template - class node_iterator - { + template + class node_iterator { using node_type = k2_tree_ns::idx_type; using size_type = k2_tree_ns::size_type; public: using value_type = node_type; - using pointer = node_type *; + using pointer = shared_ptr; using reference = node_type &; using iterator_category = std::forward_iterator_tag; node_iterator() {} - node_iterator(const k2_tree *k_tree) - { + + node_iterator(const k2_tree *k_tree) { this->tree = k_tree; - for (value_type i = 0; i < tree->get_number_nodes(); i++) - { + for (value_type i = 0; i < tree->get_number_nodes(); i++) { for (value_type j = i; j < tree->get_number_nodes(); j++) - if (tree->adj(i, j)) - { - _ptr = &i; + if (tree->adj(i, j)) { + _ptr = make_shared(i); curr_i = i; curr_j = j; return; } for (value_type j = i; j < tree->get_number_nodes(); j++) - if (tree->adj(j, i)) - { - _ptr = &i; + if (tree->adj(j, i)) { + _ptr = make_shared(i); curr_i = i + 1; curr_j = i; return; @@ -315,8 +279,7 @@ namespace sdsl } } - node_iterator(node_iterator *other) - { + node_iterator(node_iterator *other) { this->_ptr = other->_ptr; this->tree = other->tree; this->curr_i = other->curr_i; @@ -325,34 +288,38 @@ namespace sdsl ~node_iterator() {} - value_type operator*() const - { + value_type operator*() const { return *_ptr; } - bool operator==(const node_iterator &rhs) const - { - if (rhs._ptr != NULL && this->_ptr != NULL) + node_iterator &operator=(const node_iterator &other) { + if (this != &other) { + this->tree = other.tree; + this->_ptr = other._ptr; + this->curr_i = other.curr_i; + this->curr_j = other.curr_j; + } + return *this; + } + + bool operator==(const node_iterator &rhs) const { + if (rhs._ptr != nullptr && this->_ptr != nullptr) return rhs._ptr == this->_ptr; - else if (rhs._ptr == NULL && this->_ptr == NULL) + else if (rhs._ptr == nullptr && this->_ptr == nullptr) return true; return false; } - bool operator!=(const node_iterator &rhs) const - { + bool operator!=(const node_iterator &rhs) const { return !(*this == rhs); } - node_iterator &operator++() - { - for (value_type i = curr_i; i < tree->get_number_nodes(); i++) - { + node_iterator &operator++() { + for (value_type i = curr_i; i < tree->get_number_nodes(); i++) { for (value_type j = curr_j; j < tree->get_number_nodes(); j++) if (tree->adj(i, j)) return update_state(i); - for (value_type j = 0; j < tree->get_number_nodes(); j++) - { + for (value_type j = 0; j < tree->get_number_nodes(); j++) { if (j == i) continue; if (tree->adj(j, i)) @@ -363,10 +330,8 @@ namespace sdsl return *this; } - node_iterator &operator++(int) - { - node_iterator *tmp; - tmp = new node_iterator(this); + node_iterator &operator++(int) { + shared_ptr> tmp = make_shared>(this); operator++(); return *tmp; } @@ -382,21 +347,21 @@ namespace sdsl return it; } - friend void swap(node_iterator &rhs, node_iterator &lhs) - { + friend void swap(node_iterator &rhs, node_iterator &lhs) { + std::cout << "one " << *rhs._ptr << " second " << *lhs._ptr << std::endl; std::swap(rhs._ptr, lhs._ptr); + std::cout << "one " << *rhs._ptr << " second " << *lhs._ptr << std::endl; std::swap(rhs.tree, lhs.tree); std::swap(rhs.curr_i, lhs.curr_i); std::swap(rhs.curr_j, lhs.curr_j); } private: - pointer _ptr = NULL; + pointer _ptr = nullptr; const k2_tree *tree = NULL; value_type curr_i, curr_j; - node_iterator &update_state(int i) - { + node_iterator &update_state(node_type i) { *_ptr = i; curr_i = i + 1; curr_j = 0; @@ -404,7 +369,6 @@ namespace sdsl return *this; } }; // namespace sdsl - } // namespace sdsl #endif \ No newline at end of file diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index d1f37eab2..a95e5e238 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -278,14 +278,14 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) auto edge_iterator = tree.edge_begin(); ASSERT_EQ(std::get<0>(*edge_iterator), (size_t)0); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t)0); - + // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; ASSERT_EQ(std::get<0>(*another_edge_iterator), (size_t) 0); ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 0); // //OPERATOR INCREMENT - // // ++edge_iterator; // also works + // // ++edge_iterator; // also works edge_iterator++; ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 0); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 1); @@ -296,7 +296,7 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 3); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); edge_iterator++; - + //find last auto last = tree.edge_end(); ASSERT_EQ(std::get<0>(*last), tree.get_number_nodes()); @@ -384,7 +384,7 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { TypeParam tree(mat); auto node_iterator = tree.node_begin(); ASSERT_EQ(*node_iterator, (size_t)0); - + node_iterator++; ASSERT_EQ(*node_iterator, (size_t)1); @@ -399,8 +399,8 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { auto other_iterator = tree.node_begin(); swap(other_iterator, node_iterator); - ASSERT_EQ(*other_iterator, *tree.node_end()); ASSERT_EQ(*node_iterator, *tree.node_begin()); + ASSERT_EQ(*other_iterator, *tree.node_end()); } TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { From b81973927f6d21ef7cb49a31ceb30193ca3e04a5 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 8 Jul 2020 22:49:15 +0100 Subject: [PATCH 30/57] Add neighbour iterator (get neighbour lazy) --- include/sdsl/k2_tree.hpp | 14 ++ include/sdsl/k2_tree_iterator.hpp | 216 ++++++++++++++++++++++++++---- test/k2_tree_test.cpp | 31 +++++ 3 files changed, 238 insertions(+), 23 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 13924dc22..3e8bedfcb 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -57,6 +57,7 @@ class k2_tree typedef k2_tree_ns::size_type size_type; using edg_iterator = edge_iterator>; using nod_iterator = node_iterator>; + using neigh_iterator = neighbour_iterator>; protected: //! Bit array to store all the bits of the tree, except those in the @@ -80,6 +81,9 @@ class k2_tree nod_iterator node_it; nod_iterator node_it_end; + neigh_iterator neighbour_it; + neigh_iterator neighbour_it_end; + void build_from_matrix(const std::vector> &matrix) { @@ -875,6 +879,16 @@ class k2_tree node_it_end = node_it.end(); return node_it_end; } + + neigh_iterator neighbour_begin(idx_type node) { + neighbour_it = neigh_iterator(this, node); + return neighbour_it; + } + + neigh_iterator neighbour_end() { + neighbour_it_end = neighbour_it.end(); + return neighbour_it_end; + } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 425f23e10..0a4dadbaf 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -12,6 +12,23 @@ using namespace std; namespace sdsl { + typedef struct state { + unsigned node, row, col, n, level, j, y; + bool valid = false; + + void + set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) { + node = _node; + row = _row; + col = _col; + n = _n; + level = _level; + j = _j; + y = _y; + valid = true; + } + } state; + template class edge_iterator { using idx_type = k2_tree_ns::idx_type; @@ -129,22 +146,6 @@ namespace sdsl { return e1_x == e2_x && e1_y == e2_y; } - typedef struct state { - unsigned node, row, col, n, level, j, y; - bool valid = false; - - void - set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) { - node = _node; - row = _row; - col = _col; - n = _n; - level = _level; - j = _j; - y = _y; - valid = true; - } - } state; // iterator state // state st; @@ -166,7 +167,7 @@ namespace sdsl { if (tree->l().size() > 0) { edge first = _find_next(); - _ptr = make_shared(std::get<0>(first), std::get<1>(first));; + _ptr = make_shared(std::get<0>(first), std::get<1>(first)); } else { // if its empty the begin == end _ptr = make_shared(size, size); //end node @@ -336,9 +337,8 @@ namespace sdsl { return *tmp; } - node_iterator end() - { - if(tree == NULL) return *this; + node_iterator end() { + if (tree == NULL) return *this; node_iterator it = *this; value_type num_nodes = it.tree->get_number_nodes(); *(it._ptr) = it.tree->get_number_nodes(); //end node @@ -348,9 +348,7 @@ namespace sdsl { } friend void swap(node_iterator &rhs, node_iterator &lhs) { - std::cout << "one " << *rhs._ptr << " second " << *lhs._ptr << std::endl; std::swap(rhs._ptr, lhs._ptr); - std::cout << "one " << *rhs._ptr << " second " << *lhs._ptr << std::endl; std::swap(rhs.tree, lhs.tree); std::swap(rhs.curr_i, lhs.curr_i); std::swap(rhs.curr_j, lhs.curr_j); @@ -368,7 +366,179 @@ namespace sdsl { return *this; } - }; // namespace sdsl + }; + + template + class neighbour_iterator { + using idx_type = k2_tree_ns::idx_type; + using size_type = k2_tree_ns::size_type; + + public: + using value_type = int; + using pointer = shared_ptr; + using reference = int &; + using iterator_category = std::forward_iterator_tag; + + neighbour_iterator() {} + + neighbour_iterator(const k_tree *tree, value_type node) { + this->tree = tree; + this->k = tree->k_(); + this->_node = node; + _initialize(); + } + + value_type operator*() { + return *_ptr; + } + + neighbour_iterator &operator++() { + _col++; + if (_col >= k) { + _col = 0; + _row++; + } + value_type next_neigh; + next_neigh = _find_next(); + _ptr = make_shared(next_neigh); + + if(*_ptr == size) + *_ptr = -1; + return *this; + } + + neighbour_iterator &operator++(int) { + shared_ptr> tmp = make_shared>(this->tree, _node); + operator++(); + return *tmp; + } + + bool operator==(const neighbour_iterator &rhs) const { + if (rhs._ptr != nullptr && this->_ptr != nullptr) + return rhs._ptr == this->_ptr; + else if (rhs._ptr == nullptr && this->_ptr == nullptr) + return true; + return false; + } + + bool operator!=(const neighbour_iterator &rhs) const { + return !(*this == rhs); + } + + neighbour_iterator end() { + neighbour_iterator it = *this; + + value_type aux = -1; + if(it._ptr != nullptr) + *(it._ptr) = aux; //end node + else + it._ptr = make_shared(aux); + + it._level = k * std::floor(it._node / static_cast(it._n)); + it._row = k; + it._col = k; + + return it; + } + + neighbour_iterator &operator=(const neighbour_iterator &other) { + if (this != &other) { + this->_ptr = other._ptr; + this->tree = other.tree; + this->k = other.k; + + this->size = other.size; + this->_n = other._n; + this->_node = other._node; + this->_level = other._level; + this->_col = other._col; + this->_row = other._row; + this->_n = other._n; + } + return *this; + } + + friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { + std::swap(rhs._ptr, lhs._ptr); + std::swap(rhs.tree, lhs.tree); + std::swap(rhs.k, lhs.k); + + std::swap(rhs.size, lhs.size); + std::swap(rhs._n, lhs._n); + std::swap(rhs._node, lhs._node); + std::swap(rhs._level, lhs._level); + std::swap(rhs._col, lhs._col); + std::swap(rhs._row, lhs._row); + std::swap(rhs._n, lhs._n); + } + + private: + + void _initialize() { + _n = static_cast(std::pow(k, tree->height())) / k; + _row = 0; + _col = 0; + _level = k * std::floor(_node / static_cast(_n)); + size = std::pow(k, tree->height()); + + if (tree->l().size() > 0) { + value_type first_neighbour = _find_next(); + _ptr = make_shared(first_neighbour); + } else { + // if its empty the begin == end + _ptr = make_shared(-1); //end node + } + } + + bool _find_next_recursive(size_type n, value_type row, value_type col, size_type level, value_type &neigh, + unsigned initial_j) { + if (level >= tree->t().size()) // Last level + { + if (tree->l()[level - tree->t().size()] == 1) { + neigh = col; + return true; + } + return false; + } + + if (tree->t()[level] == 1) { + size_type y = tree->rank_t()(level + 1) * k * k + + k * std::floor(row / static_cast(n)); + + for (unsigned j = initial_j; j < k; j++) { + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) { + _col = j; + return true; + } + } + } + return false; + } + + value_type _find_next() { + value_type neigh; + for (; _row < k; _row++) { + neigh = size; + _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); + if (neigh < size) { + return neigh; + } + } + return -1; + } + + pointer _ptr ; + const k_tree *tree; + uint8_t k = 2; + + // iterator state // + value_type size; + size_type _n; + idx_type _node, _level; + unsigned _col; + int _row; + // + }; } // namespace sdsl #endif \ No newline at end of file diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index a95e5e238..a98f4f535 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -403,6 +403,37 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { ASSERT_EQ(*other_iterator, *tree.node_end()); } +TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { + vector> mat({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 1, 0}}); + TypeParam tree(mat); + auto neighbour_iterator = tree.neighbour_begin(2); + ASSERT_EQ(*neighbour_iterator, (size_t)2); + + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + + neighbour_iterator = tree.neighbour_begin(3); + ASSERT_EQ(*neighbour_iterator, (size_t)0); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, (size_t)1); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, (size_t)2); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + + auto other_iterator = tree.neighbour_begin(2); + swap(other_iterator, neighbour_iterator); + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_begin(2)); + ASSERT_EQ(*other_iterator, *tree.neighbour_end()); + + ASSERT_EQ(*tree.neighbour_begin(0), *tree.neighbour_end()); + } + TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { TypeParam empty_tree; ASSERT_EQ(empty_tree.node_begin(), empty_tree.node_end()); From c1d66de5cf581f3a1f2436bf249d02ac0a7386d9 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sun, 12 Jul 2020 00:34:32 +0100 Subject: [PATCH 31/57] Fix iterators --- include/sdsl/k2_tree.hpp | 48 +----- include/sdsl/k2_tree_iterator.hpp | 255 ++++++++++++++---------------- test/k2_tree_test.cpp | 14 +- 3 files changed, 138 insertions(+), 179 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 3e8bedfcb..3571fabee 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -75,16 +75,6 @@ class k2_tree uint16_t n_marked_edges = 0; size_t n_vertices = 0; - edg_iterator edge_it; - edg_iterator edge_it_end; - - nod_iterator node_it; - nod_iterator node_it_end; - - neigh_iterator neighbour_it; - neigh_iterator neighbour_it_end; - - void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -393,11 +383,7 @@ class k2_tree std::tuple{buf_x[i], buf_y[i]}); build_from_edges(edges, size); - edge_it = edg_iterator(this); - edge_it_end = edge_it.end(); n_vertices = edges.size(); - node_it = nod_iterator(this); - node_it_end = node_it.end(); } k2_tree(k2_tree &tr) @@ -416,10 +402,6 @@ class k2_tree k_l = std::move(l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - edge_it = edg_iterator(this); - edge_it_end = edge_it.end(); - node_it = nod_iterator(this); - node_it_end = node_it.end(); } t_bv t() const @@ -559,10 +541,6 @@ class k2_tree k_height = std::move(tr.k_height); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - edge_it = std::move(tr.edge_it); - edge_it_end = std::move(tr.edge_it_end); - node_it = std::move(tr.node_it); - node_it_end = std::move(tr.node_it_end); n_vertices = std::move(tr.n_vertices); } return *this; @@ -579,10 +557,6 @@ class k2_tree k_height = tr.k_height; k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - edge_it = tr.edge_it; - edge_it_end = tr.edge_it_end; - node_it = tr.node_it; - node_it_end = tr.node_it_end; n_vertices = tr.n_vertices; } @@ -856,38 +830,32 @@ class k2_tree return false; } - edg_iterator &edge_begin() + edg_iterator edge_begin() { - edge_it = edg_iterator(this); - return edge_it; + return edg_iterator(this); } - edg_iterator &edge_end() + edg_iterator edge_end() { - edge_it_end = edge_it.end(); - return edge_it_end; + return edg_iterator(this).end(); } nod_iterator node_begin() { - node_it = nod_iterator(this); - return node_it; + return nod_iterator(this); } nod_iterator node_end() { - node_it_end = node_it.end(); - return node_it_end; + return nod_iterator(this).end(); } neigh_iterator neighbour_begin(idx_type node) { - neighbour_it = neigh_iterator(this, node); - return neighbour_it; + return neigh_iterator(this, node); } neigh_iterator neighbour_end() { - neighbour_it_end = neighbour_it.end(); - return neighbour_it_end; + return neigh_iterator(this, n_vertices-1).end(); } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 0a4dadbaf..499950b9a 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -50,59 +50,53 @@ namespace sdsl { } value_type operator*() { - return *_ptr; - } - - edge_iterator &operator=(const edge_iterator &other) { - if (this != &other) { - this->tree = other.tree; - this->k = other.k; - - this->_ptr = other._ptr; - this->size = other.size; - this->_n = other._n; - this->_node = other._node; - this->_level = other._level; - this->_row = other._row; - this->_col = other._col; - } - return *this; + return _ptr; } bool operator==(const edge_iterator &rhs) const { - if (rhs._ptr != nullptr && this->_ptr != nullptr) - return equal_edge(*(rhs._ptr), *(this->_ptr)); - else if (rhs._ptr == nullptr && this->_ptr == nullptr) - return true; - return false; + return equal_edge(rhs._ptr, _ptr); } bool operator!=(const edge_iterator &rhs) const { return !(*this == rhs); } - friend void swap(edge_iterator &rhs, edge_iterator &lhs) { - if (lhs != rhs) { - std::swap(lhs.tree, rhs.tree); - std::swap(lhs.k, rhs.k); - - std::swap(lhs._ptr, rhs._ptr); - std::swap(lhs.size, rhs.size); - std::swap(lhs._node, rhs._node); - std::swap(lhs._level, rhs._level); - std::swap(lhs._row, rhs._row); - std::swap(lhs._col, rhs._col); - } + void print() { + cout << "_ptr "<< std::get<0>(_ptr) << ", " << std::get<1>(_ptr) << endl; + cout << "_node " << _node << endl; + cout << "_level " << _level << endl; + cout << "_row " << _row << endl; + cout << "_col " << _col << endl; + cout << "st " << endl; + + cout << " node: " << st.node << endl; + cout << " row: " << st.row << endl; + cout << " col: " << st.col << endl; + cout << " n: " << st.n << endl; + cout << " level: " << st.level << endl; + cout << " j: " << st.j << endl; + cout << " y: " << st.y << endl; + cout << " valid: " << st.valid << endl; + cout << endl; + } + + edge_iterator &operator++(int) { + edge prev = _ptr; + operator++(); + if (equal_edge(prev, _ptr)) + operator++(); + return *this; } edge_iterator &operator++() { if (st.valid) { - st.j++; - if (st.j < k) { + st.j = st.j + 1; + if(st.j < k) { edge e; e = _find_next_middle(); - _ptr = make_shared(std::get<0>(e), std::get<1>(e)); + _ptr = e; return *this; + } } st.valid = false; @@ -113,19 +107,15 @@ namespace sdsl { } edge e; e = _find_next(); - _ptr = make_shared(std::get<0>(e), std::get<1>(e)); + _ptr = e; + return *this; } - edge_iterator &operator++(int) { - shared_ptr> tmp = make_shared>(this->tree); - operator++(); - return *tmp; - } edge_iterator end() { edge_iterator it = *this; - it._ptr = make_shared(size, size); //end node + it._ptr = edge(size, size); //end node it._node = size - 1; it._level = k * std::floor(it._node / static_cast(it._n)); @@ -135,6 +125,20 @@ namespace sdsl { return it; } + friend void swap(edge_iterator &rhs, edge_iterator &lhs) { + if(&rhs != &lhs) { + std::swap(rhs.tree, lhs.tree); + std::swap(rhs.k, lhs.k); + + std::swap(rhs._ptr, lhs._ptr); + std::swap(rhs.size, lhs.size); + std::swap(rhs._node, lhs._node); + std::swap(rhs._level, lhs._level); + std::swap(rhs._row, lhs._row); + std::swap(rhs._col, lhs._col); + } + } + private: bool equal_edge(const edge &e1, const edge &e2) const { idx_type e1_x = std::get<0>(e1); @@ -146,7 +150,11 @@ namespace sdsl { return e1_x == e2_x && e1_y == e2_y; } - + value_type _ptr; + // container + const k_tree *tree; + uint8_t k = 2; + // // iterator state // state st; size_t size; @@ -167,10 +175,10 @@ namespace sdsl { if (tree->l().size() > 0) { edge first = _find_next(); - _ptr = make_shared(std::get<0>(first), std::get<1>(first)); + _ptr = edge(std::get<0>(first), std::get<1>(first)); } else { // if its empty the begin == end - _ptr = make_shared(size, size); //end node + _ptr = edge(size, size); //end node } } @@ -239,12 +247,6 @@ namespace sdsl { } return false; } - - pointer _ptr; - // container - const k_tree *tree; - uint8_t k = 2; - // }; template @@ -262,17 +264,26 @@ namespace sdsl { node_iterator(const k2_tree *k_tree) { this->tree = k_tree; + + if(tree->get_number_edges() == 0) { + value_type num_nodes = tree->get_number_nodes(); + _ptr = num_nodes; + curr_i = num_nodes; + curr_j = num_nodes; + return; + } + for (value_type i = 0; i < tree->get_number_nodes(); i++) { for (value_type j = i; j < tree->get_number_nodes(); j++) if (tree->adj(i, j)) { - _ptr = make_shared(i); + _ptr = i; curr_i = i; curr_j = j; return; } for (value_type j = i; j < tree->get_number_nodes(); j++) if (tree->adj(j, i)) { - _ptr = make_shared(i); + _ptr = i; curr_i = i + 1; curr_j = i; return; @@ -290,25 +301,21 @@ namespace sdsl { ~node_iterator() {} value_type operator*() const { - return *_ptr; + return _ptr; } node_iterator &operator=(const node_iterator &other) { if (this != &other) { - this->tree = other.tree; - this->_ptr = other._ptr; - this->curr_i = other.curr_i; - this->curr_j = other.curr_j; + tree = other.tree; + _ptr = other._ptr; + curr_i = other.curr_i; + curr_j = other.curr_j; } return *this; } bool operator==(const node_iterator &rhs) const { - if (rhs._ptr != nullptr && this->_ptr != nullptr) - return rhs._ptr == this->_ptr; - else if (rhs._ptr == nullptr && this->_ptr == nullptr) - return true; - return false; + return rhs._ptr == _ptr; } bool operator!=(const node_iterator &rhs) const { @@ -332,35 +339,33 @@ namespace sdsl { } node_iterator &operator++(int) { - shared_ptr> tmp = make_shared>(this); + if(_ptr == tree->get_number_nodes()-1) { + *this = end(); + return *this; + } + value_type prev = _ptr; operator++(); - return *tmp; + if(_ptr == prev) this->end(); + return *this; } node_iterator end() { if (tree == NULL) return *this; node_iterator it = *this; value_type num_nodes = it.tree->get_number_nodes(); - *(it._ptr) = it.tree->get_number_nodes(); //end node + it._ptr = num_nodes; //end node it.curr_i = num_nodes; it.curr_j = num_nodes; return it; } - friend void swap(node_iterator &rhs, node_iterator &lhs) { - std::swap(rhs._ptr, lhs._ptr); - std::swap(rhs.tree, lhs.tree); - std::swap(rhs.curr_i, lhs.curr_i); - std::swap(rhs.curr_j, lhs.curr_j); - } - private: - pointer _ptr = nullptr; + value_type _ptr; const k2_tree *tree = NULL; value_type curr_i, curr_j; node_iterator &update_state(node_type i) { - *_ptr = i; + _ptr = i; curr_i = i + 1; curr_j = 0; @@ -389,7 +394,7 @@ namespace sdsl { } value_type operator*() { - return *_ptr; + return _ptr; } neighbour_iterator &operator++() { @@ -400,25 +405,20 @@ namespace sdsl { } value_type next_neigh; next_neigh = _find_next(); - _ptr = make_shared(next_neigh); + _ptr = next_neigh; - if(*_ptr == size) - *_ptr = -1; + if(_ptr == size) + _ptr = -1; return *this; } neighbour_iterator &operator++(int) { - shared_ptr> tmp = make_shared>(this->tree, _node); operator++(); - return *tmp; + return *this; } bool operator==(const neighbour_iterator &rhs) const { - if (rhs._ptr != nullptr && this->_ptr != nullptr) - return rhs._ptr == this->_ptr; - else if (rhs._ptr == nullptr && this->_ptr == nullptr) - return true; - return false; + return rhs._ptr == this->_ptr; } bool operator!=(const neighbour_iterator &rhs) const { @@ -426,51 +426,40 @@ namespace sdsl { } neighbour_iterator end() { - neighbour_iterator it = *this; - - value_type aux = -1; - if(it._ptr != nullptr) - *(it._ptr) = aux; //end node - else - it._ptr = make_shared(aux); - - it._level = k * std::floor(it._node / static_cast(it._n)); - it._row = k; - it._col = k; - - return it; - } - - neighbour_iterator &operator=(const neighbour_iterator &other) { - if (this != &other) { - this->_ptr = other._ptr; - this->tree = other.tree; - this->k = other.k; - - this->size = other.size; - this->_n = other._n; - this->_node = other._node; - this->_level = other._level; - this->_col = other._col; - this->_row = other._row; - this->_n = other._n; - } + _ptr = -1; return *this; } - friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { - std::swap(rhs._ptr, lhs._ptr); - std::swap(rhs.tree, lhs.tree); - std::swap(rhs.k, lhs.k); - - std::swap(rhs.size, lhs.size); - std::swap(rhs._n, lhs._n); - std::swap(rhs._node, lhs._node); - std::swap(rhs._level, lhs._level); - std::swap(rhs._col, lhs._col); - std::swap(rhs._row, lhs._row); - std::swap(rhs._n, lhs._n); - } + // neighbour_iterator &operator=(const neighbour_iterator &other) { + // if (this != &other) { + // this->_ptr = other._ptr; + // this->tree = other.tree; + // this->k = other.k; + + // this->size = other.size; + // this->_n = other._n; + // this->_node = other._node; + // this->_level = other._level; + // this->_col = other._col; + // this->_row = other._row; + // this->_n = other._n; + // } + // return *this; + // } + + // friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { + // std::swap(rhs._ptr, lhs._ptr); + // std::swap(rhs.tree, lhs.tree); + // std::swap(rhs.k, lhs.k); + + // std::swap(rhs.size, lhs.size); + // std::swap(rhs._n, lhs._n); + // std::swap(rhs._node, lhs._node); + // std::swap(rhs._level, lhs._level); + // std::swap(rhs._col, lhs._col); + // std::swap(rhs._row, lhs._row); + // std::swap(rhs._n, lhs._n); + // } private: @@ -483,10 +472,10 @@ namespace sdsl { if (tree->l().size() > 0) { value_type first_neighbour = _find_next(); - _ptr = make_shared(first_neighbour); + _ptr = first_neighbour; } else { // if its empty the begin == end - _ptr = make_shared(-1); //end node + _ptr = -1; //end node } } @@ -527,7 +516,7 @@ namespace sdsl { return -1; } - pointer _ptr ; + value_type _ptr ; const k_tree *tree; uint8_t k = 2; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index a98f4f535..50523fb48 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -281,6 +281,7 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; + ASSERT_FALSE(&another_edge_iterator == &edge_iterator); ASSERT_EQ(std::get<0>(*another_edge_iterator), (size_t) 0); ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 0); @@ -289,6 +290,7 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) edge_iterator++; ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 0); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 1); + edge_iterator++; ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 2); ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); @@ -403,14 +405,14 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { ASSERT_EQ(*other_iterator, *tree.node_end()); } -TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { + TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { vector> mat({{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, {1, 1, 1, 0}}); TypeParam tree(mat); auto neighbour_iterator = tree.neighbour_begin(2); - ASSERT_EQ(*neighbour_iterator, (size_t)2); + ASSERT_EQ(*neighbour_iterator, 2); neighbour_iterator++; ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); @@ -418,11 +420,11 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); neighbour_iterator = tree.neighbour_begin(3); - ASSERT_EQ(*neighbour_iterator, (size_t)0); + ASSERT_EQ(*neighbour_iterator, 0); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, (size_t)1); + ASSERT_EQ(*neighbour_iterator, 1); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, (size_t)2); + ASSERT_EQ(*neighbour_iterator, 2); neighbour_iterator++; ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); @@ -436,7 +438,7 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { TypeParam empty_tree; - ASSERT_EQ(empty_tree.node_begin(), empty_tree.node_end()); + ASSERT_EQ(*empty_tree.node_begin(), *empty_tree.node_end()); } TYPED_TEST_CASE(k2_tree_test_k_3, k_3_implementations); From 013cdc870418e9ce40e59876e75bd4726ac57bd9 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 15 Jul 2020 23:39:08 +0100 Subject: [PATCH 32/57] Fix edge iterator --- include/sdsl/k2_tree.hpp | 2 +- include/sdsl/k2_tree_iterator.hpp | 462 +++++++++++++++++++----------- test/k2_tree_test.cpp | 162 ++++++++--- 3 files changed, 406 insertions(+), 220 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 3571fabee..c46c7b2f8 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -855,7 +855,7 @@ class k2_tree } neigh_iterator neighbour_end() { - return neigh_iterator(this, n_vertices-1).end(); + return neigh_iterator(this).end(); } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 499950b9a..3bbf9a988 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -5,19 +5,26 @@ #include #include #include +#include #include using namespace std; -namespace sdsl { +namespace sdsl +{ + using idx_type = k2_tree_ns::idx_type; + using size_type = k2_tree_ns::size_type; + using edge = std::tuple; - typedef struct state { - unsigned node, row, col, n, level, j, y; + typedef struct state + { + int node, row, col, n, level, j, y; bool valid = false; void - set(unsigned _node, unsigned _n, unsigned _row, unsigned _col, unsigned _level, unsigned _j, unsigned _y) { + set(int _node, int _n, int _row, int _col, int _level, int _j, int _y) + { node = _node; row = _row; col = _col; @@ -29,12 +36,19 @@ namespace sdsl { } } state; - template - class edge_iterator { - using idx_type = k2_tree_ns::idx_type; - using size_type = k2_tree_ns::size_type; - using edge = std::tuple; - + typedef struct tree_node + { + idx_type node; + size_type n; + unsigned row, col; + idx_type level; + unsigned j; + size_type y; + } tree_node; + + template + class edge_iterator + { public: using value_type = edge; using pointer = shared_ptr; @@ -43,90 +57,118 @@ namespace sdsl { edge_iterator() {} - edge_iterator(const k_tree *tree) { + edge_iterator(const k_tree *tree) + { this->tree = tree; this->k = tree->k_(); _initialize(); } - value_type operator*() { + value_type operator*() + { return _ptr; } - bool operator==(const edge_iterator &rhs) const { + bool operator==(const edge_iterator &rhs) const + { return equal_edge(rhs._ptr, _ptr); } - bool operator!=(const edge_iterator &rhs) const { + bool operator!=(const edge_iterator &rhs) const + { return !(*this == rhs); } - void print() { - cout << "_ptr "<< std::get<0>(_ptr) << ", " << std::get<1>(_ptr) << endl; + void print() + { + cout << "_ptr " << std::get<0>(_ptr) << ", " << std::get<1>(_ptr) << endl; cout << "_node " << _node << endl; cout << "_level " << _level << endl; cout << "_row " << _row << endl; cout << "_col " << _col << endl; cout << "st " << endl; - - cout << " node: " << st.node << endl; - cout << " row: " << st.row << endl; - cout << " col: " << st.col << endl; - cout << " n: " << st.n << endl; - cout << " level: " << st.level << endl; - cout << " j: " << st.j << endl; - cout << " y: " << st.y << endl; - cout << " valid: " << st.valid << endl; - cout << endl; - } - - edge_iterator &operator++(int) { - edge prev = _ptr; + + for (tree_node st_i : st) + { + + cout << " node: " << st_i.node << endl; + cout << " row: " << st_i.row << endl; + cout << " col: " << st_i.col << endl; + cout << " n: " << st_i.n << endl; + cout << " level: " << st_i.level << endl; + cout << " j: " << st_i.j << endl; + cout << " y: " << st_i.y << endl; + cout << endl; + } + } + + edge_iterator &operator++(int) + { operator++(); - if (equal_edge(prev, _ptr)) - operator++(); return *this; } - edge_iterator &operator++() { - if (st.valid) { - st.j = st.j + 1; - if(st.j < k) { - edge e; - e = _find_next_middle(); - _ptr = e; - return *this; - + edge_iterator &operator++() + { + while (!st.empty()) // did not go until the end of the subtree + { + tree_node &last_found = st.back(); + last_found.j++; + idx_type neigh; + if (last_found.n == _n / k && last_found.j < k) + { + if (_find_next_recursive(last_found.n / k, + last_found.row % last_found.n, + last_found.col + last_found.n * last_found.j, + last_found.y + last_found.j, + neigh, 0)) + { + _ptr = edge(last_found.node, neigh); + return *this; + } } - } - st.valid = false; - _col++; - if (_col >= k) { - _col = 0; - _row++; - } - edge e; - e = _find_next(); - _ptr = e; + if (last_found.j < k) + { + if (_find_next_recursive(last_found.n / k, + last_found.row % last_found.n, + last_found.col + last_found.n * last_found.j, + last_found.y + last_found.j, + neigh, last_found.j)) + { + _ptr = edge(last_found.node, neigh); + return *this; + } + } + st.pop_back(); + } // move to another subtree + _row++; + if (_row >= k) + { + _row = 0; + _node++; + _level = k * std::floor(_node / static_cast(_n)); + } + _ptr = _find_next(); return *this; } - - edge_iterator end() { + edge_iterator end() + { edge_iterator it = *this; it._ptr = edge(size, size); //end node it._node = size - 1; it._level = k * std::floor(it._node / static_cast(it._n)); it._row = k; - it._col = k; return it; } - friend void swap(edge_iterator &rhs, edge_iterator &lhs) { - if(&rhs != &lhs) { + friend void swap(edge_iterator &rhs, edge_iterator &lhs) + { + if (&rhs != &lhs) + { std::swap(rhs.tree, lhs.tree); std::swap(rhs.k, lhs.k); @@ -140,7 +182,8 @@ namespace sdsl { } private: - bool equal_edge(const edge &e1, const edge &e2) const { + bool equal_edge(const edge &e1, const edge &e2) const + { idx_type e1_x = std::get<0>(e1); idx_type e1_y = std::get<1>(e1); @@ -156,7 +199,7 @@ namespace sdsl { uint8_t k = 2; // // iterator state // - state st; + deque st; size_t size; size_type _n; idx_type _node, _level; @@ -165,7 +208,8 @@ namespace sdsl { // void - _initialize() { + _initialize() + { _n = static_cast(std::pow(k, tree->height())) / k; _node = 0; _row = 0; @@ -173,84 +217,74 @@ namespace sdsl { _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); - if (tree->l().size() > 0) { - edge first = _find_next(); - _ptr = edge(std::get<0>(first), std::get<1>(first)); - } else { + if (tree->l().size() > 0) + { + _ptr = _find_next(); + } + else + { // if its empty the begin == end _ptr = edge(size, size); //end node } } - edge _find_next_middle() { - if (st.valid) { - idx_type neigh = size; - _find_next_recursive(st.n / k, st.row % st.n, st.col + st.n * st.j, st.y + st.j, neigh, st.j); - if (neigh != size) { - return edge(_node, neigh); - } - } - - st.valid = false; - _col++; - if (_col >= k) { - _col = 0; - _row++; - } - return _find_next(); - } - - edge _find_next() { + edge _find_next() + { idx_type neigh; - - if (_node < size) { - for (; _row < k; _row++) { + if (_node < size) + { + for (; _row < k; _row++) + { neigh = size; - _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); - if (neigh < size) { - // cout << "x: " << _node << " y: " << neigh << endl; + _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); + if (neigh < size) + { return edge(_node, neigh); } + assert(st.empty()); } _row = 0; - _col = 0; _node++; _level = k * std::floor(_node / static_cast(_n)); - st.valid = false; return _find_next(); } return edge(size, size); // end node } - bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, idx_type &neigh, - unsigned initial_j) { - if (level >= tree->t().size()) // Last level - { - if (tree->l()[level - tree->t().size()] == 1) { + bool _find_next_recursive(size_type n, unsigned row, unsigned col, size_type level, + idx_type &neigh, unsigned initial_j) + { + if (level >= tree->t().size()) + { // Last level + if (tree->l()[level - tree->t().size()] == 1) + { neigh = col; return true; } return false; } - if (tree->t()[level] == 1) { + if (tree->t()[level] == 1) + { size_type y = tree->rank_t()(level + 1) * k * k + k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) { - st.set(_node, n, row, col, level, j, y); - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) { - _col = j; + for (unsigned j = initial_j; j < k; j++) + { + tree_node next_node = {_node, n, row, col, level, j, y}; + st.push_back(next_node); + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) return true; - } + st.pop_back(); } } return false; } }; - template - class node_iterator { + template + class node_iterator + { using node_type = k2_tree_ns::idx_type; using size_type = k2_tree_ns::size_type; @@ -262,10 +296,12 @@ namespace sdsl { node_iterator() {} - node_iterator(const k2_tree *k_tree) { + node_iterator(const k2_tree *k_tree) + { this->tree = k_tree; - if(tree->get_number_edges() == 0) { + if (tree->get_number_edges() == 0) + { value_type num_nodes = tree->get_number_nodes(); _ptr = num_nodes; curr_i = num_nodes; @@ -273,16 +309,19 @@ namespace sdsl { return; } - for (value_type i = 0; i < tree->get_number_nodes(); i++) { + for (value_type i = 0; i < tree->get_number_nodes(); i++) + { for (value_type j = i; j < tree->get_number_nodes(); j++) - if (tree->adj(i, j)) { + if (tree->adj(i, j)) + { _ptr = i; curr_i = i; curr_j = j; return; } for (value_type j = i; j < tree->get_number_nodes(); j++) - if (tree->adj(j, i)) { + if (tree->adj(j, i)) + { _ptr = i; curr_i = i + 1; curr_j = i; @@ -291,7 +330,8 @@ namespace sdsl { } } - node_iterator(node_iterator *other) { + node_iterator(node_iterator *other) + { this->_ptr = other->_ptr; this->tree = other->tree; this->curr_i = other->curr_i; @@ -300,12 +340,15 @@ namespace sdsl { ~node_iterator() {} - value_type operator*() const { + value_type operator*() const + { return _ptr; } - node_iterator &operator=(const node_iterator &other) { - if (this != &other) { + node_iterator &operator=(const node_iterator &other) + { + if (this != &other) + { tree = other.tree; _ptr = other._ptr; curr_i = other.curr_i; @@ -314,20 +357,25 @@ namespace sdsl { return *this; } - bool operator==(const node_iterator &rhs) const { + bool operator==(const node_iterator &rhs) const + { return rhs._ptr == _ptr; } - bool operator!=(const node_iterator &rhs) const { + bool operator!=(const node_iterator &rhs) const + { return !(*this == rhs); } - node_iterator &operator++() { - for (value_type i = curr_i; i < tree->get_number_nodes(); i++) { + node_iterator &operator++() + { + for (value_type i = curr_i; i < tree->get_number_nodes(); i++) + { for (value_type j = curr_j; j < tree->get_number_nodes(); j++) if (tree->adj(i, j)) return update_state(i); - for (value_type j = 0; j < tree->get_number_nodes(); j++) { + for (value_type j = 0; j < tree->get_number_nodes(); j++) + { if (j == i) continue; if (tree->adj(j, i)) @@ -338,19 +386,24 @@ namespace sdsl { return *this; } - node_iterator &operator++(int) { - if(_ptr == tree->get_number_nodes()-1) { + node_iterator &operator++(int) + { + if (_ptr == tree->get_number_nodes() - 1) + { *this = end(); return *this; } value_type prev = _ptr; operator++(); - if(_ptr == prev) this->end(); + if (_ptr == prev) + this->end(); return *this; } - node_iterator end() { - if (tree == NULL) return *this; + node_iterator end() + { + if (tree == NULL) + return *this; node_iterator it = *this; value_type num_nodes = it.tree->get_number_nodes(); it._ptr = num_nodes; //end node @@ -364,7 +417,8 @@ namespace sdsl { const k2_tree *tree = NULL; value_type curr_i, curr_j; - node_iterator &update_state(node_type i) { + node_iterator &update_state(node_type i) + { _ptr = i; curr_i = i + 1; curr_j = 0; @@ -373,8 +427,9 @@ namespace sdsl { } }; - template - class neighbour_iterator { + template + class neighbour_iterator + { using idx_type = k2_tree_ns::idx_type; using size_type = k2_tree_ns::size_type; @@ -386,46 +441,70 @@ namespace sdsl { neighbour_iterator() {} - neighbour_iterator(const k_tree *tree, value_type node) { + neighbour_iterator(const k_tree *tree, value_type node) + { this->tree = tree; this->k = tree->k_(); this->_node = node; _initialize(); } - value_type operator*() { + neighbour_iterator(const k_tree *tree) + { + this->tree = tree; + this->k = tree->k_(); + this->_node = 0; + _initialize(); + } + + value_type operator*() + { return _ptr; } - neighbour_iterator &operator++() { + neighbour_iterator &operator++(int) + { + value_type prev = _ptr; + operator++(); + if (prev == _ptr && _ptr != -1) + operator++(); + return *this; + } + + neighbour_iterator &operator++() + { + if (st.valid) + { + st.j = st.j + 1; + if (st.j < k) + { + _ptr = _find_next_middle(); + return *this; + } + } + st.valid = false; _col++; - if (_col >= k) { + if (_col >= k) + { _col = 0; _row++; } - value_type next_neigh; - next_neigh = _find_next(); - _ptr = next_neigh; - - if(_ptr == size) - _ptr = -1; + _ptr = _find_next(); return *this; } - neighbour_iterator &operator++(int) { - operator++(); - return *this; - } - - bool operator==(const neighbour_iterator &rhs) const { + bool operator==(const neighbour_iterator &rhs) const + { return rhs._ptr == this->_ptr; } - bool operator!=(const neighbour_iterator &rhs) const { + bool operator!=(const neighbour_iterator &rhs) const + { return !(*this == rhs); } - neighbour_iterator end() { + neighbour_iterator end() + { _ptr = -1; return *this; } @@ -462,40 +541,90 @@ namespace sdsl { // } private: - - void _initialize() { + void + _initialize() + { _n = static_cast(std::pow(k, tree->height())) / k; _row = 0; _col = 0; _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); - if (tree->l().size() > 0) { - value_type first_neighbour = _find_next(); - _ptr = first_neighbour; - } else { + if (tree->l().size() > 0) + { + _ptr = _find_next(); + } + else + { // if its empty the begin == end _ptr = -1; //end node } } - bool _find_next_recursive(size_type n, value_type row, value_type col, size_type level, value_type &neigh, - unsigned initial_j) { - if (level >= tree->t().size()) // Last level + value_type _find_next_middle() + { + if (st.valid) { - if (tree->l()[level - tree->t().size()] == 1) { + value_type neigh = size; + _find_next_recursive(st.n / k, st.row % st.n, st.col + st.n * st.j, st.y + st.j, neigh, st.j); + if (neigh != size) + { + return neigh; + } + } + + st.valid = false; + _col++; + if (_col >= k) + { + _col = 0; + _row++; + } + return _find_next(); + } + + value_type _find_next() + { + value_type neigh; + if (_node < size) + { + for (; _row < k; _row++) + { + neigh = size; + _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); + if (neigh < size) + { + // cout << "x: " << _node << " y: " << neigh << endl; + return neigh; + } + } + } + return -1; // end node + } + + bool _find_next_recursive(int n, int row, int col, int level, int &neigh, + unsigned initial_j) + { + if (level >= (int)tree->t().size()) // Last level + { + if (tree->l()[level - tree->t().size()] == 1) + { neigh = col; return true; } return false; } - if (tree->t()[level] == 1) { + if (tree->t()[level] == 1) + { size_type y = tree->rank_t()(level + 1) * k * k + k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) { - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) { + for (unsigned j = initial_j; j < k; j++) + { + st.set(_node, n, row, col, level, j, y); + if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) + { _col = j; return true; } @@ -504,28 +633,13 @@ namespace sdsl { return false; } - value_type _find_next() { - value_type neigh; - for (; _row < k; _row++) { - neigh = size; - _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); - if (neigh < size) { - return neigh; - } - } - return -1; - } - - value_type _ptr ; + value_type _ptr; const k_tree *tree; uint8_t k = 2; // iterator state // - value_type size; - size_type _n; - idx_type _node, _level; - unsigned _col; - int _row; + state st; + int size, _n, _node, _level, _row, _col; // }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 50523fb48..6e48f91af 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -362,21 +362,66 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.get_number_nodes()); } -// //OPERATOR DECREMENT -// last = tree.edge_end(); -// last--; -// ASSERT_EQ(std::get<0>(*last), (size_t) 3); -// ASSERT_EQ(std::get<1>(*last), (size_t) 2); -// last--; -// ASSERT_EQ(std::get<0>(*last), (size_t) 2); -// ASSERT_EQ(std::get<1>(*last), (size_t) 2); -// last--; -// ASSERT_EQ(std::get<0>(*last), (size_t) 0); -// ASSERT_EQ(std::get<1>(*last), (size_t) 1); -// last--; // does not go beyong the begin -// ASSERT_EQ(std::get<0>(*last), (size_t) 0); -// ASSERT_EQ(std::get<1>(*last), (size_t) 1); -// } +TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { + vector> mat({ + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1}, + {0, 1, 0, 0, 1, 0, 0}, + {0, 1, 0, 0, 0, 1, 0}, + {0, 1, 1, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 1}, + {0, 1, 0, 0, 0, 1, 0}, + }); + TypeParam tree(mat); + auto it = tree.edge_begin(); + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 2); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 3); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 4); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 5); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 1); + ASSERT_EQ(std::get<1>(*it), (size_t) 6); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 2); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 2); + ASSERT_EQ(std::get<1>(*it), (size_t) 4); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 3); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 3); + ASSERT_EQ(std::get<1>(*it), (size_t) 5); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 4); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 4); + ASSERT_EQ(std::get<1>(*it), (size_t) 2); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 5); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 5); + ASSERT_EQ(std::get<1>(*it), (size_t) 3); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 5); + ASSERT_EQ(std::get<1>(*it), (size_t) 6); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 6); + ASSERT_EQ(std::get<1>(*it), (size_t) 1); + it++; + ASSERT_EQ(std::get<0>(*it), (size_t) 6); + ASSERT_EQ(std::get<1>(*it), (size_t) 5); +} TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { vector> mat({{0, 0, 0, 0}, @@ -405,36 +450,63 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { ASSERT_EQ(*other_iterator, *tree.node_end()); } - TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { - vector> mat({{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 1, 0}, - {1, 1, 1, 0}}); - TypeParam tree(mat); - auto neighbour_iterator = tree.neighbour_begin(2); - ASSERT_EQ(*neighbour_iterator, 2); - - neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); - neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); - - neighbour_iterator = tree.neighbour_begin(3); - ASSERT_EQ(*neighbour_iterator, 0); - neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 1); - neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 2); - neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); - - auto other_iterator = tree.neighbour_begin(2); - swap(other_iterator, neighbour_iterator); - ASSERT_EQ(*neighbour_iterator, *tree.neighbour_begin(2)); - ASSERT_EQ(*other_iterator, *tree.neighbour_end()); - - ASSERT_EQ(*tree.neighbour_begin(0), *tree.neighbour_end()); - } +TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { + vector> mat({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 1, 0}}); + TypeParam tree(mat); + auto neighbour_iterator = tree.neighbour_begin(2); + ASSERT_EQ(*neighbour_iterator, 2); + + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + + neighbour_iterator = tree.neighbour_begin(3); + ASSERT_EQ(*neighbour_iterator, 0); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 1); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 2); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); + + auto other_iterator = tree.neighbour_begin(2); + swap(other_iterator, neighbour_iterator); + ASSERT_EQ(*neighbour_iterator, *tree.neighbour_begin(2)); + ASSERT_EQ(*other_iterator, *tree.neighbour_end()); + + ASSERT_EQ(*tree.neighbour_begin(0), *tree.neighbour_end()); +} + +TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_star) { + vector> mat({ + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1}, + {0, 1, 0, 0, 1, 0, 0}, + {0, 1, 0, 0, 0, 1, 0}, + {0, 1, 1, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 1}, + {0, 1, 0, 0, 0, 1, 0}, + }); + TypeParam tree(mat); + auto neighbour_iterator = tree.neighbour_begin(1); + ASSERT_EQ(*neighbour_iterator, 2); + + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 3); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 4); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 5); + neighbour_iterator++; + ASSERT_EQ(*neighbour_iterator, 6); +} + + + TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { TypeParam empty_tree; From cfc63ffa856a886372043615217566a724d88ab0 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 16 Jul 2020 00:24:58 +0100 Subject: [PATCH 33/57] Fix neighbour iterator --- include/sdsl/k2_tree_iterator.hpp | 132 ++++++++++++------------------ 1 file changed, 54 insertions(+), 78 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 3bbf9a988..deee33398 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -17,28 +17,9 @@ namespace sdsl using size_type = k2_tree_ns::size_type; using edge = std::tuple; - typedef struct state - { - int node, row, col, n, level, j, y; - bool valid = false; - - void - set(int _node, int _n, int _row, int _col, int _level, int _j, int _y) - { - node = _node; - row = _row; - col = _col; - n = _n; - level = _level; - j = _j; - y = _y; - valid = true; - } - } state; - typedef struct tree_node { - idx_type node; + int node; size_type n; unsigned row, col; idx_type level; @@ -85,7 +66,6 @@ namespace sdsl cout << "_node " << _node << endl; cout << "_level " << _level << endl; cout << "_row " << _row << endl; - cout << "_col " << _col << endl; cout << "st " << endl; for (tree_node st_i : st) @@ -93,7 +73,6 @@ namespace sdsl cout << " node: " << st_i.node << endl; cout << " row: " << st_i.row << endl; - cout << " col: " << st_i.col << endl; cout << " n: " << st_i.n << endl; cout << " level: " << st_i.level << endl; cout << " j: " << st_i.j << endl; @@ -177,7 +156,6 @@ namespace sdsl std::swap(rhs._node, lhs._node); std::swap(rhs._level, lhs._level); std::swap(rhs._row, lhs._row); - std::swap(rhs._col, lhs._col); } } @@ -200,11 +178,9 @@ namespace sdsl // // iterator state // deque st; - size_t size; size_type _n; - idx_type _node, _level; - unsigned _col; - int _row; + idx_type _level; + int _row, _node, size; // void @@ -213,7 +189,6 @@ namespace sdsl _n = static_cast(std::pow(k, tree->height())) / k; _node = 0; _row = 0; - _col = 0; _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); @@ -237,7 +212,7 @@ namespace sdsl { neigh = size; _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); - if (neigh < size) + if (neigh < (idx_type)size) { return edge(_node, neigh); } @@ -464,30 +439,50 @@ namespace sdsl neighbour_iterator &operator++(int) { - value_type prev = _ptr; - operator++(); - if (prev == _ptr && _ptr != -1) + if (_ptr != -1) operator++(); return *this; } neighbour_iterator &operator++() { - if (st.valid) + while (!st.empty()) // did not go until the end of the subtree { - st.j = st.j + 1; - if (st.j < k) + tree_node2 &last_found = st.back(); + last_found.j++; + value_type neigh; + if (last_found.n == _n / k && last_found.j < k) { - _ptr = _find_next_middle(); - return *this; + if (_find_next_recursive(last_found.n / k, + last_found.row % last_found.n, + last_found.col + last_found.n * last_found.j, + last_found.y + last_found.j, + neigh, 0)) + { + _ptr = neigh; + return *this; + } } - } - st.valid = false; - _col++; - if (_col >= k) + if (last_found.j < k) + { + if (_find_next_recursive(last_found.n / k, + last_found.row % last_found.n, + last_found.col + last_found.n * last_found.j, + last_found.y + last_found.j, + neigh, last_found.j)) + { + _ptr = neigh; + return *this; + } + } + st.pop_back(); + + } // move to another subtree + _row++; + if (_row >= k) { - _col = 0; - _row++; + _ptr = -1; + return *this; } _ptr = _find_next(); return *this; @@ -519,7 +514,6 @@ namespace sdsl // this->_n = other._n; // this->_node = other._node; // this->_level = other._level; - // this->_col = other._col; // this->_row = other._row; // this->_n = other._n; // } @@ -535,7 +529,6 @@ namespace sdsl // std::swap(rhs._n, lhs._n); // std::swap(rhs._node, lhs._node); // std::swap(rhs._level, lhs._level); - // std::swap(rhs._col, lhs._col); // std::swap(rhs._row, lhs._row); // std::swap(rhs._n, lhs._n); // } @@ -546,7 +539,6 @@ namespace sdsl { _n = static_cast(std::pow(k, tree->height())) / k; _row = 0; - _col = 0; _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); @@ -561,28 +553,6 @@ namespace sdsl } } - value_type _find_next_middle() - { - if (st.valid) - { - value_type neigh = size; - _find_next_recursive(st.n / k, st.row % st.n, st.col + st.n * st.j, st.y + st.j, neigh, st.j); - if (neigh != size) - { - return neigh; - } - } - - st.valid = false; - _col++; - if (_col >= k) - { - _col = 0; - _row++; - } - return _find_next(); - } - value_type _find_next() { value_type neigh; @@ -591,7 +561,7 @@ namespace sdsl for (; _row < k; _row++) { neigh = size; - _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, _col); + _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); if (neigh < size) { // cout << "x: " << _node << " y: " << neigh << endl; @@ -602,8 +572,7 @@ namespace sdsl return -1; // end node } - bool _find_next_recursive(int n, int row, int col, int level, int &neigh, - unsigned initial_j) + bool _find_next_recursive(value_type n, value_type row, value_type col, value_type level, value_type &neigh, unsigned initial_j) { if (level >= (int)tree->t().size()) // Last level { @@ -617,29 +586,36 @@ namespace sdsl if (tree->t()[level] == 1) { - size_type y = tree->rank_t()(level + 1) * k * k + + value_type y = tree->rank_t()(level + 1) * k * k + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) { - st.set(_node, n, row, col, level, j, y); + tree_node2 next_node = {_node, n, row, col, level, j, y}; + st.push_back(next_node); if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) - { - _col = j; return true; - } + st.pop_back(); } + return false; } return false; } + typedef struct tree_node2 + { + value_type node, n, row, col, level; + unsigned j; + value_type y; + } tree_node2; + value_type _ptr; const k_tree *tree; uint8_t k = 2; // iterator state // - state st; - int size, _n, _node, _level, _row, _col; + deque st; + value_type size, _n, _node, _level, _row; // }; } // namespace sdsl From 0835d703f55902351b4858865790204e133abca5 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 18 Jul 2020 17:33:13 +0100 Subject: [PATCH 34/57] Valgrind is happier now --- include/sdsl/k2_tree.hpp | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index c46c7b2f8..ebcdbfa24 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -442,6 +442,8 @@ class k2_tree { return std::pow(k, k_height); } + + using value_type = uint64_t; //! Union Operation /*! Performs the union operation between two tree. This operations requires both * trees to have the same number of nodes. @@ -462,21 +464,21 @@ class k2_tree if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); - size_t t_size_A = this->t().size(); - size_t t_size_B = k2_B.t().size(); + value_type t_size_A = this->t().size(); + value_type t_size_B = k2_B.t().size(); // C Initialization - const size_t max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; - std::deque> C(max_height); + const value_type max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; + std::deque> C(max_height); //////// // Q Initialization - std::deque> Q; + std::deque> Q; Q.push_back({0, 1, 1}); //////// - std::array next; - uint pA, pB; + std::array next; + value_type pA, pB; pA = 0; pB = 0; @@ -484,11 +486,11 @@ class k2_tree next = Q.front(); Q.pop_front(); - uint l = next[0]; - uint rA = next[1]; - uint rB = next[2]; - for (size_t i = 0; i < k_k * k_k; ++i) { - uint bA, bB; + value_type l = next[0]; + value_type rA = next[1]; + value_type rB = next[2]; + for (value_type i = 0; i < k_k * k_k; ++i) { + value_type bA, bB; bA = 0; bB = 0; if (rA == 1) { @@ -512,20 +514,21 @@ class k2_tree } // Create new K2 tree from union operation - size_t t_size = 0; - for (size_t l = 0; l < max_height - 1; l++) - t_size += C[l].size(); + value_type t_size = 0; + for (value_type j = 0; j < max_height - 1; j++) + t_size += C[j].size(); bit_vector t(t_size, 0); bit_vector l(C[max_height - 1].size(), 0); - size_t p = 0; - for (size_t l = 0; l < max_height - 1; l++) - for (size_t bit = 0; bit < C[l].size(); bit++) { - t.set_int(p, C[l][bit]); + value_type p = 0; + for (value_type i = 0; i < max_height - 1; i++) + for (value_type bit = 0; bit < C[i].size(); bit++) { + t[p] = C[i][bit]; ++p; } - for (size_t bit = 0; bit < C[max_height - 1].size(); bit++) - l.set_int(bit, C[max_height - 1][bit]); + for (value_type bit = 0; bit < C[max_height - 1].size(); bit++) { + l[bit] = C[max_height - 1][bit]; + } return k2_tree(t, l, max_height, k_k); } From 0ae031e6b7ea386da3b8072524720aa4169530cd Mon Sep 17 00:00:00 2001 From: Joana H Date: Fri, 24 Jul 2020 20:25:49 +0100 Subject: [PATCH 35/57] Try to fix memory leak --- include/sdsl/k2_tree.hpp | 31 +++++++++++++++++--------- test/k2_tree_test.cpp | 48 ++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index ebcdbfa24..e555544de 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -396,10 +396,10 @@ class k2_tree *this = std::move(tr); } - k2_tree(t_bv t, t_bv l, uint16_t height, uint8_t k_branch) : k_k(k_branch), k_height(height) + k2_tree(t_bv &t, t_bv &l, uint16_t height, uint8_t k_branch) : k_k(k_branch), k_height(height) { - k_t = std::move(t); - k_l = std::move(l); + k_t = t_bv(t); + k_l = t_bv(l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); } @@ -452,14 +452,16 @@ class k2_tree * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ - k2_tree unionOp(k2_tree &k2_B) + void unionOp(k2_tree &k2_B) { assert(this->k_k == k2_B.k_k); if (k2_B.get_number_edges() == 0) - return *this; + return; - if (this->get_number_edges() == 0) - return k2_B; + if (this->get_number_edges() == 0) { + *this = k2_B; + return; + } if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); @@ -518,8 +520,8 @@ class k2_tree for (value_type j = 0; j < max_height - 1; j++) t_size += C[j].size(); - bit_vector t(t_size, 0); - bit_vector l(C[max_height - 1].size(), 0); + t_bv t(t_size, 0); + t_bv l(C[max_height - 1].size(), 0); value_type p = 0; for (value_type i = 0; i < max_height - 1; i++) for (value_type bit = 0; bit < C[i].size(); bit++) { @@ -530,7 +532,12 @@ class k2_tree l[bit] = C[max_height - 1][bit]; } - return k2_tree(t, l, max_height, k_k); + + k_t = t; + k_l = l; + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); + k_height = max_height; } //! Move assignment operator @@ -545,6 +552,7 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); n_vertices = std::move(tr.n_vertices); + n_marked_edges = std::move(tr.n_marked_edges); } return *this; } @@ -561,6 +569,7 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); n_vertices = tr.n_vertices; + n_marked_edges = tr.n_marked_edges; } return *this; @@ -578,6 +587,8 @@ class k2_tree std::swap(k_k, tr.k_k); std::swap(k_height, tr.k_height); std::swap(n_vertices, tr.n_vertices); + std::swap(n_marked_edges, tr.n_marked_edges); + } } diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 6e48f91af..d776a4a19 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -225,10 +225,10 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) // T 0 0 0 1 // L 0 0 0 1 TypeParam tree_B(mat); + + tree_A.unionOp(tree_B); - TypeParam unionTree = tree_A.unionOp(tree_B); - - k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); + k2_tree_test_nm::check_t_l(tree_A, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 1}); } TYPED_TEST(k2_tree_test_k_2, empty_union_operation) @@ -241,15 +241,17 @@ TYPED_TEST(k2_tree_test_k_2, empty_union_operation) TypeParam tree_A(mat); TypeParam tree_B; - TypeParam unionTree = tree_A.unionOp(tree_B); - k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + TypeParam tree_A_copy = tree_A; + TypeParam tree_B_copy = tree_B; - unionTree = tree_B.unionOp(tree_A); + tree_A_copy.unionOp(tree_B); + k2_tree_test_nm::check_t_l(tree_A_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); - k2_tree_test_nm::check_t_l(unionTree, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + tree_B_copy.unionOp(tree_A); + k2_tree_test_nm::check_t_l(tree_B_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); - unionTree = tree_B.unionOp(tree_B); - k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); + tree_B.unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(tree_B, tree_B); } TYPED_TEST(k2_tree_test_k_2, union_operation_test) @@ -450,6 +452,14 @@ TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { ASSERT_EQ(*other_iterator, *tree.node_end()); } +TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_empty) { + vector> mat({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 1, 0}}); + TypeParam tree(mat); +} + TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { vector> mat({{0, 0, 0, 0}, {0, 0, 0, 0}, @@ -663,8 +673,8 @@ TYPED_TEST(k2_tree_test_k_3, union_operation_test) {0, 0, 0, 1}}); TypeParam tree_B(mat); - TypeParam unionTree = tree_A.unionOp(tree_B); - k2_tree_test_nm::check_t_l(unionTree, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); + tree_A.unionOp(tree_B); + k2_tree_test_nm::check_t_l(tree_A, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); } TYPED_TEST(k2_tree_test_k_3, empty_union_operation) @@ -683,14 +693,18 @@ TYPED_TEST(k2_tree_test_k_3, empty_union_operation) TypeParam tree_A(mat); TypeParam tree_B; - TypeParam unionTree = tree_A.unionOp(tree_B); - k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + TypeParam tree_A_copy = tree_A; + TypeParam tree_B_copy = tree_B; + + + tree_A_copy.unionOp(tree_B); + k2_tree_test_nm::check_t_l(tree_A_copy, expected_t, expected_l); - unionTree = tree_B.unionOp(tree_A); - k2_tree_test_nm::check_t_l(unionTree, expected_t, expected_l); + tree_B_copy.unionOp(tree_A); + k2_tree_test_nm::check_t_l(tree_B_copy, expected_t, expected_l); - unionTree = tree_B.unionOp(tree_B); - k2_tree_test_nm::assert_eq_tree(unionTree, tree_B); + tree_B.unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(tree_B, tree_B); } TYPED_TEST_CASE(k2_tree_test, Implementations); From 8ef83abc00a52d3743218b08b1d6a2d906573218 Mon Sep 17 00:00:00 2001 From: Joana H Date: Mon, 3 Aug 2020 21:05:01 +0100 Subject: [PATCH 36/57] Add equal operation to k2tree --- include/sdsl/k2_tree.hpp | 28 ++++++++++++++++++++++++++-- test/k2_tree_test.cpp | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index e555544de..03c3f3217 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -433,7 +433,7 @@ class k2_tree return n_marked_edges; } - int get_number_edges() const + uint16_t get_number_edges() const { return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } @@ -532,7 +532,6 @@ class k2_tree l[bit] = C[max_height - 1][bit]; } - k_t = t; k_l = l; k_t_rank = t_rank(&k_t); @@ -575,6 +574,29 @@ class k2_tree return *this; } + bool equal(const k2_tree &tr) const { + bool result = true; + + result &= n_vertices == tr.n_vertices; + result &= k_k == tr.k_k; + result &= k_height == tr.k_height; + + if(k_t.size() != tr.k_t.size()) + return false; + else { + for(unsigned int i = 0; i < k_t.size(); ++i) + result &= k_t[i] == tr.k_t[i]; + } + + if(k_l.size() != tr.k_l.size()) + return false; + else { + for(unsigned int i = 0; i < k_l.size(); ++i) + result &= k_l[i] == tr.k_l[i]; + } + return result; + } + //! Swap operator void swap(k2_tree &tr) { @@ -784,6 +806,7 @@ class k2_tree written_bytes += k_l_rank.serialize(out, child, "l_rank"); written_bytes += write_member(k_k, out, child, "k"); written_bytes += write_member(k_height, out, child, "height"); + written_bytes += write_member(n_vertices, out, child, "n_vertices"); structure_tree::add_size(child, written_bytes); return written_bytes; } @@ -802,6 +825,7 @@ class k2_tree k_l_rank.set_vector(&k_l); read_member(k_k, in); read_member(k_height, in); + read_member(n_vertices, in); } bool erase(idx_type i, idx_type j) diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index d776a4a19..05dca85df 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -62,6 +62,7 @@ void check_serialize_load(t_tree &tree) tree.serialize(ss); unserialized_tree.load(ss); ASSERT_EQ(tree, unserialized_tree); + ASSERT_TRUE(tree.equal(unserialized_tree)); } }; // namespace k2_tree_test_nm From fa0c38b5c2af985258de3b4b309f1140499e0cc4 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 12 Aug 2020 13:19:08 +0100 Subject: [PATCH 37/57] Optimize union operation --- include/sdsl/k2_tree.hpp | 104 ++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 03c3f3217..e2bd748af 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -21,7 +21,6 @@ #ifndef INCLUDED_SDSL_K2_TREE #define INCLUDED_SDSL_K2_TREE -#include #include #include #include @@ -31,6 +30,8 @@ #include "sdsl/k2_tree_iterator.hpp" #include "sdsl/int_vector_buffer.hpp" + +#include //! Namespace for the succint data structure library namespace sdsl { @@ -322,7 +323,7 @@ class k2_tree k_height = std::ceil(std::log(matrix.size()) / std::log(k_k)); build_from_matrix(matrix); - this->n_vertices = matrix.size(); + this->n_vertices = matrix.size(); } //! Constructor @@ -336,7 +337,7 @@ class k2_tree */ k2_tree(std::vector> &edges, const size_type size) - { + { assert(size > 0); assert(edges.size() > 0); @@ -443,7 +444,6 @@ class k2_tree return std::pow(k, k_height); } - using value_type = uint64_t; //! Union Operation /*! Performs the union operation between two tree. This operations requires both * trees to have the same number of nodes. @@ -466,74 +466,90 @@ class k2_tree if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) throw std::logic_error("Trees must have the same number of nodes."); - value_type t_size_A = this->t().size(); - value_type t_size_B = k2_B.t().size(); + const ulong t_size_A = k_t.size(); + const ulong t_size_B = k2_B.k_t.size(); + + const ulong l_size_A = k_l.size(); + const ulong l_size_B = k2_B.k_l.size(); // C Initialization - const value_type max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; - std::deque> C(max_height); + const ulong max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; + + ulong calc = 1; + ulong max_bits = 0; + for (ulong i = 0; i < max_height; i++) + { + calc *= k_k*k_k; + max_bits += calc; + } + + ulong C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + bit_vector C_t(C_t_size); + + max_bits += k_k*k_k; + + ulong C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + bit_vector C_l(C_l_size); //////// // Q Initialization - std::deque> Q; - Q.push_back({0, 1, 1}); + std::queue> Q; + Q.push({0, 1, 1}); //////// - std::array next; - value_type pA, pB; + std::array next; + uint64_t pA, pB; pA = 0; pB = 0; + uint64_t l, rA, rB, bA, bB; + size_type idx_t, idx_l; + idx_l = 0; + idx_t = 0; + while (!Q.empty()) { next = Q.front(); - Q.pop_front(); + Q.pop(); - value_type l = next[0]; - value_type rA = next[1]; - value_type rB = next[2]; - for (value_type i = 0; i < k_k * k_k; ++i) { - value_type bA, bB; + l = next[0]; + rA = next[1]; + rB = next[2]; + for (uint64_t i = 0; i < k_k * k_k; ++i) { bA = 0; bB = 0; if (rA == 1) { - if (l + 1 < this->k_height) - bA = this->t()[pA]; + if (l + 1 < k_height) + bA = k_t[pA]; else - bA = this->l()[pA - t_size_A]; + bA = k_l[pA - t_size_A]; pA++; } if (rB == 1) { if (l + 1 < k2_B.k_height) bB = k2_B.k_t[pB]; else - bB = k2_B.l()[pB - t_size_B]; + bB = k2_B.k_l[pB - t_size_B]; pB++; } - C[l].push_back(bA || bB); - if ((l + 1 < this->k_height || l + 1 < k2_B.k_height) && (bA || bB)) - Q.push_back({l + 1, bA, bB}); - } - } - - // Create new K2 tree from union operation - value_type t_size = 0; - for (value_type j = 0; j < max_height - 1; j++) - t_size += C[j].size(); - - t_bv t(t_size, 0); - t_bv l(C[max_height - 1].size(), 0); - value_type p = 0; - for (value_type i = 0; i < max_height - 1; i++) - for (value_type bit = 0; bit < C[i].size(); bit++) { - t[p] = C[i][bit]; - ++p; + if (l + 1 < k_height || l + 1 < k2_B.k_height) { + if(bA || bB) + Q.push({l + 1, bA, bB}); + C_t[idx_t] = (uint64_t) bA || bB; + idx_t++; + } else { + C_l[idx_l] = (uint64_t) bA || bB; + idx_l++; + } } - for (value_type bit = 0; bit < C[max_height - 1].size(); bit++) { - l[bit] = C[max_height - 1][bit]; } - k_t = t; - k_l = l; + C_t.resize(idx_t); + C_l.resize(idx_l); + + k_t = bit_vector(); + k_l = bit_vector(); + k_t = C_t; + k_l = C_l; k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); k_height = max_height; From c10e635749088c357000aa5e8762b56e1ca134f3 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 12 Aug 2020 22:54:03 +0100 Subject: [PATCH 38/57] Improve edge_iterator interface --- include/sdsl/k2_tree_iterator.hpp | 8 ++ test/k2_tree_test.cpp | 136 +++++++++++++++--------------- 2 files changed, 76 insertions(+), 68 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index deee33398..0fd62c8c3 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -45,6 +45,14 @@ namespace sdsl _initialize(); } + idx_type x() { + return get<0>(_ptr); + } + + idx_type y() { + return get<1>(_ptr); + } + value_type operator*() { return _ptr; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 05dca85df..e76fa6c47 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -279,33 +279,33 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) {0, 0, 1, 0}}); TypeParam tree(mat); auto edge_iterator = tree.edge_begin(); - ASSERT_EQ(std::get<0>(*edge_iterator), (size_t)0); - ASSERT_EQ(std::get<1>(*edge_iterator), (size_t)0); + ASSERT_EQ(edge_iterator.x(), (size_t)0); + ASSERT_EQ(edge_iterator.y(), (size_t)0); // OPERATOR ASSIGNMENT auto another_edge_iterator = edge_iterator; ASSERT_FALSE(&another_edge_iterator == &edge_iterator); - ASSERT_EQ(std::get<0>(*another_edge_iterator), (size_t) 0); - ASSERT_EQ(std::get<1>(*another_edge_iterator), (size_t) 0); + ASSERT_EQ(another_edge_iterator.x(), (size_t) 0); + ASSERT_EQ(another_edge_iterator.y(), (size_t) 0); // //OPERATOR INCREMENT // // ++edge_iterator; // also works edge_iterator++; - ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 0); - ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 1); + ASSERT_EQ(edge_iterator.x(), (size_t) 0); + ASSERT_EQ(edge_iterator.y(), (size_t) 1); edge_iterator++; - ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 2); - ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); + ASSERT_EQ(edge_iterator.x(), (size_t) 2); + ASSERT_EQ(edge_iterator.y(), (size_t) 2); edge_iterator++; - ASSERT_EQ(std::get<0>(*edge_iterator), (size_t) 3); - ASSERT_EQ(std::get<1>(*edge_iterator), (size_t) 2); + ASSERT_EQ(edge_iterator.x(), (size_t) 3); + ASSERT_EQ(edge_iterator.y(), (size_t) 2); edge_iterator++; //find last auto last = tree.edge_end(); - ASSERT_EQ(std::get<0>(*last), tree.get_number_nodes()); - ASSERT_EQ(std::get<1>(*last), tree.get_number_nodes()); + ASSERT_EQ(last.x(), tree.get_number_nodes()); + ASSERT_EQ(last.y(), tree.get_number_nodes()); // OPERATOR EQUALS ASSERT_TRUE(edge_iterator == tree.edge_end()); @@ -327,42 +327,42 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) auto it = treeIntensive.edge_begin(); - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 2); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 4); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 4); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 3); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 3); - ASSERT_EQ(std::get<1>(*it), (size_t) 4); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 4); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 3); - ASSERT_EQ(std::get<1>(*it), (size_t) 9); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 9); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 5); - ASSERT_EQ(std::get<1>(*it), (size_t) 0); + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 0); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 5); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 6); - ASSERT_EQ(std::get<1>(*it), (size_t) 0); + ASSERT_EQ(it.x(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 0); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 7); - ASSERT_EQ(std::get<1>(*it), (size_t) 0); + ASSERT_EQ(it.x(), (size_t) 7); + ASSERT_EQ(it.y(), (size_t) 0); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 9); - ASSERT_EQ(std::get<1>(*it), (size_t) 0); + ASSERT_EQ(it.x(), (size_t) 9); + ASSERT_EQ(it.y(), (size_t) 0); //OPERATION SWAP swap(last, another_edge_iterator); - ASSERT_EQ(std::get<0>(*last), (size_t) 0); - ASSERT_EQ(std::get<1>(*last), (size_t) 0); - ASSERT_EQ(std::get<0>(*another_edge_iterator), tree.get_number_nodes()); - ASSERT_EQ(std::get<1>(*another_edge_iterator), tree.get_number_nodes()); + ASSERT_EQ(last.x(), (size_t) 0); + ASSERT_EQ(last.y(), (size_t) 0); + ASSERT_EQ(another_edge_iterator.x(), tree.get_number_nodes()); + ASSERT_EQ(another_edge_iterator.y(), tree.get_number_nodes()); } TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { @@ -377,53 +377,53 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { }); TypeParam tree(mat); auto it = tree.edge_begin(); - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 2); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 3); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 3); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 4); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 4); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 5); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 5); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 1); - ASSERT_EQ(std::get<1>(*it), (size_t) 6); + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 6); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 2); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 2); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 2); - ASSERT_EQ(std::get<1>(*it), (size_t) 4); + ASSERT_EQ(it.x(), (size_t) 2); + ASSERT_EQ(it.y(), (size_t) 4); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 3); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 3); - ASSERT_EQ(std::get<1>(*it), (size_t) 5); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 5); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 4); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 4); - ASSERT_EQ(std::get<1>(*it), (size_t) 2); + ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 5); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 5); - ASSERT_EQ(std::get<1>(*it), (size_t) 3); + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 3); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 5); - ASSERT_EQ(std::get<1>(*it), (size_t) 6); + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 6); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 6); - ASSERT_EQ(std::get<1>(*it), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(std::get<0>(*it), (size_t) 6); - ASSERT_EQ(std::get<1>(*it), (size_t) 5); + ASSERT_EQ(it.x(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 5); } TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { From c559a61cc0b9866f610fcb141508af4abf7995bf Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 15 Aug 2020 17:28:46 +0100 Subject: [PATCH 39/57] Implement another edge iterator --- include/sdsl/k2_tree.hpp | 52 +++++-- include/sdsl/k2_tree_iterator.hpp | 250 +++++++++++++++--------------- test/k2_tree_test.cpp | 68 +++++--- 3 files changed, 205 insertions(+), 165 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index e2bd748af..4504266e0 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -73,7 +73,8 @@ class k2_tree uint8_t k_k; uint16_t k_height = 0; - uint16_t n_marked_edges = 0; + uint64_t n_marked_edges = 0; + uint64_t n_total_edges = 0; size_t n_vertices = 0; void build_from_matrix(const std::vector> &matrix) @@ -119,6 +120,7 @@ class k2_tree k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + n_total_edges = k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } /*! Recursive function to retrieve list of neighbors. @@ -343,6 +345,7 @@ class k2_tree build_from_edges(edges, size); this->n_vertices = size; + n_total_edges = edges.size(); } //! Constructor @@ -384,7 +387,8 @@ class k2_tree std::tuple{buf_x[i], buf_y[i]}); build_from_edges(edges, size); - n_vertices = edges.size(); + n_vertices = size; + n_total_edges = edges.size(); } k2_tree(k2_tree &tr) @@ -397,14 +401,6 @@ class k2_tree *this = std::move(tr); } - k2_tree(t_bv &t, t_bv &l, uint16_t height, uint8_t k_branch) : k_k(k_branch), k_height(height) - { - k_t = t_bv(t); - k_l = t_bv(l); - k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); - } - t_bv t() const { return k_t; @@ -414,7 +410,17 @@ class k2_tree { return k_t_rank; } + + size_type rank_t(size_type i) const + { + return k_t_rank(i); + } + size_type rank_l(size_type i) const + { + return k_l_rank(i); + } + t_bv l() const { return k_l; @@ -429,7 +435,7 @@ class k2_tree return k_height; } - uint8_t get_marked_edges() const + uint64_t get_marked_edges() const { return n_marked_edges; } @@ -439,9 +445,9 @@ class k2_tree return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); } - idx_type get_number_nodes() const + size_t get_number_nodes() const { - return std::pow(k, k_height); + return n_vertices; } //! Union Operation @@ -507,6 +513,8 @@ class k2_tree idx_l = 0; idx_t = 0; + n_total_edges = 0; + while (!Q.empty()) { next = Q.front(); Q.pop(); @@ -539,6 +547,7 @@ class k2_tree } else { C_l[idx_l] = (uint64_t) bA || bB; idx_l++; + if(bA || bB) n_total_edges++; } } } @@ -553,6 +562,7 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); k_height = max_height; + n_marked_edges = 0; } //! Move assignment operator @@ -568,6 +578,7 @@ class k2_tree k_l_rank = l_rank(&k_l); n_vertices = std::move(tr.n_vertices); n_marked_edges = std::move(tr.n_marked_edges); + n_total_edges = std::move(tr.n_total_edges); } return *this; } @@ -585,6 +596,7 @@ class k2_tree k_l_rank = l_rank(&k_l); n_vertices = tr.n_vertices; n_marked_edges = tr.n_marked_edges; + n_total_edges = tr.n_total_edges; } return *this; @@ -626,6 +638,7 @@ class k2_tree std::swap(k_height, tr.k_height); std::swap(n_vertices, tr.n_vertices); std::swap(n_marked_edges, tr.n_marked_edges); + std::swap(n_total_edges, tr.n_total_edges); } } @@ -823,6 +836,9 @@ class k2_tree written_bytes += write_member(k_k, out, child, "k"); written_bytes += write_member(k_height, out, child, "height"); written_bytes += write_member(n_vertices, out, child, "n_vertices"); + written_bytes += write_member(n_marked_edges, out, child, "n_marked_edges"); + written_bytes += write_member(n_total_edges, out, child, "n_total_edges"); + structure_tree::add_size(child, written_bytes); return written_bytes; } @@ -842,6 +858,9 @@ class k2_tree read_member(k_k, in); read_member(k_height, in); read_member(n_vertices, in); + read_member(n_marked_edges, in); + read_member(n_total_edges, in); + } bool erase(idx_type i, idx_type j) @@ -874,16 +893,21 @@ class k2_tree n = n / k_k; } - if (k_l[level - k_t.size()] == 1) + if(k_l[level - k_t.size()] == 1) { k_l[level - k_t.size()] = 0; k_l_rank = l_rank(&k_l); n_marked_edges++; + // clock_t end = clock(); return true; } return false; } + uint64_t total_edges() const { + return n_total_edges; + } + edg_iterator edge_begin() { return edg_iterator(this); diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 0fd62c8c3..2add9bec7 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -17,16 +18,7 @@ namespace sdsl using size_type = k2_tree_ns::size_type; using edge = std::tuple; - typedef struct tree_node - { - int node; - size_type n; - unsigned row, col; - idx_type level; - unsigned j; - size_type y; - } tree_node; - + /////////////////////////////////////////////////////////////////////////////////////////////// template class edge_iterator { @@ -68,27 +60,6 @@ namespace sdsl return !(*this == rhs); } - void print() - { - cout << "_ptr " << std::get<0>(_ptr) << ", " << std::get<1>(_ptr) << endl; - cout << "_node " << _node << endl; - cout << "_level " << _level << endl; - cout << "_row " << _row << endl; - cout << "st " << endl; - - for (tree_node st_i : st) - { - - cout << " node: " << st_i.node << endl; - cout << " row: " << st_i.row << endl; - cout << " n: " << st_i.n << endl; - cout << " level: " << st_i.level << endl; - cout << " j: " << st_i.j << endl; - cout << " y: " << st_i.y << endl; - cout << endl; - } - } - edge_iterator &operator++(int) { operator++(); @@ -97,58 +68,43 @@ namespace sdsl edge_iterator &operator++() { + edge e(nodes, nodes); while (!st.empty()) // did not go until the end of the subtree { - tree_node &last_found = st.back(); - last_found.j++; - idx_type neigh; - if (last_found.n == _n / k && last_found.j < k) - { - if (_find_next_recursive(last_found.n / k, - last_found.row % last_found.n, - last_found.col + last_found.n * last_found.j, - last_found.y + last_found.j, - neigh, 0)) - { - _ptr = edge(last_found.node, neigh); - return *this; - } - } - if (last_found.j < k) - { - if (_find_next_recursive(last_found.n / k, - last_found.row % last_found.n, - last_found.col + last_found.n * last_found.j, - last_found.y + last_found.j, - neigh, last_found.j)) - { - _ptr = edge(last_found.node, neigh); - return *this; - } - } + struct edge_node last_found = st.back(); st.pop_back(); - } // move to another subtree - _row++; - if (_row >= k) - { - _row = 0; - _node++; - _level = k * std::floor(_node / static_cast(_n)); + int type = last_found.type; + uint i = last_found.i; + uint j = last_found.j; + + uint dp = last_found.dp; + uint dq = last_found.dq; + uint y = last_found.y; + int l = last_found.l; + // + + j++; + if(j < k) { + if(_find_next_rec(dp, dq, y, l, type, i, j, e)) + break; + } else { + j = 0; + i++; + if(i < k) { + if(_find_next_rec(dp, dq, y, l, type, i, j, e)) + break; + } + } } - _ptr = _find_next(); + _ptr = e; return *this; } edge_iterator end() { edge_iterator it = *this; - it._ptr = edge(size, size); //end node - - it._node = size - 1; - it._level = k * std::floor(it._node / static_cast(it._n)); - it._row = k; - + it._ptr = edge(nodes, nodes); //end node return it; } @@ -160,10 +116,10 @@ namespace sdsl std::swap(rhs.k, lhs.k); std::swap(rhs._ptr, lhs._ptr); - std::swap(rhs.size, lhs.size); - std::swap(rhs._node, lhs._node); - std::swap(rhs._level, lhs._level); - std::swap(rhs._row, lhs._row); + std::swap(rhs.nodes, lhs.nodes); + std::swap(rhs.max_level, lhs.max_level); + std::swap(rhs.div_level_table, lhs.div_level_table); + std::swap(rhs.st, lhs.st); } } @@ -185,85 +141,123 @@ namespace sdsl uint8_t k = 2; // // iterator state // - deque st; - size_type _n; - idx_type _level; - int _row, _node, size; + class edge_node { + public: + uint dp, dq, y, i, j, type; + int l; + + edge_node() {} + edge_node(uint dp, uint dq, uint y, uint i, uint j, uint type, int l) : dp(dp), dq(dq), + y(y), i(i), j(j), type(type), l(l) {} + }; + std::deque st; + uint32_t max_level; + uint64_t nodes; + std::vector div_level_table; + std::vector pointerL; // + uint exp_pow(uint base, uint pow) + { + uint i, result = 1; + for (i = 0; i < pow; i++) + result *= base; + + return result; + } + void _initialize() { - _n = static_cast(std::pow(k, tree->height())) / k; - _node = 0; - _row = 0; - _level = k * std::floor(_node / static_cast(_n)); - size = std::pow(k, tree->height()); - if (tree->l().size() > 0) { - _ptr = _find_next(); + nodes = tree->get_number_nodes(); + + max_level = floor(log(nodes)/log(k)); + if(floor(log(nodes)/log(k)) == (log(nodes)/log(k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(uint i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k, max_level-i); + + pointerL = std::vector(max_level+1); + pointerL[0] = 0; + pointerL[1] = k*k; + + for(uint i = 2; i < max_level; i++) { + pointerL[i] = (tree->rank_t(pointerL[i-1]-1)+1)*k*k; + } + pointerL[max_level] = 0; + + edge e = edge(nodes, nodes); + _find_next(0, 0, -1, -1, e); + _ptr = e; } else { // if its empty the begin == end - _ptr = edge(size, size); //end node + _ptr = edge(nodes, nodes); //end node } } - edge _find_next() + bool _find_next(uint dp, uint dq, int x, int l, edge &e) { - idx_type neigh; - if (_node < size) - { - for (; _row < k; _row++) - { - neigh = size; - _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); - if (neigh < (idx_type)size) - { - return edge(_node, neigh); + if(l == (int)max_level){ + if(tree->l()[x] == 1) { + e = edge(dp, dq); + return true; + } + return false; + } + if((l == (int)max_level-1) && tree->t()[x] == 1) { + uint y = pointerL[l+1]; + pointerL[l+1] += k*k; + + for(uint i = 0; i < k; i++) { + for(uint j = 0; j < k; j++) { + st.push_back(edge_node(dp, dq, y, i, j, 1, l)); + if(_find_next(dp+i, dq+j, y+k*i+j, l+1, e)) + return true; + st.pop_back(); } - assert(st.empty()); } - _row = 0; - _node++; - _level = k * std::floor(_node / static_cast(_n)); - return _find_next(); + return false; } - return edge(size, size); // end node - } - - bool _find_next_recursive(size_type n, unsigned row, unsigned col, size_type level, - idx_type &neigh, unsigned initial_j) - { - if (level >= tree->t().size()) - { // Last level - if (tree->l()[level - tree->t().size()] == 1) - { - neigh = col; - return true; + if((x == -1) || ((l < (int)max_level-1) && tree->t()[x] ==1 )) { + uint y = pointerL[l+1]; + pointerL[l+1] += k*k; + + uint div_level = div_level_table[l+1]; + + for(uint i = 0; i < k; i++) { + for(uint j = 0; j < k; j++) { + st.push_back(edge_node(dp, dq, y, i, j, 2, l)); + if(_find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e)) + return true; + st.pop_back(); + } } return false; } - if (tree->t()[level] == 1) - { - size_type y = tree->rank_t()(level + 1) * k * k + - k * std::floor(row / static_cast(n)); + return false; + } - for (unsigned j = initial_j; j < k; j++) - { - tree_node next_node = {_node, n, row, col, level, j, y}; - st.push_back(next_node); - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) - return true; - st.pop_back(); - } + + bool _find_next_rec(uint dp, uint dq, int y, int l, uint type, uint i, uint j, edge &e) { + if(type == 1) { + st.push_back(edge_node(dp, dq, y, i, j, 1, l )); + return _find_next(dp+i, dq +j, y+k*i+j, l+1, e); + } else if(type == 2){ + uint div_level = div_level_table[l+1]; + st.push_back(edge_node(dp, dq, y, i, j, 2, l)); + return _find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e); } return false; } }; + ////////////////////////////////////////////////////////////////////////////////////////////// template class node_iterator diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index e76fa6c47..1c728501d 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -1,5 +1,5 @@ -#include "sdsl/k2_tree.hpp" #include "gtest/gtest.h" +#include "sdsl/k2_tree.hpp" #include #include @@ -208,6 +208,8 @@ TYPED_TEST(k2_tree_test_k_2, build_from_edges_array) e.push_back(t_tuple{2, 2}); tree = TypeParam(e, 3); k2_tree_test_nm::check_t_l(tree, {1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0}); + ASSERT_EQ(e.size(), (size_t)5); + ASSERT_EQ(tree.total_edges(), (uint64_t)5); } TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) @@ -330,17 +332,14 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(it.x(), (size_t) 1); ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 4); - it++; ASSERT_EQ(it.x(), (size_t) 3); ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.x(), (size_t) 1); ASSERT_EQ(it.y(), (size_t) 4); it++; ASSERT_EQ(it.x(), (size_t) 3); - ASSERT_EQ(it.y(), (size_t) 9); + ASSERT_EQ(it.y(), (size_t) 4); it++; ASSERT_EQ(it.x(), (size_t) 5); ASSERT_EQ(it.y(), (size_t) 0); @@ -354,6 +353,9 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(it.x(), (size_t) 7); ASSERT_EQ(it.y(), (size_t) 0); it++; + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 9); + it++; ASSERT_EQ(it.x(), (size_t) 9); ASSERT_EQ(it.y(), (size_t) 0); @@ -377,12 +379,19 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { }); TypeParam tree(mat); auto it = tree.edge_begin(); + ASSERT_EQ(it.x(), (size_t) 1); ASSERT_EQ(it.y(), (size_t) 2); it++; ASSERT_EQ(it.x(), (size_t) 1); ASSERT_EQ(it.y(), (size_t) 3); it++; + ASSERT_EQ(it.x(), (size_t) 2); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 1); + it++; ASSERT_EQ(it.x(), (size_t) 1); ASSERT_EQ(it.y(), (size_t) 4); it++; @@ -393,35 +402,29 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { ASSERT_EQ(it.y(), (size_t) 6); it++; ASSERT_EQ(it.x(), (size_t) 2); - ASSERT_EQ(it.y(), (size_t) 1); - it++; - ASSERT_EQ(it.x(), (size_t) 2); ASSERT_EQ(it.y(), (size_t) 4); it++; ASSERT_EQ(it.x(), (size_t) 3); - ASSERT_EQ(it.y(), (size_t) 1); - it++; - ASSERT_EQ(it.x(), (size_t) 3); ASSERT_EQ(it.y(), (size_t) 5); it++; ASSERT_EQ(it.x(), (size_t) 4); ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(it.x(), (size_t) 4); - ASSERT_EQ(it.y(), (size_t) 2); - it++; ASSERT_EQ(it.x(), (size_t) 5); ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(it.x(), (size_t) 5); - ASSERT_EQ(it.y(), (size_t) 3); + ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 2); it++; ASSERT_EQ(it.x(), (size_t) 5); - ASSERT_EQ(it.y(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 3); it++; ASSERT_EQ(it.x(), (size_t) 6); ASSERT_EQ(it.y(), (size_t) 1); it++; + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 6); + it++; ASSERT_EQ(it.x(), (size_t) 6); ASSERT_EQ(it.y(), (size_t) 5); } @@ -973,23 +976,42 @@ TYPED_TEST(k2_tree_test_marked, marked_edges) auto tree = TypeParam(mat); - ASSERT_EQ(tree.get_marked_edges(), 0); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)0); ASSERT_EQ(tree.get_number_edges(), 6); + ASSERT_EQ(tree.total_edges(), (uint64_t)6); + ASSERT_TRUE(tree.erase(0, 0)); - ASSERT_EQ(tree.get_marked_edges(), 1); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)1); ASSERT_EQ(tree.get_number_edges(), 5); ASSERT_TRUE(tree.erase(0, 4)); - ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)2); ASSERT_EQ(tree.get_number_edges(), 4); ASSERT_FALSE(tree.erase(0, 4)); - ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)2); ASSERT_EQ(tree.get_number_edges(), 4); ASSERT_FALSE(tree.erase(1, 2)); - ASSERT_EQ(tree.get_marked_edges(), 2); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)2); ASSERT_EQ(tree.get_number_edges(), 4); + + ASSERT_TRUE(tree.erase(2, 2)); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)3); + ASSERT_EQ(tree.get_number_edges(), 3); + + ASSERT_TRUE(tree.erase(2, 3)); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)4); + ASSERT_EQ(tree.get_number_edges(), 2); + + ASSERT_TRUE(tree.erase(4, 2)); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)5); + ASSERT_EQ(tree.get_number_edges(), 1); + + ASSERT_TRUE(tree.erase(4, 4)); + ASSERT_EQ(tree.get_marked_edges(), (uint64_t)6); + ASSERT_EQ(tree.get_number_edges(), 0); + } } // namespace From 6b6d0c63ddab293bfd336ae28a8f10cc0dc915b7 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 19 Aug 2020 14:47:53 +0100 Subject: [PATCH 40/57] Fix edge_iterator --- include/sdsl/k2_tree.hpp | 164 +++++++++++++---- include/sdsl/k2_tree_iterator.hpp | 297 +++++++++++++++++++++++++++--- test/k2_tree_test.cpp | 164 ++++++++++++----- 3 files changed, 524 insertions(+), 101 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 4504266e0..b9c104d9a 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -47,7 +47,7 @@ namespace sdsl * (pp. 18-30). Springer Berlin Heidelberg. */ -template @@ -70,11 +70,12 @@ class k2_tree t_rank k_t_rank; l_rank k_l_rank; - uint8_t k_k; + uint16_t k_k; uint16_t k_height = 0; uint64_t n_marked_edges = 0; uint64_t n_total_edges = 0; + uint64_t n_edges = 0; size_t n_vertices = 0; void build_from_matrix(const std::vector> &matrix) @@ -121,6 +122,7 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); n_total_edges = k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + n_edges = n_total_edges; } /*! Recursive function to retrieve list of neighbors. @@ -346,6 +348,7 @@ class k2_tree build_from_edges(edges, size); this->n_vertices = size; n_total_edges = edges.size(); + n_edges = n_total_edges; } //! Constructor @@ -389,6 +392,8 @@ class k2_tree build_from_edges(edges, size); n_vertices = size; n_total_edges = edges.size(); + n_edges = n_total_edges; + } k2_tree(k2_tree &tr) @@ -427,7 +432,7 @@ class k2_tree } - uint8_t k_() const { + uint16_t k_() const { return k_k; } @@ -440,9 +445,9 @@ class k2_tree return n_marked_edges; } - uint16_t get_number_edges() const + uint64_t get_number_edges() const { - return k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + return k_l.size() == 0? 0: k_l_rank(k_l.size()); } size_t get_number_nodes() const @@ -469,32 +474,36 @@ class k2_tree return; } - if (pow(this->k_k, this->k_height) != pow(this->k_k, k2_B.k_height)) + if (this->n_vertices != k2_B.n_vertices) throw std::logic_error("Trees must have the same number of nodes."); + if (this->k_height != k2_B.k_height) + throw std::logic_error("Trees must have the same height."); + + const uint64_t max_height = this->k_height; - const ulong t_size_A = k_t.size(); - const ulong t_size_B = k2_B.k_t.size(); + const uint64_t t_size_A = k_t.size(); + const uint64_t t_size_B = k2_B.k_t.size(); - const ulong l_size_A = k_l.size(); - const ulong l_size_B = k2_B.k_l.size(); + const uint64_t l_size_A = k_l.size(); + const uint64_t l_size_B = k2_B.k_l.size(); // C Initialization - const ulong max_height = this->k_height > k2_B.k_height ? this->k_height : k2_B.k_height; - - ulong calc = 1; - ulong max_bits = 0; - for (ulong i = 0; i < max_height; i++) + + uint64_t calc = 1; + uint64_t max_bits = 0; + for (uint64_t i = 0; i < max_height; i++) { calc *= k_k*k_k; max_bits += calc; } - ulong C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + uint64_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; bit_vector C_t(C_t_size); - max_bits += k_k*k_k; + calc *= k_k*k_k; + max_bits += calc; - ulong C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + uint64_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; bit_vector C_l(C_l_size); //////// @@ -509,11 +518,12 @@ class k2_tree pB = 0; uint64_t l, rA, rB, bA, bB; - size_type idx_t, idx_l; + uint64_t idx_t, idx_l; idx_l = 0; idx_t = 0; n_total_edges = 0; + uint64_t last_level = 0; while (!Q.empty()) { next = Q.front(); @@ -526,43 +536,49 @@ class k2_tree bA = 0; bB = 0; if (rA == 1) { - if (l + 1 < k_height) + if (l < max_height-1) bA = k_t[pA]; else bA = k_l[pA - t_size_A]; pA++; } if (rB == 1) { - if (l + 1 < k2_B.k_height) + if (l < max_height-1) bB = k2_B.k_t[pB]; else bB = k2_B.k_l[pB - t_size_B]; pB++; } - if (l + 1 < k_height || l + 1 < k2_B.k_height) { - if(bA || bB) - Q.push({l + 1, bA, bB}); - C_t[idx_t] = (uint64_t) bA || bB; + if (l < max_height-1) { + if((l == max_height-2) && (bA || bB)) last_level++; + if(bA || bB) { + Q.push({l + 1, bA, bB}); + C_t[idx_t] = 1; + } idx_t++; } else { - C_l[idx_l] = (uint64_t) bA || bB; + if(bA || bB) { + C_l[idx_l] = 1; + n_total_edges++; + } idx_l++; - if(bA || bB) n_total_edges++; } } } - + + assert(C_t_size >= idx_t); C_t.resize(idx_t); + + assert(C_l_size >= idx_l); C_l.resize(idx_l); - k_t = bit_vector(); - k_l = bit_vector(); - k_t = C_t; - k_l = C_l; + k_t = t_bv(C_t); + k_l = t_bv(C_l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); k_height = max_height; n_marked_edges = 0; + n_edges = n_total_edges; } //! Move assignment operator @@ -579,6 +595,7 @@ class k2_tree n_vertices = std::move(tr.n_vertices); n_marked_edges = std::move(tr.n_marked_edges); n_total_edges = std::move(tr.n_total_edges); + n_edges = std::move(tr.n_edges); } return *this; } @@ -597,6 +614,7 @@ class k2_tree n_vertices = tr.n_vertices; n_marked_edges = tr.n_marked_edges; n_total_edges = tr.n_total_edges; + n_edges = tr.n_edges; } return *this; @@ -639,6 +657,7 @@ class k2_tree std::swap(n_vertices, tr.n_vertices); std::swap(n_marked_edges, tr.n_marked_edges); std::swap(n_total_edges, tr.n_total_edges); + std::swap(n_edges, tr.n_edges); } } @@ -660,6 +679,11 @@ class k2_tree return true; } + bool operator!=(const k2_tree &tr) const + { + return !(*this == tr); + } + //! Indicates whether node j is adjacent to node i or not. /*! @@ -838,6 +862,7 @@ class k2_tree written_bytes += write_member(n_vertices, out, child, "n_vertices"); written_bytes += write_member(n_marked_edges, out, child, "n_marked_edges"); written_bytes += write_member(n_total_edges, out, child, "n_total_edges"); + written_bytes += write_member(n_edges, out, child, "n_edges"); structure_tree::add_size(child, written_bytes); return written_bytes; @@ -860,6 +885,7 @@ class k2_tree read_member(n_vertices, in); read_member(n_marked_edges, in); read_member(n_total_edges, in); + read_member(n_edges, in); } @@ -896,9 +922,10 @@ class k2_tree if(k_l[level - k_t.size()] == 1) { k_l[level - k_t.size()] = 0; + assert(k_l[level - k_t.size()] == 0); k_l_rank = l_rank(&k_l); n_marked_edges++; - // clock_t end = clock(); + n_edges--; return true; } return false; @@ -935,6 +962,77 @@ class k2_tree neigh_iterator neighbour_end() { return neigh_iterator(this).end(); } + + + + std::vector pointerL; + std::vector div_level_table; + uint16_t max_level; + uint64_t times; + + uint exp_pow(uint base, uint pow) + { + uint i, result = 1; + for (i = 0; i < pow; i++) + result *= base; + + return result; + } + + void edge_it_rec(uint64_t dp, uint64_t dq, int64_t x, int16_t l, std::function func) { + + if(l == (uint16_t)max_level) { + if(k_l[x] == 1) { + times++; + func(dp, dq); + } + } + + if(((l == (uint16_t)max_level-1) && (x != -1) && k_t[x] == 1)) { + uint64_t y = pointerL[l+1]; + pointerL[l+1] += k_k*k_k; + + for(int64_t i = 0; i < k_k; i++) { + for(int64_t j = 0; j < k_k; j++) { + edge_it_rec(dp+i, dq+j, y+k_k*i+j, l+1, func); + } + } + } + + if((x == -1) || ((l < (uint16_t)max_level-1) && (k_t[x] == 1) )) { + uint64_t y = pointerL[l+1]; + pointerL[l+1] += k_k*k_k; + + uint64_t div_level = div_level_table[l+1]; + for(uint64_t i = 0; i < k_k; i++) { + for(uint64_t j = 0; j < k_k; j++) { + edge_it_rec(dp+div_level*i, dq+div_level*j, y+k_k*i+j, l+1, func); + } + } + } + } + std::vector maxL; + void edge_it(std::function func) { + max_level = floor(log(n_vertices)/log(k_k)); + if(floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(uint64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); + + pointerL = std::vector(max_level+1); + pointerL[0] = 0; + pointerL[1] = k_k*k_k; + + for(uint16_t i = 2; i < max_level; i++) { + pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; + } + pointerL[max_level] = 0; + times = 0; + edge_it_rec(0, 0, -1, -1, func); + cout << "times:" << times << endl; + } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 2add9bec7..8988680db 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -18,6 +18,254 @@ namespace sdsl using size_type = k2_tree_ns::size_type; using edge = std::tuple; + + // typedef struct tree_node + // { + // int node; + // size_type n; + // unsigned row, col; + // idx_type level; + // unsigned j; + // size_type y; + // } tree_node; + + // template + // class edge_iterator + // { + // public: + // using value_type = edge; + // using pointer = shared_ptr; + // using reference = edge &; + // using iterator_category = std::forward_iterator_tag; + + // edge_iterator() {} + + // edge_iterator(const k_tree *tree) + // { + // this->tree = tree; + // this->k = tree->k_(); + // _initialize(); + // } + + // idx_type x() { + // return get<0>(_ptr); + // } + + // idx_type y() { + // return get<1>(_ptr); + // } + + // value_type operator*() + // { + // return _ptr; + // } + + // bool operator==(const edge_iterator &rhs) const + // { + // return equal_edge(rhs._ptr, _ptr); + // } + + // bool operator!=(const edge_iterator &rhs) const + // { + // return !(*this == rhs); + // } + + // void print() + // { + // cout << "_ptr " << std::get<0>(_ptr) << ", " << std::get<1>(_ptr) << endl; + // cout << "_node " << _node << endl; + // cout << "_level " << _level << endl; + // cout << "_row " << _row << endl; + // cout << "st " << endl; + + // for (tree_node st_i : st) + // { + + // cout << " node: " << st_i.node << endl; + // cout << " row: " << st_i.row << endl; + // cout << " n: " << st_i.n << endl; + // cout << " level: " << st_i.level << endl; + // cout << " j: " << st_i.j << endl; + // cout << " y: " << st_i.y << endl; + // cout << endl; + // } + // } + + // edge_iterator &operator++(int) + // { + // operator++(); + // return *this; + // } + + // edge_iterator &operator++() + // { + // while (!st.empty()) // did not go until the end of the subtree + // { + // tree_node &last_found = st.back(); + // last_found.j++; + // idx_type neigh; + // if (last_found.n == _n / k && last_found.j < k) + // { + // if (_find_next_recursive(last_found.n / k, + // last_found.row % last_found.n, + // last_found.col + last_found.n * last_found.j, + // last_found.y + last_found.j, + // neigh, 0)) + // { + // _ptr = edge(last_found.node, neigh); + // return *this; + // } + // } + // if (last_found.j < k) + // { + // if (_find_next_recursive(last_found.n / k, + // last_found.row % last_found.n, + // last_found.col + last_found.n * last_found.j, + // last_found.y + last_found.j, + // neigh, last_found.j)) + // { + // _ptr = edge(last_found.node, neigh); + // return *this; + // } + // } + // st.pop_back(); + + // } // move to another subtree + // _row++; + // if (_row >= k) + // { + // _row = 0; + // _node++; + // _level = k * std::floor(_node / static_cast(_n)); + // } + // _ptr = _find_next(); + // return *this; + // } + + // edge_iterator end() + // { + // edge_iterator it = *this; + // it._ptr = edge(size, size); //end node + + // it._node = size - 1; + // it._level = k * std::floor(it._node / static_cast(it._n)); + // it._row = k; + + // return it; + // } + + // friend void swap(edge_iterator &rhs, edge_iterator &lhs) + // { + // if (&rhs != &lhs) + // { + // std::swap(rhs.tree, lhs.tree); + // std::swap(rhs.k, lhs.k); + + // std::swap(rhs._ptr, lhs._ptr); + // std::swap(rhs.size, lhs.size); + // std::swap(rhs._node, lhs._node); + // std::swap(rhs._level, lhs._level); + // std::swap(rhs._row, lhs._row); + // } + // } + + // private: + // bool equal_edge(const edge &e1, const edge &e2) const + // { + // idx_type e1_x = std::get<0>(e1); + // idx_type e1_y = std::get<1>(e1); + + // idx_type e2_x = std::get<0>(e2); + // idx_type e2_y = std::get<1>(e2); + + // return e1_x == e2_x && e1_y == e2_y; + // } + + // value_type _ptr; + // // container + // const k_tree *tree; + // uint8_t k = 2; + // // + // // iterator state // + // deque st; + // size_type _n; + // idx_type _level; + // int _row, _node, size; + // // + + // void + // _initialize() + // { + // _n = static_cast(std::pow(k, tree->height())) / k; + // _node = 0; + // _row = 0; + // _level = k * std::floor(_node / static_cast(_n)); + // size = std::pow(k, tree->height()); + + // if (tree->l().size() > 0) + // { + // _ptr = _find_next(); + // } + // else + // { + // // if its empty the begin == end + // _ptr = edge(size, size); //end node + // } + // } + + // edge _find_next() + // { + // idx_type neigh; + // if (_node < size) + // { + // for (; _row < k; _row++) + // { + // neigh = size; + // _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); + // if (neigh < (idx_type)size) + // { + // return edge(_node, neigh); + // } + // assert(st.empty()); + // } + // _row = 0; + // _node++; + // _level = k * std::floor(_node / static_cast(_n)); + // return _find_next(); + // } + // return edge(size, size); // end node + // } + + // bool _find_next_recursive(size_type n, unsigned row, unsigned col, size_type level, + // idx_type &neigh, unsigned initial_j) + // { + // if (level >= tree->t().size()) + // { // Last level + // if (tree->l()[level - tree->t().size()] == 1) + // { + // neigh = col; + // return true; + // } + // return false; + // } + + // if (tree->t()[level] == 1) + // { + // size_type y = tree->rank_t()(level + 1) * k * k + + // k * std::floor(row / static_cast(n)); + + // for (unsigned j = initial_j; j < k; j++) + // { + // tree_node next_node = {_node, n, row, col, level, j, y}; + // st.push_back(next_node); + // if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) + // return true; + // st.pop_back(); + // } + // } + // return false; + // } + // }; /////////////////////////////////////////////////////////////////////////////////////////////// template class edge_iterator @@ -34,6 +282,7 @@ namespace sdsl { this->tree = tree; this->k = tree->k_(); + nodes = tree->get_number_nodes(); _initialize(); } @@ -78,9 +327,9 @@ namespace sdsl uint i = last_found.i; uint j = last_found.j; - uint dp = last_found.dp; - uint dq = last_found.dq; - uint y = last_found.y; + uint64_t dp = last_found.dp; + uint64_t dq = last_found.dq; + int64_t y = last_found.y; int l = last_found.l; // @@ -143,12 +392,13 @@ namespace sdsl // iterator state // class edge_node { public: - uint dp, dq, y, i, j, type; - int l; + uint64_t dp, dq, i, j; + int64_t y; + int type, l; edge_node() {} - edge_node(uint dp, uint dq, uint y, uint i, uint j, uint type, int l) : dp(dp), dq(dq), - y(y), i(i), j(j), type(type), l(l) {} + edge_node(uint64_t dp, uint64_t dq, int64_t y, uint64_t i, uint64_t j, int type, int l) : dp(dp), dq(dq), + i(i), j(j), y(y), type(type), l(l) {} }; std::deque st; uint32_t max_level; @@ -171,8 +421,6 @@ namespace sdsl { if (tree->l().size() > 0) { - nodes = tree->get_number_nodes(); - max_level = floor(log(nodes)/log(k)); if(floor(log(nodes)/log(k)) == (log(nodes)/log(k))) max_level = max_level-1; @@ -182,11 +430,12 @@ namespace sdsl div_level_table[i] = exp_pow(k, max_level-i); pointerL = std::vector(max_level+1); + pointerL[0] = 0; pointerL[1] = k*k; - for(uint i = 2; i < max_level; i++) { - pointerL[i] = (tree->rank_t(pointerL[i-1]-1)+1)*k*k; + for(uint64_t i = 2; i < max_level; i++) { + pointerL[i] = (tree->rank_t(pointerL[i-1])+1)*k*k; } pointerL[max_level] = 0; @@ -201,21 +450,21 @@ namespace sdsl } } - bool _find_next(uint dp, uint dq, int x, int l, edge &e) + bool _find_next(uint64_t dp, uint64_t dq, int64_t x, int l, edge &e) { - if(l == (int)max_level){ + if(l == (int64_t)max_level){ if(tree->l()[x] == 1) { e = edge(dp, dq); return true; } return false; } - if((l == (int)max_level-1) && tree->t()[x] == 1) { - uint y = pointerL[l+1]; + if((l == (int64_t)max_level-1) && tree->t()[x] == 1) { + int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; - for(uint i = 0; i < k; i++) { - for(uint j = 0; j < k; j++) { + for(uint64_t i = 0; i < k; i++) { + for(uint64_t j = 0; j < k; j++) { st.push_back(edge_node(dp, dq, y, i, j, 1, l)); if(_find_next(dp+i, dq+j, y+k*i+j, l+1, e)) return true; @@ -224,14 +473,14 @@ namespace sdsl } return false; } - if((x == -1) || ((l < (int)max_level-1) && tree->t()[x] ==1 )) { - uint y = pointerL[l+1]; + if((x == -1) || ((l < (int64_t)max_level-1) && tree->t()[x] ==1 )) { + int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; - uint div_level = div_level_table[l+1]; + uint64_t div_level = div_level_table[l+1]; - for(uint i = 0; i < k; i++) { - for(uint j = 0; j < k; j++) { + for(uint64_t i = 0; i < k; i++) { + for(uint64_t j = 0; j < k; j++) { st.push_back(edge_node(dp, dq, y, i, j, 2, l)); if(_find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e)) return true; @@ -245,12 +494,12 @@ namespace sdsl } - bool _find_next_rec(uint dp, uint dq, int y, int l, uint type, uint i, uint j, edge &e) { + bool _find_next_rec(uint64_t dp, uint64_t dq, int64_t y, int l, int type, uint64_t i, uint64_t j, edge &e) { if(type == 1) { st.push_back(edge_node(dp, dq, y, i, j, 1, l )); return _find_next(dp+i, dq +j, y+k*i+j, l+1, e); } else if(type == 2){ - uint div_level = div_level_table[l+1]; + uint64_t div_level = div_level_table[l+1]; st.push_back(edge_node(dp, dq, y, i, j, 2, l)); return _find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e); } diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 1c728501d..f7dff845b 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -271,6 +271,84 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); } +TYPED_TEST(k2_tree_test_k_2, edge_iterator_empty_test) { + + TypeParam tree; + ASSERT_EQ(tree.edge_begin(), tree.edge_end()); + + vector> mat1({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}); + + TypeParam emptyTree(mat1); + ASSERT_EQ(emptyTree.edge_begin().x(), (uint)4); + ASSERT_EQ(emptyTree.edge_begin().y(), (uint)4); +} + + +TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { + vector> mat({ + {0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1}, + {0, 1, 0, 0, 1, 0, 0}, + {0, 1, 0, 0, 0, 1, 0}, + {0, 1, 1, 0, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 1}, + {0, 1, 0, 0, 0, 1, 0}, + }); + TypeParam tree(mat); + auto it = tree.edge_begin(); + + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 2); + it++; + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 3); + it++; + ASSERT_EQ(it.x(), (size_t) 2); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 4); + it++; + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 5); + it++; + ASSERT_EQ(it.x(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 6); + it++; + ASSERT_EQ(it.x(), (size_t) 2); + ASSERT_EQ(it.y(), (size_t) 4); + it++; + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 5); + it++; + ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 2); + it++; + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 3); + it++; + ASSERT_EQ(it.x(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 1); + it++; + ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.y(), (size_t) 6); + it++; + ASSERT_EQ(it.x(), (size_t) 6); + ASSERT_EQ(it.y(), (size_t) 5); +} + TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) { @@ -367,66 +445,52 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test) ASSERT_EQ(another_edge_iterator.y(), tree.get_number_nodes()); } -TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_star) { - vector> mat({ - {0, 0, 0, 0, 0, 0, 0}, - {0, 0, 1, 1, 1, 1, 1}, - {0, 1, 0, 0, 1, 0, 0}, - {0, 1, 0, 0, 0, 1, 0}, - {0, 1, 1, 0, 0, 0, 0}, - {0, 1, 0, 1, 0, 0, 1}, - {0, 1, 0, 0, 0, 1, 0}, - }); - TypeParam tree(mat); - auto it = tree.edge_begin(); +TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_union) { + vector> mat({{1, 1, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 1}, + {0, 0, 1, 0}}); - ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 2); - it++; - ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 3); - it++; - ASSERT_EQ(it.x(), (size_t) 2); - ASSERT_EQ(it.y(), (size_t) 1); + TypeParam tree_A(mat); + + mat = vector>({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 0, 1}}); + TypeParam tree_B(mat); + + tree_A.unionOp(tree_B); + + auto it = tree_A.edge_begin(); + + ASSERT_EQ(it.x(), (size_t) 0); + ASSERT_EQ(it.y(), (size_t) 0); it++; - ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.x(), (size_t) 0); ASSERT_EQ(it.y(), (size_t) 1); it++; ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 4); - it++; - ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 5); - it++; - ASSERT_EQ(it.x(), (size_t) 1); - ASSERT_EQ(it.y(), (size_t) 6); - it++; - ASSERT_EQ(it.x(), (size_t) 2); - ASSERT_EQ(it.y(), (size_t) 4); + ASSERT_EQ(it.y(), (size_t) 1); it++; ASSERT_EQ(it.x(), (size_t) 3); - ASSERT_EQ(it.y(), (size_t) 5); - it++; - ASSERT_EQ(it.x(), (size_t) 4); - ASSERT_EQ(it.y(), (size_t) 1); + ASSERT_EQ(it.y(), (size_t) 0); it++; - ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.x(), (size_t) 3); ASSERT_EQ(it.y(), (size_t) 1); it++; - ASSERT_EQ(it.x(), (size_t) 4); + ASSERT_EQ(it.x(), (size_t) 2); ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(it.x(), (size_t) 5); + ASSERT_EQ(it.x(), (size_t) 2); ASSERT_EQ(it.y(), (size_t) 3); it++; - ASSERT_EQ(it.x(), (size_t) 6); - ASSERT_EQ(it.y(), (size_t) 1); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 2); it++; - ASSERT_EQ(it.x(), (size_t) 5); - ASSERT_EQ(it.y(), (size_t) 6); + ASSERT_EQ(it.x(), (size_t) 3); + ASSERT_EQ(it.y(), (size_t) 3); it++; - ASSERT_EQ(it.x(), (size_t) 6); - ASSERT_EQ(it.y(), (size_t) 5); + ASSERT_EQ(it, tree_A.edge_end()); } TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { @@ -1014,6 +1078,18 @@ TYPED_TEST(k2_tree_test_marked, marked_edges) } +TYPED_TEST(k2_tree_test_marked, edge_it) { + vector> mat({{1, 0, 0, 0, 1}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0}, + {0, 0, 1, 0, 1}}); + + auto tree = TypeParam(mat); + TypeParam t = tree; + tree.edge_it([t] (uint64_t i, uint64_t j)-> void { ASSERT_TRUE(t.adj(i,j)); }); +} + } // namespace int main(int argc, char **argv) From fac2fca7e89dd73a2d9708a18c405fc66fdc6008 Mon Sep 17 00:00:00 2001 From: Joana H Date: Thu, 20 Aug 2020 17:01:41 +0100 Subject: [PATCH 41/57] Remove k_l_rank construction - (really)bad for performance --- include/sdsl/k2_tree.hpp | 205 +++++++++++++++++++++++++++++++++------ test/k2_tree_test.cpp | 18 ++-- 2 files changed, 185 insertions(+), 38 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index b9c104d9a..bbabb88b0 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -78,6 +78,11 @@ class k2_tree uint64_t n_edges = 0; size_t n_vertices = 0; + std::vector pointerL; + std::vector div_level_table; + int16_t max_level; + uint last_level_rank = 0; + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -328,6 +333,14 @@ class k2_tree build_from_matrix(matrix); this->n_vertices = matrix.size(); + + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); } //! Constructor @@ -349,6 +362,13 @@ class k2_tree this->n_vertices = size; n_total_edges = edges.size(); n_edges = n_total_edges; + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); } //! Constructor @@ -394,6 +414,13 @@ class k2_tree n_total_edges = edges.size(); n_edges = n_total_edges; + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); } k2_tree(k2_tree &tr) @@ -447,7 +474,8 @@ class k2_tree uint64_t get_number_edges() const { - return k_l.size() == 0? 0: k_l_rank(k_l.size()); + // return k_l.size() == 0? 0: k_l_rank(k_l.size()); + return n_edges; } size_t get_number_nodes() const @@ -596,6 +624,9 @@ class k2_tree n_marked_edges = std::move(tr.n_marked_edges); n_total_edges = std::move(tr.n_total_edges); n_edges = std::move(tr.n_edges); + max_level = std::move(tr.max_level); + div_level_table = std::move(tr.div_level_table); + last_level_rank = std::move(tr.last_level_rank); } return *this; } @@ -615,6 +646,9 @@ class k2_tree n_marked_edges = tr.n_marked_edges; n_total_edges = tr.n_total_edges; n_edges = tr.n_edges; + max_level = tr.max_level; + div_level_table = tr.div_level_table; + last_level_rank = tr.last_level_rank; } return *this; @@ -658,6 +692,9 @@ class k2_tree std::swap(n_marked_edges, tr.n_marked_edges); std::swap(n_total_edges, tr.n_total_edges); std::swap(n_edges, tr.n_edges); + std::swap(max_level, tr.max_level); + std::swap(div_level_table, tr.div_level_table); + std::swap(last_level_rank, tr.last_level_rank); } } @@ -725,6 +762,58 @@ class k2_tree return k_l[level - k_t.size()] == 1; } + bool contains(uint p, uint q) + { + if(k_l.size() > 0) { + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); + + std::vector pL (max_level+1); + pL[0] = 0; + pL[1] = k_k*k_k; + + for(int16_t i = 2; i < max_level; i++) { + pL[i] = (k_t_rank(pL[i-1])+1)*k_k*k_k; + } + pL[max_level] = 0; + + if(max_level > 0) + last_level_rank = pL[max_level-1] == 0? 0 : k_t_rank(pL[max_level-1]); + else + last_level_rank = 0; + + return adj_rec(p, q, 0, 0); + } + return false; + } + + bool adj_rec(uint p, uint q, uint64_t node, int level) + { + int div_level = div_level_table[level]; + uint64_t newnode = p / div_level * k_k + q / div_level; + newnode += node; + + if(level == max_level && k_l[newnode]) { + return true; + } + else if (level < max_level - 1 && k_t[newnode]) + { + return adj_rec(p % div_level, q % div_level, k_t_rank(newnode+1) * k_k * k_k, level + 1); + } + else if(level == max_level - 1 && k_t[newnode]) + { + uint64_t posInf = (k_t_rank(newnode) - last_level_rank) * k_k * k_k; + uint64_t shift = (q % k_k + (p % k_k) * k_k); + return k_l[posInf + shift]; + } + return false; + } + //! Returns a list of neighbors of node i. /*! * \param i Node to get neighbors from. @@ -887,6 +976,14 @@ class k2_tree read_member(n_total_edges, in); read_member(n_edges, in); + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; + + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); + } bool erase(idx_type i, idx_type j) @@ -923,7 +1020,7 @@ class k2_tree { k_l[level - k_t.size()] = 0; assert(k_l[level - k_t.size()] == 0); - k_l_rank = l_rank(&k_l); + // k_l_rank = l_rank(&k_l); n_marked_edges++; n_edges--; return true; @@ -964,13 +1061,7 @@ class k2_tree } - - std::vector pointerL; - std::vector div_level_table; - uint16_t max_level; - uint64_t times; - - uint exp_pow(uint base, uint pow) + uint exp_pow(uint base, uint pow) { uint i, result = 1; for (i = 0; i < pow; i++) @@ -981,14 +1072,13 @@ class k2_tree void edge_it_rec(uint64_t dp, uint64_t dq, int64_t x, int16_t l, std::function func) { - if(l == (uint16_t)max_level) { + if(l == max_level) { if(k_l[x] == 1) { - times++; func(dp, dq); } } - if(((l == (uint16_t)max_level-1) && (x != -1) && k_t[x] == 1)) { + if(((l == max_level-1) && (x != -1) && k_t[x] == 1)) { uint64_t y = pointerL[l+1]; pointerL[l+1] += k_k*k_k; @@ -999,7 +1089,7 @@ class k2_tree } } - if((x == -1) || ((l < (uint16_t)max_level-1) && (k_t[x] == 1) )) { + if((x == -1) || ((l < max_level-1) && (k_t[x] == 1) )) { uint64_t y = pointerL[l+1]; pointerL[l+1] += k_k*k_k; @@ -1011,28 +1101,85 @@ class k2_tree } } } - std::vector maxL; + void edge_it(std::function func) { - max_level = floor(log(n_vertices)/log(k_k)); - if(floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) - max_level = max_level-1; + if(k_l.size() > 0) { + max_level = floor(log(n_vertices)/log(k_k)); + if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) + max_level = max_level-1; - div_level_table = std::vector(max_level+1); - for(uint64_t i = 0; i <= max_level; i++) - div_level_table[i] = exp_pow(k_k, max_level-i); + div_level_table = std::vector(max_level+1); + for(int64_t i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k_k, max_level-i); - pointerL = std::vector(max_level+1); - pointerL[0] = 0; - pointerL[1] = k_k*k_k; + pointerL = std::vector(max_level+1); + pointerL[0] = 0; + pointerL[1] = k_k*k_k; - for(uint16_t i = 2; i < max_level; i++) { - pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; + for(int16_t i = 2; i < max_level; i++) { + pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; + } + pointerL[max_level] = 0; + edge_it_rec(0, 0, -1, -1, func); } - pointerL[max_level] = 0; - times = 0; - edge_it_rec(0, 0, -1, -1, func); - cout << "times:" << times << endl; } + + // bool erase(uint p, uint q) + // { + // if(k_l.size() > 0) { + + + // std::vector pL (max_level+1); + // pL[0] = 0; + // pL[1] = k_k*k_k; + + // for(int16_t i = 2; i < max_level; i++) { + // pL[i] = (k_t_rank(pL[i-1])+1)*k_k*k_k; + // } + // pL[max_level] = 0; + + // if(max_level > 0) + // last_level_rank = pL[max_level-1] == 0? 0 : k_t_rank(pL[max_level-1]); + // else + // last_level_rank = 0; + + // return recursiveMarkLinkDeleted(p, q, 0, 0); + // } + // return false; + // } + + // uint recursiveMarkLinkDeleted(uint p, uint q, uint64_t node, int level) + // { + // int div_level = div_level_table[level]; + // uint64_t newnode = p / div_level * k_k + q / div_level; + // newnode += node; + + // if(level == max_level && k_l[newnode]) { + // k_l[newnode] = 0; + // // k_l_rank = l_rank(&k_l); + // n_marked_edges++; + // n_edges--; + // return true; + // } + // else if (level < max_level - 1 && k_t[newnode]) + // { + // return recursiveMarkLinkDeleted(p % div_level, q % div_level, k_t_rank(newnode+1) * k_k * k_k, level + 1); + // } + // else if(level == max_level - 1 && k_t[newnode]) + // { + // uint64_t posInf = (k_t_rank(newnode) - last_level_rank) * k_k * k_k; + // uint64_t shift = (q % k_k + (p % k_k) * k_k); + // if (k_l[posInf + shift]) + // { + // k_l[posInf + shift] = 0; + // // k_l_rank = l_rank(&k_l); + // n_marked_edges++; + // n_edges--; + // return true; + // } + // } + // return false; + // } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index f7dff845b..b252a0330 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -984,20 +984,20 @@ TYPED_TEST(k2_tree_test, adj_test) {0, 0, 1, 0, 1}}); auto tree = TypeParam(mat); - ASSERT_TRUE(tree.adj(0, 0)); - ASSERT_TRUE(tree.adj(0, 4)); - ASSERT_FALSE(tree.adj(4, 0)); - ASSERT_TRUE(tree.adj(4, 4)); - ASSERT_FALSE(tree.adj(1, 1)); - ASSERT_TRUE(tree.adj(2, 2)); - ASSERT_TRUE(tree.adj(2, 3)); + ASSERT_TRUE(tree.contains(0, 0)); + ASSERT_TRUE(tree.contains(0, 4)); + ASSERT_FALSE(tree.contains(4, 0)); + ASSERT_TRUE(tree.contains(4, 4)); + ASSERT_FALSE(tree.contains(1, 1)); + ASSERT_TRUE(tree.contains(2, 2)); + ASSERT_TRUE(tree.contains(2, 3)); mat = vector>({{0}}); tree = TypeParam(mat); - ASSERT_FALSE(tree.adj(0, 0)); + ASSERT_FALSE(tree.contains(0, 0)); mat = vector>({{1}}); tree = TypeParam(mat); - ASSERT_TRUE(tree.adj(0, 0)); + ASSERT_TRUE(tree.contains(0, 0)); } TYPED_TEST(k2_tree_test, serialize_test) From 346c4cecd46567c6853792b21397cbd15b245852 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 22 Aug 2020 14:28:51 +0100 Subject: [PATCH 42/57] Change sizes in queue in unionOp --- include/sdsl/k2_tree.hpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index bbabb88b0..9867cc9b6 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -536,22 +536,19 @@ class k2_tree //////// // Q Initialization - std::queue> Q; + std::queue> Q; Q.push({0, 1, 1}); //////// - std::array next; - uint64_t pA, pB; + std::array next; + uint16_t l, rA, rB, bA, bB; + uint64_t pA, pB, idx_t, idx_l; pA = 0; pB = 0; - - uint64_t l, rA, rB, bA, bB; - uint64_t idx_t, idx_l; idx_l = 0; idx_t = 0; - + n_total_edges = 0; - uint64_t last_level = 0; while (!Q.empty()) { next = Q.front(); @@ -570,6 +567,7 @@ class k2_tree bA = k_l[pA - t_size_A]; pA++; } + uint64_t old_pb = pB; if (rB == 1) { if (l < max_height-1) bB = k2_B.k_t[pB]; @@ -577,8 +575,8 @@ class k2_tree bB = k2_B.k_l[pB - t_size_B]; pB++; } + if (l < max_height-1) { - if((l == max_height-2) && (bA || bB)) last_level++; if(bA || bB) { Q.push({l + 1, bA, bB}); C_t[idx_t] = 1; @@ -593,7 +591,6 @@ class k2_tree } } } - assert(C_t_size >= idx_t); C_t.resize(idx_t); @@ -758,7 +755,6 @@ class k2_tree level = k_t_rank(level + 1) * k_2 + k_k * row + col; n = n / k_k; } - return k_l[level - k_t.size()] == 1; } @@ -1082,8 +1078,8 @@ class k2_tree uint64_t y = pointerL[l+1]; pointerL[l+1] += k_k*k_k; - for(int64_t i = 0; i < k_k; i++) { - for(int64_t j = 0; j < k_k; j++) { + for(uint i = 0; i < k_k; i++) { + for(uint j = 0; j < k_k; j++) { edge_it_rec(dp+i, dq+j, y+k_k*i+j, l+1, func); } } @@ -1094,8 +1090,8 @@ class k2_tree pointerL[l+1] += k_k*k_k; uint64_t div_level = div_level_table[l+1]; - for(uint64_t i = 0; i < k_k; i++) { - for(uint64_t j = 0; j < k_k; j++) { + for(uint i = 0; i < k_k; i++) { + for(uint j = 0; j < k_k; j++) { edge_it_rec(dp+div_level*i, dq+div_level*j, y+k_k*i+j, l+1, func); } } @@ -1116,7 +1112,7 @@ class k2_tree pointerL[0] = 0; pointerL[1] = k_k*k_k; - for(int16_t i = 2; i < max_level; i++) { + for(uint i = 2; i < max_level; i++) { pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; } pointerL[max_level] = 0; From 76c718f3b098751c97fc9e8db113f5918bbe6f35 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 2 Sep 2020 18:54:09 +0100 Subject: [PATCH 43/57] Fix edge and neighbour iterator --- include/sdsl/k2_tree.hpp | 89 +++++++++---------------------- include/sdsl/k2_tree_iterator.hpp | 25 ++++----- 2 files changed, 37 insertions(+), 77 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 9867cc9b6..4863da5e0 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -83,6 +83,8 @@ class k2_tree int16_t max_level; uint last_level_rank = 0; + edg_iterator it_e_begin, it_e_end; + void build_from_matrix(const std::vector> &matrix) { // Makes the size a power of k. @@ -438,6 +440,18 @@ class k2_tree return k_t; } + const t_bv *p_t() const{ + return &k_t; + } + + const t_bv *p_l() const { + return &k_l; + } + + const t_rank *p_rank_t() const{ + return &k_t_rank; + } + t_rank rank_t() const { return k_t_rank; @@ -541,7 +555,8 @@ class k2_tree //////// std::array next; - uint16_t l, rA, rB, bA, bB; + short unsigned l; + uint16_t rA, rB, bA, bB; uint64_t pA, pB, idx_t, idx_l; pA = 0; pB = 0; @@ -557,7 +572,7 @@ class k2_tree l = next[0]; rA = next[1]; rB = next[2]; - for (uint64_t i = 0; i < k_k * k_k; ++i) { + for (size_t i = 0; i < k_k * k_k; ++i) { bA = 0; bB = 0; if (rA == 1) { @@ -567,7 +582,6 @@ class k2_tree bA = k_l[pA - t_size_A]; pA++; } - uint64_t old_pb = pB; if (rB == 1) { if (l < max_height-1) bB = k2_B.k_t[pB]; @@ -1028,14 +1042,16 @@ class k2_tree return n_total_edges; } - edg_iterator edge_begin() + edg_iterator &edge_begin() { - return edg_iterator(this); + it_e_begin = edg_iterator(this); + it_e_end = it_e_begin.end(); + return it_e_begin; } - edg_iterator edge_end() + edg_iterator &edge_end() { - return edg_iterator(this).end(); + return it_e_end; } nod_iterator node_begin() @@ -1112,70 +1128,13 @@ class k2_tree pointerL[0] = 0; pointerL[1] = k_k*k_k; - for(uint i = 2; i < max_level; i++) { + for(size_t i = 2; i < max_level; i++) { pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; } pointerL[max_level] = 0; edge_it_rec(0, 0, -1, -1, func); } } - - // bool erase(uint p, uint q) - // { - // if(k_l.size() > 0) { - - - // std::vector pL (max_level+1); - // pL[0] = 0; - // pL[1] = k_k*k_k; - - // for(int16_t i = 2; i < max_level; i++) { - // pL[i] = (k_t_rank(pL[i-1])+1)*k_k*k_k; - // } - // pL[max_level] = 0; - - // if(max_level > 0) - // last_level_rank = pL[max_level-1] == 0? 0 : k_t_rank(pL[max_level-1]); - // else - // last_level_rank = 0; - - // return recursiveMarkLinkDeleted(p, q, 0, 0); - // } - // return false; - // } - - // uint recursiveMarkLinkDeleted(uint p, uint q, uint64_t node, int level) - // { - // int div_level = div_level_table[level]; - // uint64_t newnode = p / div_level * k_k + q / div_level; - // newnode += node; - - // if(level == max_level && k_l[newnode]) { - // k_l[newnode] = 0; - // // k_l_rank = l_rank(&k_l); - // n_marked_edges++; - // n_edges--; - // return true; - // } - // else if (level < max_level - 1 && k_t[newnode]) - // { - // return recursiveMarkLinkDeleted(p % div_level, q % div_level, k_t_rank(newnode+1) * k_k * k_k, level + 1); - // } - // else if(level == max_level - 1 && k_t[newnode]) - // { - // uint64_t posInf = (k_t_rank(newnode) - last_level_rank) * k_k * k_k; - // uint64_t shift = (q % k_k + (p % k_k) * k_k); - // if (k_l[posInf + shift]) - // { - // k_l[posInf + shift] = 0; - // // k_l_rank = l_rank(&k_l); - // n_marked_edges++; - // n_edges--; - // return true; - // } - // } - // return false; - // } }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 8988680db..be3c90a24 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -276,7 +276,8 @@ namespace sdsl using reference = edge &; using iterator_category = std::forward_iterator_tag; - edge_iterator() {} + edge_iterator() = default; + edge_iterator(const k_tree *tree) { @@ -352,7 +353,7 @@ namespace sdsl edge_iterator end() { - edge_iterator it = *this; + edge_iterator it; it._ptr = edge(nodes, nodes); //end node return it; } @@ -453,13 +454,13 @@ namespace sdsl bool _find_next(uint64_t dp, uint64_t dq, int64_t x, int l, edge &e) { if(l == (int64_t)max_level){ - if(tree->l()[x] == 1) { + if((*(tree->p_l()))[x] == 1) { e = edge(dp, dq); return true; } return false; } - if((l == (int64_t)max_level-1) && tree->t()[x] == 1) { + if((l == (int64_t)max_level-1) && (*(tree->p_t()))[x] == 1) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -473,7 +474,7 @@ namespace sdsl } return false; } - if((x == -1) || ((l < (int64_t)max_level-1) && tree->t()[x] ==1 )) { + if((x == -1) || ((l < (int64_t)max_level-1) && (*(tree->p_t()))[x] ==1 )) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -823,11 +824,11 @@ namespace sdsl return -1; // end node } - bool _find_next_recursive(value_type n, value_type row, value_type col, value_type level, value_type &neigh, unsigned initial_j) + bool _find_next_recursive(value_type n, value_type row, value_type col, uint level, value_type &neigh, unsigned initial_j) { - if (level >= (int)tree->t().size()) // Last level + if (level >= (*(tree->p_t())).size()) // Last level { - if (tree->l()[level - tree->t().size()] == 1) + if ((*(tree->p_l()))[level - (*(tree->p_t())).size()] == 1) { neigh = col; return true; @@ -835,9 +836,9 @@ namespace sdsl return false; } - if (tree->t()[level] == 1) + if ((*(tree->p_t()))[level] == 1) { - value_type y = tree->rank_t()(level + 1) * k * k + + value_type y = (*(tree->p_rank_t()))(level + 1) * k * k + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) @@ -855,8 +856,8 @@ namespace sdsl typedef struct tree_node2 { - value_type node, n, row, col, level; - unsigned j; + value_type node, n, row, col; + uint level, j; value_type y; } tree_node2; From 26749e2ddc2159c72ab0335893adb3c0b79669d1 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 5 Sep 2020 01:29:11 +0100 Subject: [PATCH 44/57] Add assignment and swap operations to neighbour ietrator --- include/sdsl/k2_tree.hpp | 4 ++- include/sdsl/k2_tree_iterator.hpp | 54 +++++++++++++++---------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 4863da5e0..ef2c0c156 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -84,6 +84,7 @@ class k2_tree uint last_level_rank = 0; edg_iterator it_e_begin, it_e_end; + neigh_iterator it_neigh_end; void build_from_matrix(const std::vector> &matrix) { @@ -1065,11 +1066,12 @@ class k2_tree } neigh_iterator neighbour_begin(idx_type node) { + it_neigh_end = neigh_iterator().end(); return neigh_iterator(this, node); } neigh_iterator neighbour_end() { - return neigh_iterator(this).end(); + return it_neigh_end; } diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index be3c90a24..88de46919 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -756,34 +756,32 @@ namespace sdsl return *this; } - // neighbour_iterator &operator=(const neighbour_iterator &other) { - // if (this != &other) { - // this->_ptr = other._ptr; - // this->tree = other.tree; - // this->k = other.k; - - // this->size = other.size; - // this->_n = other._n; - // this->_node = other._node; - // this->_level = other._level; - // this->_row = other._row; - // this->_n = other._n; - // } - // return *this; - // } - - // friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { - // std::swap(rhs._ptr, lhs._ptr); - // std::swap(rhs.tree, lhs.tree); - // std::swap(rhs.k, lhs.k); - - // std::swap(rhs.size, lhs.size); - // std::swap(rhs._n, lhs._n); - // std::swap(rhs._node, lhs._node); - // std::swap(rhs._level, lhs._level); - // std::swap(rhs._row, lhs._row); - // std::swap(rhs._n, lhs._n); - // } + neighbour_iterator &operator=(const neighbour_iterator &other) { + if (this != &other) { + _ptr = other._ptr; + tree = other.tree; + k = other.k; + st = other.st; + size = other.size; + _n = other._n; + _node = other._node; + _level = other._level; + _row = other._row; + } + return *this; + } + + friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { + std::swap(rhs._ptr, lhs._ptr); + std::swap(rhs.tree, lhs.tree); + std::swap(rhs.k, lhs.k); + std::swap(rhs.st, lhs.st); + std::swap(rhs.size, lhs.size); + std::swap(rhs._n, lhs._n); + std::swap(rhs._node, lhs._node); + std::swap(rhs._level, lhs._level); + std::swap(rhs._row, lhs._row); + } private: void From 3033ff5470672ec9f0693f9bfae1e6a4c49e9b33 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 5 Sep 2020 10:57:58 +0100 Subject: [PATCH 45/57] return reference in neighbour_end --- include/sdsl/k2_tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index ef2c0c156..6e1e391ae 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -1070,7 +1070,7 @@ class k2_tree return neigh_iterator(this, node); } - neigh_iterator neighbour_end() { + neigh_iterator &neighbour_end() { return it_neigh_end; } From 9cc342139b01a257a0a2aaf0a055beb56ba34ea4 Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 5 Sep 2020 14:02:55 +0100 Subject: [PATCH 46/57] Fix neighbour iterator and refactor --- include/sdsl/k2_tree.hpp | 54 +++++++++++++++++-------------- include/sdsl/k2_tree_iterator.hpp | 41 +++++++++-------------- test/k2_tree_test.cpp | 24 +++++++------- 3 files changed, 57 insertions(+), 62 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 6e1e391ae..8cb428503 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -436,44 +436,52 @@ class k2_tree *this = std::move(tr); } - t_bv t() const - { - return k_t; + bool is_bit_set_t(uint64_t i) const { + assert(i < k_t.size()); + return k_t[i] == 1; } - const t_bv *p_t() const{ - return &k_t; + bool is_bit_set_l(uint64_t i) const { + assert(i < k_l.size()); + return k_l[i] == 1; } - - const t_bv *p_l() const { - return &k_l; + + size_t t_size() const { + return k_t.size(); } - const t_rank *p_rank_t() const{ - return &k_t_rank; + size_t l_size() const { + return k_l.size(); } - t_rank rank_t() const - { - return k_t_rank; + size_t get_int_t(size_t i) { + assert(i < k_t.size()); + return k_t[i]; + } + + size_t get_int_l(size_t i) { + assert(i < k_l.size()); + return k_l[i]; + } + + bool t_empty() { + return k_t.empty(); + } + + bool l_empty() { + return k_l.empty(); } - size_type rank_t(size_type i) const + size_t rank_t(size_t i) const { return k_t_rank(i); } - size_type rank_l(size_type i) const + size_t rank_l(size_t i) const { return k_l_rank(i); } - t_bv l() const - { - return k_l; - } - - uint16_t k_() const { return k_k; } @@ -493,7 +501,7 @@ class k2_tree return n_edges; } - size_t get_number_nodes() const + size_type get_number_nodes() const { return n_vertices; } @@ -1030,8 +1038,6 @@ class k2_tree if(k_l[level - k_t.size()] == 1) { k_l[level - k_t.size()] = 0; - assert(k_l[level - k_t.size()] == 0); - // k_l_rank = l_rank(&k_l); n_marked_edges++; n_edges--; return true; diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 88de46919..2f5b5c59c 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -202,7 +202,7 @@ namespace sdsl // _level = k * std::floor(_node / static_cast(_n)); // size = std::pow(k, tree->height()); - // if (tree->l().size() > 0) + // if (tree->l_size() > 0) // { // _ptr = _find_next(); // } @@ -420,7 +420,7 @@ namespace sdsl void _initialize() { - if (tree->l().size() > 0) + if (tree->l_size() > 0) { max_level = floor(log(nodes)/log(k)); if(floor(log(nodes)/log(k)) == (log(nodes)/log(k))) @@ -454,13 +454,14 @@ namespace sdsl bool _find_next(uint64_t dp, uint64_t dq, int64_t x, int l, edge &e) { if(l == (int64_t)max_level){ - if((*(tree->p_l()))[x] == 1) { + if(tree->is_bit_set_l(x)) { e = edge(dp, dq); return true; } return false; } - if((l == (int64_t)max_level-1) && (*(tree->p_t()))[x] == 1) { + + if((l == (int64_t)max_level-1) && tree->is_bit_set_t(x)) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -474,7 +475,7 @@ namespace sdsl } return false; } - if((x == -1) || ((l < (int64_t)max_level-1) && (*(tree->p_t()))[x] ==1 )) { + if((x == -1) || ((l < (int64_t)max_level-1) && tree->is_bit_set_t(x))) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -703,25 +704,14 @@ namespace sdsl tree_node2 &last_found = st.back(); last_found.j++; value_type neigh; - if (last_found.n == _n / k && last_found.j < k) - { - if (_find_next_recursive(last_found.n / k, - last_found.row % last_found.n, - last_found.col + last_found.n * last_found.j, - last_found.y + last_found.j, - neigh, 0)) - { - _ptr = neigh; - return *this; - } - } + if (last_found.j < k) { if (_find_next_recursive(last_found.n / k, last_found.row % last_found.n, last_found.col + last_found.n * last_found.j, last_found.y + last_found.j, - neigh, last_found.j)) + neigh, 0)) { _ptr = neigh; return *this; @@ -792,7 +782,7 @@ namespace sdsl _level = k * std::floor(_node / static_cast(_n)); size = std::pow(k, tree->height()); - if (tree->l().size() > 0) + if (tree->l_size() > 0) { _ptr = _find_next(); } @@ -814,7 +804,6 @@ namespace sdsl _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); if (neigh < size) { - // cout << "x: " << _node << " y: " << neigh << endl; return neigh; } } @@ -824,9 +813,9 @@ namespace sdsl bool _find_next_recursive(value_type n, value_type row, value_type col, uint level, value_type &neigh, unsigned initial_j) { - if (level >= (*(tree->p_t())).size()) // Last level + if (level >= tree->t_size()) // Last level { - if ((*(tree->p_l()))[level - (*(tree->p_t())).size()] == 1) + if (tree->is_bit_set_l(level - tree->t_size()) == 1) { neigh = col; return true; @@ -834,14 +823,14 @@ namespace sdsl return false; } - if ((*(tree->p_t()))[level] == 1) + if (tree->is_bit_set_t(level) == 1) { - value_type y = (*(tree->p_rank_t()))(level + 1) * k * k + + value_type y = tree->rank_t(level + 1) * k * k + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) { - tree_node2 next_node = {_node, n, row, col, level, j, y}; + tree_node2 next_node = {n, row, col, level, j, y}; st.push_back(next_node); if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) return true; @@ -854,7 +843,7 @@ namespace sdsl typedef struct tree_node2 { - value_type node, n, row, col; + value_type n, row, col; uint level, j; value_type y; } tree_node2; diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index b252a0330..596d6610e 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -34,24 +34,24 @@ template void check_t_l(t_tree &tree, vector expected_t, vector expected_l) { - ASSERT_EQ(expected_t.size(), tree.t().size()); - ASSERT_EQ(expected_l.size(), tree.l().size()); + ASSERT_EQ(expected_t.size(), tree.t_size()); + ASSERT_EQ(expected_l.size(), tree.l_size()); for (unsigned i = 0; i < expected_t.size(); i++) - ASSERT_EQ(expected_t[i], tree.t().get_int(i, 1)); + ASSERT_EQ(expected_t[i], tree.get_int_t(i)); for (unsigned i = 0; i < expected_l.size(); i++) - ASSERT_EQ(expected_l[i], tree.l().get_int(i, 1)); + ASSERT_EQ(expected_l[i], tree.get_int_l(i)); } template void assert_eq_tree(t_tree &tree1, t_tree &tree2) { - ASSERT_EQ(tree1.t().size(), tree2.t().size()); - ASSERT_EQ(tree1.l().size(), tree2.l().size()); - for (unsigned i = 0; i < tree1.t().size(); i++) - ASSERT_EQ(tree1.t().get_int(i, 1), tree2.t().get_int(i, 1)); + ASSERT_EQ(tree1.t_size(), tree2.t_size()); + ASSERT_EQ(tree1.l_size(), tree2.l_size()); + for (unsigned i = 0; i < tree1.t_size(); i++) + ASSERT_EQ(tree1.get_int_t(i), tree2.get_int_t(i)); - for (unsigned i = 0; i < tree1.l().size(); i++) - ASSERT_EQ(tree1.l().get_int(i, 1), tree2.l().get_int(i, 1)); + for (unsigned i = 0; i < tree1.l_size(); i++) + ASSERT_EQ(tree1.get_int_l(i), tree2.get_int_l(i)); } template @@ -117,8 +117,8 @@ TYPED_TEST(k2_tree_test_k_2, build_from_matrix_test) mat = vector>({{0, 0}, {0, 0}}); tree = TypeParam(mat); - ASSERT_TRUE(tree.t().empty()); - ASSERT_TRUE(tree.l().empty()); + ASSERT_TRUE(tree.t_empty()); + ASSERT_TRUE(tree.l_empty()); // Size is minor than k: mat = vector>({{0}}); From 19dc49b242197c4ff80b4225b98467c967675e64 Mon Sep 17 00:00:00 2001 From: Joana H Date: Mon, 12 Oct 2020 09:30:22 +0100 Subject: [PATCH 47/57] Improve k2tree neighbor performance --- include/sdsl/k2_tree.hpp | 51 +++----- include/sdsl/k2_tree_iterator.hpp | 187 +++++++++++++++--------------- test/k2_tree_test.cpp | 9 +- 3 files changed, 110 insertions(+), 137 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 8cb428503..c68d9ea7f 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -60,9 +60,6 @@ class k2_tree using nod_iterator = node_iterator>; using neigh_iterator = neighbour_iterator>; -protected: - //! Bit array to store all the bits of the tree, except those in the - //! last level. t_bv k_t; //! Bit array to store the last level of the tree. t_bv k_l; @@ -73,6 +70,9 @@ class k2_tree uint16_t k_k; uint16_t k_height = 0; +protected: + //! Bit array to store all the bits of the tree, except those in the + //! last level. uint64_t n_marked_edges = 0; uint64_t n_total_edges = 0; uint64_t n_edges = 0; @@ -84,7 +84,7 @@ class k2_tree uint last_level_rank = 0; edg_iterator it_e_begin, it_e_end; - neigh_iterator it_neigh_end; + neigh_iterator it_neigh_begin, it_neigh_end = neigh_iterator().end(); void build_from_matrix(const std::vector> &matrix) { @@ -436,16 +436,6 @@ class k2_tree *this = std::move(tr); } - bool is_bit_set_t(uint64_t i) const { - assert(i < k_t.size()); - return k_t[i] == 1; - } - - bool is_bit_set_l(uint64_t i) const { - assert(i < k_l.size()); - return k_l[i] == 1; - } - size_t t_size() const { return k_t.size(); } @@ -472,23 +462,13 @@ class k2_tree return k_l.empty(); } - size_t rank_t(size_t i) const - { - return k_t_rank(i); - } - - size_t rank_l(size_t i) const - { - return k_l_rank(i); - } + // uint16_t k_() const { + // return k_k; + // } - uint16_t k_() const { - return k_k; - } - - uint16_t height() const { - return k_height; - } + // uint16_t height() const { + // return k_height; + // } uint64_t get_marked_edges() const { @@ -839,7 +819,7 @@ class k2_tree * \returns A list of neighbors of node i. */ std::vector neigh(idx_type i) const - { + { std::vector acc{}; if (k_l.size() == 0 && k_t.size() == 0) return acc; @@ -850,8 +830,9 @@ class k2_tree static_cast(std::pow(k_k, k_height)) / k_k; // y = k * i/n idx_type y = k_k * std::floor(i / static_cast(n)); - for (unsigned j = 0; j < k_k; j++) + for (unsigned j = 0; j < k_k; j++) { _neigh(n / k_k, i % n, n * j, y + j, acc); + } return acc; } @@ -1071,9 +1052,9 @@ class k2_tree return nod_iterator(this).end(); } - neigh_iterator neighbour_begin(idx_type node) { - it_neigh_end = neigh_iterator().end(); - return neigh_iterator(this, node); + neigh_iterator &neighbour_begin(idx_type node) { + it_neigh_begin = neigh_iterator(this, node); + return it_neigh_begin; } neigh_iterator &neighbour_end() { diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 2f5b5c59c..6d5c42bde 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -43,7 +43,7 @@ namespace sdsl // edge_iterator(const k_tree *tree) // { // this->tree = tree; - // this->k = tree->k_(); + // this->k = tree->k_k; // _initialize(); // } @@ -196,11 +196,11 @@ namespace sdsl // void // _initialize() // { - // _n = static_cast(std::pow(k, tree->height())) / k; + // _n = static_cast(std::pow(k, tree->k_height) / k; // _node = 0; // _row = 0; // _level = k * std::floor(_node / static_cast(_n)); - // size = std::pow(k, tree->height()); + // size = std::pow(k, tree->k_height; // if (tree->l_size() > 0) // { @@ -282,7 +282,7 @@ namespace sdsl edge_iterator(const k_tree *tree) { this->tree = tree; - this->k = tree->k_(); + this->k = tree->k_k; nodes = tree->get_number_nodes(); _initialize(); } @@ -436,7 +436,7 @@ namespace sdsl pointerL[1] = k*k; for(uint64_t i = 2; i < max_level; i++) { - pointerL[i] = (tree->rank_t(pointerL[i-1])+1)*k*k; + pointerL[i] = (tree->k_t_rank(pointerL[i-1])+1)*k*k; } pointerL[max_level] = 0; @@ -454,14 +454,14 @@ namespace sdsl bool _find_next(uint64_t dp, uint64_t dq, int64_t x, int l, edge &e) { if(l == (int64_t)max_level){ - if(tree->is_bit_set_l(x)) { + if(tree->k_l[x]) { e = edge(dp, dq); return true; } return false; } - if((l == (int64_t)max_level-1) && tree->is_bit_set_t(x)) { + if((l == (int64_t)max_level-1) && tree->k_t[x]) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -475,7 +475,7 @@ namespace sdsl } return false; } - if((x == -1) || ((l < (int64_t)max_level-1) && tree->is_bit_set_t(x))) { + if((x == -1) || ((l < (int64_t)max_level-1) && tree->k_t[x])) { int64_t y = pointerL[l+1]; pointerL[l+1] += k*k; @@ -662,29 +662,23 @@ namespace sdsl using size_type = k2_tree_ns::size_type; public: - using value_type = int; - using pointer = shared_ptr; - using reference = int &; + using value_type = size_type; + using pointer = shared_ptr; + using reference = size_type &; using iterator_category = std::forward_iterator_tag; - neighbour_iterator() {} + neighbour_iterator() { + _is_end = true; + } neighbour_iterator(const k_tree *tree, value_type node) { this->tree = tree; - this->k = tree->k_(); + this->k = tree->k_k; this->_node = node; _initialize(); } - neighbour_iterator(const k_tree *tree) - { - this->tree = tree; - this->k = tree->k_(); - this->_node = 0; - _initialize(); - } - value_type operator*() { return _ptr; @@ -692,7 +686,7 @@ namespace sdsl neighbour_iterator &operator++(int) { - if (_ptr != -1) + if (!_is_end) operator++(); return *this; } @@ -701,65 +695,65 @@ namespace sdsl { while (!st.empty()) // did not go until the end of the subtree { - tree_node2 &last_found = st.back(); - last_found.j++; + tree_node2 &last_found = st.front(); + ++last_found.j; value_type neigh; - if (last_found.j < k) - { + if (last_found.j < k) { if (_find_next_recursive(last_found.n / k, last_found.row % last_found.n, last_found.col + last_found.n * last_found.j, last_found.y + last_found.j, - neigh, 0)) - { + neigh, 0)) { _ptr = neigh; return *this; } } - st.pop_back(); - + st.pop_front(); } // move to another subtree - _row++; - if (_row >= k) - { - _ptr = -1; + ++_row; + if (_row >= k) { + _ptr = 0; + _is_end = true; return *this; } _ptr = _find_next(); return *this; } - bool operator==(const neighbour_iterator &rhs) const + bool operator==(neighbour_iterator &rhs) const { - return rhs._ptr == this->_ptr; + return rhs._ptr == _ptr && _is_end == rhs._is_end; } - bool operator!=(const neighbour_iterator &rhs) const + bool operator!=(neighbour_iterator &rhs) const { return !(*this == rhs); } - neighbour_iterator end() + const neighbour_iterator &end() { - _ptr = -1; + _ptr = 0; + _is_end = true; return *this; } - neighbour_iterator &operator=(const neighbour_iterator &other) { - if (this != &other) { - _ptr = other._ptr; - tree = other.tree; - k = other.k; - st = other.st; - size = other.size; - _n = other._n; - _node = other._node; - _level = other._level; - _row = other._row; - } - return *this; - } + // neighbour_iterator &operator=(const neighbour_iterator &other) { + // if (this != &other) { + // _ptr = other._ptr; + // tree = other.tree; + // k = other.k; + // st = other.st; + // size = other.size; + // _n = other._n; + // _node = other._node; + // _level = other._level; + // _row = other._row; + // t_size = other.t_size; + // _is_end = other._is_end; + // } + // return *this; + // } friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { std::swap(rhs._ptr, lhs._ptr); @@ -771,90 +765,91 @@ namespace sdsl std::swap(rhs._node, lhs._node); std::swap(rhs._level, lhs._level); std::swap(rhs._row, lhs._row); + std::swap(rhs.t_size, lhs.t_size); + std::swap(rhs._is_end, lhs._is_end); } private: void _initialize() { - _n = static_cast(std::pow(k, tree->height())) / k; + _n = static_cast(std::pow(k, tree->k_height)) / k; _row = 0; _level = k * std::floor(_node / static_cast(_n)); - size = std::pow(k, tree->height()); + size = std::pow(k, tree->k_height); + t_size = tree->t_size(); - if (tree->l_size() > 0) - { + if (tree->l_size() > 0){ _ptr = _find_next(); } - else - { + else { // if its empty the begin == end - _ptr = -1; //end node + _ptr = 0; //end node + _is_end = true; } } - value_type _find_next() - { - value_type neigh; - if (_node < size) - { - for (; _row < k; _row++) - { - neigh = size; + value_type _find_next() { + if (_node < size) { + for (; _row < k; ++_row) { + value_type neigh = size; _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); - if (neigh < size) - { + + if (neigh < size) { return neigh; } } } - return -1; // end node + _ptr = 0; + _is_end = true; + return 0; // end node } - bool _find_next_recursive(value_type n, value_type row, value_type col, uint level, value_type &neigh, unsigned initial_j) + bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, size_type &neigh, size_type initial_j) { - if (level >= tree->t_size()) // Last level - { - if (tree->is_bit_set_l(level - tree->t_size()) == 1) - { + if (level >= t_size) { + if (tree->k_l[level - t_size]) { neigh = col; return true; } return false; } - - if (tree->is_bit_set_t(level) == 1) - { - value_type y = tree->rank_t(level + 1) * k * k + + if (tree->k_t[level]) { + idx_type y = tree->k_t_rank(level + 1) * k * k + k * std::floor(row / static_cast(n)); - - for (unsigned j = initial_j; j < k; j++) - { - tree_node2 next_node = {n, row, col, level, j, y}; - st.push_back(next_node); + for (unsigned j = initial_j; j < k; j++) { + st.push_front(tree_node2(n, row, col, level, j, y)); if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) return true; - st.pop_back(); + st.pop_front(); } - return false; } return false; } - typedef struct tree_node2 + class tree_node2 { - value_type n, row, col; - uint level, j; - value_type y; - } tree_node2; + public: + size_type n; + idx_type row, col; + size_type level, j; + idx_type y; + + tree_node2() {} + tree_node2(size_type n, idx_type row, idx_type col, size_type level, size_type j,idx_type y) : + n(n), row(row), col(col), level(level), j(j), y(y) {} + }; - value_type _ptr; + size_type _ptr; + bool _is_end = false; const k_tree *tree; - uint8_t k = 2; + uint16_t k = 2; + uint t_size = 0; // iterator state // - deque st; - value_type size, _n, _node, _level, _row; + std::deque st; + size_type _n, _level, _node, size; + idx_type _row, _col; // }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 596d6610e..f735a3e77 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -530,9 +530,9 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_empty) { TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { vector> mat({{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 1, 0}, - {1, 1, 1, 0}}); + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 1, 0}}); TypeParam tree(mat); auto neighbour_iterator = tree.neighbour_begin(2); ASSERT_EQ(*neighbour_iterator, 2); @@ -583,9 +583,6 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_star) { ASSERT_EQ(*neighbour_iterator, 6); } - - - TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { TypeParam empty_tree; ASSERT_EQ(*empty_tree.node_begin(), *empty_tree.node_end()); From 6ac7f1b8fc82b9c4b2034d42a80e735e58434a80 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 14 Oct 2020 15:09:26 +0100 Subject: [PATCH 48/57] Reduce memory usage in union operation --- include/sdsl/k2_tree.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index c68d9ea7f..cba4fafd8 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -80,7 +80,7 @@ class k2_tree std::vector pointerL; std::vector div_level_table; - int16_t max_level; + uint16_t max_level; uint last_level_rank = 0; edg_iterator it_e_begin, it_e_end; @@ -528,25 +528,24 @@ class k2_tree max_bits += calc; } - uint64_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; bit_vector C_t(C_t_size); calc *= k_k*k_k; max_bits += calc; - uint64_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; bit_vector C_l(C_l_size); //////// // Q Initialization - std::queue> Q; + std::queue> Q; Q.push({0, 1, 1}); //////// - std::array next; - short unsigned l; - uint16_t rA, rB, bA, bB; - uint64_t pA, pB, idx_t, idx_l; + std::array next; + uint8_t l, rA, rB, bA, bB; + uint32_t pA, pB, idx_t, idx_l; pA = 0; pB = 0; idx_l = 0; @@ -581,7 +580,8 @@ class k2_tree if (l < max_height-1) { if(bA || bB) { - Q.push({l + 1, bA, bB}); + uint8_t l_aux = l+1; + Q.push({l_aux, bA, bB}); C_t[idx_t] = 1; } idx_t++; From ad095c6349e02ecc32038ec3d52e327516aad55b Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 14 Oct 2020 15:10:21 +0100 Subject: [PATCH 49/57] Replace push_front to emplace_front in iterator --- include/sdsl/k2_tree_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 6d5c42bde..c1934db8a 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -818,7 +818,7 @@ namespace sdsl idx_type y = tree->k_t_rank(level + 1) * k * k + k * std::floor(row / static_cast(n)); for (unsigned j = initial_j; j < k; j++) { - st.push_front(tree_node2(n, row, col, level, j, y)); + st.emplace_front(tree_node2(n, row, col, level, j, y)); if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) return true; st.pop_front(); From ff2334cd49f40cdf8fada14171bcef47b2ea5486 Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 28 Oct 2020 10:21:15 +0000 Subject: [PATCH 50/57] Union with shared_ptr --- include/sdsl/k2_tree.hpp | 255 ++++++++++++++++++++++++++++++++++++++- test/k2_tree_test.cpp | 56 ++++----- 2 files changed, 282 insertions(+), 29 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index cba4fafd8..a084b80f9 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "sdsl/bit_vectors.hpp" #include "sdsl/k2_tree_helper.hpp" #include "sdsl/k2_tree_iterator.hpp" @@ -314,6 +315,15 @@ class k2_tree k_l_rank = l_rank(&k_l); } + k2_tree(uint n_vertices) : n_vertices(n_vertices) + { + k_k = k; + k_t = bit_vector(0, 0); + k_l = bit_vector(0, 0); + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); + } + //! Constructor /*! This constructos takes the graph adjacency matrix. * The time complexity for this constructor is linear in the matrix @@ -494,6 +504,126 @@ class k2_tree * [2] Brisaboa, Nieves R., et al. "Efficient Set Operations over * k2-Trees." 2015 Data Compression Conference. IEEE, 2015. */ + void unionOp(shared_ptr k2_B) + { + assert(this->k_k == k2_B->k_k); + if(k2_B == nullptr) + return; + + if(k2_B->get_number_edges() == 0) + return; + + if (this->get_number_edges() == 0) { + *this = *k2_B; + return; + } + + + if (this->n_vertices != k2_B->n_vertices) + throw std::logic_error("Trees must have the same number of nodes."); + if (this->k_height != k2_B->k_height) + throw std::logic_error("Trees must have the same height."); + + const uint64_t max_height = this->k_height; + + const uint64_t t_size_A = k_t.size(); + const uint64_t t_size_B = k2_B->k_t.size(); + + const uint64_t l_size_A = k_l.size(); + const uint64_t l_size_B = k2_B->k_l.size(); + + // C Initialization + + uint64_t calc = 1; + uint64_t max_bits = 0; + for (uint64_t i = 0; i < max_height; i++) + { + calc *= k_k*k_k; + max_bits += calc; + } + + uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + bit_vector C_t(C_t_size); + + calc *= k_k*k_k; + max_bits += calc; + + uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + bit_vector C_l(C_l_size); + //////// + + // Q Initialization + std::queue> Q; + Q.push({0, 1, 1}); + //////// + + std::array next; + uint8_t l, rA, rB, bA, bB; + uint32_t pA, pB, idx_t, idx_l; + pA = 0; + pB = 0; + idx_l = 0; + idx_t = 0; + + n_total_edges = 0; + + while (!Q.empty()) { + next = Q.front(); + Q.pop(); + + l = next[0]; + rA = next[1]; + rB = next[2]; + for (size_t i = 0; i < k_k * k_k; ++i) { + bA = 0; + bB = 0; + if (rA == 1) { + if (l < max_height-1) + bA = k_t[pA]; + else + bA = k_l[pA - t_size_A]; + pA++; + } + if (rB == 1) { + if (l < max_height-1) + bB = k2_B->k_t[pB]; + else + bB = k2_B->k_l[pB - t_size_B]; + pB++; + } + + if (l < max_height-1) { + if(bA || bB) { + uint8_t l_aux = l+1; + Q.push({l_aux, bA, bB}); + C_t[idx_t] = 1; + } + idx_t++; + } else { + if(bA || bB) { + C_l[idx_l] = 1; + n_total_edges++; + } + idx_l++; + } + } + } + assert(C_t_size >= idx_t); + C_t.resize(idx_t); + + assert(C_l_size >= idx_l); + C_l.resize(idx_l); + + k_t = t_bv(C_t); + k_l = t_bv(C_l); + k_t_rank = t_rank(&k_t); + k_l_rank = l_rank(&k_l); + k_height = max_height; + n_marked_edges = 0; + n_edges = n_total_edges; + } + + void unionOp(k2_tree &k2_B) { assert(this->k_k == k2_B.k_k); @@ -519,7 +649,6 @@ class k2_tree const uint64_t l_size_B = k2_B.k_l.size(); // C Initialization - uint64_t calc = 1; uint64_t max_bits = 0; for (uint64_t i = 0; i < max_height; i++) @@ -609,6 +738,130 @@ class k2_tree n_edges = n_total_edges; } + // void unionOp_stages_start(k2_tree &k2_B, uint32_t n_iterations) + // { + // assert(this->k_k == k2_B.k_k); + // if (k2_B.get_number_edges() == 0) + // return; + + // if (this->get_number_edges() == 0) { + // *this = k2_B; + // return; + // } + + // if (this->n_vertices != k2_B.n_vertices) + // throw std::logic_error("Trees must have the same number of nodes."); + // if (this->k_height != k2_B.k_height) + // throw std::logic_error("Trees must have the same height."); + + // const uint64_t max_height = this->k_height; + // const uint64_t t_size_A = k_t.size(); + // const uint64_t t_size_B = k2_B.k_t.size(); + + // const uint64_t l_size_A = k_l.size(); + // const uint64_t l_size_B = k2_B.k_l.size(); + + // // C Initialization + // uint64_t calc = 1; + // uint64_t max_bits = 0; + // for (uint64_t i = 0; i < max_height; i++) + // { + // calc *= k_k*k_k; + // max_bits += calc; + // } + + // //instead of creating a new one, just add it inside the k_t and k_l + // // + // // + // uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + // bit_vector C_t(C_t_size); + // calc *= k_k*k_k; + // max_bits += calc; + // uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + // bit_vector C_l(C_l_size); + // //////// + + // // Q Initialization + // std::queue> Q; + // Q.push({0, 1, 1}); + // //////// + // std::array next; + // uint8_t l, rA, rB, bA, bB; + // uint32_t pA, pB, idx_t, idx_l; + // pA = 0; + // pB = 0; + // idx_l = 0; + // idx_t = 0; + + // n_total_edges = 0; + + // uint32_t n_1_A = k_t_rank(t_size_A) + k_l_rank(l_size_A); + // uint32_t n_1_B = k_t_rank(t_size_B) + k_l_rank(l_size_B); + // uint32_t total_iterations = max(n_1_A, n_1_B); + // total_iterations /= n_iterations; + // uint32_t iteration = 0; + + // while (!Q.empty() || iteration < total_iterations) { + // next = Q.front(); + // Q.pop(); + + // l = next[0]; + // rA = next[1]; + // rB = next[2]; + // for (size_t i = 0; i < k_k * k_k; ++i) { + // bA = 0; + // bB = 0; + // if (rA == 1) { + // if (l < max_height-1) + // bA = k_t[pA]; + // else + // bA = k_l[pA - t_size_A]; + // pA++; + // } + // if (rB == 1) { + // if (l < max_height-1) + // bB = k2_B.k_t[pB]; + // else + // bB = k2_B.k_l[pB - t_size_B]; + // pB++; + // } + + // if (l < max_height-1) { + // if(bA || bB) { + // uint8_t l_aux = l+1; + // Q.push({l_aux, bA, bB}); + // C_t[idx_t] = 1; + // } + // idx_t++; + // } else { + // if(bA || bB) { + // C_l[idx_l] = 1; + // n_total_edges++; + // } + // idx_l++; + // } + // } + // } + // assert(C_t_size >= idx_t); + // C_t.resize(idx_t); + + // assert(C_l_size >= idx_l); + // C_l.resize(idx_l); + + // k_t = t_bv(C_t); + // k_l = t_bv(C_l); + // k_t_rank = t_rank(&k_t); + // k_l_rank = l_rank(&k_l); + // k_height = max_height; + // n_marked_edges = 0; + // n_edges = n_total_edges; + // } + + // void unionOp_stages(k2_tree &k2_B) + // { + + // } + //! Move assignment operator k2_tree &operator=(k2_tree &&tr) { diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index f735a3e77..0dc1d401e 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -227,7 +227,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test_happy_path) {0, 0, 0, 1}}); // T 0 0 0 1 // L 0 0 0 1 - TypeParam tree_B(mat); + shared_ptr tree_B = make_shared(mat); tree_A.unionOp(tree_B); @@ -241,20 +241,20 @@ TYPED_TEST(k2_tree_test_k_2, empty_union_operation) {0, 0, 1, 1}, {0, 0, 1, 0}}); - TypeParam tree_A(mat); - TypeParam tree_B; + shared_ptr tree_A = make_shared(mat); + shared_ptr tree_B = make_shared(); - TypeParam tree_A_copy = tree_A; - TypeParam tree_B_copy = tree_B; + shared_ptr tree_A_copy = tree_A; + shared_ptr tree_B_copy = tree_B; - tree_A_copy.unionOp(tree_B); - k2_tree_test_nm::check_t_l(tree_A_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + tree_A_copy->unionOp(tree_B); + k2_tree_test_nm::check_t_l(*tree_A_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); - tree_B_copy.unionOp(tree_A); - k2_tree_test_nm::check_t_l(tree_B_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); + tree_B_copy->unionOp(tree_A); + k2_tree_test_nm::check_t_l(*tree_B_copy, {1, 0, 0, 1}, {1, 1, 0, 1, 1, 1, 1, 0}); - tree_B.unionOp(tree_B); - k2_tree_test_nm::assert_eq_tree(tree_B, tree_B); + tree_B->unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(*tree_B, *tree_B); } TYPED_TEST(k2_tree_test_k_2, union_operation_test) @@ -267,7 +267,7 @@ TYPED_TEST(k2_tree_test_k_2, union_operation_test) {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 1}}); - TypeParam tree_B(mat); + shared_ptr tree_B = make_shared(mat); ASSERT_THROW(tree_A.unionOp(tree_B), std::logic_error); } @@ -451,17 +451,17 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_union) { {0, 0, 1, 1}, {0, 0, 1, 0}}); - TypeParam tree_A(mat); + shared_ptr tree_A = make_shared(mat); mat = vector>({{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 1, 0}, {1, 1, 0, 1}}); - TypeParam tree_B(mat); + shared_ptr tree_B = make_shared(mat); - tree_A.unionOp(tree_B); + tree_A->unionOp(tree_B); - auto it = tree_A.edge_begin(); + auto it = tree_A->edge_begin(); ASSERT_EQ(it.x(), (size_t) 0); ASSERT_EQ(it.y(), (size_t) 0); @@ -490,7 +490,7 @@ TYPED_TEST(k2_tree_test_k_2, edge_iterator_test_union) { ASSERT_EQ(it.x(), (size_t) 3); ASSERT_EQ(it.y(), (size_t) 3); it++; - ASSERT_EQ(it, tree_A.edge_end()); + ASSERT_EQ(it, tree_A->edge_end()); } TYPED_TEST(k2_tree_test_k_2, node_iterator_test) { @@ -736,7 +736,7 @@ TYPED_TEST(k2_tree_test_k_3, union_operation_test) {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 1}}); - TypeParam tree_B(mat); + shared_ptr tree_B = make_shared(mat); tree_A.unionOp(tree_B); k2_tree_test_nm::check_t_l(tree_A, {1, 1, 0, 1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); @@ -755,21 +755,21 @@ TYPED_TEST(k2_tree_test_k_3, empty_union_operation) 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}; - TypeParam tree_A(mat); - TypeParam tree_B; + shared_ptr tree_A = make_shared(mat); + shared_ptr tree_B = make_shared(); - TypeParam tree_A_copy = tree_A; - TypeParam tree_B_copy = tree_B; + shared_ptr tree_A_copy = tree_A; + shared_ptr tree_B_copy = tree_B; - tree_A_copy.unionOp(tree_B); - k2_tree_test_nm::check_t_l(tree_A_copy, expected_t, expected_l); + tree_A_copy->unionOp(tree_B); + k2_tree_test_nm::check_t_l(*tree_A_copy, expected_t, expected_l); - tree_B_copy.unionOp(tree_A); - k2_tree_test_nm::check_t_l(tree_B_copy, expected_t, expected_l); + tree_B_copy->unionOp(tree_A); + k2_tree_test_nm::check_t_l(*tree_B_copy, expected_t, expected_l); - tree_B.unionOp(tree_B); - k2_tree_test_nm::assert_eq_tree(tree_B, tree_B); + tree_B->unionOp(tree_B); + k2_tree_test_nm::assert_eq_tree(*tree_B, *tree_B); } TYPED_TEST_CASE(k2_tree_test, Implementations); From ee9db7315dd6533d4c2fc4b3bbdcb7ed716fdd5d Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 28 Oct 2020 14:14:46 +0000 Subject: [PATCH 51/57] Fix bug --- include/sdsl/k2_tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index a084b80f9..0c692638e 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -506,7 +506,6 @@ class k2_tree */ void unionOp(shared_ptr k2_B) { - assert(this->k_k == k2_B->k_k); if(k2_B == nullptr) return; @@ -517,6 +516,7 @@ class k2_tree *this = *k2_B; return; } + assert(this->k_k == k2_B->k_k); if (this->n_vertices != k2_B->n_vertices) From 8b6ab05537a28501abe695c23918f1e6e9d80365 Mon Sep 17 00:00:00 2001 From: Joana H Date: Tue, 17 Nov 2020 14:24:20 +0000 Subject: [PATCH 52/57] Improve Union --- include/sdsl/k2_tree.hpp | 307 ++++----------------------------------- 1 file changed, 32 insertions(+), 275 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 0c692638e..14a0391ac 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -62,6 +62,8 @@ class k2_tree using neigh_iterator = neighbour_iterator>; t_bv k_t; + uint k_t_size = 0; + uint k_l_size = 0; //! Bit array to store the last level of the tree. t_bv k_l; @@ -75,7 +77,6 @@ class k2_tree //! Bit array to store all the bits of the tree, except those in the //! last level. uint64_t n_marked_edges = 0; - uint64_t n_total_edges = 0; uint64_t n_edges = 0; size_t n_vertices = 0; @@ -130,8 +131,9 @@ class k2_tree k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); - n_total_edges = k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); - n_edges = n_total_edges; + n_edges = k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + k_t_size = k_t.size(); + k_l_size = k_l.size(); } /*! Recursive function to retrieve list of neighbors. @@ -303,6 +305,9 @@ class k2_tree k_t_rank = t_rank(&k_t); k_l_rank = l_rank(&k_l); + n_edges = k_l.size() == 0? 0 : k_l_rank(k_l.size()); + k_t_size = k_t.size(); + k_l_size = k_l.size(); } public: @@ -373,8 +378,7 @@ class k2_tree build_from_edges(edges, size); this->n_vertices = size; - n_total_edges = edges.size(); - n_edges = n_total_edges; + max_level = floor(log(n_vertices)/log(k_k)); if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) max_level = max_level-1; @@ -424,8 +428,6 @@ class k2_tree build_from_edges(edges, size); n_vertices = size; - n_total_edges = edges.size(); - n_edges = n_total_edges; max_level = floor(log(n_vertices)/log(k_k)); if(max_level != 0 && floor(log(n_vertices)/log(k_k)) == (log(n_vertices)/log(k_k))) @@ -447,20 +449,20 @@ class k2_tree } size_t t_size() const { - return k_t.size(); + return k_t_size; } size_t l_size() const { - return k_l.size(); + return k_l_size; } size_t get_int_t(size_t i) { - assert(i < k_t.size()); + assert(i < k_t_size); return k_t[i]; } size_t get_int_l(size_t i) { - assert(i < k_l.size()); + assert(i < k_l_size); return k_l[i]; } @@ -472,14 +474,6 @@ class k2_tree return k_l.empty(); } - // uint16_t k_() const { - // return k_k; - // } - - // uint16_t height() const { - // return k_height; - // } - uint64_t get_marked_edges() const { return n_marked_edges; @@ -488,7 +482,7 @@ class k2_tree uint64_t get_number_edges() const { // return k_l.size() == 0? 0: k_l_rank(k_l.size()); - return n_edges; + return n_edges - n_marked_edges; } size_type get_number_nodes() const @@ -533,7 +527,6 @@ class k2_tree const uint64_t l_size_B = k2_B->k_l.size(); // C Initialization - uint64_t calc = 1; uint64_t max_bits = 0; for (uint64_t i = 0; i < max_height; i++) @@ -565,7 +558,7 @@ class k2_tree idx_l = 0; idx_t = 0; - n_total_edges = 0; + uint n_total_edges = 0; while (!Q.empty()) { next = Q.front(); @@ -621,247 +614,10 @@ class k2_tree k_height = max_height; n_marked_edges = 0; n_edges = n_total_edges; + k_t_size = idx_t; + k_l_size = idx_l; } - - void unionOp(k2_tree &k2_B) - { - assert(this->k_k == k2_B.k_k); - if (k2_B.get_number_edges() == 0) - return; - - if (this->get_number_edges() == 0) { - *this = k2_B; - return; - } - - if (this->n_vertices != k2_B.n_vertices) - throw std::logic_error("Trees must have the same number of nodes."); - if (this->k_height != k2_B.k_height) - throw std::logic_error("Trees must have the same height."); - - const uint64_t max_height = this->k_height; - - const uint64_t t_size_A = k_t.size(); - const uint64_t t_size_B = k2_B.k_t.size(); - - const uint64_t l_size_A = k_l.size(); - const uint64_t l_size_B = k2_B.k_l.size(); - - // C Initialization - uint64_t calc = 1; - uint64_t max_bits = 0; - for (uint64_t i = 0; i < max_height; i++) - { - calc *= k_k*k_k; - max_bits += calc; - } - - uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; - bit_vector C_t(C_t_size); - - calc *= k_k*k_k; - max_bits += calc; - - uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; - bit_vector C_l(C_l_size); - //////// - - // Q Initialization - std::queue> Q; - Q.push({0, 1, 1}); - //////// - - std::array next; - uint8_t l, rA, rB, bA, bB; - uint32_t pA, pB, idx_t, idx_l; - pA = 0; - pB = 0; - idx_l = 0; - idx_t = 0; - - n_total_edges = 0; - - while (!Q.empty()) { - next = Q.front(); - Q.pop(); - - l = next[0]; - rA = next[1]; - rB = next[2]; - for (size_t i = 0; i < k_k * k_k; ++i) { - bA = 0; - bB = 0; - if (rA == 1) { - if (l < max_height-1) - bA = k_t[pA]; - else - bA = k_l[pA - t_size_A]; - pA++; - } - if (rB == 1) { - if (l < max_height-1) - bB = k2_B.k_t[pB]; - else - bB = k2_B.k_l[pB - t_size_B]; - pB++; - } - - if (l < max_height-1) { - if(bA || bB) { - uint8_t l_aux = l+1; - Q.push({l_aux, bA, bB}); - C_t[idx_t] = 1; - } - idx_t++; - } else { - if(bA || bB) { - C_l[idx_l] = 1; - n_total_edges++; - } - idx_l++; - } - } - } - assert(C_t_size >= idx_t); - C_t.resize(idx_t); - - assert(C_l_size >= idx_l); - C_l.resize(idx_l); - - k_t = t_bv(C_t); - k_l = t_bv(C_l); - k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); - k_height = max_height; - n_marked_edges = 0; - n_edges = n_total_edges; - } - - // void unionOp_stages_start(k2_tree &k2_B, uint32_t n_iterations) - // { - // assert(this->k_k == k2_B.k_k); - // if (k2_B.get_number_edges() == 0) - // return; - - // if (this->get_number_edges() == 0) { - // *this = k2_B; - // return; - // } - - // if (this->n_vertices != k2_B.n_vertices) - // throw std::logic_error("Trees must have the same number of nodes."); - // if (this->k_height != k2_B.k_height) - // throw std::logic_error("Trees must have the same height."); - - // const uint64_t max_height = this->k_height; - // const uint64_t t_size_A = k_t.size(); - // const uint64_t t_size_B = k2_B.k_t.size(); - - // const uint64_t l_size_A = k_l.size(); - // const uint64_t l_size_B = k2_B.k_l.size(); - - // // C Initialization - // uint64_t calc = 1; - // uint64_t max_bits = 0; - // for (uint64_t i = 0; i < max_height; i++) - // { - // calc *= k_k*k_k; - // max_bits += calc; - // } - - // //instead of creating a new one, just add it inside the k_t and k_l - // // - // // - // uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; - // bit_vector C_t(C_t_size); - // calc *= k_k*k_k; - // max_bits += calc; - // uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; - // bit_vector C_l(C_l_size); - // //////// - - // // Q Initialization - // std::queue> Q; - // Q.push({0, 1, 1}); - // //////// - // std::array next; - // uint8_t l, rA, rB, bA, bB; - // uint32_t pA, pB, idx_t, idx_l; - // pA = 0; - // pB = 0; - // idx_l = 0; - // idx_t = 0; - - // n_total_edges = 0; - - // uint32_t n_1_A = k_t_rank(t_size_A) + k_l_rank(l_size_A); - // uint32_t n_1_B = k_t_rank(t_size_B) + k_l_rank(l_size_B); - // uint32_t total_iterations = max(n_1_A, n_1_B); - // total_iterations /= n_iterations; - // uint32_t iteration = 0; - - // while (!Q.empty() || iteration < total_iterations) { - // next = Q.front(); - // Q.pop(); - - // l = next[0]; - // rA = next[1]; - // rB = next[2]; - // for (size_t i = 0; i < k_k * k_k; ++i) { - // bA = 0; - // bB = 0; - // if (rA == 1) { - // if (l < max_height-1) - // bA = k_t[pA]; - // else - // bA = k_l[pA - t_size_A]; - // pA++; - // } - // if (rB == 1) { - // if (l < max_height-1) - // bB = k2_B.k_t[pB]; - // else - // bB = k2_B.k_l[pB - t_size_B]; - // pB++; - // } - - // if (l < max_height-1) { - // if(bA || bB) { - // uint8_t l_aux = l+1; - // Q.push({l_aux, bA, bB}); - // C_t[idx_t] = 1; - // } - // idx_t++; - // } else { - // if(bA || bB) { - // C_l[idx_l] = 1; - // n_total_edges++; - // } - // idx_l++; - // } - // } - // } - // assert(C_t_size >= idx_t); - // C_t.resize(idx_t); - - // assert(C_l_size >= idx_l); - // C_l.resize(idx_l); - - // k_t = t_bv(C_t); - // k_l = t_bv(C_l); - // k_t_rank = t_rank(&k_t); - // k_l_rank = l_rank(&k_l); - // k_height = max_height; - // n_marked_edges = 0; - // n_edges = n_total_edges; - // } - - // void unionOp_stages(k2_tree &k2_B) - // { - - // } - //! Move assignment operator k2_tree &operator=(k2_tree &&tr) { @@ -875,11 +631,12 @@ class k2_tree k_l_rank = l_rank(&k_l); n_vertices = std::move(tr.n_vertices); n_marked_edges = std::move(tr.n_marked_edges); - n_total_edges = std::move(tr.n_total_edges); n_edges = std::move(tr.n_edges); max_level = std::move(tr.max_level); div_level_table = std::move(tr.div_level_table); last_level_rank = std::move(tr.last_level_rank); + k_t_size = std::move(tr.k_t_size); + k_l_size = std::move(tr.k_l_size); } return *this; } @@ -897,12 +654,12 @@ class k2_tree k_l_rank = l_rank(&k_l); n_vertices = tr.n_vertices; n_marked_edges = tr.n_marked_edges; - n_total_edges = tr.n_total_edges; n_edges = tr.n_edges; max_level = tr.max_level; div_level_table = tr.div_level_table; last_level_rank = tr.last_level_rank; - + k_t_size = tr.k_t_size; + k_l_size = tr.k_l_size; } return *this; } @@ -943,11 +700,12 @@ class k2_tree std::swap(k_height, tr.k_height); std::swap(n_vertices, tr.n_vertices); std::swap(n_marked_edges, tr.n_marked_edges); - std::swap(n_total_edges, tr.n_total_edges); std::swap(n_edges, tr.n_edges); std::swap(max_level, tr.max_level); std::swap(div_level_table, tr.div_level_table); std::swap(last_level_rank, tr.last_level_rank); + std::swap(k_t_size, tr.k_t_size); + std::swap(k_l_size, tr.k_l_size); } } @@ -984,7 +742,8 @@ class k2_tree */ bool adj(idx_type i, idx_type j) const { - if (k_t.size() == 0 && k_l.size() == 0) + uint t_size = k_t.size(); + if (t_size == 0 && k_l.size() == 0) return false; size_type n = std::pow(k_k, k_height - 1); size_type k_2 = std::pow(k_k, 2); @@ -1000,7 +759,7 @@ class k2_tree idx_type level = k_k * row + col; n = n / k_k; - while (level < k_t.size()) + while (level < t_size) { if (k_t[level] == 0) return false; @@ -1011,7 +770,7 @@ class k2_tree level = k_t_rank(level + 1) * k_2 + k_k * row + col; n = n / k_k; } - return k_l[level - k_t.size()] == 1; + return k_l[level - t_size] == 1; } bool contains(uint p, uint q) @@ -1203,7 +962,6 @@ class k2_tree written_bytes += write_member(k_height, out, child, "height"); written_bytes += write_member(n_vertices, out, child, "n_vertices"); written_bytes += write_member(n_marked_edges, out, child, "n_marked_edges"); - written_bytes += write_member(n_total_edges, out, child, "n_total_edges"); written_bytes += write_member(n_edges, out, child, "n_edges"); structure_tree::add_size(child, written_bytes); @@ -1226,7 +984,6 @@ class k2_tree read_member(k_height, in); read_member(n_vertices, in); read_member(n_marked_edges, in); - read_member(n_total_edges, in); read_member(n_edges, in); max_level = floor(log(n_vertices)/log(k_k)); @@ -1236,6 +993,8 @@ class k2_tree div_level_table = std::vector(max_level+1); for(int64_t i = 0; i <= max_level; i++) div_level_table[i] = exp_pow(k_k, max_level-i); + k_t_size = k_t.size(); + k_l_size = k_l.size(); } @@ -1273,16 +1032,11 @@ class k2_tree { k_l[level - k_t.size()] = 0; n_marked_edges++; - n_edges--; return true; } return false; } - uint64_t total_edges() const { - return n_total_edges; - } - edg_iterator &edge_begin() { it_e_begin = edg_iterator(this); @@ -1377,6 +1131,9 @@ class k2_tree edge_it_rec(0, 0, -1, -1, func); } } + + void set_edges(uint64_t edges) { n_edges = edges;} + uint64_t total_edges() { return n_edges;} }; } // namespace sdsl From 77db149991eebb3373e8519b46ae94046605039c Mon Sep 17 00:00:00 2001 From: Joana H Date: Sat, 5 Dec 2020 10:12:33 +0000 Subject: [PATCH 53/57] Remove k_l_rank Remove rebuild in the end of union operation --- include/sdsl/int_vector.hpp | 2 +- include/sdsl/k2_tree.hpp | 134 +++++++++++++++++++++--------------- test/k2_tree_test.cpp | 18 +++++ 3 files changed, 97 insertions(+), 57 deletions(-) diff --git a/include/sdsl/int_vector.hpp b/include/sdsl/int_vector.hpp index 2b2a3a343..9c3563670 100644 --- a/include/sdsl/int_vector.hpp +++ b/include/sdsl/int_vector.hpp @@ -387,7 +387,7 @@ class int_vector //! The number of elements in the int_vector. /*! \sa max_size, bit_size, capacity */ - size_type size() const + inline size_type size() const { return m_size/m_width; } diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 14a0391ac..a6642d2a5 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -50,16 +50,15 @@ namespace sdsl template + typename t_rank = typename t_bv::rank_1_type> class k2_tree { public: typedef k2_tree_ns::idx_type idx_type; typedef k2_tree_ns::size_type size_type; - using edg_iterator = edge_iterator>; - using nod_iterator = node_iterator>; - using neigh_iterator = neighbour_iterator>; + using edg_iterator = edge_iterator>; + using nod_iterator = node_iterator>; + using neigh_iterator = neighbour_iterator>; t_bv k_t; uint k_t_size = 0; @@ -68,7 +67,6 @@ class k2_tree t_bv k_l; t_rank k_t_rank; - l_rank k_l_rank; uint16_t k_k; uint16_t k_height = 0; @@ -126,12 +124,13 @@ class k2_tree // TODO there should be a better way to do this k_l_.set_int(n * 1, (*it).get_int(i, 1), 1); n++; + if((*it).get_int(i, 1) == 1) + ++n_edges; } k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); - n_edges = k_l.size() == 0 ? 0 : k_l_rank(k_l.size()); + k_t_size = k_t.size(); k_l_size = k_l.size(); } @@ -166,6 +165,56 @@ class k2_tree } } + void _neigh_rec(size_type n, idx_type row, idx_type col, size_type level, + std::function func) const { + if (level >= k_t.size()) + { // Last level + if (k_l[level - k_t.size()] == 1) + func(col); + return; + } + + if (k_t[level] == 1) + { + idx_type y = k_t_rank(level + 1) * std::pow(k_k, 2) + + k_k * std::floor(row / static_cast(n)); + for (unsigned j = 0; j < k_k; j++) + _neigh_rec(n / k_k, row % n, col + n * j, y + j, func); + } + } + + void _edge_it_rec(uint64_t dp, uint64_t dq, int64_t x, int16_t l, std::function func) { + + if(l == max_level) { + if(k_l[x] == 1) { + func(dp, dq); + } + } + + if(((l == max_level-1) && (x != -1) && k_t[x] == 1)) { + uint64_t y = pointerL[l+1]; + pointerL[l+1] += k_k*k_k; + + for(uint i = 0; i < k_k; i++) { + for(uint j = 0; j < k_k; j++) { + _edge_it_rec(dp+i, dq+j, y+k_k*i+j, l+1, func); + } + } + } + + if((x == -1) || ((l < max_level-1) && (k_t[x] == 1) )) { + uint64_t y = pointerL[l+1]; + pointerL[l+1] += k_k*k_k; + + uint64_t div_level = div_level_table[l+1]; + for(uint i = 0; i < k_k; i++) { + for(uint j = 0; j < k_k; j++) { + _edge_it_rec(dp+div_level*i, dq+div_level*j, y+k_k*i+j, l+1, func); + } + } + } + } + /*! Recursive function to retrieve list of reverse neighbors. * * \param n Size of the submatrix in the next recursive step. @@ -252,8 +301,10 @@ class k2_tree t = 0; // Restart counter as we're storing at k_l_ now. } for (it = 0; it < k_2; it++, t++) - if (amount_by_chunk[it] != 0) + if (amount_by_chunk[it] != 0) { k_l_[t] = 1; + ++n_edges; + } // At l == 1 we do not put new elements at the queue. continue; } @@ -304,8 +355,6 @@ class k2_tree k2_tree_ns::build_template_vector(k_t_, k_l_, k_t, k_l); k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); - n_edges = k_l.size() == 0? 0 : k_l_rank(k_l.size()); k_t_size = k_t.size(); k_l_size = k_l.size(); } @@ -317,7 +366,6 @@ class k2_tree k_t = bit_vector(0, 0); k_l = bit_vector(0, 0); k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); } k2_tree(uint n_vertices) : n_vertices(n_vertices) @@ -326,7 +374,6 @@ class k2_tree k_t = bit_vector(0, 0); k_l = bit_vector(0, 0); k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); } //! Constructor @@ -481,7 +528,6 @@ class k2_tree uint64_t get_number_edges() const { - // return k_l.size() == 0? 0: k_l_rank(k_l.size()); return n_edges - n_marked_edges; } @@ -607,10 +653,9 @@ class k2_tree assert(C_l_size >= idx_l); C_l.resize(idx_l); - k_t = t_bv(C_t); - k_l = t_bv(C_l); + k_t = C_t; + k_l = C_l; k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); k_height = max_height; n_marked_edges = 0; n_edges = n_total_edges; @@ -628,7 +673,6 @@ class k2_tree k_k = std::move(tr.k_k); k_height = std::move(tr.k_height); k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); n_vertices = std::move(tr.n_vertices); n_marked_edges = std::move(tr.n_marked_edges); n_edges = std::move(tr.n_edges); @@ -651,7 +695,6 @@ class k2_tree k_k = tr.k_k; k_height = tr.k_height; k_t_rank = t_rank(&k_t); - k_l_rank = l_rank(&k_l); n_vertices = tr.n_vertices; n_marked_edges = tr.n_marked_edges; n_edges = tr.n_edges; @@ -695,7 +738,6 @@ class k2_tree std::swap(k_t, tr.k_t); std::swap(k_l, tr.k_l); util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t)); - util::swap_support(k_l_rank, tr.k_l_rank, &k_l, &(tr.k_l)); std::swap(k_k, tr.k_k); std::swap(k_height, tr.k_height); std::swap(n_vertices, tr.n_vertices); @@ -957,7 +999,6 @@ class k2_tree written_bytes += k_t.serialize(out, child, "t"); written_bytes += k_l.serialize(out, child, "l"); written_bytes += k_t_rank.serialize(out, child, "t_rank"); - written_bytes += k_l_rank.serialize(out, child, "l_rank"); written_bytes += write_member(k_k, out, child, "k"); written_bytes += write_member(k_height, out, child, "height"); written_bytes += write_member(n_vertices, out, child, "n_vertices"); @@ -978,8 +1019,6 @@ class k2_tree k_l.load(in); k_t_rank.load(in); k_t_rank.set_vector(&k_t); - k_l_rank.load(in); - k_l_rank.set_vector(&k_l); read_member(k_k, in); read_member(k_height, in); read_member(n_vertices, in); @@ -1078,38 +1117,6 @@ class k2_tree return result; } - void edge_it_rec(uint64_t dp, uint64_t dq, int64_t x, int16_t l, std::function func) { - - if(l == max_level) { - if(k_l[x] == 1) { - func(dp, dq); - } - } - - if(((l == max_level-1) && (x != -1) && k_t[x] == 1)) { - uint64_t y = pointerL[l+1]; - pointerL[l+1] += k_k*k_k; - - for(uint i = 0; i < k_k; i++) { - for(uint j = 0; j < k_k; j++) { - edge_it_rec(dp+i, dq+j, y+k_k*i+j, l+1, func); - } - } - } - - if((x == -1) || ((l < max_level-1) && (k_t[x] == 1) )) { - uint64_t y = pointerL[l+1]; - pointerL[l+1] += k_k*k_k; - - uint64_t div_level = div_level_table[l+1]; - for(uint i = 0; i < k_k; i++) { - for(uint j = 0; j < k_k; j++) { - edge_it_rec(dp+div_level*i, dq+div_level*j, y+k_k*i+j, l+1, func); - } - } - } - } - void edge_it(std::function func) { if(k_l.size() > 0) { max_level = floor(log(n_vertices)/log(k_k)); @@ -1128,12 +1135,27 @@ class k2_tree pointerL[i] = (k_t_rank(pointerL[i-1])+1)*k_k*k_k; } pointerL[max_level] = 0; - edge_it_rec(0, 0, -1, -1, func); + _edge_it_rec(0, 0, -1, -1, func); } } void set_edges(uint64_t edges) { n_edges = edges;} uint64_t total_edges() { return n_edges;} + + void neigh_it(uint64_t i, std::function func) { + if (k_l.size() == 0 && k_t.size() == 0) + return; + // n = k^h / k + // k^h - dimension n of matrix nxn + // /k - to calculate div only once and not for for all parameter again, always (n/k) + size_type n = + static_cast(std::pow(k_k, k_height)) / k_k; + // y = k * i/n + idx_type y = k_k * std::floor(i / static_cast(n)); + for (unsigned j = 0; j < k_k; j++) { + _neigh_rec(n / k_k, i % n, n * j, y + j, func); + } + } }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index 0dc1d401e..c38f5524f 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -559,6 +559,24 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { ASSERT_EQ(*tree.neighbour_begin(0), *tree.neighbour_end()); } +TYPED_TEST(k2_tree_test_k_2, neighbour_it_test) { + std::vector expected_x{0,1,2}; + uint i = 0; + + std::function func = [&](uint64_t x) { + ASSERT_EQ(x, expected_x[i]); + ++i; + }; + + vector> mat({{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {1, 1, 1, 0}}); + TypeParam tree(mat); + + tree.neigh_it(3, func); +} + TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_star) { vector> mat({ {0, 0, 0, 0, 0, 0, 0}, From b91efba0f085b94d1a009abb478cd55ae2adc8ef Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 9 Dec 2020 00:09:31 +0000 Subject: [PATCH 54/57] Improve neighbor iterator --- include/sdsl/k2_tree_iterator.hpp | 284 ++++++++++++------------------ test/k2_tree_test.cpp | 12 +- 2 files changed, 121 insertions(+), 175 deletions(-) diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index c1934db8a..242ee26d5 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -18,7 +18,6 @@ namespace sdsl using size_type = k2_tree_ns::size_type; using edge = std::tuple; - // typedef struct tree_node // { // int node; @@ -278,7 +277,6 @@ namespace sdsl edge_iterator() = default; - edge_iterator(const k_tree *tree) { this->tree = tree; @@ -287,11 +285,13 @@ namespace sdsl _initialize(); } - idx_type x() { + idx_type x() + { return get<0>(_ptr); } - idx_type y() { + idx_type y() + { return get<1>(_ptr); } @@ -335,14 +335,18 @@ namespace sdsl // j++; - if(j < k) { - if(_find_next_rec(dp, dq, y, l, type, i, j, e)) + if (j < k) + { + if (_find_next_rec(dp, dq, y, l, type, i, j, e)) break; - } else { + } + else + { j = 0; i++; - if(i < k) { - if(_find_next_rec(dp, dq, y, l, type, i, j, e)) + if (i < k) + { + if (_find_next_rec(dp, dq, y, l, type, i, j, e)) break; } } @@ -391,15 +395,16 @@ namespace sdsl uint8_t k = 2; // // iterator state // - class edge_node { + class edge_node + { public: uint64_t dp, dq, i, j; int64_t y; int type, l; - + edge_node() {} edge_node(uint64_t dp, uint64_t dq, int64_t y, uint64_t i, uint64_t j, int type, int l) : dp(dp), dq(dq), - i(i), j(j), y(y), type(type), l(l) {} + i(i), j(j), y(y), type(type), l(l) {} }; std::deque st; uint32_t max_level; @@ -422,21 +427,22 @@ namespace sdsl { if (tree->l_size() > 0) { - max_level = floor(log(nodes)/log(k)); - if(floor(log(nodes)/log(k)) == (log(nodes)/log(k))) - max_level = max_level-1; + max_level = floor(log(nodes) / log(k)); + if (floor(log(nodes) / log(k)) == (log(nodes) / log(k))) + max_level = max_level - 1; - div_level_table = std::vector(max_level+1); - for(uint i = 0; i <= max_level; i++) - div_level_table[i] = exp_pow(k, max_level-i); + div_level_table = std::vector(max_level + 1); + for (uint i = 0; i <= max_level; i++) + div_level_table[i] = exp_pow(k, max_level - i); - pointerL = std::vector(max_level+1); + pointerL = std::vector(max_level + 1); pointerL[0] = 0; - pointerL[1] = k*k; + pointerL[1] = k * k; - for(uint64_t i = 2; i < max_level; i++) { - pointerL[i] = (tree->k_t_rank(pointerL[i-1])+1)*k*k; + for (uint64_t i = 2; i < max_level; i++) + { + pointerL[i] = (tree->k_t_rank(pointerL[i - 1]) + 1) * k * k; } pointerL[max_level] = 0; @@ -453,38 +459,46 @@ namespace sdsl bool _find_next(uint64_t dp, uint64_t dq, int64_t x, int l, edge &e) { - if(l == (int64_t)max_level){ - if(tree->k_l[x]) { + if (l == (int64_t)max_level) + { + if (tree->k_l[x]) + { e = edge(dp, dq); return true; } return false; } - if((l == (int64_t)max_level-1) && tree->k_t[x]) { - int64_t y = pointerL[l+1]; - pointerL[l+1] += k*k; + if ((l == (int64_t)max_level - 1) && tree->k_t[x]) + { + int64_t y = pointerL[l + 1]; + pointerL[l + 1] += k * k; - for(uint64_t i = 0; i < k; i++) { - for(uint64_t j = 0; j < k; j++) { + for (uint64_t i = 0; i < k; i++) + { + for (uint64_t j = 0; j < k; j++) + { st.push_back(edge_node(dp, dq, y, i, j, 1, l)); - if(_find_next(dp+i, dq+j, y+k*i+j, l+1, e)) + if (_find_next(dp + i, dq + j, y + k * i + j, l + 1, e)) return true; st.pop_back(); } } return false; } - if((x == -1) || ((l < (int64_t)max_level-1) && tree->k_t[x])) { - int64_t y = pointerL[l+1]; - pointerL[l+1] += k*k; - - uint64_t div_level = div_level_table[l+1]; - - for(uint64_t i = 0; i < k; i++) { - for(uint64_t j = 0; j < k; j++) { + if ((x == -1) || ((l < (int64_t)max_level - 1) && tree->k_t[x])) + { + int64_t y = pointerL[l + 1]; + pointerL[l + 1] += k * k; + + uint64_t div_level = div_level_table[l + 1]; + + for (uint64_t i = 0; i < k; i++) + { + for (uint64_t j = 0; j < k; j++) + { st.push_back(edge_node(dp, dq, y, i, j, 2, l)); - if(_find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e)) + if (_find_next(dp + div_level * i, dq + div_level * j, y + k * i + j, l + 1, e)) return true; st.pop_back(); } @@ -492,18 +506,21 @@ namespace sdsl return false; } - return false; + return false; } - - bool _find_next_rec(uint64_t dp, uint64_t dq, int64_t y, int l, int type, uint64_t i, uint64_t j, edge &e) { - if(type == 1) { - st.push_back(edge_node(dp, dq, y, i, j, 1, l )); - return _find_next(dp+i, dq +j, y+k*i+j, l+1, e); - } else if(type == 2){ - uint64_t div_level = div_level_table[l+1]; + bool _find_next_rec(uint64_t dp, uint64_t dq, int64_t y, int l, int type, uint64_t i, uint64_t j, edge &e) + { + if (type == 1) + { + st.push_back(edge_node(dp, dq, y, i, j, 1, l)); + return _find_next(dp + i, dq + j, y + k * i + j, l + 1, e); + } + else if (type == 2) + { + uint64_t div_level = div_level_table[l + 1]; st.push_back(edge_node(dp, dq, y, i, j, 2, l)); - return _find_next(dp+div_level*i, dq+div_level*j, y+k*i+j, l+1, e); + return _find_next(dp + div_level * i, dq + div_level * j, y + k * i + j, l + 1, e); } return false; } @@ -667,16 +684,30 @@ namespace sdsl using reference = size_type &; using iterator_category = std::forward_iterator_tag; - neighbour_iterator() { + neighbour_iterator() + { _is_end = true; } - neighbour_iterator(const k_tree *tree, value_type node) + neighbour_iterator(const k_tree *tree, value_type i) { this->tree = tree; this->k = tree->k_k; - this->_node = node; - _initialize(); + this->t_size = tree->k_t.size(); + + if (tree->k_l.size() == 0 && t_size == 0) { + end(); + } + + size_type n = + static_cast(std::pow(k, tree->k_height)) / k; + // y = k * i/n + idx_type y = k * std::floor(i / static_cast(n)); + + for (unsigned j = 0; j < k; j++) { + q.emplace_front(neigh_state(n / k, i % n, n * j, y + j)); + } + operator++(); } value_type operator*() @@ -693,31 +724,29 @@ namespace sdsl neighbour_iterator &operator++() { - while (!st.empty()) // did not go until the end of the subtree + while (!q.empty()) { - tree_node2 &last_found = st.front(); - ++last_found.j; - value_type neigh; - - if (last_found.j < k) { - if (_find_next_recursive(last_found.n / k, - last_found.row % last_found.n, - last_found.col + last_found.n * last_found.j, - last_found.y + last_found.j, - neigh, 0)) { - _ptr = neigh; + neigh_state s = q.front(); + q.pop_front(); + + if (s.level >= t_size) + { + if (tree->k_l[s.level - t_size] == 1) { + _ptr = s.col; return *this; } + continue; + } + + if (tree->k_t[s.level] == 1) + { + idx_type y = tree->k_t_rank(s.level + 1) * std::pow(k, 2) + + k * std::floor(s.row / static_cast(s.n)); + for (unsigned j = 0; j < k; j++) + q.emplace_front(neigh_state(s.n / k, s.row % s.n, s.col + s.n * j, y + j)); } - st.pop_front(); - } // move to another subtree - ++_row; - if (_row >= k) { - _ptr = 0; - _is_end = true; - return *this; } - _ptr = _find_next(); + end(); return *this; } @@ -738,107 +767,17 @@ namespace sdsl return *this; } - // neighbour_iterator &operator=(const neighbour_iterator &other) { - // if (this != &other) { - // _ptr = other._ptr; - // tree = other.tree; - // k = other.k; - // st = other.st; - // size = other.size; - // _n = other._n; - // _node = other._node; - // _level = other._level; - // _row = other._row; - // t_size = other.t_size; - // _is_end = other._is_end; - // } - // return *this; - // } - - friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) { + friend void swap(neighbour_iterator &rhs, neighbour_iterator &lhs) + { std::swap(rhs._ptr, lhs._ptr); + std::swap(rhs._is_end, lhs._is_end); std::swap(rhs.tree, lhs.tree); std::swap(rhs.k, lhs.k); - std::swap(rhs.st, lhs.st); - std::swap(rhs.size, lhs.size); - std::swap(rhs._n, lhs._n); - std::swap(rhs._node, lhs._node); - std::swap(rhs._level, lhs._level); - std::swap(rhs._row, lhs._row); std::swap(rhs.t_size, lhs.t_size); - std::swap(rhs._is_end, lhs._is_end); + std::swap(rhs.q, lhs.q); } private: - void - _initialize() - { - _n = static_cast(std::pow(k, tree->k_height)) / k; - _row = 0; - _level = k * std::floor(_node / static_cast(_n)); - size = std::pow(k, tree->k_height); - t_size = tree->t_size(); - - if (tree->l_size() > 0){ - _ptr = _find_next(); - } - else { - // if its empty the begin == end - _ptr = 0; //end node - _is_end = true; - } - } - - value_type _find_next() { - if (_node < size) { - for (; _row < k; ++_row) { - value_type neigh = size; - _find_next_recursive(_n / k, _node % _n, _n * _row, _level + _row, neigh, 0); - - if (neigh < size) { - return neigh; - } - } - } - _ptr = 0; - _is_end = true; - return 0; // end node - } - - bool _find_next_recursive(size_type n, idx_type row, idx_type col, size_type level, size_type &neigh, size_type initial_j) - { - if (level >= t_size) { - if (tree->k_l[level - t_size]) { - neigh = col; - return true; - } - return false; - } - if (tree->k_t[level]) { - idx_type y = tree->k_t_rank(level + 1) * k * k + - k * std::floor(row / static_cast(n)); - for (unsigned j = initial_j; j < k; j++) { - st.emplace_front(tree_node2(n, row, col, level, j, y)); - if (_find_next_recursive(n / k, row % n, col + n * j, y + j, neigh, 0)) - return true; - st.pop_front(); - } - } - return false; - } - - class tree_node2 - { - public: - size_type n; - idx_type row, col; - size_type level, j; - idx_type y; - - tree_node2() {} - tree_node2(size_type n, idx_type row, idx_type col, size_type level, size_type j,idx_type y) : - n(n), row(row), col(col), level(level), j(j), y(y) {} - }; size_type _ptr; bool _is_end = false; @@ -847,9 +786,16 @@ namespace sdsl uint t_size = 0; // iterator state // - std::deque st; - size_type _n, _level, _node, size; - idx_type _row, _col; + class neigh_state + { + public: + size_type n, level; + idx_type row, col; + + neigh_state() {} + neigh_state(size_type n, idx_type row, idx_type col, size_type level) : n(n), level(level), row(row), col(col) {} + }; + std::deque q; // }; } // namespace sdsl diff --git a/test/k2_tree_test.cpp b/test/k2_tree_test.cpp index c38f5524f..1596bd82f 100644 --- a/test/k2_tree_test.cpp +++ b/test/k2_tree_test.cpp @@ -543,11 +543,11 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test) { ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); neighbour_iterator = tree.neighbour_begin(3); - ASSERT_EQ(*neighbour_iterator, 0); + ASSERT_EQ(*neighbour_iterator, 2); neighbour_iterator++; ASSERT_EQ(*neighbour_iterator, 1); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 2); + ASSERT_EQ(*neighbour_iterator, 0); neighbour_iterator++; ASSERT_EQ(*neighbour_iterator, *tree.neighbour_end()); @@ -589,16 +589,16 @@ TYPED_TEST(k2_tree_test_k_2, neighbour_iterator_test_star) { }); TypeParam tree(mat); auto neighbour_iterator = tree.neighbour_begin(1); - ASSERT_EQ(*neighbour_iterator, 2); + ASSERT_EQ(*neighbour_iterator, 6); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 3); + ASSERT_EQ(*neighbour_iterator, 5); neighbour_iterator++; ASSERT_EQ(*neighbour_iterator, 4); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 5); + ASSERT_EQ(*neighbour_iterator, 3); neighbour_iterator++; - ASSERT_EQ(*neighbour_iterator, 6); + ASSERT_EQ(*neighbour_iterator, 2); } TYPED_TEST(k2_tree_test_k_2, node_iterator_empty) { From bb4ce339f1ebc011ddc7377e47558173c427bb9f Mon Sep 17 00:00:00 2001 From: Joana H Date: Wed, 9 Dec 2020 17:18:53 +0000 Subject: [PATCH 55/57] Improve performance --- include/sdsl/k2_tree.hpp | 124 +++++++++++++++++++++--------- include/sdsl/k2_tree_iterator.hpp | 12 +-- 2 files changed, 93 insertions(+), 43 deletions(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index a6642d2a5..b4fabe447 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -33,6 +33,8 @@ #include +// #include +// #include //! Namespace for the succint data structure library namespace sdsl { @@ -536,6 +538,11 @@ class k2_tree return n_vertices; } + typedef struct union_node { + uint16_t level; + uint8_t rA, rB; + } union_node; + //! Union Operation /*! Performs the union operation between two tree. This operations requires both * trees to have the same number of nodes. @@ -552,19 +559,18 @@ class k2_tree if(k2_B->get_number_edges() == 0) return; - if (this->get_number_edges() == 0) { + if (get_number_edges() == 0) { *this = *k2_B; return; } - assert(this->k_k == k2_B->k_k); + assert(k_k == k2_B->k_k); - - if (this->n_vertices != k2_B->n_vertices) + if (n_vertices != k2_B->n_vertices) throw std::logic_error("Trees must have the same number of nodes."); - if (this->k_height != k2_B->k_height) + if (k_height != k2_B->k_height) throw std::logic_error("Trees must have the same height."); - const uint64_t max_height = this->k_height; + const uint16_t max_height = k_height; const uint64_t t_size_A = k_t.size(); const uint64_t t_size_B = k2_B->k_t.size(); @@ -581,70 +587,62 @@ class k2_tree max_bits += calc; } - uint32_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; + uint64_t C_t_size = max_bits < t_size_A + t_size_B ? max_bits : t_size_A + t_size_B; bit_vector C_t(C_t_size); calc *= k_k*k_k; max_bits += calc; - uint32_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; + uint64_t C_l_size = max_bits < l_size_A + l_size_B ? max_bits : l_size_A + l_size_B; bit_vector C_l(C_l_size); //////// // Q Initialization - std::queue> Q; + std::queue Q; Q.push({0, 1, 1}); //////// - std::array next; - uint8_t l, rA, rB, bA, bB; - uint32_t pA, pB, idx_t, idx_l; + union_node next; + uint8_t bA, bB; + uint64_t pA, pB, idx_t, idx_l; pA = 0; pB = 0; idx_l = 0; idx_t = 0; - uint n_total_edges = 0; - + int n_total_edges = 0; while (!Q.empty()) { next = Q.front(); Q.pop(); - - l = next[0]; - rA = next[1]; - rB = next[2]; - for (size_t i = 0; i < k_k * k_k; ++i) { + ++next.level; + for (auto i = 0; i < k_k * k_k; ++i) { bA = 0; bB = 0; - if (rA == 1) { - if (l < max_height-1) + if (next.rA == 1) { + if (next.level < max_height) bA = k_t[pA]; else bA = k_l[pA - t_size_A]; - pA++; + ++pA; } - if (rB == 1) { - if (l < max_height-1) + if (next.rB == 1) { + if (next.level < max_height) bB = k2_B->k_t[pB]; else bB = k2_B->k_l[pB - t_size_B]; - pB++; + ++pB; } - if (l < max_height-1) { - if(bA || bB) { - uint8_t l_aux = l+1; - Q.push({l_aux, bA, bB}); + if(bA || bB) { + if(next.level < max_height) { + Q.push({next.level, bA, bB}); C_t[idx_t] = 1; - } - idx_t++; - } else { - if(bA || bB) { + } else { C_l[idx_l] = 1; - n_total_edges++; + ++n_total_edges; } - idx_l++; } + next.level < max_height ? ++idx_t : ++idx_l; } } assert(C_t_size >= idx_t); @@ -653,8 +651,8 @@ class k2_tree assert(C_l_size >= idx_l); C_l.resize(idx_l); - k_t = C_t; - k_l = C_l; + k_t.swap(C_t); + k_l.swap(C_l); k_t_rank = t_rank(&k_t); k_height = max_height; n_marked_edges = 0; @@ -1156,6 +1154,58 @@ class k2_tree _neigh_rec(n / k_k, i % n, n * j, y + j, func); } } + + std::vector neigh_test(idx_type i) const + { + std::deque q; + std::vector acc{}; + + if (k_l.size() == 0 && k_t.size() == 0) + return acc; + + size_type n = + static_cast(std::pow(k_k, k_height)) / k_k; + // y = k * i/n + idx_type y = k_k * std::floor(i / static_cast(n)); + + for (unsigned j = 0; j < k_k; j++) { + q.emplace_front(tree_node2(n / k_k, i % n, n * j, y + j)); + } + + /// + while (!q.empty()) + { + tree_node2 s = q.front(); + q.pop_front(); + + if (s.level >= k_t.size()) + { + if (k_l[s.level - k_t.size()] == 1) + acc.push_back(s.col); + continue; // + } + + if (k_t[s.level] == 1) + { + idx_type y = k_t_rank(s.level + 1) * std::pow(k_k, 2) + + k_k * std::floor(s.row / static_cast(s.n)); + for (unsigned j = 0; j < k_k; j++) + q.emplace_front(tree_node2(s.n / k_k, s.row % s.n, s.col + s.n * j, y + j)); + } + + } + return acc; + } + + class tree_node2 + { + public: + size_type n; + idx_type row, col, level; + + tree_node2() {} + tree_node2(size_type n, idx_type row, idx_type col, size_type level) : n(n), row(row), col(col), level(level){} + }; }; } // namespace sdsl diff --git a/include/sdsl/k2_tree_iterator.hpp b/include/sdsl/k2_tree_iterator.hpp index 242ee26d5..48ac91b6a 100644 --- a/include/sdsl/k2_tree_iterator.hpp +++ b/include/sdsl/k2_tree_iterator.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -705,7 +706,7 @@ namespace sdsl idx_type y = k * std::floor(i / static_cast(n)); for (unsigned j = 0; j < k; j++) { - q.emplace_front(neigh_state(n / k, i % n, n * j, y + j)); + q.push(neigh_state(n / k, i % n, n * j, y + j)); } operator++(); } @@ -726,8 +727,8 @@ namespace sdsl { while (!q.empty()) { - neigh_state s = q.front(); - q.pop_front(); + neigh_state s = q.top(); + q.pop(); if (s.level >= t_size) { @@ -743,7 +744,7 @@ namespace sdsl idx_type y = tree->k_t_rank(s.level + 1) * std::pow(k, 2) + k * std::floor(s.row / static_cast(s.n)); for (unsigned j = 0; j < k; j++) - q.emplace_front(neigh_state(s.n / k, s.row % s.n, s.col + s.n * j, y + j)); + q.push(neigh_state(s.n / k, s.row % s.n, s.col + s.n * j, y + j)); } } end(); @@ -778,7 +779,6 @@ namespace sdsl } private: - size_type _ptr; bool _is_end = false; const k_tree *tree; @@ -795,7 +795,7 @@ namespace sdsl neigh_state() {} neigh_state(size_type n, idx_type row, idx_type col, size_type level) : n(n), level(level), row(row), col(col) {} }; - std::deque q; + std::stack q; // }; } // namespace sdsl From 7ffb9e6cd0e08ce0d69cc946dfd1325cb654cb96 Mon Sep 17 00:00:00 2001 From: Alexandre P Francisco Date: Thu, 15 Jul 2021 19:29:54 +0100 Subject: [PATCH 56/57] Add helper function. --- include/sdsl/k2_tree.hpp | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index b4fabe447..95cee9646 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -813,6 +813,50 @@ class k2_tree return k_l[level - t_size] == 1; } + + //! Indicates whether node j is adjacent to node i or not, and makes + // it adjacent if possible. + /*! + * \param i Node i. + * \param j Node j. + * \returns true if there is an edge going from node i to node j, + * false otherwise. + */ + bool adj_forced(idx_type i, idx_type j) const + { + uint t_size = k_t.size(); + if (t_size == 0 && k_l.size() == 0) + return false; + size_type n = std::pow(k_k, k_height - 1); + size_type k_2 = std::pow(k_k, 2); + idx_type col, row; + + // This is duplicated to avoid an extra if at the loop. As idx_type + // is unsigned and rank has an offset of one, is not possible to run + // k_t_rank with zero as parameter at the first iteration. + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); + i = i % n; + j = j % n; + idx_type level = k_k * row + col; + n = n / k_k; + + while (level < t_size) + { + if (k_t[level] == 0) + return false; + row = std::floor(i / static_cast(n)); + col = std::floor(j / static_cast(n)); + i = i % n; + j = j % n; + level = k_t_rank(level + 1) * k_2 + k_k * row + col; + n = n / k_k; + } + k_l[level - t_size] = 1; + return true; + } + + bool contains(uint p, uint q) { if(k_l.size() > 0) { From 316b4616dc9647246dd850c94ba7cca4b7a00cf3 Mon Sep 17 00:00:00 2001 From: Alexandre P Francisco Date: Thu, 15 Jul 2021 21:30:16 +0100 Subject: [PATCH 57/57] Fix non const function. --- include/sdsl/k2_tree.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sdsl/k2_tree.hpp b/include/sdsl/k2_tree.hpp index 95cee9646..cf7378206 100644 --- a/include/sdsl/k2_tree.hpp +++ b/include/sdsl/k2_tree.hpp @@ -822,7 +822,7 @@ class k2_tree * \returns true if there is an edge going from node i to node j, * false otherwise. */ - bool adj_forced(idx_type i, idx_type j) const + bool adj_forced(idx_type i, idx_type j) { uint t_size = k_t.size(); if (t_size == 0 && k_l.size() == 0)