#  Copyright (c) 1997-2018
#  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 Combinatorics
object Hypersurface { 

# Homogeneous tropical polynomial defining the hypersurface.

property POLYNOMIAL : Polynomial<TropicalNumber<Addition>>;

# Each row corresponds to one of the monomials in [[POLYNOMIAL]], each column to a variable.

property MONOMIALS : Matrix<Int>;

# Each row corresponds to one of the monomials in [[POLYNOMIAL]], each column to a variable.

property COEFFICIENTS : Vector<TropicalNumber<Addition>>;

# permuting [[MONOMIALS]] and [[COEFFICIENTS]]
permutation TermPerm : PermBase;

rule TermPerm.PERMUTATION : TermPerm.MONOMIALS, MONOMIALS {
   $this->TermPerm->PERMUTATION=find_matrix_row_permutation($this->TermPerm->MONOMIALS, $this->MONOMIALS);
}

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


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

# Indices of [[MONOMIALS]] which do not define facets of the [[DOME]].

property REDUNDANT_MONOMIALS : Set;

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

# The __dome__ of a tropical polynomial \(F:\mathbb R^d\to\mathbb R\) (and the corresponding tropical hypersurface) is the set 
# \[D(F)=\left\{(p,s)\in\mathbb R^{d+1}\mid p\in\mathbb R^d, s\in\mathbb R, s \oplus F(p) = s\right\}.\]
# It is an unbounded convex polyhedron, c.f.
# 
# 	Michael Joswig, [[http://page.math.tu-berlin.de/~joswig/etc/ETC-130412.pdf|Essentials of Tropical Combinatorics]], Chapter 1.

property DOME : polytope::Polytope<Rational>;


# Connected components of the complement.
# Rows correspond to facets of the [[DOME]], i.e. non-redundant [[MONOMIALS]] , columns correspond to [[VERTICES]].

property REGIONS : IncidenceMatrix;


rule MONOMIALS, COEFFICIENTS : POLYNOMIAL {
   my $p=$this->POLYNOMIAL;
   $this->MONOMIALS=$p->monomials_as_matrix();
   $this->COEFFICIENTS=$p->coefficients_as_vector();
}
weight 0.10;
incurs TermPerm;

rule POLYNOMIAL : MONOMIALS, COEFFICIENTS {
   $this->POLYNOMIAL = new Polynomial<TropicalNumber<Addition> >($this->COEFFICIENTS, $this->MONOMIALS);
}
weight 0.10;

rule DOME, PROJECTIVE_VERTICES, LINEALITY_SPACE, FAR_VERTICES, MAXIMAL_POLYTOPES, REDUNDANT_MONOMIALS, REGIONS, WEIGHTS : MONOMIALS, COEFFICIENTS {
   hypersurface($this);
}



# @category Combinatorics
# Subdivision of the Newton polytope dual to the tropical hypersurface.
# The vertices of this PolyhedralComplex are the non-redundant [[MONOMIALS]].
# @return fan::SubdivisionOfPoints
user_method dual_subdivision : MONOMIALS, COEFFICIENTS {
   my $this=shift;
   my $homog = ones_vector($this->MONOMIALS->rows()) | new Matrix($this->MONOMIALS);
   my $rat_coeff = new Vector<Rational>($this->COEFFICIENTS);
   return new fan::SubdivisionOfPoints( POINTS=> $homog, WEIGHTS=> Addition->orientation() * $rat_coeff);
}

# @category Topology
# The topological genus of a onedimensional hypersurface, i.e. the number of
# interior lattice points that occur in the dual subdivision.
user_method GENUS : MONOMIALS, REDUNDANT_MONOMIALS {
   my $this = shift;
   my $homog = ones_vector($this->MONOMIALS->rows()) | new Matrix($this->MONOMIALS);
   my $interior = (new polytope::Polytope(POINTS=>$homog))->INTERIOR_LATTICE_POINTS->minor(All,~[0]);
   my $interior_set = new Set<Vector<Integer> >(@{rows($interior)});
   my $monomial_set = new Set<Vector<Integer> >(@{rows($this->MONOMIALS)});
   my $redundant = new Matrix<Integer>($this->MONOMIALS->minor($this->REDUNDANT_MONOMIALS,All));
   my $redundant_set = new Set<Vector<Integer> >(@{rows($redundant)});
   return ($interior_set*$monomial_set - $redundant_set)->size();
}
precondition : PROJECTIVE_DIM {
   $this->PROJECTIVE_DIM == 1 
}


} # object Hypersurface

# @category Producing a tropical hypersurface
# Create a tropical hyperplane as object of type Hypersurface.
# @tparam Addition [[Min]] or [[Max]]
# @param Vector<TropicalNumber<Addition> > coeffs coefficients of the tropical linear form 
# (can also be specified as anonymous array).
# @return Hypersurface<Addition>

user_function hyperplane<Addition>($)  {
    my $pre_coefs = shift;
	 my $coefs = new Vector<TropicalNumber<Addition> >($pre_coefs);
    my $d=$coefs->dim();
    return new Hypersurface<Addition>(MONOMIALS=>unit_matrix($d),COEFFICIENTS=>$coefs);
}




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