#  Copyright (c) 1997-2015
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitae 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.
#-------------------------------------------------------------------------------

# @category Topology
#
# A group is encoded as a sequence ( { (t<sub>1</sub> m<sub>1</sub>) ...  (t<sub>n</sub>  m<sub>n</sub>) } f) of non-negative integers,
# with t<sub>1</sub> > t<sub>2</sub> > ... > t<sub>n</sub> > 1, plus an extra non-negative integer f.
#
# The group is isomorphic to (Z/t<sub>1</sub>)<sup>m<sub>1</sub></sup> &times; ... &times; (Z/t<sub>n</sub>)<sup>m<sub>n</sub></sup> &times; Z<sup>f</sup>, 
# where Z<sup>0</sup> is the trivial group.
#
# Access methods: //torsion// delivers the list of Z-groups, //betti_number// the number f.
#
declare property_type HomologyGroup<Scalar> : c++ (include => "polymake/topaz/ChainComplex.h");

# @category Topology
#
# A group is encoded as a pair of an integer matrix and a vector of faces.
# The elements of the group can be obtained by symbolic multiplication of both.
#
# Access methods: //coeff// delivers the integer matrix, //faces// the vector of faces.
#
# @tparam Scalar integer type of matrix elements

declare property_type CycleGroup<Scalar> : c++ (include => "polymake/topaz/ChainComplex.h");

# @category Topology
# TODO: explain the meaning of the fields: parity, positive, negative
declare property_type IntersectionForm : c++ (include => "polymake/topaz/IntersectionForm.h");

object SimplicialComplex {

declare permutation VertexPerm {

   # Transforming vertices from this into basic object.
   property PERMUTATION : Array<Int>;
}

# @category Input property
# Any description of the faces of a simplicial complex with vertices v_0 < v_1 < v_2 < ... arbitrary.  Redundant faces allowed.

property INPUT_FACES : Array<Set>;

# @category Combinatorics
# Indices of the vertices from [[INPUT_FACES]].  That is, the map i \mapsto v_i.

property VERTEX_INDICES : Array<Int>;

# @category Visualization
# Labels of the vertices.

property VERTEX_LABELS : Array<String>;

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

# @category Combinatorics
# Find the vertices by given labels.
# @param String label ... vertex labels
# @return Set<Int> vertex indices

user_method labeled_vertices {
   my $this=shift;
   if (defined (my $labels=$this->lookup("VERTEX_LABELS"))) {
      new Set([ find_labels($labels, @_) ]);
   } else {
      die "No VERTEX_LABELS stored in this complex";
   }
}

# @category Combinatorics
# Number of vertices.

property N_VERTICES : Int;


# @category Combinatorics
# Faces which are maximal with respect to inclusion, encoded as their ordered set of vertices.
# The vertices must be numbered 0, ..., n-1.

property FACETS : Array<Set>;

rule FACETS : VertexPerm.FACETS, VertexPerm.PERMUTATION {
   $this->FACETS=permuted_elements($this->VertexPerm->FACETS, $this->VertexPerm->PERMUTATION);
}
weight 1.20;

declare permutation FacetPerm {

   # Transforming [[FACETS]] from this into basic object
   property PERMUTATION : Array<Int>;
}

rule FacetPerm.PERMUTATION : FacetPerm.FACETS, FACETS {
   $this->FacetPerm->PERMUTATION=find_permutation($this->FacetPerm->FACETS, $this->FACETS);
}

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

# @category Combinatorics
# Number of [[FACETS]].

property N_FACETS : Int;


# @category Combinatorics
# Inclusion minimal non-faces (vertex subsets which are not faces of the simplicial complex).

property MINIMAL_NON_FACES : Array<Set>;

rule MINIMAL_NON_FACES : VertexPerm.MINIMAL_NON_FACES, VertexPerm.PERMUTATION {
   $this->MINIMAL_NON_FACES=permuted_elements($this->VertexPerm->MINIMAL_NON_FACES, $this->VertexPerm->PERMUTATION);
}
weight 1.20;


# @category Combinatorics
# Number of [[MINIMAL_NON_FACES]].

property N_MINIMAL_NON_FACES : Int;


# @category Combinatorics
# Maximal dimension of the [[FACETS]], where the dimension of a facet is defined as
# the number of its vertices minus one.

property DIM : Int;


# @category Combinatorics
# A simplicial complex is __pure__ if all its facets have the same dimension.

property PURE : Bool;


# @category Combinatorics
# f<sub>k</sub> is the number of k-faces, for k = 0,... , d, where d is the dimension.

property F_VECTOR : Array<Int>;

# @category Combinatorics
# The h-vector of the simplicial complex.

property H_VECTOR : Array<Int>;

# @category Combinatorics
# f<sub>ik</sub> is the number of incident pairs of i-faces and k-faces; the main
# diagonal contains the [[F_VECTOR]].

property F2_VECTOR : Matrix<Int>;

# @category Combinatorics
# True if this is shellable.

property SHELLABLE : Bool;

# @category Combinatorics
# An ordered list of facets constituting a shelling.

property SHELLING : Array<Set>;

# @category Combinatorics
# Subcomplex generated by faces of codimension 2 that are contained in an odd
# number of faces of codimension 1.

property ODD_SUBCOMPLEX : SimplicialComplex;

rule ODD_SUBCOMPLEX.VertexPerm.PERMUTATION = VertexPerm.PERMUTATION;


# @category Combinatorics
# True if [[GRAPH]] is ([[DIM]] + 1)-colorable.

property FOLDABLE : Bool;



# @category Topology
# Reduced Euler characteristic.  Alternating sum of the [[F_VECTOR]] minus 1.

property EULER_CHARACTERISTIC : Int;


# @category Topology
# Reduced simplicial homology groups H<sub>0</sub>, ..., H<sub>d</sub> (integer coefficients), listed in increasing dimension order.
# See [[HomologyGroup]] for explanation of encoding of each group.

property HOMOLOGY : Array<HomologyGroup<Integer>>;


# @category Topology
# Reduced cohomology groups, listed in increasing codimension order.
# See [[HomologyGroup]] for explanation of encoding of each group.

property COHOMOLOGY : Array<HomologyGroup<Integer>>;


# @category Topology
# Representatives of cycle groups, listed in increasing dimension order.
# See [[CycleGroup]] for explanation of encoding of each group.

property CYCLES : Array<CycleGroup<Integer>>;

### FIXME: needs a client to permute since CycleGroup embedded c++ type
rule nonexistent : CYCLES : VertexPerm.CYCLES, VertexPerm.PERMUTATION;


# @category Topology
# Representatives of cocycle groups, listed in increasing codimension order.
# See [[CycleGroup]] for explanation of encoding of each group.

property COCYCLES : Array<CycleGroup<Integer>>;

### FIXME: needs a client to permute since CycleGroup embedded c++ type
rule nonexistent : COCYCLES : VertexPerm.COCYCLES, VertexPerm.PERMUTATION;


# @category Topology
# Parity and signature of the intersection form of a closed oriented 4-manifold.
property INTERSECTION_FORM : IntersectionForm;


# @category Topology
# Mod 2 cycle representation of Stiefel-Whitney classes.  Each cycle is represented as a set of simplices.
property STIEFEL_WHITNEY : Array<PowerSet>;

### FIXME: could be done
rule nonexistent : STIEFEL_WHITNEY : VertexPerm.STIEFEL_WHITNEY, VertexPerm.PERMUTATION;


# @category Topology
# Determines if this is a compact simplicial manifold with boundary.
# Depends on heuristic [[SPHERE]] recognition.
# May be true or false or undef (if heuristic does not succeed).

property MANIFOLD : Bool;


# @category Topology
# True if this is a [[PURE]] simplicial complex with the property that each ridge is
# contained in either one or two facets.

property PSEUDO_MANIFOLD: Bool;


# @category Topology
# True if this is a [[PURE]] simplicial complex with the property that each ridge is
# contained in exactly two facets.

property CLOSED_PSEUDO_MANIFOLD : Bool;


# @category Topology
# True if this is a [[PSEUDO_MANIFOLD]] with top level homology isomorphic to Z.

property ORIENTED_PSEUDO_MANIFOLD : Bool;


# @category Topology
# An orientation of the facets of an [[ORIENTED_PSEUDO_MANIFOLD]], such that the induced orientations
# of a common ridge of two neighboring facets cancel each other out. Each facet is marked with //true//
# if the orientation is given by the increasing vertex ordering and is marked with //false// if the
# orientation is obtained from the increasing vertex ordering by a transposition.

property ORIENTATION : Array<Bool>;

rule nonexistent : ORIENTATION : VertexPerm.ORIENTATION, VertexPerm.PERMUTATION;

rule ORIENTATION : FacetPerm.ORIENTATION, FacetPerm.PERMUTATION {
   $this->ORIENTATION=permuted($this->FacetPerm->ORIENTATION, $this->VertexPerm->PERMUTATION);
}
weight 1.10;


# @category Topology
# Determines if this is homeomorphic to a sphere.
# In general, this is undecidable; therefore, the implementation depends on heuristics.
# May be true or false or undef (if heuristic does not succeed).

property SPHERE : Bool;


# @category Topology
# Determines if this is homeomorphic to a ball.
# In general, this is undecidable; therefore, the implementation depends on heuristics.
# May be true or false or undef (if heuristic does not succeed).

property BALL : Bool;


# @category Combinatorics
# The subcomplex consisting of all 1-faces.

property GRAPH : Graph;

rule GRAPH.NodePerm.PERMUTATION = VertexPerm.PERMUTATION;

# @category Combinatorics
# A coloring of the vertices.

property COLORING : Array<Int>;

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

# @category Combinatorics
# The graph of facet neighborhood.
# Two [[FACETS]] are neighbors if they share a (d-1)-dimensional face.

property DUAL_GRAPH : Graph {

   property COLORING : NodeMap<Undirected,Int> : construct(ADJACENCY);

}

rule DUAL_GRAPH.NodePerm.PERMUTATION = FacetPerm.PERMUTATION;

# @category Combinatorics
# The face lattice of the simplical complex
# organized as a directed graph.  Each node corresponds to some face
# of the simplical complex. It is represented as the list of vertices
# comprising the face. The outgoing arcs point to the containing faces
# of the next dimension. An artificial top node is added to represent
# the entire complex.

property HASSE_DIAGRAM : FaceLattice;

rule HASSE_DIAGRAM : VertexPerm.HASSE_DIAGRAM, VertexPerm.PERMUTATION {
   $this->HASSE_DIAGRAM=permuted_atoms($this->VertexPerm->HASSE_DIAGRAM, $this->VertexPerm->PERMUTATION);
}

rule HASSE_DIAGRAM : FacetPerm.HASSE_DIAGRAM, FacetPerm.PERMUTATION {
   $this->HASSE_DIAGRAM=permuted_coatoms($this->FacetPerm->HASSE_DIAGRAM, $this->FacetPerm->PERMUTATION);
}

# @category Topology
# True if this is a [[CONNECTED]] [[MANIFOLD]] of dimension 2.

property SURFACE : Bool;


# @category Topology
# The __genus__ of a surface.

property GENUS : Int;


# @category Topology
# True if the vertex star of each vertex is [[DUAL_CONNECTED]].

property LOCALLY_STRONGLY_CONNECTED : Bool;


# @category Combinatorics
# Codimension-1-faces of a [[PSEUDO_MANIFOLD]] which are contained in one facet only.

property BOUNDARY : SimplicialComplex;

rule BOUNDARY.VertexPerm.PERMUTATION = VertexPerm.PERMUTATION;


# @category Topology
# Edge-subset of a 3-sphere which is a knot or link, that is, a collection of pairwise disjoint cycles.

property KNOT : Array<Set>;

rule KNOT : VertexPerm.KNOT, VertexPerm.PERMUTATION {
   $this->KNOT=permuted_elements($this->VertexPerm->KNOT, $this->VertexPerm->PERMUTATION);
}
weight 1.20;


# @category Combinatorics
# Orbit decomposition of the group of projectivities acting on the set of vertices of facet 0.

property PROJ_ORBITS : PowerSet;

rule PROJ_ORBITS : VertexPerm.PROJ_ORBITS, VertexPerm.PERMUTATION {
   $this->PROJ_ORBITS=permuted($this->VertexPerm->PROJ_ORBITS, $this->VertexPerm->PERMUTATION);
}
weight 1.20;


# @category Combinatorics
# For each vertex the corresponding vertex of facet 0 with respect to the action of the group of projectivities.

property PROJ_DICTIONARY : Array<Int>;

rule nonexistent : PROJ_DICTIONARY : VertexPerm.PROJ_DICTIONARY, VertexPerm.PERMUTATION;

}

# A geometric simplicial complex, i.e., a simplicial complex with a geometric realization.
# //Scalar// is the numeric data type used for the coordinates.
# @tparam Scalar default: [[Rational]]
declare object GeometricSimplicialComplex<Scalar=Rational> : SimplicialComplex;

object GeometricSimplicialComplex {

# Coordinates for the vertices of the simplicial complex, such that the complex is
# embedded without crossings in some R<sup>e</sup>.  Vector (x<sub>1</sub>, .... x<sub>e</sub>) represents a point
# in Euclidean e-space.
property COORDINATES : Matrix<Scalar>;


# Dimension e of the space in which the [[COORDINATES]] of the complex is embedded.
property G_DIM : Int;

# Volume of a geometric simplicial complex.
property VOLUME : Scalar;

# A geometric simplicial complex is unimodular if all simplices have unit normalized volume.
property UNIMODULAR : Bool;

# count how many simplcies of a geometric simplicial complex are unimodular.
property N_UNIMODULAR : Int;

# Signature of a geometric simplicial complex embedded in the integer lattice.
# Like [[DUAL_GRAPH_SIGNATURE]], but only simplices with odd normalized volume are counted.
property SIGNATURE : Int;


rule G_DIM : COORDINATES {
   $this->G_DIM=$this->COORDINATES->cols;
}
weight 0.1;


rule SIGNATURE : DUAL_GRAPH.ADJACENCY, COORDINATES, FACETS {
   $this->SIGNATURE=signature($this);
}
precondition : DIM, G_DIM {
   $this->DIM==$this->G_DIM;
}

rule DUAL_GRAPH.BIPARTITE : SIGNATURE {
  $this->DUAL_GRAPH->BIPARTITE = $this->SIGNATURE >= 0;
}
weight 0.1;

rule VOLUME : FACETS, COORDINATES, DIM {
  $this->VOLUME=volume($this);
}

rule UNIMODULAR : FACETS, COORDINATES {
  $this->UNIMODULAR=unimodular($this);
}

rule N_UNIMODULAR : FACETS, COORDINATES {
  $this->N_UNIMODULAR=n_unimodular($this);
}

}

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