#  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: rational.rules 9535 2010-03-05 17:13:17Z benmuell $


# A pointed polyhedron realized in Q^d.
object Polytope<Rational> {


# @category Convex hull computation
# Use the //double description// method as implemented in [[wiki:external_software#cddlib]].
# It is the default algorithm for computation of facets from points or dually.
# It operates with arbitrary precision arithmetic ([[wiki:external_software#GMP]]).
label cdd

# @category Convex hull computation
# Use the //reverse search// method, as implemented in [[wiki:external_software#lrslib]].
label lrs

# @category Convex hull computation
# Use the sequential (beneath-beyond) convex hull algorithm. It performs well at lower dimensions
# and produces a triangulation of the polytope as a byproduct. There is no dual (vertex enumeration)
# implementation of this algorithm.
label beneath_beyond

# @topic credits/cddlib
# Implementation of the double description method of Motzkin et al.
# Copyright by Komei Fukuda.
# http://www.ifor.math.ethz.ch/~fukuda/cdd_home/cdd.html

rule cdd.convex_hull.primal: FACETS, AFFINE_HULL : VERTICES | POINTS {
   cdd_ch_primal($this);
}
weight 4.10;
precondition : N_VERTICES | N_POINTS;
permutation : FacetPerm;

rule cdd.convex_hull.dual: VERTICES, POINTED, FEASIBLE, LINEALITY_DIM : FACETS | INEQUALITIES {
   cdd_ch_dual($this);
}
weight 4.10;
permutation : VertexPerm;

rule cdd.convex_hull.redund: VERTICES, VERTEX_NORMALS : POINTS {
   cdd_eliminate_redundant_points($this);
}
weight 3.20;
permutation : VertexPerm;

rule cdd.convex_hull.redund: VERTEX_NORMALS : VERTICES {
   cdd_vertex_normals($this);
}
weight 3.10;

# @topic credits/lrslib
# Implementation of the reverse search algorithm of Avis and Fukuda.
# Copyright by David Avis.
# http://cgm.cs.mcgill.ca/~avis/lrs.html

rule lrs.convex_hull.primal: FACETS, AFFINE_HULL : VERTICES | POINTS {
   lrs_ch_primal($this);
}
weight 4.10;
precondition : N_VERTICES | N_POINTS;
permutation : FacetPerm;

rule lrs.convex_hull.dual: VERTICES, POINTED, FEASIBLE, LINEALITY_DIM : FACETS | INEQUALITIES {
   lrs_ch_dual($this);
}
weight 4.10;
permutation : VertexPerm;

rule lrs.valid_point: VALID_POINT, FEASIBLE : FACETS | INEQUALITIES {
   lrs_valid_point($this);
}
weight 3.10;

rule lrs.convex_hull.redund: VERTICES, AFFINE_HULL : POINTS {
   lrs_eliminate_redundant_points($this);
}
weight 3.20;
permutation : VertexPerm;


rule lrs.convex_hull.count: N_FACETS : VERTICES | POINTS {
   lrs_count_facets($this);
}
precondition : BOUNDED;
weight 4.5;

rule lrs.convex_hull.count: N_VERTICES, N_BOUNDED_VERTICES, POINTED, FEASIBLE, LINEALITY_DIM : FACETS | INEQUALITIES {
   lrs_count_vertices($this);
}
weight 4.5;

rule lrs.convex_hull.count: N_BOUNDED_VERTICES, POINTED, FEASIBLE, LINEALITY_DIM : FACETS | INEQUALITIES {
   lrs_count_vertices($this, 1);
}
weight 4.3;

# @topic credits/---

rule GRAPH.ADJACENCY : VERTICES {
   $this->GRAPH->ADJACENCY=graph_from_vertices($this->VERTICES);
}
precondition : BOUNDED;
weight 3.30;


rule beneath_beyond.convex_hull.primal, default.triangulation: \
     FACETS, AFFINE_HULL, VERTICES_IN_FACETS, DUAL_GRAPH.ADJACENCY, TRIANGULATION.FACETS, ESSENTIALLY_GENERIC : VERTICES {
   beneath_beyond($this);
}
weight 4.10;
precondition : N_VERTICES;
permutation : FacetPerm;

rule beneath_beyond.convex_hull.primal, default.triangulation: \
     FACETS, VERTICES, AFFINE_HULL, VERTICES_IN_FACETS, DUAL_GRAPH.ADJACENCY, TRIANGULATION_INT : POINTS {
   beneath_beyond($this, 0);
}
weight 4.10;
permutation : FacetPerm;


prefer *.convex_hull cdd, lrs, beneath_beyond



# Special computation of VERTICES for zonotopes:
# In each iteration, add one zone and eliminate the interior points
# This way we avoid the explicit creation of 2^#{ZONOTOPE_INPUT_VECTORS} points at once.
rule VERTICES : ZONOTOPE_INPUT_VECTORS {
   my $P;
   foreach my $vec (@{$this->ZONOTOPE_INPUT_VECTORS}) {
      my $opposite=-$vec;
      $opposite->[0] *= -1;
      my $Z=new Polytope<Rational>(VERTICES => [ $vec, $opposite ]);
      if (defined($P)) {
	 $P=minkowski_sum($P, $Z);
	 my $v=$P->VERTICES;	# enforce computation of VERTICES
	 $P->begin_transaction;
	 $P->remove("POINTS");
	 $P->commit;		# save memory
      } else {
	 $P=$Z;
      }
   }
   $this->VERTICES=$P->VERTICES;
}
weight 3.50;
permutation : VertexPerm;


# @category Lattice polytopes
# This is the defining property: A polytope is lattice if each vertex has integer coordinates.

property LATTICE : Bool;

rule LATTICE : VERTICES {
   $this->LATTICE=is_integral($this->VERTICES);
}


# @category 0/1-polytopes
# Number of points with 0/1-coordinates in a polytope.

property N_01POINTS : Int;


rule TRIANGULATION.FACETS : VERTICES, WEIGHTS {
   $this->TRIANGULATION->FACETS=regular_subdivision($this->VERTICES, $this->WEIGHTS);
}
precondition : WEIGHTS_GENERIC;
weight 3.10;

rule POLYTOPAL_SUBDIVISION : VERTICES, WEIGHTS {
   $this->POLYTOPAL_SUBDIVISION=regular_subdivision($this->VERTICES, $this->WEIGHTS);
}
weight 3.10;

rule TRIANGULATION.GKZ_VECTOR : VERTICES, TRIANGULATION.FACETS {
   $this->TRIANGULATION->GKZ_VECTOR=gkz_vector($this->VERTICES,$this->TRIANGULATION->FACETS);
}
precondition : DIM, AMBIENT_DIM {
   $this->DIM=$this->AMBIENT_DIM;
}

#rule VERTICES : POINTS {
#  $this->VERTICES=jarvis($this->POINTS);
#}
#precondition : BOUNDED, AMBIENT_DIM { $this->BOUNDED and $this->AMBIENT_DIM==2 }
#weight 1.50;

}


# intrinsic rules
INCLUDE
   lp_rational.rules

# self-configuring rules interfacing external software
INCLUDE
   porta.rules

# @category Utilities
#  Read an .ieq or .poi file (porta input) or .poi.ieq or .ieq.poi (porta output)
#  and convert it to a [[Polytope<Rational>]] object
# @param String file filename of a porta file (.ieq or .poi)
# @return Polytope<Rational>

user_function porta2poly($) {
   require PortaParser;
   my $parser=new PortaParser(shift);
   my $P=new Polytope<Rational>($parser->name);
   $P->AMBIENT_DIM=$parser->dim;

   if ($parser->has_points) {
      if ($parser->computed) {
	 $P->VERTICES=$parser->Points;
      } else {
	 $P->POINTS=$parser->Points;
      }
   } else {
      if ($parser->computed) {
	 $P->FACETS=$parser->Ineq;  $P->AFFINE_HULL=$parser->Eq;
      } else {
	 $P->INEQUALITIES=$parser->Ineq;  $P->EQUATIONS=$parser->Eq;
      }
   }

   $P->commit;
   $P;
}

# Local Variables:
# c-basic-offset:3
# mode: perl
# End:
