source: git/Singular/LIB/monomialideal.lib @ 47cb36e

spielwiese
Last change on this file since 47cb36e was 47cb36e, checked in by Frank Seelisch <seelisch@…>, 14 years ago
some formatting & typo correction in monomialideal.lib git-svn-id: file:///usr/local/Singular/svn/trunk@13337 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 99.9 KB
Line 
1//////////////////////////////////////////////////////////////////////////////
2version = "$Id$";
3category = "Commutative algebra";
4info = "
5LIBRARY: monomialideal.lib   Primary and irreducible decompositions of
6                             monomial ideals
7AUTHORS: I.Bermejo,          ibermejo@ull.es
8@*       E.Garcia-Llorente,  evgarcia@ull.es
9@*       Ph.Gimenez,         pgimenez@agt.uva.es
10
11OVERVIEW:
12 A library for computing a primary and the irreducible decompositions of a
13 monomial ideal using several methods.
14 In this library we specifically take advantage of the fact that the ideal
15 is monomial to make some computations that are Grobner free in this case
16 (radical, intersection, quotient...).
17
18LITERATURE: Miller, Ezra  and Sturmfels, Bernd: Combinatorial Commutative
19            Algebra, Springer 2004
20
21PROCEDURES:
22 isMonomial(id);        checks whether an ideal id is monomial
23 minbaseMon(id);        computes the minimal monomial generating set of a
24                        monomial ideal id
25 gcdMon(f,g);           computes the gcd of two monomials f, g
26 lcmMon(f,g);           computes the lcm of two monomials f, g
27 membershipMon(f,id);   checks whether a polynomial f belongs to a monomial
28                        ideal id
29 intersectMon(id1,id2); intersection of monomial ideals id1 and id2
30 quotientMon(id1,id2);  quotient ideal id1:id2
31 radicalMon(id);        computes the radical of a monomial ideal id
32 isprimeMon(id);        checks whether a monomial ideal id is prime
33 isprimaryMon(id);      checks whether a monomial ideal id is primary
34 isirreducibleMon(id);  checks whether a monomial ideal id is irreducible
35 isartinianMon(id);     checks whether a monomial ideal id is artininan
36 isgenericMon(id);      checks whether a monomial ideal id is generic, i.e.,
37                        no two minimal generators of it agree in the exponent
38                        of any variable that actually appears in both of them
39 dimMon(id);            dimension of a monomial ideal id
40 irreddecMon(id,..);    computes the irreducible decomposition of a monomial
41                        ideal id
42 primdecMon(id,..);     computes a minimal primary decomposition of a monomial
43                        ideal id
44";
45
46LIB "poly.lib";  // Para "maxdeg1" en "isprimeMon"
47
48//---------------------------------------------------------------------------
49//-----------------------   INTERNOS    -------------------------------------
50//---------------------------------------------------------------------------
51
52/////////////////////////////////////////////////////////////////////////////
53static proc checkIdeal (ideal I)
54"
55USAGE:    checkIdeal (I); I ideal.
56RETURN:   1, if the given generators of I are monomials; 0, otherwise.
57"
58// Aqui NO estoy quitando el caso de que el ideal sea el trivial.
59{
60  int i,n;
61  n = ncols(I);
62  for (i = n ; i >= 1 ; i --)
63  {
64    if ( size(I[i]) > 1 )
65    {
66      return (0);
67    }
68  }
69  return (1);
70}
71
72/////////////////////////////////////////////////////////////////////////////
73static proc quotientIdealMon (ideal I, poly f)
74"
75USAGE:    quotientIdealMon(I,f); I ideal, f polynomial.
76RETURN:   an ideal, the quotient ideal I:(f).
77ASSUME:   I is an ideal given by a list of monomials and f is a monomial
78          of the basering.
79"
80{
81  // Variables
82  int i,j;
83  poly g,generator;
84  intvec v;
85  ideal J;
86  J = 0;
87
88  int sizI = ncols(I);
89  for (i = 1 ; i <= sizI ; i++)
90  {
91    g = gcd(I[i],f);
92    // Cociente de dos monomios: restamos los exponentes, y en el
93    // denominador va el mcd
94    v = leadexp(I[i]) - leadexp(g);
95    generator = monomial (v);
96    if (membershipMon(generator,J) == 0)
97    {
98      J=J,generator;
99    }
100  }
101  // minimal monomial basis
102  return ( minbase(J) );
103}
104
105/////////////////////////////////////////////////////////////////////////////
106static proc soporte (poly f)
107"
108USAGE:    soporte(f); f polynomial.
109RETURN:   0, if the monomial f is product of more than one variable;
110          otherwise, an integer j, 1<=j<=n, if the monomial f is a power of
111          x(j).
112ASSUME:   f is a monomial of the basering K[x(1)..x(n)].
113"
114{
115  // Variables
116  int i,cont,sop;
117  intvec expf;
118  int nvar = nvars(basering);
119  expf = leadexp(f);
120  cont = 0;
121  // cont va a contar el numero de componentes del vector no nulas.
122  // En sop guardamos el subindice de la componente no nula.
123  for (i = nvar ; i >= 1 ; i--)
124  {
125    if (expf[i] > 0)
126    {
127      cont ++;
128      sop = i;
129      // Si cont > 1 ==> aparece mas de una variable, devolvemos 0
130      if (cont > 1)
131      {
132        return (0);
133      }
134    }
135  }
136  return(sop);
137}
138
139/////////////////////////////////////////////////////////////////////////////
140static proc irredAux (ideal I)
141"
142USAGE:    irredAux (I); I ideal.
143RETURN:   1, if I is irreducible; otherwise, an intvec whose first entry is
144          the position of a generator which is the product of more than one
145          variable, the next entries are the indices of those variables.
146ASSUME:   I is a monomial ideal of the basering K[x(1)..x(n)] and it is
147          generated by its minimal monomial generators.
148NOTE:     This procedure is a modification of isirreducibleMon to give
149          more information when the ideal is not irreducible.
150"
151{
152  // Variables
153  int sizI,i,nvar,j,sum;
154  intvec w,exp;
155  sizI = ncols(I);
156  nvar = nvars(basering);
157  for (i = 1 ; i <= sizI ; i++)
158  {
159    sum = 0;
160    exp = leadexp(I[i]);
161    for (j = 1 ; j <= nvar ; j++)
162    {
163      // Al menos tenemos una variable en cada generador, luego
164      // entramos minimo 1 vez, luego sum >= 1.
165      if (exp[j] <> 0)
166      {
167        sum++;
168        w[sum] = j;
169      }
170    }
171    // Si hay mas de una variable la suma sera mayor que 1; y ya
172    // sabemos que I no es irreducible.
173    if (sum <> 1)
174    {
175      return(i,w);
176    }
177  }
178  return(1);
179}
180
181/////////////////////////////////////////////////////////////////////////////
182static proc contents (ideal I, ideal J)
183"
184USAGE:    contents (I,J); I,J ideals.
185RETURN:   1, if I is contained in J; 0, otherwise.
186ASSUME:   I, J are monomial ideals of the basering.
187"
188{
189  // Variables
190  poly f;
191  int i,resp;
192  int n = ncols(I);
193  // Desde que haya un generador que no pertenzca al ideal, ya no se da
194  // el contenido y terminamos.
195  for (i = 1 ; i <= n ; i++)
196  {
197    resp = membershipMon(I[i],J);
198    if (resp == 0)
199    {
200      return(0);
201    }
202  }
203  return(1);
204}
205
206/////////////////////////////////////////////////////////////////////////////
207static proc equal (ideal I, ideal J)
208"
209USAGE:    equal (I,J); I,J ideals.
210RETURN:   1, if I and J are the same ideal; 0, otherwise.
211ASSUME:   I, J are monomial ideals of the basering and are defined by their
212          minimal monomial generators.
213"
214{
215  // Variables
216  int n,i,j;
217  intvec resps;
218  // Si no tienen el mismo numero de generadores, no pueden ser iguales; ya
219  // que vienen dados por el sistema minimal de generadores.
220  if (ncols(I) <> ncols(J))
221  {
222    return(0);
223  }
224  // Como ambos ideales vienen dados por la base minimal, no vamos a
225  // tener problemas con que comparemos uno de I con otro de J, pues
226  // no puede haber generadores iguales en el mismo ideal.
227  // Si los ordenamos, se puede comparar uno a uno
228  return(matrix( sort(I)[1])==matrix(sort(J)[1]));
229  //n = size(I);
230  //I = sort(I)[1];
231  //J = sort(J)[1];
232  //for (i = 1 ; i <= n ; i++)
233  //{
234  //  if (I[i] <> J[i])
235  //  {
236  //    return(0);
237  //  }
238  //}
239  //return(1);
240}
241
242/////////////////////////////////////////////////////////////////////////////
243static proc radicalAux (ideal I)
244"
245USAGE:    radicalAux (I); I ideal.
246RETURN:   an ideal, the radical ideal of I
247ASSUME:   I is an irreducible monomial ideal of the basering given by its
248          minimal monomial generators.
249"
250{
251  // Cambiamos de anillo
252  int nvar = nvars(basering);
253  // Variables
254  int i,cont;
255  intvec exp;
256  ideal rad;
257  // Como en cada generador aparece solo una variable,  y ademas la
258  // la misma variable no va a aparecer dos veces, es suficiente
259  // con sumar los exponentes de todos los generadores para saber que
260  // variables aparecen.
261  int n = ncols(I);
262  for (i = 1 ; i <= n ; i++)
263  {
264    exp = exp + leadexp (I[i]);
265  }
266  cont = 1;
267  for (i = 1 ; i <= nvar ; i++)
268  {
269    if (exp[i] <> 0)
270    {
271      rad[cont] = var(i);
272      cont ++;
273    }
274  }
275  return (rad);
276}
277
278/////////////////////////////////////////////////////////////////////////////
279static proc primAux (ideal I)
280"
281USAGE:    primAux (I); I ideal.
282RETURN:   1, if I is primary; otherwise, an intvec, whose first element is
283          0, the second is the index of one variable such that a power of it
284          does not appear as a generator of I, the rest of the elements are
285          the position in the ideal of those elements of I which are product
286          of more than one variable.
287ASSUME:   I is a monomial ideal of the basering K[x(1)..x(n)].
288NOTE:     This procedure detects if the ideal is primary. When the
289          ideal is not primary, it gives some additional information.
290"
291{
292  // Variables
293  int control,nvar,i,sub_in,l,j;
294  intvec v,w,exp_gen;
295  // El ideal ya entra generado por el sistema minimal
296  nvar = nvars(basering);
297  int sizI = ncols(I);
298  v[nvar] = 0;
299  int cont = 1;
300  // v = 1 en la posicion en el ideal de variables sueltas, que son
301  // las que no hay que tocar, 0 en las demas. w = posiciones de los
302  // generadores de I que hay que comprobar.
303  for (i = 1 ; i <= sizI ; i++ )
304  {
305    sub_in = soporte(I[i]);
306    if ( sub_in <> 0)
307    {
308      v[sub_in] = 1;
309    }
310    else
311    {
312      w[cont] = i;
313      cont ++;
314    }
315  }
316  l = size(w);
317  // No hay ningun generador que tenga productos de variables, luego
318  //  este ideal ya es primario.
319  if (l == 1 && w[1] == 0)
320  {
321    return (1);
322  }
323  for (i = 1 ; i <= l ; i++)
324  {
325    exp_gen = leadexp(I[w[i]]);
326    // Ahora hay que ver que valor tiene el exponente de los
327    // generadores oportunos en la posicion que es cero dentro del
328    // vector v.
329    for (j = 1 ; j <= nvar ; j++)
330    {
331      if (v[j] == 0)
332      {
333        if (exp_gen[j] <> 0)
334        {
335          return (0,j,w);
336        }
337      }
338    }
339  }
340  // Si hemos llegado hasta aqui hemos recorrido todo el ideal y por tanto
341  // es primario.
342  return (1);
343}
344
345/////////////////////////////////////////////////////////////////////////////
346static proc maxExp (ideal I, intvec v)
347"
348USAGE:    maxExp (I,v); I ideal, v integer vector.
349RETURN:   an integer, the greatest power of a variable in the minimal
350          monomial set of generators of I.
351ASSUME:   I is a monomial ideal of the basering, v=primAux(I) and the
352          variable considered is v[2].
353          If the ideal I is primary, it returns 0.
354NOTE:     The elements of the vector suggest what variable and which
355          generators we must consider to look for the greatest power
356          of this variable.
357"
358{
359  // Variables
360  int n,i,max;
361  intvec exp;
362  // Ponemos el tama?o de v menos 2 porque en el vector v a partir de
363  // la tercera componente es donde tenemos la posicion de los
364  // generadores que tenemos que estudiar.
365  n = size(v)-2;
366  // Buscamos el maximo de la variable que no aparece "sola" en los
367  // generadores del ideal (donde nos indica v).
368  max = 0;
369  for (i = 1 ; i <= n ; i++)
370  {
371    exp = leadexp (I[v[i+2]]);
372    if (exp[v[2]] > max)
373    {
374      max = exp[v[2]];
375    }
376  }
377  return (max);
378}
379
380/////////////////////////////////////////////////////////////////////////////
381static proc irredundant (list l)
382"
383USAGE:    irredundant (l); l, list.
384RETURN:   a list such that the intersection of the elements in that list has
385          no redundant component.
386ASSUME:   The elements of l are monomial ideals of the basering.
387"
388{
389  // Variables
390  int i,j,resp;
391  ideal J;
392  // Recalculamos el tamano de l cuando modificamos la lista (sizl)
393  int sizl = size(l);
394  for (i = 1 ; i <= sizl ; i++)
395  {
396    J = 1;
397    for (j = 1 ; j <= sizl ; j++)
398    {
399      // Hacemos la interseccion de todos los ideales menos uno y
400      // luego se estudia el contenido.
401      if (j <> i)
402      {
403        J = intersect (J,l[j]);
404      }
405    }
406    J = minbase(J);
407    resp = contents(J,l[i]);
408    if (resp == 1)
409    {
410      l = delete (l,i);
411      i--;
412      sizl = size(l);
413    }
414  }
415  return (l);
416}
417
418/////////////////////////////////////////////////////////////////////////////
419static proc alexDif (intvec v, ideal I)
420"
421USAGE:    alexDif (v,I); v, intvec; I, ideal.
422RETURN:   a list, irreducible monomial ideals whose intersection is the
423          Alexander dual of I with respect to v.
424ASSUME:   I is a monomial ideal of the basering K[x(1),...,x(n)] given by
425          its minimal monomial generators and v is an integer vector with
426          n entries s.t. monomial(v) is a multiple of all minimal monomial
427          generators of I.
428"
429{
430  // Cambiamos de anillo
431  int nvar = nvars(basering);
432  // Variables
433  int i,j;
434  intvec exp_I,exp;
435  list l;
436  ideal J;
437  int sizI = ncols(I);
438  // Vamos a tener tantas componentes como generadores minimales tiene el
439  // ideal, por eso el bucle es de 1 a size(I).
440  for (i = 1 ; i <= sizI ; i++)
441  {
442    J = 0;
443    exp_I = leadexp (I[i]);
444    for (j = 1 ; j <= nvar ; j++)
445    {
446      if (exp_I[j] <> 0)
447      {
448        exp[j] = v[j] + 1 - exp_I[j];
449        J = J, var(j)^exp[j];
450      }
451    }
452    // Tenemos siempre un cero por la inicializacion de J, entonces
453    // lo quitamos.
454    J = simplify (J,2);
455    l = insert (l,J);
456  }
457  return (l);
458}
459
460/////////////////////////////////////////////////////////////////////////////
461static proc irredPrimary (list l1)
462"
463USAGE:    irredPrimary (l1); l1, list of ideals.
464RETURN:   a list, primary monomial ideals whose intersection is an
465          irredundant primary decomposition.
466ASSUME:   list l1 is the list of the irredundant irreducible components of a
467          monomial ideal I of the basering.
468"
469{
470  // Variables
471  int i,sizl1,sizl2,j;
472  ideal J,K;
473  list l2,l3;
474//----- irredundant primary decomposition
475  sizl1 = size(l1);
476  for (i = 1 ; i <= sizl1 ; i++)
477  {
478    l2[i] = radicalAux (l1[i]);
479  }
480  sizl2 = size(l2);
481  int sizl2i, sizl2j;
482  // Looking for irreducible components whose radicals are equal.
483  // l1 = irreducible components list
484  // l2 = radical of irreducible components list
485  // l3 = primary components list
486  for (i = 1 ; i <= sizl1 ; i++)
487  {
488    J = l2[i];
489    sizl2i = size(l2[i]);
490    K = l1[i];
491    for (j = i+1 ; j <= sizl2 ; j++)
492    {
493      sizl2j = size(l2[j]);
494      if (sizl2i == sizl2j)
495      {
496        if (equal (J,l2[j]) == 1)
497        {
498          K = minbase(intersect (K,l1[j]));
499          l1 = delete (l1,j);
500          sizl1 = size(l1);
501          l2 = delete (l2,j);
502          sizl2 = size(l2);
503          j--;
504        }
505      }
506    }
507    l3 = insert (l3,K);
508  }
509  return (l3);
510}
511
512/////////////////////////////////////////////////////////////////////////////
513static proc isMinimal (ideal I)
514"
515USAGE:    isMinimal (I); I ideal.
516RETURN:   1, if the given generators of I are the minimal ones;
517          0 & minimal generators of I, otherwise.
518ASSUME:   I is an ideal of the basering given by monomial generators.
519"
520{
521  // VARIABLES
522  int i;
523  ideal J;
524 // Quitamos los ceros del sistema de generadores.
525  I = simplify(I,2);
526  int resp = 1;
527  int sizI = ncols(I);
528  // Cambiamos el tamano de I cuando eliminamos generadores
529  for (i = 1 ; i <= sizI ; i++)
530  {
531    if (sizI <> 1)
532    {
533      if (i == 1)
534      {
535        J = I[2..sizI];
536      }
537      else
538      {
539        if (i > 1 && i < sizI)
540        {
541          J = I[1..i-1], I[i+1..sizI];
542        }
543        else
544        {
545          J = I[1..sizI-1];
546        }
547      }
548      // Si quitamos el generador del lugar "i", luego el que
549      // ocupa ahora el lugar "i" es el "i+1", de ahi que restemos
550      // 1 al i para volver al for de manera que recorramos los
551      // generadores como debemos.
552      if (membershipMon(I[i],J) == 1)
553      {
554        resp = 0;
555        I = J;
556        i--;
557        sizI = ncols(I);
558      }
559    }
560  }
561  if (resp == 1)
562  {
563    return (1);
564  }
565  else
566  {
567    return (0,I);
568  }
569}
570
571/////////////////////////////////////////////////////////////////////////////
572static proc isMonomialGB (ideal I)
573"
574USAGE:    isMonomialGB (I); I ideal.
575RETURN:   a list, 1 & the minimal generators of I, if I is a monomial ideal;
576          0, otherwise.
577ASSUME:   I is an ideal of the basering whose given generators are not
578          monomials.
579NOTE:     This procedure is NOT Groebner free and should be used only if the
580          given generators are not monomials. (Use the proc checkIdeal first.)
581"
582{
583  // Variables
584  int resp;
585  // Si el ideal es cero, no es monomial.
586  if ( size(I) == 0)
587  {
588    return(0);
589  }
590  // Queremos la base de Grobner reducida, para uncidad.
591  intvec save_opt=option(get);
592  option(redSB);
593  // Base de Grobner
594  I = std(I);
595  option(set,save_opt);
596  // Una vez que tenemos la GB, no es mas que comprobar que el ideal
597  // esta generado por monomios.
598  resp = checkIdeal(I);
599  if (resp == 0)
600  {
601    return (0);
602  }
603  else
604  {
605    return (1,I);
606  }
607}
608
609/////////////////////////////////////////////////////////////////////////////
610//
611// Comparing irreducible decompsitions
612// WARNING: this is not a test, when the answer is 1 and the decompositions
613//          may not coincide but it is fast and easy and when the answer is
614//          0 the decompositions do not coincide.
615//
616proc areEqual(list l1, list l2)
617{
618  int i,j,sizIdeal;
619  poly generator;
620  ideal l1Ideal,l2Ideal;
621  int sizl1 = size(l1);
622  for (i = 1 ; i <= sizl1 ; i ++)
623  {
624    sizIdeal = size(l1[i]);
625    generator = 1;
626    for (j = 1 ; j <= sizIdeal ; j ++)
627    {
628      generator = generator*l1[i][j];
629    }
630    l1Ideal[i] = generator;
631  }
632  int sizl2 = size(l2);
633  for (i = 1 ; i <= sizl2 ; i ++)
634  {
635    sizIdeal = size(l2[i]);
636    generator = 1;
637    for (j = 1 ; j <= sizIdeal ; j ++)
638    {
639      generator = generator*l2[i][j];
640    }
641    l2Ideal[i] = generator;
642  }
643  return (equal(l1Ideal,l2Ideal));
644}
645
646/////////////////////////////////////////////////////////////////////////////
647//-------------------------------------------------------------------------//
648//-----------------------   EXTERNOS   ------------------------------------//
649//-------------------------------------------------------------------------//
650/////////////////////////////////////////////////////////////////////////////
651
652/////////////////////////////////////////////////////////////////////////////
653proc isMonomial (ideal I)
654"USAGE:   isMonomial (I); I ideal
655RETURN:   1, if I is a monomial ideal; 0, otherwise.
656ASSUME:   I is an ideal of the basering.
657EXAMPLE:  example isMonomial; shows some examples.
658"
659{
660  // Si el ideal es cero, no es monomial.
661  if ( size(I) == 0)
662  {
663    return(0);
664  }
665  // Si ya viene dado por sistema de generadores monomiales, devolvemos 1
666  if (checkIdeal (I) == 1)
667  {
668    return(1);
669  }
670  // Variables
671  int resp,m,k;
672  // Queremos la base de Grobner reducida, para uncidad.
673  intvec save_opt=option(get);
674  option(redSB);
675  // Hallamos GB
676  I = std(I);
677  option(set,save_opt);
678  // Una vez que tenemos la GB, no es mas que comprobar si el ideal
679  // esta generado por monomios.
680  resp = checkIdeal(I);
681  // Volvemos a dejar el comando "std" devolviendo una GB estandar.
682  return(resp);
683}
684example
685{ "EXAMPLE:"; echo = 2;
686 ring R = 0,(w,x,y,z,t),lp;
687 ideal I = w^3*x*y, w^2*x^2*y^2*z^2 - y^3*z+x^4*z^4*t^4, w*x*y*z*t - w*x^6*y^5*z^4, x^2*z^4*t^3 , w^6*y^4*z^2 + x^2*y^2*z^2;
688 isMonomial(I);
689 ideal J = w^3*x*y + x^3*y^9*t^3, w^2*x^2*y^2*z^2 - y^3*z, w*x*y*z*t - w*x^6*y^5*z^4, x^2*z^4*t^3 + y^4*z^4*t^4, w^6*y^4*z^2 + x^2*y^2*z^2;
690 isMonomial(J);
691}
692
693/////////////////////////////////////////////////////////////////////////////
694proc minbaseMon (ideal I)
695"USAGE:   minbaseMon (I); I ideal.
696RETURN:   an ideal, the minimal monomial generators of I.
697          -1 if the given generators of I are not monomials
698ASSUME:   I is an  ideal generated by a list of monomials of the basering.
699EXAMPLE:  example minbaseMon; shows an example.
700"
701{
702  // VARIABLES
703  int i;
704  ideal J;
705  // Si no esta generado por monomios este metodo no vale
706  int control = checkIdeal(I);
707  if (control == 0)
708  {
709    ERROR ("the ideal is not monomial");
710  }
711  // Quitamos los ceros del sistema de generadores.
712  I = simplify(I,2);
713  int sizI = ncols(I);
714  for (i = 1 ; i <= sizI ; i++)
715  {
716    if (sizI > 1)
717    {
718      if (i == 1)
719      {
720        J = I[2..sizI];
721      }
722      else
723      {
724        if (i > 1 && i < sizI)
725        {
726          J = I[1..i-1], I[i+1..sizI];
727        }
728        else
729        {
730          if (i == sizI)
731          {
732            J = I[1..sizI-1];
733          }
734        }
735      }
736      // Si quitamos el generador del lugar "i", luego el que
737      // ocupa ahora el lugar "i" es el "i+1", de ahi que restemos
738      // 1 al i para volver al for de manera que recorramos los
739      // generadores como debemos.
740      if (membershipMon(I[i],J) == 1)
741      {
742        I = J;
743        i--;
744        sizI = ncols(I);
745      }
746    }
747  }
748  return (I);
749}
750example
751{"EXAMPLE:"; echo = 2;
752 ring R = 0,(w,x,y,z,t),lp;
753 ideal I = w^3*x*y, w^2*x^2*y^2*z^2, y^3*z,x^4*z^4*t^4, w*x*y*z*t,w*x^6*y^5*z^4, x^2*z^4*t^3 , w^6*y^4*z^2,x^2*y^2*z^2;
754 minbaseMon(I);
755}
756
757/////////////////////////////////////////////////////////////////////////////
758proc gcdMon (poly f, poly g)
759"USAGE:   gcdMon (f,g); f,g polynomials.
760RETURN:   a monomial, the greatest common divisor of f and g.
761ASSUME:   f and g are monomials of the basering.
762EXAMPLE:  example gcdMon; shows an example.
763"
764{
765  if (size(f) <> 1 or size(g) <> 1)
766  {
767    ERROR ("the input must be 2 monomials.");
768  }
769  return(gcd(f,g));
770
771//  // Variables
772//  int k;
773//  intvec exp;
774//  int nvar = nvars(basering);
775//  // intput: monomials
776//
777//  intvec expf = leadexp(f);
778//  intvec expg = leadexp(g);
779//  // Nos quedamos con el menor exponente de cada variable.
780//  for (k = 1 ; k <= nvar ; k++)
781//    {
782//      if (expf[k] <= expg[k])
783//        {
784//          exp[k] = expf[k];
785//        }
786//      else
787//        {
788//          exp[k] = expg[k];
789//        }
790//    }
791//  // Devolvemos el monomio correspondiente al exponente que hemos
792//  // calculado.
793//  return(monomial(exp));
794}
795example
796{"EXAMPLE:"; echo = 2;
797  ring R = 0,(x,y,z,t),dp;
798  poly f = x^3*z^5*t^2;
799  poly g = y^6*z^3*t^3;
800  gcdMon(f,g);
801}
802
803/////////////////////////////////////////////////////////////////////////////
804proc lcmMon (poly f, poly g)
805"USAGE:   lcmMon (f,g); f, g polynomials.
806RETURN:   a monomial,the least common multiple of f and g.
807ASSUME:   f,g are monomials of the basering.
808EXAMPLE:  example lcmMon; shows an example.
809"
810{
811  // Hay que verificar que son monomios
812  if (size(f) <> 1 or size(g) <> 1)
813  {
814    ERROR ("the input must be 2 monomials.");
815  }
816  return(f*g/gcd(f,g));
817  //// Variables.
818  //int k;
819  //intvec exp;
820  //int nvar = nvars(basering);
821
822  //// No tenemos mas que tomar el mayor exponente.
823  //intvec expf = leadexp (f);
824  //intvec expg = leadexp (g);
825
826  //for (k = 1 ; k <= nvar ; k ++)
827  //{
828  //  if (expf[k] <= expg[k])
829  //  {
830  //    exp[k] = expg[k];
831  //  }
832  //  else
833  //  {
834  //     exp[k] = expf[k];
835  //  }
836  //}
837  //// Transformamos el vector de exponentes al monomio correspondiente.
838  //return(monomial (exp));
839}
840example
841{"EXAMPLE:"; echo = 2;
842  ring R = 0,(x,y,z,t),dp;
843  poly f = x^3*z^5*t^2;
844  poly g = y^6*z^3*t^3;
845  lcmMon(f,g);
846}
847
848/////////////////////////////////////////////////////////////////////////////
849proc membershipMon(poly f, ideal I)
850"USAGE:   membershipMon(f, I); f polynomial, I ideal.
851RETURN:   1, if f lies in I; 0 otherwise.
852          -1 if I and f are nonzero and I is not a monomial ideal
853ASSUME:   I is a monomial ideal of the basering.
854EXAMPLE:  example membershipMon; shows some examples
855"
856{
857  // Variables
858  int i,j,resp,k,control;
859  intvec restf;
860  // Si el ideal es cero no es monomial, pero la pertenencia no se da si
861  // el polinomio es no nulo
862  if ( size(I) == 0 && size(f) > 0)
863  {
864    return (0);
865  }
866 // El cero esta en todos los ideales.
867  if (f == 0)
868  {
869    return (1);
870  }
871  // COMPROBACIONES
872  control = checkIdeal(I);
873  if (control == 0)
874  {
875    list isMon = isMonomialGB (I);
876    if (isMon[1] == 0)
877    {
878      ERROR ("the ideal is not monomial.");
879    }
880    else
881    {
882      // Sabemos que I ya viene dado por el sistema minimal de
883      // generadores, aunque aqui no sea necesario.
884      I = isMon[2];
885    }
886  }
887  // Quitamos ceros.
888  I = simplify(I,2);
889  int n = ncols(I);
890  int m = size(f);
891  int nvar = nvars(basering);
892  for (i=1 ; i<=m ; i++)
893  {
894    resp = 0;
895    for (j=1 ; j<=n  ;j++)
896    {
897      // Vamos termino a termino viendo si son divididos por algun
898      // generador. Trabajamos con los exponentes, pues es mas
899      // simple.
900      restf = leadexp(f) - leadexp(I[j]);
901      for (k=1 ; k<=nvar; k++)
902      {
903        // Si hay una componente negativa es que este generador
904        // no divide. Queremos entonces ir al siguiente
905        // generador.
906        if (restf[k] < 0)
907        {
908          break;
909        }
910      }
911      // Si no ha habido componente nula, hemos encontrado un
912      // divisor para el actual termino de f. En esta situacion
913      // queremos pasar a otro termino de f, no seguir con los
914      // otros generadores.
915      if (k == nvar+1)
916      {
917        resp = 1;
918        break;
919      }
920    }
921    // Si hemos encontrado para el anterior termino, voy al
922    // siguiente; en caso contrario salimos, pues desde que un
923    // termino no sea dividido, f no esta en I.
924    if (resp == 1)
925    {
926      f = f - lead(f);
927    }
928    else
929    {
930      break;
931    }
932  }
933  // Si hemos recorrido todo el bucle, f esta en I.
934  if (i == m+1)
935  {
936    return (1);
937  }
938  return (0);
939}
940example
941{"EXAMPLE:"; echo = 2;
942 ring R = 0,(w,x,y,z,t),lp;
943 ideal I =  w*x, x^2, y*z*t, y^5*t;
944 poly f =  3*x^2*y + 6*t^5*z*y^6 - 4*x^2 + 8*w*x^5*y^6 - 10*y^10*t^10;
945 membershipMon(f,I);
946 poly g = 3*w^2*t^3 - 4*y^3*z*t^3 - 2*x^2*y^5*t + 4*x*y^3;
947 membershipMon(g,I);
948}
949
950/////////////////////////////////////////////////////////////////////////////
951proc intersectMon (ideal I, ideal J)
952"USAGE:   intersectMon (I, J); I, J ideals.
953RETURN:   an ideal, the intersection of I and J.
954          (it returns -1 if I or J are not monomial ideals)
955ASSUME:   I,J are monomial ideals of the basering.
956NOTE:     the minimal monomial generating set is returned.
957          USING THE SINGULAR COMMAND 'intersect' IS USUALLY FASTER
958EXAMPLE:  example intersectMon; shows some examples
959"
960{
961  // Variables
962  ideal K;
963  int i,j,control;
964  list isMon;
965  // El ideal trivial no es monomial.
966  if ( size(I) == 0 || size(J) == 0)
967  {
968    ERROR("one of the ideals is zero, hence not monomial.");
969  }
970 // COMPROBACIONES
971  control = checkIdeal(I);
972  if (control == 0)
973  {
974    isMon = isMonomialGB(I);
975    if (isMon[1] == 0)
976    {
977      ERROR ("the first ideal is not monomial.");
978    }
979    else
980    {
981      // Sabemos que I ya viene dado por el sistema minimal de
982      // generadores, aunque aqui no sea necesario.
983      I = isMon[2];
984    }
985  }
986  else
987  {
988    // Los generadores son monomiales, hallamos el sistema minimal
989    I = minbase(I);
990  }
991  control = checkIdeal(J);
992  if (control == 0)
993  {
994    isMon = isMonomialGB (J);
995    if (isMon[1] == 0)
996    {
997      ERROR ("the second ideal is not monomial.");
998    }
999    else
1000    {
1001      // Sabemos que J ya viene dado por el sistema minimal de
1002      // generadores, aunque aqui no sea necesario.
1003      J = isMon[2];
1004    }
1005  }
1006  else
1007  {
1008    // Los generadores son monomiales,hallamos la base minimal
1009    J = minbase(J);
1010  }
1011  // Hemos asegurado que los ideales sean monomiales.
1012  // Quitamos ceros de la base para no alargar calculos.
1013  int n = ncols(I);
1014  int m = ncols(J);
1015  // Hallamos el m.c.m.de cada par de generadores de uno y otro ideal
1016  // y los a?adimos al ideal interseccion.
1017  for (i=1 ; i<=n ; i++)
1018  {
1019    for (j=1 ; j<=m ; j++)
1020    {
1021      K = K , lcmMon (I[i],J[j]);
1022    }
1023  }
1024  // Devolvemos el ideal ya dado por la base minimal porque sabemos
1025  // que este procedimiento genera muchos generadores redundantes.
1026  return(minbase(K));
1027}
1028example
1029{"EXAMPLE:"; echo = 2;
1030 ring R = 0,(w,x,y,z,t),lp;
1031 ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z;
1032 ideal J = w*x, x^2, y*z*t, y^5*t;
1033 intersectMon (I,J);
1034}
1035
1036/////////////////////////////////////////////////////////////////////////////
1037proc quotientMon (ideal I, ideal J)
1038"USAGE:   quotientMon (I, J); I, J ideals.
1039RETURN:   an ideal, the quotient I:J.
1040          (returns -1 if I or J is not monomial)
1041ASSUME:   I, J are monomial ideals of the basering.
1042NOTE:     the minimal monomial generating set is returned.
1043EXAMPLE:  example quotientMon; shows an example.
1044"
1045{
1046  // Variables
1047  int i,control,n;
1048  poly f;
1049  list isMon;
1050  //COMPROBACIONES
1051  if (size(I) == 0 || size(J) == 0)
1052  {
1053    ERROR("one of the ideals is zero, hence not monomial.");
1054  }
1055  control = checkIdeal(I);
1056  if (control == 0)
1057  {
1058    isMon = isMonomialGB (I);
1059    if (isMon[1] == 0)
1060    {
1061      ERROR ("the first ideal is not monomial.");
1062    }
1063    else
1064    {
1065      // Sabemos que I ya viene dado por el sistema minimal de
1066      // generadores, aunque aqui no sea necesario.
1067      I = isMon[2];
1068    }
1069  }
1070  else
1071  {
1072    // Los generadores son monomiales,hallamos sistema minimal
1073    I = minbase(I);
1074  }
1075  control = checkIdeal(J);
1076  if (control == 0)
1077  {
1078    isMon = isMonomialGB (J);
1079    if (isMon[1] == 0)
1080    {
1081      ERROR ("the second ideal is not monomial.");
1082    }
1083    else
1084    {
1085      // Sabemos que J ya viene dado por el sistema minimal de
1086      // generadores, aunque aqui no sea necesario.
1087      J = isMon[2];
1088    }
1089  }
1090  else
1091  {
1092    // Los generadores son monomiales, hallamos el sistema minimal
1093    J = minbase(J);
1094  }
1095  // Tenemos los ideales dados por su sistema minimal (aunque no es necesario, ahorra
1096  // calculos. En K vamos a tener la interseccion de los ideales.
1097  ideal K = 1;
1098  // ------ Empezamos a hacer el cociente.
1099  // Los ideales estan dados por su sistema minimal, con lo que no aparecen ceros.
1100  // Luego podemos usar size(J).
1101  n = ncols(J);
1102  for (i = 1 ; i <= n ; i++)
1103  {
1104    K = intersect (K ,quotientIdealMon(I,J[i]));
1105  }
1106  // Aqui tambien surgen muchos generadores que no forman parte de la
1107  // base minimal del ideal obtenido.
1108  return(minbase(K));
1109}
1110example
1111{"EXAMPLE:"; echo = 2;
1112 ring R = 0,(w,x,y,z,t),lp;
1113 ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z;
1114 ideal J = w*x, x^2, y*z*t, y^5*t;
1115 quotientMon (I,J);
1116}
1117
1118/////////////////////////////////////////////////////////////////////////////
1119proc radicalMon(ideal I)
1120"USAGE:   radicalMon(I); I ideal
1121RETURN:   an ideal, the radical ideal of the ideal I.
1122          (returns -1 if I is not a monomial ideal)
1123ASSUME:   I is a monomial ideal of the basering.
1124NOTE:     The minimal monomial generating set is returned.
1125EXAMPLE:  example radicalMon; shows an example.
1126"
1127{
1128  // Cambiamos de anillo
1129  int nvar = nvars(basering);
1130  // Variables
1131  int i,m,j,control;
1132  poly f;
1133  intvec v;
1134  ideal rad_I;
1135  // COMPROBACIONES
1136  control = checkIdeal(I);
1137  // Si el sistema de generadores no esta formado por monomios, hay
1138  // que comprobar si el ideal es monomial.
1139  if (control == 0)
1140  {
1141    list isMon = isMonomialGB (I);
1142    if (isMon[1] == 0)
1143    {
1144      ERROR ("the ideal is not monomial.");
1145    }
1146    else
1147    {
1148      I = isMon[2];
1149      // Ya lo tenemos con los generadores monomiales minimales
1150    }
1151  }
1152  else
1153  {
1154    // Generadores monomiales, hallamos sistema minimal
1155    I = minbase(I);
1156  }
1157  // Ya tenemos el ideal generado por la BASE MINIMAL MONOMIAL
1158  m = ncols(I);
1159  // Solo hay que poner exponente 1 a todas las variables que tengan
1160  // exponente >1.
1161  for (i = 1 ; i <= m ; i++)
1162  {
1163    v = leadexp(I[i]);
1164    f = 1;
1165    for (j = 1 ; j <= nvar ; j++)
1166    {
1167      if (v[j] <> 0)
1168      {
1169        f = f*var(j);
1170      }
1171    }
1172    rad_I = rad_I,f;
1173  }
1174  // Hay que devolver el ideal dado por la base minimal, pues se
1175  // producen muchos generadores redundantes.
1176  return( minbase (rad_I));
1177}
1178example
1179{"EXAMPLE:"; echo = 2;
1180 ring R = 0,(w,x,y,z,t),lp;
1181 ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z;
1182 radicalMon(I);
1183}
1184
1185/////////////////////////////////////////////////////////////////////////////
1186proc isprimeMon (ideal I)
1187"USAGE:   isprimeMon (I); I ideal
1188RETURN:   1, if I is prime; 0, otherwise.
1189          (returns -1 if I is not a monomial ideal)
1190ASSUME:   I is a monomial ideal of the basering.
1191EXAMPLE:  example isprimeMon; shows some example.
1192"
1193{
1194  // Variables
1195  int control,i,j,suma;
1196  intvec expin;
1197 // COMPROBACIONES
1198  control = checkIdeal(I);
1199  // Si el sistema de generadores no esta formado por monomios, hay
1200  // que comprobar si el ideal es monomial.
1201  if (control == 0)
1202  {
1203    list isMon = isMonomialGB (I);
1204    if (isMon[1] == 0)
1205    {
1206      ERROR ("the ideal is not monomial.");
1207    }
1208    else
1209    {
1210      I = isMon[2];
1211      // Ya lo tenemos con los generadores minimales
1212    }
1213  }
1214  else
1215  {
1216    // Generadores monomiales, hallamos el sistema minimal
1217    I = minbase(I);
1218  }
1219  // Ya tenemos el ideal generado por la BASE MINIMAL
1220  if (maxdeg1(I) == 1)
1221  {
1222    return (1);
1223  }
1224  return (0);
1225}
1226example
1227{"EXAMPLE:"; echo = 2;
1228 ring R = 0,(w,x,y,z,t),lp;
1229 ideal I = w,y,t;
1230 isprimeMon (I);
1231 ideal J = w,y,t,x*z;
1232 isprimeMon (J);
1233}
1234
1235/////////////////////////////////////////////////////////////////////////////
1236proc isprimaryMon (ideal I)
1237"USAGE:   isprimaryMon (I); I ideal
1238RETURN:   1, if I is primary; 0, otherwise.
1239          (returns -1 if I is not a monomial ideal)
1240ASSUME:   I is a monomial ideal of the basering.
1241EXAMPLE:  example isprimaryMon; shows some examples
1242"
1243{
1244  // Variables
1245  int nvar,control,m,l,sub_in,i,j,k;
1246  intvec v,w,exp_gen;
1247  // COMPROBACIONES
1248  control = checkIdeal(I);
1249  // Si el sistema de generadores no esta formado por monomios, hay
1250  // que comprobar si el ideal es monomial.
1251  if (control == 0)
1252  {
1253    list isMon = isMonomialGB (I);
1254    if (isMon[1] == 0)
1255    {
1256      ERROR ("the ideal is not monomial.");
1257    }
1258    else
1259    {
1260      I = isMon[2];
1261      // Ya lo tenemos con los generadores minimales
1262    }
1263  }
1264  else
1265  {
1266    // Generadores monomiales, hallamos el sistema minimal
1267    I = minbase(I);
1268  }
1269  // Ya tenemos el ideal generado por la BASE MINIMAL
1270  // Usamos la funcion "soporte" que hemos creado, para saber que
1271  // variables aparecen en la base de generadores como producto de si
1272  // mismas y tambien cuales son los generadores del ideal donde
1273  // tenemos que comprobar si aparecen tales variables.
1274  nvar = nvars(basering);
1275  m = ncols(I);
1276  // Inicializo la ultima componente del vector para que contenga a
1277  // todas las variables (el subindice de la variable es el lugar
1278  // que ocupa como componente de v).
1279  v[nvar] = 0;
1280  k = 1;
1281  // v = 1 en variables solas y 0 en el resto.
1282  // w = lugar de los generadores de I que son producto de mas de una variable.
1283  for (i = 1 ; i <= m ; i++)
1284  {
1285    sub_in = soporte(I[i]);
1286    // Si soporte <> 0 la variable aparece sola, en caso contrario
1287    // el generador es producto de mas de una variable
1288    if (sub_in <> 0)
1289    {
1290      v[sub_in] = 1;
1291    }
1292    else
1293    {
1294      w[k] = i;
1295      k++;
1296    }
1297  }
1298  // Ahora solo hay que ver que no aparecen variables distintas de
1299  // las que tenemos marcadas con 1 en v.
1300  l = size(w);
1301  // Si w es cero, quiere decir que todos los generadores del ideal
1302  // son producto de una sola variable, luego es primario.
1303  if (l == 1 && w[1] == 0)
1304  {
1305    return(1);
1306  }
1307  // Estudiamos el exponente de los generadores de I oportunos (los
1308  // que nos indica w).
1309  for (i = 1 ; i <= l ; i++)
1310  {
1311    exp_gen = leadexp(I[w[i]]);
1312    for (j = 1 ; j <= nvar ; j++)
1313    {
1314      if (v[j] == 0)
1315      {
1316        if (exp_gen[j] <> 0)
1317        {
1318          return (0);
1319        }
1320      }
1321    }
1322  }
1323  // Si hemos recorrido todo el ideal sin que salte el "for"
1324  // quiere decir que no se ha contradicho la caracterizacion,
1325  // luego el ideal es primario.
1326  return(1);
1327}
1328example
1329{"EXAMPLE:"; echo = 2;
1330 ring R = 0,(w,x,y,z,t),lp;
1331 ideal I = w^4,x^3,z^2,t^5,x*t,w*x^2*z;
1332 isprimaryMon (I);
1333 ideal J = w^4,x^3,z^2,t^5,x*t,w*x^2*z,y^3*t^3;
1334 isprimaryMon (J);
1335}
1336
1337/////////////////////////////////////////////////////////////////////////////
1338proc isirreducibleMon (ideal I)
1339"USAGE:   isirreducibleMon(I); I ideal
1340RETURN:   1, if I is irreducible; 0, otherwise.
1341          returns -1 if I is not a monomial ideal
1342ASSUME:   I is a monomial ideal of the basering.
1343EXAMPLE:  example isirreducibleMon; shows some examples
1344"
1345{
1346  // Variables
1347  intvec v;
1348  int n,i,j,sum,control;
1349  control = checkIdeal(I);
1350  // Si el sistema de generadores no esta formado por monomios, hay
1351  // que comprobar si el ideal es monomial.
1352  if (control == 0)
1353  {
1354    list isMon = isMonomialGB (I);
1355    if (isMon[1] == 0)
1356    {
1357      ERROR ("the ideal is not monomial.");
1358    }
1359    else
1360    {
1361      I = isMon[2];
1362      // Ya lo tenemos con los generadores minimales
1363    }
1364  }
1365  else
1366  {
1367    // Generadores monomiales, hallamos sistema minimal
1368    I = minbase(I);
1369  }
1370  // Ya tenemos el ideal generado por la BASE MINIMAL
1371  n = ncols(I);
1372  // La funcion soporte devuelve 0 si el monomio es producto de mas
1373  // de una variable. Chequeamos generador a generador si el ideal
1374  // esta generado por potencias de variables.
1375  for (i = 1 ; i <= n ; i ++)
1376  {
1377    if (soporte(I[i]) == 0)
1378    {
1379      return(0);
1380    }
1381  }
1382  return (1);
1383}
1384example
1385{"EXAMPLE:"; echo = 2;
1386 ring R = 0,(w,x,y,z,t),lp;
1387 ideal I = w^4,x^3,z^2,t^5;
1388 isirreducibleMon (I);
1389 ideal J = w^4*x,x^3,z^2,t^5;
1390 isirreducibleMon (J);
1391}
1392
1393/////////////////////////////////////////////////////////////////////////////
1394proc isartinianMon (ideal I)
1395"USAGE:   isartinianMon(I); I ideal.
1396RETURN:   1, if ideal is artinian; 0, otherwise.
1397          returns -1 if ideal I is not a monmomial ideal
1398ASSUME:   I is a monomial ideal of the basering.
1399EXAMPLE:  example isartinianMon; shows some examples
1400"
1401{
1402  int  nvar  = nvars(basering);
1403  // Declaracion de variables
1404  int i,j,k,cont,sizI;
1405  intvec v;
1406  // COMPROBACIONES
1407  int control = checkIdeal(I);
1408  // Si el sistema de generadores no esta formado por monomios, hay
1409  // que comprobar si el ideal es monomial.
1410  if (control == 0)
1411  {
1412    list isMon = isMonomialGB (I);
1413    if (isMon[1] == 0)
1414    {
1415      ERROR ("the ideal is not monomial.");
1416    }
1417    else
1418    {
1419      I = isMon[2];
1420      // Ya lo tenemos con los generadores minimales
1421    }
1422  }
1423  else
1424  {
1425    // Generadores monomiales, hallamos sistema minimal
1426    I = minbase(I);
1427  }
1428  // Ya tenemos el ideal generado por la BASE MINIMAL
1429  sizI = ncols(I);
1430  // Comprobamos que entre los generadores minimales aparece una
1431  // potencia de cada. Cuando encontramos un generador que es potencia
1432  // de una sola variable aumento contador
1433  cont = 0;
1434  for (i = 1 ; i <= sizI ; i++)
1435  {
1436    if (soporte(I[i]) <> 0)
1437    {
1438      cont ++;
1439      // Solo volvemos a evaluar en caso de que hayamos aumentado
1440      if (cont == nvar)
1441      {
1442        // Ya hemos encontrado que todas las variables aparrecen en
1443        // el sistema minimal como potencia pura. No queremos seguir
1444        // buscando
1445        return (1);
1446      }
1447    }
1448  }
1449  // Si ha salido, es que faltan variables
1450  return(0);
1451}
1452example
1453{"EXAMPLE:"; echo = 2;
1454 ring R = 0,(w,x,y,z,t),lp;
1455 ideal I = w^4,x^3,y^4,z^2,t^6,w^2*x^2*y,w*z*t^4,x^2*y^3,z^2*t^5;
1456 isartinianMon (I);
1457 ideal J = w^4,x^3,y^4,z^2,w^2*x^2*y,w*z*t^4,x^2*y^3,z^2*t^5;
1458 isartinianMon (J);
1459}
1460
1461/////////////////////////////////////////////////////////////////////////////
1462proc isgenericMon (ideal I)
1463"USAGE:   isgenericMon(I); I ideal.
1464RETURN:   1, if ideal is generic; 0, otherwise.
1465          returns -1 if ideal I is not a monomial ideal
1466ASSUME:   I is a monomial ideal of the basering.
1467EXAMPLE:  example isgenericMon; shows some examples.
1468"
1469{
1470  int nvar = nvars(basering);
1471  // Declaracion de variables
1472  int sizI,i,j,k;
1473  list exp;
1474 // COMPROBACIONES
1475  int control = checkIdeal(I);
1476  // Si el sistema de generadores no esta formado por monomios, hay
1477  // que comprobar si el ideal es monomial.
1478  if (control == 0)
1479  {
1480    list isMon = isMonomialGB (I);
1481    if (isMon[1] == 0)
1482    {
1483      ERROR ("the ideal is not monomial.");
1484    }
1485    else
1486    {
1487      I = isMon[2];
1488      // Ya lo tenemos con los generadores minimales
1489    }
1490  }
1491  else
1492  {
1493    // Generadores monomiales, hallamos sistema minimal
1494    I = minbase(I);
1495  }
1496  // Ya tenemos el ideal generado por la BASE MINIMAL
1497  sizI = ncols(I);
1498  // Creamos una lista que tenga los exponentes de todos los
1499  // generadores.
1500  for (i = 1 ; i <= sizI ; i++)
1501  {
1502    exp[i] = leadexp(I[i]);
1503  }
1504  // Ahora hay que ver si alguno se repite, y si uno de ellos
1505  // lo hace, ya no es gen?rico.
1506  for (i = 1 ; i <= nvar ; i++)
1507  {
1508    for (j = 1 ; j <= sizI-1 ; j++)
1509    {
1510      for (k = j+1 ; k <= sizI ; k++)
1511      {
1512        // Notar que no se pueden repetir si la variable realmente
1513        // aparece en el generador, es decir, exponente >1.
1514        if (exp[j][i] == exp[k][i] & exp[j][i] <> 0)
1515        {
1516          return (0);
1517        }
1518      }
1519    }
1520  }
1521  return (1);
1522}
1523example
1524{"EXAMPLE:"; echo = 2;
1525 ring R = 0,(w,x,y,z,t),lp;
1526 ideal I = w^4,x^3,y^4,z^2,w^2*x^2*y,w*z*t^4,x*y^3,z*t^5;
1527 isgenericMon (I);
1528 ideal J = w^4,x^3,y^4,z^3,w^2*x^2*y,w*z*t^4,x*y^3,z^2*t^5;
1529 isgenericMon (J);
1530}
1531
1532/////////////////////////////////////////////////////////////////////////////
1533proc dimMon (ideal I)
1534"USAGE:  dimMon (I); I ideal
1535RETURN:  an integer, the dimension of the affine variety defined by
1536         the ideal I.
1537         returns -1 if I is not a monomial ideal
1538ASSUME:  I is a monomial ideal of the basering.
1539EXAMPLE: example dimMon; shows some examples.
1540"
1541{
1542 // El ideal trivial no es monomial.
1543  if ( size(I) == 0 )
1544  {
1545    ERROR("the ideal is zero, hence not monomial.");
1546  }
1547  // VARIABLES
1548  int control,sizSum,sumandos,i,j,k,cont;
1549 // COMPROBACIONES
1550  control = checkIdeal(I);
1551  if (control == 0)
1552  {
1553    list isMon = isMonomialGB (I);
1554    if (isMon[1] == 0)
1555    {
1556      ERROR ("the ideal is not monomial.");
1557    }
1558    else
1559    {
1560      // Sabemos que I ya viene dado por el sistema minimal de
1561      // generadores, aunque aqui no sea necesario.
1562      I = isMon[2];
1563    }
1564  }
1565  attrib(I,"isSB",1);
1566  return (dim(I));
1567//  int nvar = nvars(basering);
1568//  intvec index,indexAux,vaux,w;
1569//  list sum, sumAux;
1570//  // La base del ideal tiene que ser la monomial
1571//  // Si el ideal es artiniano, es 0-dimensional
1572//  if (isartinianMon(I) == 1)
1573//  {
1574//    return (0);
1575//  }
1576//  int sizI = ncols(I);
1577//  // v(i) = vector con sizI entradas y donde cada entrada "j" se corresponde
1578//  //        con el exponente del generador "i" en la variable "j"
1579//  for (i = 1 ; i <= nvar ; i++)
1580//  {
1581//    intvec v(i);
1582//    for (j = 1 ; j <= sizI ;j++ )
1583//    {
1584//      v(i)[j] = leadexp(I[j])[i];
1585//    }
1586//  }
1587//  // Vamos a guardar en el vector "index" la ultima variable que se ha
1588//  // sumado y en cada "sum(i)" el vector suma que se corresponde con la
1589//  // entrada "i" del vector index.
1590//  // Inicializo los valores de index y de cada sum
1591//  w[sizI] = 0;
1592//  sum[1] = w;
1593//  index[1] = 0;
1594//  sizSum = 1;
1595//  while ( 1 )
1596//  {
1597//    cont = 1;
1598//    sumandos ++;
1599//    for (i = 1 ; i <= sizSum ; i ++)
1600//    {
1601//      for (j = index[i] + 1 ; j <= nvar ; j ++)
1602//      {
1603//        w = sum[i];
1604//        vaux = w + v(j);
1605//        // Comprobamos
1606//        for (k = 1 ; k <= sizI ; k ++)
1607//        {
1608//          if (vaux[k] == 0)
1609//          {
1610//            break;
1611//          }
1612//        }
1613//        if (k == sizI +1)
1614//        {
1615//          return (nvar - sumandos);
1616//        }
1617//        if (j <> nvar)
1618//        {
1619//          sumAux[cont] = vaux;
1620//          indexAux[cont] = j;
1621//          cont ++;
1622//        }
1623//      }
1624//    }
1625//    index = indexAux;
1626//    sum = sumAux;
1627//    sizSum = size(sumAux);
1628//  }
1629}
1630example
1631{"EXAMPLE:"; echo = 2;
1632 ring R = 0,(w,x,y,z,t),lp;
1633 ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z;
1634 dimMon (I);
1635 ideal J = w^4,x^3,y^4,z^2,t^6,w^2*x^2*y,w*z*t^4,x^2*y^3,z*t^5;
1636 dimMon (J);
1637}
1638
1639/////////////////////////////////////////////////////////////////////////////
1640//-------------------------------------------------------------------------//
1641//-----------------------  DESCOMPOSICIONES  -----------------------------_//
1642//-------------------------------------------------------------------------//
1643/////////////////////////////////////////////////////////////////////////////
1644
1645//////////////////////////////////////////////////////////////////////
1646// METODO 1: Metodo directo para descomp. irreducible (ver Vasconcelos)
1647//
1648//////////////////////////////////////////////////////////////////////
1649// Este procedimiento calcula la descomposicion en irreducibles de  //
1650// un ideal monomial dado por su base minimal de generadores        //
1651// haciendo uso de la caracterizacion de ideal monomial irreducible //
1652// (Vasconcelos)                                                    //
1653//////////////////////////////////////////////////////////////////////
1654static proc irredDec1 (ideal I)
1655{
1656  // Variables
1657  int i,j,n,resp;
1658  list l1,l2;
1659  intvec exp,v;
1660  ideal J,K;
1661  // ----- DESCOMPOSICION IRREDUCIBLE
1662  // Inicializamos la lista que va a estar formada por los ideales
1663  // que tenemos que comprobar son irreducibles.
1664  I = simplify(I,1);
1665  l1 = I;
1666  while (size(l1) > 0)
1667  {
1668    for (i = 1 ; i <= size(l1) ; i++)
1669    {
1670      J = l1[i];
1671      n = ncols(J);
1672      l1 = delete(l1,i);
1673      // Llamamos a la funcion que va a detectar si el ideal es o
1674      // no irreducible, y en caso de no serlo sabemos sobre que
1675      // generador y con que variables hay que aplicar el
1676      // el resultado teorico.
1677      v = irredAux (J);
1678      // No irreducible
1679      if (size(v) > 1)
1680      {
1681        // En este caso, v[1] nos indica el generador del ideal
1682        // que debemos eliminar.
1683        exp = leadexp(J[v[1]]);
1684        if (v[1] == 1)
1685        {
1686          J = J[2..n];
1687        }
1688        if (v[1] > 1 && v[1] < n)
1689        {
1690          J = J[1..v[1]-1],J[v[1]+1..n];
1691        }
1692        if (v[1] == n)
1693        {
1694          J = J[1..n-1];
1695        }
1696        // Ahora vamos a introducir los nuevos generadores en
1697        // cada uno de los nuevos ideales que generamos. Los
1698        // ponemos en la lista en la que comprobamos.
1699        for (j = 1 ; j <= size(v)-1 ; j++)
1700        {
1701          K = J,var(v[j+1])^exp[v[j+1]];
1702          l1 = insert(l1,minbase(K));
1703        }
1704      }
1705      // Si v[1]=0, el ideal es irreducible y lo introducimos en
1706      // la lista l2, que es la que finalmente devolvera las
1707      // componentes de la descomposicion.
1708      else
1709      {
1710        l2 = insert(l2,J);
1711      }
1712    }
1713  }
1714  // ---- IRREDUNDANTE
1715  l2 = irredundant (l2);
1716  // La salida es la lista de los ideales irreducibles.
1717  return (l2);
1718}
1719
1720//////////////////////////////////////////////////////////////////////
1721// La siguiente funcion va a obtener una descomposicion primaria    //
1722// minimal a partir de la irreducible anterior.                     //
1723//////////////////////////////////////////////////////////////////////
1724static proc primDec1 (ideal I)
1725{
1726  // Variables
1727  list l1,l2;
1728// ----- DESCOMPOSICION IRREDUCIBLE
1729  l1 = irredDec1 (I);
1730// ----- DESCOMPOSICION PRIMARIA
1731  l2 = irredPrimary (l1);
1732  return (l2);
1733}
1734
1735//////////////////////////////////////////////////////////////////////
1736// METODO 2: Metodo directo para descomp. primaria (ver Vasconcelos)
1737//
1738//////////////////////////////////////////////////////////////////////
1739// La siguiente funcion va a calcular una descomposicion primaria   //
1740// minimal de un ideal monomial, pero esta vez usando la            //
1741// caracterizacion de ideal monomial primario y un resultado que    //
1742//  hace uso de esta (Vasconcelos).                                 //
1743//////////////////////////////////////////////////////////////////////
1744static proc primDec2 (ideal I)
1745{
1746  // Variables en el nuevo anillo
1747  int i,n,max;
1748  list l1,l2;
1749  intvec v;
1750  ideal J,K;
1751  // Vamos a tener dos listas: l1 que va a guardar todos los ideales
1752  // que vayamos generando con el resultado citado antes, que seran
1753  // los que vamos a comprobar si son primarios; y l2, donde guardamos
1754  // aquellos de l1 que verifiquemos son primarios.
1755  I = simplify(I,1);
1756  l1 = I;
1757  while (size(l1) > 0)
1758  {
1759    for (i = 1 ; i <= size(l1) ; i++)
1760    {
1761      J = l1[i];
1762      n = ncols(J);
1763      l1 = delete (l1,i);
1764      // Usamos la funcion que hemos creado para saber si el ideal
1765      // es primario. Si no lo es devuelve la variable que crea
1766      // conflicto y los generadores del ideal que luego hay que
1767      // usar (los que tienen productos de mas de una vble).
1768      // Se le llama con el sistema minimal de generadores
1769      v = primAux (J);
1770      // En caso de no ser primario, hay que buscar el maximo
1771      // exponente de la variable que aparece en los generadores
1772      // del ideal multiplicada siempre por otras variables,
1773      // nunca por si misma.
1774      if (v[1] == 0)
1775      {
1776        max = maxExp(J,v);
1777        K = J,var(v[2])^max;
1778        l1 = insert (l1,minbase(K));
1779        K = quotientIdealMon(J,var(v[2])^max);
1780        // quotientidealMon devuelve sistema minimal de generadores
1781        l1 = insert (l1,minbase(K));
1782      }
1783      // En caso de ser primario, lo introducimos en la lista
1784      // conveniente.
1785      else
1786      {
1787        l2 = insert (l2,J);
1788      }
1789    }
1790  }
1791// ------   IRREDUNDANTE
1792  l2 = irredundant (l2);
1793  return (l2);
1794}
1795//////////////////////////////////////////////////////////////////////
1796// METODO 3: via dual de Alexander y doble dual (Miller)
1797//
1798//////////////////////////////////////////////////////////////////////
1799// Esta funcion calcula la descomposicion irreducible usando el     //
1800// dual de Alexander teniendo en cuenta que el dual del dual es el  //
1801// ideal de partida (Miller)                                        //
1802//////////////////////////////////////////////////////////////////////
1803static proc irredDec3 (ideal I)
1804{
1805  int i,n,j;
1806  poly lcm;
1807  intvec v,exp_I,exp;
1808  ideal J;
1809  list l;
1810  // Hallamos el m.c.m. de los generadores minimales del ideal.
1811  n = ncols (I);
1812  lcm = I[1];
1813  for ( i = 2 ; i <= n ; i++ )
1814  {
1815    lcm = lcmMon (lcm,I[i]);
1816  }
1817  v = leadexp (lcm);
1818  // Calculamos el dual de Alexander.
1819  // Hacemos una funcion para este paso porque luego lo volveremos a
1820  // utilizar.
1821  l = alexDif (v,I);
1822  // Tenemos los ideales irreducibles cuya interseccion nos da el dual
1823  // de Alexander. Notar que tenemos tantos ideales como generadores
1824  // minimales tiene I.
1825  // Hallamos la base minimal.
1826  J = minbase(intersect(l[1..size(l)]));
1827  // Ya solo queda el ultimo paso: hallar de nuevo el dual de
1828  // Alexander. Sabemos que este proceso ya devuelve la descomposicion
1829  // irreducible irredundante.
1830  l = alexDif (v,J);
1831  return (l);
1832}
1833
1834//////////////////////////////////////////////////////////////////////
1835// En este caso hallamos una descomposicion primaria minimal usando //
1836// la irreducible irredundante del procedimiento anterior.          //
1837//////////////////////////////////////////////////////////////////////
1838static proc primDec3 (ideal I)
1839{
1840  // Variables
1841  list l1,l2;
1842// ----- DESCOMPOSICION IREDUCIBLE
1843  l1 = irredDec3 (I);
1844// ----- DESCOMPOSICION PRIMARIA
1845  l2 = irredPrimary (l1);
1846  return (l2);
1847}
1848
1849//////////////////////////////////////////////////////////////////////
1850// METODO 4: via dual de Alexander y cociente (Miller)
1851//
1852//////////////////////////////////////////////////////////////////////
1853// Vamos a hallar las componentes irreducibles de un ideal monomial //
1854// dado por sus generadores minimales haciendo uso del dual de      //
1855// Alexander (con el cociente) (Miller)                             //
1856//////////////////////////////////////////////////////////////////////
1857static proc irredDec4 (ideal I)
1858{
1859  // Cambiamos de anillo.
1860  int nvar = nvars(basering);
1861 // Variables
1862  int n,i,j,m,resp;
1863  poly lcm;
1864  intvec v;
1865  ideal J,K;
1866  list L;
1867  // Calculamos el l.c.m. de los generadores minimales del ideal.
1868  n = ncols (I);
1869  lcm = I[1];
1870  for ( i = 2 ; i <= n ; i++ )
1871  {
1872    lcm = lcmMon (lcm,I[i]);
1873  }
1874  v = leadexp (lcm);
1875  // Hallamos el ideal J = (x(1)^(l(1)+1),...,x(n)^(l(n)+1)). Como
1876  // luego, en el procedimiento quotientMon, vamos a hallar la base
1877  // minimal de cada ideal, no nos preocupa que tengamos un cero en
1878  // el ideal J.
1879  for ( i = 1 ; i <= nvar ; i++ )
1880  {
1881    J[i] = (var(i))^(v[i]+1);
1882  }
1883  // Ahora hacemos el cociente oportuno.
1884  K = minbase(quotient (J,I));
1885  // Buscamos aquellos generadores de K que no son divisibles por los
1886  // generadores de J. Los generadores que son divisibles los hacemos
1887  // cero y luego los eliminamos.
1888  m = ncols (K);
1889  for ( i = 1 ; i <= m ; i++ )
1890  {
1891    resp = membershipMon(K[i],J);
1892    if ( resp == 1)
1893    {
1894      K[i] = 0;
1895    }
1896  }
1897  K = simplify (K,2);
1898  // Ahora obtenemos las componentes de la descomposicion irreducible,
1899  // que estan en correspondencia con los generadores minimales de K.
1900  L = alexDif (v,K);
1901  // Volvemos al anillo de partida y devolvemos la lista de las
1902  // componentes irreducibles irredundantes.
1903  return (L);
1904}
1905
1906//////////////////////////////////////////////////////////////////////
1907// Ahora hallamos una descomposicion primaria irredundante usando   //
1908// la ultima funcion para hallar las componentes irreducibles de un //
1909// ideal monomial dado por sus generadores minimales.               //
1910//////////////////////////////////////////////////////////////////////
1911static proc primDec4 (ideal I)
1912{
1913  // Variables
1914  list l1,l2;
1915// ----- DESCOMPOSICION IREDUCIBLE
1916  l1 = irredDec4 (I);
1917// ----- DESCOMPOSICION PRIMARIA
1918  l2 = irredPrimary (l1);
1919  return (l2);
1920}
1921
1922//////////////////////////////////////////////////////////////////////
1923// METODO 5: un misterio!!
1924//
1925//////////////////////////////////////////////////////////////////////
1926// Este procedimiento halla los elementos maximales de la base      //
1927// estandar del ideal, que se correspoenden con las componentes     //
1928// irreducibles del ideal 1-1.                                      //
1929//////////////////////////////////////////////////////////////////////
1930static proc irredDec5 (ideal I)
1931{
1932  int nvar = nvars(basering);
1933  //Variables
1934  int i,j;
1935  ideal K;
1936  // Artinianization
1937  list artiniano = artinian (I);
1938  if (artiniano[1] == 0)
1939  {
1940    I = artiniano[2];
1941    intvec elimina = artiniano[3];
1942  }
1943  // Quotient
1944  ideal M = maxideal(1);
1945  ideal J = quotient (I,M);
1946  // Deleting generators lying in I
1947  for (i = 1 ; i <= ncols(J) ; i ++)
1948  {
1949    if (membershipMon(J[i],I) == 1)
1950    {
1951      if (i == 1)
1952      {
1953        J = J[2..ncols(J)];
1954        i --;
1955      }
1956      else
1957      {
1958        if (i == ncols(J))
1959        {
1960          J = J[1..i-1];
1961          i --;
1962        }
1963        else
1964        {
1965          J = J[1..i-1],J[i+1..ncols(J)];
1966          i --;
1967        }
1968      }
1969    }
1970  }
1971  // Exponents of the ideals are going to form the decomposition
1972  int sizJ = ncols(J);
1973  for (i = 1 ; i <= sizJ ; i ++ )
1974  {
1975    intvec exp(i) = leadexp(J[i]) + 1;
1976  }
1977  // Deleting artinianization process
1978  if (artiniano[1] == 0)
1979  {
1980    // En elimina estan guardadas las variables que hay que eliminar
1981    for (i = 1 ; i <= nvar ; i ++)
1982    {
1983      if (elimina[i] <> 0)
1984      {
1985        for (j = 1 ; j <= sizJ ; j ++)
1986        {
1987          if (exp(j)[i] == elimina[i])
1988          {
1989            exp(j)[i] = 0;
1990          }
1991        }
1992      }
1993    }
1994  }
1995  // En exp(i) tengo los exponentes de cada variable de las que aparecen
1996  // en cada ideal.
1997  list facets;
1998  for (i = 1 ; i <= sizJ ; i ++)
1999  {
2000    J = 0;
2001    for (j = 1 ; j <= nvar ; j ++)
2002    {
2003      if (exp(i)[j] <> 0)
2004      {
2005        J = J,var(j)^exp(i)[j];
2006      }
2007    }
2008    J = simplify(J,2);
2009    facets[i] = J;
2010  }
2011  return (facets);
2012}
2013
2014//////////////////////////////////////////////////////////////////////
2015// Ahora hallamos una descomposicion primaria irredundante usando   //
2016// la ultima funcion para hallar las componentes irreducibles de un //
2017// ideal monomial dado por sus generadores minimales.               //
2018//////////////////////////////////////////////////////////////////////
2019static proc primDec5 (ideal I)
2020{
2021  // Variables
2022  list l1,l2;
2023// ----- IRREDUCIBLE DECOMPOSITION
2024  l1 = irredDec5 (I);
2025// ----- PRIMARY DECOMPOSITION
2026  l2 = irredPrimary (l1);
2027  return (l2);
2028}
2029
2030//////////////////////////////////////////////////////////////////////
2031// METODO 6: via complejo de Scarf (Milovsky)
2032//
2033//////////////////////////////////////////////////////////////////////
2034// Metodo que usa el complejo de Scarf asociado a un ideal monomial //
2035// de k[x(1)..x(n)] (Milowski)                                      //
2036//////////////////////////////////////////////////////////////////////
2037//////////////////////////////////////////////////////////////////////
2038// Calcula el maximo exponente de la variable x(i) entre los        //
2039// generadores del ideal.                                           //
2040//////////////////////////////////////////////////////////////////////
2041static proc maximoExp(ideal I,int i)
2042{
2043  // VARIABLES
2044  int max,j,k,sizI;
2045  intvec exp;
2046  sizI = ncols(I);
2047  max = 0;
2048  for (j = 1 ; j <= sizI ; j ++)
2049  {
2050    exp = leadexp(I[j]);
2051    if ( exp[i] > max)
2052    {
2053      max = exp[i];
2054    }
2055  }
2056  return(max);
2057}
2058
2059//////////////////////////////////////////////////////////////////////
2060// Esta funcion estudia si un ideal monomial dado por su sistema    //
2061// minimal de generadores es o no artiniano. En caso de no serlo,   //
2062// halla el artiniano mas proximo y ademas devuelve los generadores //
2063// que han sido introducidos.                                       //
2064//////////////////////////////////////////////////////////////////////
2065static proc artinian (ideal I)
2066{
2067  // Cambiamos de anillo
2068  int  nvar  = nvars(basering);
2069  // Declaracion de variables
2070  int i,j,k,cont1,cont2,sizI,marcavar,max;
2071  intvec v,variablesin,cambio;
2072  list nuevo;
2073  ideal J;
2074  sizI = ncols(I);
2075  // Comprobamos que entre los generadores minimales aparece una
2076  // potencia de cada
2077  cont2 = 0;
2078  for (i = 1 ; i <= sizI ; i++)
2079  {
2080    v = leadexp(I[i]);
2081    marcavar  = 0;
2082    cont1 = 0;
2083    for (j = 1 ; j <= nvar ; j++)
2084    {
2085      if (v[j] <> 0)
2086      {
2087        cont1 ++;
2088        marcavar = j;
2089      }
2090    }
2091    // Si cont1=1 hemos encontrado un generador de los que nos
2092    // interesa."variablesin" guarda el indice de las que estan.
2093    if (cont1 == 1)
2094    {
2095      cont2 ++;
2096      variablesin[cont2] = marcavar;
2097    }
2098  }
2099  // Notar que como el sistema de generadores es minimal no se
2100  // va a repetir la potencia de la misma variable. Por tanto basta
2101  // comprobar si cont2 es o no nvar.
2102  if (cont2 == nvar)
2103  {
2104    list output;
2105    output[1] = 1;
2106    return(output);
2107  }
2108  else
2109  {
2110    J = I;
2111    // Buscamos las que no estan
2112    if (cont2 == 0)
2113    {
2114      for (i = 1 ; i <= nvar ; i ++)
2115      {
2116        max = maximoExp(I,i);
2117        cambio[i] = max + 1;
2118        J = J,var(i)^(max + 1);
2119      }
2120    }
2121    else
2122    {
2123      for (i = 1 ; i <= nvar ; i++)
2124      {
2125        for (j = 1 ; j <= cont2 ; j ++)
2126        {
2127          if (i == variablesin[j])
2128          {
2129            cambio[i] = 0;
2130            break;
2131          }
2132        }
2133        if (j == cont2 + 1)
2134        {
2135          max = maximoExp(I,i);
2136          cambio[i] = max + 1;
2137          J = J,var(i)^(max + 1);
2138        }
2139      }
2140    }
2141    list output;
2142    output[1] = 0;
2143    output[2] = J;
2144    output[3] = cambio;
2145    return(output);
2146  }
2147}
2148
2149//////////////////////////////////////////////////////////////////////
2150// En este caso vamos primero a chequear si el ideal es o no        //
2151// generico y en caso de no serlo vamos a devolver  los cambios,    //
2152// pues estos son una aplicacion biyectiva.                         //
2153//////////////////////////////////////////////////////////////////////
2154static proc generic (ideal I)
2155{
2156  // New ring
2157  int nvar = nvars(basering);
2158  // VARIABLES
2159  int i,j,k;
2160  // Cargamos la matriz con los exponentes
2161  int sizI = ncols(I);
2162  intmat EXP[sizI][nvar];
2163  for (i = 1 ; i <= sizI ; i ++)
2164  {
2165    // Ordenamos el vector de exponentes oportuno
2166    EXP[i,1..nvar] = leadexp(I[i]);
2167  }
2168
2169  // Ahora tenemos que ordenarla segun la variable que este en conficto.
2170  intvec vari,change;
2171  intmat NEWEXP = EXP;
2172  list aux;
2173  int count = 0;
2174  for (i = 1 ; i <= nvar ; i ++)
2175  {
2176    // Buscamos conflicto en la variable x(i), para ello tengo que ordenar
2177    // la columna i de EXP
2178    vari = EXP[1..sizI,i];
2179    aux = sort(vari);
2180    vari = aux[1];
2181    change = aux[2];
2182    for (j = 1 ; j <= sizI - 1 ; j ++)
2183    {
2184      if (vari[j] > 0)
2185      {
2186        while (NEWEXP[change[j + count] , i] >= vari[j + 1 + count])
2187        {
2188          NEWEXP[change[j + 1 + count] , i] = NEWEXP[change[j + count] , i] + 1;
2189          count ++;
2190          if (j + 1 + count > sizI)
2191          {
2192            break;
2193          }
2194        }
2195      }
2196      j = j + count;
2197      count = 0;
2198    }
2199  }
2200  // Devolvemos tambien la matriz, pues aqui tengo la biyeccion entre los exponentes
2201  if (EXP == NEWEXP)
2202  {
2203    return (1,I);
2204  }
2205  else
2206  {
2207    // Hallamos el ideal con los nuevos exponentes
2208    intvec expI;
2209    for (i = 1 ; i <= sizI ; i ++)
2210    {
2211      expI = NEWEXP[i,1..nvar];
2212      I[i] = monomial(expI);
2213    }
2214    return(0,I,EXP,NEWEXP);
2215  }
2216}
2217
2218//////////////////////////////////////////////////////////////////////
2219// Esta funci?n obtiene una descomposicion irreducible del ideal    //
2220// monomial a partir de la descomposicion irreducible del idal      //
2221// generico que le asociamos.                                       //
2222//////////////////////////////////////////////////////////////////////
2223static proc nonGeneric (EXP,NEWEXP,Faces,sizI)
2224{
2225  int nvar = nvars(basering);
2226  int sizFaces = size(Faces);
2227  // Variables
2228  int i,j,k;
2229  // Vamos variable a variable
2230  intvec exp, newexp;
2231  list newFaces;
2232  newFaces = Faces;
2233  for (i = 1 ; i <= nvar ; i ++)
2234  {
2235    // comparamos las matrices de exponentes por columnas
2236    exp = EXP[1..sizI,i];
2237    newexp = NEWEXP[1..sizI,i];
2238    if (exp <> newexp)
2239    {
2240      for (j = 1 ; j <= sizI ; j ++)
2241      {
2242        if (exp[j] <> newexp[j])
2243        {
2244          for (k = 1 ; k <= sizFaces ; k ++)
2245          {
2246            if (Faces[k][i] == newexp[j])
2247            {
2248              newFaces[k][i] = exp[j];
2249            }
2250          }
2251        }
2252      }
2253    }
2254  }
2255  return (newFaces);
2256}
2257
2258//////////////////////////////////////////////////////////////////////
2259// Este procedimiento va a dar una faceta inicial para el complejo  //
2260// de Scarf asociado a I, donde I es un ideal monomial artiniano    //
2261// y generico (evidentemente I dado por la bse minimal)             //
2262//////////////////////////////////////////////////////////////////////
2263static proc initialFacet (ideal I)
2264{
2265  // Cambiamos de anillo
2266  // Queremos usar x(1)..x(n) como variables.
2267  int nvar = nvars(basering);
2268  // Declaracion de variables.
2269  int i,sizJ,j,max,aux,sizK,l, elim;
2270  intvec v;
2271  list face;
2272  // Hacemos una copia de I pues ahora modificaremos el sistema
2273  // de generadores.
2274  ideal J = I;
2275  sizJ = ncols(J);
2276  // Para cada variable buscamos el maximo exponente, teniendo en
2277  // cuenta que un mismo generador no puede dar dos exponentes.
2278  // Vamos a guardar los exponentes en "expIni"
2279  intvec expIni;
2280  for (i = 1 ; i <= nvar ; i++)
2281  {
2282    max = 0;
2283    for (j = 1 ; j <= sizJ ; j++)
2284    {
2285      aux = leadexp(J[j])[i];
2286      if (aux > max)
2287      {
2288        max = aux;
2289        elim = j;
2290      }
2291    }
2292    // Guardamos el exponente
2293    expIni[i] = max;
2294    // Ahora tenemos el maximo de la variable x(i), por lo que
2295    // eliminamos el generador en el que la encontramos.
2296    // Si queda un generador no hay nada que hacer
2297    if (sizJ <> 1)
2298    {
2299      if (elim <> 1 & elim <> sizJ)
2300      {
2301        J = J[1..elim-1],J[elim+1..sizJ];
2302      }
2303      else
2304      {
2305        if (elim == 1)
2306        {
2307          J = J[2..sizJ];
2308        }
2309        else
2310        {
2311          J = J[1..sizJ-1];
2312        }
2313      }
2314      sizJ = ncols(J);
2315      // Eliminamos la variable x(i) en todos los generadores.
2316      for (j = 1 ; j <= sizJ ; j++)
2317      {
2318        v = leadexp(J[j]);
2319        if (v [i] <> 0)
2320        {
2321          v[i] = 0;
2322          J[j] = monomial(v);
2323        }
2324      }
2325      // Hallamos el sistema minimal de generadores que
2326      // corresponde al ideal que nos ha quedado.
2327      J = minbase(J);
2328      sizJ = ncols(J);
2329    }
2330  }
2331  // En expIni tenemos los exponentes de los monomios que dan la cara
2332  // inicial, ahora hay que buscar en el ideal original a que
2333  // generador se corresponde (el ideal es generico)
2334  int sizI = ncols(I);
2335  for (i = 1 ; i <= nvar ; i ++)
2336  {
2337    for (j = 1 ; j <= sizI ; j ++)
2338    {
2339      if (expIni[i] == leadexp(I[j])[i])
2340      {
2341        face = insert(face, I[j]);
2342        // Si lo encontramos buscamos el siguiente
2343        break;
2344      }
2345    }
2346  }
2347  return (face);
2348}
2349
2350//////////////////////////////////////////////////////////////////////
2351// La funcion que sigue devuelve las facetas adyacentes a una dada  //
2352// en el complejo de Scarf asociado a I.                            //
2353//////////////////////////////////////////////////////////////////////
2354static proc adyacency (list l1, ideal I)
2355{
2356  // Cambiamos de anillo
2357  // Queremos usar x(1)..x(n) como variables.
2358  int nvar = nvars(basering);
2359  // Declaracion de variables.
2360  int i,j,cambio,sizI,k,min,m,generador,max;
2361  list l2,newl1,w,expI;
2362  poly LCM,newLCM;
2363  intvec v,newv,expgen;
2364  sizI = ncols(I);
2365  // Hallamos el lcm de los elementos, e. d., la faceta del
2366  // complejo para luego comparar con los nuevos
2367  LCM = 1;
2368  for (i = 1 ; i <= nvar ; i++)
2369  {
2370    LCM = lcmMon(LCM,l1[i]);
2371  }
2372  v = leadexp(LCM);
2373  // Calculo los exponentes de los monomios de I
2374  for (i = 1 ; i <= sizI ; i++)
2375  {
2376    expI[i] = leadexp(I[i]);
2377  }
2378  // Hay que quitar cada elemento de la lista y comprobar si hay o no
2379  // cara adyacente al simplice que queda, y en caso de haberla, la
2380  // calculamos.
2381  for (i = 1 ; i <= nvar ; i++)
2382  {
2383    newl1 = delete(l1,i);
2384    // Hallamos el lcm de los elementos que hay en la nueva lista.
2385    newLCM = 1;
2386    for (j = 1 ; j <= nvar - 1 ; j++)
2387    {
2388      newLCM = lcmMon(newLCM,newl1[j]);
2389    }
2390    // Ahora hay que detectar si alguna variable ha desaparecido
2391    // en este LCM.
2392    newv = leadexp(newLCM);
2393    for (j = 1 ; j <= nvar ; j++)
2394    {
2395      if (newv[j] == 0)
2396      {
2397        l2[i] = 0;
2398        break;
2399      }
2400    }
2401    if (j == nvar+1)
2402    {
2403      // Si no ha habido ceros, queremos hallar la cara adyacente,
2404      // es decir, buscar un generador que introducido en l1 de una
2405      // faceta del complejo.
2406      // Comparamos los lcm entre s?, para comprobar en que variable
2407      // contribu?a el monomio que hemos eliminado.
2408      for (j = 1 ; j <= nvar ; j++)
2409      {
2410        if (v[j] <> newv[j])
2411        {
2412          cambio = j;
2413          // Una vez encontrado no hay mas
2414          break;
2415        }
2416      }
2417      // Hallamos los exponentes de los monomios que quedan
2418      // para ver cual da el exponente en "newv"
2419      for (j = 1 ; j <= nvar - 1 ; j++)
2420      {
2421        w[j] = leadexp(newl1[j]);
2422      }
2423      for (j = 1 ; j <= nvar ; j++)
2424      {
2425        for (k = 1 ; k <= nvar - 1 ; k++)
2426        {
2427          if (newv[cambio] == w[k][cambio])
2428          {
2429            cambio = k;
2430            break;
2431          }
2432        }
2433        // Si no termino el for con k es que hemos encontrado ya
2434        // los que son iguales.
2435        if (k <> nvar)
2436        {
2437          break;
2438        }
2439      }
2440
2441      // Donde contribuye antes, e.d., en "v"
2442      for (j = 1 ; j <= nvar ; j++)
2443      {
2444        if (w[cambio][j] == v[j])
2445        {
2446          cambio = j;
2447          break;
2448        }
2449      }
2450      // Ahora ya buscamos entre los generadores el nuevo monomio.
2451      // Ponemos de tope para encontrar el minimo el maximo de
2452      // las variables en el ideal
2453      max = 0;
2454      for (m = 1 ; m <= sizI ; m ++)
2455      {
2456        if (expI[m][cambio] > max)
2457        {
2458          max = expI[m][cambio];
2459        }
2460      }
2461      min = max;
2462      for (j = 1 ; j <= sizI ; j++)
2463      {
2464        for (k = 1 ; k <= nvar ; k ++)
2465        {
2466          if (I[j] == l1[k])
2467          {
2468            break;
2469          }
2470        }
2471        // El generador no esta en la lista, es de los que hay que
2472        // comprobar
2473        if (k == nvar +1)
2474        {
2475          for (m = 1 ; m <= nvar ; m++)
2476          {
2477            if (m <> cambio)
2478            {
2479              if (expI[j][m] > newv[m])
2480              {
2481                break;
2482              }
2483            }
2484            else
2485            {
2486              if (expI[j][m] <= newv[m])
2487              {
2488                break;
2489              }
2490            }
2491          }
2492          // Si termina el bucle cumple las condiciones
2493          // oportunas, solo hay que comparar con el
2494          // otro que tengamos.
2495          if (m == nvar + 1)
2496          {
2497            if (expI[j][cambio] <=  min)
2498            {
2499              min = expI[j][cambio];
2500              generador = j;
2501            }
2502          }
2503        }
2504      }
2505      // En la lista ponemos en el lugar "i" el generador que
2506      // hay que introducir cuando eliminamos el generador
2507      // "i" de la lista de entrada.
2508      l2[i] = I[generador];
2509    }
2510  }
2511  return(l2);
2512}
2513
2514//////////////////////////////////////////////////////////////////////
2515// Metodo que calcula la descomposicion irreducible de un ideal     //
2516// monomial usando el complejo de Scarf (Milowski)                  //
2517//////////////////////////////////////////////////////////////////////
2518static proc ScarfMethod (ideal I)
2519{
2520  // Cambiamos de anillo
2521  // Queremos usar x(1)..x(n) como variables.
2522  int nvar = nvars(basering);
2523  // Sabemos que dp siempre es mejor para trabajar, auqque luego para
2524  // comparar I y genI vamos a cambiarlo al lexicografico.
2525  // Variables
2526  int i,j,k,sizl1,sizl,cont1,cont2;
2527  int sizI;
2528  list auxl,expl1,l1,l,l2,newLCM,expI,expgenI,Faces;
2529  poly LCM,mon;
2530  intvec v,w,betas;
2531  ideal J,genI,artgenI;
2532  // Comprobamos si el ideal es generico y artiniano, y, en caso de
2533  // no serlo, obtenemos una modificacion de este ideal que si
2534  // verifique estas propiedades
2535  list genericlist = generic(I);
2536  if (genericlist[1] == 0)
2537  {
2538    genI = genericlist[2];
2539  }
2540  else
2541  {
2542    genI = I;
2543  }
2544  list artinianization = artinian (genI);
2545  if (artinianization[1] == 0)
2546  {
2547    artgenI = artinianization[2];
2548  }
2549  else
2550  {
2551    artgenI = genI;
2552  }
2553  // Una vez tenemos el ideal artiniano y generico, podemos hallar
2554  // el complejo de Scarf asociado al ideal modificado
2555
2556  // Hay que obtener una cara inicial del ideal.
2557  list initial = initialFacet(artgenI);
2558  // Ahora de cada cara que tengamos en una lista obtenemos sus
2559  // caras adyacentes. Hay que tener en cuenta que si una cara la
2560  // obtengo como adyacente de otra, cuando calculemos sus adyacentes
2561  // sale la anterior, luego hay que evitar repetir.
2562  // Guardamos la primera faceta, su LCM
2563  LCM = 1;
2564  for (i = 1 ; i <= nvar ; i++)
2565  {
2566    mon = initial[i];
2567    LCM = lcmMon(LCM,mon);
2568  }
2569  v = leadexp(LCM);
2570  // Guardamos la primera faceta
2571  Faces[1] = v;
2572  int sizfaces = 1;
2573  // Lista de monomios que dan las facetas para hallar sus caras
2574  // adyacentes
2575  l[1] = initial;
2576  sizl = 1;
2577  // Ahora hayamos las posibles caras maximales adyacentes
2578  while (sizl <> 0)
2579  {
2580    // Hallamos la lista de monomios que hay que introducir
2581    // cuando eliminamos cada monomio.
2582    auxl = adyacency(l[1],artgenI);
2583    cont1 = 1;
2584    cont2 = 0;
2585    l1 = 0;
2586    for (j = 1 ; j <= nvar ; j++)
2587    {
2588      if (auxl[j] <> 0)
2589      {
2590        l2 = delete(l[1],j);
2591        l1[cont1] = insert(l2,auxl[j],cont1 + cont2 - 1);
2592        cont1 ++;
2593      }
2594      else
2595      {
2596        cont2 ++;
2597      }
2598    }
2599    // Hallamos los nuevos LCM
2600    sizl1 = size(l1);
2601    for (i = 1 ; i <= sizl1 ; i++)
2602    {
2603      newLCM[i] = 1;
2604      for (j = 1 ; j <= nvar ; j++)
2605      {
2606        newLCM[i] = lcmMon(newLCM[i],l1[i][j]);
2607      }
2608      expl1[i] = leadexp(newLCM[i]);
2609    }
2610    // Hallamos los LCM de las nuevas caras y eliminamos las que
2611    // ya esten en la lista Faces
2612    cont1 = 0;
2613    cont2 = 0;
2614    for (i = 1 ; i <= sizl1 ; i++)
2615    {
2616      for (j = 1 ; j <= sizfaces ; j++)
2617      {
2618        v = expl1[i];
2619        w = Faces[j];
2620        if (v == w)
2621        {
2622          // Si ya esta el LCM en la lista, no queremos
2623          // seguir buscando
2624          break;
2625        }
2626      }
2627      // Si no ha salido del bucle en "j" es que este LCM
2628      // no esta en la lista de las caras, la introducimos
2629      if (j == sizfaces + 1)
2630      {
2631        Faces = insert(Faces,expl1[i],sizfaces + cont1);
2632        l = insert(l,l1[i]);
2633        cont1 ++;
2634      }
2635    }
2636    l = delete(l,cont1 + 1);
2637    sizl = size(l);
2638    sizfaces = size(Faces);
2639  }
2640  // En "Faces" ya tengo los exponentes que luego seran los exponentes
2641  // de los ideales que forman la descomposicion.
2642  // Deshacemos la artinianizacion
2643  intvec elimin = artinianization[3];
2644  if (artinianization[1] == 0)
2645  {
2646    // En elimina tenemos las variables que hemos introducido
2647    // y cual es la potencia
2648    // Solo miro las que tengan cambio
2649    for (i = 1 ; i <= nvar ; i ++)
2650    {
2651      if (elimin[i] <> 0)
2652      {
2653        for (j = 1 ; j <= sizfaces ; j ++)
2654        {
2655          if (Faces[j][i] == elimin[i])
2656          {
2657            Faces[j][i] = 0;
2658          }
2659        }
2660      }
2661    }
2662  }
2663  // Generico
2664  sizI = ncols(I);
2665  if (genericlist[1] == 0)
2666  {
2667    Faces = nonGeneric(genericlist[3],genericlist[4],Faces,sizI);
2668  }
2669  // Ya tenemos en Faces los exponentes de las componentes
2670  // ahora solo hay que obtener los ideales.
2671  for (i = 1 ; i <= sizfaces ; i ++)
2672  {
2673    J = 0;
2674    for (j = 1 ; j <= nvar ; j ++)
2675    {
2676      if (Faces[i][j] <> 0)
2677      {
2678        J = J,var(j)^(Faces[i][j]);
2679      }
2680    }
2681    J = simplify(J,2);
2682    Faces[i] = J;
2683  }
2684  // Esta es la parte LENTA computacionalmente si el ideal de partida
2685  // no es generico
2686  if (genericlist[1] == 0)
2687  {
2688    Faces = irredundant(Faces);
2689  }
2690  return(Faces);
2691}
2692
2693//////////////////////////////////////////////////////////////////////
2694// Devuelve una descomposicion primaria minimal de un ideal         //
2695// monomial via el complejo de Scarf.                               //
2696//////////////////////////////////////////////////////////////////////
2697static proc scarfMethodPrim (ideal I)
2698{
2699 // VARIABLES
2700  list l1,l2;
2701  // Hallamos la despomposicion irreducible del ideal dado usando
2702  // el complejo de Scarf
2703  l1 = ScarfMethod (I);
2704// ----- DESCOMPOSICION PRIMARIA
2705  l2 = irredPrimary (l1);
2706  return (l2);
2707}
2708
2709//////////////////////////////////////////////////////////////////////
2710// METODO 7: algoritmo de etiquetas (Roune)
2711//
2712//////////////////////////////////////////////////////////////////////
2713// Las siguientes funciones calculan la descomposicion en           //
2714// irreducibles de un ideal monomial. En este caso utilizamos el    //
2715// algoritmo de etiquetas de B. Roune.                              //
2716//////////////////////////////////////////////////////////////////////
2717static proc phi (list F)
2718{
2719  // Cambiamos de anillo
2720  int nvar = nvars(basering);
2721  // Variables
2722  int sizF,i,j;
2723  poly f;
2724  list listphi;
2725  intvec exp,newexp;
2726  // F es una lista de pares, que indica una x(i) etiqueta de una
2727  // cara del ideal. Suponemos que F tiene ordenados sus elementos
2728  // segun las x(i)
2729  sizF = size(F);
2730  for (i = 1 ; i <= sizF ; i ++)
2731  {
2732    f = F[i];
2733    exp = leadexp(f);
2734    for (j = 1 ; j <= nvar ; j ++)
2735    {
2736      if (j <> i)
2737      {
2738        exp[j] = exp[j] + 1;
2739      }
2740    }
2741    listphi[i] = monomial(exp);
2742  }
2743  // Ya tenemos la lista de los monomios a los que
2744  // luego haremos el "lcm"
2745  return (listphi);
2746}
2747
2748/////////////////////////////////////////////////////////////////////////////
2749static proc pi(poly f)
2750{
2751 // Cambiamos de anillo
2752  int nvar = nvars(basering);
2753  int i,sizI;
2754  intvec exp;
2755  exp = leadexp(f);
2756  for (i = nvar ; i > 0  ; i --)
2757  {
2758    if (exp[i] <> 0)
2759    {
2760      exp[i] = exp[i] - 1;
2761    }
2762  }
2763  f = monomial(exp);
2764  return (f);
2765}
2766
2767/////////////////////////////////////////////////////////////////////////////
2768static proc conditionComplex (intvec posActual,ideal I,ideal S)
2769{
2770  int nvar = nvars(basering);
2771  // VARIABLES
2772  int i,nuevo;
2773  list F;
2774  // Vemos cual ha sido la ultima incorporacion al ideal, que es el
2775  // ultimo dentro de posActual que es distinto de 0.
2776  for (i = 1 ; i <= nvar ; i ++)
2777  {
2778    if (posActual[i] == 0)
2779    {
2780      break;
2781    }
2782  }
2783  nuevo = i - 1;
2784  // No se pueden repetir generadores, se mira que el ultimo que se ha
2785  // ha introducido no sea de los que ya tenemos
2786  for (i = 1 ; i <= nuevo - 1 ; i ++)
2787  {
2788    if (posActual[i] == posActual[nuevo])
2789    {
2790      return (0);
2791    }
2792  }
2793  // Vemos si la variable oportuna divide al generador
2794  if (leadexp(I[i]) == 0)
2795  {
2796    return (0);
2797  }
2798  // Caso de que el LCM sea multiplo de los que ya tenemos
2799  poly LCM = 1;
2800  for (i = 1 ; i <= nuevo ; i ++)
2801  {
2802    F = insert (F,I[posActual[i]],size(F));
2803  }
2804  list phiF = phi(F);
2805  for (i = 1 ; i <= nuevo ; i ++)
2806  {
2807    LCM = lcmMon(phiF[i],LCM);
2808  }
2809  // Comprobamos si ya tenemos algun divisor del actual
2810  if (membershipMon(LCM,S) == 1)
2811  {
2812    return (0);
2813  }
2814  // Ahora vemos si la lista esta en el complejo simplicial
2815  if (membershipMon(LCM,I) == 1)
2816  {
2817    if (membershipMon(pi(LCM),I) == 0)
2818    {
2819      return (1,LCM);
2820    }
2821  }
2822  return (0);
2823}
2824
2825/////////////////////////////////////////////////////////////////////////////
2826static proc findFaces (ideal I)
2827{
2828  int nvar = nvars(basering);
2829  // Variables
2830  int i;
2831  ideal S;
2832  list condiciones;
2833  // Inicializamos valores
2834  list F;
2835  intvec posActual;
2836  posActual[nvar] = 0;
2837
2838  int variable = 1;
2839  int sizI = ncols(I);
2840  while (1)
2841  {
2842    while (posActual[variable] == sizI)
2843    {
2844      posActual[variable] = 0;
2845      variable --;
2846      if (variable == 0)
2847      {
2848        break;
2849      }
2850    }
2851    // Comprobamos si hemos recorrido todas las posibilidades. Si
2852    // es as?, terminamos el while
2853    if (variable == 0)
2854    {
2855      break;
2856    }
2857    posActual[variable] = posActual[variable] + 1;
2858    // Comprobamos las condiciones para saber si los generadores que
2859    // tenemos est?n o no en el complejo.
2860    condiciones = conditionComplex (posActual,I,S);
2861
2862    if (condiciones[1] == 1 )
2863    {
2864      if (posActual[nvar] <> 0)
2865      {
2866        S = S,condiciones[2];
2867        F = insert (F,condiciones[2]);
2868      }
2869      if (variable < nvar)
2870      {
2871        variable ++;
2872      }
2873    }
2874  }
2875  return (F);
2876}
2877
2878//////////////////////////////////////////////////////////////////////
2879// La siguiente funcion calcula la descomposicion en irreducibles de//
2880// un ideal monomial artininano usando el algoritmo de etiquetas del//
2881// metodo de Bjarke Roune.                                          //
2882//////////////////////////////////////////////////////////////////////
2883static proc labelAlgorithm(ideal I)
2884{
2885  int nvar = nvars(basering);
2886
2887  // Variables
2888  int i,j,sizComponents;
2889  list components;
2890  // El ideal tiene que ser artininano, si no lo es hacemos el cambio
2891  // oportuno para que lo sea (luego se deshace).
2892  ideal artI;
2893  list artiniano = artinian (I);
2894  if (artiniano[1] == 0)
2895  {
2896    artI = artiniano[2];
2897    intvec elimina = artiniano[3];
2898  }
2899  else
2900  {
2901    artI = I;
2902  }
2903  // Llamamos a findFaces para que encuentre las caras maximales del
2904  // complejo asociado al ideal
2905  components = findFaces(artI);
2906  sizComponents = size(components);
2907  list expComponents;
2908  poly f;
2909  for (i = 1 ; i <= sizComponents ; i ++)
2910  {
2911    f = components[i];
2912    expComponents[i] = leadexp(f);
2913  }
2914  // Deshacemos la artinianizacion
2915  if (artiniano[1] == 0)
2916  {
2917    // En elimina tenemos las variables que hemos introducido
2918    // y cual es la potencia
2919    // Solo miro las que tengan cambio
2920    for (i = 1 ; i <= nvar ; i ++)
2921    {
2922      if (elimina[i] <> 0)
2923      {
2924        for (j = 1 ; j <= sizComponents ; j ++)
2925        {
2926          if (expComponents[j][i] == elimina[i])
2927          {
2928            expComponents[j][i] = 0;
2929          }
2930        }
2931      }
2932    }
2933  }
2934  // En exp(i) tengo los exponentes de cada variable de las que aparecen
2935  // en cada ideal.
2936  ideal J;
2937  list facets;
2938  for (i = 1 ; i <= sizComponents ; i ++)
2939  {
2940    J = 0;
2941    for (j = 1 ; j <= nvar ; j ++)
2942    {
2943      if (expComponents[i][j] <> 0)
2944      {
2945        J = J,var(j)^expComponents[i][j];
2946      }
2947    }
2948    J = simplify(J,2);
2949    facets[i] = J;
2950  }
2951  return (facets);
2952}
2953
2954//////////////////////////////////////////////////////////////////////
2955// Devuelve una descomposicion primaria minimal de un ideal monomial//
2956// dado.                                                            //
2957//////////////////////////////////////////////////////////////////////
2958static proc labelAlgPrim (ideal I)
2959{
2960  // VARIABLES
2961  list l1,l2;
2962  // Hallamos la despomposicion irreducible del ideal dado usando
2963  // el complejo de Scarf
2964  l1 = labelAlgorithm (I);
2965// ----- DESCOMPOSICION PRIMARIA
2966  l2 = irredPrimary (l1);
2967  return (l2);
2968}
2969
2970//////////////////////////////////////////////////////////////////////
2971// METODO 8: Gao-Zhu
2972//
2973//////////////////////////////////////////////////////////////////////
2974static proc divide (intvec v, intvec w, int k)
2975{
2976  int nvar = nvars(basering);
2977  // Variables
2978  int i;
2979  for (i = nvar ; i > 0 ; i --)
2980  {
2981    if (i == k)
2982    {
2983      if (v[i] <> w[i])
2984      {
2985        return (0);
2986      }
2987    }
2988    else
2989    {
2990      if (v[i] >= w[i])
2991      {
2992        return (0);
2993      }
2994    }
2995  }
2996  return (1);
2997}
2998
2999/////////////////////////////////////////////////////////////////////////////
3000static proc incrementalAlg (ideal I)
3001{
3002  int nvar = nvars(basering);
3003  // COMPROBACIONES
3004  // Variables
3005  int i,sop,j,k,l,m,cont,cont2;
3006  intvec beta,dbeta,betaaux,elimina;
3007  // El ideal tiene que ser artininano, si no lo es hacemos el cambio
3008  // oportuno para que lo sea (luego se deshace).
3009  list artiniano = artinian (I);
3010  ideal artI;
3011  if (artiniano[1] == 0)
3012  {
3013    artI = artiniano[2];
3014    elimina = artiniano[3];
3015  }
3016  else
3017  {
3018    artI = I;
3019    elimina[nvar] = 0;
3020  }
3021  // Buscamos la primera componente irreducible o, lo que es lo
3022  // mismo, aquellos generadores que son potencia de una variable.
3023  // Si el tama?o de elimina es nvar es que hemos a?adido todos los
3024  // generadores que son potencia luego estar?n todos al final del
3025  // ideal.
3026  list MinI,componentes;
3027  int sizartI = ncols(artI);
3028  int sizelimina = size(elimina);
3029  for (i = 1 ; i <= nvar ; i ++)
3030  {
3031    if (elimina[i] == 0)
3032    {
3033      // Buscamos en el ideal los generadores que nos interesan
3034      for (j = 1 ; j <= sizartI ; j ++)
3035      {
3036        sop = soporte(artI[j]);
3037        if (sop <> 0)
3038        {
3039          beta[sop] = leadexp(artI[j])[sop];
3040          MinI = insert(MinI,leadexp(artI[j]));
3041          if (j <> 1 and j <> sizartI)
3042          {
3043            artI = artI[1..j - 1],artI[j + 1..sizartI];
3044          }
3045          else
3046          {
3047            if (j == 1)
3048            {
3049              artI = artI[2..sizartI];
3050            }
3051            else
3052            {
3053              artI = artI[1..sizartI - 1];
3054            }
3055          }
3056          sizartI = ncols(artI);
3057          break;
3058        }
3059      }
3060    }
3061    else
3062    {
3063      // Buscamos la que esta al final
3064      sop = soporte(artI[sizartI]);
3065      beta[sop] = leadexp(artI[sizartI])[sop];
3066      MinI = insert(MinI,leadexp(artI[sizartI]));
3067      if (sizartI <> 1)
3068      {
3069        artI = artI[1..sizartI - 1];
3070      }
3071      else
3072      {
3073        artI = artI[1];
3074      }
3075      sizartI = ncols(artI);
3076    }
3077  }
3078  // En beta tenemos la primera componente
3079  componentes = insert(componentes,beta);
3080  int sizcomponents = size(componentes);
3081  int sizMin = size(MinI);
3082  // Es mas facil trabajar con los exponentes para nuestro objetivo
3083  // Se elige un nuevo generador, que en nuestro caso es un nuevo
3084  // exponente.
3085  int min,max;
3086  intvec expartI;
3087  for(i = 1 ; i <= sizartI ; i ++)
3088  {
3089    expartI = leadexp(artI[1]);
3090    if (ncols(artI) <> 1)
3091    {
3092      artI = artI[2..ncols(artI)];
3093    }
3094    // Hay que distinguir T_1 y T_2. Para ello se comparar vectores
3095    // de la lista actual de generadores con el que se acaba de
3096    // introducir.
3097    cont2 = 0;
3098    for (j = 1 ; j <= sizcomponents ; j ++)
3099    {
3100      beta = componentes[1 + cont2];
3101      // Si el nuevo generador divide a la componente beta, hay
3102      // que buscar las nuevas componentes
3103      for (k = 1 ; k <= nvar ; k ++)
3104      {
3105        if (expartI[k] >= beta[k])
3106        {
3107          break;
3108        }
3109      }
3110      // Si el bucle anterior termino, divide y hay que hacer
3111      // los cambios.
3112      if (k == nvar + 1)
3113      {
3114        componentes = delete (componentes,1 + cont2);
3115        // Buscamos las nuevas componentes calculando las
3116        // distancias. Para cada variable busco d(beta,k,l)
3117        for (k = 1 ; k <= nvar ; k ++)
3118        {
3119          betaaux = beta;
3120          max = -1;
3121          cont = 0;
3122          dbeta = 0;
3123          for (l = 1 ; l <= nvar ; l ++)
3124          {
3125            if (l <> k)
3126            {
3127              min = 32767;
3128              cont ++;
3129              for (m = 1 ; m <= sizMin ; m ++)
3130              {
3131                // Estos son de los buenos
3132                if (divide(MinI[m],beta,l) == 1)
3133                {
3134                  if (MinI[m][k] < min)
3135                  {
3136                    min = MinI[m][k];
3137                  }
3138                }
3139              }
3140              dbeta[cont] = min;
3141            }
3142          }
3143          // Aqui ya tenemos d(beta,k,l) para cada k
3144          // Hallamos el maximo cuando terminemos
3145          for (l = 1 ; l <= cont ; l ++)
3146          {
3147            if (dbeta[l] > max)
3148            {
3149              max = dbeta[l];
3150            }
3151          }
3152          // Condicion para introducir nueva componente
3153          if (max < expartI[k])
3154          {
3155            betaaux[k] = expartI[k];
3156            componentes = insert(componentes,betaaux,size(componentes));
3157          }
3158        }
3159      }
3160      else
3161      {
3162        cont2 ++;
3163      }
3164    }
3165    MinI = insert(MinI,expartI);
3166    sizMin = size(MinI);
3167    sizcomponents = size(componentes);
3168  }
3169  // Deahacer los cambios de artiniano si se han hecho
3170  if (artiniano[1] == 0)
3171  {
3172    // En elimina tenemos las variables que hemos introducido
3173    // y cual es la potencia
3174    // Solo miro las que tengan cambio
3175    for (i = 1 ; i <= nvar ; i ++)
3176    {
3177      if (elimina[i] <> 0)
3178      {
3179        for (j = 1 ; j <= sizcomponents ; j ++)
3180        {
3181          if (componentes[j][i] == elimina[i])
3182          {
3183            componentes[j][i] = 0;
3184          }
3185        }
3186      }
3187    }
3188  }
3189  // En exp(i) tengo los exponentes de cada variable de las que aparecen
3190  // en cada ideal.
3191  ideal J;
3192  list facets;
3193  for (i = 1 ; i <= sizcomponents ; i ++)
3194  {
3195    J = 0;
3196    for (j = 1 ; j <= nvar ; j ++)
3197    {
3198      if (componentes[i][j] <> 0)
3199      {
3200        J = J,var(j)^componentes[i][j];
3201      }
3202    }
3203    J = simplify(J,2);
3204    facets[i] = J;
3205  }
3206  return (facets);
3207}
3208
3209/////////////////////////////////////////////////////////////////////////////
3210static proc  incrementalAlgPrim (ideal I)
3211{
3212  // VARIABLES
3213  list l1,l2;
3214  // Hallamos la despomposicion irreducible del ideal dado usando
3215  // el algoritmo de Gao-Zhu
3216  l1 = incrementalAlg (I);
3217// ----- DESCOMPOSICION PRIMARIA
3218  l2 = irredPrimary (l1);
3219  return (l2);
3220}
3221
3222//////////////////////////////////////////////////////////////////////
3223// METODO 9: slice algorithm (Roune)
3224//
3225//////////////////////////////////////////////////////////////////////
3226// SLICE ALGORITHM (B.Roune)                                        //
3227//////////////////////////////////////////////////////////////////////
3228static proc divideMon (poly f , poly g)
3229{
3230  return (lead(g)/lead(f)!=0);
3231  //int nvar = nvars(basering);
3232  //intvec expf = leadexp(f);
3233  //intvec expg = leadexp(g);
3234  //for (int i = 1 ; i <= nvar ; i ++)
3235  //{
3236  //  if (expf[i] > expg[i])
3237  //  {
3238  //    return (0);
3239  //  }
3240  //}
3241  //return (1);
3242}
3243
3244/////////////////////////////////////////////////////////////////////////////
3245static proc pivot (ideal I , poly lcmMin, ideal S)
3246{
3247  // I is monomial ideal
3248  int sizI = ncols(I);
3249  int nvar = nvars(basering);
3250  intvec explcmMin = leadexp(lcmMin);
3251  // Variables
3252  int i,j;
3253  // The median estrategy
3254  poly p;
3255  int cont, exp, median, sizxi, max;
3256  intvec xiexp;
3257  for (i = 1 ; i <= nvar ; i ++)
3258  {
3259    if (explcmMin[i] >= 2 )
3260    {
3261      // Median exponent of x(i) from intersection(minI,x(i))
3262      cont = 0;
3263      for (j = 1 ; j <= sizI ; j ++)
3264      {
3265        exp = leadexp(I[j])[i];
3266        if (exp > 0)
3267        {
3268          cont ++;
3269          xiexp[cont] = exp;
3270        }
3271      }
3272      xiexp = sort(xiexp)[1];
3273      sizxi = size(xiexp);
3274      if (size(xiexp) == 1)
3275      {
3276        median = xiexp[1] - 1;
3277      }
3278      else
3279      {
3280        if (size(xiexp) == 2)
3281        {
3282          median = xiexp[2] - 1;
3283        }
3284        else
3285        {
3286          median = xiexp[(size(xiexp) + 1) / 2];
3287        }
3288      }
3289      p = var(i)^median;
3290      // valid pivot??
3291      if ( membershipMon(p,S) == 0)
3292      {
3293        return(p);
3294      }
3295      else
3296      {
3297        max = maximoExp(S,i);
3298        if ( xiexp[sizxi] == max )
3299        {
3300          return(var(i)^(max-1));
3301        }
3302      }
3303      xiexp = 0;
3304    }
3305  }
3306}
3307
3308/////////////////////////////////////////////////////////////////////////////
3309static proc simplification (I)
3310{
3311  // VARIABLES
3312  int i, j, k, cont, numdeleted;
3313  intvec isMaximal;
3314  int sizI = ncols(I);
3315  int nvar = nvars(basering);
3316  poly lcmMinI = 1;
3317  for (i = 1 ; i <= sizI ; i ++)
3318  {
3319    lcmMinI = lcmMon(I[i],lcmMinI);
3320  }
3321  intvec explcmMinI = leadexp(lcmMinI);
3322  // Buscamos los elementos que son x(i) maximales. En caso de que
3323  // un generador del ideal sea maximal para 2 variables distintas,
3324  // ese generador se elimina.
3325  isMaximal[sizI] = 0;
3326  intvec genexp;
3327  for (i = 1 ; i <= sizI ; i ++)
3328  {
3329    genexp = leadexp(I[i]);
3330    cont = 0;
3331    for ( j = 1 ; j <= nvar ; j ++)
3332    {
3333      if (genexp[j] <> 0 && genexp[j] == explcmMinI[j])
3334      {
3335        if (cont == 0)
3336        {
3337          cont ++;
3338          isMaximal[i] = j;
3339        }
3340        else
3341        {
3342          // Porque cuando encontramos que era maximal para
3343          // la primera variable, lo guardamos
3344          isMaximal[i] = 0;
3345          // Eliminamos del ideal
3346          if (i <> 1 && i <> sizI)
3347          {
3348            I = I[1..i - 1],I[i + 1..sizI];
3349          }
3350          else
3351          {
3352            if (i == 1)
3353            {
3354              I = I[2..sizI];
3355            }
3356            else
3357            {
3358              I = I[1..sizI - 1];
3359            }
3360          }
3361          i --;
3362          sizI = ncols(I);
3363          // Generador i eliminado, miramos el siguiente
3364          break;
3365        }
3366      }
3367    }
3368  }
3369   // En isMaximal[i] tenemos 0 si I[i] no es maximal,
3370   // y j si I[i] es maximal en x(j).
3371  // Matriz de exponentes de los generadores del ideal
3372  intmat expI[sizI][nvar];
3373  for (i = 1 ; i <= sizI ; i++)
3374  {
3375    expI[i,1..nvar] = leadexp(I[i]);
3376  }
3377  // Buscamos ahora cota inferior
3378  poly lcmMi = 1;
3379  poly l,gcdMi;
3380  intvec Mi, mincol,expgcd;
3381  for (i = 1 ; i <= nvar ; i ++)
3382  {
3383    Mi = 0;
3384    cont = 0;
3385    for (j = 1 ; j <= sizI ; j ++)
3386    {
3387      // De isMaximal solo se usan las entradas que se corresponden con elementos del ideal
3388      if (expI[j,i] <> 0)
3389      {
3390        if (isMaximal[j] == 0 or isMaximal[j] == i)
3391        {
3392          // Elementos del sistema minimal que estan
3393          // en Mi
3394          cont ++;
3395          Mi[cont] = j;
3396        }
3397      }
3398    }
3399    // Si solo hay un elemento en Mi, no hay nada que hacer
3400    if (cont > 1)
3401    {
3402      gcdMi = I[Mi[1]];
3403      // Tenemos los generadores a los que hay que hallar el gcd
3404      for (j = 2; j <= cont ; j ++)
3405      {
3406        gcdMi = gcd(gcdMi,I[Mi[j]]);
3407      }
3408    }
3409    else
3410    {
3411      if (Mi <> 0)
3412      {
3413        gcdMi = I[Mi[1]];
3414      }
3415      else
3416      {
3417        // Falta alguna variable
3418        return (0,I);
3419      }
3420    }
3421    l = gcdMi/var(i);
3422    lcmMi = lcmMon(lcmMi,l);
3423  }
3424  // Ahora devolvemos la cota inferior, que luego hay que multiplicar
3425  // por el monomio que define el corte.
3426  // Devolvemos tambien el ideal (por si se ha modificado).
3427  return (lcmMi,I);
3428}
3429
3430/////////////////////////////////////////////////////////////////////////////
3431static proc con (ideal I , ideal S , poly q)
3432{
3433  int nvar = nvars(basering);
3434  // Variables
3435  int i;
3436  poly piI;
3437  int sizI = ncols(I);
3438  // Simplification process
3439  poly p;
3440  list sol;
3441  while (1)
3442  {
3443    // (I,S,q) normal slice?
3444    // Como cada vez que introducimos una cota inferior sabemos
3445    // que la slice actual es la inner slice (la otra es vacio),
3446    // hay que volver a verificar si es normal
3447    if ( S <> 0 )
3448    {
3449      // m/rad(m) esta en S, para m generador minimal de I??
3450      for (i = 1 ; i <= sizI ; i ++)
3451      {
3452        piI = pi(I[i]);
3453        if (membershipMon(piI,S) == 1)
3454        {
3455          if (i == 1)
3456          {
3457            I = I[2..sizI];
3458          }
3459          else
3460          {
3461            if (i == sizI)
3462            {
3463              I = I[1..sizI - 1];
3464            }
3465            else
3466            {
3467              I = I[1..i - 1],I[i + 1..sizI];
3468            }
3469          }
3470          sizI = ncols(I);
3471          i --;
3472        }
3473      }
3474    }
3475    // Buscamos cota inferior, y si es distinta de 1, simplificamos
3476    sol = simplification(I);
3477    p = sol[1];
3478    if (p == 1)
3479    {
3480      break;
3481    }
3482    else
3483    {
3484      if (p == 0)
3485      {
3486        break;
3487      }
3488      else
3489      {
3490        if (membershipMon(p,I) == 1 )
3491        {
3492          break;
3493        }
3494      }
3495    }
3496    // Changing slice by simplification
3497    I = sol[2];
3498    I = minbase(quotient(I,p));
3499    q = p*q;
3500    S = minbase(quotient(S,p));
3501    sizI = ncols(I);
3502  }
3503  sizI = ncols(I);
3504  // (I,S,q) base case?
3505  poly lcmMinI;
3506  lcmMinI = 1;
3507  for (i = 1 ; i <= sizI ; i ++)
3508  {
3509    lcmMinI = lcmMon(lcmMinI,I[i]);
3510  }
3511  // a:b generates an intvec of length b with constant entries a
3512  intvec one = 1:nvar;
3513  if (divideMon(monomial(one),lcmMinI) == 0)
3514  {
3515    return (0);
3516  }
3517  if (equal(radicalMon(I),I) == 1)
3518  {
3519    if (equal(I, maxideal(1)) == 0)
3520    {
3521      return (0);
3522    }
3523    else
3524    {
3525      for (i = 1 ; i <= nvar ; i ++)
3526      {
3527        q = q * var(i);
3528      }
3529      return (q);
3530    }
3531  }
3532  // Selecting pivot
3533  p = pivot(I,lcmMinI,S);
3534  // New slices
3535  ideal S1 = minbase(quotient(S,p));
3536  ideal I1 = minbase(quotient(I,p));
3537  ideal S2 = S,p;
3538  S2 = minbase(S2);
3539  return (con(I1,S1,p*q),con(I,S2,q));
3540}
3541
3542/////////////////////////////////////////////////////////////////////////////
3543static proc irredDecMonSlice (ideal I)
3544{
3545  int nvar = nvars(basering);
3546  int sizI = ncols(I);
3547  int i,j;
3548  // Artinian ideal
3549  ideal artI;
3550  list artinianization = artinian(I);
3551  if (artinianization[1] == 0)
3552  {
3553    artI = artinianization[2];
3554  }
3555  else
3556  {
3557    artI = I;
3558  }
3559  // Easy case: 2 variables
3560  if (nvar == 2)
3561  {
3562    artI = sort(artI)[1];
3563    int sizartI = ncols(artI);
3564    for (i = 1 ; i <= sizartI - 1 ; i ++)
3565    {
3566      components[i] = var(1)^(leadexp[artI[i]][1])*var(2)^(leadexp[artI[i + 1]][2]);
3567    }
3568    return (components);
3569  }
3570  ideal irredDec = con (artI,0,1);
3571  // Delelting zeros
3572  irredDec = simplify(irredDec,2);
3573  // Delting, in case, generators
3574  intvec elimina;
3575  if (artinianization[1] == 0)
3576  {
3577    elimina = artinianization[3];
3578  }
3579  else
3580  {
3581    elimina = 0;
3582  }
3583 // Each generator (monomial) corresponds to an ideal
3584  list components;
3585  poly comp;
3586  intvec exp;
3587  int sizIrred = ncols(irredDec);
3588  ideal auxIdeal;
3589  for (i = 1 ; i <= sizIrred ; i ++)
3590  {
3591    comp = irredDec[i];
3592    exp = leadexp(comp);
3593    for (j = 1 ; j <= nvar ; j ++)
3594    {
3595      if (exp[j] <> 0)
3596      {
3597        if (elimina <> 0)
3598        {
3599          if (exp[j] == elimina[j])
3600          {
3601            auxIdeal[j] = 0;
3602          }
3603          else
3604          {
3605            auxIdeal[j] = var(j)^exp[j];
3606          }
3607        }
3608        else
3609        {
3610          auxIdeal[j] = var(j)^exp[j];
3611        }
3612      }
3613    }
3614    components[i] = simplify(auxIdeal,2);
3615    auxIdeal = 0;
3616  }
3617  return (components);
3618}
3619
3620/////////////////////////////////////////////////////////////////////////////
3621static proc primDecMonSlice (ideal I)
3622{
3623 // VARIABLES
3624  list l1,l2;
3625  // ---- Irreducible decomposition
3626  // Slice Method
3627  l1 = irredDecMonSlice (I);
3628// ----- Primary decomposition
3629  l2 = irredPrimary (l1);
3630  return (l2);
3631}
3632
3633//////////////////////////////////////////////////////////////////////
3634//                                                                  //
3635//                       DECOMPOSITIONS                             //
3636//                                                                  //
3637//////////////////////////////////////////////////////////////////////
3638//////////////////////////////////////////////////////////////////////
3639
3640/////////////////////////////////////////////////////////////////////////////
3641proc irreddecMon
3642"USAGE:   irreddecMon (I[,alg]); I ideal, alg string.
3643RETURN:   list, the irreducible components of the monomial ideal I.
3644          (returns -1 if I is not a monomial ideal).
3645ASSUME:   I is a monomial ideal of the basering k[x(1)..x(n)].
3646NOTE:     This procedure returns the irreducible decomposition of I,
3647          i.e., the unique irredundant decomposition of I into irreducible
3648          monomial ideals.
3649          One may call the procedure with different algorithms using
3650          the optional argument 'alg':
3651          - the direct method following Vasconcelos' book (alg=vas)
3652          - via the Alexander dual and using doble dual (alg=add),
3653          - via the Alexander dual and quotients following E. Miller
3654            (alg=ad),
3655          - the formula of irreducible components (alg=for),
3656          - via the Scarf complex following Milowski (alg=mil),
3657          - using the label algorihtm of Roune (alg=lr),
3658          - using the algorithm of Gao-Zhu (alg=gz).
3659          - using the slice algorithm of Roune (alg=sr).
3660EXAMPLE:  example irreddecMon; shows some examples.
3661"
3662{
3663  // COMPROBACIONES
3664  ideal I = #[1];
3665  int control = checkIdeal(I);
3666  // Si el sistema de generadores no esta formado por monomios, hay
3667  // que comprobar si el ideal es monomial.
3668  if (control == 0)
3669  {
3670    list isMon = isMonomialGB (I);
3671    if (isMon[1] == 0)
3672    {
3673      ERROR ("the ideal is not monomial.");
3674    }
3675    else
3676    {
3677      I = isMon[2];
3678      // Ya lo tenemos con los generadores minimales
3679    }
3680  }
3681  else
3682  {
3683    // Generadores monomiales, hallamos sistema minimal
3684    I = minbase(I);
3685  }
3686  // Si el ideal es irreducible, devolvemos el mismo
3687  if (isirreducibleMon(I) == 1)
3688  {
3689    return (I);
3690  }
3691  // Si no me han dado opcion, elijo una yo.
3692  if (size(#) == 1)
3693  {
3694    return (irredDec3(I));
3695  }
3696  // Leo la opcion y llamo al procedimiento oportuno
3697  else
3698  {
3699    if (#[2] == "vas")
3700    {
3701      return (irredDec1(I));
3702    }
3703    if (#[2] == "add")
3704    {
3705      return (irredDec3(I));
3706    }
3707    if (#[2] == "ad")
3708    {
3709      return (irredDec4(I));
3710    }
3711    if (#[2] == "for")
3712    {
3713      return (irredDec5(I));
3714    }
3715    if (#[2] == "mil")
3716    {
3717      return (ScarfMethod(I));
3718    }
3719    if (#[2] == "lr")
3720    {
3721      return (labelAlgorithm(I));
3722    }
3723    if (#[2] == "gz")
3724    {
3725      return (incrementalAlg(I));
3726    }
3727    if (#[2] == "sr")
3728    {
3729      return (irredDecMonSlice(I));
3730    }
3731  }
3732}
3733example
3734{"EXAMPLE:"; echo = 2;
3735 ring R = 0,(w,x,y,z),Dp;
3736ideal I = w^3*x*y,w*x*y*z,x^2*y^2*z^2,x^2*z^4,y^3*z;
3737// Vasconcelos
3738 irreddecMon (I,"vas");
3739// Alexander Dual
3740 irreddecMon (I,"ad");
3741 // Scarf Complex
3742 irreddecMon (I,"mil");
3743 // slice algorithm
3744 irreddecMon(I,"sr");
3745}
3746
3747/////////////////////////////////////////////////////////////////////////////
3748proc primdecMon
3749"USAGE:   primdecMon (I[,alg]); I ideal, alg string
3750RETURN:   list, the components in a minimal primary decomposition of I.
3751          (returns -1 if I is not a monomial ideal).
3752ASSUME:   I is a monomial ideal of the basering k[x(1)..x(n)].
3753NOTE:     This procedure returns a minimal primary decomposition of I.
3754          One may call the procedure with different algorithms using
3755          the optional argument 'alg':
3756          - the direct method for a primary decomposition following
3757            Vasconcelos' book (alg=vp),
3758          - from the irreducible decomposition obtained via the direct
3759            method following Vasconcelos' book (alg=vi),
3760          - from the irreducible decomposition obtained via the
3761            Alexander dual and using doble dual (alg=add),
3762          - from the irreducible decomposition obtained via the
3763            Alexander dual and quotients following E. Miller (alg=ad),
3764          - from the irreducible decomposition obtained
3765            via ........ (alg=for),
3766          - from the irreducible decomposition obtained via the Scarf
3767            complex following Milowski (alg=mil),
3768          - from the irreducible decomposition obtained using the label
3769            algorihtm of Roune (alg=lr),
3770          - from the irreducible decomposition obtained using the
3771            algorithm of Gao-Zhu (alg=gz),
3772          - from the irreducible decomposition obtained using the slice
3773            algorithm of Roune (alg=sr).
3774EXAMPLE:  example primdecMon; shows some examples.
3775"
3776{
3777  // COMPROBACIONES
3778  ideal I = #[1];
3779  int control = checkIdeal(I);
3780  // Si el sistema de generadores no esta formado por monomios, hay
3781  // que comprobar si el ideal es monomial.
3782  if (control == 0)
3783  {
3784    list isMon = isMonomialGB (I);
3785    if (isMon[1] == 0)
3786    {
3787      ERROR ("the ideal is not monomial.");
3788    }
3789    else
3790    {
3791      I = isMon[2];
3792      // Ya lo tenemos con los generadores minimales
3793    }
3794  }
3795  else
3796  {
3797    // Generadores monomiales, hallamos sistema minimal
3798    I = minbase(I);
3799  }
3800  // Estudiamos si el ideal es o no primario
3801  if (isprimaryMon(I) == 1)
3802  {
3803    return (I);
3804  }
3805  // Si no me han dado opcion, elijo una yo.
3806  if (size(#) == 1)
3807  {
3808    return(primDec3(I));
3809  }
3810  // Leo la opcion y llamo al procedimiento oportuno
3811  else
3812  {
3813    if (#[2] == "vi")
3814    {
3815      return (primDec1(I));
3816    }
3817    if (#[2] == "vp")
3818    {
3819      return (primDec2(I));
3820    }
3821    if (#[2] == "add")
3822    {
3823      return (primDec3(I));
3824    }
3825    if (#[2] == "ad")
3826    {
3827      return (primDec4(I));
3828    }
3829    if (#[2] == "for")
3830    {
3831      return (primDec5(I));
3832    }
3833    if (#[2] == "mil")
3834    {
3835      return (scarfMethodPrim(I));
3836    }
3837    if (#[2] == "lr")
3838    {
3839      return (labelAlgPrim(I));
3840    }
3841    if (#[2] == "gz")
3842    {
3843      return (incrementalAlgPrim(I));
3844    }
3845    if (#[2] == "sr")
3846    {
3847      return (primDecMonSlice(I));
3848    }
3849  }
3850}
3851example
3852{"EXAMPLE:"; echo = 2;
3853 ring R = 0,(w,x,y,z),Dp;
3854ideal I = w^3*x*y,w*x*y*z,x^2*y^2*z^2,x^2*z^4,y^3*z;
3855// Vasconcelos para primaria
3856 primdecMon(I,"vp");
3857// Alexander dual
3858 primdecMon(I,"add");
3859 // label algorithm
3860 primdecMon(I,"lr");
3861 //slice algorithm
3862 primdecMon(I,"sr");
3863}
Note: See TracBrowser for help on using the repository browser.