#  Copyright (c) 1997-2021
#  Ewgenij Gawrilow, Michael Joswig, and the polymake team
#  Technische Universität Berlin, Germany
#  https://polymake.org
#
#  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.
#-------------------------------------------------------------------------------

object Cone<Rational> {

rule TRIANGULATION.FACETS : RAYS, TRIANGULATION.WEIGHTS {
   $this->TRIANGULATION->FACETS=regular_subdivision($this->RAYS, $this->TRIANGULATION->WEIGHTS);
}
weight 3.10;
incurs TRIANGULATION.FacetPerm;

rule TRIANGULATION.WEIGHTS : RAYS, TRIANGULATION.FACETS {
   $this->TRIANGULATION->WEIGHTS=is_regular($this->RAYS,$this->TRIANGULATION->FACETS);
}

}

object Polytope<Rational> {

# @category Geometry
# A rational polytope is lattice if each bounded vertex has integer coordinates.
property LATTICE : Bool;

rule LATTICE : VERTICES , FAR_FACE {
   $this->LATTICE=is_integral($this->VERTICES->minor(~$this->FAR_FACE,All));
}
precondition : POINTED;

rule TRIANGULATION.GKZ_VECTOR : RAYS, TRIANGULATION.FACETS {
   $this->TRIANGULATION->GKZ_VECTOR=gkz_vector($this->RAYS,$this->TRIANGULATION->FACETS);
}
precondition : FULL_DIM;
precondition : BOUNDED;


# @category Geometry
# Number of points with 0/1-coordinates in a polytope.
# @depends azove
property N_01POINTS : Int;


# @category Triangulation and volume
# The //k//-dimensional Euclidean volume of a //k//-dimensional rational polytope 
# embedded in R^n.
# This value is obtained by summing the square roots of the entries in SQUARED_RELATIVE_VOLUMES
# using the function //naive_sum_of_square_roots//. Since this latter function
# does not try very hard to compute the real value, you may have to resort to
# a computer algebra package.
# The value is encoded as a map collecting the coefficients of various roots encountered in the sum.
# For example, {(3 1/2),(5 7)} represents sqrt{3}/2 + 7 sqrt{5}.
# If the output is not satisfactory, please use a symbolic algebra package.
# @example [require bundled:flint] The following prints the 2-dimensional volume of a centered square with side length 2 embedded in the 3-space (the result is 4):
# > $M = new Matrix([1,-1,1,0],[1,-1,-1,0],[1,1,-1,0],[1,1,1,0]);
# > $p = new Polytope<Rational>(VERTICES=>$M);
# > print $p->RELATIVE_VOLUME;
# | {(1 4)}
property RELATIVE_VOLUME : Map<Rational, Rational>;

rule RELATIVE_VOLUME : SQUARED_RELATIVE_VOLUMES {
    $this->RELATIVE_VOLUME = sum_of_square_roots_naive($this->SQUARED_RELATIVE_VOLUMES);
}

# @category Geometry
# The (d-1)-dimensional Euclidean volumes of the facets of an d-dimensional rational polytope emedded in R^d.
# Each entry in the returned Array is the volume of one facet of the polytope, 
# where the facets are indexed as in [[FACETS|FACETS]].
# @example The 2-dimensional cross-polytope is a rational polytope whose edges (facets) all have lengths sqrt(2).
# > print cross(2)->FACET_VOLUMES;
# | 0+1r2 0+1r2 0+1r2 0+1r2 
property FACET_VOLUMES : Array<QuadraticExtension>;

rule FACET_VOLUMES : VERTICES, VERTICES_IN_FACETS, FACETS {
  $this->FACET_VOLUMES = facet_areas($this->VERTICES, $this->VERTICES_IN_FACETS, $this->FACETS) 
}
precondition : FULL_DIM;
precondition : BOUNDED;

}

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

# @category Optimization
#  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->CONE_AMBIENT_DIM=($parser->dim)+1;

   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:
# cperl-indent-level:3
# mode: perl
# End:
