/* Copyright (c) 1997-2004
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
   http://www.math.tu-berlin.de/polymake,  mailto:polymake@math.tu-berlin.de

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
*/

#ident "$Project: polymake $$Id: subcomplex_tools.cc,v 1.11 2004/07/27 18:12:29 gawrilow Exp $"

#include <complex_tools.h>

namespace polymake { namespace topaz {

FacetList star_in_HD (const HasseDiagram<>& HD, const int f)
{
   FacetList star;
   
   Bitset visited(HD.nodes());
   std::list<int> node_queue;
   node_queue.push_back(f);
   visited+=f;
   
   while (!node_queue.empty()) {
      const int n=node_queue.front();
      node_queue.pop_front(); 
      
      const bool is_facet = HD.out_edges(n).begin().to_node() == HD.top_node();
      
      if (is_facet)
	 star.insert(HD.node(n));
      else
	 for (Entire<HasseDiagram<>::out_edge_list>::const_iterator e=entire(HD.out_edges(n));
	      !e.at_end(); ++e) {
	    const int nn=e.to_node();
	    
	    if ( !visited.contains(nn) ) {     // add nn to the queue.
	       visited+=nn;
	       node_queue.push_back(nn);
	    }
	 }
   }
   
   return star;
}
   
FacetList link_in_HD (const HasseDiagram<>& HD, const int f)
{
   const Set<int> F = HD.node(f);
   FacetList link;
   
   Bitset visited(HD.nodes());
   std::list<int> node_queue;
   node_queue.push_back(f);
   visited+=f;
   
   while (!node_queue.empty()) {
      const int n=node_queue.front();
      node_queue.pop_front(); 
      
      const bool is_facet = HD.out_edges(n).begin().to_node() == HD.top_node();
      
      if (is_facet) {
	 const HasseDiagram<>::node_attr& face= HD.node(n);
	 link.insert(face-F);
	 
      } else    
	 for (Entire<HasseDiagram<>::out_edge_list>::const_iterator e=entire(HD.out_edges(n));
	      !e.at_end(); ++e) {
	    const int nn=e.to_node();
	    
	    if ( !visited.contains(nn) ) {     // add nn to the queue.
	       visited+=nn;
	       node_queue.push_back(nn);
	    }
	 }
   }
   
   return link;
}
   
std::list< Set<int> > vertexStar_of_HD(const HasseDiagram<>& HD, const int v)
{
  std::list< Set<int> > star;

  // search the vertices of the HD for v
  int start_node;
  for (Entire<sequence>::iterator it=entire(HD.nodes_of_dim(0)); !it.at_end(); ++it)
    if (HD.node(*it).front()==v) {
      start_node=*it;
      break;
    }

  Bitset visited(HD.nodes());
  std::list<int> node_queue;
  node_queue.push_back(start_node);
  visited+=start_node;

  while (!node_queue.empty()) {
    const int n=node_queue.front();      // remove first node from the queue
    node_queue.pop_front();

    const HasseDiagram<>::node_attr& f= HD.node(n);
    const bool is_facet = HD.out_edges(n).begin().to_node() == HD.top_node();

    if (is_facet)
      star.push_back(f);

    else
      for (Entire<HasseDiagram<>::out_edge_list>::const_iterator e=entire(HD.out_edges(n)); !e.at_end(); ++e) {
	const int nn=e.to_node();
	
	if ( !visited.contains(nn) ) {     // add nn to the queue
	  visited+=nn;
	  node_queue.push_back(nn);
	}
      }
  }
  
  return star;
}

std::list< Set<int> > vertexLink_of_HD(const HasseDiagram<>& HD, const int v)
{
  std::list< Set<int> > link;

  // search the vertices of the HD for v
  int start_node;
  for (Entire<sequence>::iterator it=entire(HD.nodes_of_dim(0)); !it.at_end(); ++it)
    if (HD.node(*it).front()==v) {
      start_node=*it;
      break;
    }

  Bitset visited(HD.nodes());
  std::list<int> node_queue;
  node_queue.push_back(start_node);
  visited+=start_node;

  while (!node_queue.empty()) {
    const int n=node_queue.front();      // remove first node from the queue
    node_queue.pop_front();
     
    const HasseDiagram<>::node_attr& f= HD.node(n);
    const bool is_facet = HD.out_edges(n).begin().to_node() == HD.top_node();

    if (is_facet)
      link.push_back(f-v);

    else
      for (Entire<HasseDiagram<>::out_edge_list>::const_iterator e=entire(HD.out_edges(n)); !e.at_end(); ++e) {
	const int nn=e.to_node();
	
	if ( !visited.contains(nn) ) {
	  visited+=nn;
	  node_queue.push_back(nn);
	}
      }
  }
  
  return link;
}

// computes the vertex set of the link of the vertex v. 
Set<int> vert_of_vertexLink(const HasseDiagram<>& HD, const int v)
{
  Set<int> V;

  // search the vertices of the HD for v
  int start_node;
  for (Entire<sequence>::const_iterator it=entire(HD.nodes_of_dim(0)); !it.at_end(); ++it) {
    if (HD.node(*it).front()==v) {
      start_node=*it;
      break;
    }
  }

  Bitset visited(HD.nodes());
  std::list<int> node_queue;
  node_queue.push_back(start_node);
  visited+=start_node;

  while (!node_queue.empty()) {
    const int n=node_queue.front();      // remove first node from the queue
    node_queue.pop_front();
    
    const HasseDiagram<>::node_attr& f= HD.node(n);
    const bool is_facet = HD.out_edges(n).begin().to_node() == HD.top_node();
    
    if (is_facet)
      V+=f;
  
    else  
      for (Entire<HasseDiagram<>::out_edge_list>::const_iterator e=entire(HD.out_edges(n)); !e.at_end(); ++e) {
	const int nn=e.to_node();
	
	if ( !visited.contains(nn) ) {
	  visited+=nn;
	  node_queue.push_back(nn);
	}
      }
  }
  V-=v;  // remove v from the list of vertices of the link of v
  
  return V;
}

} }

// Local Variables:
// mode:C++
// c-basic-offset:3
// End:
