Skip to content

Commit

Permalink
Finish testing and fix from edges_array
Browse files Browse the repository at this point in the history
  • Loading branch information
fmontoto committed Sep 15, 2016
1 parent 53dffea commit 32bbb88
Show file tree
Hide file tree
Showing 2 changed files with 308 additions and 243 deletions.
220 changes: 106 additions & 114 deletions include/sdsl/k2_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#ifndef INCLUDED_SDSL_K2_TREE
#define INCLUDED_SDSL_K2_TREE

#include <deque>
#include <queue>
#include <stdexcept>
#include <tuple>
Expand Down Expand Up @@ -73,34 +74,32 @@ class k2_tree
std::vector<std::deque<bit_vector>> acc(k_height + 1);

k2_tree_ns::_build_from_matrix<bit_vector>(matrix, k,
simulated_size, k_height,
1, 0, 0, acc);
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++)
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++)
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++)
// TODO erase
for(unsigned i = 0; i < (*it).size(); i++) {
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++)
// TODO erase
for(unsigned i = 0; i < (*it).size(); i++) {
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++;
Expand All @@ -124,16 +123,16 @@ class k2_tree
void _neigh(size_type n, idx_type row, idx_type col, size_type level,
std::vector<idx_type>& 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(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<double>(n));
for(unsigned j = 0; j < k_k; j++)
k_k * std::floor(row/static_cast<double>(n));
for (unsigned j = 0; j < k_k; j++)
_neigh(n/k_k, row % n, col + n * j, y + j, acc);
}
}
Expand All @@ -152,17 +151,17 @@ class k2_tree
void _reverse_neigh(size_type n, idx_type row, idx_type col,
size_type level, std::vector<idx_type>& 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<double>(n));
for(unsigned j = 0; j < k_k; j++)
std::floor(col/static_cast<double>(n));
for (unsigned j = 0; j < k_k; j++)
_reverse_neigh(n/k_k, row + n * j, col % n,
y + j * k_k, acc);
}
Expand All @@ -181,12 +180,12 @@ class k2_tree
*/
k2_tree(std::vector<std::vector <int>>& matrix)
{
if(matrix.size() < 1) {
if (matrix.size() < 1) {
throw std::logic_error("Matrix has no elements");
}
std::vector<bit_vector> t;
k_k = k;
if(matrix.size() < 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));
Expand All @@ -205,11 +204,11 @@ 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<std::tuple<idx_type, idx_type>> &edges,
k2_tree(std::vector<std::tuple<idx_type, idx_type>>& edges,
const size_type size)
{
typedef std::tuple<idx_type, idx_type, size_type, idx_type,
idx_type> t_part_tuple;
idx_type> t_part_tuple;

assert(size > 0);
assert(edges.size() > 0);
Expand All @@ -218,89 +217,82 @@ class k2_tree
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);
size_type s = std::pow(k_k, k_height);
k_t = t_bv(k_2 * k_height * edges.size(), 0);
bit_vector k_t_ = bit_vector(k_2 * k_height * edges.size(), 0);
bit_vector k_l_;

std::queue<t_part_tuple> q;
idx_type t = 0, last_level = 0;
idx_type i, j, r_0, c_0, it, c, r;
size_type l;
std::vector<idx_type> pos_by_chunk(k_2, 0);

q.push(t_part_tuple(0, edges.size(), s/k_k, 0, 0));

while(!q.empty()) {
std::vector<idx_type> amount_by_chunk(k_2, 0);
std::tie(i, j, l, r_0, c_0) = q.front();
q.pop();
// Sorting
// 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) {
size_type l = std::pow(k_k, k_height - 1);
std::vector<idx_type> pos_by_chunk(k_2 + 1, 0);

q.push(t_part_tuple(0, edges.size(), l, 0, 0));

while (!q.empty()) {
std::vector<idx_type> 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 = t_bv(k_t.size() - last_level, 0);
k_t.resize(last_level);
last_level = 1; // TODO if t was 0 ?
t = 0;
}
for(it = 0; it < k_2; it++) {
if(amount_by_chunk[it] != 0) {
k_l[t] = 1;
}
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;
}

// 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];
}
for(it = 0; it < k_2 - 1; it++) {
// If not empty chunk, set bit to 1
if(amount_by_chunk[it] != 0) {
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;
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));
}
t++;
}
if(amount_by_chunk[k_2 - 1] != 0) {
k_t[t] = 1;
q.push(t_part_tuple(pos_by_chunk[it],
j,
l/k_k,
r_0 + (k_k - 1) * l,
c_0 + (k_k - 1) * l));
}
t++;
idx_type chunk;

for(it = i; it < j; it++) {
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]);
it--;
// Sort edges' vector
for (unsigned ch = 0; ch < k_2; ch++) {
idx_type be = ch == 0 ? 0 : 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]++;
}
pos_by_chunk[chunk]++;
}
}
}
k_l.resize(t);
k_l_.resize(t);
k2_tree_ns::build_template_vector<t_bv>(k_t_, k_l_, k_t, k_l);

k_t_rank = t_rank(&k_t);
}
Expand All @@ -319,7 +311,7 @@ class k2_tree
//! Move assignment operator
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);
Expand All @@ -333,7 +325,7 @@ class k2_tree
//! Assignment operator
k2_tree& operator=(k2_tree& tr)
{
if(this != &tr) {
if (this != &tr) {
k_t = tr.k_t;
k_l = tr.k_l;
k_t_rank = tr.k_t_rank;
Expand All @@ -345,28 +337,28 @@ class k2_tree
//! Swap operator
void swap(k2_tree& tr)
{
if(this != &tr) {
if (this != &tr) {
std::swap(k_t, tr.k_t);
util::swap_support(k_t_rank, tr.k_t_rank, &k_t, &(tr.k_t));
}
}

//! 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;
}
{
// 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()
{
Expand All @@ -387,7 +379,7 @@ class k2_tree
*/
bool adj(idx_type i, idx_type j) const
{
if(k_t.size() == 0 && k_l.size() == 0)
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);
Expand All @@ -404,8 +396,8 @@ class k2_tree
n = n/k_k;
idx_type y;

while(level < k_t.size()) {
if(k_t[level] == 0)
while (level < k_t.size()) {
if (k_t[level] == 0)
return false;
row = std::floor(i/static_cast<double>(n));
col = std::floor(j/static_cast<double>(n));
Expand All @@ -426,12 +418,12 @@ class k2_tree
std::vector<idx_type>neigh(idx_type i) const
{
std::vector<idx_type> acc{};
if(k_l.size() == 0 && k_t.size() == 0)
if (k_l.size() == 0 && k_t.size() == 0)
return acc;
size_type n =
static_cast<size_type>(std::pow(k_k, k_height)) / k_k;
static_cast<size_type>(std::pow(k_k, k_height)) / k_k;
idx_type y = k_k * std::floor(i/static_cast<double>(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;
}
Expand All @@ -444,13 +436,13 @@ class k2_tree
std::vector<idx_type> reverse_neigh(idx_type i) const
{
std::vector<idx_type> acc{};
if(k_l.size() == 0 && k_t.size() == 0)
if (k_l.size() == 0 && k_t.size() == 0)
return acc;
// Size of the first square division
size_type n =
static_cast<size_type>(std::pow(k_k, k_height)) / k_k;
static_cast<size_type>(std::pow(k_k, k_height)) / k_k;
idx_type y = std::floor(i/static_cast<double>(n));
for(unsigned j = 0; j < k_k; j++)
for (unsigned j = 0; j < k_k; j++)
_reverse_neigh(n/k_k, n * j, i % n, y + j * k_k, acc);

return acc;
Expand All @@ -468,7 +460,7 @@ class k2_tree
std::string name="")
{
structure_tree_node* child = structure_tree::add_child(
v, name, util::class_name(*this));
v, name, util::class_name(*this));
size_type written_bytes = 0;

written_bytes += k_t.serialize(out, child, "t");
Expand Down
Loading

0 comments on commit 32bbb88

Please sign in to comment.