#  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 SubdivisionOfVectors {

file_suffix sov

# @category Geometry
# The vectors of the subdivision, 
property VECTORS : Matrix<Scalar> {

  method canonical { 
      my ($this,$M)=@_;
      if ($this->isa("SubdivisionOfPoints")) {
         polytope::canonicalize_point_configuration($M);
      }
  }
}

# permuting [[VECTORS]]
permutation VectorPerm : PermBase;

rule VectorPerm.PERMUTATION : VectorPerm.VECTORS, VECTORS {
   $this->VectorPerm->PERMUTATION = find_matrix_row_permutation($this->VectorPerm->VECTORS, $this->VECTORS)
      // die "no permutation";
}

rule VECTORS : VectorPerm.VECTORS, VectorPerm.PERMUTATION {
   $this->VECTORS = permuted($this->VectorPerm->VECTORS, $this->VectorPerm->PERMUTATION);
}
weight 1.10;



# @category Geometry
# Dimension of the space in which the vector configuration lives.
property VECTOR_AMBIENT_DIM : Int;


# @category Geometry
# Dimension of the linear hull of the vector configuration.
property VECTOR_DIM : Int;


# @category Geometry
# [[AMBIENT_DIM]] and [[DIM]] coincide.
property FULL_DIM : Bool;


# @category Geometry
# Number of [[VECTORS]].
property N_VECTORS : Int;


# @category Geometry
# Dual basis of the linear hull of the vector configuration
property LINEAR_SPAN : Matrix<Scalar>;

# @category Visualization
# Unique names assigned to the [[VECTORS]].
# If specified, they are shown by visualization tools instead of point indices.
property LABELS : Array<String> : mutable;

rule LABELS : VectorPerm.LABELS, VectorPerm.PERMUTATION {
   $this->LABELS=permuted($this->VectorPerm->LABELS, $this->VectorPerm->PERMUTATION);
}
weight 1.10;

# @category Combinatorics
# Maximal cells of the polyhedral complex.
# Indices refer to [[VECTORS]]. Points do not have to be vertices of the cells.
property MAXIMAL_CELLS : IncidenceMatrix;

# @category Combinatorics
# The number of [[MAXIMAL_CELLS]]
property N_MAXIMAL_CELLS : Int;

rule MAXIMAL_CELLS : VectorPerm.MAXIMAL_CELLS, VectorPerm.PERMUTATION {
   $this->MAXIMAL_CELLS=permuted_cols($this->VectorPerm->MAXIMAL_CELLS, $this->VectorPerm->PERMUTATION);
}
weight 1.10;

# permuting [[MAXIMAL_CELLS]]
permutation CellPerm : PermBase;

rule CellPerm.PERMUTATION : CellPerm.MAXIMAL_CELLS, MAXIMAL_CELLS {
   $this->CellPerm->PERMUTATION = find_permutation(rows($this->CellPerm->MAXIMAL_CELLS), rows($this->MAXIMAL_CELLS))
      // die "no permutation";
}

rule MAXIMAL_CELLS : CellPerm.MAXIMAL_CELLS, CellPerm.PERMUTATION {
   $this->MAXIMAL_CELLS = permuted_rows($this->CellPerm->MAXIMAL_CELLS, $this->CellPerm->PERMUTATION);
}
weight 1.10;


# If M is incidence matrix between the vertices and the [[MAXIMAL_CELLS]],
# then the Altshuler determinant is defined as
# max{det(M ∗ M<sup>T</sup>), det(M<sup>T</sup> ∗ M)}.
property ALTSHULER_DET : Integer;

rule ALTSHULER_DET : MAXIMAL_CELLS {
   $this->ALTSHULER_DET=altshuler_det($this->MAXIMAL_CELLS);
}

# @category Geometry
# True if [[VECTORS]] for each maximal cell are in convex position.
property CONVEX : Bool;

# @category Geometry
# Minimal nonnegative lattice vector in secondary cone of the subdivision given by [[MAXIMAL_CELLS]].
property MIN_WEIGHTS : Vector<Int>; 

# @category Geometry
# Returns the //i//-th cell of the complex as a [[VectorConfiguration]]
# @param Int i 
# @return VectorConfiguration
user_method cell($) : MAXIMAL_CELLS, VECTORS {
   my ($self, $i) = @_;
   return new VectorConfiguration<Scalar>(VECTORS=>$self->VECTORS->minor($self->MAXIMAL_CELLS->[$i],All));
}



}

object SubdivisionOfPoints {

file_suffix sop

# @category Geometry
# The points of the configuration.  Multiples allowed.
property POINTS = override VECTORS;

# @category Geometry
# The number of [[POINTS]] in the configuration.
property N_POINTS = override N_VECTORS;

# @category Geometry
# Affine dimension of the point configuration.
# Similar to [[PointConfiguration::DIM]].
user_method DIM() : VECTOR_DIM {
   return $_[0]->VECTOR_DIM-1;
}

# @category Geometry
# Ambient dimension of the point configuration (without the homogenization coordinate).
# Similar to [[PointConfiguration::AMBIENT_DIM]].
user_method AMBIENT_DIM() : VECTOR_AMBIENT_DIM {
   return $_[0]->VECTOR_AMBIENT_DIM-1;
}

# @category Visualization
# Unique names assigned to the [[POINTS]].
# If specified, they are shown by visualization tools instead of point indices.
property POINT_LABELS = override LABELS;

# @category Geometry
# Vector assigning a weight to each point to get a regular subdivision.
property WEIGHTS : Vector<Scalar>;

rule WEIGHTS : VectorPerm.WEIGHTS, VectorPerm.PERMUTATION {
   $this->WEIGHTS=permuted($this->VectorPerm->WEIGHTS, $this->VectorPerm->PERMUTATION);
}
weight 1.10;

# @category Geometry
# Whether the subdivision is regular, i.e. induced by a weight vector.
property REGULAR : Bool;

# @category Geometry
# A subdivision is unimodular if it is a triangulation such that each maximal simplex has unit normalized volume.
# @example Unit square, triangulated.
# > $S = new SubdivisionOfPoints(POINTS=>cube(2,0)->VERTICES, WEIGHTS=>[0,0,0,1]);
# > print $S->UNIMODULAR
# | true
# @example Unit 3-cube, triangulation induced by four compatible vertex splits.
# > $S = new SubdivisionOfPoints(POINTS=>cube(3,0)->VERTICES, WEIGHTS=>[0,1,1,0,1,0,1,0]);
# > print $S->UNIMODULAR
# | false
property UNIMODULAR : Bool;

# @category Geometry
# The polyhedral complex induced by the cells of the subdivision.
property POLYHEDRAL_COMPLEX : PolyhedralComplex<Scalar>;

# @category Geometry
# Returns the //i//-th cell of the complex as a [[PointConfiguration]]
# @param Int i
# @return PointConfiguration
user_method cell($) : MAXIMAL_CELLS, POINTS {
   my ($self, $i) = @_;
   return new PointConfiguration<Scalar>(POINTS=>$self->POINTS->minor($self->MAXIMAL_CELLS->[$i],All));
}

# @category Geometry
# The tight span of the subdivision.
property TIGHT_SPAN : PolyhedralComplex<Scalar>;

}


object polytope::Polytope {

# @category Triangulation and volume
# Polytopal Subdivision of the polytope using only its vertices.
property POLYTOPAL_SUBDIVISION : SubdivisionOfPoints<Scalar> : multiple{

# @category Combinatorics
# The splits that are coarsenings of the subdivision.
# If the subdivision is regular these form the unique split decomposition of
# the corresponding weight function.
property REFINED_SPLITS : Set<Int>;

}


rule POLYTOPAL_SUBDIVISION.MAXIMAL_CELLS : VertexPerm.POLYTOPAL_SUBDIVISION.MAXIMAL_CELLS, VertexPerm.PERMUTATION {
   $this->POLYTOPAL_SUBDIVISION->MAXIMAL_CELLS=permuted_cols($this->VertexPerm->POLYTOPAL_SUBDIVISION->MAXIMAL_CELLS, $this->VertexPerm->PERMUTATION);
}
weight 1.20;

}



object polytope::PointConfiguration {

# @category Triangulation and volume
#Polytopal Subdivision of the point configuration
property POLYTOPAL_SUBDIVISION : SubdivisionOfPoints<Scalar> : multiple{

# @category Combinatorics
# The splits that are coarsenings of the subdivision.
# If the subdivision is regular these form the unique split decomposition of
# the corresponding weight function.
property REFINED_SPLITS : Set<Int>;

}

}

# Local Variables:
# mode: perl
# cperl-indent-level:3
# indent-tabs-mode:nil
# End:
