source: git/Singular/LIB/cisimplicial.lib @ 33b509

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