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 
18 #include "polymake/client.h"
19 #include "polymake/topaz/connected_sum.h"
20 
21 namespace polymake { namespace topaz {
22 
connected_sum_complex(BigObject p_in1,BigObject p_in2,const Int f1,const Int f2,OptionSet options)23 BigObject connected_sum_complex(BigObject p_in1, BigObject p_in2, const Int f1, const Int f2, OptionSet options)
24 {
25    const bool no_labels=options["no_labels"];
26    const Array<Set<Int>> C1 = p_in1.give("FACETS");
27    Array<std::string> L1;  // connected_sum interprets empty labels as no labels
28    if (!no_labels) p_in1.give("VERTEX_LABELS") >> L1;
29 
30    const Array<Set<Int>> C2 = p_in2.give("FACETS");
31    Array<std::string> L2;
32    if (!no_labels) p_in2.give("VERTEX_LABELS") >> L2;
33 
34    if (f1 >= C1.size()) {
35       std::ostringstream e;
36       e << "connected_sum: " << f1 << " is not a facet.";
37       throw std::runtime_error(e.str());
38    }
39 
40    if (f2 >= C2.size()) {
41       std::ostringstream e;
42       e << "connected_sum: " << f2 << " is not a facet.";
43       throw std::runtime_error(e.str());
44    }
45 
46    if (C1[f1].size() != C2[f2].size()) {
47       std::ostringstream e;
48       e << "connected_sum: " << f1 << " and " << f2
49         << " do not have the same dimension.";
50       throw std::runtime_error(e.str());
51    }
52 
53 
54    // set permutation: connected_sum interprets empty permutation as trivial
55    hash_map<Int, Int> Perm;
56 
57    BigObject p_out("SimplicialComplex");
58 
59    // testing P
60    Array<Int> P;
61    if (options["permutation"]>>P) {
62 
63       Set<Int> V;
64       accumulate_in(entire(P), operations::add(), V);
65 
66       if (incl(V, C1[f1]) != 0) {
67          std::ostringstream e;
68          e << "connected_sum: Specified permutation does not match facets " << f1 << ".";
69          throw std::runtime_error(e.str());
70       }
71 
72       auto v = C1[f1].begin();
73       for (auto p = entire(P); !p.at_end(); ++p, ++v)
74          Perm[*v] = *p;
75       p_out.set_description() << "Connected sum of " << p_in1.name() << ", using facet " << f1
76                               << ",\nand " << p_in2.name() << ", using facet " << f2 << "." << endl
77                               << "The vertices of facet " << f2 << " of " << p_in2.name() << " are permuted " << P << "."<<endl;
78    } else {
79       p_out.set_description() << "Connected sum of " << p_in1.name() << ", using facet " << f1
80                               << ",\nand " << p_in2.name() << ", using facet " << f2 << "." << endl;
81    }
82    p_out.take("FACETS") << as_array(connected_sum(C1, C2, f1, f2, L1, L2, Perm));
83 
84    if (!no_labels)
85       p_out.take("VERTEX_LABELS") << L1;
86    return p_out;
87 }
88 
89 UserFunction4perl("# @category Producing a new simplicial complex from others\n"
90                   "# Compute the __connected sum__ of two complexes.\n"
91                   "# "
92                   "# Parameters //f_1// and //f_2// specify which facet of the first and second complex correspondingly are glued together.\n"
93                   "# Default is the 0-th facet of both.\n"
94                   "# "
95                   "# The vertices in the selected facets are identified with each other according to their order in the facet\n"
96                   "# (that is, in icreasing index order). The glueing facet iteself is not included in the connected sum.\n"
97                   "#  The option //permutation// allows one to get an alternative identification. It should specify a\n"
98                   "# permutation of the vertices of the second facet.\n"
99                   "# "
100                   "# The vertices of the new complex get the original labels with ''_1'' or ''_2'' appended, according to the input complex\n"
101                   "#  they came from.  If you set the //no_labels// flag, the label generation will be omitted.\n"
102                   "# @param SimplicialComplex complex1"
103                   "# @param SimplicialComplex complex2"
104                   "# @param Int f1 default: 0"
105                   "# @param Int f2 default: 0"
106                   "# @option Array<Int> permutation"
107                   "# @option Bool no_labels"
108                   "# @return SimplicialComplex"
109                   "# @example Glueing together two tori to make a genus 2 double torus, rotating the second one clockwise:"
110                   "# > $cs = connected_sum(torus(),torus(),permutation=>[1,2,0]);"
111                   "# > print $cs->SURFACE.','.$cs->GENUS;"
112                   "# | 1,2",
113                   &connected_sum_complex,"connected_sum(SimplicialComplex SimplicialComplex; $=0,$=0, { permutation => undef, no_labels => 0 })");
114 } }
115 
116 // Local Variables:
117 // mode:C++
118 // c-basic-offset:3
119 // indent-tabs-mode:nil
120 // End:
121