source: git/gfanlib/gfanlib_zcone.cpp @ 19addd1

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