1 /* TriangulationWithTOPCOM.cpp -- Compute a triangulation using TOPCOM
2 
3    Copyright 2006 Matthias Koeppe
4    Derived from the TOPCOM source files points2placingtriang.cc, ComputeTriangs.cc
5      which are copyright 1999 Joerg Rambau
6 
7    This file is part of LattE.
8 
9    LattE is free software; you can redistribute it and/or modify it
10    under the terms of the version 2 of the GNU General Public License
11    as published by the Free Software Foundation.
12 
13    LattE is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with LattE; if not, write to the Free Software Foundation,
20    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 */
22 
23 #include <list>
24 #include <iostream>
25 #include "config.h"
26 #include "triangulation/TriangulationWithTOPCOM.h"
27 #include "latte_gmp.h"
28 #include "latte_system.h"
29 #ifdef HAVE_TOPCOM_LIB
30 #include <Matrix.hh>
31 #include <PointConfiguration.hh>
32 #include <PlacingTriang.hh>
33 #include <Symmetry.hh>
34 #include <SymmetricBFS.hh>
35 #endif
36 
37 using namespace std;
38 
39 static vector<listVector *>
ray_array(listCone * cone)40 ray_array(listCone *cone)
41 {
42   int num_rays = lengthListVector(cone->rays);
43   vector<listVector *> rays(num_rays);
44   int j;
45   listVector *ray;
46   for (j = 0, ray = cone->rays; ray!=NULL; j++, ray = ray->rest)
47     rays[j] = ray;
48   return rays;
49 }
50 
51 
52 //
53 // Functions using the TOPCOM library.
54 //
55 #ifdef HAVE_TOPCOM_LIB
56 static void
triangulation_to_cones(const SimplicialComplex & sc,listCone * cone,ConeConsumer & consumer)57 triangulation_to_cones(const SimplicialComplex &sc,
58 		       listCone *cone,
59 		       ConeConsumer &consumer)
60 {
61   // Copy rays into an array, so we can index them.
62   vector<listVector *> rays = ray_array(cone);
63   // Iterate through simplices and collect them.
64   for (SimplicialComplex::const_iterator i = sc.begin(); i!=sc.end(); ++i) {
65     const Simplex &simplex = *i;
66     listCone *c = createListCone();
67     c->vertex = new Vertex(*cone->vertex);
68     for (Simplex::const_iterator j = simplex.begin(); j!=simplex.end(); ++j) {
69       size_t index = *j;
70       c->rays = new listVector(rays[index]->first, c->rays);
71     }
72     consumer.ConsumeCone(c);
73   }
74 }
75 
76 static PointConfiguration
cone_to_point_configuration(listCone * cone,int numOfVars)77 cone_to_point_configuration(listCone *cone, int numOfVars)
78 {
79   int num_rays = lengthListVector(cone->rays);
80   Matrix matrix(numOfVars, num_rays);
81   size_type i, j;
82   listVector *ray;
83   for (j = 0, ray = cone->rays; ray!=NULL; j++, ray = ray->rest) {
84     for (i = 0; i<numOfVars; i++) {
85       mpz_class mpz = convert_ZZ_to_mpz(ray->first[i]);
86       matrix(i, j) = Rational(mpz.get_mpz_t());
87     }
88   }
89   PointConfiguration points(matrix);
90   return points;
91 }
92 
93 void
triangulate_cone_with_TOPCOM(listCone * cone,int numOfVars,ConeConsumer & consumer)94 triangulate_cone_with_TOPCOM(listCone *cone, int numOfVars, ConeConsumer &consumer)
95 {
96   PointConfiguration points = cone_to_point_configuration(cone, numOfVars);
97   if (points.rank() > points.no()) {
98     std::cerr << "rank must not be larger than no of points." << std::endl;
99     exit(1);
100   }
101   Chirotope chiro(points, /*preprocess:*/ false);
102   PlacingTriang triang(chiro);
103   //  std::cout << "Triangulation: " << triang << std::endl;
104   triangulation_to_cones(triang, cone, consumer);
105 }
106 #endif
107 
108 
109 //
110 // Functions using the TOPCOM binaries
111 //
112 
113 #ifdef HAVE_TOPCOM_BIN
114 
115 static void
read_TOPCOM_triangulation(istream & in,listCone * cone,ConeConsumer & consumer)116 read_TOPCOM_triangulation(istream &in,
117 			  listCone *cone,
118 			  ConeConsumer &consumer)
119 {
120   // Copy rays into an array, so we can index them.
121   vector<listVector *> rays = ray_array(cone);
122   // Read a triangulation in the TOPCOM format:
123   // T[1]:={{0,1,2,3,4,5,6,8},{0,1,2,3,4,5,7,8}};
124   char c;
125   // Find and consume left brace of triangulation.
126   do { in.get(c); } while (in.good() && c != '{');
127   bool result = false;
128   do {
129     // Consume left brace of simplex.
130     in.get(c);
131     if (!(in.good() && c == '{')) break;
132     listCone *simp = createListCone();
133     simp->vertex = new Vertex(*cone->vertex);
134     while (in.good() && in.peek()!='}') {
135       int index;
136       in >> index;
137       simp->rays = new listVector(rays[index]->first, simp->rays);
138       // Skip the ',' of simplex.
139       if (in.peek()==',') in.get(c);
140     }
141     consumer.ConsumeCone(simp);
142     if (!in.good()) break;
143     // Consume the '}' of simplex.
144     in.get(c);
145     // Expect ',' or '}' of triangulation.
146     in.get(c);
147     if (!in.good()) break;
148     if (c == '}') return;
149   } while (c == ',');
150   // Error situation:
151   cerr << "Failed to read triangulation from TOPCOM output" << endl;
152   exit(1);
153 }
154 
155 static void
write_TOPCOM_point_configuration(ostream & out,listCone * cone,int numOfVars)156 write_TOPCOM_point_configuration(ostream &out,
157 				 listCone *cone, int numOfVars)
158 {
159   out << "[";
160   listVector *ray;
161   for (ray = cone->rays; ray!=NULL; ray=ray->rest) {
162     out << "[";
163     int i;
164     out << ray->first[0];
165     for (i = 1; i<numOfVars; i++)
166       out << ", " << ray->first[i];
167     out << "]";
168     if (ray->rest != NULL)
169       out << "," << endl;
170   }
171   out << "]" << endl;
172 }
173 
174 #ifndef HAVE_TOPCOM_LIB
175 // Alternative implementation if the TOPCOM library cannot be used.
176 void
triangulate_cone_with_TOPCOM(listCone * cone,int numOfVars,ConeConsumer & consumer)177 triangulate_cone_with_TOPCOM(listCone *cone, int numOfVars, ConeConsumer &consumer)
178 {
179   string topcom_input_file_name = temporary_file_name("topcom_input");
180   string topcom_output_file_name = temporary_file_name("topcom_output");
181   {
182     ofstream topcom_input(topcom_input_file_name.c_str());
183     write_TOPCOM_point_configuration(topcom_input, cone, numOfVars);
184   }
185   system_with_error_check(TOPCOM_POINTS2PLACINGTRIANG " < " + topcom_input_file_name
186 			  + " > " + topcom_output_file_name);
187   ifstream topcom_output(topcom_output_file_name.c_str());
188   read_TOPCOM_triangulation(topcom_output, cone, consumer);
189 }
190 #endif
191 
192 list<listCone *>
all_triangulations_of_cone_with_TOPCOM(listCone * cone,int numOfVars)193 all_triangulations_of_cone_with_TOPCOM(listCone *cone, int numOfVars)
194 {
195   string topcom_input_file_name = temporary_file_name("topcom_input");
196   string topcom_output_file_name = temporary_file_name("topcom_output");
197   {
198     ofstream topcom_input(topcom_input_file_name.c_str());
199     write_TOPCOM_point_configuration(topcom_input, cone, numOfVars);
200   }
201   system_with_error_check(TOPCOM_POINTS2TRIANGS " < " + topcom_input_file_name
202 			  + " > " + topcom_output_file_name);
203   ifstream topcom_output(topcom_output_file_name.c_str());
204   list<listCone *> triangulations;
205   while (topcom_output.good()) {
206     CollectingConeConsumer ccc;
207     read_TOPCOM_triangulation(topcom_output, cone, ccc);
208     listCone *triangulation = ccc.Collected_Cones;
209     if (!triangulation) break;
210     triangulations.push_front(triangulation);
211   }
212   return triangulations;
213 }
214 
215 #endif
216