source: git/Singular/dyn_modules/gitfan/gitfan.cc @ 9fe6c3

spielwiese
Last change on this file since 9fe6c3 was 9fe6c3, checked in by Hans Schoenemann <hannes@…>, 5 years ago
add: subsets(kn,) in subsets.so (all subsets of 1..n with k elements)
  • Property mode set to 100644
File size: 16.3 KB
Line 
1/***************************************************************
2 *
3 * File:       gitfan.cc
4 * Purpose:    Computationally intensive procedures for gitfan.lib,
5 *             outsourced to improve the performance.
6 * Authors:    Janko Boehm    boehm@mathematik.uni-kl.de
7 *             Simon Keicher  keicher@mail.mathematik.uni-tuebingen.de
8 *             Yue Ren        ren@mathematik.uni-kl.de
9 *
10 ***************************************************************/
11
12#include "kernel/mod2.h"
13
14#if HAVE_GFANLIB
15
16#include "Singular/dyn_modules/gfanlib/callgfanlib_conversion.h"
17#include "Singular/dyn_modules/gfanlib/bbcone.h"
18#include "Singular/dyn_modules/gfanlib/bbfan.h"
19#include "Singular/mod_lib.h"
20
21#include "gitfan.h"
22
23
24
25namespace gitfan
26{
27
28  facet::facet():
29    eta(gfan::ZCone()),
30    interiorPoint(gfan::ZVector()),
31    facetNormal(gfan::ZVector())
32  {
33  }
34
35  facet::facet(const gitfan::facet &f):
36    eta(f.eta),
37    interiorPoint(f.interiorPoint),
38    facetNormal(f.facetNormal)
39  {
40#ifndef SING_NDEBUG
41    gfan::ZCone c = f.eta;
42    gfan::ZVector v = f.interiorPoint;
43    gfan::ZVector w = f.facetNormal;
44    assume(c.ambientDimension() == (int)v.size());
45    assume(c.ambientDimension() == (int)w.size());
46    assume(c.contains(v));
47    assume(!c.contains(w));
48#endif
49  }
50
51  facet::facet(const gfan::ZCone &c, const gfan::ZVector &v, const gfan::ZVector &w):
52    eta(c),
53    interiorPoint(v),
54    facetNormal(w)
55  {
56#ifndef SING_NDEBUG
57    assume(c.ambientDimension() == (int)v.size());
58    assume(c.ambientDimension() == (int)w.size());
59    assume(c.contains(v));
60    assume(!c.contains(w));
61#endif
62  }
63
64  facet::~facet()
65  {
66#ifndef SING_NDEBUG
67    gfan::ZCone c = this->eta;
68    gfan::ZVector v = this->interiorPoint;
69    gfan::ZVector w = this->facetNormal;
70    assume(c.ambientDimension() == (int)v.size());
71    assume(c.ambientDimension() == (int)w.size());
72    assume(c.contains(v));
73    assume(!c.contains(w));
74#endif
75  }
76
77  void mergeFacets(facets &F, const facets &newFacets)
78  {
79    std::pair<facets::iterator,bool> check(newFacets.begin(),false);
80    for(facets::iterator p=newFacets.begin(); p!=newFacets.end(); p++)
81    {
82      check = F.insert(*p);
83      if(!check.second)
84        F.erase(check.first);
85    }
86  }
87
88}
89
90
91static gfan::ZCone subcone(const lists &cones, const gfan::ZVector &point)
92{
93  gfan::ZCone sigma = gfan::ZCone(gfan::ZMatrix(1,point.size()), gfan::ZMatrix(1,point.size()));
94  gfan::ZCone* zc;
95  for (int i=0; i<=cones->nr; i++)
96  {
97    zc = (gfan::ZCone*) cones->m[i].Data();
98    if (zc->contains(point))
99      sigma = gfan::intersection(sigma,*zc);
100  }
101  return(sigma);
102}
103
104static gitfan::facets interiorFacets(const gfan::ZCone &zc, const gfan::ZCone &bound)
105{
106  gfan::ZMatrix inequalities = zc.getFacets();
107  gfan::ZMatrix equations = zc.getImpliedEquations();
108  int r = inequalities.getHeight();
109  int c = inequalities.getWidth();
110  gitfan::facets F;
111  if (r*c == 0)
112    /***
113     * this is the trivial case where either we are in a zerodimensional ambient space,
114     * or the cone has no facets.
115     **/
116    return F;
117
118  // int index = 0;
119  /* next we iterate over each of the r facets, build the respective cone and add it to the list */
120  /* this is the i=0 case */
121  gfan::ZMatrix newInequalities = inequalities.submatrix(1,0,r,c);
122  gfan::ZMatrix newEquations = equations;
123  newEquations.appendRow(inequalities[0]);
124  gfan::ZCone eta = gfan::ZCone(newInequalities,newEquations);
125  eta.canonicalize();
126  gfan::ZVector v = eta.getRelativeInteriorPoint();
127  gfan::ZVector w = inequalities[0];
128
129  if (bound.containsRelatively(v))
130    F.insert(gitfan::facet(eta,v,w));
131
132  /* these are the cases i=1,...,r-2 */
133  for (int i=1; i<r-1; i++)
134  {
135    newInequalities = inequalities.submatrix(0,0,i,c);
136    newInequalities.append(inequalities.submatrix(i+1,0,r,c));
137    newEquations = equations;
138    newEquations.appendRow(inequalities[i]);
139    eta = gfan::ZCone(newInequalities,newEquations);
140    eta.canonicalize();
141    v = eta.getRelativeInteriorPoint();
142    w = inequalities[i];
143    if (bound.containsRelatively(v))
144      F.insert(gitfan::facet(eta,v,w));
145  }
146
147  /* this is the i=r-1 case */
148  newInequalities = inequalities.submatrix(0,0,r-1,c);
149  newEquations = equations;
150  newEquations.appendRow(inequalities[r-1]);
151  eta = gfan::ZCone(newInequalities,newEquations);
152  eta.canonicalize();
153
154  v = eta.getRelativeInteriorPoint();
155  w = inequalities[r-1];
156  if (bound.containsRelatively(v))
157    F.insert(gitfan::facet(eta,v,w));
158
159  return F;
160}
161
162BOOLEAN refineCones(leftv res, leftv args)
163{
164  leftv u=args;
165  if ((u != NULL) && (u->Typ() == LIST_CMD))
166  {
167    leftv v=u->next;
168    if ((v != NULL) && (v->Typ() == BIGINTMAT_CMD))
169    {
170      lists cones = (lists) u->Data();
171      bigintmat* bim = (bigintmat*) v->Data();
172      gfan::ZMatrix* zm = bigintmatToZMatrix(bim->transpose());
173      gfan::ZCone support = gfan::ZCone::givenByRays(*zm, gfan::ZMatrix(0, zm->getWidth()));
174      delete zm;
175
176      /***
177       * Randomly compute a first full-dimensional cone and insert it into the fan.
178       * Compute a list of facets and relative interior points.
179       * The relative interior points are unique, assuming the cone is stored in canonical form,
180       * which is the case in our algorithm, as we supply no redundant inequalities.
181       * Hence we can decide whether a facet need to be traversed by crosschecking
182       * its relative interior point with this list.
183       **/
184      gfan::ZCone lambda; gfan::ZVector point;
185      do
186      {
187        point = randomPoint(&support);
188        lambda = subcone(cones, point);
189      }
190      while (lambda.dimension() < lambda.ambientDimension());
191      int iterationNumber = 1;
192      std::cout << "cones found: " << iterationNumber++ << std::endl;
193
194      lambda.canonicalize();
195      gfan::ZFan* Sigma = new gfan::ZFan(lambda.ambientDimension());
196      Sigma->insert(lambda);
197      gitfan::facets F = interiorFacets(lambda, support);
198      if (F.empty())
199      {
200        res->rtyp = fanID;
201        res->data = (void*) Sigma;
202        return FALSE;
203      }
204      int mu = 1024;
205
206      gitfan::facet f;
207      gfan::ZCone eta;
208      gfan::ZVector interiorPoint;
209      gfan::ZVector facetNormal;
210      gitfan::facets newFacets;
211      while (!F.empty())
212      {
213        /***
214         * Extract a facet to traverse and its relative interior point.
215         **/
216        f = *(F.begin());
217        eta = f.getEta();
218        interiorPoint = f.getInteriorPoint();
219        facetNormal = f.getFacetNormal();
220
221        /***
222         * construct a point, which lies on the other side of the facet.
223         * make sure it lies in the known support of our fan
224         * and that the cone around the point is maximal, containing eta.
225         **/
226        point = mu * interiorPoint - facetNormal;
227        while (!support.containsRelatively(point))
228        {
229          mu = mu * 16;
230          point = mu * interiorPoint - facetNormal;
231        }
232
233        lambda = subcone(cones,point);
234        while ((lambda.dimension() < lambda.ambientDimension()) && !(lambda.contains(interiorPoint)))
235        {
236          mu = mu * 16;
237          point = mu * interiorPoint - facetNormal;
238          lambda = subcone(cones,point);
239        }
240        std::cout << "cones found: " << iterationNumber++ << std::endl;
241
242        /***
243         * insert lambda into Sigma, and create a list of facets of lambda.
244         * merge the two lists of facets
245         **/
246        lambda.canonicalize();
247        Sigma->insert(lambda);
248        newFacets = interiorFacets(lambda, support);
249        mergeFacets(F,newFacets);
250        newFacets.clear();
251      }
252      res->rtyp = fanID;
253      res->data = (void*) Sigma;
254      return FALSE;
255    }
256  }
257  WerrorS("refineCones: unexpected parameters");
258  return TRUE;
259}
260
261
262static int binomial(int n, int k)
263{
264  if (n<k)
265    return(0);
266  gfan::Integer num = 1;
267  gfan::Integer den = 1;
268  for (int i=1; i<=k; i++)
269    den = den*i;
270  for (int j=n-k+1; j<=n; j++)
271    num = num*j;
272  gfan::Integer bin = num/den;
273  return(bin.toInt());
274}
275
276
277intvec* intToAface(unsigned int v0, int n, int k)
278{
279  intvec* v = new intvec(k);
280  int j = 0;
281  for (int i=0; i<n; i++)
282  {
283    if (v0 & (1<<i))
284      (*v)[j++] = i+1;
285  }
286  return v;
287}
288
289
290BOOLEAN listOfAfacesToCheck(leftv res, leftv args)
291{
292  leftv u = args;
293  if ((u != NULL) && (u->Typ() == INT_CMD))
294  {
295    leftv v = u->next;
296    if ((v != NULL) && (v->Typ() == INT_CMD))
297    {
298      int n = (int)(long) u->Data();
299      int k = (int)(long) v->Data();
300      unsigned int v = 0;
301      for (int i=0; i<k; i++)
302        v |= 1<<i;  // sets the first k bits of v as 1
303
304      lists L = (lists)omAllocBin(slists_bin);
305      int count = (int) binomial(n,k); L->Init(count);
306      unsigned int t;
307      while (!(v & (1<<n)))
308      {
309        L->m[--count].rtyp = INTVEC_CMD;
310        L->m[count].data = (void*) intToAface(v,n,k);
311
312        // t gets v's least significant 0 bits set to 1
313        t = v | (v - 1);
314        // Next set to 1 the most significant bit to change,
315        // set to 0 the least significant ones, and add the necessary 1 bits.
316        v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
317      }
318      res->rtyp = LIST_CMD;
319      res->data = (void*) L;
320      return FALSE;
321    }
322  }
323  WerrorS("listOfAfacesToCheck: unexpected parameter");
324  return TRUE;
325}
326
327
328BOOLEAN nextAfaceToCheck(leftv res, leftv args)
329{
330  leftv u = args;
331  if ((u != NULL) && (u->Typ() == INTVEC_CMD))
332  {
333    leftv v = u->next;
334    if ((v != NULL) && (v->Typ() == INT_CMD))
335    {
336      leftv w = v->next;
337      if ((w != NULL) && (w->Typ() == INT_CMD))
338      {
339        intvec* aface = (intvec*) u->Data();
340        int ambientDimension = (int)(long) v->Data();
341        int dimension = (int)(long) w->Data();
342
343        unsigned int af = 0;
344        for (int i=0; i<aface->length(); i++)
345          af |= 1<<((*aface)[i]-1);
346
347        unsigned int t = af | (af - 1);
348        af = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(af) + 1));
349
350        if (af & (1<<ambientDimension))
351        {
352          res->rtyp = INTVEC_CMD;
353          res->data = (void*) new intvec(1);
354          return FALSE;
355        }
356
357        res->rtyp = INTVEC_CMD;
358        res->data = (void*) intToAface(af,ambientDimension,dimension);
359        return FALSE;
360      }
361    }
362  }
363  WerrorS("nextAfaceToCheck: unexpected parameter");
364  return TRUE;
365}
366
367
368BOOLEAN checkSigns(leftv res, leftv args)
369{
370  leftv u = args;
371  if ((u != NULL) && (u->Typ()==BIGINTMAT_CMD || u->Typ()==INTMAT_CMD))
372  {
373    leftv v = u->next;
374    if ((v != NULL) && (v->Typ() == INTVEC_CMD) && (v->next == NULL))
375    {
376      bigintmat* interiorPoint = NULL;
377      if (u->Typ() == INTMAT_CMD)
378      {
379        intvec* p0 = (intvec*) u->Data();
380        interiorPoint = iv2bim(p0,coeffs_BIGINT);
381      }
382      else
383        interiorPoint = (bigintmat*) u->Data();
384      intvec* hash = (intvec*) v->Data();
385      res->rtyp = INT_CMD;
386      for (int i=0; i<hash->length(); i++)
387      {
388        if ( (*hash)[i]<0 && n_GreaterZero((*interiorPoint)[i],interiorPoint->basecoeffs()) )
389        {
390          res->data = (void*) (long) 0;
391          return FALSE;
392        }
393        if ( (*hash)[i]>0 && !n_IsZero((*interiorPoint)[i],interiorPoint->basecoeffs()) )
394        {
395          number neg = n_Copy((*interiorPoint)[i],interiorPoint->basecoeffs());
396          neg = n_InpNeg(neg,interiorPoint->basecoeffs());
397          if (n_GreaterZero(neg,interiorPoint->basecoeffs()))
398          {
399            n_Delete(&neg,interiorPoint->basecoeffs());
400            res->data = (void*) (long) 0;
401            return FALSE;
402          }
403          n_Delete(&neg,interiorPoint->basecoeffs());
404        }
405      }
406      res->data = (void*) (long) 1;
407      if (v->Typ() == INTMAT_CMD)
408        delete interiorPoint;
409      return FALSE;
410    }
411  }
412  WerrorS("checkSigns: unexpected parameter");
413  return TRUE;
414}
415
416
417BOOLEAN binaryToBigint(leftv res, leftv args)
418{
419  leftv u = args;
420  if ((u != NULL) && (u->Typ() == INTVEC_CMD) && (u->next == NULL))
421  {
422    intvec* iv = (intvec*) u->Data();
423    const int l = (iv->rows())*(iv->cols());
424    number base = n_Init(2,coeffs_BIGINT);
425    number endResult;
426    n_Power(base,(*iv)[0]-1,&endResult,coeffs_BIGINT);
427    for (int i=1; i<l; i++)
428    {
429      number endResultCache;
430      number currentBit;
431      n_Power(base,(*iv)[i]-1,&currentBit,coeffs_BIGINT);
432      endResultCache = n_Add(endResult,currentBit,coeffs_BIGINT);
433      n_Delete(&endResult,coeffs_BIGINT);
434      n_Delete(&currentBit,coeffs_BIGINT);
435      endResult = endResultCache;
436      endResultCache = NULL;
437    }
438    n_Delete(&base,coeffs_BIGINT);
439    res->rtyp = BIGINT_CMD;
440    res->data = (void*) endResult;
441    return FALSE;
442  }
443  WerrorS("binaryToBigint: unexpected parameter");
444  return TRUE;
445}
446
447
448BOOLEAN composeIntvecs(leftv res, leftv args)
449{
450  leftv u = args;
451  if ((u!=NULL) && (u->Typ()==INTVEC_CMD))
452  {
453    leftv v = u->next;
454    if ((v!=NULL) && (v->Typ()==INTVEC_CMD) && (v->next==NULL))
455    {
456      intvec* iv1 = (intvec*) u->Data();
457      intvec* iv2 = (intvec*) v->Data();
458      int k = iv2->length();
459      intvec* composedIntvec = new intvec(k);
460      for (int i=0; i<k; i++)
461        (*composedIntvec)[i] = (*iv1)[(*iv2)[i]-1];
462      res->rtyp = INTVEC_CMD;
463      res->data = (void*) composedIntvec;
464      return FALSE;
465    }
466  }
467  WerrorS("composeIntvecs: unexpected parameter");
468  return TRUE;
469}
470
471
472BOOLEAN findPlaceToInsert(leftv res, leftv args)
473{
474  leftv u = args;
475  if ((u!=NULL) && (u->Typ()==LIST_CMD))
476  {
477    leftv v = u->next;
478    if ((v!=NULL) && (v->Typ()==BIGINT_CMD) && (v->next==NULL))
479    {
480      lists listOfNumbers = (lists) u->Data();
481      number numberToInsert = (number) v->Data();
482      int lowerBound = 0;
483      int upperBound = lSize(listOfNumbers);
484      if (upperBound<0)
485      {
486        res->rtyp = INT_CMD;
487        res->data = (void*) (long) (lowerBound+1);
488        return FALSE;
489      }
490
491      number lowerNumber = (number) listOfNumbers->m[lowerBound].Data();
492      if (n_Equal(lowerNumber,numberToInsert,coeffs_BIGINT))
493      {
494        res->rtyp = INT_CMD;
495        res->data = (void*) (long) (-1);
496        return FALSE;
497      }
498      if (n_Greater(lowerNumber,numberToInsert,coeffs_BIGINT))
499      {
500        res->rtyp = INT_CMD;
501        res->data = (void*) (long) (lowerBound+1);
502        return FALSE;
503      }
504
505      number upperNumber = (number) listOfNumbers->m[upperBound].Data();
506      if (n_Equal(numberToInsert,upperNumber,coeffs_BIGINT))
507      {
508        res->rtyp = INT_CMD;
509        res->data = (void*) (long) (-1);
510        return FALSE;
511      }
512      if (n_Greater(numberToInsert,upperNumber,coeffs_BIGINT))
513      {
514        res->rtyp = INT_CMD;
515        res->data = (void*) (long) (upperBound+2);
516        return FALSE;
517      }
518
519      while (lowerBound+1<upperBound)
520      {
521        int middle = lowerBound + (upperBound-lowerBound) / 2;
522        number lowerNumber = (number) listOfNumbers->m[lowerBound].Data();
523        number upperNumber = (number) listOfNumbers->m[upperBound].Data();
524        number middleNumber = (number) listOfNumbers->m[middle].Data();
525        if ((n_Equal(lowerNumber,numberToInsert,coeffs_BIGINT)) ||
526            (n_Equal(middleNumber,numberToInsert,coeffs_BIGINT)) ||
527            (n_Equal(upperNumber,numberToInsert,coeffs_BIGINT)))
528        {
529          res->rtyp = INT_CMD;
530          res->data = (void*) (long) -1;
531          return FALSE;
532        }
533        if (n_Greater(numberToInsert,middleNumber,coeffs_BIGINT))
534          lowerBound = middle;
535        if (n_Greater(middleNumber,numberToInsert,coeffs_BIGINT))
536          upperBound = middle;
537      }
538
539      res->rtyp = INT_CMD;
540      res->data = (void*) (long) (upperBound+1);
541      return FALSE;
542    }
543  }
544  WerrorS("findPlaceToInsert: unexpected parameter");
545  return TRUE;
546}
547
548
549void subset(std::vector<int> &arr, int size, int left, int index, std::vector<int> &l, std::vector<std::vector<int> > &L)
550{
551  if(left==0)
552  {
553    L.push_back(l);
554    return;
555  }
556
557  for(int i=index; i<size;i++)
558  {
559    l.push_back(arr[i]);
560    subset(arr,size,left-1,i+1,l,L);
561    l.pop_back();
562  }
563}
564
565extern "C" int SI_MOD_INIT(gitfan) (SModulFunctions* p)
566{
567  gfan::initializeCddlibIfRequired();
568  p->iiAddCproc("gitfan.lib","refineCones",FALSE,refineCones);
569  p->iiAddCproc("gitfan.lib","listOfAfacesToCheck",FALSE,listOfAfacesToCheck);
570  p->iiAddCproc("gitfan.lib","nextAfaceToCheck",FALSE,nextAfaceToCheck);
571  p->iiAddCproc("gitfan.lib","checkSigns",FALSE,checkSigns);
572  p->iiAddCproc("gitfan.lib","binaryToBigint",FALSE,binaryToBigint);
573  p->iiAddCproc("gitfan.lib","composeIntvecs",FALSE,composeIntvecs);
574  p->iiAddCproc("gitfan.lib","findPlaceToInsert",FALSE,findPlaceToInsert);
575  return (MAX_TOK);
576}
577
578#endif
Note: See TracBrowser for help on using the repository browser.