1 #include "polyhedralcone.h"
2 
3 #include "lp.h"
4 #include "subspace.h"
5 #include "symmetry.h"
6 #include "polymakefile.h"
7 #include "wallideal.h"
8 #include <sstream>
9 #include "triangulation.h"
10 #include "triangulation2.h"
11 #include "linalg.h"
12 #include "linalgfloat.h"
13 #include "continuedfractions.h"
14 #include "polyhedralfan.h"
15 #include "log.h"
16 
hasFullRowRank(IntegerVectorList const & l)17 static bool hasFullRowRank(IntegerVectorList const &l)//The tests where this is used can actually be improved by also using the known equations
18 {
19   int s=l.size();
20   if(s==0)return true;
21   if(s>l.front().size())return false;
22   return ::rank(rowsToIntegerMatrix(l))==s;
23 }
24 
25 //--------------------------------
26 // PolyhedralCone
27 //--------------------------------
28 
compareIntegerLists(IntegerVectorList const & a,IntegerVectorList const & b)29 static bool compareIntegerLists(IntegerVectorList const &a, IntegerVectorList const &b)
30 {
31   assert(a.size()==b.size());
32 
33   IntegerVectorList::const_iterator B=b.begin();
34   for(IntegerVectorList::const_iterator A=a.begin();A!=a.end();A++)
35     {
36       if(LexicographicTermOrder()(*A,*B))return true;
37       if(LexicographicTermOrder()(*B,*A))return false;
38       B++;
39     }
40   return false;
41 }
42 
operator <(PolyhedralCone const & a,PolyhedralCone const & b)43 bool operator<(PolyhedralCone const &a, PolyhedralCone const &b)
44 {
45   assert(a.state>=3);
46   assert(b.state>=3);
47 
48   if(a.dimension()>b.dimension())return true;//INVERTED
49   if(a.dimension()<b.dimension())return false;//INVERTED
50 
51   if(a.equations.size()<b.equations.size())return true;
52   if(a.equations.size()>b.equations.size())return false;
53 
54   if(a.n<b.n)return true;
55   if(a.n>b.n)return false;
56 
57   if(a.inequalities.size()<b.inequalities.size())return true;
58   if(a.inequalities.size()>b.inequalities.size())return false;
59 
60   if(compareIntegerLists(a.equations,b.equations))return true;
61   if(compareIntegerLists(b.equations,a.equations))return false;
62 
63   if(compareIntegerLists(a.inequalities,b.inequalities))return true;
64   if(compareIntegerLists(b.inequalities,a.inequalities))return false;
65 
66   return false;
67 }
68 
operator !=(PolyhedralCone const & a,PolyhedralCone const & b)69 bool operator!=(PolyhedralCone const &a, PolyhedralCone const &b)
70 {
71   return (a<b)||(b<a);
72 }
73 
74 
ensureStateAsMinimum(int s)75 void PolyhedralCone::ensureStateAsMinimum(int s)
76 {
77   if((state<1) && (s==1))
78     {
79       //log0 cerr<<"Number of inequalities: "<<halfSpaces.size()<<" Number of equations: "<<equations.size()<<endl;
80 
81 /*      if(inequalities.size()==0)
82         {
83           equations=subsetBasis(equations);
84         }
85       else*/
86       {
87 	IntegerMatrix temp=rowsToIntegerMatrix(equations,n);
88 	FieldMatrix m=integerMatrixToFieldMatrix(temp,Q);
89 	m.reduce();
90 	m.removeZeroRows();
91 
92 	IntegerVectorList newInequalities;
93 	for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
94 	  {
95 	    FieldVector w=integerVectorToFieldVector(*i,Q);
96 	    w=m.canonicalize(w);
97 	    if(!w.isZero())
98 	      newInequalities.push_back(w.primitive());
99 	  }
100 
101         inequalities=newInequalities;
102         removeDuplicates(inequalities);
103         equations=fieldMatrixToIntegerMatrixPrimitive(m).getRows();
104       }
105 
106       //      log0 cerr<<"Number of inequalities: "<<halfSpaces.size()<<" Number of equations: "<<equations.size()<<endl;
107 
108       //      log0 fprintf(Stderr,"+\n");
109       if(!(preassumptions&PCP_impliedEquationsKnown))
110       if(inequalities.size()>1)//there can be no implied equation unless we have at least two inequalities
111       if(!hasFullRowRank(inequalities))//the inequalities have been moved to an appropriate subspace above, so now we can easily check if the dual cone is simplicial
112         removeRedundantRows(&inequalities,&equations,false);
113       //log0 cerr<<"Number of inequalities: "<<halfSpaces.size()<<" Number of equations: "<<equations.size()<<endl;
114       //log0 fprintf(Stderr,"+\n");
115     }
116   if((state<2) && (s>=2) && !(preassumptions&PCP_facetsKnown))
117     {
118       //      halfSpaces.sort();
119       //      AsciiPrinter(Stderr).printVectorList(halfSpaces);
120 
121        if(inequalities.size()>25)
122 	 //	if(0)
123 	 {
124 	  IntegerVectorList h1;
125 	  IntegerVectorList h2;
126 	  bool a=false;
127 	  for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
128 	    {
129 	      if(a)
130 		h1.push_back(*i);
131 	      else
132 		h2.push_back(*i);
133 	      a=!a;
134 	    }
135 	  PolyhedralCone c1(h1,equations);
136 	  PolyhedralCone c2(h2,equations);
137 	  c1.ensureStateAsMinimum(2);
138 	  c2.ensureStateAsMinimum(2);
139 	  inequalities=c1.inequalities;
140 	  for(IntegerVectorList::const_iterator i=c2.inequalities.begin();i!=c2.inequalities.end();i++)
141 	    inequalities.push_back(*i);
142 	}
143 
144 
145        //      fprintf(Stderr,"Number half spaces: %i, number of equations: %i\n",halfSpaces.size(),equations.size());
146       if(equations.size())
147 	{
148 	  FieldMatrix equationSpace=integerMatrixToFieldMatrix(rowsToIntegerMatrix(equations,n),Q);
149 	  equationSpace.reduce();
150 	  IntegerVectorList halfSpaces2;
151 	  for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
152 	    {
153 	      halfSpaces2.push_back(equationSpace.canonicalize(integerVectorToFieldVector(*i,Q)).primitive());
154 	    }
155 	  if(hasFullRowRank(halfSpaces2))goto noFallBack;//the inequalities have been moved to an appropriate subspace above, so now we can easily check if the dual cone is simplicial
156 	  for(IntegerVectorList::const_iterator i=halfSpaces2.begin();i!=halfSpaces2.end();i++)
157 	    if((i->max()>1000) || (i->min()<-1000))goto fallBack;//more overflows caught in lp_cdd.
158 
159 	  inequalities=fastNormals(halfSpaces2);
160 	  goto noFallBack;
161 	fallBack:
162 	  removeRedundantRows(&inequalities,&equations,true);
163 	noFallBack:;
164 	}
165       else
166 	inequalities=fastNormals(inequalities);
167       //   fprintf(Stderr,"done\n");
168     }
169   if((state<3) && (s>=3))
170     {
171       //      fprintf(Stderr,"Number half spaces: %i, number of equations: %i\n",halfSpaces.size(),equations.size());
172       //      log1 fprintf(Stderr,"Computing subspace...\n");
173       Subspace v(equations,n);
174 
175       equations=v.getRepresentation();
176       //      log1 fprintf(Stderr,"...done computing subspace.\n");
177 
178 
179       for(IntegerVectorList::iterator i=inequalities.begin();i!=inequalities.end();i++)
180 	{
181 	  *i=v.canonicalizeVector(*i);
182 	}
183       inequalities.sort();
184       //fprintf(Stderr,"done\n");
185     }
186   state=s;
187 }
188 
canonicalize()189 void PolyhedralCone::canonicalize()
190 {
191   ensureStateAsMinimum(3);
192 }
193 
194 
findFacets()195 void PolyhedralCone::findFacets()
196 {
197   ensureStateAsMinimum(2);
198 }
199 
findImpliedEquations()200 void PolyhedralCone::findImpliedEquations()
201 {
202   ensureStateAsMinimum(1);
203 }
204 
205 /*PolyhedralCone::PolyhedralCone(IntegerVectorList const &halfSpaces_, IntegerVectorList const &equations_, int ambientDimension, int state):
206 	inequalities(halfSpaces_),
207 	equations(equations_),
208 	state(0),
209 	multiplicity(1),
210 	n(ambientDimension)
211 {
212 	this->state=state;
213 }
214 */
215 
PolyhedralCone(int ambientDimension)216 PolyhedralCone::PolyhedralCone(int ambientDimension):
217   n(ambientDimension),
218   state(1),
219   preassumptions(PCP_impliedEquationsKnown|PCP_facetsKnown),
220   multiplicity(1),
221   haveExtremeRaysBeenCached(false),
222   haveGeneratorsOfLinealitySpaceBeenCached(false)
223 {
224 }
225 
226 
PolyhedralCone(IntegerVectorList const & halfSpaces_,IntegerVectorList const & equations_,int ambientDimension,int preassumptions_)227 PolyhedralCone::PolyhedralCone(IntegerVectorList const &halfSpaces_, IntegerVectorList const &equations_, int ambientDimension, int preassumptions_):
228 //PolyhedralCone::PolyhedralCone(IntegerVectorList const &halfSpaces_, IntegerVectorList const &equations_, int ambientDimension):
229   inequalities(halfSpaces_),
230   equations(equations_),
231 //  equations(subsetBasis(equations_)),
232   state(0),
233   preassumptions(preassumptions_),
234   multiplicity(1),
235   haveExtremeRaysBeenCached(false),
236   haveGeneratorsOfLinealitySpaceBeenCached(false)
237 {
238   n=ambientDimension;
239   if(n==-1)
240     {
241       if(!halfSpaces_.empty())
242 	n=halfSpaces_.begin()->size();
243       else if(!equations_.empty())
244 	n=equations_.begin()->size();
245       else
246 	{
247 	  assert(0);
248 	}
249     }
250   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
251     {
252       assert(i->size()==n);
253     }
254   for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
255     {
256       /*AsciiPrinter P(Stderr);
257       P.printString("FJDSKFJA\n");
258       P.printVector(*i);
259       */
260       assert(i->size()==n);
261     }
262   ensureStateAsMinimum(1);
263   //  computeAndReduceLinearitySpace();
264 }
265 
266 
getRelativeInteriorPoint() const267 IntegerVector PolyhedralCone::getRelativeInteriorPoint()const
268 {
269   //  ensureStateAsMinimum(1);
270   assert(state>=1);
271   IntegerVector ret;
272   IntegerVectorList g=equations;
273   int numberOfEqualities=g.size();
274   g.insert(g.end(),inequalities.begin(),inequalities.end());
275   IntegerVector equalitySet(g.size());
276   for(int i=0;i<numberOfEqualities;i++)equalitySet[i]=1;
277 
278   if(!g.empty())
279     ret=relativeInteriorPoint(ambientDimension(),g,&equalitySet);
280   else
281     ret=IntegerVector(n);//cone is the full space, lp code would fail, since the dimension is unknown
282 
283   for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
284     {
285       assert(dotLong(*i,ret)==0);
286     }
287 
288   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
289     {
290       if(!(dotLong(*i,ret)>0))
291 	{
292 	  fprintf(Stderr,"PolyhedralCone::relativeInteriorPoint() : halfSpaces not reduced or mistake in cdd interface!!!\n");
293 	}
294     }
295 
296   return ret;
297 }
298 
299 
getHalfSpaces() const300 IntegerVectorList const &PolyhedralCone::getHalfSpaces()const
301 {
302   return inequalities;
303 }
304 
305 
getEquations() const306 const IntegerVectorList &PolyhedralCone::getEquations()const
307 {
308   assert(state>=1);
309   return equations;
310 }
311 
312 
getImpliedEquations() const313 const IntegerVectorList &PolyhedralCone::getImpliedEquations()const
314 {
315   const_cast<PolyhedralCone*>(this)->findImpliedEquations();
316   return equations;
317 }
318 
319 
generatorsOfSpan() const320 IntegerVectorList PolyhedralCone::generatorsOfSpan()const
321 {
322 	assert(isInStateMinimum(1));
323 	IntegerVectorList empty;
324 	PolyhedralCone temp(empty,getEquations(),n);
325 	return temp.dualCone().getEquations();
326 }
327 
328 
generatorsOfLinealitySpace() const329 IntegerVectorList PolyhedralCone::generatorsOfLinealitySpace()const
330 {
331   if(haveGeneratorsOfLinealitySpaceBeenCached)return cachedGeneratorsOfLinealitySpace;
332   IntegerVectorList l=equations;
333   l.insert(l.end(),inequalities.begin(),inequalities.end());
334   FieldMatrix L=integerMatrixToFieldMatrix(rowsToIntegerMatrix(l,ambientDimension()),Q);
335   cachedGeneratorsOfLinealitySpace=fieldMatrixToIntegerMatrixPrimitive(L.reduceAndComputeKernel()).getRows();
336 //  return linealitySpace().generatorsOfSpan();
337   haveGeneratorsOfLinealitySpaceBeenCached=true;
338   return cachedGeneratorsOfLinealitySpace;
339 }
340 
341 
ambientDimension() const342 int PolyhedralCone::ambientDimension()const
343 {
344   return n;
345 }
346 
347 
codimension() const348 int PolyhedralCone::codimension()const
349 {
350   return ambientDimension()-dimension();
351   //  return getEquations().size();
352 }
353 
354 
dimension() const355 int PolyhedralCone::dimension()const
356 {
357   assert(state>=1);
358   //  ensureStateAsMinimum(1);
359   return ambientDimension()-equations.size();
360 }
361 
362 
isZero() const363 bool PolyhedralCone::isZero()const
364 {
365   return dimension()==0;
366 }
367 
368 
isFullSpace() const369 bool PolyhedralCone::isFullSpace()const
370 {
371 	for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
372 		if(!i->isZero())return false;
373 	for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
374 		if(!i->isZero())return false;
375 	return true;
376 }
377 
378 
intersection(const PolyhedralCone & a,const PolyhedralCone & b)379 PolyhedralCone intersection(const PolyhedralCone &a, const PolyhedralCone &b)
380 {
381   if(a.ambientDimension()!=b.ambientDimension())
382     {
383       debug<<a.ambientDimension()<<"=="<<b.ambientDimension();
384       assert(a.ambientDimension()==b.ambientDimension());
385     }
386   IntegerVectorList inequalities=a.inequalities;
387   inequalities.insert(inequalities.end(),b.inequalities.begin(),b.inequalities.end());
388   IntegerVectorList equations=a.equations;
389 
390 
391   equations.insert(equations.end(),b.equations.begin(),b.equations.end());
392   {
393     removeDuplicates(equations);
394     removeDuplicates(inequalities);
395     IntegerVectorList Aequations=a.equations;
396     IntegerVectorList Ainequalities=a.inequalities;
397     removeDuplicates(Aequations);
398     removeDuplicates(Ainequalities);
399     if((Ainequalities.size()==inequalities.size()) && (Aequations.size()==equations.size()))return a;
400     IntegerVectorList Bequations=b.equations;
401     IntegerVectorList Binequalities=b.inequalities;
402     removeDuplicates(Bequations);
403     removeDuplicates(Binequalities);
404     if((Binequalities.size()==inequalities.size()) && (Bequations.size()==equations.size()))return b;
405   }
406 
407   return PolyhedralCone(inequalities,equations,a.ambientDimension());
408 }
409 
product(const PolyhedralCone & a,const PolyhedralCone & b)410 PolyhedralCone product(const PolyhedralCone &a, const PolyhedralCone &b)
411 {
412   IntegerVectorList equations2;
413   IntegerVectorList inequalities2;
414 
415   int n1=a.n;
416   int n2=b.n;
417 
418   for(IntegerVectorList::const_iterator i=a.equations.begin();i!=a.equations.end();i++)
419     equations2.push_back(concatenation(*i,IntegerVector(n2)));
420   for(IntegerVectorList::const_iterator i=b.equations.begin();i!=b.equations.end();i++)
421     equations2.push_back(concatenation(IntegerVector(n1),*i));
422   for(IntegerVectorList::const_iterator i=a.inequalities.begin();i!=a.inequalities.end();i++)
423     inequalities2.push_back(concatenation(*i,IntegerVector(n2)));
424   for(IntegerVectorList::const_iterator i=b.inequalities.begin();i!=b.inequalities.end();i++)
425     inequalities2.push_back(concatenation(IntegerVector(n1),*i));
426 
427   PolyhedralCone ret(inequalities2,equations2,n1+n2);
428   ret.setMultiplicity(a.getMultiplicity()*b.getMultiplicity());
429   ret.setLinearForm(concatenation(a.getLinearForm(),b.getLinearForm()));
430 
431   ret.ensureStateAsMinimum(a.state);
432   ret.ensureStateAsMinimum(b.state);
433 
434   return ret;
435 }
436 
positiveOrthant(int dimension)437 PolyhedralCone PolyhedralCone::positiveOrthant(int dimension)
438 {
439   IntegerVectorList halfSpaces;
440 
441   for(int i=0;i<dimension;i++)halfSpaces.push_back(IntegerVector::standardVector(dimension,i));
442 
443   IntegerVectorList empty;
444   return PolyhedralCone(halfSpaces,empty,dimension);
445 }
446 
447 
isInStateMinimum(int s) const448 bool PolyhedralCone::isInStateMinimum(int s)const
449 {
450   return state>=s;
451 }
452 
getState() const453 int PolyhedralCone::getState()const
454 {
455   return state;
456 }
457 
458 
print(class Printer * p,bool xml) const459 void PolyhedralCone::print(class Printer *p, bool xml)const
460 {
461   if(0)
462     {
463       p->printString("Printing PolyhedralCone");
464       p->printNewLine();
465       p->printString("Ambient dimension: ");
466       p->printInteger(n);
467       p->printNewLine();
468       if(isInStateMinimum(1))
469 	{
470 	  p->printString("Dimension: ");
471 	  p->printInteger(dimension());
472 	  p->printNewLine();
473 	}
474       p->printString("Linearity space:");
475       //  p->printNewLine();
476       p->printVectorList(equations);
477       p->printString("Inequalities:");
478       p->printVectorList(inequalities);
479       p->printString("Relative interior point:\n");
480       p->printVector(getRelativeInteriorPoint());
481       p->printNewLine();
482       p->printString("Done printing PolyhedralCone.");
483       p->printNewLine();
484     }
485   else
486     {
487       PolymakeFile polymakeFile;
488       polymakeFile.create("NONAME","PolyhedralCone","PolyhedralCone",xml);
489       polymakeFile.writeCardinalProperty("AMBIENT_DIM",n);
490       if(isInStateMinimum(1))
491 	{
492 	  polymakeFile.writeCardinalProperty("DIM",dimension());
493 	  //need to check that the following is done correctly
494 	  //       	  polymakeFile.writeCardinalProperty("LINEALITY_DIM",dimensionOfLinealitySpace());
495 
496 	  polymakeFile.writeMatrixProperty("IMPLIED_EQUATIONS",rowsToIntegerMatrix(equations,n));
497 	}
498       polymakeFile.writeCardinalProperty("LINEALITY_DIM",dimensionOfLinealitySpace());
499       polymakeFile.writeMatrixProperty("LINEALITY_SPACE",rowsToIntegerMatrix(linealitySpace().dualCone().getEquations(),n));
500 
501 
502       if(isInStateMinimum(2))
503 	polymakeFile.writeMatrixProperty("FACETS",rowsToIntegerMatrix(inequalities,n));
504       else
505 	polymakeFile.writeMatrixProperty("INEQUALITIES",rowsToIntegerMatrix(inequalities,n));
506 
507       polymakeFile.writeCardinalVectorProperty("RELATIVE_INTERIOR_POINT",getRelativeInteriorPoint());
508 
509 
510       stringstream s;
511       polymakeFile.writeStream(s);
512       string S=s.str();
513       p->printString(S.c_str());
514     }
515 }
516 
517 
printAsFan(class Printer * p) const518 void PolyhedralCone::printAsFan(class Printer *p)const
519 {
520   IntegerVectorList empty;
521   PolyhedralCone C2=*this;
522   C2.canonicalize();
523   PolyhedralFan F(n);F.insert(C2);
524   F.printWithIndices(p,FPF_default);
525 }
526 
527 
dehomogenize(IntegerVector const & v)528 static IntegerVector dehomogenize(IntegerVector const &v)
529 {
530   assert(v.size()>0);
531 
532   IntegerVector ret(v.size()-1);
533 
534   for(int i=0;i<v.size()-1;i++)ret[i]=v[i];
535   return ret;
536 }
537 
dehomogenize(IntegerVectorList const & l)538 static IntegerVectorList dehomogenize(IntegerVectorList const &l)
539 {
540   IntegerVectorList ret;
541 
542   for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
543     {
544       ret.push_back(dehomogenize(*i));
545     }
546   return ret;
547 }
548 
withLastCoordinateRemoved() const549 PolyhedralCone PolyhedralCone::withLastCoordinateRemoved()const
550 {
551   assert(n>0);
552 
553   return PolyhedralCone(dehomogenize(inequalities),dehomogenize(equations));
554 }
555 
containsPositiveVector() const556 bool PolyhedralCone::containsPositiveVector()const
557 {
558   PolyhedralCone temp=intersection(*this,PolyhedralCone::positiveOrthant(n));
559   IntegerVector v=temp.getRelativeInteriorPoint();
560   return v.isPositive();
561 }
562 
563 
dimensionOfLinealitySpace() const564 int PolyhedralCone::dimensionOfLinealitySpace()const
565 {
566   if(inequalities.empty())return dimension();
567   IntegerVectorList a;
568   PolyhedralCone temp(a,inequalities);
569   temp=intersection(temp,*this);
570 
571   return temp.dimension();
572 }
573 
574 
contains(IntegerVector const & v) const575 bool PolyhedralCone::contains(IntegerVector const &v)const
576 {
577   for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
578     {
579       if(dotLong(*i,v)!=0)return false;
580     }
581 
582   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
583     {
584       if(dotLong(*i,v)<0)return false;
585     }
586 
587   return true;
588 }
589 
590 
contains(IntegerVectorList const & l) const591 bool PolyhedralCone::contains(IntegerVectorList const &l)const
592 {
593   for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
594     if(!contains(*i))return false;
595   return true;
596 }
597 
contains(PolyhedralCone const & c) const598 bool PolyhedralCone::contains(PolyhedralCone const &c)const
599 {
600   PolyhedralCone c2=intersection(*this,c);
601   PolyhedralCone c3=c;
602   c2.canonicalize();
603   c3.canonicalize();
604   return !(c2!=c3);
605 }
606 
607 
containsPerturbed(IntegerVectorList const & l) const608 bool PolyhedralCone::containsPerturbed(IntegerVectorList const &l)const
609 {
610 	for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
611 	{
612 		for(IntegerVectorList::const_iterator j=l.begin();j!=l.end();j++)
613 			if(dotLong(*i,*j)!=0)return false;
614 	}
615 
616 	for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
617 	{
618 		for(IntegerVectorList::const_iterator j=l.begin();j!=l.end();j++)
619 			if(dotLong(*i,*j)<0)return false;
620 			else if(dotLong(*i,*j)>0) break;
621 	}
622 	return true;
623 }
624 
containsRelatively(IntegerVector const & v) const625 bool PolyhedralCone::containsRelatively(IntegerVector const &v)const
626 {
627   assert(state>=1);
628   for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
629     {
630       if(dotLong(*i,v)!=0)return false;
631     }
632 
633   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
634     {
635       if(dotLong(*i,v)<=0)return false;
636     }
637 
638   return true;
639 }
640 
641 
permuted(IntegerVector const & v) const642 PolyhedralCone PolyhedralCone::permuted(IntegerVector const &v)const
643 {
644   PolyhedralCone ret(SymmetryGroup::permuteIntegerVectorList(inequalities,v),SymmetryGroup::permuteIntegerVectorList(equations,v),n,(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0)+(areFacetsKnown()?PCP_facetsKnown:0));
645   if(state>=1)ret.state=1;
646   if(state>=2)ret.state=2;
647 
648   ret.ensureStateAsMinimum(state);
649   ret.setMultiplicity(multiplicity);
650   return ret;
651 }
652 
getUniquePoint() const653 IntegerVector PolyhedralCone::getUniquePoint()const
654 {
655   IntegerVectorList rays=extremeRays();
656   IntegerVector ret(n);
657   for(IntegerVectorList::const_iterator i=rays.begin();i!=rays.end();i++)
658     ret+=*i;
659 
660   assert(containsRelatively(ret));//remove this check later
661   return ret;
662 }
663 
getUniquePointFromExtremeRays(IntegerVectorList const & extremeRays) const664 IntegerVector PolyhedralCone::getUniquePointFromExtremeRays(IntegerVectorList const &extremeRays)const
665 {
666 	IntegerVector ret(n);
667 	for(IntegerVectorList::const_iterator i=extremeRays.begin();i!=extremeRays.end();i++)
668 		if(contains(*i))ret+=*i;
669 	return ret;
670 }
671 
672 /**
673  * Returns a primitive vector parallel to the projection of v onto the orthogonal complement of E.
674  */
primitiveProjection(IntegerVectorList const & E,IntegerVector & v,bool useFloat)675 static IntegerVector primitiveProjection(IntegerVectorList const &E, IntegerVector &v, bool useFloat)
676 {
677 	int n=v.size();
678 if(useFloat)
679 	{
680 	IntegerMatrix E2=rowsToIntegerMatrix(E,n);
681 	linalgfloat::Matrix E3(E.size(),n);
682 	for(int i=0;i<E3.getHeight();i++)
683 		for(int j=0;j<E3.getWidth();j++)
684 			E3[i][j]=E2[i][j];
685 	cerr<<E3;
686 	E3.orthogonalize();
687 	linalgfloat::Vector v2(n);
688 	for(int i=0;i<n;i++)v2[i]=v[i];
689 	cerr<<E3;
690 	linalgfloat::Vector coefficients=E3.projectionCoefficients(v2);
691 
692 	cerr<<coefficients<<"\n";
693 
694 	vector<double> temp(coefficients.size());
695 	for(int i=0;i<coefficients.size();i++)temp[i]=coefficients[i];
696 	vector<int> tempInt(coefficients.size());
697 	int denominator;
698 	doubleVectorToFractions(temp, tempInt, denominator);
699 	IntegerVector tempInt2(tempInt.size());for(int i=0;i<tempInt.size();i++)tempInt2[i]=tempInt[i];
700 	if(tempInt2.max()>1000)goto fallback;
701 	if(tempInt2.min()<-1000)goto fallback;
702 	if(denominator>1000)goto fallback;
703 	if(denominator<-1000)goto fallback;
704 	IntegerVector ret=denominator*v;
705 	int I=0;
706 	for(IntegerVectorList::const_iterator i=E.begin();i!=E.end();i++,I++)ret-=coefficients[I]*(*i);
707 	if(!E2.inKernel(ret))goto fallback;
708 	return normalized(ret);
709 	}
710 	fallback:
711 	debug<<"FLOATCONELINALG FALLBACK\n";
712 
713 	IntegerVectorList inequalities;
714 	inequalities.push_back(v);
715 	FieldMatrix linealitySpaceOrth=combineOnTop(integerMatrixToFieldMatrix(rowsToIntegerMatrix(E,n),Q),integerMatrixToFieldMatrix(rowsToIntegerMatrix(inequalities,n),Q));
716 	FieldMatrix temp=combineOnTop(linealitySpaceOrth.reduceAndComputeKernel(),integerMatrixToFieldMatrix(rowsToIntegerMatrix(E,n),Q));
717 	FieldMatrix temp2=temp.reduceAndComputeKernel();
718 	assert(temp2.getHeight()==1);
719 	  return temp2[0].primitive();
720 }
721 
extremeRays(IntegerVectorList const * generatorsOfLinealitySpace) const722 IntegerVectorList PolyhedralCone::extremeRays(IntegerVectorList const *generatorsOfLinealitySpace)const
723 {
724   assert((dimension()==ambientDimension()) || (state>=3));
725 
726   if(haveExtremeRaysBeenCached)return cachedExtremeRays;
727 
728   //The generators of the lineality space are not known, we may as well compute them. Since we typycally will use them at least once.
729   IntegerVectorList generatorsOfLinealitySpace2;
730   if(!generatorsOfLinealitySpace)
731     {
732       FieldMatrix linealitySpaceOrth=combineOnTop(integerMatrixToFieldMatrix(rowsToIntegerMatrix(this->equations,n),Q),integerMatrixToFieldMatrix(rowsToIntegerMatrix(this->inequalities,n),Q));
733       generatorsOfLinealitySpace2=fieldMatrixToIntegerMatrixPrimitive(linealitySpaceOrth.reduceAndComputeKernel()).getRows();
734       generatorsOfLinealitySpace=&generatorsOfLinealitySpace2;
735     }
736   //	 this->print(&debug);
737   /* This code actually works even for lower dimensional cones if they have been canonicalized. */
738 
739   //  AsciiPrinter(Stderr).printVectorList(halfSpaces);
740   //  AsciiPrinter(Stderr).printVectorList(equations);
741 
742   IntegerVectorList ret;
743 
744   // log0 fprintf(Stderr,"calling double description (cddlib)\n");
745   IntegerVectorList indices=extremeRaysInequalityIndices(inequalities);
746   //  log0 fprintf(Stderr,"returning\n");
747   // log0 fprintf(Stderr,"computing relative interior points\n");
748 
749 //  debug<<"INDICES"<<indices;
750   for(IntegerVectorList::const_iterator i=indices.begin();i!=indices.end();i++)
751     {
752 //        log0 AsciiPrinter(Stderr)<<*i;
753       if(1)
754 	{
755       /* At this point we know lineality space, implied equations and
756 	 also inequalities for the ray. To construct a vector on the
757 	 ray which is stable under (or indendent of) angle and
758 	 linarity preserving transformation we find the dimension 1
759 	 subspace orthorgonal to the implied equations and the
760 	 lineality space and pick a suitable primitive generator */
761 
762     	  /* To be more precise,
763     	   * let E be the set of equations, and v the inequality defining a  ray R.
764     	   * We wish to find a vector satisfying these, but it must also be orthogonal
765     	   * to the lineality space of the cone, that is, in the span of {E,v}.
766     	   * One way to get such a vector is to project v to E an get a vector p.
767     	   * Then v-p is in the span of {E,v} by construction.
768     	   * The vector v-p is also in the orthogonal complement to E by construction,
769     	   * that is, the span of R.
770     	   * We wish to argue that it is not zero.
771     	   * That would imply that v=p, meaning that v is in the span of the equations.
772     	   * However, that would contradict that R is a ray.
773     	   * In case v-p does not satisfy the inequality v (is this possible?), we change the sign.
774     	   *
775     	   * As a consequence we need the following procedure
776     	   * primitiveProjection():
777     	   *    Input: E,v
778     	   *    Output: A primitive representation of the vector v-p, where p is the projection of v onto E
779     	   *
780     	   * Notice that the output is a Q linear combination of the input and that p is
781     	   * a linear combination of E. The check that p has been computed correctly,
782     	   * it suffices to check that v-p satisfies the equations E.
783     	   * The routine will actually first compute a multiple of v-p.
784     	   * It will do this using floating point arithmetics. It will then transform
785     	   * the coefficients to get the multiple of v-p into integers. Then it
786     	   * verifies in exact arithmetics, that with these coefficients we get a point
787     	   * satisfying E. It then returns the primitive vector on the ray v-p.
788     	   * In case of a failure it falls back to an implementation using rational arithmetics.
789     	   */
790 
791 
792 	  IntegerVector asVector(inequalities.size());
793     //  log0 AsciiPrinter(Stderr)<<asVector;
794 	  for(int j=0;j<i->size();j++)asVector[(*i)[j]]=1;
795      // log0 AsciiPrinter(Stderr)<<asVector;
796 
797 	  IntegerVectorList equations=this->equations;
798 	  IntegerVectorList inequalities;
799 
800 	  IntegerVector theInequality;
801 
802     //  log0 AsciiPrinter(Stderr)<<inequalities;
803 
804       IntegerVectorList::const_iterator a=this->inequalities.begin();
805 	  for(int j=0;j<asVector.size();j++,a++)
806 	    if(asVector[j])
807 	      equations.push_back(*a);
808 	    else
809 	    	theInequality=*a;
810 
811 	  assert(!theInequality.isZero());
812 
813 	  IntegerVector thePrimitiveVector;
814 	  if(generatorsOfLinealitySpace)
815 	  {
816 		IntegerMatrix temp=rowsToIntegerMatrix(equations,n);
817 		temp.append(rowsToIntegerMatrix(*generatorsOfLinealitySpace,n));
818 
819 //		debug<<*generatorsOfLinealitySpace;
820 //			debug.printVectorList(temp.getRows());
821 		log3 debug<<temp.getRows();
822 		thePrimitiveVector=vectorInKernel(temp);
823 	  }
824 	  else
825 	  {
826 	  //log0  AsciiPrinter(Stderr)<<equations;
827 /*		  {
828 			  IntegerVectorList equations2=this->equations;
829 			  for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)equations2.push_back(*i);
830 		  debug<<primitiveProjection(equations2,theInequality,true)<<"\n";
831 		  debug<<primitiveProjection(equations2,theInequality,false)<<"\n";
832 		  }
833 */
834 		  /** TODO: These calls are slow, but used often in the symmetric traversal. Maybe they should be done in floating point somehow.*/
835 	  FieldMatrix linealitySpaceOrth=combineOnTop(integerMatrixToFieldMatrix(rowsToIntegerMatrix(this->equations,n),Q),integerMatrixToFieldMatrix(rowsToIntegerMatrix(this->inequalities,n),Q));
836 	  FieldMatrix temp=combineOnTop(linealitySpaceOrth.reduceAndComputeKernel(),integerMatrixToFieldMatrix(rowsToIntegerMatrix(equations,n),Q));
837 	  FieldMatrix temp2=temp.reduceAndComputeKernel();
838 
839 	  assert(temp2.getHeight()==1);
840 	  thePrimitiveVector=temp2[0].primitive();
841 
842 	//  debug<<thePrimitiveVector<<"\n";
843 	  }
844 	  if(!contains(thePrimitiveVector))thePrimitiveVector=-thePrimitiveVector;
845 	  ret.push_back(thePrimitiveVector);
846 	}
847       else
848 	{
849   /*      IntegerVectorList equations;
850       for(int j=0;j<i->size();j++)
851 	{
852 	  IntegerVectorList::const_iterator a=halfSpaces.begin();
853 	  for(int k=0;k<(*i)[j];k++)
854 	    {
855 	      assert(a!=halfSpaces.end());
856 	      	      a++;
857 	    }
858 	  assert(a!=halfSpaces.end());
859 	  equations.push_back(*a);
860 	  }*/
861 
862 	  IntegerVector asVector(inequalities.size());
863 	  for(int j=0;j<i->size();j++)asVector[(*i)[j]]=1;
864 
865 	  IntegerVectorList equations=this->equations;
866 	  IntegerVectorList inequalities;
867 
868 	  IntegerVectorList::const_iterator a=inequalities.begin();
869 	  for(int j=0;j<asVector.size();j++,a++)
870 	    if(asVector[j])
871 	      equations.push_back(*a);
872 	    else
873 	      inequalities.push_back(*a);
874 
875 
876 	  //log0 fprintf(Stderr,"Equations %i, HalfSpaces: %i\n",equations.size(),inequalities.size());
877 	  IntegerVector u=PolyhedralCone(inequalities,equations).getRelativeInteriorPoint();
878 	  if(!u.isZero())
879 	    ret.push_back(u);
880 	  else
881 	    {
882 	      log2 fprintf(Stderr,"Remember to fix cdd double description interface\n");
883 	    }
884 	}
885     }
886   // log0 fprintf(Stderr,"done computing relative interior points\n");
887 
888 
889   /*   //triangulation method. Keep this code.
890   {
891     IntegerMatrix temp=rowsToIntegerMatrix(halfSpaces);
892  log0 fprintf(Stderr,"calling double description (triangulation)\n");
893     IntegerVectorList ret2=Triangulation::normals(temp);
894  log0 fprintf(Stderr,"returning\n");
895  return ret2;
896 
897     AsciiPrinter(Stderr).printVectorList(halfSpaces);
898     AsciiPrinter(Stderr).printVectorList(equations);
899     fprintf(Stderr,"dim:%i\n",dimension());
900     //ret.sort();
901     AsciiPrinter(Stderr).printVectorList(ret);
902     //  AsciiPrinter(Stderr).printVectorList(fastNormals(ret2));
903     AsciiPrinter(Stderr).printVectorList(ret2);
904 
905     fprintf(stderr,"-----------------------\n");
906   }
907   */
908 
909   cachedExtremeRays=ret;
910   haveExtremeRaysBeenCached=true;
911 
912   return ret;
913 }
914 
915 
isSimplicial() const916 bool PolyhedralCone::isSimplicial()const
917 {
918   assert(state>=2);
919 
920   //  ensureStateAsMinimum(2);
921   //  AsciiPrinter P(Stderr);
922   //  print(&P);
923   return codimension()+getHalfSpaces().size()+dimensionOfLinealitySpace()==n;
924 }
925 
926 
checkDual(PolyhedralCone const & c) const927 bool PolyhedralCone::checkDual(PolyhedralCone const &c)const
928 {
929   assert(dimensionOfLinealitySpace()+c.dimension()==ambientDimension());
930 
931   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
932     {
933       assert(c.contains(*i));
934     }
935   for(IntegerVectorList::const_iterator i=equations.begin();i!=equations.end();i++)
936     {
937       assert(c.contains(*i));
938     }
939   return true;
940 }
941 
942 
dualCone() const943 PolyhedralCone PolyhedralCone::dualCone()const
944 {
945   assert(state>=1);
946 
947   IntegerVectorList dualInequalities,dualEquations;
948 
949   dual(ambientDimension(),inequalities,equations,&dualInequalities,&dualEquations);
950 
951   PolyhedralCone ret(dualInequalities,dualEquations);
952 
953   ret.ensureStateAsMinimum(state);
954   //  ret.canonicalize();
955 
956 
957   assert(checkDual(ret));
958   assert(ret.checkDual(*this));
959 
960   return ret;
961 }
962 
963 
negated() const964 PolyhedralCone PolyhedralCone::negated()const
965 {
966   IntegerVectorList inequalities2;
967   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)inequalities2.push_back(-*i);
968 //  PolyhedralCone ret(inequalities2,equations,n);
969   PolyhedralCone ret(inequalities2,equations,n,(areFacetsKnown()?PCP_facetsKnown:0)|(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0));
970   ret.ensureStateAsMinimum(state);
971   return ret;
972 }
973 
linealitySpace() const974 PolyhedralCone PolyhedralCone::linealitySpace()const
975 {
976   IntegerVectorList l1=getEquations();
977   IntegerVectorList l2=getHalfSpaces();
978 
979   l1.splice(l1.begin(),l2);
980 
981   IntegerVectorList temp;
982   PolyhedralCone ret(temp,l1,n);
983   ret.ensureStateAsMinimum(state);
984   return ret;
985 }
986 
987 
span() const988 PolyhedralCone PolyhedralCone::span()const
989 {
990   return PolyhedralCone(IntegerVectorList(),getImpliedEquations(),n);
991 }
992 
993 
getMultiplicity() const994 int PolyhedralCone::getMultiplicity()const
995 {
996   return multiplicity;
997 }
998 
999 
setMultiplicity(int m)1000 void PolyhedralCone::setMultiplicity(int m)
1001 {
1002   multiplicity=m;
1003 }
1004 
1005 
quotientLatticeBasis() const1006 IntegerVectorList PolyhedralCone::quotientLatticeBasis()const
1007 {
1008   assert(isInStateMinimum(1));// Implied equations must have been computed in order to know the span of the cone
1009 
1010   return basisOfQuotientLattice(equations,inequalities,n);
1011 }
1012 
1013 
semiGroupGeneratorOfRay() const1014 IntegerVector PolyhedralCone::semiGroupGeneratorOfRay()const
1015 {
1016   IntegerVectorList temp=quotientLatticeBasis();
1017   assert(temp.size()==1);
1018   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
1019     if(dotLong(temp.front(),*i)<0)
1020       {
1021 	temp.front()=-temp.front();
1022 	break;
1023       }
1024   return temp.front();
1025 }
1026 
1027 
getLinearForm() const1028 IntegerVector const &PolyhedralCone::getLinearForm()const
1029 {
1030   return linearForm;
1031 }
1032 
1033 
setLinearForm(IntegerVector const & linearForm_)1034 void PolyhedralCone::setLinearForm(IntegerVector const &linearForm_)
1035 {
1036   linearForm=linearForm_;
1037 }
1038 
1039 
link(IntegerVector const & w) const1040 PolyhedralCone PolyhedralCone::link(IntegerVector const &w)const
1041 {
1042 	/*
1043 	 * Observe that the inequalities giving rise to facets
1044 	 * also give facets in the link, if they are kept as
1045 	 * inequalities. This means that the state cannot decrease when taking links.
1046 	 *
1047 	 */
1048 //  assert(state>=3);
1049   IntegerVectorList inequalities2;
1050   for(IntegerVectorList::const_iterator j=inequalities.begin();j!=inequalities.end();j++)
1051     if(dotLong(w,*j)==0)inequalities2.push_back(*j);
1052 //  PolyhedralCone C(inequalities2,getEquations(),n);
1053 //  C.canonicalize();
1054 //  PolyhedralCone C(inequalities2,getEquations(),n,state);//STATE-----------------------------------------------------
1055   PolyhedralCone C(inequalities2,getEquations(),n,(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0)|(areFacetsKnown()?PCP_facetsKnown:0));
1056   C.ensureStateAsMinimum(state);
1057 
1058   C.setLinearForm(getLinearForm());
1059   C.setMultiplicity(getMultiplicity());
1060 
1061   return C;
1062 }
1063 
1064 
givenByRays(IntegerVectorList const & generators,IntegerVectorList const & linealitySpace,int n)1065 PolyhedralCone PolyhedralCone::givenByRays(IntegerVectorList const &generators, IntegerVectorList const &linealitySpace, int n)
1066 {
1067   //rewrite modulo lineality space
1068   IntegerVectorList newGenerators=generators;
1069   {
1070     Subspace l(linealitySpace,n);
1071     for(IntegerVectorList::const_iterator i=generators.begin();i!=generators.end();i++)
1072       newGenerators.push_back(l.canonicalizeVector(*i));
1073   }
1074 
1075   PolyhedralCone dual(newGenerators,linealitySpace,n);
1076   dual.findFacets();
1077   dual.canonicalize();
1078   IntegerVectorList inequalities=dual.extremeRays();
1079 
1080   IntegerVectorList span=generators;
1081   for(IntegerVectorList::const_iterator i=linealitySpace.begin();i!=linealitySpace.end();i++)span.push_back(*i);
1082   FieldMatrix m2Q=integerMatrixToFieldMatrix(rowsToIntegerMatrix(span,n),Q);
1083   IntegerVectorList equations=fieldMatrixToIntegerMatrixPrimitive(m2Q.reduceAndComputeKernel()).getRows();
1084 
1085   return PolyhedralCone(inequalities,equations,n);
1086 }
1087 
1088 
volume() const1089 FieldElement PolyhedralCone::volume()const
1090 {
1091   AsciiPrinter P(Stderr);
1092 
1093   PolyhedralCone Ctemp=intersection(*this,this->linealitySpace().dualCone());
1094 
1095   Ctemp.canonicalize();
1096   cerr<<"testestests";
1097   IntegerVectorList eq2=rowsToIntegerMatrix(Ctemp.equations,n).transposed().getRows();
1098   eq2.push_front(IntegerVector(Ctemp.equations.size()));
1099   eq2=rowsToIntegerMatrix(eq2).transposed().getRows();
1100   cerr<<"testestests2";
1101 
1102   IntegerVectorList in2=rowsToIntegerMatrix(Ctemp.inequalities,n).transposed().getRows();
1103   in2.push_front(IntegerVector(Ctemp.inequalities.size()));
1104   in2=rowsToIntegerMatrix(in2).transposed().getRows();
1105 
1106   for(int i=0;i<n;i++)
1107     {
1108       in2.push_back(IntegerVector::standardVector(n+1,i+1)+IntegerVector::standardVector(n+1,0));
1109       in2.push_back(-IntegerVector::standardVector(n+1,i+1)+IntegerVector::standardVector(n+1,0));
1110     }
1111 
1112   debug<<in2;
1113   debug<<eq2;
1114 
1115   PolyhedralCone lifted(in2,eq2,n+1);
1116 
1117 
1118   lifted.print(&debug);
1119 
1120   lifted.canonicalize();
1121   IntegerMatrix A=rowsToIntegerMatrix(lifted.extremeRays()).transposed();//points are columns
1122 
1123   cerr << "height " << A.getHeight() << " width" <<A.getWidth()<<endl;
1124 
1125   P<<A.transposed().getRows();
1126 
1127   FieldMatrix A2(Q,A.getHeight()-1,A.getWidth());
1128   for(int i=0;i<A.getHeight()-1;i++)
1129     {
1130       A2[i]=integerVectorToFieldVector(A[i+1],Q)/integerVectorToFieldVector(A[0],Q);
1131     }
1132   A2=A2.transposed();//Now points are rows
1133 
1134   P<<"Triangulating\n";
1135   list<Triangulation::Cone> T=Triangulation::triangulate(A.transposed(),true);//revlex
1136   P<<"Done triangulating\n";
1137 
1138 
1139   P<<(int)T.size();
1140 
1141   FieldElement ret(Q);
1142 
1143   for(list<Triangulation::Cone>::const_iterator i=T.begin();i!=T.end();i++)
1144     {
1145       FieldMatrix S=A2.submatrixRows(*i);
1146 
1147       debug<<"M"<<S<<"M";
1148 
1149 
1150       FieldMatrix S1(Q,S.getHeight()-1,S.getWidth());
1151       for(int j=0;j<S1.getHeight();j++)
1152 	S1[j]=S[j+1]-S[0];
1153 
1154       FieldMatrix S2=S1*(S1.transposed());
1155       FieldElement square=S2.reduceAndComputeDeterminant();
1156 
1157       //      ret+=square.squareroot();
1158     }
1159 
1160   return ret;
1161 }
1162 
1163 
1164 #include "halfopencone.h"
hasFace(PolyhedralCone const & f) const1165 bool PolyhedralCone::hasFace(PolyhedralCone const &f)const
1166 {
1167   if(!contains(f))return false;
1168   IntegerVectorList linealitySpace=this->linealitySpace().dualCone().getEquations();
1169   IntegerVectorList rays=extremeRays();
1170 
1171   for(IntegerVectorList::const_iterator i=linealitySpace.begin();i!=linealitySpace.end();i++)
1172     if(!f.contains(*i))return false;
1173 
1174   IntegerVectorList strict;
1175   for(IntegerVectorList::const_iterator i=rays.begin();i!=rays.end();i++)
1176     if(!f.contains(*i))
1177       strict.push_back(*i);
1178 
1179   IntegerVectorList linealitySpace2=f.linealitySpace().dualCone().getEquations();
1180   IntegerVectorList rays2=f.extremeRays();
1181 
1182   for(IntegerVectorList::const_iterator i=rays2.begin();i!=rays2.end();i++)
1183     {
1184       linealitySpace2.push_back(*i);
1185     }
1186   IntegerVectorList empty;
1187   HalfOpenCone C(n,linealitySpace2, empty, strict);
1188   return !C.isEmpty();
1189 }
1190 
faceContaining(IntegerVector const & v) const1191 PolyhedralCone PolyhedralCone::faceContaining(IntegerVector const &v)const
1192 {
1193 	assert(n==v.size());
1194 	if(!contains(v))
1195 	{
1196 		debug<<"Not contained in cone:\n"<<v<<"\n";
1197 		assert(contains(v));
1198 	}
1199 	IntegerVectorList newEquations=equations;
1200 	IntegerVectorList newInequalities;
1201 	for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
1202 		if(dotLong(*i,v))
1203 			newInequalities.push_back(*i);
1204 		else
1205 			newEquations.push_back(*i);
1206 
1207 	PolyhedralCone ret(newInequalities,newEquations,n,(state>=1)?PCP_impliedEquationsKnown:0);
1208 	ret.ensureStateAsMinimum(state);
1209 	return ret;
1210 }
1211 
1212 
faceContainingPerturbed(IntegerVectorList const & l) const1213 PolyhedralCone PolyhedralCone::faceContainingPerturbed(IntegerVectorList const &l)const
1214 {
1215   IntegerVectorList newEquations=equations;
1216   IntegerVectorList newInequalities;
1217   for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
1218     {
1219       bool onFacet=true;
1220       for(IntegerVectorList::const_iterator j=l.begin();j!=l.end();j++)
1221         if(dotLong(*i,*j)){onFacet=false;break;}
1222       if(!onFacet)
1223         newInequalities.push_back(*i);
1224       else
1225         newEquations.push_back(*i);
1226     }
1227   PolyhedralCone ret(newInequalities,newEquations,n,(state>=1)?PCP_impliedEquationsKnown:0);
1228   ret.ensureStateAsMinimum(state);
1229   return ret;
1230 }
1231 
1232 
projection(int newn) const1233 PolyhedralCone PolyhedralCone::projection(int newn)const
1234 {
1235 	assert(newn<=n);
1236 	assert(newn>=0);
1237 	IntegerVectorList rays=extremeRays();
1238 	IntegerVectorList lines=linealitySpace().generatorsOfSpan();
1239 	rays=rowsToIntegerMatrix(rays,n).submatrix(0,0,rays.size(),newn).getRows();
1240 	lines=rowsToIntegerMatrix(lines,n).submatrix(0,0,lines.size(),newn).getRows();
1241 	return givenByRays(rays,lines,newn);
1242 }
1243 
sum(PolyhedralCone const & A,PolyhedralCone const & B)1244 PolyhedralCone sum(PolyhedralCone const &A, PolyhedralCone const &B)
1245 {
1246   IntegerVectorList raysA=A.extremeRays();
1247   IntegerVectorList raysB=B.extremeRays();
1248   for(IntegerVectorList::const_iterator i=raysB.begin();i!=raysB.end();i++)raysA.push_back(*i);
1249   IntegerVectorList gensA=A.generatorsOfLinealitySpace();
1250   IntegerVectorList gensB=B.generatorsOfLinealitySpace();
1251   for(IntegerVectorList::const_iterator i=gensB.begin();i!=gensB.end();i++)gensA.push_back(*i);
1252 
1253 
1254   return PolyhedralCone::givenByRays(raysA,gensA,A.ambientDimension());
1255 }
1256 
inducedLink(PolyhedralCone const & c,PolyhedralCone const & l)1257 IntegerVectorList inducedLink(PolyhedralCone const &c, PolyhedralCone const &l)
1258 {
1259   PolyhedralCone A=sum(c,l);
1260   A.canonicalize();
1261   IntegerVectorList ret;
1262   if(A.dimension()==l.dimension())return ret;
1263   assert(l.dimension()+1==A.dimension());
1264   int nineq=A.getHalfSpaces().size();
1265   assert(nineq<=1);
1266   if(nineq==1)
1267     {
1268       ret.push_back(A.getUniquePoint());
1269     }
1270   else
1271     {
1272       PolyhedralCone ADual=A.dualCone();
1273       IntegerVectorList L=l.getEquations();
1274       for(IntegerVectorList::const_iterator i=L.begin();i!=L.end();i++)
1275         if(!ADual.contains(*i))
1276           {
1277             IntegerVectorList temp;temp.push_back(*i);
1278             PolyhedralCone ray(temp,A.getImpliedEquations());
1279             ray.canonicalize();
1280             IntegerVector v=ray.getUniquePoint();
1281             ret.push_back(v);
1282             ret.push_back(-v);
1283             break;
1284           }
1285       assert(!ret.empty());
1286     }
1287   return ret;
1288 }
1289 
doesSatisfyInequalityExpensive(IntegerVector const & ineq) const1290 bool PolyhedralCone::doesSatisfyInequalityExpensive(IntegerVector const &ineq)const
1291 {
1292   if(!haveExtremeRaysBeenCached)this->extremeRays();
1293   if(!haveGeneratorsOfLinealitySpaceBeenCached)this->generatorsOfLinealitySpace();
1294   assert(haveGeneratorsOfLinealitySpaceBeenCached);
1295   assert(haveExtremeRaysBeenCached);
1296 
1297   for(IntegerVectorList::const_iterator i=cachedGeneratorsOfLinealitySpace.begin();i!=cachedGeneratorsOfLinealitySpace.end();i++)
1298     if(dotLong(*i,ineq)!=0)return false;
1299   for(IntegerVectorList::const_iterator i=cachedExtremeRays.begin();i!=cachedExtremeRays.end();i++)
1300     if(dotLong(*i,ineq)<0)return false;
1301 
1302   return true;
1303 }
1304 
1305 
triangulation() const1306 list<PolyhedralCone> PolyhedralCone::triangulation()const
1307 {
1308   IntegerVectorList rays=this->extremeRays();
1309   rays.sort();
1310   IntegerVectorList lines=this->generatorsOfLinealitySpace();
1311   IntegerMatrix M=rowsToIntegerMatrix(rays,n);
1312   IntegerMatrix M2=M.transposed();
1313   Triangulation2 T(M2);
1314   T.triangulate();
1315   T.changeToTriangulationInducedBy(LexicographicTermOrder());
1316   list<PolyhedralCone> ret;
1317   for(set<IntegerVector>::const_iterator i=T.bases.begin();i!=T.bases.end();i++)
1318     {
1319       IntegerVectorList gens;
1320       for(int j=0;j<i->size();j++)gens.push_back(M[(*i)[j]]);
1321       ret.push_back(PolyhedralCone::givenByRays(gens,lines,n));
1322     }
1323   return ret;
1324 }
1325