#  Copyright (c) 1997-2006
#  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.
#----------------------------------------------------------------------------
#  $Project: polymake $$Id: common.rules 7561 2007-01-15 15:18:23Z sherrmann $


INCLUDE
  polytope_properties.rules
  flag_vector.rules
  polarize.rules

object Polytope;

FACET_LABELS : VERTEX_LABELS, VERTICES_IN_FACETS
   $this->FACET_LABELS=induced_labels($this->VERTEX_LABELS, $this->VERTICES_IN_FACETS);

AMBIENT_DIM : VERTICES | POINTS
WEIGHT 0.10
# projective dimension of the space where the POINTS live in
   $this->AMBIENT_DIM=dim($this->VERTICES | POINTS)-1;

AMBIENT_DIM : FACETS | INEQUALITIES
WEIGHT 0.10
# projective dimension of the space where the INEQUALITIES live in
   $this->AMBIENT_DIM=dim($this->FACETS | INEQUALITIES)-1;

DIM : AMBIENT_DIM, AFFINE_HULL
WEIGHT 0.10
   $this->DIM= $this->AMBIENT_DIM - @{$this->AFFINE_HULL};

POINTED :
PRECONDITION: VERTICES | VALID_POINT
   defined($this->VERTICES | VALID_POINT)
WEIGHT 0.10
   $this->POINTED=1

POINTED : POINTS
WEIGHT 1.10
   foreach (@{$this->POINTS}) {
      if (! /^\s*0+(?:\.0*)?\s/) {
         $this->POINTED=1;
	 return;
      }
   }
   $this->POINTED=0;

ONE_VERTEX : 
PRECONDITION: VERTICES 
  defined($this->VERTICES)
WEIGHT 0.10
  $this->ONE_VERTEX=(@{$this->VERTICES})[0];


ONE_VERTEX : FACETS | INEQUALITIES
PRECONDITION: POINTED
  $this->POINTED
WEIGHT 3.20
  client("one_vertex",$this);
  
FEASIBLE :
PRECONDITION: VERTICES | POINTS | FACETS | VALID_POINT
   defined($this->VERTICES | POINTS | FACETS | VALID_POINT)
WEIGHT 0.10
   $this->FEASIBLE=1

N_POINTS : POINTS
WEIGHT 0.10
   $this->N_POINTS=@{$this->POINTS};

N_VERTICES : VERTICES
WEIGHT 0.10
   $this->N_VERTICES=@{$this->VERTICES};

N_VERTICES : VERTICES_IN_FACETS
WEIGHT 0.10
# some day here will be called some tiny C++ snippet returning VIF.cols()
   $this->N_VERTICES=max_elem($this->VERTICES_IN_FACETS)+1;

N_INEQUALITIES : INEQUALITIES
WEIGHT 0.10
   $this->N_INEQUALITIES=@{$this->INEQUALITIES};

N_BOUNDED_VERTICES : N_VERTICES, FAR_FACE
WEIGHT 0.10
   my @far=$this->FAR_FACE =~ /(\d+)/g;
   $this->N_BOUNDED_VERTICES=$this->N_VERTICES-@far;

N_FACETS : FACETS
WEIGHT 0.10
   $this->N_FACETS=@{$this->FACETS};

N_FACETS : VERTICES_IN_FACETS
WEIGHT 0.10
   $this->N_FACETS=@{$this->VERTICES_IN_FACETS};

N_EDGES : GRAPH
WEIGHT 1.10
   my $edges=0;
   foreach (row_sizes($this->GRAPH)) { $edges+=$_ }
   if ($edges % 2 == 0) {
      $edges /= 2;
   } else {
      die "GRAPH contains an edge which is not matched\n";
   }
   $this->N_EDGES=$edges;

N_RIDGES : DUAL_GRAPH
WEIGHT 1.10
   my $ridges=0;
   foreach (row_sizes($this->DUAL_GRAPH)) { $ridges+=$_ }
   if ($ridges % 2 == 0) {
      $ridges /= 2;
   } else {
      die "DUAL_GRAPH contains a ridge which is not matched.\n";
   }
   $this->N_RIDGES=$ridges;

N_VERTEX_FACET_INC : VERTICES_IN_FACETS
WEIGHT 1.10
   my $n=0;
   foreach (row_sizes($this->VERTICES_IN_FACETS)) { $n+=$_ }
   $this->N_VERTEX_FACET_INC=$n;

N_VERTEX_FACET_INC : F2_VECTOR
WEIGHT 0.10
  my $f=$this->F2_VECTOR->[0]; # first row of the f^2-vector
   $f =~ /(\d)+ \D*$/x;
   $this->N_VERTEX_FACET_INC=$1;

FACETS_THRU_VERTICES : VERTICES_IN_FACETS
WEIGHT 1.10
   $this->FACETS_THRU_VERTICES=transpose($this->VERTICES_IN_FACETS);

SIMPLICIAL :
PRECONDITION: ESSENTIALLY_GENERIC
   $this->ESSENTIALLY_GENERIC
WEIGHT 0.10
   $this->SIMPLICIAL=1

SIMPLICIAL : DIM, VERTICES_IN_FACETS
WEIGHT 1.10
   foreach my $nv (row_sizes($this->VERTICES_IN_FACETS)) {
      if ($nv != $this->DIM) {
	 $this->SIMPLICIAL=0;
	 return;
      }
   }
   $this->SIMPLICIAL=1;

SIMPLE : DIM, VERTICES_IN_FACETS
WEIGHT 1.10
   foreach my $nv (col_sizes($this->VERTICES_IN_FACETS)) {
      if ($nv != $this->DIM) {
	 $this->SIMPLE=0;
	 return;
      }
   }
   $this->SIMPLE=1;

SIMPLE, SIMPLE_POLYHEDRON : DIM, FAR_FACE, VERTEX_DEGREES
   my %far_face= map { $_ => 1 } $this->FAR_FACE =~ /(\d+)/g;
   my $simple=1;
   my $simple_polyhedron=1;
   my $v=0;
   foreach (split /\s+/, $this->VERTEX_DEGREES) {
      if ($_ != $this->DIM) {
         $simple=0;
	 if (!exists($far_face{$v})) {
            $simple_polyhedron=0;
            break;
	 }
      }
      ++$v;
   }
   $this->SIMPLE=$simple;
   $this->SIMPLE_POLYHEDRON=$simple_polyhedron;

TOWARDS_FAR_FACE : VERTICES, FAR_FACE
PRECONDITION: BOUNDED
   !$this->BOUNDED
BODY:
   my @far_face= $this->FAR_FACE =~ /(\d+)/g;
   my $cone= new Apps::polytope::RationalPolytope(INEQUALITIES => @{$this->VERTICES}[@far_face]);
   $this->TOWARDS_FAR_FACE= $cone->REL_INT_POINT;

TOWARDS_FAR_FACE :
PRECONDITION: BOUNDED
   $this->BOUNDED
BODY:
   $this->TOWARDS_FAR_FACE= undef;

EVEN : GRAPH
WEIGHT 1.10
   client("bipartite", $this, "GRAPH", "EVEN");

DUAL_EVEN : DUAL_GRAPH
WEIGHT 1.10
   client("bipartite", $this, "DUAL_GRAPH", "DUAL_EVEN");

GRAPH_SIGNATURE, EVEN : GRAPH
WEIGHT 2.10
  client("bipartite", $this, "GRAPH", "EVEN", "GRAPH_SIGNATURE");

DUAL_GRAPH_SIGNATURE, EVEN : DUAL_GRAPH
WEIGHT 2.10
  client("bipartite", $this, "GRAPH", "EVEN", "DUAL_GRAPH_SIGNATURE");

TRIANGLE_FREE : GRAPH
   client("triangle_free", $this, "GRAPH", "TRIANGLE_FREE");

DUAL_TRIANGLE_FREE : DUAL_GRAPH
   client("triangle_free", $this, "DUAL_GRAPH", "DUAL_TRIANGLE_FREE");

TRIANGLE_FREE :
PRECONDITION: EVEN
   $this->EVEN
WEIGHT 0.10
   $this->TRIANGLE_FREE=1;

DUAL_TRIANGLE_FREE :
PRECONDITION: DUAL_EVEN
   $this->DUAL_EVEN
WEIGHT 0.10
   $this->DUAL_TRIANGLE_FREE=1;

CONNECTIVITY : GRAPH
   client("connectivity", $this, "GRAPH", "CONNECTIVITY")

DUAL_CONNECTIVITY : DUAL_GRAPH
   client("connectivity", $this, "DUAL_GRAPH", "DUAL_CONNECTIVITY")

F_VECTOR, F2_VECTOR : HASSE_DIAGRAM
WEIGHT 3.10
   client("f2_vector", $this)

SIMPLICITY, SIMPLICIALITY : DIM
PRECONDITION : N_VERTICES
   $this->DIM+1 == $this->N_VERTICES
WEIGHT 0.10
# simplex case
   $this->SIMPLICIALITY=$this->SIMPLICITY=$this->DIM;

SIMPLICIALITY : F_VECTOR, F2_VECTOR
PRECONDITION: DIM, N_VERTICES
   $this->DIM+1 != $this->N_VERTICES
BODY:
# a polytope is k-simplicial if each k-face is a simplex,
# i.e. f_{0,k} = (k+1) * f_k
   my @flag0= $this->F2_VECTOR->[0] =~ /\d+/g;
   my $k=0;
   foreach my $f ($this->F_VECTOR =~ /\d+/g) {
      last if $flag0[$k] != ($k+1)*$f;
      $k++;
   }
   $this->SIMPLICIALITY=$k-1;

SIMPLICITY : F_VECTOR, F2_VECTOR
PRECONDITION: DIM, N_VERTICES
   $this->DIM+1 != $this->N_VERTICES
BODY:
# dual notion to simpliciality,
# i.e. f_{k,d-1} = (k+1) * f_k
   my @flag_1= $this->F2_VECTOR->[-1] =~ /\d+/g;
   my $k=0;
   foreach my $f (reverse($this->F_VECTOR =~ /\d+/g)) {
      last if $flag_1[-1-$k] != ($k+1)*$f;
      $k++;
   }
   $this->SIMPLICITY=$k-1;

FACE_SIMPLICITY : DIM
PRECONDITION: SIMPLE
   $this->SIMPLE
BODY:
   $this->FACE_SIMPLICITY=$this->DIM;

FACE_SIMPLICITY : F2_VECTOR
PRECONDITION: SIMPLE
   !$this->SIMPLE
BODY :
# a polytope is k-face-simple if all k-faces are simple
# i.e. 2 f_{1,k} = f_{0,1,k} = k * f_{0,k}
   my $k=0;
   while ($k < $#{$this->F2_VECTOR}) {
      my @f=split(/\s+/, $this->F2_VECTOR->[$k+1]);
      last if 2 * $f[1] != ($k+1) * $f[0];
      ++$k;
   }
   $this->FACE_SIMPLICITY=$k;

CUBICALITY : F2_VECTOR
PRECONDITION: EVEN
   $this->EVEN
BODY:
# a polytope is k-cubical if its graph is bipartite and all j-faces have 2^j vertices for all j<=k
# i.e. f_{j,0} = 2^j * f_j
   my $k=1;
   my $k2=2; # 2^k
   my $dim=@{$this->F2_VECTOR};
   my ($n_vertices) = $this->F2_VECTOR->[0] =~ m/^\s*(\d+)\s+.*/;
   while ($k<$dim-1) {
      my @f=split /\s+/, $this->F2_VECTOR->[$k+1];
      $k2*=2;
      last if $f[0] != $k2 * $f[$k+1];
      ++$k;
   }
   if (($k==$dim-1) && ($n_vertices==2*$k2)) { ++$k; } # it's a cube
   $this->CUBICALITY=$k;

CUBICAL : FACET_SIZES
PRECONDITION: EVEN, DIM
  $this->EVEN && $this->DIM==4
WEIGHT 1.10
# this is a special case of the previous rule which is useful for 4-polytopes with a very large face lattice
  my @facet_sizes= split  /\s+/, $this->FACET_SIZES;
  my $cubical=1;
  foreach (@facet_sizes) {
    if ($_ != 8) {
      $cubical=0;
      last;
    }
  }
  $this->CUBICAL=$cubical;

CUBICALITY : DIM
PRECONDITION: EVEN
   !$this->EVEN
WEIGHT 0.10
   $this->CUBICALITY= $this->DIM>0;

CUBICAL : CUBICALITY, DIM
WEIGHT 0.10
   $this->CUBICAL= $this->CUBICALITY >= $this->DIM-1;

COCUBICALITY : F2_VECTOR
PRECONDITION: DUAL_EVEN
   $this->DUAL_EVEN
BODY:
# a polytope is k-cocubical if its dual is k-cubical
# f_{d-1-j,d-1} = 2^j * f_j for all j<=k
    my $k=1;
    my $k2=2; # 2^k
    my $dim=@{$this->F2_VECTOR};
    my ($n_facets) = $this->F2_VECTOR->[-1] =~ /(\d+)$/;
    while ($k<$dim-1) {
       my @f= $this->F2_VECTOR->[$dim-1-($k+1)] =~ /\d+/g;
       $k2*=2;
       last if $f[$dim-1] != $k2 * $f[$dim-1-($k+1)];
       ++$k;
    }
    if (($k==$dim-1) && ($n_facets==2*$k2)) { ++$k; } # it's a cross polytope
    $this->COCUBICALITY=$k;

COCUBICALITY : DIM
PRECONDITION: DUAL_EVEN
   !$this->DUAL_EVEN
WEIGHT 0.10
   $this->COCUBICALITY= $this->DIM>0;

COCUBICAL : COCUBICALITY, DIM
WEIGHT 0.10
   $this->COCUBICAL= $this->COCUBICALITY >= $this->DIM-1;

NEIGHBORLINESS : F_VECTOR, N_VERTICES
# a polytope is k-neighborly if any k vertices form a face (which is necessarily simplicial)
# i.e. f_{k-1} = binomial(n,k), where n = N_VERTICES
   my $k=0;
   foreach my $f ($this->F_VECTOR =~ /\d+/g) {
      if ($f == binomial($this->N_VERTICES, $k+1)) {
	 $k++;
      } else {
	 last;
      }
   }
   $this->NEIGHBORLINESS=$k;

BALANCE : F_VECTOR, N_FACETS
# dual notion to neighborliness
# i.e. f_{n-k} = binomial(n,k), where n = N_FACETS
   my $k=0;
   foreach my $f (reverse($this->F_VECTOR =~ /\d+/g)) {
      if ($f == binomial($this->N_FACETS, $k+1)) {
	 $k++;
      } else {
	 last;
      }
   }
   $this->BALANCE=$k;

SIMPLICIAL : SIMPLICIALITY, DIM
WEIGHT 0.10
   $this->SIMPLICIAL= $this->SIMPLICIALITY >= $this->DIM-1;

SIMPLE : SIMPLICITY, DIM
WEIGHT 0.10
   $this->SIMPLE= $this->SIMPLICITY >= $this->DIM-1;

NEIGHBORLY : NEIGHBORLINESS, DIM
WEIGHT 0.10
   $this->NEIGHBORLY= $this->NEIGHBORLINESS >= $this->DIM/2;

BALANCED : BALANCE, DIM
WEIGHT 0.10
   $this->BALANCED= $this->BALANCE >= $this->DIM/2;

FATNESS : F_VECTOR
PRECONDITION: DIM
   $this->DIM == 4;
BODY:
   my @F_VECTOR = ($this->F_VECTOR =~ /\d+/g);
   $this->FATNESS = ($F_VECTOR[1]+$F_VECTOR[2]-20)/($F_VECTOR[0]+$F_VECTOR[3]-10)

COMPLEXITY : F_VECTOR, F2_VECTOR
PRECONDITION: DIM
   $this->DIM == 4;
BODY:
   my @F_VECTOR = ($this->F_VECTOR =~ /\d+/g);
   my @F2_0 = ($this->F2_VECTOR->[0] =~ /\d+/g);
   $this->COMPLEXITY = ($F_VECTOR[0]+$F_VECTOR[3]-10)/($F2_0[3]-20)

TWO_FACE_SIZES : HASSE_DIAGRAM
  client("2-face-sizes", $polyname, "TWO_FACE_SIZES","-primal");

TWO_FACE_SIZES : GRAPH, VERTICES_IN_FACETS
PRECONDITION: SIMPLE
  $this->SIMPLE;
BODY:
  client("2-face-sizes-simple", $polyname, "-primal");

SUBRIDGE_SIZES : HASSE_DIAGRAM
  client("2-face-sizes", $polyname, "SUBRIDGE_SIZES", "-dual");

DIM : VERTICES_IN_FACETS
WEIGHT 3.10
   client("dim_from_incidence", $this);

GRAPH : VERTICES_IN_FACETS
WEIGHT 3.10
   client("graph_from_incidence", $this, "VERTICES_IN_FACETS", "-primal");

DUAL_GRAPH : VERTICES_IN_FACETS
WEIGHT 3.10
   client("graph_from_incidence", $this, "VERTICES_IN_FACETS", "-dual");

# category: Combinatorics
# Dump the face lattice to the standard output.
# The output is ordered by dimension. Each row starts with [ `-k` : `f_{d-k}` ],
# where `k` is the co-dimension, and `f_{d-k}` the number of faces
# (as in @see F_VECTOR.) The faces are represented as lists of vertex indices.
# They appear lexicographically sorted.

user_method FACE_LATTICE() {
   client("face_lattice", shift, "-primal");
   return ();
}

# category: Combinatorics
# Dual to @see FACE_LATTICE. The dual faces are represented
# as lists of facet indices

user_method DUAL_FACE_LATTICE() {
   client("face_lattice", shift, "-dual");
   return ();
}

HASSE_DIAGRAM : VERTICES_IN_FACETS
WEIGHT 4.10
   client("hasse_diagram", $this, "VERTICES_IN_FACETS");

DIM : HASSE_DIAGRAM
WEIGHT 1.10
   my @l=split /\s+/, $this->HASSE_DIAGRAM->[0];
   $this->DIM=$#l;

GRAPH : HASSE_DIAGRAM
   client("graph_from_face_lattice", $this, "-primal");

DUAL_GRAPH : HASSE_DIAGRAM
   client("graph_from_face_lattice", $this, "-dual");

DIAMETER : GRAPH
   client("diameter", $this, "GRAPH", "DIAMETER");

DUAL_DIAMETER : DUAL_GRAPH
   client("diameter", $this, "DUAL_GRAPH", "DUAL_DIAMETER");

VERTEX_DEGREES : GRAPH
WEIGHT 1.10
   $this->VERTEX_DEGREES=join(" ", row_sizes($this->GRAPH));

FACET_DEGREES : DUAL_GRAPH
WEIGHT 1.10
   $this->FACET_DEGREES=join(" ", row_sizes($this->DUAL_GRAPH));

VERTEX_SIZES : VERTICES_IN_FACETS
WEIGHT 1.10
   $this->VERTEX_SIZES=join(" ", col_sizes($this->VERTICES_IN_FACETS));

FACET_SIZES : VERTICES_IN_FACETS
WEIGHT 1.10
   $this->FACET_SIZES=join(" ", row_sizes($this->VERTICES_IN_FACETS));

BOUNDED : VERTICES | POINTS
WEIGHT 1.10
   foreach (@{$this->VERTICES | POINTS}) {
      # due to canonicalization the first element is always 0 or 1
      /\d+/;
      if ($& != 1) {
	 $this->BOUNDED=0;
	 return;
      }
   }
   $this->BOUNDED=1;

BOUNDED : FAR_FACE
WEIGHT 0.10
   $this->BOUNDED= $this->FAR_FACE !~ /\d/;

FAR_FACE : VERTICES
WEIGHT 1.10
   #client("far_face", $this);
   my $i=0;
   my @far;
   foreach (@{$this->VERTICES}) {
      push @far, $i if /^0/;
      ++$i;
   }
   $this->FAR_FACE="{@far}";

UNBOUNDED_FACETS : VERTICES_IN_FACETS, FAR_FACE
   client("does_contain", $this, "UNBOUNDED_FACETS", "VERTICES_IN_FACETS", "FAR_FACE");

BOUNDED_GRAPH : GRAPH, FAR_FACE
   client("induced_subgraph", $this, "GRAPH", "FAR_FACE", "BOUNDED_GRAPH", "-compl");

EDGE_COLORED_BOUNDED_GRAPH : HASSE_DIAGRAM, FAR_FACE
WEIGHT 4.20
# there is a rule for tight spans with the same signature which is faster
  client("edge_colored_bounded_graph", $this, "EDGE_COLORED_BOUNDED_GRAPH", "HASSE_DIAGRAM", "FAR_FACE")

SPLITS : VERTICES, FACETS, DIM
   client("splits", $this);

CENTERED : FACETS, AFFINE_HULL
WEIGHT 1.10
   foreach (@{$this->FACETS}) {
      no integer;
      m'^\s*([-+\d.eE]+)(?:\s|/)';
      if ($1 <= 0) {
	 $this->CENTERED=0;
	 return;
      }
   }
   foreach (@{$this->AFFINE_HULL}) {
      no integer;
      m'^\s*([-+\d.eE]+)(?:\s|/)';
      if ($1 != 0) {
	 $this->CENTERED=0;
	 return;
      }
   }
   $this->CENTERED=1;

POSITIVE : VERTICES | POINTS
WEIGHT 1.10
   foreach (@{$this->VERTICES | POINTS}) {
      if (/(?:^|\s)-[0.]*[1-9]/) {
	 $this->POSITIVE=0;
	 return;
      }
   }
   $this->POSITIVE=1;

POINTS : ZONOTOPE_INPUT_VECTORS
WEIGHT 5.10
   client("zonotope", $this)

ALTSHULER_DET : VERTICES_IN_FACETS
   client("altshuler_det", $this)

TRIANGULATION_BOUNDARY : TRIANGULATION, VERTICES_IN_FACETS
   client("triang_boundary", $this);

TRIANGULATION_BOUNDARY : VERTICES_IN_FACETS
PRECONDITION: SIMPLICIAL
   $this->SIMPLICIAL
WEIGHT 1.10
   # add the extra set of { }
   $this->TRIANGULATION_BOUNDARY=[ map { /\{.*\}/; "{$&}\n" } @{$this->VERTICES_IN_FACETS} ];

#MINIMAL_NON_FACES : ESSENTIALLY_GENERIC, TRIANGULATION
#   client("non_faces", $this);

# helper clients for various visualization tasks

VIF_CYCLIC_NORMAL, NEIGHBOR_FACETS_CYCLIC_NORMAL : DIM, VERTICES, VERTICES_IN_FACETS, DUAL_GRAPH
PRECONDITION: BOUNDED
   $this->BOUNDED
BODY:
   client("neighbors_cyclic_normal", $this, "-primal");

FTV_CYCLIC_NORMAL, NEIGHBOR_VERTICES_CYCLIC_NORMAL : DIM, FACETS, VERTICES_IN_FACETS, GRAPH
PRECONDITION: CENTERED
   $this->CENTERED
BODY:
   client("neighbors_cyclic_normal", $this, "-dual")

TRIANGULATION_SIGNS : TRIANGULATION, VERTICES
   client("triang_sign", $this, "TRIANGULATION", "VERTICES", "TRIANGULATION_SIGNS");

TRIANGULATION_INT_SIGNS : TRIANGULATION_INT, POINTS
   client("triang_sign", $this, "TRIANGULATION_INT", "POINTS", "TRIANGULATION_INT_SIGNS");


# clients capable of handling different coordinate types

DIM : VERTICES | POINTS
   client("dimension", $this, "-primal", "DIM");

POINTED : AMBIENT_DIM, FACETS | INEQUALITIES
   my $d=[ ];	# a scratch section
   client("dimension", $this, "-dual", $d);
   $this->POINTED= $this->AMBIENT_DIM == $d->[0];

AFFINE_HULL : VERTICES | POINTS
   client("nullspace", $this, "VERTICES | POINTS", "AFFINE_HULL");

VERTICES_IN_FACETS : VERTICES, FACETS
   client("incidence", $this, "FACETS", "VERTICES", "VERTICES_IN_FACETS");

POINTS_IN_FACETS : POINTS, FACETS
   client("incidence", $this, "FACETS", "POINTS", "POINTS_IN_FACETS");

VERTICES_IN_INEQUALITIES : INEQUALITIES, VERTICES
   client("incidence", $this, "INEQUALITIES", "VERTICES", "VERTICES_IN_INEQUALITIES");

VERTICES_IN_FACETS, VERTICES : POINTS_IN_FACETS, POINTS
   client("compress_incidence", $this, "-primal");
   $this->remove("POINTS_IN_FACETS");

VERTICES_IN_FACETS, FACETS, AFFINE_HULL : VERTICES_IN_INEQUALITIES, INEQUALITIES, FAR_FACE
   client("compress_incidence", $this, "-dual");
   $this->remove("VERTICES_IN_INEQUALITIES");

FACETS, AFFINE_HULL : VERTICES, VERTICES_IN_FACETS
   client("facets_from_incidence", $this, "-primal");

VERTICES : FACETS, AFFINE_HULL, VERTICES_IN_FACETS
   client("facets_from_incidence", $this, "-dual");

VERTEX_BARYCENTER : VERTICES
PRECONDITION: BOUNDED
   $this->BOUNDED
WEIGHT 1.10
   client("vertex_barycenter", $this);

MINIMAL_VERTEX_ANGLE : VERTICES, VERTEX_BARYCENTER
   client("minimal_vertex_angle", $this);
   

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