1 /*
2 This program is free software; you can redistribute it and/or
3 modify it under the terms of the GNU General Public License
4 as published by the Free Software Foundation; either version 2
5 of the License, or (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor,
15 Boston, MA 02110-1301, USA.
16
17 ---
18 Copyright (C) 2011 - 2015, Simon Hampe <simon.hampe@googlemail.com>
19
20 ---
21 Copyright (c) 2016-2021
22 Ewgenij Gawrilow, Michael Joswig, and the polymake team
23 Technische Universität Berlin, Germany
24 https://polymake.org
25
26 Contains functions to compute tropical Hurwitz cycles.
27 */
28
29 #include "polymake/client.h"
30 #include "polymake/Matrix.h"
31 #include "polymake/Rational.h"
32 #include "polymake/Vector.h"
33 #include "polymake/IncidenceMatrix.h"
34 #include "polymake/PowerSet.h"
35 #include "polymake/permutations.h"
36 #include "polymake/linalg.h"
37 #include "polymake/tropical/morphism_special.h"
38 #include "polymake/tropical/specialcycles.h"
39 #include "polymake/tropical/refine.h"
40 #include "polymake/tropical/convex_hull_tools.h"
41 #include "polymake/tropical/moduli_rational.h"
42 #include "polymake/tropical/thomog.h"
43 #include "polymake/tropical/morphism_thomog.h"
44 #include "polymake/TropicalNumber.h"
45 #include "polymake/tropical/misc_tools.h"
46 #include "polymake/polytope/convex_hull.h"
47
48 namespace polymake { namespace tropical {
49
50 struct HurwitzResult {
51 BigObject subdivision;
52 BigObject cycle;
53 };
54
55 /**
56 @brief Takes a RationalCurve and a list of node indices. Then inserts additional leaves (starting from N_LEAVES+1) at these nodes and returns the resulting RationalCurve object
57 @param BigObject curve A RationalCurve object
58 @param Vector<Int> nodes A list of node indices of the curve
59 */
insert_leaves(BigObject curve,const Vector<Int> & nodes)60 BigObject insert_leaves(BigObject curve, const Vector<Int>& nodes)
61 {
62 // Extract values
63 Int max_leaf = curve.give("N_LEAVES");
64 IncidenceMatrix<> setsInc = curve.give("SETS");
65 Vector<Set<Int>> sets = incMatrixToVector(setsInc);
66 Vector<Rational> coeffs = curve.give("COEFFS");
67 IncidenceMatrix<> nodes_by_sets = curve.give("NODES_BY_SETS");
68 IncidenceMatrix<> nodes_by_leavesInc = curve.give("NODES_BY_LEAVES");
69 Vector<Set<Int> > nodes_by_leaves = incMatrixToVector(nodes_by_leavesInc);
70
71 for (Int n_el = 0; n_el < nodes.dim(); ++n_el) {
72 Int n = nodes[n_el];
73 ++max_leaf;
74 // Easy case: There is already a leaf at this vertex
75 if (nodes_by_leaves[n].size() > 0) {
76 Int ref_leaf = *( nodes_by_leaves[n].begin());
77 for (Int s = 0; s < sets.dim(); ++s) {
78 if (sets[s].contains(ref_leaf)) {
79 sets[s] += max_leaf;
80 }
81 }
82 } //END if there is already a leaf
83 else {
84 // Normalize the sets at the node to point away from it. Order them in an arbitrary way
85 // Intersect the first two, I_1 and I_2: I_1 points away from the node, if and only if
86 // I_1 cap I_2 = empty or I_1. The subsequent sets I_k only have to fulfill
87 // I_k cap I_1 = empty
88 Vector<Int> adjacent_sets(nodes_by_sets.row(n));
89 Vector<Set<Int>> normalized_sets;
90 // FIXME: misuse of vector concatenation
91 Set<Int> first_inter = sets[adjacent_sets[0]] * sets[adjacent_sets[1]];
92 normalized_sets |=
93 (first_inter.size() == 0 || first_inter.size() == sets[adjacent_sets[0]].size()) ? sets[adjacent_sets[0]] : (sequence(1, max_leaf-1) - sets[adjacent_sets[0]]);
94 for (Int as = 1; as < adjacent_sets.dim(); ++as) {
95 Set<Int> subseq_inter = normalized_sets[0] * sets[adjacent_sets[as]];
96 normalized_sets |=
97 (subseq_inter.size() == 0)? sets[adjacent_sets[as]] : (sequence(1,max_leaf-1) - sets[adjacent_sets[as]]);
98 }
99 // Now for each set count, how many of the adjacent sets intersect it nontrivially
100 // It points away from the node, if and only if this number is 1 (otherwise its all)
101 for (Int s = 0; s < sets.dim(); ++s) {
102 Int inter_count = 0;
103 for (Int ns = 0; ns < normalized_sets.dim(); ++ns) {
104 if ((sets[s] * normalized_sets[ns]).size() > 0) ++inter_count;
105 if (inter_count > 1) break;
106 }
107 if (inter_count > 1) {
108 sets[s] += max_leaf;
109 }
110 }
111 } //END if there are only bounded edges
112
113 nodes_by_leaves[n] += max_leaf;
114 } //END iterate nodes
115
116 return BigObject("RationalCurve",
117 "SETS", sets,
118 "COEFFS", coeffs,
119 "N_LEAVES", max_leaf);
120 }
121
122 /**
123 @brief Takes a RationalCurve object and returns the rays v_I corresponding to its bounded edges as a matrix of row vectors in matroid coordinates (with leading coordinate 0).
124 @param BigObject curve A RationalCurve object
125 @return Matrix<Rational> The rays corresponding to the bounded edges
126 */
127 template <typename Addition>
edge_rays(BigObject curve)128 Matrix<Rational> edge_rays(BigObject curve)
129 {
130 IncidenceMatrix<> sets = curve.give("SETS");
131 Int n = curve.give("N_LEAVES");
132 Matrix<Rational> result(0, n*(n-3)/2 + 2);
133 for (Int s = 0; s < sets.rows(); ++s) {
134 BigObject rcurve("RationalCurve",
135 "SETS", sets.minor(scalar2set(s), All),
136 "N_LEAVES", n,
137 "COEFFS", ones_vector<Rational>(1));
138 Vector<Rational> rray = call_function("matroid_coordinates_from_curve", mlist<Addition>(), rcurve);
139 result /= rray;
140 }
141 return result;
142 }
143
144 /**
145 @brief Computes all ordered lists of k elements in {0,...,n-1}
146 @param Int n The size of the set {0,...,n-1}
147 @param Int k The size of the ordered subsets
148 @return Matrix<Int> All ordered k-sets as a list of row vectors, i.e. a matrix of dimension ( (n choose k) * k!) x k
149 */
ordered_k_choices(Int n,Int k)150 Matrix<Int> ordered_k_choices(Int n, Int k)
151 {
152 Matrix<Int> result(0,k);
153
154 // Compute all k-choices of the set {0,..,n-1}
155 const auto kchoices = all_subsets_of_k(sequence(0, n), k);
156
157 // Compute all permutations on a k-set
158 const auto kperm = all_permutations(k);
159
160 for (const auto& kchoice : kchoices) {
161 Vector<Int> kvec(kchoice);
162 for (auto p = entire(kperm); !p.at_end(); ++p) {
163 result /= permuted(kvec, *p);
164 }
165 }
166
167 return result;
168 }
169
170 /**
171 @brief Takes a matrix and computes the gcd of the absolute values of the maximal minors
172 */
gcd_maxminor(const Matrix<Rational> & map)173 Integer gcd_maxminor(const Matrix<Rational>& map)
174 {
175 const auto r_choices = all_subsets_of_k(sequence(0, map.cols()), map.rows());
176 Integer g = 0;
177 for (const auto& r_choice : r_choices) {
178 g = gcd(g, Integer(det(map.minor(All, r_choice))));
179 }
180 return abs(g);
181 }
182
183 /**
184 @brief This takes a list of cones (in terms of ray indices) and their weights and inserts another cone with given weight. If the new cone already exists in the list, the weight is added
185 */
insert_cone(Vector<Set<Int>> & cones,Vector<Integer> & weights,const Set<Int> & ncone,const Integer & nweight)186 void insert_cone(Vector<Set<Int>>& cones, Vector<Integer>& weights, const Set<Int>& ncone, const Integer& nweight)
187 {
188 Int ncone_index = -1;
189 for (Int c = 0; c < cones.dim(); ++c) {
190 if (ncone == cones[c]) {
191 ncone_index = c; break;
192 }
193 }
194 if (ncone_index == -1) {
195 cones |= ncone;
196 weights |= nweight;
197 } else if (weights.dim() > ncone_index) {
198 weights[ncone_index] += nweight;
199 }
200 }
201
202 /**
203 @brief Checks whether the cone of the positive orthant intersects all of the hyperplanes defined by ev_maps.row(i) = p_i in its interior (i.e. is not contained in one of the half spaces >= pi / <= pi), where p_i = 1,2,... This can be used to check whether a choice of fixed vertices is valid (because the corresponding refinement has to have at least one interior cone for a generic choice of points p_i). In fact, this is equivalent to saying that each row of the matrix has at least one positive entry and that the hyperplanes intersect the orthant in a cone, s.t. for each entry _j there is at least one ray or vertex v s.t. v_j > 0.
204 */
is_valid_choice(const Matrix<Rational> & ev_maps)205 bool is_valid_choice(const Matrix<Rational>& ev_maps)
206 {
207 // Check if all maps have a positive entry.
208 for (Int r = 0; r < ev_maps.rows(); ++r) {
209 bool found_positive = false;
210 for (Int c = 0; c < ev_maps.cols(); ++c) {
211 if (ev_maps(r,c) > 0) {
212 found_positive = true; break;
213 }
214 }
215 if (!found_positive) return false;
216 }
217
218 // Now compute the intersection of all hyperplanes with the positive orthant
219 Matrix<Rational> ineq = unit_matrix<Rational>(ev_maps.cols());
220 ineq = zero_vector<Rational>() | ineq;
221 Matrix<Rational> eq = ev_maps;
222 eq = - Vector<Rational>(sequence(1,ev_maps.rows())) | eq;
223 try {
224 Matrix<Rational> rays = polytope::enumerate_vertices(ineq, eq, false).first;
225 bool found_positive = false;
226 for (Int c = 1; c < rays.cols(); ++c) {
227 for (Int r = 0; r < rays.rows(); ++r) {
228 if (rays(r,c) > 0) {
229 found_positive = true; break;
230 }
231 }
232 if (!found_positive) return false;
233 }
234 }
235 catch(...) {
236 // This might happen, if the system has no solution
237 return false;
238 }
239 return true;
240 }
241
242 /**
243 @brief Computes a subdivision of M_0,n containing H_k(degree) and (possibly) the cycle itself. The function returns a struct containing the subdivision as subobject "subdivision" and the Hurwitz cycle as subobject "cycle", both as BigObject. Optionally one can specify a RationalCurve object representing a ray around which the whole computation is performed locally (the vector is only for default initalization).
244 */
245 template <typename Addition>
hurwitz_computation(Int k,const Vector<Int> & degree,Vector<Rational> points,bool compute_cycle,BigObject local_restriction,bool output_progress)246 HurwitzResult hurwitz_computation(Int k, const Vector<Int>& degree, Vector<Rational> points, bool compute_cycle, BigObject local_restriction, bool output_progress)
247 {
248 // Make points default points ( = 0)
249 if (points.dim() < degree.dim() - 3- k) {
250 points = points | zero_vector<Rational>( degree.dim()-3-k-points.dim());
251 }
252 if (points.dim() > degree.dim() - 3 - k) {
253 points = points.slice(sequence(0,degree.dim()-3-k));
254 }
255
256 Int n = degree.dim();
257 Int big_n = 2*n - k -2;
258 Int big_moduli_dim = big_n * (big_n - 3) / 2;//Affine ambient dimension of the stable maps.
259
260 // Compute M_0,n and extract cones
261 BigObject m0n;
262 Vector<Rational> compare_vector;
263 bool restrict_local = local_restriction.valid();
264
265 if (restrict_local) {
266 m0n = call_function("local_m0n", mlist<Addition>(), local_restriction);
267 compare_vector = call_function("matroid_coordinates_from_curve", mlist<Addition>(), local_restriction);
268 // We need to dehomogenize to make comparison possible.
269 compare_vector = tdehomog_vec(compare_vector);
270 } else {
271 m0n = call_function("m0n", mlist<Addition>(), n);
272 }
273
274 IncidenceMatrix<> mn_cones = m0n.give("MAXIMAL_POLYTOPES");
275 IncidenceMatrix<> mn_restrict;
276 m0n.lookup("LOCAL_RESTRICTION") >> mn_restrict;
277
278 // Create evaluation maps
279 Matrix<Rational> ev_maps(0, big_moduli_dim);
280 Matrix<Rational> rat_degree(n,0);
281 rat_degree |= degree;
282 Vector<Rational> zero_translate(2);
283 for (Int i = n+2; i <= 2*n-2-k; ++i) {
284 BigObject evi = evaluation_map<Addition>(n-2-k, thomog(rat_degree,0,false), i-n-1);
285 Matrix<Rational> evimatrix = evi.give("MATRIX");
286 // We take the representation of the evaluation map on charts 0 and 0.
287 evimatrix = tdehomog_morphism(evimatrix, zero_translate).first;
288 // ... and forget the xR-coordinate, as it is assumed to be always 0.
289 ev_maps /= (evimatrix.row(0).slice(sequence(0, evimatrix.cols()-1)));
290 }
291
292 // Affine ambient dim of m0n
293 Int mn_ambient_dim = n*(n-3)/2;
294 // Will contain the rays/cones of the subdivided M_0,n (with leading coordinates)
295 Matrix<Rational> subdiv_rays(0,mn_ambient_dim);
296 Vector<Set<Int>> subdiv_cones;
297 Vector<Integer> subdiv_weights;
298
299 // Will contain the rays/cones/weights of the Hurwitz cycle
300 Matrix<Rational> cycle_rays(0,mn_ambient_dim);
301 Vector<Set<Int>> cycle_cones;
302 Vector<Integer> cycle_weights;
303
304 // Iterate all cones of M_0,n and compute their refinement as well as the
305 // Hurwitz cycle cones within
306 for (Int mc = 0; mc < mn_cones.rows(); ++mc) {
307 if (output_progress)
308 cout << "Refining cone " << mc << " of " << mn_cones.rows() << endl;
309
310 // Extract the combinatorial type to compute evaluation maps
311 BigObject mc_type = call_function("rational_curve_from_cone", m0n, degree.dim(), mc);
312
313 // This will be a model of the subdivided cone of M_0,n
314 Matrix<Rational> model_rays = unit_matrix<Rational>(degree.dim()-2);
315 Vector<Set<Int>> model_cones; model_cones |= sequence(0, degree.dim()-2);
316 // Translate the local restriction if necessary
317 Vector<Set<Int>> model_local_restrict;
318 if (restrict_local) {
319 Set<Int> single_index_set;
320 Matrix<Rational> erays = edge_rays<Addition>(mc_type);
321 for (Int er = 0; er < erays.rows(); ++er) {
322 if (tdehomog_vec(Vector<Rational>(erays.row(er))) == compare_vector) {
323 single_index_set += er; break;
324 }
325 }
326 model_local_restrict |= single_index_set;
327 }
328
329 BigObject model_complex("Cycle", mlist<Addition>());
330 model_complex.take("VERTICES") << thomog(model_rays);
331 model_complex.take("MAXIMAL_POLYTOPES") << model_cones;
332 if (restrict_local) {
333 model_complex.take("LOCAL_RESTRICTION") << model_local_restrict;
334 }
335
336 // Iterate over all possible ordered choices of (#vert-k)-subsets of nodes
337 Matrix<Int> fix_node_sets = ordered_k_choices(n-2, n-2-k);
338
339 // We save the evaluation matrices for use in the computation
340 // of tropical weights in the Hurwitz cycle
341 Vector<Matrix<Rational> > evmap_list;
342
343 for (Int nchoice = 0 ; nchoice < fix_node_sets.rows(); ++nchoice) {
344 // Compute combinatorial type obtained by adding further ends to chosen nodes
345 BigObject higher_type = insert_leaves(mc_type, fix_node_sets.row(nchoice));
346 // Convert evaluation maps to local basis of rays
347 Matrix<Rational> local_basis = tdehomog(edge_rays<Addition>(higher_type)).minor(All, range_from(1));
348 Matrix<Rational> converted_maps = ev_maps * T(local_basis);
349
350 // Check if this choice of fixed vertices induces some valid Hurwitz type
351 // (in the generic case)
352 if (is_valid_choice(converted_maps)) {
353 evmap_list |= converted_maps;
354 }
355
356 // Now refine along each evaluation map
357 for (Int evmap = 0; evmap < converted_maps.rows(); ++evmap) {
358 // Compute half-space fan induced by the equation ev_i >= / = / <= p_i
359 // Then refine the model cone along this halfspace
360 if (!is_zero(converted_maps.row(evmap))) {
361 // Create homogenized version of evaluation map
362 Vector<Rational> hom_converted_map = converted_maps.row(evmap);
363 // TODO: replace with sum()
364 hom_converted_map = ( - ones_vector<Rational>(hom_converted_map.dim()) * hom_converted_map) | hom_converted_map;
365
366 BigObject evi_halfspace = halfspace_subdivision<Addition>(points[evmap],hom_converted_map,1);
367 model_complex = refinement(model_complex, evi_halfspace, false,false,false,true,false).complex;
368 }
369 } //END iterate evaluation maps
370 } //END iterate choices of fixed nodes
371
372 // If we are actually computing the Hurwitz cycle, we take the evalutation map
373 // corresponding to each choice of vertex placement. We then compute the k-cones
374 // in the subdivision on which this map is (p_1,..,p_r) and add the gcd of the maximal minors of the
375 // matrix as tropical weight to these cones
376 IncidenceMatrix<> model_hurwitz_cones;
377 Vector<Integer> model_hurwitz_weights;
378 Matrix<Rational> model_hurwitz_rays;
379 Vector<Set<Int>> model_hurwitz_local;
380 if (compute_cycle) {
381 BigObject skeleton = call_function("skeleton_complex", model_complex, k, false);
382 // We go through all dimension - k cones of the subdivision
383 Matrix<Rational> k_rays = skeleton.give("VERTICES");
384 k_rays = tdehomog(k_rays);
385 IncidenceMatrix<> k_cones = skeleton.give("MAXIMAL_POLYTOPES");
386 model_hurwitz_weights = zero_vector<Integer>(k_cones.rows());
387 Set<Int> non_zero_cones;
388 for (Int m = 0; m < evmap_list.dim(); ++m) {
389 // Compute gcd of max-minors
390 Integer g = gcd_maxminor(evmap_list[m]);
391 for (Int c = 0; c < k_cones.rows(); ++c) {
392 // Check if ev maps to the p_i on this cone (rays have to be mapped to 0!)
393 bool maps_to_pi = true;
394 for (const Int c_elem : k_cones.row(c)) {
395 Vector<Rational> cmp_vector =
396 k_rays(c_elem, 0) == 1 ? points : zero_vector<Rational>(points.dim());
397 if (evmap_list[m] * k_rays.row(c_elem).slice(range_from(1)) != cmp_vector) {
398 maps_to_pi = false; break;
399 }
400 }
401 if (maps_to_pi) {
402 model_hurwitz_weights[c] += g;
403 if(g != 0) non_zero_cones += c;
404 }
405 }
406 } //END iterate evaluation maps
407 // Identify cones with non-zero weight and the rays they use
408 Set<Int> used_rays = accumulate(rows(k_cones.minor(non_zero_cones,All)),operations::add());
409 model_hurwitz_rays = Matrix<Rational>(k_rays.minor(used_rays,All));
410 model_hurwitz_cones = IncidenceMatrix<>(k_cones).minor(non_zero_cones,used_rays);
411 model_hurwitz_weights = model_hurwitz_weights.slice(non_zero_cones);
412 } //END compute hurwitz weights
413
414 // Finally convert the model cones back to M_0,n-coordinates
415
416 Matrix<Rational> model_subdiv_rays = model_complex.give("VERTICES");
417 model_subdiv_rays = tdehomog(model_subdiv_rays);
418 IncidenceMatrix<> model_subdiv_cones = model_complex.give("MAXIMAL_POLYTOPES");
419 Vector<Integer> model_subdiv_weights = ones_vector<Integer>(model_subdiv_cones.rows());
420 // If we want to compute the Hurwitz cycle, we take the k-cones instead
421
422 for (Int i = 0; i <= 1; ++i) {
423 if (i == 1 && !compute_cycle) break;
424 Matrix<Rational> rays_to_convert = i==0 ? model_subdiv_rays : model_hurwitz_rays;
425 IncidenceMatrix<> cones_to_convert = i == 0 ? model_subdiv_cones: model_hurwitz_cones;
426 Vector<Integer> weights_to_convert = i == 0 ? model_subdiv_weights : model_hurwitz_weights;
427
428 // First convert the rays back
429
430 Matrix<Rational> model_conv_rays =
431 rays_to_convert.col(0) |
432 (rays_to_convert.minor(All, range_from(1)) *
433 tdehomog(edge_rays<Addition>(mc_type)).minor(All, range_from(1)));
434 Vector<Int> model_rays_perm = insert_rays(i == 0? subdiv_rays : cycle_rays, model_conv_rays,false);
435 Map<Int, Int> ray_index_map;
436 for (Int mrp = 0; mrp < model_rays_perm.dim(); ++mrp) {
437 ray_index_map[mrp] = model_rays_perm[mrp];
438 }
439 // Then use the above index list to transform the cones
440 for (Int msc = 0; msc < cones_to_convert.rows(); ++msc) {
441 insert_cone(i == 0 ? subdiv_cones : cycle_cones,
442 i == 0 ? subdiv_weights : cycle_weights,
443 Set<Int>{ ray_index_map.map(cones_to_convert.row(msc)) },
444 weights_to_convert[msc]);
445 }
446 }
447
448 } //END iterate cones of M_0,n
449
450 // Finally find the localizing ray in both complexes
451 Set<Int> subdiv_local;
452 Set<Int> cycle_local;
453 if (restrict_local) {
454 for (Int sr = 0; sr < subdiv_rays.rows(); ++sr) {
455 if (subdiv_rays.row(sr) == compare_vector) {
456 subdiv_local += sr; break;
457 }
458 }
459 for (Int cr = 0; cr < cycle_rays.rows(); ++cr) {
460 if (cycle_rays.row(cr) == compare_vector) {
461 cycle_local += cr; break;
462 }
463 }
464
465 // Find vertex
466 for (Int sr = 0; sr < subdiv_rays.rows(); ++sr) {
467 if (subdiv_rays.row(sr) == unit_vector<Rational>(subdiv_rays.cols(),0)) {
468 subdiv_local += sr; break;
469 }
470 }
471 for (Int cr = 0; cr < cycle_rays.rows(); ++cr) {
472 if (cycle_rays.row(cr) == unit_vector<Rational>(cycle_rays.cols(),0)) {
473 cycle_local += cr; break;
474 }
475 }
476 } //END restrict
477
478 BigObject result("Cycle", mlist<Addition>(),
479 "VERTICES", thomog(subdiv_rays),
480 "MAXIMAL_POLYTOPES", subdiv_cones,
481 "WEIGHTS", subdiv_weights);
482 if (restrict_local)
483 result = call_function("local_restrict", result, IncidenceMatrix<>(1, subdiv_local.back()+1, &subdiv_local));
484
485 BigObject cycle("Cycle", mlist<Addition>(),
486 "VERTICES", thomog(cycle_rays),
487 "MAXIMAL_POLYTOPES", cycle_cones,
488 "WEIGHTS", cycle_weights);
489 if (restrict_local)
490 cycle = call_function("local_restrict", cycle, IncidenceMatrix<>(1, cycle_local.back()+1, &cycle_local));
491
492 return { result, cycle };
493 }
494
495 // Documentation see perl wrapper
496 template <typename Addition>
hurwitz_subdivision(Int k,const Vector<Int> & degree,const Vector<Rational> & points,OptionSet options)497 BigObject hurwitz_subdivision(Int k, const Vector<Int>& degree, const Vector<Rational>& points, OptionSet options)
498 {
499 return hurwitz_computation<Addition>(k,degree, points, false, BigObject(), options["Verbose"]).subdivision;
500 }
501
502 // Documentation see perl wrapper
503 template <typename Addition>
hurwitz_cycle(Int k,const Vector<Int> & degree,const Vector<Rational> & points,OptionSet options)504 BigObject hurwitz_cycle(Int k, const Vector<Int>& degree, const Vector<Rational>& points, OptionSet options)
505 {
506 return hurwitz_computation<Addition>(k, degree, points, true, BigObject(), options["Verbose"]).cycle;
507 }
508
509 // Documentation see perl wrapper
510 template <typename Addition>
hurwitz_pair(Int k,const Vector<Int> & degree,const Vector<Rational> & points,OptionSet options)511 ListReturn hurwitz_pair(Int k, const Vector<Int>& degree, const Vector<Rational>& points, OptionSet options)
512 {
513 const HurwitzResult r = hurwitz_computation<Addition>(k, degree, points, true, BigObject(), options["Verbose"]);
514 ListReturn l;
515 l << r.subdivision;
516 l << r.cycle;
517 return l;
518 }
519
520 // Documentation see perl wrapper
521 template <typename Addition>
hurwitz_pair_local(Int k,const Vector<Int> & degree,BigObject local_restriction,OptionSet options)522 ListReturn hurwitz_pair_local(Int k, const Vector<Int>& degree, BigObject local_restriction, OptionSet options)
523 {
524 HurwitzResult r = hurwitz_computation<Addition>(k, degree, Vector<Rational>(), true, local_restriction, options["Verbose"]);
525 ListReturn l;
526 l << r.subdivision;
527 l << r.cycle;
528 return l;
529 }
530
531 UserFunctionTemplate4perl("# @category Hurwitz cycles"
532 "# This function computes a subdivision of M_0,n containing the Hurwitz cycle"
533 "# H_k(x), x = (x_1,...,x_n) as a subfan. If k = n-4, this subdivision is the unique"
534 "# coarsest subdivision fulfilling this property"
535 "# @param Int k The dimension of the Hurwitz cycle, i.e. the number of moving vertices"
536 "# @param Vector<Int> degree The degree x. Should add up to 0"
537 "# @param Vector<Rational> points Optional. Should have length n-3-k. Gives the images of "
538 "# the fixed vertices (besides the first one, which always goes to 0) as elements of R."
539 "# If not given, all fixed vertices are mapped to 0"
540 "# and the function computes the subdivision of M_0,n containing the recession fan of H_k(x)"
541 "# @option Bool Verbose If true, the function outputs some progress information. True by default."
542 "# @tparam Addition Min or Max, where the coordinates live."
543 "# @return Cycle A subdivision of M_0,n",
544 "hurwitz_subdivision<Addition>($,Vector<Int>;Vector<Rational> = new Vector<Rational>(),{Verbose=>1})");
545
546 UserFunctionTemplate4perl("# @category Hurwitz cycles"
547 "# This function computes the Hurwitz cycle H_k(x), x = (x_1,...,x_n)"
548 "# @param Int k The dimension of the Hurwitz cycle, i.e. the number of moving vertices"
549 "# @param Vector<Int> degree The degree x. Should add up to 0"
550 "# @param Vector<Rational> points Optional. Should have length n-3-k. Gives the images of "
551 "# the fixed vertices (besides 0). If not given all fixed vertices are mapped to 0"
552 "# and the function computes the recession fan of H_k(x)"
553 "# @option Bool Verbose If true, the function outputs some progress information. True by default."
554 "# @tparam Addition Min or Max, where the coordinates live."
555 "# @return Cycle<Addition> H_k(x), in homogeneous coordinates",
556 "hurwitz_cycle<Addition>($,Vector<Int>;Vector<Rational> = new Vector<Rational>(),{Verbose=>1})");
557
558 UserFunctionTemplate4perl("# @category Hurwitz cycles"
559 "# This function computes hurwitz_subdivision and hurwitz_cycle at the same time, "
560 "# returning the result in an array"
561 "# @param Int k The dimension of the Hurwitz cycle, i.e. the number of moving vertices"
562 "# @param Vector<Int> degree The degree x. Should add up to 0"
563 "# @param Vector<Rational> points Optional. Should have length n-3-k. Gives the images of "
564 "# the fixed vertices (besides 0). If not given all fixed vertices are mapped to 0"
565 "# and the function computes the subdivision of M_0,n containing the recession fan of H_k(x)"
566 "# @option Bool Verbose If true, the function outputs some progress information. True by default."
567 "# @tparam Addition Min or Max, where the coordinates live."
568 "# @return List( Cycle subdivision of M_0,n, Cycle Hurwitz cycle )",
569 "hurwitz_pair<Addition>($,Vector<Int>;Vector<Rational> = new Vector<Rational>(),{Verbose=>1})");
570
571 UserFunctionTemplate4perl("# @category Hurwitz cycles"
572 "# Does the same as hurwitz_pair, except that no points are given and the user can give a "
573 "# RationalCurve object representing a ray. If given, the computation"
574 "# will be performed locally around the ray."
575 "# @param Int k"
576 "# @param Vector<Int> degree"
577 "# @option Bool Verbose If true, the function outputs some progress information. True by default."
578 "# @tparam Addition Min or Max, where the coordinates live."
579 "# @param RationalCurve local_curve",
580 "hurwitz_pair_local<Addition>($,Vector<Int>,RationalCurve,{Verbose=>1})");
581
582 UserFunction4perl("# @category Abstract rational curves"
583 "# Takes a RationalCurve and a list of node indices. Then inserts additional "
584 "# leaves (starting from N_LEAVES+1) at these nodes and returns the resulting "
585 "# RationalCurve object"
586 "# @param RationalCurve curve A RationalCurve object"
587 "# @param Vector<Int> nodes A list of node indices of the curve",
588 &insert_leaves, "insert_leaves(RationalCurve,$)");
589 } }
590