source: git/gfanlib/gfanlib_zcone.cpp @ 74a91c9

spielwiese
Last change on this file since 74a91c9 was def863, checked in by Frank Seelisch <seelisch@…>, 13 years ago
included Anders Jensens gfan lib git-svn-id: file:///usr/local/Singular/svn/trunk@13558 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  state=s;
720}
721
722std::ostream &operator<<(std::ostream &f, ZCone const &c)
723{
724  f<<"Ambient dimension:"<<c.n<<std::endl;
725  f<<"Inequalities:"<<std::endl;
726  f<<c.inequalities<<std::endl;
727  f<<"Equations:"<<std::endl;
728  f<<c.equations<<std::endl;
729}
730
731
732ZCone::ZCone(int ambientDimension):
733  n(ambientDimension),
734  state(1),
735  preassumptions(PCP_impliedEquationsKnown|PCP_facetsKnown),
736  multiplicity(1),
737  haveExtremeRaysBeenCached(false),
738  linearForms(ZMatrix(0,ambientDimension))
739{
740}
741
742
743ZCone::ZCone(ZMatrix const &inequalities_, ZMatrix const &equations_, int preassumptions_):
744  inequalities(inequalities_),
745  equations(equations_),
746  state(0),
747  preassumptions(preassumptions_),
748  multiplicity(1),
749  haveExtremeRaysBeenCached(false),
750  n(inequalities_.getWidth()),
751  linearForms(ZMatrix(0,inequalities_.getWidth()))
752  {
753  assert(preassumptions_<4);//OTHERWISE WE ARE DOING SOMETHING STUPID LIKE SPECIFYING AMBIENT DIMENSION
754  assert(equations_.getWidth()==n);
755  ensureStateAsMinimum(1);
756}
757
758void ZCone::canonicalize()
759{
760  ensureStateAsMinimum(3);
761}
762
763void ZCone::findFacets()
764{
765  ensureStateAsMinimum(2);
766}
767
768ZMatrix ZCone::getFacets()const
769{
770  ensureStateAsMinimum(2);
771  return inequalities;
772}
773
774void ZCone::findImpliedEquations()
775{
776  ensureStateAsMinimum(1);
777}
778
779ZMatrix ZCone::getImpliedEquations()const
780{
781  ensureStateAsMinimum(1);
782  return equations;
783}
784
785ZVector ZCone::getRelativeInteriorPoint()const
786{
787  ensureStateAsMinimum(1);
788//  assert(state>=1);
789
790  return lpSolver.relativeInteriorPoint(inequalities,equations);
791}
792
793ZVector ZCone::getUniquePoint()const
794{
795  ZMatrix rays=extremeRays();
796  ZVector ret(n);
797  for(int i=0;i<rays.getHeight();i++)
798    ret+=rays[i];
799
800  return ret;
801}
802
803ZVector ZCone::getUniquePointFromExtremeRays(ZMatrix const &extremeRays)const
804{
805  ZVector ret(n);
806  for(int i=0;i<extremeRays.getHeight();i++)
807    if(contains(extremeRays[i]))ret+=extremeRays[i];
808  return ret;
809}
810
811
812int ZCone::ambientDimension()const
813{
814  return n;
815}
816
817
818int ZCone::codimension()const
819{
820  return ambientDimension()-dimension();
821}
822
823
824int ZCone::dimension()const
825{
826//  assert(state>=1);
827  ensureStateAsMinimum(1);
828  return ambientDimension()-equations.getHeight();
829}
830
831
832int ZCone::dimensionOfLinealitySpace()const
833{
834  ZMatrix temp=inequalities;
835  temp.append(equations);
836  ZCone temp2(ZMatrix(0,n),temp);
837  return temp2.dimension();
838}
839
840
841bool ZCone::isOrigin()const
842{
843  return dimension()==0;
844}
845
846
847bool ZCone::isFullSpace()const
848{
849  for(int i=0;i<inequalities.getHeight();i++)
850    if(!inequalities[i].isZero())return false;
851  for(int i=0;i<equations.getHeight();i++)
852    if(!equations[i].isZero())return false;
853  return true;
854}
855
856
857ZCone intersection(const ZCone &a, const ZCone &b)
858{
859  assert(a.ambientDimension()==b.ambientDimension());
860  ZMatrix inequalities=a.inequalities;
861  inequalities.append(b.inequalities);
862  ZMatrix equations=a.equations;
863  equations.append(b.equations);
864
865  equations.sortAndRemoveDuplicateRows();
866  inequalities.sortAndRemoveDuplicateRows();
867
868  {
869    ZMatrix Aequations=a.equations;
870    ZMatrix Ainequalities=a.inequalities;
871    Aequations.sortAndRemoveDuplicateRows();
872    Ainequalities.sortAndRemoveDuplicateRows();
873    if((Ainequalities.getHeight()==inequalities.getHeight()) && (Aequations.getHeight()==equations.getHeight()))return a;
874    ZMatrix Bequations=b.equations;
875    ZMatrix Binequalities=b.inequalities;
876    Bequations.sortAndRemoveDuplicateRows();
877    Binequalities.sortAndRemoveDuplicateRows();
878    if((Binequalities.getHeight()==inequalities.getHeight()) && (Bequations.getHeight()==equations.getHeight()))return b;
879  }
880
881  return ZCone(inequalities,equations);
882}
883
884/*
885PolyhedralCone product(const PolyhedralCone &a, const PolyhedralCone &b)
886{
887  IntegerVectorList equations2;
888  IntegerVectorList inequalities2;
889
890  int n1=a.n;
891  int n2=b.n;
892
893  for(IntegerVectorList::const_iterator i=a.equations.begin();i!=a.equations.end();i++)
894    equations2.push_back(concatenation(*i,IntegerVector(n2)));
895  for(IntegerVectorList::const_iterator i=b.equations.begin();i!=b.equations.end();i++)
896    equations2.push_back(concatenation(IntegerVector(n1),*i));
897  for(IntegerVectorList::const_iterator i=a.inequalities.begin();i!=a.inequalities.end();i++)
898    inequalities2.push_back(concatenation(*i,IntegerVector(n2)));
899  for(IntegerVectorList::const_iterator i=b.inequalities.begin();i!=b.inequalities.end();i++)
900    inequalities2.push_back(concatenation(IntegerVector(n1),*i));
901
902  PolyhedralCone ret(inequalities2,equations2,n1+n2);
903  ret.setMultiplicity(a.getMultiplicity()*b.getMultiplicity());
904  ret.setLinearForm(concatenation(a.getLinearForm(),b.getLinearForm()));
905
906  ret.ensureStateAsMinimum(a.state);
907  ret.ensureStateAsMinimum(b.state);
908
909  return ret;
910}*/
911
912
913ZCone ZCone::positiveOrthant(int dimension)
914{
915  return ZCone(ZMatrix::identity(dimension),ZMatrix(0,dimension));
916}
917
918
919ZCone ZCone::givenByRays(ZMatrix const &generators, ZMatrix const &linealitySpace)
920{
921  //rewrite modulo lineality space
922  ZMatrix newGenerators(generators.getHeight(),generators.getWidth());
923  {
924    QMatrix l=ZToQMatrix(linealitySpace);
925    l.reduce();
926    for(int i=0;i<generators.getHeight();i++)
927      newGenerators[i]=QToZVectorPrimitive(l.canonicalize(ZToQVector(generators[i])));
928  }
929
930  ZCone dual(newGenerators,linealitySpace);
931  dual.findFacets();
932  dual.canonicalize();
933  ZMatrix inequalities=dual.extremeRays();
934
935  ZMatrix span=generators;
936  span.append(linealitySpace);
937  QMatrix m2Q=ZToQMatrix(span);
938  ZMatrix equations=QToZMatrixPrimitive(m2Q.reduceAndComputeKernel());
939
940  return ZCone(inequalities,equations);
941}
942
943
944bool ZCone::containsPositiveVector()const
945{
946  ZCone temp=intersection(*this,ZCone::positiveOrthant(n));
947  return temp.getRelativeInteriorPoint().isPositive();
948}
949
950
951bool ZCone::contains(ZVector const &v)const
952{
953  for(int i=0;i<equations.getHeight();i++)
954    {
955      if(!dot(equations[i],v).isZero())return false;
956    }
957  for(int i=0;i<inequalities.getHeight();i++)
958    {
959      if(dot(inequalities[i],v).sign()<0)return false;
960    }
961  return true;
962}
963
964
965bool ZCone::containsRowsOf(ZMatrix const &m)const
966{
967  for(int i=0;i<m.getHeight();i++)
968    if(!contains(m[i]))return false;
969  return true;
970}
971
972
973bool ZCone::contains(ZCone const &c)const
974{
975  ZCone c2=intersection(*this,c);
976  ZCone c3=c;
977  c2.canonicalize();
978  c3.canonicalize();
979  return !(c2!=c3);
980}
981
982
983bool ZCone::containsRelatively(ZVector const &v)const
984{
985  ensureStateAsMinimum(1);
986//  assert(state>=1);
987  for(int i=0;i<equations.getHeight();i++)
988    {
989      if(!dot(equations[i],v).isZero())return false;
990    }
991  for(int i=0;i<inequalities.getHeight();i++)
992    {
993      if(dot(inequalities[i],v).sign()<=0)return false;
994    }
995  return true;
996}
997
998
999bool ZCone::isSimplicial()const
1000{
1001//  assert(state>=2);
1002  ensureStateAsMinimum(2);
1003  return codimension()+inequalities.getHeight()+dimensionOfLinealitySpace()==n;
1004}
1005
1006
1007ZCone ZCone::linealitySpace()const
1008{
1009  ZCone ret(ZMatrix(0,n),combineOnTop(equations,inequalities));
1010//  ret.ensureStateAsMinimum(state);
1011  return ret;
1012}
1013
1014
1015ZCone ZCone::dualCone()const
1016{
1017  ensureStateAsMinimum(1);
1018//  assert(state>=1);
1019
1020  ZMatrix dualInequalities,dualEquations;
1021  lpSolver.dual(inequalities,equations,dualInequalities,dualEquations);
1022  ZCone ret(dualInequalities,dualEquations);
1023  ret.ensureStateAsMinimum(state);
1024
1025  return ret;
1026}
1027
1028
1029ZCone ZCone::negated()const
1030{
1031  ZCone ret(-inequalities,equations,(areFacetsKnown()?PCP_facetsKnown:0)|(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0));
1032//  ret.ensureStateAsMinimum(state);
1033  return ret;
1034}
1035
1036
1037ZMatrix ZCone::extremeRays(ZMatrix const *generatorsOfLinealitySpace)const
1038{
1039//  assert((dimension()==ambientDimension()) || (state>=3));
1040  if(dimension()!=ambientDimension())
1041    ensureStateAsMinimum(3);
1042
1043  if(haveExtremeRaysBeenCached)return cachedExtremeRays;
1044  ZMatrix ret(0,n);
1045  std::vector<std::vector<int> > indices=lpSolver.extremeRaysInequalityIndices(inequalities);
1046
1047  for(int i=0;i<indices.size();i++)
1048    {
1049      /* At this point we know lineality space, implied equations and
1050         also inequalities for the ray. To construct a vector on the
1051         ray which is stable under (or indendent of) angle and
1052         linarity preserving transformation we find the dimension 1
1053         subspace orthorgonal to the implied equations and the
1054         lineality space and pick a suitable primitive generator */
1055
1056          /* To be more precise,
1057           * let E be the set of equations, and v the inequality defining a  ray R.
1058           * We wish to find a vector satisfying these, but it must also be orthogonal
1059           * to the lineality space of the cone, that is, in the span of {E,v}.
1060           * One way to get such a vector is to project v to E an get a vector p.
1061           * Then v-p is in the span of {E,v} by construction.
1062           * The vector v-p is also in the orthogonal complement to E by construction,
1063           * that is, the span of R.
1064           * We wish to argue that it is not zero.
1065           * That would imply that v=p, meaning that v is in the span of the equations.
1066           * However, that would contradict that R is a ray.
1067           * In case v-p does not satisfy the inequality v (is this possible?), we change the sign.
1068           *
1069           * As a consequence we need the following procedure
1070           * primitiveProjection():
1071           *    Input: E,v
1072           *    Output: A primitive representation of the vector v-p, where p is the projection of v onto E
1073           *
1074           * Notice that the output is a Q linear combination of the input and that p is
1075           * a linear combination of E. The check that p has been computed correctly,
1076           * it suffices to check that v-p satisfies the equations E.
1077           * The routine will actually first compute a multiple of v-p.
1078           * It will do this using floating point arithmetics. It will then transform
1079           * the coefficients to get the multiple of v-p into integers. Then it
1080           * verifies in exact arithmetics, that with these coefficients we get a point
1081           * satisfying E. It then returns the primitive vector on the ray v-p.
1082           * In case of a failure it falls back to an implementation using rational arithmetics.
1083           */
1084
1085
1086          std::vector<int> asVector(inequalities.getHeight());
1087          for(int j=0;j<indices[i].size();j++){asVector[indices[i][j]]=1;}
1088          ZMatrix equations=this->equations;
1089          ZVector theInequality;
1090
1091          for(int j=0;j<asVector.size();j++)
1092            if(asVector[j])
1093              equations.appendRow(inequalities[j]);
1094            else
1095              theInequality=inequalities[j];
1096
1097          assert(!theInequality.isZero());
1098
1099          ZVector thePrimitiveVector;
1100          if(generatorsOfLinealitySpace)
1101          {
1102            QMatrix temp=ZToQMatrix(combineOnTop(equations,*generatorsOfLinealitySpace));
1103            thePrimitiveVector=QToZVectorPrimitive(temp.reduceAndComputeVectorInKernel());
1104          }
1105          else
1106          {
1107            QMatrix linealitySpaceOrth=ZToQMatrix(combineOnTop(this->equations,inequalities));
1108
1109
1110            QMatrix temp=combineOnTop(linealitySpaceOrth.reduceAndComputeKernel(),ZToQMatrix(equations));
1111            thePrimitiveVector=QToZVectorPrimitive(temp.reduceAndComputeVectorInKernel());
1112          }
1113          if(!contains(thePrimitiveVector))thePrimitiveVector=-thePrimitiveVector;
1114          ret.appendRow(thePrimitiveVector);
1115    }
1116
1117  cachedExtremeRays=ret;
1118  haveExtremeRaysBeenCached=true;
1119
1120  return ret;
1121}
1122
1123
1124Integer ZCone::getMultiplicity()const
1125{
1126  return multiplicity;
1127}
1128
1129
1130void ZCone::setMultiplicity(Integer const &m)
1131{
1132  multiplicity=m;
1133}
1134
1135
1136ZMatrix ZCone::getLinearForms()const
1137{
1138  return linearForms;
1139}
1140
1141
1142void ZCone::setLinearForms(ZMatrix const &linearForms_)
1143{
1144  linearForms=linearForms_;
1145}
1146
1147
1148ZMatrix ZCone::quotientLatticeBasis()const
1149{
1150//  assert(isInStateMinimum(1));// Implied equations must have been computed in order to know the span of the cone
1151  ensureStateAsMinimum(1);
1152
1153
1154  int a=equations.getHeight();
1155  int b=inequalities.getHeight();
1156
1157  // Implementation below could be moved to nonLP part of code.
1158
1159  // small vector space defined by a+b equations.... big by a equations.
1160
1161  ZMatrix M=combineLeftRight(combineLeftRight(
1162                                                  equations.transposed(),
1163                                                  inequalities.transposed()),
1164                                 ZMatrix::identity(n));
1165  M.reduce(false,true);
1166  /*
1167    [A|B|I] is reduced to [A'|B'|C'] meaning [A'|B']=C'[A|B] and A'=C'A.
1168
1169    [A'|B'] is in row echelon form, implying that the rows of C' corresponding to zero rows
1170    of [A'|B'] generate the lattice cokernel of [A|B] - that is the linealityspace intersected with Z^n.
1171
1172    [A'] is in row echelon form, implying that the rows of C' corresponding to zero rows of [A'] generate
1173    the lattice cokernel of [A] - that is the span of the cone intersected with Z^n.
1174
1175    It is clear that the second row set is a superset of the first. Their difference is a basis for the quotient.
1176   */
1177  ZMatrix ret(0,n);
1178
1179  for(int i=0;i<M.getHeight();i++)
1180    if(M[i].subvector(0,a).isZero()&&!M[i].subvector(a,a+b).isZero())
1181      {
1182        ret.appendRow(M[i].subvector(a+b,a+b+n));
1183      }
1184
1185  return ret;
1186}
1187
1188
1189ZVector ZCone::semiGroupGeneratorOfRay()const
1190{
1191  ZMatrix temp=quotientLatticeBasis();
1192  assert(temp.getHeight()==1);
1193  for(int i=0;i<inequalities.getHeight();i++)
1194    if(dot(temp[0],inequalities[i]).sign()<0)
1195      {
1196        temp[0]=-temp[0];
1197        break;
1198      }
1199  return temp[0];
1200}
1201
1202
1203ZCone ZCone::link(ZVector const &w)const
1204{
1205  /* Observe that the inequalities giving rise to facets
1206   * also give facets in the link, if they are kept as
1207   * inequalities. This means that the state cannot decrease
1208   * when taking links - that is why we specify the PCP flags.
1209   */
1210  ZMatrix inequalities2(0,n);
1211  for(int j=0;j<inequalities.getHeight();j++)
1212    if(dot(w,inequalities[j]).sign()==0)inequalities2.appendRow(inequalities[j]);
1213  ZCone C(inequalities2,equations,(areImpliedEquationsKnown()?PCP_impliedEquationsKnown:0)|(areFacetsKnown()?PCP_facetsKnown:0));
1214  C.ensureStateAsMinimum(state);
1215
1216  C.setLinearForms(getLinearForms());
1217  C.setMultiplicity(getMultiplicity());
1218
1219  return C;
1220}
1221
1222ZCone ZCone::faceContaining(ZVector const &v)const
1223{
1224  assert(n==v.size());
1225  assert(contains(v));
1226  ZMatrix newEquations=equations;
1227  ZMatrix newInequalities(0,n);
1228  for(int i=0;i<inequalities.getHeight();i++)
1229    if(dot(inequalities[i],v).sign()!=0)
1230      newInequalities.appendRow(inequalities[i]);
1231    else
1232      newEquations.appendRow(inequalities[i]);
1233
1234  ZCone ret(newInequalities,newEquations,(state>=1)?PCP_impliedEquationsKnown:0);
1235  ret.ensureStateAsMinimum(state);
1236  return ret;
1237}
1238
1239
1240ZMatrix ZCone::getInequalities()const
1241{
1242  return inequalities;
1243}
1244
1245
1246ZMatrix ZCone::getEquations()const
1247{
1248  return equations;
1249}
1250
1251
1252ZMatrix ZCone::generatorsOfSpan()const
1253{
1254  ensureStateAsMinimum(1);
1255  QMatrix l=ZToQMatrix(equations);
1256  return QToZMatrixPrimitive(l.reduceAndComputeKernel());
1257}
1258
1259
1260ZMatrix ZCone::generatorsOfLinealitySpace()const
1261{
1262  QMatrix l=ZToQMatrix(combineOnTop(inequalities,equations));
1263  return QToZMatrixPrimitive(l.reduceAndComputeKernel());
1264}
1265
1266};
Note: See TracBrowser for help on using the repository browser.