#  Copyright (c) 1997-2015
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
#  http://www.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 polytope::Polytope {


# @category Unbounded polyhedra
# Bounded subcomplex.
# Defined as the bounded cells of the boundary of the pointed part of the polytope. 
# Therefore it only depends on [[VERTICES_IN_FACETS]] and [[FAR_FACE]].
property BOUNDED_COMPLEX : PolyhedralComplex {


  property GRAPH {

    # Each edge indicates the maximal dimension of a bounded
    # face containing it.  Mainly used for visualization purposes.

    property EDGE_COLORS : EdgeMap<Undirected,Int> : construct(ADJACENCY);

    # Difference of the vertices for each edge (only defined up to signs).
    property EDGE_DIRECTIONS : EdgeMap<Undirected,Vector<Scalar>> : construct(ADJACENCY);
 
    # The length of each edge measured in the maximum metric.
    property EDGE_LENGTHS : EdgeMap<Undirected,Scalar> : construct(ADJACENCY);

    # Sum of all [[EDGE_LENGTHS]].
    property TOTAL_LENGTH : Scalar;
  }

}



rule BOUNDED_COMPLEX.GRAPH.NodePerm.PERMUTATION = VertexPerm.PERMUTATION;

rule BOUNDED_COMPLEX.GRAPH.ADJACENCY : GRAPH.ADJACENCY, FAR_FACE, BOUNDED {
   $this->BOUNDED_COMPLEX->GRAPH->ADJACENCY= $this->BOUNDED ? $this->GRAPH->ADJACENCY : induced_subgraph($this->GRAPH->ADJACENCY, ~ $this->FAR_FACE);
}
weight 1.20;

# there is a rule for tight spans with the same signature which is faster
rule BOUNDED_COMPLEX.GRAPH.EDGE_COLORS : BOUNDED_COMPLEX.GRAPH.ADJACENCY, HASSE_DIAGRAM, FAR_FACE {
   polytope::edge_colored_bounded_graph($this->BOUNDED_COMPLEX->GRAPH,$this->HASSE_DIAGRAM, $this->FAR_FACE)
}
weight 4.20;

rule BOUNDED_COMPLEX.GRAPH.EDGE_DIRECTIONS : BOUNDED_COMPLEX.GRAPH.ADJACENCY, VERTICES {
   $this->BOUNDED_COMPLEX->GRAPH->EDGE_DIRECTIONS = edge_directions($this->BOUNDED_COMPLEX->GRAPH,$this->VERTICES);
}

rule BOUNDED_COMPLEX.GRAPH.EDGE_LENGTHS : BOUNDED_COMPLEX.GRAPH.EDGE_DIRECTIONS {
   $this->BOUNDED_COMPLEX->GRAPH->EDGE_LENGTHS=[ map {
      my $max=0;
      assign_max($max, abs($_)) for @$_;
      $max
   } @{$this->BOUNDED_COMPLEX->GRAPH->EDGE_DIRECTIONS} ];
}
weight 3.10;

rule BOUNDED_COMPLEX.GRAPH.TOTAL_LENGTH : BOUNDED_COMPLEX.GRAPH.EDGE_LENGTHS {
   my $l=0;
   foreach (@{$this->BOUNDED_COMPLEX->GRAPH->EDGE_LENGTHS}) {
      $l+=$_;
   }
   $this->BOUNDED_COMPLEX->GRAPH->TOTAL_LENGTH=$l;
}
weight 2.10;


rule BOUNDED_COMPLEX.DUAL_GRAPH.NodePerm.PERMUTATION = FacetPerm.PERMUTATION;

rule BOUNDED_COMPLEX.DUAL_GRAPH.ADJACENCY : DUAL_GRAPH.ADJACENCY, UNBOUNDED_FACETS, BOUNDED {
   $this->BOUNDED_COMPLEX->DUAL_GRAPH->ADJACENCY= $this->BOUNDED ? $this->DUAL_GRAPH->ADJACENCY : induced_subgraph($this->DUAL_GRAPH->ADJACENCY, ~ $this->UNBOUNDED_FACETS);
}
weight 1.20;


rule BOUNDED_COMPLEX.DUAL_GRAPH.NODE_LABELS = FACET_LABELS;


rule BOUNDED_COMPLEX.GRAPH.NODE_LABELS = VERTEX_LABELS;


# FIXME:
#$apply_diff{VERTICES}=
#$apply_diff{FACETS}=

rule BOUNDED_COMPLEX.HASSE_DIAGRAM : VERTICES_IN_FACETS, FAR_FACE {
   $this->BOUNDED_COMPLEX->HASSE_DIAGRAM=bounded_hasse_diagram($this->VERTICES_IN_FACETS, $this->FAR_FACE);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };
weight 6.20;



rule BOUNDED_COMPLEX.MAXIMAL_POLYTOPES : VERTICES_IN_FACETS, FAR_FACE {
   $this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES=bounded_complex($this->VERTICES_IN_FACETS, $this->FAR_FACE);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };
weight 6.10;

rule BOUNDED_COMPLEX.MAXIMAL_POLYTOPES : HASSE_DIAGRAM, FAR_FACE {
   $this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES=bounded_complex($this->HASSE_DIAGRAM, $this->FAR_FACE);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };

rule BOUNDED_COMPLEX.MAXIMAL_POLYTOPES : BOUNDED_COMPLEX.HASSE_DIAGRAM {
   $this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES(temporary)=bounded_complex($this->BOUNDED_COMPLEX->HASSE_DIAGRAM);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };
weight 1.10;

rule BOUNDED_COMPLEX.MAXIMAL_POLYTOPES = VERTICES_IN_FACETS;
precondition : FAR_FACE { $this->FAR_FACE->size()==0 };

rule BOUNDED_COMPLEX.COMBINATORIAL_DIM : BOUNDED_COMPLEX.HASSE_DIAGRAM {
   $this->BOUNDED_COMPLEX->COMBINATORIAL_DIM=$this->BOUNDED_COMPLEX->HASSE_DIAGRAM->dim;
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };
weight 0.1;

rule BOUNDED_COMPLEX.VERTICES : VERTICES, FAR_FACE, N_VERTICES {
   $this->BOUNDED_COMPLEX->VERTICES=$this->VERTICES->minor(~($this->FAR_FACE),All);
}
precondition : POINTED;
weight 0.20;

rule BOUNDED_COMPLEX.BOUNDED : {
  $this->BOUNDED_COMPLEX->BOUNDED=1;
}
weight 0.1;

rule BOUNDED_COMPLEX.N_VERTICES = N_BOUNDED_VERTICES;

rule BOUNDED_COMPLEX.FAN_AMBIENT_DIM = CONE_AMBIENT_DIM;

rule BOUNDED_COMPLEX.F_VECTOR : BOUNDED_COMPLEX.HASSE_DIAGRAM, BOUNDED_COMPLEX.COMBINATORIAL_DIM {
   $this->BOUNDED_COMPLEX->F_VECTOR=[ map { scalar( @{$this->BOUNDED_COMPLEX->HASSE_DIAGRAM->nodes_of_dim($_)} ) } 0..$this->BOUNDED_COMPLEX->COMBINATORIAL_DIM ];
}


# @category Unbounded polyhedra
# Graph of the bounded subcomplex.
user_method BOUNDED_GRAPH = BOUNDED_COMPLEX.GRAPH;

# @category Unbounded polyhedra
# Dual graph of the bounded subcomplex.
user_method BOUNDED_DUAL_GRAPH = BOUNDED_COMPLEX.DUAL_GRAPH;

# @category Unbounded polyhedra
# [[HASSE_DIAGRAM]] constrained to affine vertices
# Nodes representing the maximal inclusion-independent faces are connected to the top-node
# regardless of their dimension
user_method BOUNDED_HASSE_DIAGRAM = BOUNDED_COMPLEX.HASSE_DIAGRAM;

}

# FIXME: #195, #479
# the rule below is taken out for release 2.12 since it is too difficult for the scheduler
# 
#object polytope::Polytope<Rational> {
# 
#rule VERTICES, BOUNDED, FAR_FACE, BOUNDED_COMPLEX.GRAPH.ADJACENCY, LINEALITY_SPACE : ONE_VERTEX, FACETS | INEQUALITIES {
#    reverse_search_graph($this,$this->ONE_VERTEX);
 #}
 #precondition : SIMPLE_POLYHEDRON;
 #precondition : POINTED;
 #weight 4.20;
 #permutation : VertexPerm;
 #
 #}


object polytope::TightSpan{

rule BOUNDED_COMPLEX.GRAPH.EDGE_COLORS : BOUNDED_COMPLEX.GRAPH.ADJACENCY, HASSE_DIAGRAM, FAR_FACE, COMBINATORIAL_DIM {
   edge_colored_bounded_graph($this->BOUNDED_COMPLEX->GRAPH,$this->HASSE_DIAGRAM, $this->FAR_FACE, $this->COMBINATORIAL_DIM/2)
}
weight 4.10;

}

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