1 /*
2  * bsptree.cpp
3  *
4  *  Created on: Feb 5, 2011
5  *      Author: anders
6  */
7 
8 #include "linalg.h"
9 #include "bsptree.h"
10 #include "lp.h"
11 #include "matrix.h"
12 #include "log.h"
13 
buildHyperplanes()14   void BSPTree::buildHyperplanes()
15   {
16     set<IntegerVector> temp;
17     IntegerVector v;
18     for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();i++)
19       {
20         i->assignEquation(v);
21         temp.insert(v);
22       }
23     hyperplanes=vector<IntegerVector>(temp.size());
24     int I=0;
25     for(set<IntegerVector>::const_iterator i=temp.begin();i!=temp.end();i++,I++)
26       hyperplanes[I]=*i;
27   }
28 
29   /* Figure out what the right assumptions are. These seem not to be right:
30    * A is assumed to be full-dimensional.
31    * B is assumed to be of codimension 1 with known facets and implied equations.
32    */
isIntersectionOfCodimensionOne(PolyhedralCone const & A,BSPTree::SmallCone const & B)33   static bool isIntersectionOfCodimensionOne(PolyhedralCone const &A, BSPTree::SmallCone const &B)
34   {
35 
36     IntegerVectorList strictInequalities=A.getHalfSpaces();
37     IntegerVectorList strictInequalities2=B.getHalfSpaces();
38     for(IntegerVectorList::const_iterator i=strictInequalities2.begin();i!=strictInequalities2.end();i++)strictInequalities.push_back(*i);
39     if(B.getEquations().size()!=1)
40       {
41 assert(0);        //debug<<B;
42       }
43     assert(B.getEquations().size()==1);
44     strictInequalities.push_front(B.getEquations().front());
45     IntegerVector ei(strictInequalities.size());ei[0]=1;
46 //    bool originalReturnValue=hasInteriorPoint(strictInequalities, false, &ei);
47 
48 
49     //////////////////
50     IntegerVectorList inequalities;
51       IntegerVectorList::const_iterator i=strictInequalities.begin();i++;
52       for(;i!=strictInequalities.end();i++)
53         inequalities.push_back(concatenation(-IntegerVector::standardVector(1,0),*i));
54       IntegerVectorList equations;
55       equations.push_back(concatenation(IntegerVector(1),strictInequalities.front()));
56       bool fastReturnValue=hasHomogeneousSolution(A.ambientDimension()+1,inequalities,equations);
57 
58   //    assert(originalReturnValue==fastReturnValue);
59       /////////////////
60     return fastReturnValue;
61 
62 //    return originalReturnValue;
63   }
isInClosedHalfSpace(BSPTree::SmallCone const & A,IntegerVector const & normal)64   static bool isInClosedHalfSpace(BSPTree::SmallCone const &A, IntegerVector const &normal)
65   {
66     //WE ALSO NEED TO CHECK LINEALITYSPACE!
67     IntegerVectorList temp2=A.generatorsOfLinealitySpace();
68     for(IntegerVectorList::const_iterator i=temp2.begin();i!=temp2.end();i++)
69       if(dotLong(normal,*i)!=0)return false;
70 
71 
72 
73     IntegerVectorList temp=A.extremeRays();
74     for(IntegerVectorList::const_iterator i=temp.begin();i!=temp.end();i++)
75       if(dotLong(normal,*i)<0)return false;
76     return true;
77   }
78 
79 
80   class ProgressPrinter
81   {
82 public:
83     static int depth;
84     static char s[16];
85     static int timeToPrint;
86   public:
ProgressPrinter()87     ProgressPrinter()
88     {
89       if(depth>0 && depth<17)s[depth-1]++;
90       depth++;
91       if(depth<17)s[depth-1]=0;
92 
93       timeToPrint++;
94       if(depth<16)
95 //      if(!(timeToPrint&1))
96         {
97           log1 debug<<"Progress:";
98           log1 for(int i=0;(i<depth-1)&&(i<16);i++)
99               debug<<((s[i]-1)?"1":"0");
100           log1 debug<<"\n";
101         }
102     }
~ProgressPrinter()103     ~ProgressPrinter()
104     {
105       depth--;
106     }
107   };
108   int ProgressPrinter::depth;
109   char ProgressPrinter::s[16];
110   int ProgressPrinter::timeToPrint;
111 
heuristic1(PolyhedralCone const & region,vector<int> const & active)112   IntegerVector BSPTree::heuristic1(PolyhedralCone const &region, vector<int> const &active)
113     {
114     int index=active[rand()%active.size()];
115     assert(theCones[index].getEquations().size()==1);
116     IntegerVector normal=theCones[index].getEquations().front();
117 
118     {
119       map<IntegerVector,int> M;
120       for(vector<int>::const_iterator i=active.begin();i!=active.end();i++)
121         {
122           M[theCones[*i].getEquations().front()]++;
123         }
124       int highScore=0;
125       IntegerVector const *p=0;
126       for(map<IntegerVector,int>::const_iterator i=M.begin();i!=M.end();i++)
127         {
128           if(highScore<i->second)
129             {
130               highScore=i->second;
131               p=&(i->first);
132             }
133         }
134       normal=*p;
135     }
136     return normal;
137     }
138 
heuristic2(PolyhedralCone const & region,vector<int> const & active)139   IntegerVector BSPTree::heuristic2(PolyhedralCone const &region, vector<int> const &active)
140   {
141     if(active.size()<1000)return heuristic1(region,active);
142 
143     int bestScore=1000;
144     IntegerVector bestNormal=theCones[active[0]].getEquations().front();
145 
146     for(int i=0;i<100;i++)
147       {
148         int index=active[rand()%active.size()];
149         int inPlane=0;
150         int right=0;
151         int left=0;
152 
153         IntegerVector normal=theCones[index].getEquations().front();
154 
155         IntegerVectorList temp;temp.push_back(normal);
156         IntegerVectorList empty;
157         PolyhedralCone rightRegion=intersection(region,PolyhedralCone(temp,empty));
158         PolyhedralCone leftRegion=intersection(region,PolyhedralCone(temp,empty).negated());
159         PolyhedralCone hyperPlane=intersection(region,PolyhedralCone(empty,temp));
160 
161 
162         for(int j=0;j<100;j++)
163           {
164 //          int r=
165               int rindex=active[rand()%active.size()];
166           if(dependent(normal,theCones[rindex].getEquations().front()))inPlane++;
167           else
168             {
169             if(isIntersectionOfCodimensionOne(leftRegion,theCones[rindex]))left++;
170             if(isIntersectionOfCodimensionOne(rightRegion,theCones[rindex]))right++;
171             }
172           }
173         int score=left+right;
174 
175         debug<<inPlane<<" "<<left<<" "<<right<<" "<<left+right<<"\n";
176 
177         if(score<bestScore)
178           {
179             bestScore=score;
180             bestNormal=normal;
181           }
182       }
183       return bestNormal;
184 //    return heuristic1(region,active);
185   }
186 
187 
buildTree(PolyhedralCone const & region,vector<int> const & active)188   BSPTree::Node *BSPTree::buildTree(PolyhedralCone const &region, vector<int> const &active)
189   {
190     ProgressPrinter PP;
191   //  depth++;
192   //  debug<<"Size:"<<(int)active.size()<<"\n";
193     if(active.size()==0)return 0;
194 
195     IntegerVector normal=heuristic1(region,active);
196 
197     vector<int> conesInHyperplane;
198     vector<int> conesLeft;
199     vector<int> conesRight;
200     IntegerVectorList temp;temp.push_back(normal);
201     IntegerVectorList empty;
202     PolyhedralCone rightRegion=intersection(region,PolyhedralCone(temp,empty));
203     PolyhedralCone leftRegion=intersection(region,PolyhedralCone(temp,empty).negated());
204     PolyhedralCone hyperPlane=intersection(region,PolyhedralCone(empty,temp));
205     int counter=0;
206     for(vector<int>::const_iterator i=active.begin();i!=active.end();i++)
207       {
208         counter++;
209         log1 if(!(counter&(4096*4-1)))debug<<counter<<"\n";
210         /*
211          * Cases:
212          * The intersection of the cone with the relative interior of the left region is of codimension 1
213          * The intersection of the cone with the relative interior of the right region is of codimension 1
214          * None of these are the case, then the cone is contained in the chosen hyperplane, and should be added to the node.
215          */
216 
217 //        PolyhedralCone iHyperplane=intersection(theCones[*i],hyperPlane);
218 //        iHyperplane.findImpliedEquations();
219 //        if(iHyperplane.dimension()==n-1)
220         if(dependent(normal,theCones[*i].getEquations().front()))
221           conesInHyperplane.push_back(*i);
222         else
223           {
224             bool A=isInClosedHalfSpace(theCones[*i],-normal);
225             bool B=isInClosedHalfSpace(theCones[*i],normal);
226 //            if(isInClosedHalfSpace(theCones[*i],-normal)||!isInClosedHalfSpace(theCones[*i],normal))
227             if(A||!B)
228             if(isIntersectionOfCodimensionOne(leftRegion,theCones[*i]))
229               conesLeft.push_back(*i);
230 //            if(isInClosedHalfSpace(theCones[*i],normal)||!isInClosedHalfSpace(theCones[*i],-normal))
231             if(B||!A)
232             if(isIntersectionOfCodimensionOne(rightRegion,theCones[*i]))
233               conesRight.push_back(*i);
234           }
235       }
236     if(PP.depth<10+15)debug<<PP.depth<<":"<<(int)conesInHyperplane.size()<<" "<<(int)conesLeft.size()<<" "<<(int)conesRight.size()<<"\n";
237     return new Node(
238         buildTree(leftRegion,conesLeft),
239         buildTree(rightRegion,conesRight),
240         normal,conesInHyperplane);
241   }
BSPTree(int n_,vector<BSPTree::SmallCone> const & theCones_,PolyhedralCone const * restrictingCone,bool doBuild)242   BSPTree::BSPTree(int n_, vector<BSPTree::SmallCone> const &theCones_, PolyhedralCone const *restrictingCone, bool doBuild):
243     theCones(theCones_),
244     n(n_),
245     hasBeenBuilt(false)
246     {
247       buildHyperplanes();
248       vector<int> active(theCones.size());
249       for(int i=0;i<active.size();i++)active[i]=i;
250       if(doBuild)
251         {
252           if(restrictingCone)
253             root=buildTree(*restrictingCone,active);
254           else
255             root=buildTree(PolyhedralCone(n),active);
256           hasBeenBuilt=true;
257         }
258       else
259         root=0;
260     }
isOnRightHandSide(IntegerVectorList const & omega,IntegerVector const & normal)261   bool BSPTree::isOnRightHandSide(IntegerVectorList const &omega, IntegerVector const &normal)
262   {
263     for(IntegerVectorList::const_iterator i=omega.begin();i!=omega.end();i++)
264       {
265         if(dotLong(*i,normal)>0)return true;
266         if(dotLong(*i,normal)<0)return false;
267       }
268     for(int i=0;i<normal.size();i++)
269       {
270         if(normal[i]>0)return true;
271         if(normal[i]<0)return false;
272       }
273     assert(0);
274     return true;
275   }
glue(PolyhedralCone A,PolyhedralCone B,IntegerVector const & normal)276   PolyhedralCone BSPTree::glue(PolyhedralCone A, PolyhedralCone B, IntegerVector const &normal)
277   {
278     A.findFacets();
279     B.findFacets();
280     IntegerVectorList inequalitiesA=A.getHalfSpaces();
281     IntegerVectorList inequalitiesB=B.getHalfSpaces();
282     set<IntegerVector> inequalities;
283     for(IntegerVectorList::const_iterator i=inequalitiesA.begin();i!=inequalitiesA.end();i++)
284       if(!dependent(*i,normal))inequalities.insert(normalized(*i));
285     for(IntegerVectorList::const_iterator i=inequalitiesB.begin();i!=inequalitiesB.end();i++)
286       if(!dependent(*i,normal))inequalities.insert(normalized(*i));
287     IntegerVectorList empty;
288     IntegerVectorList inequalities2;for(set<IntegerVector>::const_iterator i=inequalities.begin();i!=inequalities.end();i++)inequalities2.push_back(*i);
289     PolyhedralCone ret(inequalities2,empty,normal.size(),PCP_facetsKnown|PCP_impliedEquationsKnown);
290     return ret;
291 //    ret.canonicalize();
292 
293 #if 0
294     //Assumes that A and B are full dimensional.
295     A.canonicalize();
296     B.canonicalize();
297 /*    debug<<"Gluing:\n";
298     debug<<normal<<"\n";
299     debug<<A;
300     debug<<B;
301 */
302   /*  {
303       PolyhedralCone in=intersection(A,B);
304       IntegerVector v=in.getRelativeInteriorPoint();
305       PolyhedralCone FA=A.faceContaining(v);
306       PolyhedralCone FB=B.faceContaining(v);
307 
308       FA.canonicalize();
309       FB.canonicalize();
310       debug<<"FA"<<FA;
311       debug<<"FB"<<FB;
312       assert(!(FA<FB));
313       assert(!(FB<FA));
314     }
315 */
316 
317 
318     IntegerVectorList inequalitiesA=A.getHalfSpaces();
319     IntegerVectorList inequalitiesB=B.getHalfSpaces();
320     IntegerVectorList inequalities;
321     for(IntegerVectorList::const_iterator i=inequalitiesA.begin();i!=inequalitiesA.end();i++)
322       if(!dependent(*i,normal))inequalities.push_back(*i);
323     for(IntegerVectorList::const_iterator i=inequalitiesB.begin();i!=inequalitiesB.end();i++)
324       if(!dependent(*i,normal))inequalities.push_back(*i);
325 
326     //debug<<inequalities;
327     IntegerVectorList empty;
328     PolyhedralCone ret(inequalities,empty,normal.size());
329     ret.canonicalize();
330     //debug<<"RET"<<ret;
331 /*
332     {
333       IntegerVectorList generatorsA=A.extremeRays();
334       IntegerVectorList generatorsB=B.extremeRays();
335       IntegerVectorList generatorsAL=A.generatorsOfLinealitySpace();
336       IntegerVectorList generatorsBL=B.generatorsOfLinealitySpace();
337       for(IntegerVectorList::const_iterator i=generatorsB.begin();i!=generatorsB.end();i++)generatorsA.push_back(*i);
338       for(IntegerVectorList::const_iterator i=generatorsBL.begin();i!=generatorsBL.end();i++)generatorsAL.push_back(*i);
339       PolyhedralCone ret2=PolyhedralCone::givenByRays(generatorsA,generatorsAL,A.ambientDimension());
340       ret2.canonicalize();
341       debug<<"RET2"<<ret2;
342       assert(ret.contains(ret2));
343       assert(ret2.contains(ret));
344       assert(!(ret2<ret));
345       assert(!(ret<ret2));
346 //      return ret2;
347 //      assert(ret==ret2);
348     }*/
349     return ret;
350 #endif
351     }
352 
regionRek(PolyhedralCone const & C,IntegerVectorList const & omega,const Node * tree) const353   PolyhedralCone BSPTree::regionRek(PolyhedralCone const &C, IntegerVectorList const &omega, const Node *tree)const
354   {
355     if(tree==0)return C;
356     IntegerVectorList empty;
357     IntegerVectorList temp;temp.push_back(tree->normal);
358     PolyhedralCone hyperPlane(empty,temp);
359     PolyhedralCone rightHalfSpace(temp,empty);//HERE
360     PolyhedralCone leftHalfSpace=rightHalfSpace.negated();
361     int sideWeAreOn=isOnRightHandSide(omega,tree->normal);
362     IntegerVectorList tempIneq=C.getHalfSpaces();tempIneq.push_back(sideWeAreOn?tree->normal:-tree->normal);
363     PolyhedralCone tempIntersection(tempIneq,empty,n,PCP_impliedEquationsKnown);
364 //    PolyhedralCone A=regionRek(intersection(C,sideWeAreOn?rightHalfSpace:leftHalfSpace),omega,tree->leftRight[sideWeAreOn]);
365     PolyhedralCone A=regionRek(tempIntersection,omega,tree->leftRight[sideWeAreOn]);
366 
367     bool isANormal=false;
368     A.findFacets();
369     IntegerVectorList normals=A.getHalfSpaces();
370     for(IntegerVectorList::const_iterator i=normals.begin();i!=normals.end();i++)
371       if(dependent(tree->normal,*i)){isANormal=true;break;}
372     if(!isANormal)return A;
373 
374 
375     PolyhedralCone iA(normals,temp,n,PCP_impliedEquationsKnown);
376 //    PolyhedralCone iA=intersection(A,hyperPlane);
377 //    iA.findImpliedEquations();
378 
379 
380 //    if(iA.dimension()==n-1)
381       {
382       IntegerVector v=iA.getRelativeInteriorPoint();
383       bool isContained=false;
384       for(vector<int>::const_iterator i=tree->conesInHyperplane.begin();i!=tree->conesInHyperplane.end();i++)
385         if(theCones[*i].contains(v)){isContained=true;break;}
386       if(!isContained)
387         {
388           IntegerVectorList omega2;
389           omega2.push_back(v);omega2.push_back(sideWeAreOn?-(tree->normal):tree->normal);//HERE
390           IntegerVectorList tempIneq2=C.getHalfSpaces();tempIneq2.push_back(sideWeAreOn?-tree->normal:tree->normal);
391           PolyhedralCone tempIntersection2(tempIneq2,empty,n,PCP_impliedEquationsKnown);
392           PolyhedralCone B=regionRek(tempIntersection2,omega2,tree->leftRight[1-sideWeAreOn]);
393 //          PolyhedralCone B=regionRek(intersection(C,sideWeAreOn?leftHalfSpace:rightHalfSpace),omega2,tree->leftRight[1-sideWeAreOn]);
394           return glue(A,B,tree->normal);
395         }
396       }
397     return A;
398   }
region(IntegerVectorList const & omega) const399   PolyhedralCone BSPTree::region(IntegerVectorList const &omega)const
400   {
401     assert(hasBeenBuilt);
402     PolyhedralCone C=PolyhedralCone(n);
403     return regionRek(C,omega,root);
404   }
printRek(Node const * p)405   void BSPTree::printRek(Node const *p)
406   {
407     if(p)
408       {
409         debug<<p->normal;
410         debug<<"[";
411         printRek(p->leftRight[1]);
412         debug<<":";
413         printRek(p->leftRight[0]);
414         debug<<"]\n";
415       }
416 
417   }
print() const418   void BSPTree::print()const
419   {
420     printRek(root);
421   }
numberOfRegionsRek(Node const * v) const422   int BSPTree::numberOfRegionsRek(Node const *v)const
423   {
424     if(v==0)return 1;
425     return numberOfRegionsRek(v->leftRight[0])+numberOfRegionsRek(v->leftRight[1]);
426   }
numberOfRegions() const427   int BSPTree::numberOfRegions()const
428   {
429     return numberOfRegionsRek(root);
430   }
431 
isPerturbedDotProductPositive(IntegerVector const & p,IntegerVector const & ineq)432   static bool isPerturbedDotProductPositive(IntegerVector const &p, IntegerVector const &ineq)
433     {
434       if(dotLong(p,ineq)>0)return true;
435       if(dotLong(p,ineq)<0)return false;
436       for(int i=0;i<p.size();i++)
437         {
438           if(ineq[i]>0)return true;
439           if(ineq[i]<0)return false;
440         }
441       assert(ineq.isZero());
442       return false;
443     }
444 
445   /**
446    * Given vectors u,p and hyperplanes h1 h2, decide if the ray going from u to a lex perturbed p intersects h1 before h2.
447    */
before(IntegerVector const & u,IntegerVector const & p,IntegerVector const & h1,IntegerVector const & h2)448   static bool before(IntegerVector const &u, IntegerVector const &p, IntegerVector const &h1, IntegerVector const &h2)
449   {
450     /*
451      * The ray is (after scaling) parameterized as follows
452      * v(t)=tu+b+eps*e_1+...+eps^n*e_n
453      * where t goes from infinity through 0 to minus infinity.
454      *
455      * The times for intersection are
456      * t_i=(hi*b+eps*hi_1+...+eps^n*hi_n)/(-u*hi)
457      * WLOG we assume that u*hi>0
458      *
459      * Hence we check if
460      * (h1*b+eps*h1_1+...+eps^n*h1_n)*(u*h2) < (h2*b+eps*h2_1+...+eps^n*h2_n)*(u*h1)
461      */
462 /*    int64 uh1=dotLong(u,h1);
463     int64 uh2=dotLong(u,h2);
464     int64 ph1=dotLong(p,h1);
465     int64 ph2=dotLong(p,h2);
466 */
467     int64 uh1,uh2,ph1,ph2;
468     dotLong4(u,p,h1,h2,uh1,uh2,ph1,ph2);
469     bool flag=(uh1<0)^(uh2<0);
470 /*    if(uh1<0)
471       {
472         uh1=-uh1;
473         h1=-h1;
474       }
475     if(uh2<0)
476       {
477         uh2=-uh2;
478         h2=-h2;
479       }
480     if(dotLong(h1,p)*uh2>dotLong(h2,p)*uh1)return false^flag;
481     if(dotLong(h1,p)*uh2<dotLong(h2,p)*uh1)return true^flag;
482 */
483     if(ph1*uh2>ph2*uh1)return false^flag;
484     if(ph1*uh2<ph2*uh1)return true^flag;
485     for(int i=0;i<u.size();i++)
486       {
487         if(h1[i]*uh2>h2[i]*uh1)return false^flag;
488         if(h1[i]*uh2<h2[i]*uh1)return true^flag;
489       }
490     if(flag)assert((h1+h2).isZero());
491     else assert((h1-h2).isZero());
492     return false;
493   }
494 
495 /**
496  * Checks if the given vector is in the complement of the stored cones.
497  */
isInComplement(IntegerVector const & v) const498   bool BSPTree::isInComplement(IntegerVector const &v)const
499   {
500     for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();i++)
501       if(i->contains(v))return false;
502     return true;
503   }
504 
505   /**
506    * Returns random vector in complement.
507    */
randomVectorInComplement() const508   IntegerVector BSPTree::randomVectorInComplement()const
509   {
510     while(1)
511       {
512         IntegerVector ret=randomIntegerVector(n,100);
513 
514         if(isInComplement(ret))return ret;
515       }
516     return IntegerVector();
517   }
518 
519 
520   /**
521    * Given a vector u and a vector n, such that none of the stored cones contain u+epsilon n for epsilon>0 sufficient small,
522    * find a vector ret in the span of u and n such that the open line segment between u and ret does intersect any of the
523    * stored cones.
524    */
perturbationToVectorInComplement(IntegerVector const & u,IntegerVector const & normal) const525   IntegerVector BSPTree::perturbationToVectorInComplement(IntegerVector const &u, IntegerVector const &normal)const
526   {
527 /*    if(theCones.size()==0)return u+normals;
528     vector<SmallCone>::const_iterator best=theCones.end();
529     for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();i++)
530       {
531         IntegerVector equation=i->getEquation().front();
532         if(dotLong(equation,u)==0)continue;
533 
534       }
535 
536       */
537     //Fix this later
538 
539     bool found=false;
540     IntegerVector const *current=0;
541     for(vector<IntegerVector>::const_iterator i=hyperplanes.begin();i!=hyperplanes.end();i++)
542       {
543         if(dotLong(*i,u)){
544             current=&*i;
545             found=true;
546         }
547       }
548     if(!found)
549       {
550         return normal;
551       }
552     for(vector<IntegerVector>::const_iterator i=hyperplanes.begin();i!=hyperplanes.end();i++)
553       if(dotLong(*i,u))
554         if(before(u, normal, *i, *current))current=&*i;
555 
556     int s=1;
557     int64 ud=dotLong(*current,u);
558     IntegerVector ret=u+normal;
559     for(int i=0;i<30;i++)
560       {
561         if(ud<0 && dotLong(*current,ret)<0)return ret;
562         if(ud>0 && dotLong(*current,ret)>0)return ret;
563         s*=2;
564         ret+=s*u;
565       }
566     assert(0);
567     return 100*u+normal;
568   }
569 
570 
571   /**
572    * Given a subset of the stored cones, a vector u in the complement and a point p, find the first codimension one intersecting
573    * the ray starting at u and passing through a lex perturbation of p.
574    */
firstIntersectionNormal(IntegerVector const & u,IntegerVector const & p,vector<SmallCone>::const_iterator i) const575   IntegerVector BSPTree::firstIntersectionNormal(IntegerVector const &u, IntegerVector const &p, vector<SmallCone>::const_iterator i)const
576   {
577     IntegerVector ret;
578     bool found=false;
579     IntegerVector equation;
580 //    for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();i++)
581       for(;i!=theCones.end();i++)
582       {
583 
584         i->assignEquation(equation);
585       //  IntegerVectorList equations=i->getEquations();
586       //  assert(equations.size()==1);
587       //  IntegerVector equation=equations.front();
588         // check if equation is better that current
589         if(dotLong(equation,u))
590         if(!found || before(u,p,equation,ret))
591           {
592             bool doIntersect=true;
593             int doint=i->doIntersectNonPerturbed(u,p);
594             if(doint==2)goto noTestNeeded;
595             if(doint==0)continue;
596             //check if ray intersects cone
597             {
598                 IntegerVectorList inequalities=i->getHalfSpaces();
599             for(IntegerVectorList::const_iterator j=inequalities.begin();j!=inequalities.end();j++)
600               {
601                 int64 ju=dotLong(*j,u);
602 
603 
604                 if( (ju==0)&& !isPerturbedDotProductPositive(p,*j)||
605                     (ju>0)&&before(u,p,*j,equation)||
606                     (ju<0)&&before(u,p,equation,*j))
607                   {
608                     doIntersect=false;
609                     break;
610                   }
611               }
612             }
613             noTestNeeded:
614             if(doIntersect)
615               {
616 /*                if(ret.size())
617                 for(int k=0;k<12;k++)
618                   {
619                     IntegerVector temp=k*p+(10-k)*u;
620                     D((int)dotLong(ret,temp));
621                     D((int)dotLong(equation,temp));
622                   }*/
623                 ret=equation;
624                 found=true;
625             }
626           }
627       }
628     assert(found);
629     return ret;
630   }
631 
632 
633   /**
634    * Given a vector u not contained in any of the stored cones find the closure of the connected component of the complement
635    * of the stored cones containing u.
636    */
regionFast(IntegerVector const & u) const637   PolyhedralCone BSPTree::regionFast(IntegerVector const &u)const
638   {
639 if(0)    {
640       static int abort;
641       if(!abort)D(abort);
642       abort++;
643       if(abort>1000)assert(0);
644     }
645     assert(u.size()==n);
646     PolyhedralCone ret=(n);
647     IntegerVectorList ineq;
648     IntegerVectorList ineqNeg;
649     for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();)
650       {
651         bool skip=false;
652 #if 0
653         IntegerVectorList gen;i->appendGeneratorsOfLinealitySpace(gen);
654         IntegerVectorList rays;i->appendExtremeRays(rays);
655 //        IntegerVectorList ineq=ret.getHalfSpaces();
656         for(IntegerVectorList::const_iterator j=ineq.begin();j!=ineq.end();j++)
657           {
658             bool isCert=true;
659             for(IntegerVectorList::const_iterator i=gen.begin();i!=gen.end();i++)
660               if(dotLong(*i,*j)!=0){isCert=false;goto leave;}
661             for(IntegerVectorList::const_iterator i=rays.begin();i!=rays.end();i++)
662               if(dotLong(*i,*j)>0){isCert=false;goto leave;}
663         leave:
664           if(isCert){skip=true;break;}
665           }
666 #else
667         for(IntegerVectorList::const_iterator j=ineqNeg.begin();j!=ineqNeg.end();j++)
668           {
669             if(i->doesSatisfyInequalityExpensive(*j)){skip=true;break;}
670           }
671 #endif
672 //          D(skip);
673 
674           if(!skip && isIntersectionOfCodimensionOne(ret,*i))
675           {
676             PolyhedralCone B=intersection(ret,PolyhedralCone(i->getHalfSpaces(),i->getEquations(),n));
677             IntegerVector p=B.getRelativeInteriorPoint();
678             IntegerVector w=firstIntersectionNormal(u,p,i);
679             if(dotLong(w,u)<0)w=-w;
680             IntegerVectorList temp;temp.push_back(w);
681             ret=intersection(ret,PolyhedralCone(temp,IntegerVectorList(),n));
682             ineq.push_back(w);
683             ineqNeg.push_back(-w);
684             assert(ret.contains(u));
685           }
686           else
687             i++;
688       }
689     return ret;
690   }
691 
multiplicity(IntegerVector const & v,IntegerVector const & normal) const692   int BSPTree::multiplicity(IntegerVector const &v, IntegerVector const &normal)const
693   {
694 	  int ret=0;
695 	  IntegerVectorList temp;temp.push_back(normal);
696 	  IntegerMatrix t=rowsToIntegerMatrix(temp);
697 	  FieldMatrix M=integerMatrixToFieldMatrix(t,Q);
698 	  IntegerVectorList l=fieldMatrixToIntegerMatrixPrimitive(M.reduceAndComputeKernel()).getRows();
699 	  l.push_front(v);
700 	  for(vector<SmallCone>::const_iterator i=theCones.begin();i!=theCones.end();i++)
701 		  if(i->contains(v))
702 		  {
703 			  ret+=i->multiplicity();
704 		  }
705 
706 	  return ret;
707   }
708