1#  Copyright (c) 1997-2021
2#  Ewgenij Gawrilow, Michael Joswig, and the polymake team
3#  Technische Universität Berlin, Germany
4#  https://polymake.org
5#
6#  This program is free software; you can redistribute it and/or modify it
7#  under the terms of the GNU General Public License as published by the
8#  Free Software Foundation; either version 2, or (at your option) any
9#  later version: http://www.gnu.org/licenses/gpl.txt.
10#
11#  This program is distributed in the hope that it will be useful,
12#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14#  GNU General Public License for more details.
15#-------------------------------------------------------------------------------
16
17# @Category Combinatorics
18object Cycle {
19
20   # Any cycle is pure-dimensional by default.
21   rule initial : PURE : {
22      $this->PURE = 1;
23   }
24
25   # @category Input property
26   # A list of (non-redundant) vertices and rays of the complex. Note that [[VERTICES]]
27   # are supposed to be normalized to a leading 0. If you want to input non-normalized vertices,
28   # use this property.
29   # [[VERTICES]] will be derived from this: Each row of [[VERTICES]] is just the corresponding row
30   # of [[PROJECTIVE_VERTICES]], with the first coordinate (i.e. column index 1) normalized to 0.
31   property PROJECTIVE_VERTICES : Matrix<Rational>;
32
33   rule VERTICES : PROJECTIVE_VERTICES {
34      my $m = new Matrix<Rational>($this->PROJECTIVE_VERTICES);
35      if ($m->rows() > 0) { # Might be the empty cycle
36         canonicalize_scalar_to_leading_zero($m->minor(All,~[0]));
37      }
38      $this->VERTICES = $m;
39   }
40
41   rule RaysPerm.PERMUTATION : RaysPerm.PROJECTIVE_VERTICES, PROJECTIVE_VERTICES {
42      $this->RaysPerm->PERMUTATION = find_matrix_row_permutation($this->RaysPerm->PROJECTIVE_VERTICES, $this->PROJECTIVE_VERTICES)
43         // die "no permutation";
44   }
45
46   rule PROJECTIVE_VERTICES : RaysPerm.PROJECTIVE_VERTICES, RaysPerm.PERMUTATION {
47      $this->PROJECTIVE_VERTICES = permuted_rows($this->RaysPerm->PROJECTIVE_VERTICES, $this->RaysPerm->PERMUTATION);
48   }
49   weight 1.10;
50
51   # @Category Weights and lattices
52   # These are the integer weights associated to the maximal cells of the complex.
53   # Entries correspond to (rows of) [[MAXIMAL_POLYTOPES]].
54   property WEIGHTS : Vector<Integer>;
55
56   rule WEIGHTS : ConesPerm.WEIGHTS, ConesPerm.PERMUTATION {
57      $this->WEIGHTS=permuted($this->ConesPerm->WEIGHTS, $this->ConesPerm->PERMUTATION);
58   }
59   weight 1.10;
60
61   # @Category Combinatorics
62   # Non-redundant list of all codimension one faces. Indices refer to
63   # [[VERTICES]]. Does not include any far faces.
64   property CODIMENSION_ONE_POLYTOPES : IncidenceMatrix;
65
66   rule CODIMENSION_ONE_POLYTOPES : RaysPerm.CODIMENSION_ONE_POLYTOPES, RaysPerm.PERMUTATION {
67      $this->CODIMENSION_ONE_POLYTOPES=permuted_cols($this->RaysPerm->CODIMENSION_ONE_POLYTOPES,
68                                                     $this->RaysPerm->PERMUTATION);
69   }
70   weight 1.10;
71
72   # @Category Combinatorics
73   # Incidence matrix of codimension one polytopes and maximal polytopes.
74   # Rows refer to [[CODIMENSION_ONE_POLYTOPES]], columns to
75   # [[MAXIMAL_POLYTOPES]].
76   property MAXIMAL_AT_CODIM_ONE : IncidenceMatrix;
77
78   # @category Combinatorics
79   # This maps an index pair (i,j), where i corresponds to the i-th row of [[CODIMENSION_ONE_POLYTOPES]] and
80   # j to the j-th row of [[MAXIMAL_POLYTOPES]], to the matching row number in [[FACET_NORMALS]].
81   property FACET_NORMALS_BY_PAIRS : Map<Pair<Int,Int>, Int>;
82
83   rule MAXIMAL_AT_CODIM_ONE : ConesPerm.MAXIMAL_AT_CODIM_ONE, ConesPerm.PERMUTATION {
84      $this->MAXIMAL_AT_CODIM_ONE=permuted_cols($this->ConesPerm->MAXIMAL_AT_CODIM_ONE,$this->ConesPerm->PERMUTATION);
85   }
86   weight 1.10;
87
88   # permuting [[CODIMENSION_ONE_POLYTOPES]]
89   permutation CodimPerm : PermBase;
90
91   rule CodimPerm.PERMUTATION : CodimPerm.CODIMENSION_ONE_POLYTOPES, CODIMENSION_ONE_POLYTOPES {
92      $this->CodimPerm->PERMUTATION = find_permutation(new Array<Set<Int>>(rows($this->CodimPerm->CODIMENSION_ONE_POLYTOPES)),
93                                                       new Array<Set<Int>>(rows($this->CODIMENSION_ONE_POLYTOPES)))
94         // die "no permutation";
95   }
96   weight 5.10;
97
98   rule MAXIMAL_AT_CODIM_ONE : CodimPerm.MAXIMAL_AT_CODIM_ONE, CodimPerm.PERMUTATION {
99      $this->MAXIMAL_AT_CODIM_ONE=permuted_rows($this->CodimPerm->MAXIMAL_AT_CODIM_ONE,$this->CodimPerm->PERMUTATION);
100   }
101   weight 1.10;
102
103   rule FACET_NORMALS_BY_PAIRS : CodimPerm.FACET_NORMALS_BY_PAIRS, CodimPerm.PERMUTATION {
104      $this->FACET_NORMALS_BY_PAIRS=permute_map_first_factor($this->CodimPerm->FACET_NORMALS_BY_PAIRS, $this->CodimPerm->PERMUTATION);
105   }
106   weight 1.10;
107
108   rule FACET_NORMALS_BY_PAIRS : ConesPerm.FACET_NORMALS_BY_PAIRS, ConesPerm.PERMUTATION {
109      $this->FACET_NORMALS_BY_PAIRS=permute_map_second_factor($this->ConesPerm->FACET_NORMALS_BY_PAIRS, $this->ConesPerm->PERMUTATION);
110   }
111   weight 1.10;
112
113
114
115   rule CODIMENSION_ONE_POLYTOPES, MAXIMAL_AT_CODIM_ONE, FACET_NORMALS_BY_PAIRS : MAXIMAL_POLYTOPES, VERTICES, MAXIMAL_POLYTOPES_FACETS, FACET_NORMALS, FAR_VERTICES {
116      compute_codimension_one_polytopes($this);
117   }
118   weight 2.10;
119   incurs CodimPerm;
120
121
122   # @Category Weights and lattices
123   # The lattice normals of codimension one faces with respect to adjacent
124   # maximal cells. It maps a pair of indices (i,j) to the lattice normal
125   # of the codimension one face given by row i in [[CODIMENSION_ONE_POLYTOPES]]
126   # in the maximal cell given by row j in [[MAXIMAL_POLYTOPES]].
127   # The lattice normal is a representative of a generator of the quotient of
128   # the saturated lattice of the maximal cell by the saturated lattice of the
129   # codimension one face. It is chosen such that it "points into the maximal cell"
130   # and is only unique modulo the lattice spanned by the codimension one cell.
131   property LATTICE_NORMALS : Map<Pair<Int,Int>,Vector<Integer>> {
132
133      method equal {
134         my ($this, $l1, $l2) = @_;
135         return compare_lattice_normals($this->VERTICES, $this->LINEALITY_SPACE, $this->CODIMENSION_ONE_POLYTOPES, $l1, $l2);
136      }
137
138   };
139
140   rule LATTICE_NORMALS : ConesPerm.LATTICE_NORMALS, ConesPerm.PERMUTATION  {
141      $this->LATTICE_NORMALS=permute_map_second_factor($this->ConesPerm->LATTICE_NORMALS, $this->ConesPerm->PERMUTATION);
142   }
143   weight 1.10;
144
145   rule LATTICE_NORMALS : CodimPerm.LATTICE_NORMALS, CodimPerm.PERMUTATION {
146      $this->LATTICE_NORMALS=permute_map_first_factor($this->CodimPerm->LATTICE_NORMALS,$this->CodimPerm->PERMUTATION);
147   }
148
149
150   rule LATTICE_NORMALS : MAXIMAL_POLYTOPES, CODIMENSION_ONE_POLYTOPES, MAXIMAL_AT_CODIM_ONE, MAXIMAL_POLYTOPES_AFFINE_HULL_NORMALS, FACET_NORMALS_BY_PAIRS, FACET_NORMALS, MAXIMAL_POLYTOPES_FACETS, AFFINE_HULL, FAN_DIM {
151      compute_lattice_normals($this);
152   }
153   weight 3.10;
154
155
156   # @Category Affine and projective coordinates
157   # This is the projective dimension of the cycle.
158   # Alias for [[DIM]].
159   property PROJECTIVE_DIM : Int;
160
161   rule PROJECTIVE_DIM : FAN_DIM {
162      $this->PROJECTIVE_DIM = $this->FAN_DIM-1;
163   }
164   weight 0.1;
165
166   # @Category Affine and projective coordinates
167   # This is the ambient projective dimension, i.e. it is
168   # [[FAN_AMBIENT_DIM]]-2.
169   property PROJECTIVE_AMBIENT_DIM : Int;
170
171   rule PROJECTIVE_AMBIENT_DIM : FAN_AMBIENT_DIM {
172      $this->PROJECTIVE_AMBIENT_DIM = $this->FAN_AMBIENT_DIM-2;
173   }
174   weight 0.1;
175
176   label with_new_properties
177
178   # Note: We need to redefine this rule: If only [[PROJECTIVE_VERTICES]] are present,
179   # the standard ruleset of fan will give 0 as an ambient dim.
180   rule with_new_properties : FAN_AMBIENT_DIM : {
181      my $d=0;
182      foreach (qw(RAYS INPUT_RAYS LINEALITY_SPACE INPUT_LINEALITY FACET_NORMALS LINEAR_SPAN_NORMALS PROJECTIVE_VERTICES)) {
183         my $M;
184         if (defined ($M=$this->lookup($_)) && $M->cols()>0) {
185            $d=$M->cols();
186            last;
187         }
188      }
189      $this->FAN_AMBIENT_DIM=$d;
190   }
191   precondition : defined(RAYS | INPUT_RAYS | LINEALITY_SPACE | INPUT_LINEALITY | FACET_NORMALS | LINEAR_SPAN_NORMALS | PROJECTIVE_VERTICES);
192   weight 0.5;
193
194   # @category Affine and projective coordinates
195   # Codimension of the cycle. Same as [[PROJECTIVE_AMBIENT_DIM]] - [[PROJECTIVE_DIM]]
196   property PROJECTIVE_CODIMENSION : Int;
197
198   rule PROJECTIVE_CODIMENSION : PROJECTIVE_AMBIENT_DIM, PROJECTIVE_DIM {
199      $this->PROJECTIVE_CODIMENSION = $this->PROJECTIVE_AMBIENT_DIM - $this->PROJECTIVE_DIM;
200   }
201   weight 0.1;
202
203   # @category Weights and lattices
204   # For a onedimensional cycle, this produces the lengths of the [[MAXIMAL_POLYTOPES]], as multiples of the
205   # corresponding [[LATTICE_NORMALS]]. The i-th entry is the length of cell i. For unbounded cells
206   # this number is inf
207   # @return Array<Rational>
208   user_method CURVE_EDGE_LENGTHS : VERTICES, FAR_VERTICES, LATTICE_NORMALS, MAXIMAL_POLYTOPES, MAXIMAL_AT_CODIM_ONE {
209      return cycle_edge_lengths(shift);
210   }
211   precondition : PROJECTIVE_DIM {
212      $this->PROJECTIVE_DIM == 1;
213   }
214
215   # @category Affine and projective coordinates
216   # This produces a version of the cycle in the coordinates of a standard
217   # tropical chart, i.e. one coordinate is set to 0.
218   # It is returned as an ordinary polyhedral complex (which can, for example,
219   # be used for visualization).
220   # @param Int chart The coordinate which should be set to 0. Indexed from
221   # 0 to [[AMBIENT_DIM]]-1 and 0 by default.
222   # @return fan::PolyhedralComplex<Rational>
223   user_method affine_chart(;$=0) {
224      my ($this,$chart) = @_;
225      if ($this->FAN_AMBIENT_DIM==0) {
226         $this
227      } else {
228         new fan::PolyhedralComplex(VERTICES=>tdehomog($this->VERTICES,$chart),
229                                    MAXIMAL_POLYTOPES=>$this->MAXIMAL_POLYTOPES,
230                                    LINEALITY_SPACE=>tdehomog($this->LINEALITY_SPACE,$chart));
231      }
232   }
233
234   # @category Weights and lattices
235   # Convenience function to ask for [[LATTICE_NORMALS]]->{new Pair<Int,Int>(i,j)}
236   # @param Int i Row index in [[CODIMENSION_ONE_POLYTOPES]].
237   # @param Int j Row index in [[MAXIMAL_POLYTOPES]].
238   # @return Vector<Integer>
239   user_method lattice_normal($,$) {
240      my ($this, $i, $j)=@_;
241      return $this->LATTICE_NORMALS->{new Pair<Int,Int>($i,$j)};
242   }
243
244   # @category Combinatorics
245   # Convenience function to ask for [[FACET_NORMALS_BY_PAIRS]]->{new Pair<Int,Int>(i,i)}
246   # @param Int i Row index in [[CODIMENSION_ONE_POLYTOPES]].
247   # @param Int j Row index in [[MAXIMAL_POLYTOPES]].
248   # @return Int Row index in [[FACET_NORMALS]].
249   user_method facet_normal($,$) {
250      my ($this, $i, $j)=@_;
251      return $this->FACET_NORMALS_BY_PAIRS->{new Pair<Int,Int>($i,$j)};
252   }
253
254}
255
256
257# Local Variables:
258# mode: perl
259# cperl-indent-level:3
260# indent-tabs-mode:nil
261# End:
262