//
//=======================================================================
// Copyright 1997-2001 University of Notre Dame.
// Copyright 2009 Trustees of Indiana University.
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//

#ifndef BOOST_INCREMENTAL_COMPONENTS_HPP
#define BOOST_INCREMENTAL_COMPONENTS_HPP

#include <boost/detail/iterator.hpp>
#include <boost/graph/detail/incremental_components.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/make_shared.hpp>
#include <boost/pending/disjoint_sets.hpp>
#include <iterator>

namespace boost {

  // A connected component algorithm for the case when dynamically
  // adding (but not removing) edges is common.  The
  // incremental_components() function is a preparing operation. Call
  // same_component to check whether two vertices are in the same
  // component, or use disjoint_set::find_set to determine the
  // representative for a vertex.

  // This version of connected components does not require a full
  // Graph. Instead, it just needs an edge list, where the vertices of
  // each edge need to be of integer type. The edges are assumed to
  // be undirected. The other difference is that the result is stored in
  // a container, instead of just a decorator.  The container should be
  // empty before the algorithm is called. It will grow during the
  // course of the algorithm. The container must be a model of
  // BackInsertionSequence and RandomAccessContainer
  // (std::vector is a good choice). After running the algorithm the
  // index container will map each vertex to the representative
  // vertex of the component to which it belongs.
  //
  // Adapted from an implementation by Alex Stepanov. The disjoint
  // sets data structure is from Tarjan's "Data Structures and Network
  // Algorithms", and the application to connected components is
  // similar to the algorithm described in Ch. 22 of "Intro to
  // Algorithms" by Cormen, et. all.
  //  

  // An implementation of disjoint sets can be found in
  // boost/pending/disjoint_sets.hpp
  
  template <class EdgeListGraph, class DisjointSets>
  void incremental_components(EdgeListGraph& g, DisjointSets& ds)
  {
    typename graph_traits<EdgeListGraph>::edge_iterator e, end;
    for (boost::tie(e,end) = edges(g); e != end; ++e)
      ds.union_set(source(*e,g),target(*e,g));
  }
  
  template <class ParentIterator>
  void compress_components(ParentIterator first, ParentIterator last)
  {
    for (ParentIterator current = first; current != last; ++current) 
      detail::find_representative_with_full_compression(first, current-first);
  }
  
  template <class ParentIterator>
  typename boost::detail::iterator_traits<ParentIterator>::difference_type
  component_count(ParentIterator first, ParentIterator last)
  {
    std::ptrdiff_t count = 0;
    for (ParentIterator current = first; current != last; ++current) 
      if (*current == current - first) ++count; 
    return count;
  }
  
  // This algorithm can be applied to the result container of the
  // connected_components algorithm to normalize
  // the components.
  template <class ParentIterator>
  void normalize_components(ParentIterator first, ParentIterator last)
  {
    for (ParentIterator current = first; current != last; ++current) 
      detail::normalize_node(first, current - first);
  }
  
  template <class VertexListGraph, class DisjointSets> 
  void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds)
  {
    typename graph_traits<VertexListGraph>
      ::vertex_iterator v, vend;
    for (boost::tie(v, vend) = vertices(G); v != vend; ++v)
      ds.make_set(*v);
  }

  template <class Vertex, class DisjointSet>
  inline bool same_component(Vertex u, Vertex v, DisjointSet& ds)
  {
    return ds.find_set(u) == ds.find_set(v);
  }

  // Class that builds a quick-access indexed linked list that allows
  // for fast iterating through a parent component's children.
  template <typename IndexType>
  class component_index {

  private:
    typedef std::vector<IndexType> IndexContainer;

  public:
    typedef counting_iterator<IndexType> iterator;
    typedef iterator const_iterator;
    typedef IndexType value_type;
    typedef IndexType size_type;

    typedef detail::component_index_iterator<typename IndexContainer::iterator>
      component_iterator;

  public:
    template <typename ParentIterator,
              typename ElementIndexMap>
    component_index(ParentIterator parent_start,
                    ParentIterator parent_end,
                    const ElementIndexMap& index_map) :
      m_num_elements(std::distance(parent_start, parent_end)),
      m_components(make_shared<IndexContainer>()),
      m_index_list(make_shared<IndexContainer>(m_num_elements)) {

      build_index_lists(parent_start, index_map);
      
    } // component_index

    template <typename ParentIterator>
    component_index(ParentIterator parent_start,
                    ParentIterator parent_end) :
      m_num_elements(std::distance(parent_start, parent_end)),
      m_components(make_shared<IndexContainer>()),
      m_index_list(make_shared<IndexContainer>(m_num_elements)) {

      build_index_lists(parent_start, boost::identity_property_map());

    } // component_index

    // Returns the number of components
    inline std::size_t size() const {
      return (m_components->size());
    }

    // Beginning iterator for component indices
    iterator begin() const {
      return (iterator(0));
    }

    // End iterator for component indices
    iterator end() const {
      return (iterator(this->size()));
    }

    // Returns a pair of begin and end iterators for the child
    // elements of component [component_index].
    std::pair<component_iterator, component_iterator>
    operator[](IndexType component_index) const {

      IndexType first_index = (*m_components)[component_index];

      return (std::make_pair
              (component_iterator(m_index_list->begin(), first_index),
               component_iterator(m_num_elements)));
    }

  private:
    template <typename ParentIterator,
              typename ElementIndexMap>
    void build_index_lists(ParentIterator parent_start,
                           const ElementIndexMap& index_map) {

      typedef typename std::iterator_traits<ParentIterator>::value_type Element;
      typename IndexContainer::iterator index_list =
        m_index_list->begin();

      // First pass - find root elements, construct index list
      for (IndexType element_index = 0; element_index < m_num_elements;
           ++element_index) {

        Element parent_element = parent_start[element_index];
        IndexType parent_index = get(index_map, parent_element);

        if (element_index != parent_index) {
          index_list[element_index] = parent_index;
        }
        else {
          m_components->push_back(element_index);

          // m_num_elements is the linked list terminator
          index_list[element_index] = m_num_elements;
        }
      }

      // Second pass - build linked list
      for (IndexType element_index = 0; element_index < m_num_elements;
           ++element_index) {

        Element parent_element = parent_start[element_index];
        IndexType parent_index = get(index_map, parent_element);

        if (element_index != parent_index) {

          // Follow list until a component parent is found
          while (index_list[parent_index] != m_num_elements) {
            parent_index = index_list[parent_index];
          }

          // Push element to the front of the linked list
          index_list[element_index] = index_list[parent_index];
          index_list[parent_index] = element_index;
        }
      }

    } // build_index_lists

  protected:
    IndexType m_num_elements;
    shared_ptr<IndexContainer> m_components, m_index_list;

  }; // class component_index
 
} // namespace boost

#endif // BOOST_INCREMENTAL_COMPONENTS_HPP
