source: git/gfanlib/gfanlib_zcone.cpp @ 6ce030f

spielwiese
Last change on this file since 6ce030f was e543dd, checked in by Frank Seelisch <seelisch@…>, 13 years ago
new gfanlib from Anders git-svn-id: file:///usr/local/Singular/svn/trunk@14098 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 33.4 KB
Line 
1/*
2 * lib_cone.cpp
3 *
4 *  Created on: Sep 29, 2010
5 *      Author: anders
6 */
7
8#include "gfanlib_zcone.h"
9
10#include <vector>
11#include <set>
12
13#include "setoper.h"
14#include "cdd.h"
15
16namespace gfan{
17
18  static void cddinitGmp()
19  {
20    static bool initialized;
21    if(!initialized)
22      {
23        dd_set_global_constants();  /* First, this must be called. */
24        initialized=true;
25      }
26  }
27
28
29class LpSolver
30{
31  static dd_MatrixPtr ZMatrix2MatrixGmp(ZMatrix const &g, dd_ErrorType *Error)
32  {
33    int n=g.getWidth();
34    dd_MatrixPtr M=NULL;
35    dd_rowrange m_input,i;
36    dd_colrange d_input,j;
37    dd_RepresentationType rep=dd_Inequality;
38    dd_boolean found=dd_FALSE, newformat=dd_FALSE, successful=dd_FALSE;
39    char command[dd_linelenmax], comsave[dd_linelenmax];
40    dd_NumberType NT;
41
42    (*Error)=dd_NoError;
43
44    rep=dd_Inequality; newformat=dd_TRUE;
45
46    m_input=g.getHeight();
47    d_input=n+1;
48
49    NT=dd_Rational;
50
51    M=dd_CreateMatrix(m_input, d_input);
52    M->representation=rep;
53    M->numbtype=NT;
54
55    for (i = 0; i < m_input; i++) {
56      dd_set_si(M->matrix[i][0],0);
57      for (j = 1; j < d_input; j++) {
58        g[i][j-1].setGmp(mpq_numref(M->matrix[i][j]));
59        mpz_init_set_ui(mpq_denref(M->matrix[i][j]), 1);
60        mpq_canonicalize(M->matrix[i][j]);
61      }
62    }
63
64    successful=dd_TRUE;
65
66    return M;
67  }
68  static dd_MatrixPtr ZMatrix2MatrixGmp(ZMatrix const &inequalities, ZMatrix const &equations, dd_ErrorType *err)
69  {
70    ZMatrix g=inequalities;
71    g.append(equations);
72    int numberOfInequalities=inequalities.getHeight();
73    int numberOfRows=g.getHeight();
74    dd_MatrixPtr A=NULL;
75    cddinitGmp();
76    A=ZMatrix2MatrixGmp(g, err);
77    for(int i=numberOfInequalities;i<numberOfRows;i++)
78      set_addelem(A->linset,i+1);
79    return A;
80  }
81  static ZMatrix getConstraints(dd_MatrixPtr A, bool returnEquations)
82  {
83    int rowsize=A->rowsize;
84    int n=A->colsize-1;
85
86    ZMatrix ret(0,n);
87    for(int i=0;i<rowsize;i++)
88      {
89        bool isEquation=set_member(i+1,A->linset);
90        if(isEquation==returnEquations)
91          {
92            QVector v(n);
93            for(int j=0;j<n;j++)v[j]=Rational(A->matrix[i][j+1]);
94            ret.appendRow(QToZVectorPrimitive(v));
95          }
96      }
97    return ret;
98  }
99  static bool isFacet(ZMatrix const &g, int index)
100  {
101    bool ret;
102    dd_MatrixPtr M=NULL,M2=NULL,M3=NULL;
103    dd_colrange d;
104    dd_ErrorType err=dd_NoError;
105    dd_rowset redrows,linrows,ignoredrows, basisrows;
106    dd_colset ignoredcols, basiscols;
107    dd_DataFileType inputfile;
108    FILE *reading=NULL;
109
110    cddinitGmp();
111
112    M=ZMatrix2MatrixGmp(g, &err);
113    if (err!=dd_NoError) goto _L99;
114
115    d=M->colsize;
116
117    static dd_Arow temp;
118    dd_InitializeArow(g.getWidth()+1,&temp);
119
120    ret= !dd_Redundant(M,index+1,temp,&err);
121
122    dd_FreeMatrix(M);
123    dd_FreeArow(g.getWidth()+1,temp);
124
125    if (err!=dd_NoError) goto _L99;
126    return ret;
127   _L99:
128    assert(0);
129    return false;
130  }
131
132  /*
133    Heuristic for checking if inequality of full dimensional cone is a
134    facet. If the routine returns true then the inequality is a
135    facet. If it returns false it is unknown.
136   */
137  static bool fastIsFacetCriterion(ZMatrix const &normals, int i)
138  {
139    int n=normals.getWidth();
140    for(int j=0;j<n;j++)
141      if(normals[i][j].sign()!=0)
142        {
143          int sign=normals[i][j].sign();
144          bool isTheOnly=true;
145          for(int k=0;k<normals.getHeight();k++)
146            if(k!=i)
147              {
148                if(normals[i][j].sign()==sign)
149                  {
150                    isTheOnly=false;
151                    break;
152                  }
153              }
154          if(isTheOnly)return true;
155        }
156    return false;
157  }
158
159  static bool fastIsFacet(ZMatrix const &normals, int i)
160  {
161    if(fastIsFacetCriterion(normals,i))return true;
162    return isFacet(normals,i);
163  }
164
165  class MyHashMap
166  {
167    typedef std::vector<std::set<ZVector> > Container;
168    Container container;
169    int tableSize;
170  public:
171    class iterator
172    {
173      class MyHashMap &hashMap;
174      int index; // having index==-1 means that we are before/after the elements.
175      std::set<ZVector>::iterator i;
176    public:
177      bool operator++()
178      {
179        if(index==-1)goto search;
180        i++;
181        while(i==hashMap.container[index].end())
182          {
183            search:
184            index++;
185            if(index>=hashMap.tableSize){
186              index=-1;
187              return false;
188            }
189            i=hashMap.container[index].begin();
190          }
191        return true;
192      }
193      ZVector const & operator*()const
194      {
195        return *i;
196      }
197      ZVector operator*()
198      {
199        return *i;
200      }
201      iterator(MyHashMap &hashMap_):
202        hashMap(hashMap_)
203        {
204          index=-1;
205        }
206    };
207    unsigned int function(const ZVector &v)
208    {
209      unsigned int ret=0;
210      int n=v.size();
211      for(int i=0;i<n;i++)
212        ret=(ret<<3)+(ret>>29)+v.UNCHECKEDACCESS(i).hashValue();
213      return ret%tableSize;
214    }
215    MyHashMap(int tableSize_):
216      container(tableSize_),
217      tableSize(tableSize_)
218      {
219        assert(tableSize_>0);
220      }
221    void insert(const ZVector &v)
222    {
223      container[function(v)].insert(v);
224    }
225    void erase(ZVector const &v)
226    {
227      container[function(v)].erase(v);
228    }
229    iterator begin()
230    {
231      iterator ret(*this);
232      ++    ret;
233      return ret;
234    }
235    int size()
236    {
237      iterator i=begin();
238      int ret=0;
239      do{ret++;}while(++i);
240      return ret;
241    }
242  };
243
244
245  static ZMatrix normalizedWithSumsAndDuplicatesRemoved(ZMatrix const &a)
246  {
247    // TODO: write a version of this function which will work faster if the entries fit in 32bit
248    if(a.getHeight()==0)return a;
249    int n=a.getWidth();
250    ZVector temp1(n);
251//    ZVector temp2(n);
252    ZMatrix ret(0,n);
253    MyHashMap b(a.getHeight());
254
255    for(int i=0;i<a.getHeight();i++)
256      {
257        assert(!(a[i].isZero()));
258        b.insert(a[i].normalized());
259      }
260
261      {
262        MyHashMap::iterator i=b.begin();
263
264        do
265          {
266            MyHashMap::iterator j=i;
267            while(++j)
268              {
269                ZVector const &I=*i;
270                ZVector const &J=*j;
271                for(int k=0;k<n;k++)temp1[k]=I.UNCHECKEDACCESS(k)+J.UNCHECKEDACCESS(k);
272//                normalizedLowLevel(temp1,temp2);
273//                b.erase(temp2);//this can never remove *i or *j
274                b.erase(temp1.normalized());//this can never remove *i or *j
275              }
276          }
277          while(++i);
278      }
279    ZMatrix original(0,n);
280    {
281      MyHashMap::iterator i=b.begin();
282      do
283        {
284          original.appendRow(*i);
285        }
286      while(++i);
287    }
288
289    for(int i=0;i!=original.getHeight();i++)
290      for(int j=0;j!=a.getHeight();j++)
291        if(!dependent(original[i],a[j]))
292            {
293              ZVector const &I=original[i];
294              ZVector const &J=a[j];
295              for(int k=0;k<n;k++)temp1[k]=I.UNCHECKEDACCESS(k)+J.UNCHECKEDACCESS(k);
296//              normalizedLowLevel(temp1,temp2);
297//              b.erase(temp2);//this can never remove *i or *j
298              b.erase(temp1.normalized());//this can never remove *i or *j
299            }
300        {
301          MyHashMap::iterator i=b.begin();
302          do
303          {
304            ZVector temp=*i;
305            ret.appendRow(temp);
306          }
307          while(++i);
308      }
309    return ret;
310  }
311public:
312  static ZMatrix fastNormals(ZMatrix const &inequalities)
313  {
314    ZMatrix normals=normalizedWithSumsAndDuplicatesRemoved(inequalities);
315    for(int i=0;i!=normals.getHeight();i++)
316      if(!fastIsFacet(normals,i))
317        {
318          normals[i]=normals[normals.getHeight()-1];
319          normals.eraseLastRow();
320          i--;
321        }
322    return normals;
323  }
324  void removeRedundantRows(ZMatrix &inequalities, ZMatrix &equations, bool removeInequalityRedundancies)
325  {
326    cddinitGmp();
327    int numberOfEqualities=equations.getHeight();
328    int numberOfInequalities=inequalities.getHeight();
329    int numberOfRows=numberOfEqualities+numberOfInequalities;
330
331    if(numberOfRows==0)return;//the full space, so description is already irredundant
332
333    dd_rowset r=NULL;
334    ZMatrix g=inequalities;
335    g.append(equations);
336
337    dd_LPSolverType solver=dd_DualSimplex;
338    dd_MatrixPtr A=NULL;
339    dd_ErrorType err=dd_NoError;
340
341    A=ZMatrix2MatrixGmp(g,&err);
342    if (err!=dd_NoError) goto _L99;
343
344    for(int i=numberOfInequalities;i<numberOfRows;i++)
345      set_addelem(A->linset,i+1);
346
347    A->objective=dd_LPmax;
348
349    dd_rowset impl_linset;
350    dd_rowset redset;
351    dd_rowindex newpos;
352
353    if(removeInequalityRedundancies)
354      dd_MatrixCanonicalize(&A, &impl_linset, &redset, &newpos, &err);
355    else
356      dd_MatrixCanonicalizeLinearity(&A, &impl_linset, &newpos, &err);
357
358    if (err!=dd_NoError) goto _L99;
359
360    {
361      int n=A->colsize-1;
362      equations=ZMatrix(0,n);     //TODO: the number of rows needed is actually known
363      inequalities=ZMatrix(0,n);  //is known by set_card(). That might save some copying.
364
365      {
366        int rowsize=A->rowsize;
367        QVector point(n);
368        for(int i=0;i<rowsize;i++)
369          {
370            for(int j=0;j<n;j++)point[j]=Rational(A->matrix[i][j+1]);
371            ((set_member(i+1,A->linset))?equations:inequalities).appendRow(QToZVectorPrimitive(point));
372          }
373      }
374      assert(set_card(A->linset)==equations.getHeight());
375      assert(A->rowsize==equations.getHeight()+inequalities.getHeight());
376
377      set_free(impl_linset);
378      if(removeInequalityRedundancies)
379        set_free(redset);
380      free(newpos);
381
382      dd_FreeMatrix(A);
383      return;
384    }
385   _L99:
386    assert(!"Cddlib reported error when called by Gfanlib.");
387  }
388  ZVector relativeInteriorPoint(const ZMatrix &inequalities, const ZMatrix &equations)
389  {
390    QVector retUnscaled(inequalities.getWidth());
391    cddinitGmp();
392    int numberOfEqualities=equations.getHeight();
393    int numberOfInequalities=inequalities.getHeight();
394    int numberOfRows=numberOfEqualities+numberOfInequalities;
395
396    dd_rowset r=NULL;
397    ZMatrix g=inequalities;
398    g.append(equations);
399
400    dd_LPSolverType solver=dd_DualSimplex;
401    dd_MatrixPtr A=NULL;
402    dd_ErrorType err=dd_NoError;
403
404    A=ZMatrix2MatrixGmp(g,&err);
405    if (err!=dd_NoError) goto _L99;
406    {
407      dd_LPSolutionPtr lps1;
408      dd_LPPtr lp,lp1;
409
410      for(int i=0;i<numberOfInequalities;i++)
411        dd_set_si(A->matrix[i][0],-1);
412      for(int i=numberOfInequalities;i<numberOfRows;i++)
413        set_addelem(A->linset,i+1);
414
415      A->objective=dd_LPmax;
416      lp=dd_Matrix2LP(A, &err);
417      if (err!=dd_NoError) goto _L99;
418
419      lp1=dd_MakeLPforInteriorFinding(lp);
420      dd_LPSolve(lp1,solver,&err);
421      if (err!=dd_NoError) goto _L99;
422
423      lps1=dd_CopyLPSolution(lp1);
424
425      assert(!dd_Negative(lps1->optvalue));
426
427      for (int j=1; j <(lps1->d)-1; j++)
428        retUnscaled[j-1]=Rational(lps1->sol[j]);
429
430      dd_FreeLPData(lp);
431      dd_FreeLPSolution(lps1);
432      dd_FreeLPData(lp1);
433      dd_FreeMatrix(A);
434      return QToZVectorPrimitive(retUnscaled);
435    }
436_L99:
437    assert(0);
438    return QToZVectorPrimitive(retUnscaled);
439  }
440  void dual(ZMatrix const &inequalities, ZMatrix const &equations, ZMatrix &dualInequalities, ZMatrix &dualEquations)
441  {
442    int result;
443
444    dd_MatrixPtr A=NULL;
445    dd_ErrorType err=dd_NoError;
446
447    cddinitGmp();
448
449    A=ZMatrix2MatrixGmp(inequalities, equations, &err);
450
451    dd_PolyhedraPtr poly;
452    poly=dd_DDMatrix2Poly2(A, dd_LexMin, &err);
453
454    if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) assert(0);
455
456    dd_MatrixPtr      A2=dd_CopyGenerators(poly);
457
458    dualInequalities=getConstraints(A2,false);
459    dualEquations=getConstraints(A2,true);
460
461    dd_FreeMatrix(A2);
462    dd_FreeMatrix(A);
463    dd_FreePolyhedra(poly);
464
465    return;
466   _L99:
467    assert(0);
468  }
469  // this procedure is take from cddio.c.
470  static void dd_ComputeAinc(dd_PolyhedraPtr poly)
471  {
472  /* This generates the input incidence array poly->Ainc, and
473     two sets: poly->Ared, poly->Adom.
474  */
475    dd_bigrange k;
476    dd_rowrange i,m1;
477    dd_colrange j;
478    dd_boolean redundant;
479    dd_MatrixPtr M=NULL;
480    mytype sum,temp;
481
482    dd_init(sum); dd_init(temp);
483    if (poly->AincGenerated==dd_TRUE) goto _L99;
484
485    M=dd_CopyOutput(poly);
486    poly->n=M->rowsize;
487    m1=poly->m1;
488
489    /* this number is same as poly->m, except when
490        poly is given by nonhomogeneous inequalty:
491        !(poly->homogeneous) && poly->representation==Inequality,
492        it is poly->m+1.   See dd_ConeDataLoad.
493     */
494    poly->Ainc=(set_type*)calloc(m1, sizeof(set_type));
495    for(i=1; i<=m1; i++) set_initialize(&(poly->Ainc[i-1]),poly->n);
496    set_initialize(&(poly->Ared), m1);
497    set_initialize(&(poly->Adom), m1);
498
499    for (k=1; k<=poly->n; k++){
500      for (i=1; i<=poly->m; i++){
501        dd_set(sum,dd_purezero);
502        for (j=1; j<=poly->d; j++){
503          dd_mul(temp,poly->A[i-1][j-1],M->matrix[k-1][j-1]);
504          dd_add(sum,sum,temp);
505        }
506        if (dd_EqualToZero(sum)) {
507          set_addelem(poly->Ainc[i-1], k);
508        }
509      }
510      if (!(poly->homogeneous) && poly->representation==dd_Inequality){
511        if (dd_EqualToZero(M->matrix[k-1][0])) {
512          set_addelem(poly->Ainc[m1-1], k);  /* added infinity inequality (1,0,0,...,0) */
513        }
514      }
515    }
516
517    for (i=1; i<=m1; i++){
518      if (set_card(poly->Ainc[i-1])==M->rowsize){
519        set_addelem(poly->Adom, i);
520      }
521    }
522    for (i=m1; i>=1; i--){
523      if (set_card(poly->Ainc[i-1])==0){
524        redundant=dd_TRUE;
525        set_addelem(poly->Ared, i);
526      }else {
527        redundant=dd_FALSE;
528        for (k=1; k<=m1; k++) {
529          if (k!=i && !set_member(k, poly->Ared)  && !set_member(k, poly->Adom) &&
530              set_subset(poly->Ainc[i-1], poly->Ainc[k-1])){
531            if (!redundant){
532              redundant=dd_TRUE;
533            }
534            set_addelem(poly->Ared, i);
535          }
536        }
537      }
538    }
539    dd_FreeMatrix(M);
540    poly->AincGenerated=dd_TRUE;
541  _L99:;
542    dd_clear(sum);  dd_clear(temp);
543  }
544
545
546  std::vector<std::vector<int> > extremeRaysInequalityIndices(const ZMatrix &inequalities)
547  {
548    int dim2=inequalities.getHeight();
549    if(dim2==0)return std::vector<std::vector<int> >();
550    int dimension=inequalities.getWidth();
551
552    dd_MatrixPtr A=NULL;
553    dd_ErrorType err=dd_NoError;
554
555    cddinitGmp();
556    A=ZMatrix2MatrixGmp(inequalities, &err);
557
558    dd_PolyhedraPtr poly;
559    poly=dd_DDMatrix2Poly2(A, dd_LexMin, &err);
560
561    if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) assert(0);
562    if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
563
564    std::vector<std::vector<int> > ret;
565
566    /*
567      How do we interpret the cddlib output?  For a long ting gfan has
568      been using poly->n as the number of rays of the cone and thus
569      returned sets of indices that actually gave the lineality
570      space. The mistake was then caught later in PolyhedralCone. On Feb
571      17 2009 gfan was changed to check the length of each set to make
572      sure that it does not specify the lineality space and only return
573      those sets giving rise to rays.  This does not seem to be the best
574      strategy and might even be wrong.
575     */
576
577
578    for (int k=1; k<=poly->n; k++)
579      {
580        int length=0;
581        for (int i=1; i<=poly->m1; i++)
582          if(set_member(k,poly->Ainc[i-1]))length++;
583        if(length!=dim2)
584          {
585            std::vector<int> v(length);
586            int j=0;
587            for (int i=1; i<=poly->m1; i++)
588              if(set_member(k,poly->Ainc[i-1]))v[j++]=i-1;
589            ret.push_back(v);
590          }
591      }
592
593    dd_FreeMatrix(A);
594    dd_FreePolyhedra(poly);
595
596    return ret;
597   _L99:
598    assert(0);
599    return std::vector<std::vector<int> >();
600  }
601
602};
603
604LpSolver lpSolver;
605
606bool ZCone::isInStateMinimum(int s)const
607{
608  return state>=s;
609}
610
611
612bool operator<(ZCone const &a, ZCone const &b)
613{
614  assert(a.state>=3);
615  assert(b.state>=3);
616
617  if(a.n<b.n)return true;
618  if(a.n>b.n)return false;
619
620  if(a.equations<b.equations)return true;
621  if(b.equations<a.equations)return false;
622
623  if(a.inequalities<b.inequalities)return true;
624  if(b.inequalities<a.inequalities)return false;
625
626  return false;
627}
628
629
630bool operator!=(ZCone const &a, ZCone const &b)
631{
632  return (a<b)||(b<a);
633}
634
635
636void ZCone::ensureStateAsMinimum(int s)const
637{
638  if((state<1) && (s==1))
639    {
640     {
641        QMatrix m=ZToQMatrix(equations);
642        m.reduce();
643        m.removeZeroRows();
644
645        ZMatrix newInequalities(0,inequalities.getWidth());
646        for(int i=0;i<inequalities.getHeight();i++)
647          {
648            QVector w=ZToQVector(inequalities[i]);
649            w=m.canonicalize(w);
650            if(!w.isZero())
651              newInequalities.appendRow(QToZVectorPrimitive(w));
652          }
653
654        inequalities=newInequalities;
655        inequalities.sortAndRemoveDuplicateRows();
656        equations=QToZMatrixPrimitive(m);
657      }
658
659      if(!(preassumptions&PCP_impliedEquationsKnown))
660      if(inequalities.getHeight()>1)//there can be no implied equation unless we have at least two inequalities
661        lpSolver.removeRedundantRows(inequalities,equations,false);
662
663      assert(inequalities.getWidth()==equations.getWidth());
664      }
665  if((state<2) && (s>=2) && !(preassumptions&PCP_facetsKnown))
666    {
667/*       if(inequalities.size()>25)
668         {
669          IntegerVectorList h1;
670          IntegerVectorList h2;
671          bool a=false;
672          for(IntegerVectorList::const_iterator i=inequalities.begin();i!=inequalities.end();i++)
673            {
674              if(a)
675                h1.push_back(*i);
676              else
677                h2.push_back(*i);
678              a=!a;
679            }
680          PolyhedralCone c1(h1,equations);
681          PolyhedralCone c2(h2,equations);
682          c1.ensureStateAsMinimum(2);
683          c2.ensureStateAsMinimum(2);
684          inequalities=c1.inequalities;
685          for(IntegerVectorList::const_iterator i=c2.inequalities.begin();i!=c2.inequalities.end();i++)
686            inequalities.push_back(*i);
687        }
688*/
689      if(equations.getHeight())
690        {
691          QMatrix m=ZToQMatrix(equations);
692          m.reduce();
693          ZMatrix inequalities2(0,equations.getWidth());
694          for(int i=0;i<inequalities.getHeight();i++)
695            {
696              inequalities2.appendRow(QToZVectorPrimitive(m.canonicalize(ZToQVector(inequalities[i]))));
697            }
698          inequalities=LpSolver::fastNormals(inequalities2);
699          goto noFallBack;
700        fallBack://alternativ (disabled)
701          lpSolver.removeRedundantRows(inequalities,equations,true);
702        noFallBack:;
703        }
704      else
705        inequalities=LpSolver::fastNormals(inequalities);
706    }
707  if((state<3) && (s>=3))
708    {
709      QMatrix equations2=ZToQMatrix(equations);
710      equations2.reduce();
711
712      for(int i=0;i<inequalities.getHeight();i++)
713        {
714          inequalities[i]=QToZVectorPrimitive(equations2.canonicalize(ZToQVector(inequalities[i])));
715        }
716      inequalities.sortRows();
717      equations=QToZMatrixPrimitive(equations2);
718    }
719  if(state<s)
720    state=s;
721}
722
723std::ostream &operator<<(std::ostream &f, ZCone const &c)
724{
725  f<<"Ambient dimension:"<<c.n<<std::endl;
726  f<<"Inequalities:"<<std::endl;
727  f<<c.inequalities<<std::endl;
728  f<<"Equations:"<<std::endl;
729  f<<c.equations<<std::endl;
730}
731
732
733ZCone::ZCone(int ambientDimension):
734  n(ambientDimension),
735  state(1),
736  preassumptions(PCP_impliedEquationsKnown|PCP_facetsKnown),
737  multiplicity(1),
738  haveExtremeRaysBeenCached(false),
739  linearForms(ZMatrix(0,ambientDimension))
740{
741}
742
743
744ZCone::ZCone(ZMatrix const &inequalities_, ZMatrix const &equations_, int preassumptions_):
745  inequalities(inequalities_),
746  equations(equations_),
747  state(0),
748  preassumptions(preassumptions_),
749  multiplicity(1),
750  haveExtremeRaysBeenCached(false),
751  n(inequalities_.getWidth()),
752  linearForms(ZMatrix(0,inequalities_.getWidth()))
753  {
754  assert(preassumptions_<4);//OTHERWISE WE ARE DOING SOMETHING STUPID LIKE SPECIFYING AMBIENT DIMENSION
755  assert(equations_.getWidth()==n);
756  ensureStateAsMinimum(1);
757}
758
759void ZCone::canonicalize()
760{
761  ensureStateAsMinimum(3);
762}
763
764void ZCone::findFacets()
765{
766  ensureStateAsMinimum(2);
767}
768
769ZMatrix ZCone::getFacets()const
770{
771  ensureStateAsMinimum(2);
772  return inequalities;
773}
774
775void ZCone::findImpliedEquations()
776{
777  ensureStateAsMinimum(1);
778}
779
780ZMatrix ZCone::getImpliedEquations()const
781{
782  ensureStateAsMinimum(1);
783  return equations;
784}
785
786ZVector ZCone::getRelativeInteriorPoint()const
787{
788  ensureStateAsMinimum(1);
789//  assert(state>=1);
790
791  return lpSolver.relativeInteriorPoint(inequalities,equations);
792}
793
794ZVector ZCone::getUniquePoint()const
795{
796  ZMatrix rays=extremeRays();
797  ZVector ret(n);
798  for(int i=0;i<rays.getHeight();i++)
799    ret+=rays[i];
800
801  return ret;
802}
803
804ZVector ZCone::getUniquePointFromExtremeRays(ZMatrix const &extremeRays)const
805{
806  ZVector ret(n);
807  for(int i=0;i<extremeRays.getHeight();i++)
808    if(contains(extremeRays[i]))ret+=extremeRays[i];
809  return ret;
810}
811
812
813int ZCone::ambientDimension()const
814{
815  return n;
816}
817
818
819int ZCone::codimension()const
820{
821  return ambientDimension()-dimension();
822}
823
824
825int ZCone::dimension()const
826{
827//  assert(state>=1);
828  ensureStateAsMinimum(1);
829  return ambientDimension()-equations.getHeight();
830}
831
832
833int ZCone::dimensionOfLinealitySpace()const
834{
835  ZMatrix temp=inequalities;
836  temp.append(equations);
837  ZCone temp2(ZMatrix(0,n),temp);
838  return temp2.dimension();
839}
840
841
842bool ZCone::isOrigin()const
843{
844  return dimension()==0;
845}
846
847
848bool ZCone::isFullSpace()const
849{
850  for(int i=0;i<inequalities.getHeight();i++)
851    if(!inequalities[i].isZero())return false;
852  for(int i=0;i<equations.getHeight();i++)
853    if(!equations[i].isZero())return false;
854  return true;
855}
856
857
858ZCone intersection(const ZCone &a, const ZCone &b)
859{
860  assert(a.ambientDimension()==b.ambientDimension());
861  ZMatrix inequalities=a.inequalities;
862  inequalities.append(b.inequalities);
863  ZMatrix equations=a.equations;
864  equations.append(b.equations);
865
866  equations.sortAndRemoveDuplicateRows();
867  inequalities.sortAndRemoveDuplicateRows();
868
869  {
870    ZMatrix Aequations=a.equations;
871    ZMatrix Ainequalities=a.inequalities;
872    Aequations.sortAndRemoveDuplicateRows();
873    Ainequalities.sortAndRemoveDuplicateRows();
874    if((Ainequalities.getHeight()==inequalities.getHeight()) && (Aequations.getHeight()==equations.getHeight()))return a;
875    ZMatrix Bequations=b.equations;
876    ZMatrix Binequalities=b.inequalities;
877    Bequations.sortAndRemoveDuplicateRows();
878    Binequalities.sortAndRemoveDuplicateRows();
879    if((Binequalities.getHeight()==inequalities.getHeight()) && (Bequations.getHeight()==equations.getHeight()))return b;
880  }
881
882  return ZCone(inequalities,equations);
883}
884
885/*
886PolyhedralCone product(const PolyhedralCone &a, const PolyhedralCone &b)
887{
888  IntegerVectorList equations2;
889  IntegerVectorList inequalities2;
890
891  int n1=a.n;
892  int n2=b.n;
893
894  for(IntegerVectorList::const_iterator i=a.equations.begin();i!=a.equations.end();i++)
895    equations2.push_back(concatenation(*i,IntegerVector(n2)));
896  for(IntegerVectorList::const_iterator i=b.equations.begin();i!=b.equations.end();i++)
897    equations2.push_back(concatenation(IntegerVector(n1),*i));
898  for(IntegerVectorList::const_iterator i=a.inequalities.begin();i!=a.inequalities.end();i++)
899    inequalities2.push_back(concatenation(*i,IntegerVector(n2)));
900  for(IntegerVectorList::const_iterator i=b.inequalities.begin();i!=b.inequalities.end();i++)
901    inequalities2.push_back(concatenation(IntegerVector(n1),*i));
902
903  PolyhedralCone ret(inequalities2,equations2,n1+n2);
904  ret.setMultiplicity(a.getMultiplicity()*b.getMultiplicity());
905  ret.setLinearForm(concatenation(a.getLinearForm(),b.getLinearForm()));
906
907  ret.ensureStateAsMinimum(a.state);
908  ret.ensureStateAsMinimum(b.state);
909
910  return ret;
911}*/
912
913
914ZCone ZCone::positiveOrthant(int dimension)
915{
916  return ZCone(ZMatrix::identity(dimension),ZMatrix(0,dimension));
917}
918
919
920ZCone ZCone::givenByRays(ZMatrix const &generators, ZMatrix const &linealitySpace)
921{
922  //rewrite modulo lineality space
923  ZMatrix newGenerators(generators.getHeight(),generators.getWidth());
924  {
925    QMatrix l=ZToQMatrix(linealitySpace);
926    l.reduce();
927    for(int i=0;i<generators.getHeight();i++)
928      newGenerators[i]=QToZVectorPrimitive(l.canonicalize(ZToQVector(generators[i])));
929  }
930
931  ZCone dual(newGenerators,linealitySpace);
932  dual.findFacets();
933  dual.canonicalize();
934  ZMatrix inequalities=dual.extremeRays();
935
936  ZMatrix span=generators;
937  span.append(linealitySpace);
938  QMatrix m2Q=ZToQMatrix(span);
939  ZMatrix equations=QToZMatrixPrimitive(m2Q.reduceAndComputeKernel());
940
941  return ZCone(inequalities,equations);
942}
943
944
945bool ZCone::containsPositiveVector()const
946{
947  ZCone temp=intersection(*this,ZCone::positiveOrthant(n));
948  return temp.getRelativeInteriorPoint().isPositive();
949}
950
951
952bool ZCone::contains(ZVector const &v)const
953{
954  for(int i=0;i<equations.getHeight();i++)
955    {
956      if(!dot(equations[i],v).isZero())return false;
957    }
958  for(int i=0;i<inequalities.getHeight();i++)
959    {
960      if(dot(inequalities[i],v).sign()<0)return false;
961    }
962  return true;
963}
964
965
966bool ZCone::containsRowsOf(ZMatrix const &m)const
967{
968  for(int i=0;i<m.getHeight();i++)
969    if(!contains(m[i]))return false;
970  return true;
971}
972
973
974bool ZCone::contains(ZCone const &c)const
975{
976  ZCone c2=intersection(*this,c);
977  ZCone c3=c;
978  c2.canonicalize();
979  c3.canonicalize();
980  return !(c2!=c3);
981}
982
983
984bool ZCone::containsRelatively(ZVector const &v)const
985{
986  ensureStateAsMinimum(1);
987//  assert(state>=1);
988  for(int i=0;i<equations.getHeight();i++)
989    {
990      if(!dot(equations[i],v).isZero())return false;
991    }
992  for(int i=0;i<inequalities.getHeight();i++)
993    {
994      if(dot(inequalities[i],v).sign()<=0)return false;
995    }
996  return true;
997}
998
999
1000bool ZCone::isSimplicial()const
1001{
1002//  assert(state>=2);
1003  ensureStateAsMinimum(2);
1004  return codimension()+inequalities.getHeight()+dimensionOfLinealitySpace()==n;
1005}
1006
1007
1008ZCone ZCone::linealitySpace()const
1009{
1010  ZCone ret(ZMatrix(0,n),combineOnTop(equations,inequalities));
1011//  ret.ensureStateAsMinimum(state);
1012  return ret;
1013}
1014
1015
1016ZCone ZCone::dualCone()const
1017{
1018  ensureStateAsMinimum(1);
1019//  assert(state>=1);
1020
1021  ZMatrix dualInequalities,dualEquations;
1022  lpSolver.dual(inequalities,equations,dualInequalities,dualEquations);
1023  ZCone ret(dualInequalities,dualEquations);
1024  ret.ensureStateAsMinimum(state);
1025
1026  return ret;
1027}
1028
1029
1030ZCone ZCone::negated()const
1031{
1032  ZCone ret(-inequalities,equations,(areFacetsKnown()?PCP_facetsKnown:0)|(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0));
1033//  ret.ensureStateAsMinimum(state);
1034  return ret;
1035}
1036
1037
1038ZMatrix ZCone::extremeRays(ZMatrix const *generatorsOfLinealitySpace)const
1039{
1040//  assert((dimension()==ambientDimension()) || (state>=3));
1041  if(dimension()!=ambientDimension())
1042    ensureStateAsMinimum(3);
1043
1044  if(haveExtremeRaysBeenCached)return cachedExtremeRays;
1045  ZMatrix ret(0,n);
1046  std::vector<std::vector<int> > indices=lpSolver.extremeRaysInequalityIndices(inequalities);
1047
1048  for(int i=0;i<indices.size();i++)
1049    {
1050      /* At this point we know lineality space, implied equations and
1051         also inequalities for the ray. To construct a vector on the
1052         ray which is stable under (or indendent of) angle and
1053         linarity preserving transformation we find the dimension 1
1054         subspace orthorgonal to the implied equations and the
1055         lineality space and pick a suitable primitive generator */
1056
1057          /* To be more precise,
1058           * let E be the set of equations, and v the inequality defining a  ray R.
1059           * We wish to find a vector satisfying these, but it must also be orthogonal
1060           * to the lineality space of the cone, that is, in the span of {E,v}.
1061           * One way to get such a vector is to project v to E an get a vector p.
1062           * Then v-p is in the span of {E,v} by construction.
1063           * The vector v-p is also in the orthogonal complement to E by construction,
1064           * that is, the span of R.
1065           * We wish to argue that it is not zero.
1066           * That would imply that v=p, meaning that v is in the span of the equations.
1067           * However, that would contradict that R is a ray.
1068           * In case v-p does not satisfy the inequality v (is this possible?), we change the sign.
1069           *
1070           * As a consequence we need the following procedure
1071           * primitiveProjection():
1072           *    Input: E,v
1073           *    Output: A primitive representation of the vector v-p, where p is the projection of v onto E
1074           *
1075           * Notice that the output is a Q linear combination of the input and that p is
1076           * a linear combination of E. The check that p has been computed correctly,
1077           * it suffices to check that v-p satisfies the equations E.
1078           * The routine will actually first compute a multiple of v-p.
1079           * It will do this using floating point arithmetics. It will then transform
1080           * the coefficients to get the multiple of v-p into integers. Then it
1081           * verifies in exact arithmetics, that with these coefficients we get a point
1082           * satisfying E. It then returns the primitive vector on the ray v-p.
1083           * In case of a failure it falls back to an implementation using rational arithmetics.
1084           */
1085
1086
1087          std::vector<int> asVector(inequalities.getHeight());
1088          for(int j=0;j<indices[i].size();j++){asVector[indices[i][j]]=1;}
1089          ZMatrix equations=this->equations;
1090          ZVector theInequality;
1091
1092          for(int j=0;j<asVector.size();j++)
1093            if(asVector[j])
1094              equations.appendRow(inequalities[j]);
1095            else
1096              theInequality=inequalities[j];
1097
1098          assert(!theInequality.isZero());
1099
1100          ZVector thePrimitiveVector;
1101          if(generatorsOfLinealitySpace)
1102          {
1103            QMatrix temp=ZToQMatrix(combineOnTop(equations,*generatorsOfLinealitySpace));
1104            thePrimitiveVector=QToZVectorPrimitive(temp.reduceAndComputeVectorInKernel());
1105          }
1106          else
1107          {
1108            QMatrix linealitySpaceOrth=ZToQMatrix(combineOnTop(this->equations,inequalities));
1109
1110
1111            QMatrix temp=combineOnTop(linealitySpaceOrth.reduceAndComputeKernel(),ZToQMatrix(equations));
1112            thePrimitiveVector=QToZVectorPrimitive(temp.reduceAndComputeVectorInKernel());
1113          }
1114          if(!contains(thePrimitiveVector))thePrimitiveVector=-thePrimitiveVector;
1115          ret.appendRow(thePrimitiveVector);
1116    }
1117
1118  cachedExtremeRays=ret;
1119  haveExtremeRaysBeenCached=true;
1120
1121  return ret;
1122}
1123
1124
1125Integer ZCone::getMultiplicity()const
1126{
1127  return multiplicity;
1128}
1129
1130
1131void ZCone::setMultiplicity(Integer const &m)
1132{
1133  multiplicity=m;
1134}
1135
1136
1137ZMatrix ZCone::getLinearForms()const
1138{
1139  return linearForms;
1140}
1141
1142
1143void ZCone::setLinearForms(ZMatrix const &linearForms_)
1144{
1145  linearForms=linearForms_;
1146}
1147
1148
1149ZMatrix ZCone::quotientLatticeBasis()const
1150{
1151//  assert(isInStateMinimum(1));// Implied equations must have been computed in order to know the span of the cone
1152  ensureStateAsMinimum(1);
1153
1154
1155  int a=equations.getHeight();
1156  int b=inequalities.getHeight();
1157
1158  // Implementation below could be moved to nonLP part of code.
1159
1160  // small vector space defined by a+b equations.... big by a equations.
1161
1162  ZMatrix M=combineLeftRight(combineLeftRight(
1163                                                  equations.transposed(),
1164                                                  inequalities.transposed()),
1165                                 ZMatrix::identity(n));
1166  M.reduce(false,true);
1167  /*
1168    [A|B|I] is reduced to [A'|B'|C'] meaning [A'|B']=C'[A|B] and A'=C'A.
1169
1170    [A'|B'] is in row echelon form, implying that the rows of C' corresponding to zero rows
1171    of [A'|B'] generate the lattice cokernel of [A|B] - that is the linealityspace intersected with Z^n.
1172
1173    [A'] is in row echelon form, implying that the rows of C' corresponding to zero rows of [A'] generate
1174    the lattice cokernel of [A] - that is the span of the cone intersected with Z^n.
1175
1176    It is clear that the second row set is a superset of the first. Their difference is a basis for the quotient.
1177   */
1178  ZMatrix ret(0,n);
1179
1180  for(int i=0;i<M.getHeight();i++)
1181    if(M[i].subvector(0,a).isZero()&&!M[i].subvector(a,a+b).isZero())
1182      {
1183        ret.appendRow(M[i].subvector(a+b,a+b+n));
1184      }
1185
1186  return ret;
1187}
1188
1189
1190ZVector ZCone::semiGroupGeneratorOfRay()const
1191{
1192  ZMatrix temp=quotientLatticeBasis();
1193  assert(temp.getHeight()==1);
1194  for(int i=0;i<inequalities.getHeight();i++)
1195    if(dot(temp[0],inequalities[i]).sign()<0)
1196      {
1197        temp[0]=-temp[0];
1198        break;
1199      }
1200  return temp[0];
1201}
1202
1203
1204ZCone ZCone::link(ZVector const &w)const
1205{
1206  /* Observe that the inequalities giving rise to facets
1207   * also give facets in the link, if they are kept as
1208   * inequalities. This means that the state cannot decrease
1209   * when taking links - that is why we specify the PCP flags.
1210   */
1211  ZMatrix inequalities2(0,n);
1212  for(int j=0;j<inequalities.getHeight();j++)
1213    if(dot(w,inequalities[j]).sign()==0)inequalities2.appendRow(inequalities[j]);
1214  ZCone C(inequalities2,equations,(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0)|(areFacetsKnown()?PCP_facetsKnown:0));
1215  C.ensureStateAsMinimum(state);
1216
1217  C.setLinearForms(getLinearForms());
1218  C.setMultiplicity(getMultiplicity());
1219
1220  return C;
1221}
1222
1223ZCone ZCone::faceContaining(ZVector const &v)const
1224{
1225  assert(n==v.size());
1226  assert(contains(v));
1227  ZMatrix newEquations=equations;
1228  ZMatrix newInequalities(0,n);
1229  for(int i=0;i<inequalities.getHeight();i++)
1230    if(dot(inequalities[i],v).sign()!=0)
1231      newInequalities.appendRow(inequalities[i]);
1232    else
1233      newEquations.appendRow(inequalities[i]);
1234
1235  ZCone ret(newInequalities,newEquations,(state>=1)?PCP_impliedEquationsKnown:0);
1236  ret.ensureStateAsMinimum(state);
1237  return ret;
1238}
1239
1240
1241ZMatrix ZCone::getInequalities()const
1242{
1243  return inequalities;
1244}
1245
1246
1247ZMatrix ZCone::getEquations()const
1248{
1249  return equations;
1250}
1251
1252
1253ZMatrix ZCone::generatorsOfSpan()const
1254{
1255  ensureStateAsMinimum(1);
1256  QMatrix l=ZToQMatrix(equations);
1257  return QToZMatrixPrimitive(l.reduceAndComputeKernel());
1258}
1259
1260
1261ZMatrix ZCone::generatorsOfLinealitySpace()const
1262{
1263  QMatrix l=ZToQMatrix(combineOnTop(inequalities,equations));
1264  return QToZMatrixPrimitive(l.reduceAndComputeKernel());
1265}
1266
1267};
Note: See TracBrowser for help on using the repository browser.