source: git/Singular/LIB/cisimplicial.lib @ 3686937

spielwiese
Last change on this file since 3686937 was 3686937, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Added '$Id$' as a comment to all libs (LIB/*.lib)
  • Property mode set to 100644
File size: 47.7 KB
Line 
1//////////////////////////////////////////////////////////////////////
2
3category= "Commutative Algebra";
4version="version cisimplicial.lib 4.0.0.0 Jun_2013 "; // $Id$
5info="
6LIBRARY: cisimplicial.lib. Determines if the toric ideal of
7a simplicial toric variety is a complete intersection
8
9AUTHORS: I.Bermejo,               ibermejo@ull.es
10@*       I.Garcia-Marco,          iggarcia@ull.es
11
12OVERVIEW:
13  A library for determining if a simplicial toric ideal is a complete
14  intersection with NO NEED of computing explicitly a system of generators
15  of such ideal. The procedures are based on two papers:
16  I. Bermejo, I. Garcia-Marco and J.J. Salazar-Gonzalez: 'An algorithm for
17  checking whether the toric ideal of an affine monomial curve is a complete
18  intersection', J. Symbolic Computation 42 (2007) pags: 971--991 and
19  I.Bermejo and I. Garcia-Marco: 'Complete  intersections in simplicial toric
20  varieties', Preprint (2010)
21
22PROCEDURES:
23 minMult(a,b);        computes the minimum multiple of a that belongs to the
24                semigroup generated by b
25 belongSemigroup(v,A[,n]);     checks whether A*x = v has a nonnegative
26                               integral solution
27 oneDimBelongSemigroup(n,v[,m]);      checks whether v*x = n has a
28                                      nonnegative integral solution
29 cardGroup(A);           computes the cardinal of Z^m / ZA
30 isCI(A);     checks wether I(A) is a complete intersection
31";
32
33LIB "general.lib";
34
35
36/////////////////////////////////////////////////////////////////////
37
38
39static proc Multiple(intvec v, intmat A, list #)
40"
41USAGE:   Multiple(v,A[,n]); v is an integral vector, A is an integral matrix, n is an integer.
42RETURN:  0 if none of the [n first] columns of A divides the vector v or an intvec otherwise.
43         In this case v = answer[2] * (answer[1]-th column of A).
44ASSUME:  nrows(v) = nrows(A) [and n <= nrows(A)].
45"
46{
47
48   intvec answer;
49   if (v == 0)
50   {
51      answer[1] = 1;
52      answer[2] = 0;
53      return (answer);
54   }
55
56   int last;
57   int e = size(#);
58   if  (e > 0)
59   {
60      last = #[1];
61   }
62   else
63   {
64      last = ncols(A);
65   }
66
67   int i,j,s;
68   for (j = 1; j <= last; j++)
69   {
70      s = 0;
71      for (i = 1; i <= nrows(A); i++)
72      {
73          if ((v[i] == 0)&&(A[i,j] != 0))
74          {
75             // it is not multiple of A_j
76            break;
77          }
78          if (v[i] != 0)
79          {
80            if (A[i,j] == 0)
81            {
82              // it is not multiple of A_j
83              break;
84            }
85            if (s == 0)
86            {
87              s = v[i] div A[i,j];
88            }
89            if (v[i] != s * A[i,j])
90            {
91              break;
92            }
93      }
94      if (i == nrows(A))
95      {
96        answer[1] = j;
97        answer[2] = s;
98        // v = s * A_j
99        return (answer);
100      }
101    }
102   }
103
104   // None of the columns of A divides v
105   return (0);
106
107}
108
109/////////////////////////////////////////////////////////////////////
110
111
112proc oneDimBelongSemigroup(int n, intvec v, list #)
113"
114USAGE:   oneDimBelongSemigroup(n,v[,m]); v is an integral vector,
115         n is a positive integer[, m is a positive integer].
116RETURN:  counters, a vector with nonnegative entries such that
117         v*counters = n. If it does not exist such a vector, it returns 0.
118         If a third parameter m is introduced, it will only consider the
119         first m entries of v.
120ASSUME:  v is an integral vector with positive entries.
121EXAMPLE: example oneDimBelongSemigroup; shows some examples.
122"
123{
124//--------------------------- initialisation ---------------------------------
125
126
127   int i, j;
128   int PartialSum;
129   int num;
130   int e = size(#);
131
132   if  (e > 0)
133   {
134      num = #[1];
135   }
136   else
137   {
138      num = nrows(v);
139   }
140
141   intvec v2 = v[1..num];
142   intvec counter, belong;
143   belong[num] = 0;
144   counter[num] = 0;
145   for (i = 1; i <= num; i++)
146   {
147      if (n % v[i] == 0)
148      {
149         // ---- n is multiple of v[i]
150         belong[i] = n div v[i];
151         return (belong);
152      }
153   }
154
155   if (num == 1)
156   {
157      // ---- num = 1 and n is not multiple of v[1] --> FALSE
158      return(0);
159   }
160
161   PartialSum = 0;
162
163   intvec w = sort(v2)[1];
164   intvec cambio = sort(v2)[2];
165
166   // ---- Iterative procedure to determine if n is in the semigroup generated by v
167   while (1)
168   {
169      if (n  >= PartialSum)
170      {
171         if (((n - PartialSum) % w[1]) == 0)
172         {
173            // ---- n belongs to the semigroup generated by v,
174            belong[cambio[1]] = (n - PartialSum) div w[1];
175            for (j = 2; j <= num; j++)
176            {
177               belong[cambio[j]] = counter[j];
178            }
179            return(belong);
180         }
181      }
182      i = num;
183      while (!defined(end))
184      {
185         if (i == 1)
186         {
187            // ---- Stop, n is not in the semigroup
188            return(0);
189         }
190         if (i > 1)
191         {
192            // counters control
193            if (w[i] > n - PartialSum)
194            {
195               PartialSum = PartialSum - (counter[i]*w[i]);
196               counter[i] = 0;
197               i--;
198            }
199            else
200            {
201               counter[i] = counter[i] + 1;
202               PartialSum = PartialSum + w[i];
203               int end;
204            }
205         }
206      }
207      kill end;
208   }
209}
210example
211{ "EXAMPLE:";echo=2;
212   int a = 95;
213   intvec v = 18,51,13;
214   oneDimBelongSemigroup(a,v);
215   "// 95 = 1*18 + 1*25 + 2*13";
216   oneDimBelongSemigroup(a,v,2);
217   "// 95 is not a combination of 18 and 52;";
218}
219
220
221
222/////////////////////////////////////////////////////////////////////
223
224
225proc SBelongSemigroup (intvec v, intmat A, list #)
226"
227USAGE:  SBelongSemigroup(v,A[,k]); v is an integral vector, A is an
228        integral matrix, n is a positive integer.
229RETURN: counters, a vector with nonnegative entries such that
230        A*counters = v. If it does not exist such vector, it returns 0.
231        If a third parameter k is introduced, it will only consider the
232        first k columns of A.
233ASSUME: A is an m x n matrix with nonnegative entries, n >= m, for every
234        i,j <= m, i != j then A[i,j] = 0, v has nonnegative entries and
235        nrows(v) = nrows(A);
236"
237{
238
239   int last;
240   int e = size(#);
241   if  (e > 0)
242   {
243      last = #[1];
244   }
245   else
246   {
247      last = ncols(A);
248   }
249
250   intvec counters;
251   counters[last] = 0;
252
253   int i, j, k, l;
254   intvec d;
255   for (i = 1; i <= nrows(A); i++)
256   {
257      d[i] = A[i,i];
258   }
259
260   i = 1;
261   while ((i < nrows(v)) && (v[i] % d[i] == 0))
262   {
263      i++;
264   }
265   if (v[i] % d[i] == 0)
266   {
267      // v is a combination of the first nrows(A) columns
268      for (j = 1; j <= nrows(v); j++)
269      {
270         counters[j] = v[j] div d[j];
271      }
272      return(counters);
273   }
274
275   int gcdrow;
276   for (i = 1; i <= nrows(A); i++)
277   {
278      gcdrow = d[i];
279      for (j = nrows(A)+1; j <= last; j++)
280      {
281         if (A[i,j] != 0)
282         {
283            gcdrow = gcd(gcdrow,A[i,j]);
284         }
285      }
286      if (v[i] % gcdrow != 0)
287      {
288         return (0);
289      }
290   }
291
292   intvec swap;
293   for (i = 1; i <= last; i++)
294   {
295      swap[i] = i;
296   }
297   for (i = nrows(A) + 1; i <= last; i++)
298   {
299      for (j = 1; j <= nrows(v); j++)
300      {
301         if (A[j,i] > v[j])
302         {
303            swap[i] = 0;
304            for (k = 1; k <= nrows(A); k++)
305            {
306               A[k,i] = A[k,last];
307            }
308            swap[i] = swap[last];
309            last--;
310            i--;
311            break;
312         }
313      }
314   }
315   if (nrows(A) == last)
316   {
317      return (0);
318   }
319
320
321   intvec order;
322   order[last] = 0;
323   for (i = nrows(A) + 1; i <= last; i++)
324   {
325      order[i] = 1;
326      for (j = 1; j <= nrows(A); j++)
327      {
328         if (A[j,i] > 0)
329         {
330            order[i] = lcm(order[i], d[j] div gcd(A[j,i],d[j]));
331         }
332      }
333   }
334
335   intvec counters2;
336   counters2[last] = 0;
337
338   // A full enumeration is performed
339   while(1)
340   {
341      i = nrows(counters2);
342      while (1)
343      {
344         j = 1;
345         if (counters2[i] < order[i] - 1)
346         {
347            while ((j < nrows(A)) and (v[j] >= A[j,i]))
348            {
349               j++;
350            }
351         }
352         if ((v[j] < A[j,i])||(counters2[i] == order[i] - 1))
353         {
354            // A_j is not < v componentwise or counters2 = order[i]
355            // we cannot increase counters2[i]
356            if (counters2[i] != 0)
357            {
358               for (k = 1; k <= nrows(v); k++)
359               {
360                  v[k] = v[k] + counters2[i] * A[k,i];
361               }
362               counters2[i] = 0;
363            }
364            i--;
365            if (i <= nrows(A))
366            {
367               // A*x = v has not nonnegative integral solution
368               return(0);
369            }
370         }
371         else
372         {
373            // j = nrows(A), then A_j < v (componentwise)
374            // we add one unit to counters2[i]
375            for (k = 1; k <= nrows(v); k++)
376            {
377               v[k] = v[k] - A[k,i];
378            }
379            counters2[i] = counters2[i] + 1;
380
381            l = 1;
382            while ((l < nrows(v)) and (v[l] % d[l] == 0))
383            {
384               l++;
385            }
386            if (v[l] % d[l] == 0)
387            {
388               // v is a combination of the first nrows(A) columns
389               for (k = 1; k <= nrows(v); k++)
390               {
391                  counters[k] = v[k] div d[k];
392               }
393               for (k = nrows(v) + 1; k <= nrows(counters2); k++)
394               {
395                  counters[swap[k]] = counters2[k];
396               }
397               // A*counters = v
398               return(counters);
399            }
400
401            break;
402         }
403      }
404   }
405}
406
407
408/////////////////////////////////////////////////////////////////////
409
410
411
412proc belongSemigroup (intvec v, intmat A, list #)
413"
414USAGE:   belongSemigroup(v,A[,k]); v is an integral vector, A is an
415         integral matrix, n is a positive integer.
416RETURN:  counters, a vector with nonnegative entries such that
417         A*counters = v. If it does not exist such a vector, it returns 0.
418         If a third parameter k is introduced, it will only consider the
419         first k columns of A.
420ASSUME:  A is a matrix with nonnegative entries, nonzero colums,
421         v is a nonnegative vector and nrows(v) = nrows(A).
422EXAMPLE: example belongSemigroup; shows some examples.
423"
424{
425   int inputlast;
426   int e = size(#);
427   if  (e > 0)
428   {
429      inputlast = #[1];
430   }
431   else
432   {
433      inputlast = ncols(A);
434   }
435
436   int i, j, k;
437   intvec counters;
438   int last = inputlast;
439
440   if (last == 0)
441   {
442      return (counters);
443   }
444
445   intvec swap;
446   for (i = 1; i <= last; i++)
447   {
448      swap[i] = i;
449   }
450   for (i = 1; i <= last; i++)
451   {
452      for (j = 1; j <= nrows(v); j++)
453      {
454         if (A[j,i] > v[j])
455         {
456            swap[i] = 0;
457            for (k = 1; k <= nrows(A); k++)
458            {
459               A[k,i] = A[k,last];
460            }
461            swap[i] = swap[last];
462            last--;
463            i--;
464            break;
465         }
466      }
467   }
468
469   if (last == 0)
470   {
471      return (0);
472   }
473
474   intvec multip = Multiple(v, A, last);
475
476   if (multip != 0)
477   {
478      intvec counters2;
479      counters2[inputlast] = 0;
480      // v = mult.value * ((mult.column)-th column of A)
481      counters2[swap[multip[1]]] = multip[2];
482      return (counters2);
483   }
484
485   counters[last] = 0;
486   // A full enumeration is performed
487   // Example: si v = (3,2,6), a1 = (1,0,0), a2 = (0,1,1), a3 = (0,0,1), then counters will take the
488   // following values:
489   // 000, 001, 002, 003, 004, 005, 006, 010, 011, 012, 013, 014, 015, 020, 021, 022, 023, 024 ---> 324
490   while(1)
491   {
492      i = nrows(counters);
493      while (1)
494      {
495         j = 1;
496         while (j <= nrows(A))
497         {
498            if (v[j] < A[j,i])
499            {
500               break;
501            }
502            j++;
503         }
504         if (j <= nrows(A))
505         {
506            if (counters[i] != 0)
507            {
508               for (k = 1; k <= nrows(A); k++)
509               {
510                  v[k] = v[k] + counters[i] * A[k,i];
511               }
512               counters[i] = 0;
513            }
514            i--;
515            if (i < 2)
516            {
517               // Does not belong
518               return (0);
519            }
520         }
521         else
522         {
523            for (k = 1; k <= nrows(A); k++)
524            {
525               v[k] = v[k] - A[k,i];
526            }
527            counters[i] = counters[i] + 1;
528            multip = Multiple(v, A, i);
529            if (multip != 0)
530            {
531               // v belongs, we return the solution counters so that A * counters = v
532               counters[multip[1]] = multip[2];
533               intvec counters2;
534               counters2[inputlast] = 0;
535               for (i = 1; i <= last; i++)
536               {
537                  counters2[swap[i]] = counters[i];
538               }
539               return (counters2);
540            }
541
542            break;
543         }
544      }
545   }
546}
547example
548{ "EXAMPLE:"; echo=2;
549   intmat A[3][4] = 10,3,2,1,2,1,1,3,5,0,1,2;
550   print(A);
551   intvec v = 23,12,10;
552   belongSemigroup(v,A);
553   "// A * (1,3,1,2) = v";
554   belongSemigroup(v,A,3);
555   "// v is not a combination of the first 3 columns of A";
556   intvec w = 12,4,1;
557   belongSemigroup(w,A);
558   "// w is not a combination of the columns of A";
559}
560
561/////////////////////////////////////////////////////////////////////
562
563
564
565proc cardGroup(intmat A, list #)
566"
567USAGE:   cardGroup(A[,n]); A is a matrix with integral coefficients.
568RETURN:         It returns a bigint. If we denote by ZA the group generated
569         by the columns of the matrix A, then it returns the number of
570         elements of the group of Z^m / ZA, where m = number of rows of A.
571         If a second parameter n is introduced, it will
572         only consider the first n columns of A. It returns 0 if Z^m / ZA
573         is infinite; this is, when rank ZA < m.
574EXAMPLE: example cardGroup; shows an example.
575"
576{
577   int i, j, k, l;
578   int coef1, coef2, aux;
579   bigint aux2, aux3;
580   list gcdiv;
581
582   int last;
583   int e = size(#);
584   if  (e > 0)
585   {
586      last = #[1];
587   }
588   else
589   {
590      last = ncols(A);
591   }
592
593   // First we put the matrix A in diagonal form.
594   for (i = 1; i <= nrows(A); i++)
595   {
596      j = i;
597      while (A[i,j] == 0)
598      {
599         j++;
600         if (j > last)
601         {
602            return (0);
603            // Group is infinite
604         }
605      }
606      if (j > i)
607      {
608         for (k = i; k <= nrows(A); k++)
609         {
610            // swap columns to have a nonzero pivot
611            aux = A[k,i];
612            A[k,i] = A[k,j];
613            A[k,j] = aux;
614         }
615      }
616      for (k = j+1; k <= last; k++)
617      {
618         if (A[i,k] != 0)
619         {
620            gcdiv = extgcd(A[i,i],A[i,k]);
621            coef1 = A[i,k] div gcdiv[1];
622            coef2 = A[i,i] div gcdiv[1];
623            for (l = i; l <= nrows(A); l++)
624            {
625               // Perform elemental operations in the matrix
626               // to put A in diagonal form
627               aux2 = bigint(gcdiv[2]) * bigint(A[l,i]) + bigint(gcdiv[3]) * bigint(A[l,k]);
628               aux3 = bigint(coef1) * bigint(A[l,i]) - bigint(coef2) * bigint(A[l,k]);
629               A[l,k] = int(aux3);
630               A[l,i] = int(aux2);
631            }
632         }
633      }
634   }
635
636   // Once the matrix is in diagonal form, we only have to multiply
637   // the diagonal elements
638
639   bigint determinant = bigint(A[1,1]);
640   bigint entry;
641   for (i = 2; i <= nrows(A); i++)
642   {
643      entry = bigint(A[i,i]);
644      determinant = determinant * entry;
645   }
646   determinant = absValue(determinant);
647   return(determinant);
648
649}
650example
651{ "EXAMPLE:"; echo=2;
652   intmat A[3][5] = 24,  0,  0,  8, 3,
653                     0, 24,  0, 10, 6,
654                     0,  0, 24,  5, 9;
655   cardGroup(A);
656}
657
658///////////////////////////////////////////////////////////////////////////////////////////////////////////
659
660proc minMult(int a, intvec b)
661"
662USAGE:   minMult (a, b); a integer, b integer vector.
663RETURN:  an integer k, the minimum positive integer such that k*a belongs to the
664         semigroup generated by the integers in b.
665ASSUME:  a is a positive integer, b is a vector of positive integers.
666EXAMPLE: example minMult; shows an example.
667"
668{
669//--------------------------- initialisation ---------------------------------
670   int i, j, min, max;
671   int n = nrows(b);
672
673   if (n == 1)
674   {
675      // ---- trivial case
676      return(b[1]/gcd(a,b[1]));
677   }
678
679   max = b[1];
680   for (i = 2; i <= n; i++)
681   {
682      if (b[i] > max)
683      {
684         max = b[i];
685      }
686   }
687   int NumNodes = a + max; //----Number of nodes in the graph
688
689   int dist = 1;
690   // ---- Auxiliary structures to obtain the shortest path between the nodes 1 and a+1 of this graph
691   intvec queue = 1;
692   intvec queue2;
693
694   // ---- Control vector:
695   //      control[i] = 0 -> node not reached yet
696   //      control[i] = 1 -> node in queue1
697   //      control[i] = 2 -> node in queue2
698   //      control[i] = 3 -> node already processed
699   intvec control;
700   control[1] = 3;         // Starting node
701   control[a + max] = 0;   // Ending node
702   int current = 1;        // Current node
703   int next;               // Node connected to corrent by arc (current, next)
704
705   int ElemQueue, ElemQueue2;
706   int PosQueue = 1;
707
708   // Algoritmo de Dijkstra
709   while (1)
710   {
711      if (current <= a)
712      {
713         // ---- current <= a, arcs are (current, current + b[i])
714         for (i = 1; i <= n; i++)
715         {
716            next = current + b[i];
717            if (next == a+1)
718            {
719               kill control;
720               kill queue;
721               kill queue2;
722               return (dist);
723            }
724            if ((control[next] == 0)||(control[next] == 2))
725            {
726               control[next] = 1;
727               queue = queue, next;
728            }
729         }
730      }
731      if (current > a)
732      {
733         // ---- current > a, the only possible ars is (current, current - a)
734         next = current - a;
735         if (control[next] == 0)
736         {
737            control[next] = 2;
738            queue2[nrows(queue2) + 1] = next;
739         }
740      }
741      PosQueue++;
742      if (PosQueue <= nrows(queue))
743      {
744         current = queue[PosQueue];
745      }
746      else
747      {
748         dist++;
749         if (control[a+1] == 2)
750         {
751            return(dist);
752         }
753         queue = queue2[2..nrows(queue2)];
754         current = queue[1];
755         PosQueue = 1;
756         queue2 = 0;
757      }
758      control[current] = 3;
759   }
760}
761example
762{ "EXAMPLE:";echo=2;
763   int a = 46;
764   intvec b = 13,17,59;
765   minMult(a,b);
766   "// 3*a = 8*b[1] + 2*b[2]"
767}
768
769
770/////////////////////////////////////////////////////////////////////
771
772
773static proc CheckMin (int posiblemin, intmat A, int column, list #)
774"
775USAGE:  CheckMin(posiblemin,A,column[,n]); posiblemin is an integer,
776        A is an integral matrix and column and last are integers.
777RETURN: 1 if posiblemin is the minimum value x such that x * (column-th colum of A)
778        belongs to the semigroup generated by all the columns of A except
779        A_column. It returns 0 otherwise. If an extra parameter n is
780        introduced then it will only consider the first n columns of A.
781ASSUME: 1 <= column <= ncols(A), A does not have negative entries or zero columns
782"
783{
784
785   // If one can write (posiblemin-1)*A_column as a non-trivial combination of the
786   // colums of A, then posiblemin is > to the real minimum
787   intvec counters, multip;
788   counters[ncols(A)] = 0;
789
790   int i,j,k;
791   int last;
792
793   int e = size(#);
794   if  (e > 0)
795   {
796      last = #[1];
797   }
798   else
799   {
800      last = ncols(A);
801   }
802
803   intvec v, aux;
804   for (i = 1; i <= nrows(A); i++)
805   {
806      v[i] = (posiblemin-1)*A[i,column];
807      // We swap A_column with A_1
808      aux[i] = A[i,1];
809      A[i,1] = A[i,column];
810      A[i,column] = aux[i];
811   }
812
813   for (i = 2; i <= last; i++)
814   {
815      for (j = 1; j <= nrows(v); j++)
816      {
817         if (A[j,i] > v[j])
818         {
819            for (k = 1; k <= nrows(A); k++)
820            {
821               A[k,i] = A[k,last];
822            }
823            last--;
824            i--;
825            break;
826         }
827      }
828   }
829
830   // A full enumeration is performed
831   while(1)
832   {
833      i = last;
834      while (1)
835      {
836         j = 1;
837         while (j <= nrows(A))
838         {
839            if (v[j] < A[j,i])
840            {
841               break;
842            }
843            j++;
844         }
845         if (j <= nrows(A))
846         {
847            if (counters[i] != 0)
848            {
849               for (k = 1; k <= nrows(A); k++)
850               {
851                  v[k] = v[k] + counters[i] * A[k,i];
852               }
853               counters[i] = 0;
854            }
855            i--;
856            if (i == 1)
857            {
858               // The only solution is that v = (posiblemin-1)*A.col[1]
859               return (1);
860            }
861         }
862         else
863         {
864            for (k = 1; k <= nrows(A); k++)
865            {
866               v[k] = v[k] - A[k,i];
867            }
868            counters[i] = counters[i]+1;
869            multip = Multiple(v, A, i);
870            if (multip != 0)
871            {
872               return (0);
873            }
874            break;
875         }
876      }
877   }
878}
879
880/////////////////////////////////////////////////////////////////////
881
882
883static proc SimplicialCheckMin (int posiblemin, intmat A, int column, list #)
884"
885USAGE:  SimplicialCheckMin(posiblemin,A,column[,last]); posiblemin is an integer,
886        A is an integral matrix and column and last are integers.
887RETURN: 1 if posiblemin is less or equal to the minimum value x such that
888        x * A_column belongs to the semigroup generated by all the columns of A
889        except A_column. It returns 0 otherwise. If an extra parameter last is
890        introduced then it will only consider the first n columns of A.
891ASSUME: 1 <= column <= ncols(A), A does not have negative entries or zero columns
892        A[i,j] = 0 for all 1 <= i,j <= nrows(A) where i != j
893"
894{
895   // If one can write (posiblemin-1)*A_column as a non-trivial combination of the
896   // colums of A, then posiblemin is > than the real minimum
897
898   int last;
899   int e = size(#);
900   if  (e > 0)
901   {
902      last = #[1];
903   }
904   else
905   {
906      last = ncols(A);
907   }
908
909   int i, j, k, l;
910   intvec d, v;
911   for (i = 1; i <= nrows(A); i++)
912   {
913      d[i] = A[i,i];
914   }
915
916   for (i = 1; i <= nrows(A); i++)
917   {
918      v[i] = A[i,column] * (posiblemin-1);
919   }
920
921   i = 1;
922   while ((i < nrows(v)) && (v[i] % d[i] == 0))
923   {
924      i++;
925   }
926   if (v[i] % d[i] == 0)
927   {
928      // v is a combination of the first nrows(A) columns
929      return(0);
930   }
931
932   int aux;
933   for (i = 1; i <= nrows(A); i++)
934   {
935      aux = A[i,nrows(A)+1];
936      A[i,nrows(A)+1] = A[i,column];
937      A[i,column] = aux;
938   }
939
940   for (i = nrows(A) + 2; i <= last; i++)
941   {
942       for (j = 1; j <= nrows(v); j++)
943       {
944          if (A[j,i] > v[j])
945          {
946             for (k = 1; k <= nrows(A); k++)
947             {
948                A[k,i] = A[k,last];
949             }
950             last--;
951             i--;
952             break;
953          }
954       }
955    }
956
957    intvec order;
958    order[last] = 0;
959    for (i = nrows(A) + 1; i <= last; i++)
960    {
961       order[i] = 1;
962       for (j = 1; j <= nrows(A); j++)
963       {
964          if (A[j,i] > 0)
965          {
966             order[i] = lcm(order[i], d[j] div gcd(A[j,i],d[j]));
967          }
968       }
969    }
970
971
972    if (order[nrows(A)+1] < posiblemin-1)
973    {
974       return (0);
975    }
976
977    order[nrows(A)+1] = posiblemin-1;
978
979    intvec counters;
980    counters[last] = 0;
981
982    // A full enumeration is performed
983    while(1)
984    {
985       i = last;
986       while (1)
987       {
988          j = 1;
989          if (counters[i] < order[i] - 1)
990          {
991             while ((j < nrows(A)) and (v[j] >= A[j,i]))
992             {
993                j++;
994             }
995          }
996          if ((v[j] < A[j,i])||(counters[i] == order[i] - 1))
997          {
998             // A_j is not < v componentwise or counters = order[i]-1
999             // we cannot increase counters[i]
1000             if (counters[i] != 0)
1001             {
1002                for (k = 1; k <= nrows(v); k++)
1003                {
1004                   v[k] = v[k] + counters[i] * A[k,i];
1005                }
1006                counters[i] = 0;
1007             }
1008             i--;
1009            if (i <= nrows(A))
1010            {
1011               // A*x = v has not nonnegative integral solution different
1012               // from the trivial one
1013               return(1);
1014            }
1015         }
1016         else
1017         {
1018            // j = nrows(A), then A_j < v (componentwise)
1019            // we add one unit to counters[i]
1020            for (k = 1; k <= nrows(v); k++)
1021            {
1022               v[k] = v[k] - A[k,i];
1023            }
1024            counters[i] = counters[i] + 1;
1025
1026            l = 1;
1027            while ((l < nrows(v)) and (v[l] % d[l] == 0))
1028            {
1029               l++;
1030            }
1031            if (v[l] % d[l] == 0)
1032            {
1033               // v is a combination of the first nrows(A) columns
1034               return(0);
1035            }
1036
1037            break;
1038         }
1039      }
1040   }
1041}
1042
1043
1044
1045/////////////////////////////////////////////////////////////////////
1046
1047
1048static proc Proportional(intvec a, intvec b)
1049"
1050USAGE:  Proportional(a,b); a,b integral vectors
1051RETURN: 1 if nrows(a) = nrows(b) and the vectors a and b are proportional;
1052        this is, there exist a rational number k such that k*a = b, and
1053        0 otherwise
1054ASSUME: a, b are nonzero vectors
1055"
1056{
1057
1058   if (nrows(a) != nrows(b))
1059   {
1060      return (0)
1061   }
1062
1063   int i, pivot;
1064   pivot = 1;
1065   while (a[pivot] == 0)
1066   {
1067      if (b[pivot] != 0)
1068      {
1069         // Not proportional
1070         return (0);
1071      }
1072      pivot++;
1073   }
1074
1075   if (b[pivot] == 0)
1076   {
1077      // Not proportional
1078      return (0);
1079   }
1080
1081   for (i = pivot + 1; i <= nrows(a); i++)
1082   {
1083      if (a[i] * b[pivot] != a[pivot] * b[i])
1084      {
1085         // Not proportional
1086         return (0);
1087      }
1088   }
1089   return (1);
1090
1091}
1092
1093/////////////////////////////////////////////////////////////////////
1094
1095
1096static proc StimatesMin(intmat A, int column, intvec line, list #)
1097"
1098USAGE:  StimatesMin(A,column,line[,n]); A is an integral matrix, column is
1099        an integer, line is an integral vector and n is an integer.
1100RETURN: The minimum integer k such that k * A_column belongs to the
1101        semigroup generated by all the columns of A except A_column. It
1102        returns 0 if it is not necessary to compute for the main program.
1103        If an extra parameter n is introuduced it considers the first n
1104        colums of A.
1105ASSUME: 1 <= column [<= n] <= ncols(A), A has nonnegative entries, line is
1106        a vector such that line[i] = line[j] if and only if the i-th and
1107        j-th columns of A are proportional
1108"
1109{
1110
1111   int last;
1112   int e = size(#);
1113   if  (e > 0)
1114   {
1115      last = #[1];
1116   }
1117   else
1118   {
1119      last = nrows(line);
1120   }
1121
1122   intvec current;
1123   int i,j,k;
1124   for (i = 1; i <= nrows(A); i++)
1125   {
1126      current[i] = A[i,column];
1127   }
1128
1129   int nonzero = 1;
1130   while (current[nonzero] == 0)
1131   {
1132      nonzero++;
1133   }
1134
1135   // We will only consider those colums A_j such that line[j] = line[column]
1136   intvec prop, jthcolumn;
1137   for (j = 1; j <= last; j++)
1138   {
1139      if (j != column)
1140      {
1141         if (line[column] == line[j])
1142         {
1143            prop[nrows(prop)+1] = A[nonzero,j];
1144         }
1145      }
1146   }
1147   int posiblemin = 0;
1148   if (prop[nrows(prop)] > 0)
1149   {
1150      // 1-dim minimum
1151      posiblemin = minMult(current[nonzero],prop);
1152   }
1153
1154   if (line[column] <= nrows(A))
1155   {
1156      // It is not necessary to do CheckMin
1157      return(posiblemin);
1158   }
1159
1160
1161   if (posiblemin > 0)
1162   {
1163      if (SimplicialCheckMin(posiblemin, A, column, last))
1164      {
1165         // It is the real minimum, otherwise minimum < posiblemin
1166         return (posiblemin);
1167      }
1168   }
1169   // Not necessary to compute the minimum explicitly
1170   return (0);
1171}
1172
1173/////////////////////////////////////////////////////////////////////
1174
1175
1176proc isCI(intmat A)
1177"
1178USAGE:   isCI(A); A is an integral matrix
1179RETURN:  1 if the simplicial toric ideal I(A) is a complete intersection
1180         and 0 otherwise. If printlevel > 0 and I(A) is a complete
1181         intersection it also shows a minimal set of generators of I(A)
1182ASSUME:  A is an m x n integral matrix with nonnegative entries and for
1183         every 1 <= i <= m, there exist a column in A whose i-th coordinate
1184         is not null and the rest are 0.
1185EXAMPLE: example isCI; shows some examples
1186"
1187{
1188//--------------------------- initialisation ---------------------------------
1189
1190   intvec d;
1191   intvec minimum;
1192   intvec swap;                // swap[i] = j if and only if the i-th column of B equals the j-th column of A
1193   intvec line;                // line[i] = line[j] if and only if the i-th and the j-th column of B are proportional
1194
1195
1196   int n, m;           // Size of the input
1197   int i,j,k,l,t;
1198
1199   n = ncols(A);
1200   m = nrows(A);
1201   intmat B[m][n];                                // auxiliary matrix
1202   intmat support[2*n-m][n];        // support[i,j] = 1 if and only if a_j belongs to V_i
1203   if (printlevel > 0)
1204   {
1205      ring r = 0,x(1..n),dp;
1206      ideal toric;                        // In case I(A) is a complete intersection, we obtain a
1207                                        // minimal set of generators
1208   }
1209
1210   for (i = 1; i <= n; i++)
1211   {
1212      int zero = 0;
1213      swap[i] = i;
1214      for (j = 1; j <= m; j++)
1215      {
1216         B[j,i] = A[j,i];
1217         if (B[j,i] > 0)
1218         {
1219            zero++;
1220         }
1221         if (B[j,i] < 0)
1222         {
1223            print("// There are negative entries in the matrix");
1224            return (0);
1225         }
1226      }
1227      if (zero == 0)
1228      {
1229         print ("// There is a zero column in the matrix");
1230         return (0);
1231      }
1232   kill zero;
1233   }
1234
1235//--------------------------- preprocessing the input ---------------------------------
1236
1237
1238   int aux, found;
1239
1240   // We write B in a standard form; this is, for 1 <= i,j <= m, j != i then B[i,j] = 0
1241   for (i = 1; i <= m; i++)
1242   {
1243      j = i;
1244      found = 0;
1245      while (j <= n)
1246      {
1247         if (B[i,j] != 0)
1248         {
1249            k = 1;
1250            while ((k == i)||(B[k,j] == 0))
1251            {
1252               k++;
1253               if (k == m+1)
1254               {
1255                  for (l = 1; l <= m; l++)
1256                  {
1257                     aux = B[l,j];
1258                     B[l,j] = B[l,i];
1259                     B[l,i] = aux;
1260                  }
1261                  aux = swap[j];
1262                  swap[j] = swap[i];
1263                  swap[i] = aux;
1264                  found = 1;
1265                  break;
1266               }
1267            }
1268         }
1269         if (found == 1)
1270         {
1271            break;
1272         }
1273         j++;
1274      }
1275      if (j == n+1)
1276      {
1277         print("// There exists an i such that no column in A has the i-th coordinate positive and the rest are 0.");
1278            // It is not simplicial
1279         return (0);
1280      }
1281   }
1282
1283   // Initialisation of variables
1284   int numgens = 0;                // number of generators built
1285
1286   for (i = 1; i <= n; i++)
1287   {
1288      support[i,i] = 1;
1289   }
1290
1291   intvec ithcolumn, jthcolumn, belong;
1292   int numcols = ncols(B);
1293   line[numcols] = 0;
1294
1295   // line[i] = line[j] if and only if B_i and B_j are proportional.
1296   // Moreover for i = 1,...,nrows(B) we have that line[i]= i
1297   for (i = 1; i <= numcols; i++)
1298   {
1299      if (line[i] == 0)
1300      {
1301         for (j = 1; j <= nrows(B); j++)
1302         {
1303            ithcolumn[j] = B[j,i];
1304         }
1305         line[i] = i;
1306         for (j = i+1; j <= numcols; j++)
1307         {
1308            for (k = 1; k <= nrows(B); k++)
1309            {
1310               jthcolumn[k] = B[k,j];
1311            }
1312            if (Proportional(ithcolumn, jthcolumn))
1313            {
1314               line[j] = i;
1315            }
1316         }
1317      }
1318   }
1319
1320//----------------- We apply reduction ---------------
1321
1322   bigint det1, det2;
1323   int minim, swapiold, lineiold;
1324   int change = 1;
1325
1326   det1 = cardGroup(B,numcols);
1327   while (change == 1)
1328   {
1329      change = 0;
1330      for (i = 1; i <= numcols; i++)
1331      {
1332         for (j = 1; j <= m; j++)
1333         {
1334            ithcolumn[j] = B[j,i];
1335            B[j,i] = B[j,numcols];
1336         }
1337         swapiold = swap[i];
1338         swap[i] = swap[numcols];
1339         lineiold = line[i];
1340         line[i] = line[numcols];
1341         det2 = cardGroup(B,numcols-1);
1342         minim = int(det2/det1);
1343         if (lineiold > m)
1344         {
1345            belong = SBelongSemigroup(minim*ithcolumn,B,numcols-1);
1346            if (belong != 0)
1347            {
1348               // It belongs, we remove the ith column
1349               if (printlevel > 0)
1350               {
1351                  // Create a generator
1352                  poly mon1 = x(swapiold)^(minim);
1353                  poly mon2 = 1;
1354                  for (j = 1; j <= nrows(belong); j++)
1355                  {
1356                     mon2 = mon2 * x(swap[j])^(belong[j]);
1357                  }
1358                  toric = toric, mon1-mon2;
1359                  kill mon1;
1360                  kill mon2;
1361               }
1362               det1 = det2;
1363               change = 1;
1364               numgens++;
1365               numcols--;
1366               i--;
1367            }
1368         }
1369         else
1370         {
1371            // line[i] <= m
1372            intvec semigroup, supportmon;
1373            int position;
1374            for (j = 1; j <= numcols-1; j++)
1375            {
1376               if (line[j] == lineiold)
1377               {
1378                  position = j;
1379                  semigroup = semigroup, B[lineiold,j];
1380                  supportmon = supportmon, swap[j];
1381               }
1382            }
1383            if (semigroup == 0)
1384            {
1385               belong = 0;
1386            }
1387            else
1388            {
1389               semigroup = semigroup[2..nrows(semigroup)];
1390               supportmon = supportmon[2..nrows(supportmon)];
1391               belong = oneDimBelongSemigroup(minim*ithcolumn[lineiold],semigroup);
1392            }
1393            if (belong != 0)
1394            {
1395               // It belongs, we remove the ith column
1396               if (printlevel > 0)
1397               {
1398                  // We create a generator
1399                  poly mon1,mon2;
1400                  mon1 = x(swapiold)^(minim);
1401                  mon2 = 1;
1402                  for (j = 1; j <= nrows(supportmon); j++)
1403                  {
1404                     mon2 = mon2 * x(supportmon[j])^(belong[j]);
1405                  }
1406                  toric = toric, mon1-mon2;
1407                  kill mon1, mon2;
1408               }
1409               det1 = det2;
1410               numcols--;
1411               numgens++;
1412               change = 1;
1413               if (i <= m)
1414               {
1415                  // We put again B in standard form
1416                  if (position != i)
1417                  {
1418                     for (j = 1; j <= m; j++)
1419                     {
1420                        aux = B[j,position];
1421                        B[j,position] = B[j,i];
1422                        B[j,i] = aux;
1423                     }
1424                     aux = swap[i];
1425                     swap[i] = swap[position];
1426                     swap[position] = aux;
1427                     aux = line[i];
1428                     line[i] = line[position];
1429                     line[position] = aux;
1430                  }
1431               }
1432               i--;
1433            }
1434            kill position;
1435            kill semigroup;
1436            kill supportmon;
1437         }
1438         if (belong == 0)
1439         {
1440            for (j = 1; j <= m; j++)
1441            {
1442               B[j,i] = ithcolumn[j];
1443            }
1444            swap[i] = swapiold;
1445            line[i] = lineiold;
1446         }
1447      }
1448   }
1449
1450    // Initialisation of variables
1451    minimum[numcols] = 0;
1452
1453//----------------- We run the first part of the algorithm ---------------
1454
1455   // Estimation of m_i with i = 1,...,n
1456   for (i = 1; i <= numcols; i++)
1457   {
1458      minimum[i] = StimatesMin(B,i,line,numcols);
1459   }
1460
1461   int nonzero;
1462   int stagenumber = 0;
1463   change = 1;
1464   while (change == 1)
1465   {
1466      // If for every i,j we have that m_i*B_i != m_j*B_j we leave the while loop
1467      change = 0;
1468      for (i = 1; (i <= numcols) && (change == 0); i++)
1469      {
1470         if (minimum[i] != 0)
1471         {
1472            for (j = i+1; (j <= numcols) && (change == 0); j++)
1473            {
1474               if ((minimum[j] != 0)&&(line[i] == line[j]))
1475               {
1476                  // We look for a nonzero entry in B_i
1477                  nonzero = 1;
1478                  while (B[nonzero,i] == 0)
1479                  {
1480                     nonzero++;
1481                  }
1482                  if (minimum[i]*B[nonzero,i] == minimum[j]*B[nonzero,j])
1483                  {
1484                     // m_i b_i = m_j b_j
1485                     numgens++;
1486                     stagenumber++;
1487                     if (swap[i] <= n)
1488                     {
1489                        // For k = swap[i], we have that V_k = {b_i}, so m_i b_i belongs to V_k
1490                              if (printlevel > 0)
1491                        {
1492                           poly mon1 = x(swap[i])^(minimum[i]);
1493                        }
1494                     }
1495                     else
1496                     {
1497                        // We check wether m_i b_i belongs to the semigroup generated by V_k
1498                        // where k = swap[i]. All vectors in V_k are proportional to b_i
1499                        intvec checkbelong;
1500                        int miai;
1501                        intvec supporti;
1502                        miai = minimum[i]*B[nonzero,i];
1503                        for (k = 1; k <= n; k++)
1504                        {
1505                           if (support[swap[i],k])
1506                           {
1507                              supporti = supporti, k;
1508                              checkbelong[nrows(supporti)-1] = A[nonzero,k];
1509                           }
1510                        }
1511                        // 1-dim belong semigroup
1512                        belong = oneDimBelongSemigroup(miai,checkbelong);
1513                        if (belong == 0)
1514                        {
1515                           // It does not belong
1516                           print ("// It is NOT a complete intersection");
1517                           return (0);
1518                        }
1519                        if (printlevel > 0)
1520                        {
1521                           poly mon1 = 1;
1522                           // It belongs, we construct a monomial of the new generator
1523                           for (k = 1; k < nrows(supporti); k++)
1524                           {
1525                              mon1 = mon1 * x(supporti[k+1])^(belong[k]);
1526                           }
1527                        }
1528                        kill miai;
1529                        kill checkbelong;
1530                        kill supporti;
1531                     }
1532                     if (swap[j] <= n)
1533                     {
1534                        // For k = swap[j], we have that V_k = {b_j}, so m_j b_j belongs to V_k
1535                        if (printlevel > 0)
1536                        {
1537                           poly mon2 = x(swap[j])^(minimum[j]);
1538                           toric = toric, mon1-mon2;
1539                           kill mon1;
1540                           kill mon2;
1541                        }
1542                     }
1543                     else
1544                     {
1545                        // We check wether m_j b_j belongs to the semigroup generated by V_k
1546                        // where k = swap[j]. All vectors in V_k are proportional to b_j
1547                        intvec checkbelong;
1548                        int mjaj;
1549                        intvec supportj;
1550                        nonzero = 1;
1551                        while (B[nonzero,j] == 0)
1552                        {
1553                           nonzero++;
1554                        }
1555                        mjaj = minimum[j]*B[nonzero,j];
1556                        for (k = 1; k <= n; k++)
1557                        {
1558                           if (support[swap[j],k])
1559                           {
1560                              supportj = supportj, k;
1561                              checkbelong[nrows(supportj)-1] = A[nonzero,k];
1562                           }
1563                        }
1564                        // 1-dim belong semigroup
1565                        belong = oneDimBelongSemigroup(mjaj,checkbelong);
1566                        if (belong == 0)
1567                        {
1568                           // It does not belong
1569                           print ("// It is NOT a complete intersection");
1570                           return (0);
1571                        }
1572                        if (printlevel > 0)
1573                        {
1574                           poly mon2 = 1;
1575                           // It belongs, we construct the second monomial of the generator
1576                           for (k = 1; k < nrows(supportj); k++)
1577                           {
1578                              mon2 = mon2 * x(supportj[k+1])^(belong[k]);
1579                           }
1580                           toric = toric,mon1-mon2;
1581                           kill mon1;
1582                           kill mon2;
1583                        }
1584                        kill checkbelong;
1585                        kill mjaj;
1586                        kill supportj;
1587                     }
1588
1589                     // Now we remove b_i, b_j from B and we add gcd(b_i,b_j)
1590                     change = 1;
1591                     for (k = 1; k <= n; k++)
1592                     {
1593                        // V_{support.nrows} = V_i + V_j
1594                        support[n+stagenumber,k] = support[swap[i],k] + support[swap[j],k];
1595                     }
1596                     // line[i] does not change
1597                     line[j] = line[numcols];
1598                     swap[i] = n+stagenumber;
1599                     swap[j] = swap[numcols];
1600                     k = 1;
1601                     while (B[k,i] == 0)
1602                     {
1603                        k++;
1604                     }
1605                     int dp;
1606                     dp = gcd(B[k,i], B[k,j]);
1607                     int factor = B[k,i] div dp;
1608                     B[k,i] = dp;
1609                     k++;
1610                     kill dp;
1611                     while (k <= nrows(B))
1612                     {
1613                        B[k,i] = B[k,i] / factor;
1614                        k++;
1615                     }
1616                     kill factor;
1617                     for (k = 1; k <= nrows(B); k++)
1618                     {
1619                        B[k,j] = B[k,numcols];
1620                     }
1621                     minimum[j] = minimum[numcols];
1622                     numcols--;
1623                     // We compute a new m_i
1624                     minimum[i] = StimatesMin(B,i,line,numcols);
1625                  }
1626               }
1627            }
1628         }
1629      }
1630   }
1631
1632//--------------------------- We apply reduction ---------------------------------
1633
1634   intvec minZ;
1635   for (i = 1; i <= n+stagenumber; i++)
1636   {
1637      minZ[i] = 1;
1638   }
1639   det1 = cardGroup(B,numcols);
1640   int posaux;
1641   intvec counters1,counters2;
1642
1643   while (numgens < n - m)
1644   {
1645      change = 0;
1646      i = nrows(B) + 1;
1647      while ((i <= numcols)&&(numgens < n-m))
1648      {
1649         // The vector we are going to study
1650         for (j = 1; j <= nrows(B); j++)
1651         {
1652            ithcolumn[j] = B[j,i];
1653            B[j,i] = B[j,numcols];
1654         }
1655         posaux = swap[i];
1656         swap[i] = swap[numcols];
1657
1658         numcols--;
1659
1660         det2 = cardGroup(B,numcols);
1661         minim = int(det2/det1);
1662
1663         if (minim != 1)
1664         {
1665            // If minimum = 1, we have previously checked that current does not belong to
1666            // the semigroup generated by the columns of B.
1667
1668            for (j = 1; j <= nrows(B); j++)
1669            {
1670               ithcolumn[j] = ithcolumn[j]*minim;
1671            }
1672            minZ[posaux] = minim * minZ[posaux];
1673            det1 = det2;  // det1 *= minimum
1674
1675            intvec support1, support2;
1676            nonzero = 1;
1677            while (ithcolumn[nonzero] == 0)
1678            {
1679               nonzero++;
1680               if (nonzero > nrows(ithcolumn))
1681               {
1682                  print("// ERROR");
1683                  return (0);
1684               }
1685            }
1686            int currentnonzero = ithcolumn[nonzero];
1687            intvec B1;
1688            for (j = 1; j <= n; j++)
1689            {
1690               if (support[posaux,j])
1691               {
1692                  // a_j is proportional to b_i = a_posaux
1693                  support1 = support1, j;
1694                  B1[nrows(support1)-1] = A[nonzero,j];
1695               }
1696            }
1697            // 1-dim belongsemigroup
1698            counters1 = oneDimBelongSemigroup(currentnonzero, B1);
1699            kill currentnonzero;
1700            kill B1;
1701            if (counters1 != 0)
1702            {
1703               intmat B2[m][n];
1704               // It belongs, now we have to check if current belongs to the semigroup
1705               // generated by the columns of B2
1706               for (j = 1; j <= numcols; j++)
1707               {
1708                  for (k = 1; k <= n; k++)
1709                  {
1710                     if (support[swap[j],k])
1711                     {
1712                        // a_k may not be proportional to b_i = a_posaux
1713                        support2 = support2, k;
1714                        for (l = 1; l <= m; l++)
1715                        {
1716                           B2[l,nrows(support2)-1] = A[l,k];
1717                        }
1718                     }
1719                  }
1720               }
1721               // We write B2 in standard form
1722               for (l = 1; l <= m; l++)
1723               {
1724                  j = l;
1725                  found = 0;
1726                  while (found == 0)
1727                  {
1728                     if (B2[l,j] != 0)
1729                     {
1730                        k = 1;
1731                        while ((k == l)||(B2[k,j] == 0))
1732                        {
1733                           k++;
1734                           if (k == m + 1)
1735                           {
1736                              for (t = 1; t <= m; t++)
1737                              {
1738                                 jthcolumn[t] = B2[t,j];
1739                                 B2[t,j] = B2[t,l];
1740                                 B2[t,l] = jthcolumn[t];
1741                              }
1742                              aux = support2[j+1];
1743                              support2[j+1] = support2[l+1];
1744                              support2[l+1] = aux;
1745                              found = 1;
1746                              break;
1747                           }
1748                        }
1749                     }
1750                     j++;
1751                  }
1752               }
1753
1754               // m-dim belong semigroup
1755               counters2 = SBelongSemigroup(ithcolumn, B2, nrows(support2)-1);
1756               kill B2;
1757
1758               if (counters2 != 0)
1759               {
1760                  // current belongs, we construct the new generator
1761                  numgens++;
1762                  if (printlevel > 0)
1763                  {
1764                     poly mon1, mon2;
1765                     mon1 = 1;
1766                     mon2 = 1;
1767                     for (j = 1; j < nrows(support1); j++)
1768                     {
1769                        mon1 = mon1 * x(support1[j+1])^(counters1[j]);
1770                     }
1771                     for (j = 1; j < nrows(support2); j++)
1772                     {
1773                        mon2 = mon2 * x(support2[j+1])^(counters2[j]);
1774                     }
1775                     toric = toric, mon1-mon2;
1776                     kill mon1;
1777                     kill mon2;
1778                  }
1779
1780                  if (i != numcols)
1781                  {
1782                     i--;
1783                  }
1784                  change = 1; // We have removed a column of B
1785
1786               }
1787            }
1788            kill support1,support2;
1789         }
1790
1791         if ((counters1 == 0)||(counters2 == 0)||(minim == 1))
1792         {
1793            // We swap again the columns in B
1794            for (j = 1; j <= m; j++)
1795            {
1796               B[j,i] = ithcolumn[j];
1797            }
1798            numcols++;
1799            swap[numcols] = swap[i];
1800            swap[i] = posaux;
1801         }
1802
1803         if ((i == numcols)&&(change == 0))
1804         {
1805            print(" // It is NOT a Complete Intersection.");
1806            return (0);
1807         }
1808         i++;
1809      }
1810   }
1811
1812   // We have removed all possible columns
1813   if (printlevel > 0)
1814   {
1815      print("// Generators of the toric ideal");
1816      toric = simplify(toric,2);
1817      toric;
1818   }
1819   print("// It is a complete intersection");
1820   return(1);
1821}
1822example
1823{ "EXAMPLE:"; echo=2;
1824   intmat A[2][5] = 60,0,140,150,21,0,60,140,150,21;
1825   print(A);
1826   printlevel = 0;
1827   isCI(A);
1828   printlevel = 1;
1829   isCI(A);
1830   intmat B[3][5] = 12,0,0,1,2,0,10,0,3,2,0,0,8,3,3;
1831   print(B);
1832   isCI(B);
1833   printlevel=0;
1834}
1835
1836
Note: See TracBrowser for help on using the repository browser.