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

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