source: git/Singular/LIB/monomial.lib @ a0b5e2

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