/* Copyright (c) 1997-2005
   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: morse_matching_critical_faces.cc,v 1.6 2006/01/20 14:26:06 gawrilow Exp $"


#include <Poly.h>
#include <HasseDiagram.h>

#include <morse_matching_tools.h>


using namespace polymake;




/** @file morse_matching_critical_faces
 *
 *  Input: Morse matching
 *
 *  Output: list of critical faces and for each dimension: number of critical faces
 *
 *  @client   morse_matching_critical_faces
 *  @synopsis morse_matching_critical_faces <file>
 *
 *  @reading  MORSE_MATCHING
 *  @writing  MORSE_MATCHING_CRITICAL_FACE_VECTOR, MORSE_MATCHING_N_CRITICAL_FACES
 *
 *  @author   Marc Pfetsch
 *  @date     Fall 2005
 */

int main(int argc, const char* argv[])
{
   typedef Entire<HasseDiagram<Set<int>,bool>::out_edge_list>::const_iterator HasseDiagramOutConstIterator;

   if (argc != 2)
   {
      cerr << "usage: " << argv[0] << " <file> " << endl;
      return 1;
   }

   // read Hasse diagram
   try
   {
      Poly p(argv[1], ios::in | ios::out);
      HasseDiagram<Set<int>,bool> M;

      // read Morse
      if ( p.exists("MORSE_MATCHING") )
      {
	 p.give("MORSE_MATCHING") >> M;
	 int d = M.dim() - 1;

	 // get critical faces
	 Bitset critical = collectCriticalFaces(M);
	 Array<int> numCritical(d+1);
	 for (int k = 0; k <= d; ++k)
	 {
	    for (Entire<sequence>::const_iterator f = entire(M.nodes_of_dim(k)); !f.at_end(); ++f)
	    {
	       if ( critical.contains(*f) )
	       {
		  int dim = M.dim_of_node(*f);
		  assert( 0 <= dim && dim <= d );
		  ++numCritical[dim];
	       }
	    }
	 }

#if POLY_DEBUG
	 cout << endl;
	 for (int k = 0; k <= d; ++k)
	    cout << "d: " << k << "\tcritical: " << numCritical[k] << endl;
#endif

	 /* get critical faces
	  * Note: this is not merged with the above code, since this code should
	  * also work for arbitrary complexes in which we cannot deduce the dimension
	  * from the vertex sets of the faces (as they are used in the following):
	  */
	 PowerSet<int> criticalFaces = findCriticalFaces(M);

	 // write vector
	 p.take("MORSE_MATCHING_CRITICAL_FACE_VECTOR") << numCritical;
	 // write faces
	 p.take("MORSE_MATCHING_CRITICAL_FACES") << as_array(criticalFaces);
      }
   }
   catch (const std::exception& e)
   {
      std::cerr << e.what() << endl;
      abort();
   }

   return 0;
}
