/* Copyright (c) 1997-2010
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: remove_redundancies.cc 9991 2010-12-12 23:36:28Z gawrilow $
*/

#include "polymake/client.h"
#include "polymake/Matrix.h"
#include "polymake/hash_map"
#include "polymake/IncidenceMatrix.h"
#include "polymake/Set.h"
#include "polymake/FacetList.h"

namespace polymake { namespace fan {
  
template <typename Coord>
void remove_redundancies(perl::Object f)
{
   const int ambientDim = f.give("AMBIENT_DIM");
   const Matrix<Coord> i_rays = f.give("INPUT_RAYS");
   const IncidenceMatrix<> i_cones = f.give("INPUT_CONES");
   const Matrix<Coord> linealitySpace = f.lookup("LINEALITY_SPACE");
   const int n_i_cones=i_cones.rows();
   perl::ObjectType t=perl::ObjectType::construct<Coord>("Cone");
   hash_map<Vector<Coord>,int > rays;    
   FacetList max_cones;
   int n_rays=0;
    
   for(int i=0; i<n_i_cones;++i) 
   {
      perl::Object cone(t);
      cone.take("INPUT_RAYS")<<i_rays.minor(i_cones.row(i),All);
      cone.take("LINEALITY_SPACE")<<linealitySpace;
      const Matrix<Coord> c_rays=cone.give("RAYS");
      Set<int> ray_indices;
      for(typename Entire<Rows<Matrix<Coord> > >::const_iterator r=entire(rows(c_rays)); !r.at_end(); ++r) {
         typename hash_map<Vector<Coord>,int >::iterator r_iti=rays.find(*r);
         if (r_iti==rays.end()) {
            rays[*r]=n_rays;
            ray_indices.insert(n_rays++);
         }
         else 
            ray_indices.insert(r_iti->second);
      }
      max_cones.insertMax(ray_indices);
   }
    
    

   // create ray matrix
   Matrix<Coord> R(n_rays,ambientDim);
   for(typename Entire<hash_map<Vector<Coord>,int> >::const_iterator r=entire(rays); !r.at_end(); ++r)
      R.row(r->second)=r->first;

   f.take("RAYS")<<R;
   f.take("MAXIMAL_CONES")<<max_cones;
}
  
FunctionTemplate4perl("remove_redundancies<Coord>(PolyhedralFan<Coord>) : void");

} }

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