# 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: