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

# @Category Combinatorics
object Hypersurface {

# Homogeneous tropical polynomial defining the hypersurface.
# Note: The homogeneity of the polynomial is never checked.
property POLYNOMIAL : Polynomial<TropicalNumber<Addition>>;

# Exponent vectors of the homogeneous tropical polynomial [[POLYNOMIAL]]. Each
# row corresponds to one of the monomials in [[POLYNOMIAL]], each column to a
# variable.

property MONOMIALS : Matrix<Int>;

# Coefficients of the homogeneous tropical polynomial [[POLYNOMIAL]]. Each
# entry corresponds to one of the terms in [[POLYNOMIAL]]. The order is
# compatible with the order of [[MONOMIALS]].

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)
      // die "no permutation";
}

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 (inhomogeneous) tropical polynomial \(F:\mathbb R^d\to\mathbb R\) (and the corresponding affine 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/|Essentials of Tropical Combinatorics]], Chapter 1.
#
# For a projective tropical hypersurface, the __dome__ is the intersection of the dome for the affine case with the hyperplane at height 1.
# Note: To account for negative exponents, the dome may have been repositioned by multiplying the original polynomial with a suitable monomial.

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.INEQUALITIES, DOME.FEASIBLE, DOME.BOUNDED : MONOMIALS, COEFFICIENTS {
   hypersurface_dome($this);
}

rule PROJECTIVE_VERTICES = DOME.VERTICES;

rule LINEALITY_SPACE = DOME.LINEALITY_SPACE;

rule FAR_VERTICES = DOME.FAR_FACE;

rule MAXIMAL_POLYTOPES, REDUNDANT_MONOMIALS, REGIONS, WEIGHTS : DOME.VERTICES_IN_FACETS, DOME.VERTICES_IN_INEQUALITIES, DOME.DUAL_GRAPH.ADJACENCY, FAR_VERTICES , MONOMIALS {
   dome_regions($this);
}

# @category Combinatorics
# Subdivision of the Newton polytope dual to the tropical hypersurface.
# The vertices of this PolyhedralComplex are the non-redundant [[MONOMIALS]].

property DUAL_SUBDIVISION : fan::SubdivisionOfPoints;

rule DUAL_SUBDIVISION.POINTS, DUAL_SUBDIVISION.WEIGHTS : MONOMIALS, COEFFICIENTS {
   my $homog = ones_vector($this->MONOMIALS->rows()) | new Matrix($this->MONOMIALS);
   my $rat_coeff = new Vector<Rational>($this->COEFFICIENTS);
   $this->DUAL_SUBDIVISION = new fan::SubdivisionOfPoints( POINTS=> $homog, WEIGHTS=> Addition->orientation() * $rat_coeff);
}

# @category Combinatorics
# Returns [[DUAL_SUBDIVISION]]; backward compatibility.
# @return fan::SubdivisionOfPoints
user_method dual_subdivision() : DUAL_SUBDIVISION {
   my $this=shift;
   return $this->DUAL_SUBDIVISION;
}

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