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


# @category Geometry
# A [[PolyhedralFan]] with a symmetry group acting on the coordinates.
declare object SymmetricFan<Scalar=Rational> [ is_ordered_field(Scalar) ] : PolyhedralFan<Scalar>;

object SymmetricFan {


# @category Symmetry
# Each element of the array is a generator of the subgroup of the symmetric group
# acting on the coordintates. Each generator is represented by an Array whose ith
# entry is the image of ith coordinate.
property SYMMETRY_GENERATORS : Array<Array<Int>>;

# @category Symmetry
# Each element of the array is an element of the symmetry group.
property SYMMETRY_GROUP : Array<Array<Int>>;


# @category Symmetry
# Number of elements of the symmetry group.
property N_SYMMETRIES : Int;


# @category Input property
# One Ray from each orbit.  May be redundant.
#
#property INPUT_RAYS_REPS : Matrix<Scalar>;


# @category Input property
# Maybe redundant list of not necessarily maximal cones, one from each orbit.  
# All vectors in the input must be non-zero.
# Indices refer to [[INPUT_RAYS]].
property INPUT_CONES_REPS : Array<Set<Int>>;


# @category Symmetry
# One ray from each orbit. Non-redundant.
property RAYS_REPS : Matrix<Scalar>;

# @category Symmetry
# Tells which ray is in the orbit of which representative, indices refers to rows of [[RAYS]].
property RAYS_IN_ORBITS : Array<Set<Int>>;

# @category Symmetry
# Number of orbits of [[RAYS]].
property N_RAY_ORBITS : Int;


# @category Symmetry 
# Each row contains the image of all [[RAYS]] under one element of the symmetry group.
property RAYS_IMAGES : Array<Array<Int>>;

# @category Symmetry 
# Number of elements of each orbit of [[RAYS]].
property RAYS_ORBIT_SIZES : Array<Int>;



# @category Symmetry
# Non redundant list of maximal cones, one from each orbit.  Indices refer to [[RAYS]].
property MAXIMAL_CONES_REPS : Array<Set<Int>>;

# @category Symmetry
# Tells which maximal cone is in the orbit of which representative, indices refers to rows of [[MAXIMAL_CONES]].
property MAXIMAL_CONES_IN_ORBITS : Array<Set<Int>>;

# @category Symmetry
# Number of orbits of [[MAXIMAL_CONES]].
property N_MAXIMAL_CONE_ORBITS : Int;

# @category Symmetry
# Number of [[MAXIMAL_CONES_REPS]] in each orbit.
property MAXIMAL_CONES_ORBIT_SIZES : Array<Int>;

# @category Symmetry
# The dimensions of [[MAXIMAL_CONES_REPS]].
property MAXIMAL_CONES_REPS_DIMS : Array<Int>;



# @category Symmetry
# List of all cones of all dimensions of the fan, one from each orbit.  Indices refer to [[RAYS]].
property CONES_REPS : Array<Array<Set<Int>>>;

# @category Symmetry
# f<sub>k</sub> is the number of k-dimensional cones up to symmetry.
property ORBITS_F_VECTOR  : Vector<Integer>;

# @category Symmetry
# Number of [[CONES_REPS]] in each orbit.
property CONES_ORBIT_SIZES : Array<Array<Int>>;



# @category Symmetry
# Unique names assigned to the [[RAYS_REPS]].
property RAYS_REPS_LABELS : Array<String> : mutable;



# @category Symmetry
# The possible facet normals of all maximal cone representatives.
property REPS_FACET_NORMALS : Matrix<Scalar>;

# @category Symmetry
# Tells for each maximal cone representative what are its facets.
# A negative number means that the corresponding row of
# [[REPS_FACET_NORMALS]] has to be negated.
property MAXIMAL_CONES_REPS_FACETS : SparseMatrix<Int>;

# @category Symmetry
# The possible linear span normals of all maximal cone representatives.
property REPS_LINEAR_SPAN_NORMALS : Matrix<Scalar>;

# @category Symmetry
# Tells for each maximal cone representative what is its linear span.
# Indices refer to [[REPS_LINEAR_SPAN_NORMALS]].
# Rows correspond to [[MAXIMAL_CONES_REPS_FACETS]]
property MAXIMAL_CONES_REPS_LINEAR_SPAN_NORMALS : IncidenceMatrix;


# Returns the //i//-th maximal cone representative.
# @param Int i
# @return Cone
user_method cone_representative($)  {
   my $p=new Cone<Scalar>(RAYS=>$_[0]->RAYS->minor($_[0]->MAXIMAL_CONES_REPS->[$_[1]],All));
   return $p;
}


rule MAXIMAL_CONES_REPS_DIMS : RAYS, MAXIMAL_CONES_REPS, LINEALITY_SPACE {
   my @dims;
   foreach (@{$this->MAXIMAL_CONES_REPS}) {
      push @dims, (new polytope::Cone(RAYS=>$this->RAYS->minor($_,All),LINEALITY_SPACE=>$this->LINEALITY_SPACE))->CONE_DIM;
   }
   $this->MAXIMAL_CONES_REPS_DIMS=\@dims;
}
weight 1.50;

rule MAXIMAL_CONES_REPS_DIMS : FAN_DIM, N_MAXIMAL_CONE_ORBITS {
   $this->MAXIMAL_CONES_REPS_DIMS(temporary)=[ ( $this->FAN_DIM ) x $this->N_MAXIMAL_CONE_ORBITS ];
}
precondition : PURE;
weight 0.10;

rule LINEALITY_SPACE : RAYS, MAXIMAL_CONES_REPS {
   $this->LINEALITY_SPACE=new Matrix<Scalar>(0, $this->RAYS->cols);
}
weight 0.10;


rule N_MAXIMAL_CONE_ORBITS : MAXIMAL_CONES_REPS {
   $this->N_MAXIMAL_CONE_ORBITS=scalar(@{$this->MAXIMAL_CONES_REPS});
}
weight 0.1;

rule F_VECTOR, ORBITS_F_VECTOR, CONES_REPS, CONES_ORBIT_SIZES : RAYS, MAXIMAL_CONES_REPS, RAYS_IMAGES, COMBINATORIAL_DIM, LINEALITY_SPACE {
    all_cones_symmetry($this,$this->COMBINATORIAL_DIM);
}
weight 3.10;

rule F_VECTOR, ORBITS_F_VECTOR, CONES_REPS, CONES_ORBIT_SIZES, COMBINATORIAL_DIM, MAXIMAL_CONES_REPS_DIMS : RAYS, MAXIMAL_CONES_REPS, RAYS_IMAGES, LINEALITY_SPACE {
    all_cones_symmetry($this);
}
weight 3.60;

rule FAN_DIM, PURE : MAXIMAL_CONES_REPS_DIMS {
   my $dim=$this->MAXIMAL_CONES_REPS_DIMS->[0];
   my $pure=1;
   foreach (@{$this->MAXIMAL_CONES_REPS_DIMS})  {
      if ($_>$dim) {
         $dim =$_;
	 $pure=0;
     }
     else {if ($_<$dim) {
     	 $pure=0;
     }}
   }
   $this->FAN_DIM=$dim;
   $this->PURE=$pure;
}
weight 1.30;

rule PURE : MAXIMAL_CONES_REPS_DIMS {
    my $dim=$this->MAXIMAL_CONES_REPS_DIMS->[0];
    foreach (@{$this->MAXIMAL_CONES_REPS_DIMS})  {
      if ($_!=$dim) {
          $this->PURE=0;
	  return;
     }
   }
   $this->PURE=1;
}
weight 1.10;

}

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