#  Copyright (c) 1997-2016
#  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<Scalar> {

	# For every row of [[VERTICES]] this indicates the corresponding row in the
	# [[VERTICES]] of the parent polytope.
	property VERTEX_MAP : Array<Int>;

  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, BOUNDED_COMPLEX.VERTEX_MAP, N_VERTICES {
   $this->BOUNDED_COMPLEX->GRAPH->ADJACENCY= $this->BOUNDED ? $this->GRAPH->ADJACENCY :
		permuted_inv_nodes( new props::Graph(induced_subgraph($this->GRAPH->ADJACENCY, ~ $this->FAR_FACE)), map_vertices_down($this->BOUNDED_COMPLEX->VERTEX_MAP, $this->N_VERTICES) );
}
weight 1.20;

rule BOUNDED_COMPLEX.GRAPH.EDGE_COLORS : BOUNDED_COMPLEX.MAXIMAL_POLYTOPES_COMBINATORIAL_DIMS, BOUNDED_COMPLEX.MAXIMAL_POLYTOPES, BOUNDED_COMPLEX.GRAPH.ADJACENCY, BOUNDED_COMPLEX.GRAPH.N_EDGES {
	polytope::edge_colored_bounded_graph($this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES_COMBINATORIAL_DIMS,
													 $this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES,
													 $this->BOUNDED_COMPLEX->GRAPH);
}
weight 4.20;

rule BOUNDED_COMPLEX.GRAPH.EDGE_DIRECTIONS : BOUNDED_COMPLEX.GRAPH.ADJACENCY, BOUNDED_COMPLEX.VERTICES {
   $this->BOUNDED_COMPLEX->GRAPH->EDGE_DIRECTIONS = edge_directions($this->BOUNDED_COMPLEX->GRAPH,$this->BOUNDED_COMPLEX->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.NODE_LABELS = FACET_LABELS;


rule BOUNDED_COMPLEX.GRAPH.NODE_LABELS = VERTEX_LABELS;


rule BOUNDED_COMPLEX.HASSE_DIAGRAM.ADJACENCY, BOUNDED_COMPLEX.HASSE_DIAGRAM.DECORATION, BOUNDED_COMPLEX.HASSE_DIAGRAM.INVERSE_RANK_MAP, \
     BOUNDED_COMPLEX.HASSE_DIAGRAM.TOP_NODE, BOUNDED_COMPLEX.HASSE_DIAGRAM.BOTTOM_NODE : \
     VERTICES_IN_FACETS, FAR_FACE, BOUNDED_COMPLEX.VERTEX_MAP {
   $this->BOUNDED_COMPLEX->HASSE_DIAGRAM=relabeled_bounded_hasse_diagram($this->VERTICES_IN_FACETS, $this->FAR_FACE, $this->BOUNDED_COMPLEX->VERTEX_MAP);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };
weight 6.20;

rule BOUNDED_COMPLEX.MAXIMAL_POLYTOPES : HASSE_DIAGRAM.ADJACENCY, HASSE_DIAGRAM.DECORATION, HASSE_DIAGRAM.INVERSE_RANK_MAP, HASSE_DIAGRAM.TOP_NODE, HASSE_DIAGRAM.BOTTOM_NODE, FAR_FACE, BOUNDED_COMPLEX.VERTEX_MAP, N_VERTICES {
   $this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES=bounded_complex($this->HASSE_DIAGRAM, $this->FAR_FACE, $this->BOUNDED_COMPLEX->VERTEX_MAP, $this->N_VERTICES);
}
precondition : FAR_FACE { $this->FAR_FACE->size()>0 };

rule BOUNDED_COMPLEX.VERTICES, BOUNDED_COMPLEX.MAXIMAL_POLYTOPES, BOUNDED_COMPLEX.VERTEX_MAP : VERTICES, VERTICES_IN_FACETS {
	$this->BOUNDED_COMPLEX->MAXIMAL_POLYTOPES = $this->VERTICES_IN_FACETS;
	$this->BOUNDED_COMPLEX->VERTICES = $this->VERTICES;
	$this->BOUNDED_COMPLEX->VERTEX_MAP = new Array<Int>(sequence(0,$this->VERTICES->rows()));
}
precondition : FAR_FACE { $this->FAR_FACE->size()==0 };
weight 0.10;

rule BOUNDED_COMPLEX.VERTICES, BOUNDED_COMPLEX.VERTEX_MAP : VERTICES, FAR_FACE, N_VERTICES {
   $this->BOUNDED_COMPLEX->VERTICES=$this->VERTICES->minor(~($this->FAR_FACE),All);
	$this->BOUNDED_COMPLEX->VERTEX_MAP = new Array<Int>(sequence(0, $this->VERTICES->rows()) - $this->FAR_FACE);
}
precondition : POINTED;
weight 0.20;

rule BOUNDED_COMPLEX.VERTEX_MAP : BOUNDED_COMPLEX.VERTICES, VERTICES, FAR_FACE {
	$this->BOUNDED_COMPLEX->VERTEX_MAP = find_bounded_mapping($this->BOUNDED_COMPLEX->VERTICES, $this->VERTICES, $this->FAR_FACE);
}
weight 2.1;

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;

# @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;

}

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