This file is indexed.

/usr/include/polymake/tropical/make_complex.h is in libpolymake-dev-common 3.2r2-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/*
	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
	of the License, or (at your option) any later version.

	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.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor,
	Boston, MA  02110-1301, USA.

	---
	Copyright (C) 2011 - 2015, Simon Hampe <simon.hampe@googlemail.com>

	Contains a function to make an arbitrary list of polyhedra into a polyhedral complex.
	*/

#ifndef POLYMAKE_ATINT_MAKE_COMPLEX_H
#define POLYMAKE_ATINT_MAKE_COMPLEX_H

#include "polymake/client.h"
#include "polymake/Rational.h"
#include "polymake/Matrix.h"
#include "polymake/Vector.h"
#include "polymake/PowerSet.h"
#include "polymake/linalg.h"
#include "polymake/IncidenceMatrix.h"
#include "polymake/tropical/thomog.h"
#include "polymake/tropical/solver_def.h"

namespace polymake { namespace tropical {

	/*
	 * @brief Takes a collection of weighted polyhedra of the same dimension and refines them in such a way that
	 * they form a weighted polyhedral complex. Weights of cells lying one over the other add up.
	 * @param Matrix<Rational> rays A matrix of rays in tropical projective coordinates and with leading coordinate.
	 * @param Vector<Set<int> > cones A list of cells in terms of the rays.
	 * @oaram Vector<Integer> weights The i-th element is the weight of the i-th cone.
	 * @return Cycle A weighted complex, whose support is the union of the given cones.
	 *
	 */
	template <typename Addition>
	perl::Object make_complex(Matrix<Rational> rays, Vector<Set<int> > max_cones, Vector<Integer> weights) {
		solver<Rational> sv;
		rays = tdehomog(rays);
		//First we compute all the H-representations of the cones
		Vector<Matrix<Rational> > inequalities(max_cones.dim());
		Vector<Matrix<Rational> > equalities(max_cones.dim());
		for(int c = 0; c < max_cones.dim(); c++) {
			//To make computations come out right, we always have to add a zero in front
			std::pair<Matrix<Rational>, Matrix<Rational> > fanEqs =
				sv.enumerate_facets(zero_vector<Rational>() | rays.minor(max_cones[c],All), Matrix<Rational>(0,rays.cols()+1), false,false);
			inequalities[c] = fanEqs.first;
			equalities[c] = fanEqs.second;
		}
		//Compute the dimension
		int dimension = rays.cols() - equalities[0].rows() - 1;

		//The following matrix marks pairs of cones (i,j) that don't need to be made compatible since they already are
		//More precisely: a value of true at position (i,j), i < j means that cone i and cone j are compatible. A value of false or
		// any value on or below the diagonal carries no information
		Matrix<bool> markedPairs(max_cones.dim(), max_cones.dim());

		//The following value indicates that new cones have been created through refinement 
		bool created;
		//The following values indicate that during an instance of the for(i,j)-loop below, 
		//the cone i and/or j has been removed and replaced by other cones. Note that here
		// assigning a different weight does count as "new"
		//     bool replacedI = false;
		//     bool replacedJ = false;

		//We go through all cone pairs i < j and check if we need to refine anything. As soon as we actually made some changes, we start all over
		do {
			created = false;
			for(int i = 0; i < max_cones.dim() -1 && !created; i++) {
				for(int j = i+1; j < max_cones.dim() && !created;j++) {
					//replacedI = false; replacedJ = false;
					//We only intersect non-marked pairs
					if(!markedPairs[i][j]) {
						//Compute an irredundant H-rep of the intersection of cones i and j
						Matrix<Rational> isIneq = inequalities[i]/inequalities[j];
						Matrix<Rational> isEq = equalities[i] / equalities[j];
						Matrix<Rational> isMatrix = isIneq / isEq;

						std::pair<Bitset,Bitset> isection = sv.canonicalize(isIneq,isEq,1);

						int isDimension = isMatrix.cols() - isection.second.size() - 2; 

						//If the dimension is < 0 (this can only occur in the homog. case), then the two
						//cells don't intersect at all and we don't need to refine
						if(isDimension < 0) {
							continue;
						}

						//This set contains the indices in isMatrix of equations coming from i
						Set<int> IIndices = sequence(0,inequalities[i].rows()) +
							sequence(isIneq.rows(),equalities[i].rows());
						//We now put together the equations for the intersection, such that the equations from i
						//come first
						//Note: If the intersection is full-dimensional, we don't need to refine along the equalities
						Matrix<Rational> hsEquations = isMatrix.minor(Set<int>(isection.first) * IIndices,All);
						if(isDimension < dimension) hsEquations /= isMatrix.minor(Set<int>(isection.second) * IIndices,All);
						int equationsFromI = hsEquations.rows();
						hsEquations /= isMatrix.minor(Set<int>(isection.first) - IIndices,All);
						if(isDimension < dimension) hsEquations /= isMatrix.minor(Set<int>(isection.second) - IIndices,All);

						//These variables remember the refinements of i and j (as indices in max_cones)
						Set<int> newconesI, newconesJ;	

						for(int coneindex = i; coneindex <= j; coneindex += (j-i)) {
							//First we have to determine the relevant sign choices. We only want to change
							//the signs of equations NOT coming from the cone we currently refine
							//A sign choice's semantics is that x is in signChoices[s], iff the equation at index
							//s in relevantEquations has sign +1, otherwise it has sign -1
							Matrix<Rational> relevantEquations;
							if(coneindex == j) { 
								relevantEquations = hsEquations.minor(sequence(0,equationsFromI),All);
							}
							else {
								relevantEquations = hsEquations.minor(~sequence(0,equationsFromI),All);
							}
							Array<Set<int>> signChoices{ all_subsets(sequence(0, relevantEquations.rows())) };

							for(int s = 0; s < signChoices.size(); s++) {
								//If the intersection is full-dimensional and the signs are all +1's, then we
								//only compute this intersection for coneindex == i
								if(isDimension == dimension && signChoices[s].size() == relevantEquations.rows() && coneindex == j) {
									continue;
								}

								//Compute intersection of coneindex with current sign choice

								Matrix<Rational> refIneqs = relevantEquations.minor(signChoices[s],All);
								refIneqs /= (-relevantEquations.minor(~signChoices[s],All));	

								Matrix<Rational> refineIneqs = inequalities[coneindex] / refIneqs;
								try {
									Matrix<Rational> ref = sv.enumerate_vertices(
											refineIneqs.minor(All,~scalar2set(0)),
											equalities[coneindex].minor(All,~scalar2set(0)),false,true).first;
									//If the refinement is full-dimensional, we get a new cone 
									if(rank(ref) - 1 == dimension) {
										//First we canonicalize the directional rays
										for(int rw = 0; rw < ref.rows(); rw++) {
											if(ref(rw,0) == 0) {
												for(int cl = 0; cl < ref.cols();cl++) {
													if(ref(rw,cl) != 0) {
														ref.row(rw) /= abs(ref(rw,cl));
														break;
													}
												}
											}
										}

										//Add as new cone
										//Go through all rays and check if they already exist
										//Assign appropriate indices
										Set<int> coneRays;
										int noOfRays = rays.rows();
										for(int nr = 0; nr < ref.rows(); nr++) {
											for(int r = 0; r < noOfRays; r++) {
												if(rays.row(r) == ref.row(nr)) {
													coneRays += r;
													break;
												}
												if(r == noOfRays-1) {
													rays /= ref.row(nr);
													int newrayindex = rays.rows()-1;
													coneRays += newrayindex;
												}
											}
										}

										//We have to check for doubles: If i fulfills one of the relevant equations with
										//equality, we can change its sign and still get the same refinement cone
										bool isDouble = false;
										for(Entire<Set<int> >::iterator existing = entire(coneindex == i? newconesI : newconesJ); !existing.at_end(); existing++) {
											if(max_cones[*existing] == coneRays) {
												isDouble = true; break;
											}
										}
										if(isDouble) continue;

										//Add the cone
										max_cones |= coneRays;
										int newconeindex = max_cones.dim()-1;
										if(coneindex == i) newconesI += newconeindex;
										else newconesJ += newconeindex;

										//Weight is the weight of coneindex (or the sum of both, if s is everything)
										weights |= (isDimension < dimension || 
												signChoices[s].size() < relevantEquations.rows()? 
												weights[coneindex] : weights[i] + weights[j]);


										inequalities |= (inequalities[coneindex] / refIneqs);
										equalities |= equalities[coneindex];
										markedPairs |= Vector<bool>(markedPairs.rows());
										markedPairs /= Vector<bool>(markedPairs.cols());		
									} //END if refDimension = dimension
								}
								catch(...) {
								}
							}//END iterate sign choices
						}//END iterate i and j

						//Now if we did create anything new, we remove i and/or j
						//(depending on whether any proper refinement of each cone was created)
						//We only set 'created' to true, if at least one of i and j has 
						//been replaced by at least two cones.
						//If both have been replaced by a single cone (i.e. by themselves),
						//we throw out the new cones instead of the old ones
						//(Except, if the intersection is full-dimensional. In this case i and j agree
						// and they are replaced by the single new cone with weight the sum of their weights)
						if(newconesI.size() + newconesJ.size() > 0) {


							created = true;//newconesI.size() >= 2 || newconesJ.size() >= 2;
							//Will contain the indices of cones to be marked compatible
							Vector<int> markIndices;
							//Will contain the indices of cones to be removed
							Set<int> removedIndices;


							//Find out indices to be marked and removed:

							//If the cones intersect in full dimension, then we keep the new cones in any case
							//and discard the old ones
							if(isDimension == dimension) {
								removedIndices += i; removedIndices += j;
								markIndices |= Vector<int>(newconesI);
								markIndices |= Vector<int>(newconesJ);
								//replacedI = replacedJ = true;
							}
							else {
								//Otherwise we discard the old cones iff they have been refined by at least 2 cones
								if(newconesI.size() >= 2) {
									markIndices |= Vector<int>(newconesI);
									removedIndices += i;
									//replacedI = true;
								}
								else {
									markIndices |= i;
									removedIndices += newconesI;
								}		  

								if(newconesJ.size() >= 2) {
									markIndices |= Vector<int>(newconesJ);
									removedIndices += j;
									//replacedJ = true;
								}
								else {
									markIndices |= j;
									removedIndices += newconesJ;
								}
							}

							// 		for(int coneindex = i; coneindex <= j; coneindex += (j-i)) {
							// 		  Set<int> st = coneindex == i? newconesI : newconesJ;
							// 		  for(Entire<Set<int> >::iterator ni = entire(st); !ni.at_end(); ni++) {
							// 		    if(max_cones[*ni].contains(3) && max_cones[*ni].contains(8) && !removedIndices.contains(*ni)) {
							// 		      for(int k = 0; k < *ni; k++) {
							// 			if(max_cones[k] == max_cones[*ni]) {
							// 			}
							// 		      }
							// 		    }
							// 		  }
							// 		}


							for(int v = 0; v < markIndices.dim()-1; v++) {
								for(int w = v+1; w < markIndices.dim(); w++) {
									markedPairs(markIndices[v],markIndices[w]) = true;
								}
							}


							//Now remove them
							max_cones = max_cones.slice(~removedIndices);
							weights = weights.slice(~removedIndices);
							inequalities = inequalities.slice(~removedIndices);
							equalities = equalities.slice(~removedIndices);
							markedPairs = markedPairs.minor(~removedIndices,~removedIndices);
						}


					}//END refine i and j
				}//END iterate j
			}//END iterate i
			//       for(int k = 0; k < max_cones.dim();k++) {
			// 	 for(int l = k+1; l < max_cones.dim(); l++) {
			// 	    if(max_cones[k] == max_cones[l] && max_cones[k].contains(3) && max_cones[k].contains(8)) {
			// 	    }
			// 	 }
			//       }
		} while(created);

		perl::Object result(perl::ObjectType::construct<Addition>("Cycle"));
		result.take("VERTICES") << thomog(rays);
		result.take("MAXIMAL_POLYTOPES") << max_cones;
		result.take("WEIGHTS") << weights;
		return result;
	}


}}


#endif