source: git/gfanlib/gfanlib_zcone.cpp @ 5cea7a

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