Raw File
kruskal.hpp
/*
 * Kruskal.h
 *
 * Created on: Feb 04, 2020
 *     Author: Hung Tran (hung@ae.cs.uni-frankfurt.de)
 */

#ifndef EM_CC_KRUSKAL_H
#define EM_CC_KRUSKAL_H

#include "robin_hood.h"
#include "defs.hpp"


namespace SemiExtMem {
  #define im_node_map robin_hood::unordered_map
  #define simple_node_map std::vector

  template<typename EdgeVectorType>
  class Kruskal {
  private:
      const EdgeVectorType &_edges;
      const size_t _min_index;
      const size_t _max_index;
      em_mapping& _components;

	  node_t _next_node;
	  im_node_map<node_t,node_t> _id_map;
	  simple_node_map<node_t> _reverse_map;
	  simple_node_map<node_t> _parent;
	  simple_node_map<uint8_t> _height;

  public:
	  static constexpr size_t MEMORY_OVERHEAD_FACTOR = 8;
      Kruskal(const EdgeVectorType& edges, size_t min_index, size_t max_index, em_mapping & components) :
        _edges(edges),
        _min_index(min_index),
        _max_index(max_index),
        _components(components),
        _next_node(0),
        _id_map(),
        _reverse_map(),
        _parent(),
        _height()
      {
          // go through edges
	      int index = 0;
          for (auto it=edges.begin()+_min_index; it!=edges.begin()+_max_index; it++) {
	          index++;
              const auto& edge = *it;
	          node_t u = use_map(edge.u);
	          node_t v = use_map(edge.v);
              if (op_union(u, v)) {
              }
          }

          // output component assignment
          for (node_t i=0; i<_reverse_map.size(); ++i) {
	          const node_t& u = _reverse_map[i];
	          const node_t& j = op_find(i);
	          const node_t& v = _reverse_map[j];
	          if (u != v) {
		          _components.push_back(edge_t(u, v));
	          }
          }
      }

  private:

	  inline node_t use_map(node_t u) {
		  auto lookup = _id_map.find(u);
		  if (lookup == _id_map.end()) {
			  _id_map[u] = _next_node;
			  _reverse_map.push_back(u);
			  _parent.push_back(_next_node);
			  _height.push_back(0);
			  _next_node++;
			  return _next_node-1;
		  } else {
			  return lookup->second;
		  }

	  }

      inline node_t op_find(node_t u) {
          // find root
          node_t root = u;
          while (_parent[root] != root) {
	          root = _parent[root];
          }

          // apply path compression
          node_t tmp;
          while (_parent[u] != u) {
              tmp = _parent[u];
              _parent[u] = root;
              u = tmp;
          }

          return root;
      }

      inline bool op_union(node_t u, node_t v) {
          const node_t root_u = op_find(u);
          const node_t root_v = op_find(v);

          // cycle detected
          if (root_u == root_v) return false;

          // attach smaller to bigger tree
          if (_height[root_u] < _height[root_v]) {
              _parent[root_u] = root_v;
          } else {
              _parent[root_v] = root_u;
          }

          // increment the height of the resulting tree if they are the same
          if (_height[root_u] == _height[root_v]) {
              ++_height[root_u];
          }

          return true;
      }
  };

}

template class SemiExtMem::Kruskal<em_edge_vector>;
template class SemiExtMem::Kruskal<im_edge_vector>;
using IMKruskal = SemiExtMem::Kruskal<im_edge_vector>;
using SEMKruskal = SemiExtMem::Kruskal<em_edge_vector>;

#endif //EM_CC_KRUSKAL_H
back to top