/* Copyright (c) 1997-2009
   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: lattice_isomorphic_polytopes.cc 9294 2009-08-14 14:48:37Z paffenho $
*/

#include <polymake.h>
#include <Integer.h>
#include <Rational.h>
#include <Matrix.h>
#include <SparseMatrix.h>
#include <Vector.h>
#include <Graph.h>
#include <graph_compare.h>

namespace polymake { namespace polytope {

   void facet_vertex_distance_graph(Graph<>& G, Vector<int>& C, const SparseMatrix<int>& D)
   {
      int m = D.rows();
      G.resize(m+D.cols());
      C = zero_vector<int>(m)|ones_vector<int>(D.cols());
      
      for ( Entire<Rows<SparseMatrix<int> > >::const_iterator r = entire(rows(D));
	    !r.at_end(); ++r )
	 for ( Entire<SparseMatrix<int>::row_type>::const_iterator c = entire(*r);
	      !c.at_end(); ++c ) {
	    int n = G.add_node();
	    G.edge(r.index(),n);
	    G.edge(m+c.index(),n);
	    C |= D[r.index()][c.index()];
	 }
   }
    
   bool lattice_isomorphic_smooth_polytopes(perl::Object p1, perl::Object p2)
   {
      if ( !p1.give("LATTICE") || !p2.give("LATTICE") ) 
	 throw std::runtime_error("lattice isomorphism test: polytopes must be lattice polytopes");

      if ( !p1.give("SMOOTH") || !p2.give("SMOOTH") ) 
	 throw std::runtime_error("lattice isomorphism test: polytopes must be smooth");
      
      Matrix<int> D1 = p1.give("FACET_VERTEX_LATTICE_DISTANCES");
      Matrix<int> D2 = p2.give("FACET_VERTEX_LATTICE_DISTANCES");

      if ( D1.rows() != D2.rows() || D1.cols() != D2.cols() ) 
	 return false;

      Graph<> G1, G2;
      Vector<int> C1, C2;
      facet_vertex_distance_graph(G1,C1,D1);
      facet_vertex_distance_graph(G2,C2,D2);
      
      return graph::isomorphic(G1,C1,G2,C2);
   }

   UserFunction4perl("# @category Comparing"
		     "# Tests whether two smooth lattice polytopes are lattice equivalent"
                     "# by comparing lattice distances between vertices and facets. "
		     "# @param LatticePolytope P1"
		     "# @param LatticePolytope P2",
		     &lattice_isomorphic_smooth_polytopes, "lattice_isomorphic_smooth_polytopes(Polytope,Polytope)");
} }
