source: git/Singular/LIB/multigrading.lib @ 1f9a84

spielwiese
Last change on this file since 1f9a84 was 1f9a84, checked in by Hans Schoenemann <hannes@…>, 13 years ago
more int division from the manual git-svn-id: file:///usr/local/Singular/svn/trunk@14203 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 109.7 KB
Line 
1// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
3///////////////////////////////////////////////////////////////////
4version="$Id$";
5category="Combinatorial Commutative Algebra";
6info="
7LIBRARY:  multigrading.lib          Multigraded Rings
8
9AUTHORS:  Benjamin Bechtold, benjamin.bechtold@googlemail.com
10@*        Rene Birkner, rbirkner@math.fu-berlin.de
11@*        Lars Kastner, lkastner@math.fu-berlin.de
12@*        Simon Keicher, keicher@mail.mathematik.uni-tuebingen.de
13@*        Oleksandr Motsak, U@D, where U={motsak}, D={mathematik.uni-kl.de}
14@*        Anna-Lena Winz, anna-lena.winz@math.fu-berlin.de
15
16OVERVIEW: This library allows one to virtually add multigradings to Singular:
17grade multivariate polynomial rings with arbitrary (fin. gen. Abelian) groups.
18For more see http://code.google.com/p/convex-singular/wiki/Multigrading
19For theoretical references see:
20@* E. Miller, B. Sturmfels: 'Combinatorial Commutative Algebra'
21and
22@* M. Kreuzer, L. Robbiano: 'Computational Commutative Algebra'.
23
24NOTE: 'multiDegBasis' relies on 4ti2 for computing Hilbert Bases.
25All groups are finitely generated Abelian
26
27PROCEDURES:
28setBaseMultigrading(M,L); attach multiweights/grading group matrices to the basering
29getVariableWeights([R]);  get matrix of multidegrees of vars attached to a ring
30
31getGradingGroup([R]);     get grading group attached to a ring
32getLattice([R[,choice]]); get grading group' lattice attached to a ring (or its NF)
33
34createGroup(S,L);          create a group generated by S, with relations L
35createQuotientGroup(L);    create a group generated by the unit matrix whith relations L
36createTorsionFreeGroup(S); create a group generated by S which is torsionfree
37printGroup(G);             print a group
38
39isGroup(G);                   test whether G is a valid group
40isGroupHomomorphism(L1,L2,A); test wheter A defines a group homomrphism from L1 to L2
41
42isGradedRingHomomorphism(R,f,A);  test graded ring homomorph
43createGradedRingHomomorphism(R,f,A);  create a graded ring homomorph
44
45setModuleGrading(M,v);    attach multiweights of units to a module and return it
46getModuleGrading(M);      get multiweights of module units (attached to M)
47
48isSublattice(A,B);        test whether A is a sublattice of B
49imageLattice(P,L);        computes an integral basis for P(L)
50intRank(A);               computes the rank of the intmat A
51kernelLattice(P);         computes an integral basis for the kernel of the linear map P.
52latticeBasis(B);          computes an integral basis of the lattice B
53preimageLattice(P,L);     computes an integral basis for the preimage of the lattice L under the linear map P.
54projectLattice(B);        computes a linear map of lattices having the primitive span of B as its kernel.
55intersectLattices(A,B);   computes an integral basis for the intersection of the lattices A and B.
56isIntegralSurjective(P);  test whether the map P of lattices is surjective.
57isPrimitiveSublattice(A); test whether A generates a primitive sublattice.
58intInverse(A);            computes the integral inverse matrix of the intmat A
59integralSection(P);       for a given linear surjective map P of lattices this procedure returns an integral section of P.
60primitiveSpan(A);         computes a basis for the minimal primitive sublattice that contains the given vectors (by A).
61
62factorgroup(G,H);         create the group G mod H
63productgroup(G,H);        create the group G x H
64
65multiDeg(A);                  compute the multidegree of A
66multiDegBasis(d);             compute all monomials of multidegree d
67multiDegPartition(p);         compute the multigraded-homogeneous components of p
68
69isTorsionFree();          test whether the current multigrading is  free
70isPositive();             test whether the current multigrading is positive
71isZeroElement(p);         test whether p has zero multidegree
72areZeroElements(M);       test whether an integer matrix M considered as a collection of columns has zero multidegree
73isHomogeneous(a);         test whether 'a' is multigraded-homogeneous
74
75equalMultiDeg(e1,e2[,V]);     test whether e1==e2 in the current multigrading
76
77multiDegGroebner(M);          compute the multigraded GB/SB of M
78multiDegSyzygy(M);            compute the multigraded syzygies of M
79multiDegModulo(I,J);          compute the multigraded 'modulo' module of I and J
80multiDegResolution(M,l[,m]);  compute the multigraded resolution of M
81multiDegTensor(m,n);          compute the tensor product of multigraded modules m,n
82multiDegTor(i,m,n);           compute the Tor_i(m,n) for multigraded modules m,n
83
84defineHomogeneous(p);     get a grading group wrt which p becomes homogeneous
85pushForward(f);           find the finest grading on the image ring, homogenizing f
86gradiator(h);             coarsens grading of the ring until h becomes homogeneous
87
88hermiteNormalForm(A);     compute the Hermite Normal Form of a matrix
89smithNormalForm(A,#);     compute matrices D,P,Q with D=P*A*Q and D is the smith normal form of A
90
91hilbertSeries(M);         compute the multigraded Hilbert Series of M
92
93lll(A);                   applies LLL(.) of lll.lib which only works for lists on a matrix A
94
95           (parameters in square brackets [] are optional)
96
97KEYWORDS:  multigrading, multidegree, multiweights, multigraded-homogeneous, integral linear algebra
98";
99
100/// evalHilbertSeries(h,v);   evaluate hilberts series h by substituting v[i] for t_(i) (too experimentall)
101
102// finestMDeg(def r)
103// newMap(map F, intmat Q, list #)
104
105LIB "standard.lib"; // for groebner
106// LIB "lll.lib"; // for lll_matrix // no need now, right?
107LIB "matrix.lib"; // for multiDegTor
108
109/******************************************************/
110
111static proc concatintmat(intmat A, intmat B)
112{
113
114 if ( nrows(A) != nrows(B) )
115   {
116     ERROR("matrices A and B have different number of rows.");
117   }
118
119 intmat At = transpose(A);
120 intmat Bt = transpose(B);
121
122 intmat Ct[nrows(At) + nrows(Bt)][ncols(At)] = At, Bt;
123
124 return(transpose(Ct));
125}
126
127
128/******************************************************/
129proc createGradedRingHomomorphism(def src, ideal Im, def A)
130"USAGE: createGradedRingHomomorphism(R, f, A); ring R, ideal f, group homomorphism A
131PURPOSE: create a multigraded group ring homomorphism defined by
132a ring map from R to the current ring, given by generators images f
133and a group homomorphism A between grading groups
134RETURN: graded ring homorphism
135EXAMPLE: example createGradedRingHomomorphism; shows an example
136"
137{
138  string isGRH = "isGRH";
139
140  if( !isGradedRingHomomorphism(src, Im, A) )
141  {
142    ERROR("Input data is wrong");
143  }
144
145  list h;
146  h[3] = A;
147
148//  map f = src, Im;
149  h[2] = Im; // f?
150  h[1] = src;
151
152  attrib(h, isGRH, (1==1)); // mark it "a graded ring homomorphism"
153
154  return(h);
155}
156example
157{
158  "EXAMPLE:"; echo=2;
159
160  ring r = 0, (x, y, z), dp;
161  intmat S1[3][3] =
162                   1, 0, 0,
163                   0, 1, 0,
164                   0, 0, 1;
165  intmat L1[3][1] =
166                   0,
167                   0,
168                   0;
169
170  def G1 = createGroup(S1, L1); // (S1 + L1)/L1
171  printGroup(G1);
172
173  setBaseMultigrading(S1, L1); // to change...
174
175  ring R = 0, (a, b, c), dp;
176  intmat S2[2][3] =
177                   1, 0,
178                   0, 1;
179  intmat L2[2][1] =
180                   0,
181                   2;
182
183  def G2 = createGroup(S2, L2);
184  printGroup(G2);
185
186  setBaseMultigrading(S2, L2); // to change...
187
188
189  map F = r, a, b, c;
190  intmat A[nrows(L2)][nrows(L1)] =
191                                  1, 0, 0,
192                                  3, 2, -6;
193
194  // graded ring homomorphism is given by (compatible):
195  print(F);
196  print(A);
197
198  isGradedRingHomomorphism(r, ideal(F), A);
199  def h = createGradedRingHomomorphism(r, ideal(F), A);
200
201  print(h);
202}
203
204
205/******************************************************/
206proc isGradedRingHomomorphism(def src, ideal Im, def A)
207"USAGE: isGradedRingHomomorphism(R, f, A); ring R, ideal f, group homomorphism A
208PURPOSE: test a multigraded group ring homomorphism defined by
209a ring map from R to the current ring, given by generators images f
210and a group homomorphism A between grading groups
211RETURN: int, 1 for TRUE, 0 otherwise
212EXAMPLE: example isGradedRingHomomorphism; shows an example
213"
214{
215  def dst = basering;
216
217  intmat result_degs = multiDeg(Im);
218//  print(result_degs);
219
220  setring src;
221
222  intmat input_degs = multiDeg(maxideal(1));
223//  print(input_degs);
224
225  def image_degs = A * input_degs;
226//  print( image_degs );
227
228  def df = image_degs - result_degs;
229//  print(df);
230
231  setring dst;
232
233  return (areZeroElements( df ));
234}
235example
236{
237  "EXAMPLE:"; echo=2;
238
239  ring r = 0, (x, y, z), dp;
240  intmat S1[3][3] =
241    1, 0, 0,
242    0, 1, 0,
243    0, 0, 1;
244  intmat L1[3][1] =
245    0,
246    0,
247    0;
248
249  def G1 = createGroup(S1, L1); // (S1 + L1)/L1
250  printGroup(G1);
251
252  setBaseMultigrading(S1, L1); // to change...
253
254  ring R = 0, (a, b, c), dp;
255  intmat S2[2][3] =
256    1, 0,
257    0, 1;
258  intmat L2[2][1] =
259    0,
260    2;
261
262  def G2 = createGroup(S2, L2);
263  printGroup(G2);
264
265  setBaseMultigrading(S2, L2); // to change...
266
267
268  map F = r, a, b, c;
269  intmat A[nrows(L2)][nrows(L1)] =
270      1, 0, 0,
271      3, 2, -6;
272
273  // graded ring homomorphism is given by (compatible):
274  print(F);
275  print(A);
276
277  isGradedRingHomomorphism(r, ideal(F), A);
278  def h = createGradedRingHomomorphism(r, ideal(F), A);
279
280  print(h);
281
282  // not a homo..
283  intmat B[nrows(L2)][nrows(L1)] =
284     1, 1, 1,
285     0, 0, 0;
286  print(B);
287
288  isGradedRingHomomorphism(r, ideal(F), B); // FALSE: there is no such homomorphism!
289  // Therefore: the following command should return an error
290  // createGradedRingHomomorphism(r, ideal(F), B);
291
292}
293
294
295proc createQuotientGroup(intmat L)
296"USAGE: createGroup(L); L is an integer matrix
297PURPOSE: create the group of the form (I+L)/L,
298where I is the square identity matrix of size nrows(L) x nrows(L)
299NOTE: L specifies relations between free generators of Z^nrows(L)
300RETURN: group
301EXAMPLE: example createQuotientGroup; shows an example
302"
303{
304  int r = nrows(L); int i;
305  intmat S[r][r]; // SQUARE!!!
306  for(i = r; i > 0; i--){ S[i, i] = 1; }
307  return (createGroup(S,L));
308}
309example
310{
311  "EXAMPLE:"; echo=2;
312
313  intmat I[3][3] =
314                  1, 0, 0,
315                  0, 1, 0,
316                  0, 0, 1;
317
318  intmat L[3][2] =
319                  1, 1,
320                  1, 3,
321                  1, 5;
322
323
324  // The group Z^3 / L can be constructed as follows:
325
326  // shortcut:
327  def G = createQuotientGroup(L);
328  printGroup(G);
329
330  // the general way:
331  def GG = createGroup(I, L); // (I+L)/L
332  printGroup(GG);
333}
334
335proc createTorsionFreeGroup(intmat S)
336"USAGE: createTorsionFreeGroup(S); S is an integer matrix
337PURPOSE: create the free subgroup generated by S within the
338free Abelian group of rank nrows(S)
339RETURN: group
340EXAMPLE: example createTorsionFreeGroup; shows an example
341"
342{
343  int r = nrows(S); int i;
344  intmat L[r][1] = 0;
345  return (createGroup(S,L));
346}
347example
348{
349  "EXAMPLE:"; echo=2;
350
351  // ----------- extreme case ------------ //
352  intmat S[1][3] =
353                  1,  -1, 10;
354
355  // Torsion:
356  intmat L[1][1] =
357                  0;
358
359
360  // The free subgroup generated by elements of S within Z^1
361  // can be constructed as follows:
362
363  // shortcut:
364  def G = createTorsionFreeGroup(S);
365  printGroup(G);
366
367  // the general way:
368  def GG = createGroup(S, L); // (S+L)/L
369  printGroup(GG);
370}
371
372
373/******************************************************/
374proc createGroup(intmat S, intmat L)
375"USAGE: createGroup(S, L); S, L are integer matrices
376PURPOSE: create the group of the form (S+L)/L, i.e.
377S specifies generators, L specifies relations.
378RETURN: group
379EXAMPLE: example createGroup; shows an example
380"
381{
382  string isGroup = "isGroup";
383  string attrGroupHNF = "hermite";
384  string attrGroupSNF = "smith";
385
386
387/*
388  if( size(#) > 0 )
389  {
390    if( typeof(#[1]) == "intmat" )
391    {
392      intmat S = #[1];
393    } else { ERROR("Wrong optional argument: 1"); }
394
395    if( size(#) > 1 )
396    {
397      if( typeof(#[2]) == "intmat" )
398      {
399        intmat L = #[2];
400      } else { ERROR("Wrong optional argument: 2"); }
401    }
402  }
403*/
404
405  if( nrows(L) != nrows(S) )
406  {
407    ERROR("Incompatible matrices!");
408  }
409
410  def H = attrib(L, attrGroupHNF);
411  if( typeof(H) != "intmat")
412  {
413    attrib(L, attrGroupHNF, hermiteNormalForm(L));
414  } else { kill H; }
415
416  def HH = attrib(L, attrGroupSNF);
417  if( typeof(HH) != "intmat")
418  {
419    attrib(L, attrGroupSNF, smithNormalForm(L));
420  } else { kill HH; }
421
422  list G; // Please, note the order: Generators + Relations:
423  G[1] = S;
424  G[2] = L;
425  // And now a quick-and-dirty fix of Singular inability to handle attribs of attribs:
426  // For the use of a group as an attribute for multigraded rings
427  G[3] = attrib(L, attrGroupHNF);
428  G[4] = attrib(L, attrGroupSNF);
429
430
431  attrib(G, isGroup, (1==1)); // mark it "a group"
432
433  return (G);
434}
435example
436{
437  "EXAMPLE:"; echo=2;
438
439  intmat S[3][3] =
440    1, 0, 0,
441    0, 1, 0,
442    0, 0, 1;
443
444  intmat L[3][2] =
445    1, 1,
446    1, 3,
447    1, 5;
448
449  def G = createGroup(S, L); // (S+L)/L
450
451  printGroup(G);
452
453  kill S, L, G;
454
455  /////////////////////////////////////////////////
456  intmat S[2][3] =
457    1, -2, 1,
458    1,  1, 0;
459
460  intmat L[2][1] =
461    0,
462    2;
463
464  def G = createGroup(S, L); // (S+L)/L
465
466  printGroup(G);
467
468  kill S, L, G;
469
470  // ----------- extreme case ------------ //
471  intmat S[1][3] =
472    1,  -1, 10;
473
474  // Torsion:
475  intmat L[1][1] =
476    0;
477
478  def G = createGroup(S, L); // (S+L)/L
479
480  printGroup(G);
481}
482
483
484/******************************************************/
485proc printGroup(def G)
486"USAGE: printGroup(G); G is a group
487PURPOSE: prints the group G
488RETURN: nothing
489EXAMPLE: example printGroup; shows an example
490"
491{
492  "Generators: ";
493  print(G[1]);
494
495  "Relations: ";
496  print(G[2]);
497
498//  attrib(G[2]);
499}
500example
501{
502  "EXAMPLE:"; echo=2;
503
504  intmat S[3][3] =
505                  1, 0, 0,
506                  0, 1, 0,
507                  0, 0, 1;
508
509  intmat L[3][2] =
510                  1, 1,
511                  1, 3,
512                  1, 5;
513
514  def G = createGroup(S, L); // (S+L)/L
515  printGroup(G);
516
517}
518
519/******************************************************/
520static proc areIsomorphicGroups(def G, def H)
521"USAGE: areIsomorphicGroups(G, H); G and H are groups
522PURPOSE: Check whether G and H define isomorphic groups.
523RETURN: int, 1 for TRUE, 0 otherwise
524EXAMPLE: example areIsomorphicGroups; shows an example
525"
526{
527  ERROR("areIsomorphicGroups: Not yet implemented!");
528  return (1); // TRUE
529}
530example
531{
532  "EXAMPLE:"; echo=2;
533
534  // TODO!
535
536}
537
538/******************************************************/
539proc isGroup(def G)
540"USAGE: isGroup(G); G a list
541PURPOSE: checks whether G is a valid group
542NOTE: G should be created by createGroup
543(or createQuotientGroup, createTorsionFreeGroup)
544RETURN: int, 1 if G is a valid group and 0 otherwise
545EXAMPLE: example isGroup; shows an example
546"
547{
548  string isGroup = "isGroup";
549
550  // valid?
551  if( typeof(G) != "list" ){ return(0); }
552
553  def a = attrib(G, isGroup);
554
555///// TODO for Hans: fix attr^2 bug in Singular!
556
557//  if( !defined(a) ) { return(0); }
558//  if( typeof(a) != "int" ) { return(0); }
559  if( defined(a) ){ if(typeof(a) == "int") { return(a); } }
560
561
562  if( (size(G) != 2) && (size(G) != 4) ){ return(0); }
563  if( typeof(G[1]) != "intmat" ){ return(0); }
564  if( typeof(G[2]) != "intmat" ){ return(0); }
565  if( nrows(G[1]) != nrows(G[2]) ){ return(0); }
566
567  return(1);
568}
569example
570{
571  "EXAMPLE:"; echo=2;
572
573  intmat S[3][3] =
574                  1, 0, 0,
575                  0, 1, 0,
576                  0, 0, 1;
577
578  intmat L[3][2] =
579                  1, 1,
580                  1, 3,
581                  1, 5;
582
583  def G = createGroup(S, L); // (S+L)/L
584
585  isGroup(G);
586
587  printGroup(G);
588
589}
590
591
592
593/******************************************************/
594proc setBaseMultigrading(intmat M, list #)
595"USAGE: setBaseMultigrading(M[, G]); M is an integer matrix, G is a group (or lattice)
596PURPOSE: attaches weights of variables and grading group to the basering.
597NOTE: M encodes the weights of variables column-wise.
598RETURN: nothing
599EXAMPLE: example setBaseMultigrading; shows an example
600"
601{
602  string attrMgrad   = "mgrad";
603  string attrGradingGroup = "gradingGroup";
604
605  int i = 1;
606  if( size(#) >= i )
607  {
608    def a = #[i];
609    if( typeof(a) == "intmat" )
610    {
611      def L = createGroup(M, a);
612      i++;
613    }
614
615    if( isGroup(a) )
616    {
617      def L = a;
618
619      if( !isSublattice(M, L[1]) )
620      {
621        ERROR("Multigrading is not contained in the grading group!");
622      }
623      i++;
624    }
625    if( i == 1 ){ ERROR("Wrong arguments: no group given?"); }
626    kill a;
627  }
628  else
629  {
630    def L = createTorsionFreeGroup(M);
631  }
632
633
634  attrib(basering, attrMgrad, M);
635  attrib(basering, attrGradingGroup, L);
636
637  ideal Q = ideal(basering); // quotient ideal is assumed to be a GB!
638  if( !isHomogeneous(Q, "checkGens") ) // easy now, but would be hard before setting ring attributes!
639  {
640    "Warning: your quotient ideal is not homogenous (multigrading was set anyway)!";
641  }
642
643}
644example
645{
646  "EXAMPLE:"; echo=2;
647
648  ring R = 0, (x, y, z), dp;
649
650  // Weights of variables
651  intmat M[3][3] =
652    1, 0, 0,
653    0, 1, 0,
654    0, 0, 1;
655
656  // GradingGroup:
657  intmat L[3][2] =
658    1, 1,
659    1, 3,
660    1, 5;
661
662  // attaches M & L to R (==basering):
663  setBaseMultigrading(M, L); // Grading: Z^3/L
664
665  // Weights are accessible via "getVariableWeights()":
666  getVariableWeights();
667
668  // Test all possible usages:
669  (getVariableWeights() == M) && (getVariableWeights(R) == M) && (getVariableWeights(basering) == M);
670
671  // Grading group is accessible via "getLattice()":
672  getLattice();
673
674  // Test all possible usages:
675  (getLattice() == L) && (getLattice(R) == L) && (getLattice(basering) == L);
676
677  // And its hermite NF via getLattice("hermite"):
678  getLattice("hermite");
679
680  // Test all possible usages:
681  intmat H = hermiteNormalForm(L);
682  (getLattice("hermite") == H) && (getLattice(R, "hermite") == H) && (getLattice(basering, "hermite") == H);
683
684  kill L, M;
685
686  // ----------- isomorphic multigrading -------- //
687
688  // Weights of variables
689  intmat M[2][3] =
690    1, -2, 1,
691    1,  1, 0;
692
693  // Torsion:
694  intmat L[2][1] =
695    0,
696    2;
697
698  // attaches M & L to R (==basering):
699  setBaseMultigrading(M, L); // Grading: Z + (Z/2Z)
700
701  // Weights are accessible via "getVariableWeights()":
702  getVariableWeights() == M;
703
704  // Torsion is accessible via "getLattice()":
705  getLattice() == L;
706
707  kill L, M;
708  // ----------- extreme case ------------ //
709
710  // Weights of variables
711  intmat M[1][3] =
712    1,  -1, 10;
713
714  // Torsion:
715  intmat L[1][1] =
716    0;
717
718  // attaches M & L to R (==basering):
719  setBaseMultigrading(M); // Grading: Z^3
720
721  // Weights are accessible via "getVariableWeights()":
722  getVariableWeights() == M;
723
724  // Torsion is accessible via "getLattice()":
725  getLattice() == L;
726}
727
728
729/******************************************************/
730proc getVariableWeights(list #)
731"USAGE: getVariableWeights([R])
732PURPOSE: get associated multigrading matrix for the basering [or R]
733RETURN:  intmat, matrix of multidegrees of variables
734EXAMPLE: example getVariableWeights; shows an example
735"
736{
737  string attrMgrad = "mgrad";
738
739
740  if( size(#) > 0 )
741  {
742    if(( typeof(#[1]) == "ring" ) || ( typeof(#[1]) == "qring" ))
743    {
744      def R = #[1];
745    }
746    else
747    {
748      ERROR("Optional argument must be a ring!");
749    }
750  }
751  else
752  {
753    def R = basering;
754  }
755
756  def M = attrib(R, attrMgrad);
757  if( typeof(M) == "intmat"){ return (M); }
758  ERROR( "Sorry no multigrading matrix!" );
759}
760example
761{
762  "EXAMPLE:"; echo=2;
763
764  ring R = 0, (x, y, z), dp;
765
766  // Weights of variables
767  intmat M[3][3] =
768    1, 0, 0,
769    0, 1, 0,
770    0, 0, 1;
771
772  // Grading group:
773  intmat L[3][2] =
774    1, 1,
775    1, 3,
776    1, 5;
777
778  // attaches M & L to R (==basering):
779  setBaseMultigrading(M, L); // Grading: Z^3/L
780
781  // Weights are accessible via "getVariableWeights()":
782  getVariableWeights() == M;
783
784  kill L, M;
785
786  // ----------- isomorphic multigrading -------- //
787
788  // Weights of variables
789  intmat M[2][3] =
790    1, -2, 1,
791    1,  1, 0;
792
793  // Grading group:
794  intmat L[2][1] =
795    0,
796    2;
797
798  // attaches M & L to R (==basering):
799  setBaseMultigrading(M, L); // Grading: Z + (Z/2Z)
800
801  // Weights are accessible via "getVariableWeights()":
802  getVariableWeights() == M;
803
804  kill L, M;
805
806  // ----------- extreme case ------------ //
807
808  // Weights of variables
809  intmat M[1][3] =
810    1,  -1, 10;
811
812  // Grading group:
813  intmat L[1][1] =
814    0;
815
816  // attaches M & L to R (==basering):
817  setBaseMultigrading(M); // Grading: Z^3
818
819  // Weights are accessible via "getVariableWeights()":
820  getVariableWeights() == M;
821}
822
823
824proc getGradingGroup(list #)
825"USAGE: getGradingGroup([R])
826PURPOSE: get associated grading group
827RETURN: group, the grading group
828EXAMPLE: example getGradingGroup; shows an example
829"
830{
831  string attrGradingGroup    = "gradingGroup";
832
833  int i = 1;
834
835  if( size(#) >= i )
836  {
837    if( ( typeof(#[i]) == "ring" ) or ( typeof(#[i]) == "qring" ) )
838    {
839      def R = #[i];
840      i++;
841    }
842  }
843
844  if( i == 1 )
845  {
846    def R = basering;
847  }
848
849  def G = attrib(R, attrGradingGroup);
850
851  if( !isGroup(G) )
852  {
853    ERROR("Sorry no grading group!");
854  }
855
856  return(G);
857}
858example
859{
860  "EXAMPLE:"; echo=2;
861
862  ring R = 0, (x, y, z), dp;
863
864  // Weights of variables
865  intmat M[3][3] =
866    1, 0, 0,
867    0, 1, 0,
868    0, 0, 1;
869
870  // Torsion:
871  intmat L[3][2] =
872    1, 1,
873    1, 3,
874    1, 5;
875
876  // attaches M & L to R (==basering):
877  setBaseMultigrading(M, L); // Grading: Z^3/L
878
879  def G = getGradingGroup();
880
881  printGroup( G );
882
883  G[1] == M; G[2] == L;
884
885  kill L, M, G;
886
887  // ----------- isomorphic multigrading -------- //
888
889  // Weights of variables
890  intmat M[2][3] =
891    1, -2, 1,
892    1,  1, 0;
893
894  // Torsion:
895  intmat L[2][1] =
896    0,
897    2;
898
899  // attaches M & L to R (==basering):
900  setBaseMultigrading(M, L); // Grading: Z + (Z/2Z)
901
902  def G = getGradingGroup();
903
904  printGroup( G );
905
906  G[1] == M; G[2] == L;
907
908  kill L, M, G;
909  // ----------- extreme case ------------ //
910
911  // Weights of variables
912  intmat M[1][3] =
913    1,  -1, 10;
914
915  // Torsion:
916  intmat L[1][1] =
917    0;
918
919  // attaches M & L to R (==basering):
920  setBaseMultigrading(M); // Grading: Z^3
921
922  def G = getGradingGroup();
923
924  printGroup( G );
925
926  G[1] == M; G[2] == L;
927
928  kill L, M, G;
929}
930
931
932/******************************************************/
933proc getLattice(list #)
934"USAGE: getLattice([R[,opt]])
935PURPOSE: get associated grading group matrix, i.e. generators (cols) of the grading group
936RETURN: intmat, the grading group matrix, or
937its hermite normal form if an optional argument (\"hermiteNormalForm\") is given or
938smith normal form if an optional argument (\"smith\") is given
939EXAMPLE: example getLattice; shows an example
940"
941{
942  int i = 1;
943  if( size(#) >= i )
944  {
945    def a = #[i];
946    if( ( typeof(a) == "ring" ) or ( typeof(a) == "qring" ) )
947    {
948      i++;
949    }
950    kill a;
951  }
952
953  string attrGradingGroupHNF = "hermite";
954  string attrGradingGroupSNF = "smith";
955
956  def G = getGradingGroup(#);
957
958//  printGroup(G);
959
960
961
962  def T = G[2];
963
964  if( size(#) >= i )
965  {
966    def a = #[i];
967
968    if( typeof(a) != "string" )
969    {
970      ERROR("Sorry wrong arguments!");
971    }
972
973    if( a == "hermite" )
974    {
975      def M = attrib(T, attrGradingGroupHNF);
976      if( typeof(M) != "intmat" )
977      {
978        if( size(G) > 2 )
979        {
980          M = G[3];
981        } else
982        {
983          M = hermiteNormalForm(T);
984        }
985      }
986      return (M);
987    }
988
989    if( a == "smith" )
990    {
991      def M = attrib(T, attrGradingGroupSNF);
992      if( typeof(M) != "intmat" )
993      {
994        if( size(G) > 2 )
995        {
996          M = G[4];
997        } else
998        {
999          M = smithNormalForm(T);
1000        }
1001      }
1002      return (M);
1003    }
1004  }
1005
1006  return(T);
1007}
1008example
1009{
1010  "EXAMPLE:"; echo=2;
1011
1012  ring R = 0, (x, y, z), dp;
1013
1014  // Weights of variables
1015  intmat M[3][3] =
1016    1, 0, 0,
1017    0, 1, 0,
1018    0, 0, 1;
1019
1020  // Torsion:
1021  intmat L[3][2] =
1022    1, 1,
1023    1, 3,
1024    1, 5;
1025
1026  // attaches M & L to R (==basering):
1027  setBaseMultigrading(M, L); // Grading: Z^3/L
1028
1029  // Torsion is accessible via "getLattice()":
1030  getLattice() == L;
1031
1032  // its hermite NF:
1033  print(getLattice("hermite"));
1034
1035  kill L, M;
1036
1037  // ----------- isomorphic multigrading -------- //
1038
1039  // Weights of variables
1040  intmat M[2][3] =
1041    1, -2, 1,
1042    1,  1, 0;
1043
1044  // Torsion:
1045  intmat L[2][1] =
1046    0,
1047    2;
1048
1049  // attaches M & L to R (==basering):
1050  setBaseMultigrading(M, L); // Grading: Z + (Z/2Z)
1051
1052  // Torsion is accessible via "getLattice()":
1053  getLattice() == L;
1054
1055  // its hermite NF:
1056  print(getLattice("hermite"));
1057
1058  kill L, M;
1059
1060  // ----------- extreme case ------------ //
1061
1062  // Weights of variables
1063  intmat M[1][3] =
1064    1,  -1, 10;
1065
1066  // Torsion:
1067  intmat L[1][1] =
1068    0;
1069
1070  // attaches M & L to R (==basering):
1071  setBaseMultigrading(M); // Grading: Z^3
1072
1073  // Torsion is accessible via "getLattice()":
1074  getLattice() == L;
1075
1076  // its hermite NF:
1077  print(getLattice("hermite"));
1078}
1079
1080proc getGradedGenerator(def m, int i)
1081"USAGE: getGradedGenerator(M, i), 'M' module/ideal, 'i' int
1082RETURN: returns the i-th generator of M, endowed with the module grading from M
1083EXAMPLE: example getGradedGenerator; shows an example
1084"
1085{
1086  if( typeof(m) == "ideal" )
1087  {
1088    return (m[i]);
1089  }
1090
1091  if( typeof(m) == "module" )
1092  {
1093    def v = getModuleGrading(m);
1094
1095    return ( setModuleGrading(m[i],v) );
1096  }
1097
1098  ERROR("m is expected to be an ideal or a module");
1099}
1100example
1101{
1102  "EXAMPLE:"; echo=2;
1103
1104  ring r = 0,(x,y,z,w),dp;
1105  intmat MM[2][4]=
1106                  1,1,1,1,
1107                  0,1,3,4;
1108  setBaseMultigrading(MM);
1109
1110  module M = ideal(  xw-yz, x2z-y3, xz2-y2w, yw2-z3);
1111
1112
1113  intmat v[2][nrows(M)]=
1114                        1,
1115                        0;
1116
1117  M = setModuleGrading(M, v);
1118
1119  isHomogeneous(M);
1120  "Multidegrees: "; print(multiDeg(M));
1121
1122  // Let's compute syzygies!
1123  def S = multiDegSyzygy(M); S;
1124  "Module Units Multigrading: "; print( getModuleGrading(S) );
1125  "Multidegrees: "; print(multiDeg(S));
1126
1127  isHomogeneous(S);
1128
1129  // same as S[1] together with the induced module weighting
1130  def v = getGradedGenerator(S, 1);
1131  print(v);
1132  print(setModuleGrading(v));
1133
1134  isHomogeneous(v);
1135
1136  isHomogeneous(S[1]);
1137}
1138
1139/******************************************************/
1140proc getModuleGrading(def m)
1141"USAGE: getModuleGrading(m), 'm' module/vector
1142RETURN: integer matrix of the multiweights of free module generators attached to 'm'
1143EXAMPLE: example getModuleGrading; shows an example
1144"
1145{
1146  string attrModuleGrading = "genWeights";
1147
1148  //  print(m);  typeof(m);  attrib(m);
1149
1150  def V = attrib(m, attrModuleGrading);
1151
1152  if( typeof(V) != "intmat" )
1153  {
1154    if( (typeof(m) == "ideal") or (typeof(m) == "poly") )
1155    {
1156      intmat M = getVariableWeights();
1157      intmat VV[nrows(M)][1];
1158      return (VV);
1159    }
1160
1161    ERROR("Sorry: vector or module need module-grading-matrix! See 'getModuleGrading'.");
1162  }
1163
1164  if( nrows(V) != nrows(getVariableWeights()) )
1165  {
1166    ERROR("Sorry wrong height of V: " + string(nrows(V)));
1167  }
1168
1169  if( ncols(V) < nrows(m) )
1170  {
1171    ERROR("Sorry wrong width of V: " + string(ncols(V)));
1172  }
1173
1174  return (V);
1175}
1176example
1177{
1178  "EXAMPLE:"; echo=2;
1179
1180   ring R = 0, (x,y), dp;
1181   intmat M[2][2]=
1182     1, 1,
1183     0, 2;
1184   intmat T[2][5]=
1185     1,  2,  3,  4, 0,
1186     0, 10, 20, 30, 1;
1187
1188   setBaseMultigrading(M, T);
1189
1190   ideal I = x, y, xy^5;
1191   isHomogeneous(I);
1192
1193   intmat V = multiDeg(I); print(V);
1194
1195   module S = syz(I); print(S);
1196
1197   S = setModuleGrading(S, V);
1198
1199   getModuleGrading(S) == V;
1200
1201   vector v = getGradedGenerator(S, 1);
1202   getModuleGrading(v) == V;
1203   isHomogeneous(v);
1204   print( multiDeg(v) );
1205
1206   isHomogeneous(S);
1207   print( multiDeg(S) );
1208}
1209
1210/******************************************************/
1211proc setModuleGrading(def m, intmat G)
1212"USAGE: setModuleGrading(m, G), m module/vector, G intmat
1213PURPOSE: attaches the multiweights of free module generators to 'm'
1214WARNING: The method does not verify whether the multigrading makes the
1215         module/vector homogeneous. One can do that using isHomogeneous(m).
1216EXAMPLE: example setModuleGrading; shows an example
1217"
1218{
1219  string attrModuleGrading = "genWeights";
1220
1221  intmat R = getVariableWeights();
1222
1223  if(nrows(G) != nrows(R)){ ERROR("Incompatible gradings.");}
1224  if(ncols(G) < nrows(m)){ ERROR("Multigrading does not fit to module.");}
1225
1226  attrib(m, attrModuleGrading, G);
1227  return(m);
1228}
1229example
1230{
1231  "EXAMPLE:"; echo=2;
1232
1233   ring R = 0, (x,y), dp;
1234   intmat M[2][2]=
1235     1, 1,
1236     0, 2;
1237   intmat T[2][5]=
1238     1,  2,  3,  4, 0,
1239     0, 10, 20, 30, 1;
1240
1241   setBaseMultigrading(M, T);
1242
1243   ideal I = x, y, xy^5;
1244   intmat V = multiDeg(I);
1245
1246   // V == M; modulo T
1247   print(V);
1248
1249   module S = syz(I);
1250
1251   S = setModuleGrading(S, V);
1252   getModuleGrading(S) == V;
1253
1254   print(S);
1255
1256   vector v = getGradedGenerator(S, 1);
1257   getModuleGrading(v) == V;
1258
1259   print( multiDeg(v) );
1260
1261   isHomogeneous(S);
1262
1263   print( multiDeg(S) );
1264}
1265
1266
1267proc multiDegTensor(module m, module n)
1268"
1269USAGE: multiDegTensor(m, n), m,n  modules or matrices.
1270PURPOSE: Computes the multigraded tensor product of to multigraded modules.
1271RETURN: A module.
1272EXAMPLE: example multiDegTensor; shows an example
1273"
1274{
1275  matrix M = m;
1276  matrix N = n;
1277  intmat gm = getModuleGrading(m);
1278  intmat gn = getModuleGrading(n);
1279  int grows = nrows(gm);
1280  int mr = nrows(M);
1281  int mc = ncols(M);
1282  if(rank(M) == 0){ mc = 0;}
1283  int nr = nrows(N);
1284  int nc = ncols(N);
1285  if(rank(N) == 0){ nc = 0;}
1286  intmat gresult[nrows(gm)][mr*nr];
1287  matrix result[mr*nr][mr*nc+mc*nr];
1288  int i, j;
1289  int column = 1;
1290  for(i = 1; i<=mr; i++){
1291    for(j = 1; j<=nr; j++){
1292      gresult[1..grows,(i-1)*nr+j] = gm[1..grows,i]+gn[1..grows,j];
1293    }
1294  }
1295  //gresult;
1296  if( nc!=0 ){
1297    for(i = 1; i<=mr; i++)
1298    {
1299      result[((i-1)*nr+1)..(i*nr),((i-1)*nc+1)..(i*nc)] = N[1..nr,1..nc];
1300    }
1301  }
1302  list rownumbers, colnumbers;
1303  //print(result);
1304  if( mc!=0 ){
1305    for(j = 1; j<=nr; j++)
1306    {
1307      rownumbers = nr*(0..(mr-1))+j*(1:mr);
1308      colnumbers = ((mr*nc+j):mc)+nr*(0..(mc-1));
1309      result[rownumbers[1..mr],colnumbers[1..mc] ] = M[1..mr,1..mc];
1310    }
1311  }
1312  module res = result;
1313  res = setModuleGrading(res, gresult);
1314  //getModuleGrading(res);
1315  return(res);
1316}
1317example
1318{
1319"EXAMPLE: ";echo=2;
1320ring r = 0,(x),dp;
1321intmat g[2][1]=1,1;
1322setBaseMultigrading(g);
1323matrix m[5][3]=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;
1324matrix n[3][2]=x,x2,x3,x4,x5,x6;
1325module mm = m;
1326module nn = n;
1327intmat gm[2][5]=1,2,3,4,5,0,0,0,0,0;
1328intmat gn[2][3]=0,0,0,1,2,3;
1329mm = setModuleGrading(mm, gm);
1330nn = setModuleGrading(nn, gn);
1331module mmtnn = multiDegTensor(mm, nn);
1332print(mmtnn);
1333getModuleGrading(mmtnn);
1334LIB "homolog.lib";
1335module tt = tensorMod(mm,nn);
1336print(tt);
1337
1338kill m, mm, n, nn, gm, gn;
1339
1340matrix m[7][3] = x, x-1,x+2, 3x, 4x, x5, x6, x-7, x-8, 9, 10, 11x, 12 -x, 13x, 14x, x15, (x-4)^2, x17, 18x, 19x, 20x, 21x;
1341matrix n[2][4] = 1, 2, 3, 4, x, x2, x3, x4;
1342module mm = m;
1343module nn = n;
1344print(mm);
1345print(nn);
1346intmat gm[2][7] = 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0;
1347intmat gn[2][2] = 0, 0, 1, 2;
1348mm = setModuleGrading(mm, gm);
1349nn = setModuleGrading(nn, gn);
1350module mmtnn = multiDegTensor(mm, nn);
1351print(mmtnn);
1352getModuleGrading(mmtnn);
1353matrix a = mmtnn;
1354matrix b = tensorMod(mm, nn);
1355print(a-b);
1356
1357}
1358
1359proc multiDegTor(int i, module m, module n)
1360{
1361  def res = multiDegResolution(n, 0, 1);
1362  //print(res);
1363  list l = res;
1364  if(size(l)<i){ return(0);}
1365  else
1366  {
1367
1368    matrix fd[nrows(m)][0];
1369    matrix fd2[nrows(l[i+1])][0];
1370    matrix fd3[nrows(l[i])][0];
1371
1372    module freedim = fd;
1373    module freedim2 = fd2;
1374    module freedim3 = fd3;
1375
1376    freedim = setModuleGrading(freedim,getModuleGrading(m));
1377    freedim2 = setModuleGrading(freedim2,getModuleGrading(l[i+1]));
1378    freedim3 = setModuleGrading(freedim3, getModuleGrading(l[i]));
1379
1380    module mimag = multiDegTensor(freedim3, m);
1381    //"mimag ok.";
1382    module mf = multiDegTensor(l[i], freedim);
1383    //"mf ok.";
1384    module mim1 = multiDegTensor(freedim2 ,m);
1385    module mim2 = multiDegTensor(l[i+1],freedim);
1386    //"mim1+2 ok.";
1387    module mker = multiDegModulo(mf,mimag);
1388    //"mker ok.";
1389    module mim = mim1,mim2;
1390    mim = setModuleGrading(mim, getModuleGrading(mim1));
1391    //"mim: r: ",nrows(mim)," c: ",ncols(mim);
1392    //"mim1: r: ",nrows(mim1)," c: ",ncols(mim1);
1393    //"mim2: r: ",nrows(mim2)," c: ",ncols(mim2);
1394    //matrix mimmat = mim;
1395    //matrix mimmat1[16][4]=mimmat[1..16,25..28];
1396    //print(mimmat1-matrix(mim2));
1397    return(multiDegModulo(mker,mim));
1398    //return(0);
1399  }
1400  return(0);
1401}
1402example
1403{
1404"EXAMPLE: ";echo=2;
1405LIB "homolog.lib";
1406ring r = 0,(x_(1..4)),dp;
1407intmat g[2][4]=1,1,0,0,0,1,1,-1;
1408setBaseMultigrading(g);
1409ideal i = maxideal(1);
1410module m = multiDegSyzygy(i);
1411module rt = Tor(2,m,m);
1412module multiDegT = multiDegTor(2,m,m);
1413print(matrix(rt)-matrix(multiDegT));
1414/*
1415ring r = 0,(x),dp;
1416intmat g[2][1]=1,1;
1417setBaseMultigrading(g);
1418matrix m[5][3]=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;
1419matrix n[3][2]=x,x2,x3,x4,x5,x6;
1420module mm = m;
1421module nn = n;
1422intmat gm[2][5]=1,1,1,1,1,1,1,1,1,1,1;
1423intmat gn[2][3]=0,-2,-4,0,-2,-4;
1424mm = setModuleGrading(mm, gm);
1425nn = setModuleGrading(nn, gn);
1426isHomogeneous(mm,"checkGens");
1427isHomogeneous(nn,"checkGens");
1428multiDegTor(1,mm, nn);
1429
1430kill m, mm, n, nn, gm, gn;
1431
1432matrix m[7][3] = x, x-1,x+2, 3x, 4x, x5, x6, x-7, x-8, 9, 10, 11x, 12 -x, 13x, 14x, x15, (x-4)^2, x17, 18x, 19x, 20x, 21x;
1433matrix n[2][4] = 1, 2, 3, 4, x, x2, x3, x4;
1434module mm = m;
1435module nn = n;
1436print(mm);
1437print(nn);
1438intmat gm[2][7] = 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0;
1439intmat gn[2][2] = 0, 0, 1, 2;
1440mm = setModuleGrading(mm, gm);
1441nn = setModuleGrading(nn, gn);
1442module mmtnn = multiDegTensor(mm, nn);
1443*/
1444}
1445
1446
1447/******************************************************/
1448proc isGroupHomomorphism(def L1, def L2, intmat A)
1449"USAGE: isGoupHomomorphism(L1,L2,A); L1 and L2 are groups, A is an integer matrix
1450PURPOSE: checks whether A defines a group homomorphism phi: L1 --> L2
1451RETURN: int, 1 if A defines the homomorphism and 0 otherwise
1452EXAMPLE: example isGroupHomomorphism; shows an example
1453"
1454{
1455  // TODO: L1, L2
1456  if( (ncols(A) != nrows(L1)) or (nrows(A) != nrows(L2)) )
1457  {
1458    ERROR("Incompatible sizes!");
1459  }
1460
1461  intmat im = A * L1;
1462
1463  return  (areZeroElements(im, L2));
1464}
1465example
1466{
1467  "EXAMPLE:"; echo=2;
1468
1469   intmat L1[4][1]=
1470     0,
1471     0,
1472     0,
1473     2;
1474
1475   intmat L2[3][2]=
1476     0, 0,
1477     2, 0,
1478     0, 3;
1479
1480  intmat A[3][4] =
1481     1, 2, 3, 0,
1482     7, 0, 0, 0,
1483     1, 2, 0, 3;
1484  print( A );
1485
1486  isGroupHomomorphism(L1, L2, A);
1487
1488  intmat B[3][4] =
1489     1, 2, 3, 0,
1490     7, 0, 0, 0,
1491     1, 2, 0, 2;
1492  print( B );
1493
1494  isGroupHomomorphism(L1, L2, B); // Not a homomorphism!
1495}
1496
1497/******************************************************/
1498proc isTorsionFree()
1499"USAGE: isTorsionFree()
1500PURPOSE: Determines whether the multigrading attached to the current ring is free.
1501RETURN: boolean, the result of the test
1502EXAMPLE: example isTorsionFree; shows an example
1503"
1504{
1505  intmat H = smithNormalForm(getLattice()); // TODO: ?cache it?  //******
1506
1507  int i, j;
1508  int r = nrows(H);
1509  int c = ncols(H);
1510  int d = 1;
1511  for( i = 1; (i <= c) && (i <= r); i++ )
1512  {
1513    for( j = i; (H[j, i] == 0)&&(j < r); j++ )
1514    {
1515    }
1516
1517    if(H[j, i]!=0)
1518    {
1519      d=d*H[j, i];
1520    }
1521  }
1522
1523  if( (d*d)==1 )
1524  {
1525    return(1==1);
1526  }
1527  return(0==1);
1528}
1529example
1530{
1531  "EXAMPLE:"; echo=2;
1532
1533   ring R = 0,(x,y),dp;
1534   intmat M[2][2]=
1535     1,0,
1536     0,1;
1537   intmat T[2][5]=
1538     1, 2, 3, 4, 0,
1539     0,10,20,30, 1;
1540
1541   setBaseMultigrading(M,T);
1542
1543   // Is the resulting group  free?
1544   isTorsionFree();
1545
1546   kill R, M, T;
1547   ///////////////////////////////////////////
1548
1549   ring R=0,(x,y,z),dp;
1550   intmat A[3][3] =
1551     1,0,0,
1552     0,1,0,
1553     0,0,1;
1554   intmat B[3][4]=
1555     3,3,3,3,
1556     2,1,3,0,
1557     1,2,0,3;
1558   setBaseMultigrading(A,B);
1559   // Is the resulting group  free?
1560   isTorsionFree();
1561
1562   kill R, A, B;
1563}
1564
1565
1566static proc gcdcomb(int a, int b)
1567{
1568  // a;
1569  // b;
1570  intvec av = a,1,0;
1571  intvec bv = b,0,1;
1572  intvec save;
1573  while(av[1]*bv[1] != 0)
1574  {
1575    bv = bv - (bv[1] - bv[1]%av[1]) div av[1] * av;
1576    save = bv;
1577    bv = av;
1578    av = save;
1579  }
1580  if(bv[1] < 0)
1581  {
1582    bv = -bv;
1583  }
1584  return(bv);
1585}
1586
1587
1588proc lll(def A)
1589"
1590The lll algorithm of lll.lib only works for lists of vectors.
1591Maybe one should rescript it for matrices. This method will
1592convert a matrix to a list, plug it into lll and make the result
1593a matrix and return it.
1594"
1595{
1596  if(typeof(A) == "list")
1597  {
1598    int sizeA= size (A);
1599    if (sizeA == 0)
1600    {
1601      return (A);
1602    }
1603    if (typeof (A [1]) != "intvec")
1604    {
1605      ERROR("Unrecognized type.");
1606    }
1607    int columns= size (A [1]);
1608    int i;
1609    for (i= 2; i <= sizeA; i++)
1610    {
1611      if (typeof (A[i]) != "intvec")
1612      {
1613        ERROR("Unrecognized type.");
1614      }
1615      if (size (A [i]) != columns)
1616      {
1617        ERROR ("expected equal dimension");
1618      }
1619    }
1620    int j;
1621    intmat m [columns] [sizeA];
1622    for (i= 1; i <= sizeA; i++)
1623    {
1624      for (j= 1; j <= columns; j++)
1625      {
1626        m[i,j]= A[i] [j];
1627      }
1628    }
1629    m= system ("LLL", m);
1630    list result= list();
1631    intvec buf;
1632
1633    for (i= 1; i <= sizeA; i++)
1634    {
1635      buf = intvec (m[i , 1..columns]);
1636      result= result+ list (buf);
1637
1638    }
1639    return(result);
1640  }
1641  else
1642  {
1643    if(typeof(A) == "intmat")
1644    {
1645      A= system ("LLL", A);
1646      return(A);
1647    }
1648    else
1649    {
1650      ERROR("Unrecognized type.");
1651    }
1652  }
1653}
1654example
1655{
1656  "EXAMPLE:"; echo=2;
1657
1658  ring R = 0,x,dp;
1659  intmat m[5][5] =
1660                  13,25,37,83,294,
1661                  12,-33,9,0,64,
1662                  77,12,34,6,1,
1663                  43,2,88,91,100,
1664                  -46,32,37,42,15;
1665  lll(m);
1666
1667  list l =
1668      intvec(13,25,37, 83, 294),
1669      intvec(12, -33, 9,0,64),
1670      intvec (77,12,34,6,1),
1671      intvec (43,2,88,91,100),
1672      intvec (-46,32,37,42,15);
1673  lll(l);
1674}
1675
1676
1677proc smithNormalForm(intmat A, list #)
1678"USAGE: smithNormalForm(A[,opt]); intmat A
1679PURPOSE: Computes the Smith Normal Form of A
1680RETURN: if no optional argument is given: intmat, the Smith Normal Form of A,
1681otherwise: a list of 3 integer matrices P, D Q, such that D == P*A*Q.
1682EXAMPLE: example smithNormalForm; shows an example
1683"
1684{
1685  list l1 = hermiteNormalForm(A, 5);
1686  // l1;
1687  intmat B = transpose(l1[1]);
1688  list l2 = hermiteNormalForm(B, 5);
1689  // l2;
1690  intmat P = transpose(l2[2]);
1691  intmat D = transpose(l2[1]);
1692  intmat Q = l1[2];
1693  int cc = ncols(D);
1694  int rr = nrows(D);
1695  intmat transform;
1696  int k = 1;
1697  int a, b, c;
1698  // D;
1699  intvec v;
1700  if((cc==1)||(rr==1))
1701  {
1702    if(size(#)==0)
1703    {
1704      return(D);
1705    }
1706    else
1707    {
1708      return(list(P,D,Q));
1709    }
1710  }
1711  while(D[k+1,k+1] !=0)
1712  {
1713    if(D[k+1,k+1]%D[k,k]!=0)
1714    {
1715      b = D[k, k]; c = D[k+1, k+1];
1716      v = gcdcomb(D[k,k],D[k+1,k+1]);
1717      transform = unitMatrix(cc);
1718      transform[k+1,k] = 1;
1719      a = -v[3]*D[k+1,k+1] div v[1];
1720      transform[k, k+1] = a;
1721      transform[k+1, k+1] = a+1;
1722      //det(transform);
1723      D = D*transform;
1724      Q = Q*transform;
1725      //D;
1726      transform = unitMatrix(rr);
1727      transform[k,k] = v[2];
1728      transform[k,k+1] = v[3];
1729      transform[k+1,k] = -c div v[1];
1730      transform[k+1,k+1] = b div v[1];
1731      D = transform * D;
1732      P = transform * P;
1733      //" ";
1734      //D;
1735      //"small transform: ", det(transform);
1736      //transform;
1737      k=0;
1738    }
1739    k++;
1740    if((k==rr) || (k==cc))
1741    {
1742      break;
1743    }
1744  }
1745  //"here is the size ",size(#);
1746  if(size(#) == 0)
1747  {
1748    return(D);
1749  }
1750  else
1751  {
1752    return(list(P, D, Q));
1753  }
1754}
1755example
1756{
1757  "EXAMPLE:"; echo=2;
1758
1759
1760  intmat A[5][7] =
1761                  1,0,1,0,-2,9,-71,
1762                  0,-24,248,-32,-96,448,-3496,
1763                  0,4,-42,4,-8,30,-260,
1764                  0,0,0,18,-90,408,-3168,
1765                  0,0,0,-32,224,-1008,7872;
1766
1767  print( smithNormalForm(A) );
1768
1769  list l = smithNormalForm(A, 5);
1770
1771  l;
1772
1773  l[1]*A*l[3];
1774
1775  det(l[1]);
1776  det(l[3]);
1777}
1778
1779
1780/******************************************************/
1781proc hermiteNormalForm(intmat A, list #)
1782"USAGE: hermiteNormalForm( A );
1783PURPOSE: Computes the (lower triangular) Hermite Normal Form
1784           of the matrix A by column operations.
1785RETURN: intmat, the Hermite Normal Form of A
1786EXAMPLE: example hermiteNormalForm; shows an example
1787"
1788{
1789
1790  int row, column, i, j;
1791  int rr = nrows(A);
1792  int cc = ncols(A);
1793  intvec savev, gcdvec, v1, v2;
1794  intmat q = unitMatrix(cc);
1795  intmat transform;
1796  column = 1;
1797  for(row = 1; (row<=rr)&&(column<=cc); row++)
1798    {
1799      if(A[row,column]==0)
1800        {
1801          for(j = column; j<=cc; j++)
1802            {
1803              if(A[row, j]!=0)
1804                {
1805                  transform = unitMatrix(cc);
1806                  transform[j,j] = 0;
1807                  transform[column, column] = 0;
1808                  transform[column,j] = 1;
1809                  transform[j,column] = 1;
1810                  q = q*transform;
1811                  A = A*transform;
1812                  break;
1813                }
1814            }
1815        }
1816      if(A[row,column] == 0)
1817        {
1818          row++;
1819          continue;
1820        }
1821      for(j = column+1; j<=cc; j++)
1822        {
1823          if(A[row, j]!=0)
1824            {
1825              gcdvec = gcdcomb(A[row,column],A[row,j]);
1826              // gcdvec;
1827              // typeof(A[1..rr,column]);
1828              v1 = A[1..rr,column];
1829              v2 = A[1..rr,j];
1830              transform = unitMatrix(cc);
1831              transform[j,j] = v1[row] div gcdvec[1];
1832              transform[column, column] = gcdvec[2];
1833              transform[column,j] = -v2[row] div gcdvec[1];
1834              transform[j,column] = gcdvec[3];
1835              q = q*transform;
1836              A = A*transform;
1837              // A;
1838            }
1839        }
1840      if(A[row,column]<0)
1841        {
1842          transform = unitMatrix(cc);
1843          transform[column,column] = -1;
1844          q = q*transform;
1845          A = A*transform;
1846        }
1847      for( j=1; j<column; j++){
1848        if(A[row, j]!=0){
1849          transform = unitMatrix(cc);
1850          transform[column, j] = (-A[row,j]+A[row, j]%A[row, column]) div A[row, column];
1851          if(A[row,j]<0){
1852            transform[column,j]=transform[column,j]+1;}
1853          q = q*transform;
1854          A = A*transform;
1855        }
1856      }
1857      column++;
1858    }
1859  if(size(#) > 0){
1860    return(list(A, q));
1861  }
1862  return(A);
1863}
1864example
1865{
1866  "EXAMPLE:"; echo=2;
1867
1868   intmat M[2][5] =
1869     1, 2, 3, 4, 0,
1870     0,10,20,30, 1;
1871
1872   // Hermite Normal Form of M:
1873   print(hermiteNormalForm(M));
1874
1875   intmat T[3][4] =
1876     3,3,3,3,
1877     2,1,3,0,
1878     1,2,0,3;
1879
1880   // Hermite Normal Form of T:
1881   print(hermiteNormalForm(T));
1882
1883   intmat A[4][5] =
1884     1,2,3,2,2,
1885     1,2,3,4,0,
1886     0,5,4,2,1,
1887     3,2,4,0,2;
1888
1889   // Hermite Normal Form of A:
1890   print(hermiteNormalForm(A));
1891}
1892
1893proc areZeroElements(intmat m, list #)
1894"USAGE: areZeroElements(D, [T]); intmat D, group T
1895PURPOSE: For a integer matrix D, considered column-wise as a set of
1896   integer vecors representing the multidegree of some polynomial
1897   or vector this method checks whether all these multidegrees
1898   are contained in the grading group
1899   group (either set globally or given as an optional argument),
1900i.e. if they all are zero in the multigrading.
1901EXAMPLE: example areZeroElements; shows an example
1902"
1903{
1904  int r = nrows(m);
1905  int i = ncols(m);
1906
1907  intvec v;
1908
1909  for( ; i > 0; i-- )
1910  {
1911    v = m[1..r, i];
1912    if( !isZeroElement(v, #) )
1913    {
1914      return (0);
1915    }
1916  }
1917  return(1);
1918}
1919example
1920{
1921  "EXAMPLE:"; echo=2;
1922
1923  ring r = 0,(x,y,z),dp;
1924
1925  intmat S[2][3]=
1926    1,0,1,
1927    0,1,1;
1928
1929  intmat L[2][1]=
1930    2,
1931    2;
1932
1933  setBaseMultigrading(S,L);
1934
1935  poly a = 1;
1936  poly b = xyz;
1937
1938  ideal I = a, b;
1939  print(multiDeg(I));
1940
1941  intmat m[5][2]=multiDeg(a),multiDeg(b); m=transpose(m);
1942
1943  print(multiDeg(a));
1944  print(multiDeg(b));
1945
1946  print(m);
1947
1948  areZeroElements(m);
1949
1950  intmat LL[2][1]=
1951     1,
1952    -1;
1953
1954  areZeroElements(m,LL);
1955}
1956
1957
1958/******************************************************/
1959proc isZeroElement(intvec mdeg, list #)
1960"USAGE: isZeroElement(d, [T]); intvec d, group T
1961PURPOSE: For a integer vector 'd' representing the multidegree of some polynomial
1962or vector this method computes if the multidegree is contained in the grading group
1963group (either set globally or given as an optional argument), i.e. if it is zero in the multigrading.
1964EXAMPLE: example isZeroElement; shows an example
1965"
1966{
1967  int i = 1;
1968  if( size(#) >= i )
1969  {
1970    def a = #[1];
1971    if( typeof(a) == "intmat" )
1972    {
1973      intmat H = hermiteNormalForm(a);
1974      i++;
1975    }
1976    if( typeof(a) == "list" )
1977    {
1978      list L = a;
1979      intmat H = attrib(L, "hermite"); // todo
1980      i++;
1981    }
1982    kill a;
1983  }
1984
1985  if( i == 1 )
1986  {
1987    intmat H = getLattice("hermite");
1988  }
1989
1990  int x, k, row;
1991
1992  int r = nrows(H);
1993  int c = ncols(H);
1994
1995  int rr = nrows(mdeg);
1996  row = 1;
1997  intvec v;
1998  for(i=1; (i<=r)&&(row<=r)&&(i<=c); i++)
1999  {
2000    while((H[row,i]==0)&&(row<=r))
2001    {
2002      row++;
2003      if(row == (r+1)){
2004        break;
2005      }
2006    }
2007    if(row<=r){
2008      if(H[row,i]!=0)
2009      {
2010        v = H[1..r,i];
2011        mdeg = mdeg-(mdeg[row]-mdeg[row]%v[row]) div v[row]*v;
2012      }
2013    }
2014  }
2015  return( mdeg == 0 );
2016
2017}
2018example
2019{
2020 "EXAMPLE:"; echo=2;
2021
2022  ring r = 0,(x,y,z),dp;
2023
2024  intmat g[2][3]=
2025    1,0,1,
2026    0,1,1;
2027  intmat t[2][1]=
2028    -2,
2029    1;
2030
2031  intmat tt[2][1]=
2032    1,
2033    -1;
2034
2035  setBaseMultigrading(g,t);
2036
2037  poly a = x10yz;
2038  poly b = x8y2z;
2039  poly c = x4z2;
2040  poly d = y5;
2041  poly e = x2y2;
2042  poly f = z2;
2043
2044  intvec v1 = multiDeg(a) - multiDeg(b);
2045  v1;
2046  isZeroElement(v1);
2047  isZeroElement(v1, tt);
2048
2049  intvec v2 = multiDeg(a) - multiDeg(c);
2050  v2;
2051  isZeroElement(v2);
2052  isZeroElement(v2, tt);
2053
2054  intvec v3 = multiDeg(e) - multiDeg(f);
2055  v3;
2056  isZeroElement(v3);
2057  isZeroElement(v3, tt);
2058
2059  intvec v4 = multiDeg(c) - multiDeg(d);
2060  v4;
2061  isZeroElement(v4);
2062  isZeroElement(v4, tt);
2063}
2064
2065
2066/******************************************************/
2067proc defineHomogeneous(poly f, list #)
2068"USAGE: defineHomogeneous(f[, G]); polynomial f, integer matrix G
2069PURPOSE: Yields a matrix which has to be appended to the grading group matrix to make the
2070polynomial f homogeneous in the grading by grad.
2071EXAMPLE: example defineHomogeneous; shows an example
2072"
2073{
2074  int i = 1;
2075  if( size(#) >= i )
2076  {
2077    def a = #[1];
2078    if( typeof(a) == "intmat" )
2079    {
2080      intmat grad = a;
2081      i++;
2082    }
2083    kill a;
2084  }
2085
2086  if( i == 1 )
2087  {
2088    intmat grad = getVariableWeights();
2089  }
2090
2091  intmat newgg[nrows(grad)][size(f)-1];
2092  int j;
2093  intvec l = grad*leadexp(f);
2094  intvec v;
2095  for(i=2; i <= size(f); i++)
2096  {
2097    v = grad * leadexp(f[i]) - l;
2098    for( j=1; j<=size(v); j++)
2099    {
2100      newgg[j,i-1] = v[j];
2101    }
2102  }
2103  return(newgg);
2104}
2105example
2106{
2107  "EXAMPLE:"; echo=2;
2108
2109  ring r =0,(x,y,z),dp;
2110  intmat grad[2][3] =
2111    1,0,1,
2112    0,1,1;
2113
2114  setBaseMultigrading(grad);
2115
2116  poly f = x2y3-z5+x-3zx;
2117
2118  intmat M = defineHomogeneous(f);
2119  M;
2120  defineHomogeneous(f, grad) == M;
2121
2122  isHomogeneous(f);
2123  setBaseMultigrading(grad, M);
2124  isHomogeneous(f);
2125}
2126
2127
2128proc gradiator(def h)
2129"PURPOSE: coarsens the grading of the basering until the polynom or ideal h becomes homogeneous."
2130{
2131  if(typeof(h)=="poly"){
2132    intmat W = getVariableWeights();
2133    intmat L = getLattice();
2134    intmat toadd = defineHomogeneous(h);
2135    //h;
2136    //toadd;
2137    if(ncols(toadd) == 0)
2138    {
2139      return(1==1);
2140    }
2141    int rr = nrows(W);
2142    intmat newL[rr][ncols(L)+ncols(toadd)];
2143    newL[1..rr,1..ncols(L)] = L[1..rr,1..ncols(L)];
2144    newL[1..rr,(ncols(L)+1)..(ncols(L)+ncols(toadd))] = toadd[1..rr,1..ncols(toadd)];
2145    setBaseMultigrading(W,newL);
2146    return(1==1);
2147  }
2148  if(typeof(h)=="ideal"){
2149    int i;
2150    def s = (1==1);
2151    for(i=1;i<=size(h);i++){
2152      s = s && gradiator(h[i]);
2153    }
2154    return(s);
2155  }
2156  return(1==0);
2157}
2158example
2159{
2160  "EXAMPLE:"; echo=2;
2161
2162ring r = 0,(x,y,z),dp;
2163intmat g[2][3] = 1,0,1,0,1,1;
2164intmat l[2][1] = 3,0;
2165
2166setBaseMultigrading(g,l);
2167
2168getLattice();
2169
2170ideal i = -y5+x4,
2171          y6+xz,
2172          x2y;
2173gradiator(i);
2174getLattice();
2175isHomogeneous(i);
2176}
2177
2178
2179proc pushForward(map f)
2180"USAGE: pushForward(f);
2181PURPOSE: Computes the finest grading of the image ring which makes the map f
2182a map of graded rings. The group map between the two grading groups is given
2183by transpose( (Id, 0) ). Pay attention that the group spanned by the columns of
2184the grading group matrix may not be a subgroup of the grading group. Still all columns
2185are needed to find the correct image of the preimage gradings.
2186EXAMPLE: example pushForward; shows an example
2187"
2188{
2189
2190  int k,i,j;
2191//  f;
2192
2193//  listvar();
2194  def pre = preimage(f);
2195
2196//  "pre: ";  pre;
2197
2198  intmat oldgrad=getVariableWeights(pre);
2199  intmat oldlat=getLattice(pre);
2200
2201  int n=nvars(pre);
2202  int np=nvars(basering);
2203  int p=nrows(oldgrad);
2204  int pp=p+np;
2205
2206  intmat newgrad[pp][np];
2207
2208  //This will set the finest grading on the image ring. We will proceed by coarsening this grading until f becomes homogeneous.
2209  for(i=1;i<=np;i++){ newgrad[p+i,i]=1;}
2210
2211  //newgrad;
2212
2213
2214
2215  list newlat;
2216  intmat toadd;
2217  int columns=0;
2218
2219  intmat toadd1[pp][n];
2220  intvec v;
2221  poly im;
2222
2223  for(i=1;i<=p;i++){
2224    for(j=1;j<=n;j++){ toadd1[i,j]=oldgrad[i,j];}
2225  }
2226
2227  // This will make the images of homogeneous elements homogeneous, namely the variables of the preimage ring.
2228  for(i=1;i<=n;i++){
2229    im=f[i];
2230    //im;
2231    toadd = defineHomogeneous(im, newgrad);
2232    newlat=insert(newlat,toadd);
2233    columns=columns+ncols(toadd);
2234
2235    v=leadexp(f[i]);
2236    for(j=p+1;j<=p+np;j++){ toadd1[j,i]=-v[j-p];}
2237  }
2238
2239  newlat=insert(newlat,toadd1);
2240  columns=columns+ncols(toadd1);
2241
2242  //If the image ring is a quotient ring by some ideal, we have to coarsen the grading in order to make the ideal homogeneous.
2243  if(typeof(basering)=="qring"){
2244    //"Entering qring";
2245    ideal a=ideal(basering);
2246    for(i=1;i<=size(a);i++){
2247      toadd = defineHomogeneous(a[i], newgrad);
2248      //toadd;
2249      columns=columns+ncols(toadd);
2250      newlat=insert(newlat,toadd);
2251    }
2252  }
2253
2254  //The grading group of the preimage ring might not have been torsion free. We have to add this torsion to the grading group of the image ring.
2255  intmat imofoldlat[pp][ncols(oldlat)];
2256  for(i=1; i<=nrows(oldlat);i++){
2257    for(j=1; j<=ncols(oldlat); j++){
2258      imofoldlat[i,j]=oldlat[i,j];
2259    }
2260  }
2261
2262  columns=columns+ncols(oldlat);
2263  newlat=insert(newlat, imofoldlat);
2264
2265  intmat gragr[pp][columns];
2266  columns=0;
2267  for(k=1;k<=size(newlat);k++){
2268    for(i=1;i<=pp;i++){
2269      for(j=1;j<=ncols(newlat[k]);j++){gragr[i,j+columns]=newlat[k][i,j];}
2270    }
2271    columns=columns+ncols(newlat[k]);
2272  }
2273
2274  //The following is just for reducing the size of the matrices.
2275  gragr=hermiteNormalForm(gragr);
2276  intmat result[pp][pp];
2277  for(i=1;i<=pp;i++){
2278    for(j=1;j<=pp;j++){result[i,j]=gragr[i,j];}
2279  }
2280
2281  setBaseMultigrading(newgrad, result);
2282
2283}
2284example
2285{
2286  "EXAMPLE:"; echo=2;
2287
2288  ring r = 0,(x,y,z),dp;
2289
2290
2291
2292  // Setting degrees for preimage ring.;
2293  intmat grad[3][3] =
2294    1,0,0,
2295    0,1,0,
2296    0,0,1;
2297
2298  setBaseMultigrading(grad);
2299
2300  // grading on r:
2301  getVariableWeights();
2302  getLattice();
2303
2304  // only for the purpose of this example
2305  if( voice > 1 ){ /*keepring(r);*/ export(r); }
2306
2307  ring R = 0,(a,b),dp;
2308  ideal i = a2-b2+a6-b5+ab3,a7b+b15-ab6+a6b6;
2309
2310  // The quotient ring by this ideal will become our image ring.;
2311  qring Q = std(i);
2312
2313  listvar();
2314
2315  map f = r,-a2b6+b5+a3b+a2+ab,-a2b7-3a2b5+b4+a,a6-b6-b3+a2; f;
2316
2317
2318  // TODO: Unfortunately this is not a very spectacular example...:
2319  // Pushing forward f:
2320  pushForward(f);
2321
2322  // due to pushForward we have got new grading on Q
2323  getVariableWeights();
2324  getLattice();
2325
2326
2327  // only for the purpose of this example
2328  if( voice > 1 ){ kill r; }
2329
2330}
2331
2332
2333/******************************************************/
2334proc equalMultiDeg(intvec exp1, intvec exp2, list #)
2335"USAGE: equalMultiDeg(exp1, exp2[, V]); intvec exp1, exp2, intmat V
2336PURPOSE: Tests if the exponent vectors of two monomials (given by exp1 and exp2)
2337represent the same multidegree.
2338NOTE: the integer matrix V encodes multidegrees of module components,
2339if module component is present in exp1 and exp2
2340EXAMPLE: example equalMultiDeg; shows an example
2341"
2342{
2343  if( size(exp1) != size(exp2) )
2344  {
2345    ERROR("Sorry: we cannot compare exponents comming from a polynomial and a vector yet!");
2346  }
2347
2348  if( exp1 == exp2)
2349  {
2350    return (1==1);
2351  }
2352
2353
2354
2355  intmat M = getVariableWeights();
2356
2357  if( nrows(exp1) > ncols(M) ) // vectors => last exponent is the module component!
2358  {
2359    if( (size(#) == 0) or (typeof(#[1])!="intmat") )
2360    {
2361      ERROR("Sorry: wrong or missing module-unit-weights-matrix V!");
2362    }
2363    intmat V = #[1];
2364
2365    // typeof(V); print(V);
2366
2367    int N = ncols(M);
2368    int r = nrows(M);
2369
2370    intvec d = intvec(exp1[1..N]) - intvec(exp2[1..N]);
2371    intvec dm = intvec(V[1..r, exp1[N+1]]) - intvec(V[1..r, exp2[N+1]]);
2372
2373    intvec difference = M * d + dm;
2374  }
2375  else
2376  {
2377    intvec d = (exp1 - exp2);
2378    intvec difference = M * d;
2379  }
2380
2381  if (isFreeRepresented()) // no grading group!?
2382  {
2383    return ( difference == 0);
2384  }
2385  return ( isZeroElement( difference ) );
2386}
2387example
2388{
2389  "EXAMPLE:"; echo=2;printlevel=3;
2390
2391  ring r = 0,(x,y,z),dp;
2392
2393  intmat g[2][3]=
2394    1,0,1,
2395    0,1,1;
2396
2397  intmat t[2][1]=
2398    -2,
2399    1;
2400
2401  setBaseMultigrading(g,t);
2402
2403  poly a = x10yz;
2404  poly b = x8y2z;
2405  poly c = x4z2;
2406  poly d = y5;
2407  poly e = x2y2;
2408  poly f = z2;
2409
2410
2411  equalMultiDeg(leadexp(a), leadexp(b));
2412  equalMultiDeg(leadexp(a), leadexp(c));
2413  equalMultiDeg(leadexp(a), leadexp(d));
2414  equalMultiDeg(leadexp(a), leadexp(e));
2415  equalMultiDeg(leadexp(a), leadexp(f));
2416
2417  equalMultiDeg(leadexp(b), leadexp(c));
2418  equalMultiDeg(leadexp(b), leadexp(d));
2419  equalMultiDeg(leadexp(b), leadexp(e));
2420  equalMultiDeg(leadexp(b), leadexp(f));
2421
2422  equalMultiDeg(leadexp(c), leadexp(d));
2423  equalMultiDeg(leadexp(c), leadexp(e));
2424  equalMultiDeg(leadexp(c), leadexp(f));
2425
2426  equalMultiDeg(leadexp(d), leadexp(e));
2427  equalMultiDeg(leadexp(d), leadexp(f));
2428
2429  equalMultiDeg(leadexp(e), leadexp(f));
2430
2431}
2432
2433
2434
2435/******************************************************/
2436static proc isFreeRepresented()
2437"check whether the base muligrading is free (it is zero).
2438"
2439{
2440  intmat T = getLattice();
2441
2442  intmat Z[nrows(T)][ncols(T)];
2443
2444  return (T == Z); // no grading group!
2445}
2446
2447
2448/******************************************************/
2449proc isHomogeneous(def a, list #)
2450"USAGE: isHomogeneous(a[, f]); a polynomial/vector/ideal/module
2451RETURN: boolean, TRUE if a is (multi)homogeneous, and FALSE otherwise
2452EXAMPLE: example isHomogeneous; shows an example
2453"
2454{
2455  if( (typeof(a) == "poly") or (typeof(a) == "vector") )
2456  {
2457    return ( size(multiDegPartition(a)) <= 1 )
2458  }
2459
2460  if( (typeof(a) == "ideal") or (typeof(a) == "module") )
2461  {
2462    if(size(#) > 0)
2463    {
2464      if (#[1] == "checkGens")
2465      {
2466        def aa;
2467        for( int i = ncols(a); i > 0; i-- )
2468        {
2469          aa = getGradedGenerator(a, i);
2470
2471          if(!isHomogeneous(aa))
2472          {
2473            return(0==1);
2474          }
2475        }
2476        return(1==1);
2477      }
2478    }
2479
2480    def g = groebner(a); // !!!!
2481
2482    def b, aa; int j;
2483    for( int i = ncols(a); i > 0; i-- )
2484    {
2485      aa = getGradedGenerator(a, i);
2486
2487      b = multiDegPartition(aa);
2488      for( j = ncols(b); j > 0; j-- )
2489      {
2490        if(NF(b[j],g) != 0)
2491        {
2492          return(0==1);
2493        }
2494      }
2495    }
2496    return(1==1);
2497  }
2498}
2499example
2500{
2501  "EXAMPLE:"; echo=2;
2502
2503  ring r = 0,(x,y,z),dp;
2504
2505  //Grading and Torsion matrices:
2506  intmat M[3][3] =
2507    1,0,0,
2508    0,1,0,
2509    0,0,1;
2510
2511  intmat T[3][1] =
2512    1,2,3;
2513
2514  setBaseMultigrading(M,T);
2515
2516  attrib(r);
2517
2518  poly f = x-yz;
2519
2520  multiDegPartition(f);
2521  print(multiDeg(_));
2522
2523  isHomogeneous(f);   // f: is not homogeneous
2524
2525  poly g = 1-xy2z3;
2526  isHomogeneous(g); // g: is homogeneous
2527  multiDegPartition(g);
2528
2529  kill T;
2530  /////////////////////////////////////////////////////////
2531  // new Torsion matrix:
2532  intmat T[3][4] =
2533    3,3,3,3,
2534    2,1,3,0,
2535    1,2,0,3;
2536
2537  setBaseMultigrading(M,T);
2538
2539  f;
2540  isHomogeneous(f);
2541  multiDegPartition(f);
2542
2543  // ---------------------
2544  g;
2545  isHomogeneous(g);
2546  multiDegPartition(g);
2547
2548  kill r, T, M;
2549
2550  ring R = 0, (x,y,z), dp;
2551
2552  intmat A[2][3] =
2553    0,0,1,
2554    3,2,1;
2555  intmat T[2][1] =
2556    -1,
2557     4;
2558  setBaseMultigrading(A, T);
2559
2560  isHomogeneous(ideal(x2 - y3 -xy +z, x*y-z, x^3 - y^2*z + x^2 -y^3)); // 1
2561  isHomogeneous(ideal(x2 - y3 -xy +z, x*y-z, x^3 - y^2*z + x^2 -y^3), "checkGens");
2562  isHomogeneous(ideal(x+y, x2 - y2)); // 0
2563
2564  // Degree partition:
2565  multiDegPartition(x2 - y3 -xy +z);
2566  multiDegPartition(x3 -y2z + x2 -y3 + z + 1);
2567
2568
2569  module N = gen(1) + (x+y) * gen(2), z*gen(3);
2570
2571  intmat V[2][3] = 0; // 1, 2, 3,  4, 5, 6; //  column-wise weights of components!!??
2572
2573  vector v1, v2;
2574
2575  v1 = setModuleGrading(N[1], V); v1;
2576  multiDegPartition(v1);
2577  print( multiDeg(_) );
2578
2579  v2 = setModuleGrading(N[2], V); v2;
2580  multiDegPartition(v2);
2581  print( multiDeg(_) );
2582
2583  N = setModuleGrading(N, V);
2584  isHomogeneous(N);
2585  print( multiDeg(N) );
2586
2587  ///////////////////////////////////////
2588
2589  V =
2590    1, 2, 3,
2591    4, 5, 6;
2592
2593  v1 = setModuleGrading(N[1], V); v1;
2594  multiDegPartition(v1);
2595  print( multiDeg(_) );
2596
2597  v2 = setModuleGrading(N[2], V); v2;
2598  multiDegPartition(v2);
2599  print( multiDeg(_) );
2600
2601  N = setModuleGrading(N, V);
2602  isHomogeneous(N);
2603  print( multiDeg(N) );
2604
2605  ///////////////////////////////////////
2606
2607  V =
2608    0, 0, 0,
2609    4, 1, 0;
2610
2611  N = gen(1) + x * gen(2), z*gen(3);
2612  N = setModuleGrading(N, V); print(N);
2613  isHomogeneous(N);
2614  print( multiDeg(N) );
2615  v1 = getGradedGenerator(N,1); print(v1);
2616  multiDegPartition(v1);
2617  print( multiDeg(_) );
2618  N = setModuleGrading(N, V); print(N);
2619  isHomogeneous(N);
2620  print( multiDeg(N) );
2621}
2622
2623/******************************************************/
2624proc multiDeg(def A)
2625"USAGE: multiDeg(A); polynomial/vector/ideal/module A
2626PURPOSE: compute multidegree
2627EXAMPLE: example multiDeg; shows an example
2628"
2629{
2630  def a = attrib(A, "grad");
2631  if( typeof(a) == "intvec" || typeof(a) == "intmat" )
2632  {
2633    return (a);
2634  }
2635
2636  intmat M = getVariableWeights();
2637  int N = nvars(basering);
2638
2639  if( ncols(M) != N )
2640  {
2641    ERROR("Sorry wrong mgrad-size of M: " + string(ncols(M)));
2642  }
2643
2644  int r = nrows(M);
2645
2646  if( (typeof(A) == "vector") or (typeof(A) == "module") )
2647  {
2648    intmat V = getModuleGrading(A);
2649
2650    if( nrows(V) != r )
2651    {
2652      ERROR("Sorry wrong mgrad-size of V: " + string(nrows(V)));
2653    }
2654  }
2655
2656  if( A == 0 )
2657  {
2658    intvec v; v[r] = 0;
2659    return (v);
2660  }
2661
2662  intvec m; m[r] = 0;
2663
2664  if( typeof(A) == "poly" )
2665  {
2666    intvec v = leadexp(A); //  v;
2667    m = M * v;
2668
2669    // We assume homogeneous input!
2670    return(m);
2671
2672    A = A - lead(A);
2673    while( size(A) > 0 )
2674    {
2675      v = leadexp(A); //  v;
2676      m = max( m, M * v, r ); // ????
2677      A = A - lead(A);
2678    }
2679
2680    return(m);
2681  }
2682
2683
2684  if( typeof(A) == "vector" )
2685  {
2686    intvec v;
2687    v = leadexp(A); //  v;
2688    m = intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]);
2689
2690    // We assume homogeneous input!
2691    return(m);
2692
2693    A = A - lead(A);
2694    while( size(A) > 0 )
2695    {
2696      v = leadexp(A); //  v;
2697
2698      // intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]);
2699
2700      m = max( m, intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]), r ); // ???
2701
2702      A = A - lead(A);
2703    }
2704
2705    return(m);
2706  }
2707
2708  int i, j; intvec d;
2709
2710  if( typeof(A) == "ideal" )
2711  {
2712    intmat G[ r ] [ ncols(A)];
2713    for( i = ncols(A); i > 0; i-- )
2714    {
2715      d = multiDeg( A[i] );
2716
2717      for( j = 1; j <= r; j++ ) // see ticket: 253
2718      {
2719        G[j, i] = d[j];
2720      }
2721    }
2722    return(G);
2723  }
2724
2725  if( typeof(A) == "module" )
2726  {
2727    intmat G[ r ] [ ncols(A)];
2728    vector v;
2729
2730    for( i = ncols(A); i > 0; i-- )
2731    {
2732      v = getGradedGenerator(A, i);
2733
2734      // G[1..r, i]
2735      d = multiDeg(v);
2736
2737      for( j = 1; j <= r; j++ ) // see ticket: 253
2738      {
2739        G[j, i] = d[j];
2740      }
2741
2742    }
2743
2744    return(G);
2745  }
2746
2747}
2748example
2749{
2750  "EXAMPLE:"; echo=2;
2751
2752  ring r = 0,(x, y), dp;
2753
2754  intmat A[2][2] = 1, 0, 0, 1;
2755  print(A);
2756
2757  intmat Ta[2][1] = 0, 3;
2758  print(Ta);
2759
2760  //   attrib(A, "gradingGroup", Ta); // to think about
2761
2762//  "poly:";
2763  setBaseMultigrading(A);
2764
2765
2766  multiDeg( x*x, A );
2767  multiDeg( y*y*y, A );
2768
2769  setBaseMultigrading(A, Ta);
2770
2771  multiDeg( x*x*y );
2772
2773  multiDeg( y*y*y*x );
2774
2775  multiDeg( x*y + x + 1 );
2776
2777  multiDegPartition(x*y + x + 1);
2778
2779  print ( multiDeg(0) );
2780  poly zero = 0;
2781  print ( multiDeg(zero) );
2782
2783//  "ideal:";
2784
2785  ideal I = y*x*x, x*y*y*y;
2786  print( multiDeg(I) );
2787
2788  print ( multiDeg(ideal(0)) );
2789  print ( multiDeg(ideal(0,0,0)) );
2790
2791//  "vectors:";
2792
2793  intmat B[2][2] = 0, 1, 1, 0;
2794  print(B);
2795
2796  multiDeg( setModuleGrading(y*y*y*gen(2), B ));
2797  multiDeg( setModuleGrading(x*x*gen(1), B ));
2798
2799
2800  vector V = x*gen(1) + y*gen(2);
2801  V = setModuleGrading(V, B);
2802  multiDeg( V );
2803
2804  vector v1 = setModuleGrading([0, 0, 0], B);
2805  print( multiDeg( v1 ) );
2806
2807  vector v2 = setModuleGrading([0], B);
2808  print( multiDeg( v2 ) );
2809
2810//  "module:";
2811
2812  module D = x*gen(1), y*gen(2);
2813  D;
2814  D = setModuleGrading(D, B);
2815  print( multiDeg( D ) );
2816
2817
2818  module DD = [0, 0],[0, 0, 0];
2819  DD = setModuleGrading(DD, B);
2820  print( multiDeg( DD ) );
2821
2822  module DDD = [0, 0];
2823  DDD = setModuleGrading(DDD, B);
2824  print( multiDeg( DDD ) );
2825
2826};
2827
2828
2829
2830
2831
2832/******************************************************/
2833proc multiDegPartition(def p)
2834"USAGE: multiDegPartition(def p), p polynomial/vector
2835RETURNS: an ideal/module consisting of multigraded-homogeneous parts of p
2836EXAMPLE: example multiDegPartition; shows an example
2837"
2838{ // TODO: What about an ideal or module???
2839
2840  if( typeof(p) == "poly" )
2841  {
2842    ideal I;
2843    poly mp, t, tt;
2844    intmat V;
2845  }
2846  else
2847  {
2848    if(  typeof(p) == "vector" )
2849    {
2850      module I;
2851      vector mp, t, tt;
2852      intmat V = getModuleGrading(p);
2853    }
2854    else
2855    {
2856      ERROR("Wrong ARGUMENT type!");
2857    }
2858  }
2859
2860  if( size(p) > 1)
2861  {
2862    intvec m;
2863
2864    while( p != 0 )
2865    {
2866      m = leadexp(p);
2867      mp = lead(p);
2868      p = p - lead(p);
2869      tt = p; t = 0;
2870
2871      while( size(tt) > 0 )
2872      {
2873        // TODO: we do not cache matrices (M,T,H,V), which remain the same :(
2874        // TODO: we need some low-level procedure with all these arguments...!
2875        if( equalMultiDeg( leadexp(tt), m, V  ) )
2876        {
2877          mp = mp + lead(tt); // "mp", mp;
2878        }
2879        else
2880        {
2881          t = t + lead(tt);  //  "t", t;
2882        }
2883
2884        tt = tt - lead(tt);
2885      }
2886
2887      I[size(I)+1] = mp;
2888
2889      p = t;
2890    }
2891  }
2892  else
2893  {
2894    I[1] = p; // single monom
2895  }
2896
2897  if( typeof(I) == "module" )
2898  {
2899    I = setModuleGrading(I, V);
2900  }
2901
2902  return (I);
2903}
2904example
2905{
2906  "EXAMPLE:"; echo=2;
2907
2908  ring r = 0,(x,y,z),dp;
2909
2910  intmat g[2][3]=
2911    1,0,1,
2912    0,1,1;
2913  intmat t[2][1]=
2914    -2,
2915    1;
2916
2917  setBaseMultigrading(g,t);
2918
2919  poly f = x10yz+x8y2z-x4z2+y5+x2y2-z2+x17z3-y6;
2920
2921  multiDegPartition(f);
2922
2923  vector v = xy*gen(1)-x3y2*gen(2)+x4y*gen(3);
2924  intmat B[2][3]=1,-1,-2,0,0,1;
2925  v = setModuleGrading(v,B);
2926  getModuleGrading(v);
2927
2928  multiDegPartition(v, B);
2929}
2930
2931
2932
2933/******************************************************/
2934static proc unitMatrix(int n)
2935{
2936  intmat A[n][n];
2937
2938  for( int i = n; i > 0; i-- )
2939  {
2940    A[i,i] = 1;
2941  }
2942
2943  return (A);
2944}
2945
2946
2947
2948/******************************************************/
2949static proc finestMDeg(def r)
2950"
2951USAGE: finestMDeg(r); ring r
2952RETURN: ring, r endowed with the finest multigrading
2953TODO: not yet...
2954"
2955{
2956  def save = basering;
2957  setring (r);
2958
2959  // in basering
2960      ideal I = ideal(basering);
2961
2962  int n = 0; int i; poly p;
2963  for( i = ncols(I); i > 0; i-- )
2964  {
2965    p = I[i];
2966    if( size(p) > 1 )
2967    {
2968      n = n + (size(p) - 1);
2969    }
2970    else
2971    {
2972      I[i] = 0;
2973    }
2974  }
2975
2976  int N = nvars(basering);
2977  intmat A = unitMatrix(N);
2978
2979
2980
2981  if( n > 0)
2982  {
2983
2984    intmat L[N][n];
2985    //  list L;
2986    int j = n;
2987
2988    for(  i = ncols(I); i > 0; i-- )
2989    {
2990      p = I[i];
2991
2992      if( size(p) > 1 )
2993      {
2994        intvec m0 = leadexp(p);
2995        p = p - lead(p);
2996
2997        while( size(p) > 0 )
2998        {
2999          L[ 1..N, j ] = leadexp(p) - m0;
3000          p = p - lead(p);
3001          j--;
3002        }
3003      }
3004    }
3005
3006    print(L);
3007    setBaseMultigrading(A, L);
3008  }
3009  else
3010  {
3011    setBaseMultigrading(A);
3012  }
3013
3014  //  ERROR("nope");
3015
3016  //  ring T = integer, (x), (C, dp);
3017
3018  setring(save);
3019  return (r);
3020}
3021example
3022{
3023  "EXAMPLE:"; echo=2;
3024
3025  ring r = 0,(x, y), dp;
3026  qring q  = std(x^2 - y);
3027
3028  finestMDeg(q);
3029
3030}
3031
3032
3033
3034
3035/******************************************************/
3036static proc newMap(map F, intmat Q, list #)
3037"
3038USAGE: newMap(F, Q[, P]); map F, intmat Q[, intmat P]
3039PURPOSE: endowe the map F with the integer matrices P [and Q]
3040"
3041{
3042  attrib(F, "Q", Q);
3043
3044  if( size(#) > 0 and typeof(#[1]) == "intmat" )
3045  {
3046    attrib(F, "P", #[1]);
3047  }
3048  return (F);
3049}
3050
3051/******************************************************/
3052static proc matrix2intmat( matrix M )
3053{
3054  execute( "intmat A[ "+ string(nrows(M)) + "]["+ string(ncols(M)) + "] = " + string(M) + ";" );
3055  return (A);
3056}
3057
3058
3059/******************************************************/
3060static proc leftKernelZ(intmat M)
3061"USAGE:  leftKernel(M);   M a matrix
3062RETURN:  module
3063PURPOSE: computes left kernel of matrix M (a module of all elements v such that vM=0)
3064EXAMPLE: example leftKernel; shows an example
3065"
3066{
3067  int @bf = 0;
3068  if( nameof(basering) != "basering" )
3069  {
3070    @bf = 1;
3071    def @save@ = basering;
3072  }
3073
3074  ring r = integer, (x), dp;
3075
3076
3077  //  basering;
3078  module N = matrix((M)); // transpose
3079  //  print(N);
3080
3081  def MM = modulo( N, std(0) ) ;
3082  //  print(MM);
3083
3084  intmat R = (  matrix2intmat( MM ) ); // transpose
3085
3086  if( @bf == 1 )
3087  {
3088    setring @save@;
3089  }
3090
3091  kill r;
3092  return( R );
3093}
3094example
3095{
3096  "EXAMPLE:"; echo=2;
3097
3098  ring r= 0,(x,y,z),dp;
3099  matrix M[3][1] = x,y,z;
3100  print(M);
3101  matrix L = leftKernel(M);
3102  print(L);
3103  // check:
3104  print(L*M);
3105};
3106
3107
3108
3109/******************************************************/
3110// the following is taken from "sing4ti2.lib" as we need 'hilbert' from 4ti2
3111
3112static proc hilbert4ti2intmat(intmat A, list #)
3113"USAGE:  hilbert4ti2(A[,i]);
3114@*       A=intmat
3115@*       i=int
3116ASSUME:  - A is a matrix with integer entries which describes the lattice
3117@*         as ker(A), if second argument is not present, and
3118@*         as the left image Im(A) = {zA : z \in ZZ^k}, if second argument is a positive integer
3119@*       - number of variables of basering equals number of columns of A
3120@*         (for ker(A)) resp. of rows of A (for Im(A))
3121CREATE:  temporary files sing4ti2.mat, sing4ti2.lat, sing4ti2.mar
3122@*       in the current directory (I/O files for communication with 4ti2)
3123NOTE:    input rules for 4ti2 also apply to input to this procedure
3124@*       hence ker(A)={x|Ax=0} and Im(A)={xA}
3125RETURN:  toric ideal specified by Hilbert basis thereof
3126EXAMPLE: example graver4ti2; shows an example
3127"
3128{
3129   if( system("sh","which hilbert 2> /dev/null 1> /dev/null") != 0 )
3130   {
3131     ERROR("Sorry: cannot find 'hilbert' command from 4ti2. Please install 4ti2!");
3132   }
3133
3134//--------------------------------------------------------------------------
3135// Initialization and Sanity Checks
3136//--------------------------------------------------------------------------
3137   int i,j;
3138   int nr=nrows(A);
3139   int nc=ncols(A);
3140   string fileending="mat";
3141   if (size(#)!=0)
3142   {
3143//--- default behaviour: use ker(A) as lattice
3144//--- if #[1]!=0 use Im(A) as lattice
3145      if(typeof(#[1])!="int")
3146      {
3147         ERROR("optional parameter needs to be integer value");
3148      }
3149      if(#[1]!=0)
3150      {
3151         fileending="lat";
3152      }
3153   }
3154//--- we should also be checking whether all entries are indeed integers
3155//--- or whether there are fractions, but in this case the error message
3156//--- of 4ti2 is printed directly
3157
3158//--------------------------------------------------------------------------
3159// preparing input file for 4ti2
3160//--------------------------------------------------------------------------
3161   link eing=":w sing4ti2."+fileending;
3162   string eingstring=string(nr)+" "+string(nc);
3163   write(eing,eingstring);
3164   for(i=1;i<=nr;i++)
3165   {
3166      kill eingstring;
3167      string eingstring;
3168      for(j=1;j<=nc;j++)
3169      {
3170        //          if(g(A[i,j])>0)||(char(basering)!=0)||(npars(basering)>0))
3171        //          {
3172        //             ERROR("Input to hilbert4ti2 needs to be a matrix with integer entries");
3173        //          }
3174        eingstring=eingstring+string(A[i,j])+" ";
3175      }
3176      write(eing, eingstring);
3177   }
3178   close(eing);
3179
3180//----------------------------------------------------------------------
3181// calling 4ti2 and converting output
3182// Singular's string is too clumsy for this, hence we first prepare
3183// using standard unix commands
3184//----------------------------------------------------------------------
3185
3186
3187   j=system("sh","hilbert -q -n sing4ti2"); ////////// be quiet + no loggin!!!
3188
3189   j=system("sh", "awk \'BEGIN{ORS=\",\";}{print $0;}\' sing4ti2.hil " +
3190                "| sed s/[\\\ \\\t\\\v\\\f]/,/g " +
3191                "| sed s/,+/,/g|sed s/,,/,/g " +
3192                "| sed s/,,/,/g " +
3193                "> sing4ti2.converted" );
3194
3195
3196//----------------------------------------------------------------------
3197// reading output of 4ti2
3198//----------------------------------------------------------------------
3199   link ausg=":r sing4ti2.converted";
3200//--- last entry ideal(0) is used to tie the list to the basering
3201//--- it will not be processed any further
3202
3203   string s = read(ausg);
3204
3205   if( defined(keepfiles) <= 0)
3206   {
3207      j=system("sh",("rm -f sing4ti2.hil sing4ti2.converted sing4ti2."+fileending));
3208   }
3209
3210   string ergstr = "intvec erglist = " + s + "0;";
3211   execute(ergstr);
3212
3213   //   print(erglist);
3214
3215   int Rnc = erglist[1];
3216   int Rnr = erglist[2];
3217
3218   intmat R[Rnr][Rnc];
3219
3220   int k = 3;
3221
3222   for(i=1;i<=Rnc;i++)
3223   {
3224     for(j=1;j<=Rnr;j++)
3225     {
3226       //       "i: ", i, ", j: ", j, ", v: ", erglist[k];
3227       R[j, i] = erglist[k];
3228       k = k + 1;
3229     }
3230   }
3231
3232
3233
3234   return (R);
3235//--- get rid of leading entry 0;
3236//   toric=toric[2..ncols(toric)];
3237//   return(toric);
3238}
3239// A nice example here is the 3x3 Magic Squares
3240example
3241{
3242  "EXAMPLE:"; echo=2;
3243
3244   ring r=0,(x1,x2,x3,x4,x5,x6,x7,x8,x9),dp;
3245   intmat M[7][9]=
3246      1, 1, 1, -1, -1, -1, 0, 0, 0,
3247      1, 1, 1,  0,  0,  0,-1,-1,-1,
3248      0, 1, 1, -1,  0,  0,-1, 0, 0,
3249      1, 0, 1,  0, -1,  0, 0,-1, 0,
3250      1, 1, 0,  0,  0, -1, 0, 0,-1,
3251      0, 1, 1,  0, -1,  0, 0, 0,-1,
3252      1, 1, 0,  0, -1,  0,-1, 0, 0;
3253   hilbert4ti2intmat(M);
3254   hermiteNormalForm(M);
3255}
3256
3257/////////////////////////////////////////////////////////////////////////////
3258static proc getMonomByExponent(intvec exp)
3259{
3260  int n = nvars(basering);
3261
3262  if( nrows(exp) < n )
3263  {
3264    n = nrows(exp);
3265  }
3266
3267  poly m = 1; int e;
3268
3269  for( int i = 1; i <= n; i++ )
3270  {
3271    e = exp[i];
3272    if( e < 0 )
3273    {
3274      ERROR("Negative exponent!!!");
3275    }
3276
3277    m = m * (var(i)^e);
3278  }
3279
3280  return (m);
3281
3282}
3283
3284/******************************************************/
3285proc multiDegBasis(intvec d)
3286"USAGE: multidegree d
3287ASSUME: current ring is multigraded, monomial ordering is global
3288PURPOSE: compute all monomials of multidegree d
3289EXAMPLE: example multiDegBasis; shows an example
3290"
3291{
3292  def R = basering;  // setring R;
3293
3294  intmat M = getVariableWeights(R);
3295
3296  //  print(M);
3297
3298  int nr = nrows(M);
3299  int nc = ncols(M);
3300
3301  intmat A[nr][nc+1];
3302  A[1..nr, 1..nc] = M[1..nr, 1..nc];
3303  //typeof(A[1..nr, nc+1]);
3304  if( nr==1)
3305  {
3306    A[1..nr, nc+1]=-d[1];
3307  }
3308  else
3309  {
3310    A[1..nr, nc+1] = -d;
3311  }
3312
3313  intmat T = getLattice(R);
3314
3315  if( isFreeRepresented() )
3316  {
3317    intmat B = hilbert4ti2intmat(A);
3318
3319    //      matrix B = unitMatrix(nrows(T));
3320  }
3321  else
3322  {
3323    int n = ncols(T);
3324
3325    nc = ncols(A);
3326
3327    intmat AA[nr][nc + 2 * n];
3328    AA[1..nr, 1.. nc] = A[1..nr, 1.. nc];
3329    AA[1..nr, nc + (1.. n)] = T[1..nr, 1.. n];
3330    AA[1..nr, nc + n + (1.. n)] = -T[1..nr, 1.. n];
3331
3332
3333    //      print ( AA );
3334
3335    intmat K = leftKernelZ(( AA ) ); //
3336
3337    //      print(K);
3338
3339    intmat KK[nc][ncols(K)] = K[ 1.. nc, 1.. ncols(K) ];
3340
3341    //      print(KK);
3342    //      "!";
3343
3344    intmat B = hilbert4ti2intmat(transpose(KK), 1);
3345
3346    //      "!";      print(B);
3347
3348  }
3349
3350
3351  //  print(A);
3352
3353
3354
3355  int i;
3356  int nnr = nrows(B);
3357  int nnc = ncols(B);
3358  ideal I, J;
3359  if(nnc==0){
3360    I=0;
3361    return(I);
3362  }
3363  I[nnc] = 0;
3364  J[nnc] = 0;
3365
3366  for( i = 1; i <= nnc; i++ )
3367  {
3368    //      "i: ", i;    B[nnr, i];
3369
3370    if( B[nnr, i] == 1)
3371    {
3372      // intvec(B[1..nnr-1, i]);
3373      I[i] = getMonomByExponent(intvec(B[1..nnr-1, i]));
3374    }
3375    else
3376    {
3377      if( B[nnr, i] == 0)
3378      {
3379        // intvec(B[1..nnr-1, i]);
3380        J[i] = getMonomByExponent(intvec(B[1..nnr-1, i]));
3381      }
3382    }
3383    //      I[i];
3384  }
3385
3386  ideal Q = (ideal(basering));
3387
3388  if ( size(Q) > 0 )
3389  {
3390    I = NF( I, lead(Q) );
3391    J = NF( J, lead(Q) ); // Global ordering!!!
3392  }
3393
3394  I = simplify(I, 2); // d
3395  J = simplify(J, 2); // d
3396
3397  attrib(I, "ZeroPart", J);
3398
3399  return (I);
3400
3401  //  setring ;
3402}
3403example
3404{
3405  "EXAMPLE:"; echo=2;
3406
3407  ring R = 0, (x, y), dp;
3408
3409  intmat g1[2][2]=1,0,0,1;
3410  intmat l[2][1]=2,0;
3411  intmat g2[2][2]=1,1,1,1;
3412  intvec v1=4,0;
3413  intvec v2=4,4;
3414
3415  intmat g3[1][2]=1,1;
3416  setBaseMultigrading(g3);
3417  intvec v3=4:1;
3418  v3;
3419  multiDegBasis(v3);
3420
3421  setBaseMultigrading(g1,l);
3422  multiDegBasis(v1);
3423  setBaseMultigrading(g2);
3424  multiDegBasis(v2);
3425
3426  intmat M[2][2] = 1, -1, -1, 1;
3427  intvec d = -2, 2;
3428
3429  setBaseMultigrading(M);
3430
3431  multiDegBasis(d);
3432  attrib(_, "ZeroPart");
3433
3434  kill R, M, d;
3435  ring R = 0, (x, y, z), dp;
3436
3437  intmat M[2][3] = 1, -2, 1,     1, 1, 0;
3438
3439  intmat L[2][1] = 0, 2;
3440
3441  intvec d = 4, 1;
3442
3443  setBaseMultigrading(M, L);
3444
3445  multiDegBasis(d);
3446  attrib(_, "ZeroPart");
3447
3448
3449  kill R, M, d;
3450
3451  ring R = 0, (x, y, z), dp;
3452  qring Q = std(ideal( y^6+ x*y^3*z-x^2*z^2 ));
3453
3454
3455  intmat M[2][3] = 1, 1, 2,     2, 1, 1;
3456  //  intmat T[2][1] = 0, 2;
3457
3458  setBaseMultigrading(M); // BUG????
3459
3460  intvec d = 6, 6;
3461  multiDegBasis(d);
3462  attrib(_, "ZeroPart");
3463
3464
3465
3466  kill R, Q, M, d;
3467  ring R = 0, (x, y, z), dp;
3468  qring Q = std(ideal( x*z^3 - y *z^6, x*y*- x^4*y^2 ));
3469
3470
3471  intmat M[2][3] = 1, -2, 1,     1, 1, 0;
3472  intmat T[2][1] = 0, 2;
3473
3474  intvec d = 4, 1;
3475
3476  setBaseMultigrading(M, T); // BUG????
3477
3478  multiDegBasis(d);
3479  attrib(_, "ZeroPart");
3480}
3481
3482
3483proc multiDegSyzygy(def I)
3484"USAGE: multiDegSyzygy(I); I is a ideal or a module
3485PURPOSE: computes the multigraded syzygy module of I
3486RETURNS: module, the syzygy module of I
3487NOTE: generators of I must be multigraded homogeneous
3488EXAMPLE: example multiDegSyzygy; shows an example
3489"
3490{
3491  if( isHomogeneous(I, "checkGens") == 0)
3492  {
3493    ERROR ("Sorry: inhomogeneous input!");
3494  }
3495  module S = syz(I);
3496  S = setModuleGrading(S, multiDeg(I));
3497  return (S);
3498}
3499example
3500{
3501  "EXAMPLE:"; echo=2;
3502
3503  ring r = 0,(x,y,z,w),dp;
3504  intmat MM[2][4]=
3505    1,1,1,1,
3506    0,1,3,4;
3507  setBaseMultigrading(MM);
3508  module M = ideal(  xw-yz, x2z-y3, xz2-y2w, yw2-z3);
3509
3510
3511  intmat v[2][nrows(M)]=
3512    1,
3513    0;
3514
3515  M = setModuleGrading(M, v);
3516
3517  isHomogeneous(M);
3518  "Multidegrees: "; print(multiDeg(M));
3519  // Let's compute syzygies!
3520  def S = multiDegSyzygy(M); S;
3521  "Module Units Multigrading: "; print( getModuleGrading(S) );
3522  "Multidegrees: "; print(multiDeg(S));
3523
3524  isHomogeneous(S);
3525}
3526
3527
3528
3529proc multiDegModulo(def I, def J)
3530"USAGE: multiDegModulo(I); I, J are ideals or modules
3531PURPOSE: computes the multigraded 'modulo' module of I and J
3532RETURNS: module, see 'modulo' command
3533NOTE: I and J should have the same multigrading, and their
3534generators must be multigraded homogeneous
3535EXAMPLE: example multiDegModulo; shows an example
3536"
3537{
3538  if( (isHomogeneous(I, "checkGens") == 0) or (isHomogeneous(J, "checkGens") == 0) )
3539  {
3540    ERROR ("Sorry: inhomogeneous input!");
3541  }
3542  module K = modulo(I, J);
3543  K = setModuleGrading(K, multiDeg(I));
3544  return (K);
3545}
3546example
3547{
3548  "EXAMPLE:"; echo=2;
3549
3550  ring r = 0,(x,y,z),dp;
3551  intmat MM[2][3]=
3552    -1,1,1,
3553     0,1,3;
3554  setBaseMultigrading(MM);
3555
3556  ideal h1 = x, y, z;
3557  ideal h2 = x;
3558
3559  "Multidegrees: "; print(multiDeg(h1));
3560
3561  // Let's compute modulo(h1, h2):
3562  def K = multiDegModulo(h1, h2); K;
3563
3564  "Module Units Multigrading: "; print( getModuleGrading(K) );
3565  "Multidegrees: "; print(multiDeg(K));
3566
3567  isHomogeneous(K);
3568}
3569
3570
3571proc multiDegGroebner(def I)
3572"USAGE: multiDegGroebner(I); I is a poly/vector/ideal/module
3573PURPOSE: computes the multigraded standard/groebner basis of I
3574NOTE: I must be multigraded homogeneous
3575RETURNS: ideal/module, the computed basis
3576EXAMPLE: example multiDegGroebner; shows an example
3577"
3578{
3579  if( isHomogeneous(I) == 0)
3580  {
3581    ERROR ("Sorry: inhomogeneous input!");
3582  }
3583
3584  def S = groebner(I);
3585
3586  if( typeof(I) == "module" or typeof(I) == "vector" )
3587  {
3588    S = setModuleGrading(S, getModuleGrading(I));
3589  }
3590
3591  return(S);
3592}
3593example
3594{
3595  "EXAMPLE:"; echo=2;
3596
3597  ring r = 0,(x,y,z,w),dp;
3598
3599  intmat MM[2][4]=
3600    1,1,1,1,
3601    0,1,3,4;
3602
3603  setBaseMultigrading(MM);
3604
3605
3606  module M = ideal(  xw-yz, x2z-y3, xz2-y2w, yw2-z3);
3607
3608
3609  intmat v[2][nrows(M)]=
3610    1,
3611    0;
3612
3613  M = setModuleGrading(M, v);
3614
3615
3616  /////////////////////////////////////////////////////////////////////////////
3617  // GB:
3618  M = multiDegGroebner(M); M;
3619  "Module Units Multigrading: "; print( getModuleGrading(M) );
3620  "Multidegrees: "; print(multiDeg(M));
3621
3622  isHomogeneous(M);
3623
3624  /////////////////////////////////////////////////////////////////////////////
3625  // Let's compute Syzygy!
3626  def S = multiDegSyzygy(M); S;
3627  "Module Units Multigrading: "; print( getModuleGrading(S) );
3628  "Multidegrees: "; print(multiDeg(S));
3629
3630  isHomogeneous(S);
3631
3632  /////////////////////////////////////////////////////////////////////////////
3633  // GB:
3634  S = multiDegGroebner(S); S;
3635  "Module Units Multigrading: "; print( getModuleGrading(S) );
3636  "Multidegrees: "; print(multiDeg(S));
3637
3638  isHomogeneous(S);
3639}
3640
3641
3642/******************************************************/
3643proc multiDegResolution(def I, int ll, list #)
3644"USAGE: multiDegResolution(I,l,[f]); I is poly/vector/ideal/module; l,f are integers
3645PURPOSE: computes the multigraded resolution of I of the length l,
3646or the whole resolution if l is zero. Returns minimal resolution if an optional
3647argument 1 is supplied
3648NOTE: input must have multigraded-homogeneous generators.
3649The returned list is truncated beginning with the first zero differential.
3650RETURNS: list, the computed resolution
3651EXAMPLE: example multiDegResolution; shows an example
3652"
3653{
3654  if( isHomogeneous(I, "checkGens") == 0)
3655  {
3656    ERROR ("Sorry: inhomogeneous input!");
3657  }
3658
3659  def R = res(I, ll, #); list L = R; int l = size(L);
3660  def V = getModuleGrading(I);
3661  if( (typeof(I) == "module") or (typeof(I) == "vector") )
3662  {
3663    L[1] = setModuleGrading(L[1], V);
3664  }
3665
3666  int i;
3667  for( i = 2; i <= l; i++ )
3668  {
3669    if( size(L[i]) > 0 )
3670    {
3671      L[i] = setModuleGrading( L[i], multiDeg(L[i-1]) );
3672    } else
3673    {
3674      return (L[1..(i-1)]);
3675    }
3676  }
3677
3678  return (L);
3679
3680
3681}
3682example
3683{
3684  "EXAMPLE:"; echo=2;
3685
3686  ring r = 0,(x,y,z,w),dp;
3687
3688  intmat M[2][4]=
3689    1,1,1,1,
3690    0,1,3,4;
3691
3692  setBaseMultigrading(M);
3693
3694
3695  module m= ideal(  xw-yz, x2z-y3, xz2-y2w, yw2-z3);
3696
3697  isHomogeneous(ideal(  xw-yz, x2z-y3, xz2-y2w, yw2-z3), "checkGens");
3698
3699  ideal A = xw-yz, x2z-y3, xz2-y2w, yw2-z3;
3700
3701  int j;
3702
3703  for(j=1; j<=ncols(A); j++)
3704  {
3705    multiDegPartition(A[j]);
3706  }
3707
3708  intmat v[2][1]=
3709    1,
3710    0;
3711
3712  m = setModuleGrading(m, v);
3713
3714  // Let's compute Syzygy!
3715  def S = multiDegSyzygy(m); S;
3716  "Module Units Multigrading: "; print( getModuleGrading(S) );
3717  "Multidegrees: "; print(multiDeg(S));
3718
3719  /////////////////////////////////////////////////////////////////////////////
3720
3721  S = multiDegGroebner(S); S;
3722  "Module Units Multigrading: "; print( getModuleGrading(S) );
3723  "Multidegrees: "; print(multiDeg(S));
3724
3725  /////////////////////////////////////////////////////////////////////////////
3726
3727  def L = multiDegResolution(m, 0, 1);
3728
3729  for( j =1; j<=size(L); j++)
3730  {
3731    "----------------------------------- ", j, " -----------------------------";
3732    L[j];
3733    "Module Multigrading: "; print( getModuleGrading(L[j]) );
3734    "Multigrading: "; print(multiDeg(L[j]));
3735  }
3736
3737  /////////////////////////////////////////////////////////////////////////////
3738
3739  L = multiDegResolution(maxideal(1), 0, 1);
3740
3741  for( j =1; j<=size(L); j++)
3742  {
3743    "----------------------------------- ", j, " -----------------------------";
3744    L[j];
3745    "Module Multigrading: "; print( getModuleGrading(L[j]) );
3746    "Multigrading: "; print(multiDeg(L[j]));
3747  }
3748
3749  kill v;
3750
3751
3752  def h = hilbertSeries(m);
3753  setring h;
3754
3755  numerator1;
3756  factorize(numerator1);
3757
3758  denominator1;
3759  factorize(denominator1);
3760
3761  numerator2;
3762  factorize(numerator2);
3763
3764  denominator2;
3765  factorize(denominator2);
3766}
3767
3768/******************************************************/
3769proc hilbertSeries(def I)
3770"USAGE: hilbertSeries(I); I is poly/vector/ideal/module
3771PURPOSE: computes the multigraded Hilbert Series of I
3772NOTE: input must have multigraded-homogeneous generators.
3773Multigrading should be positive.
3774RETURNS: a ring in variables t_(i), s_(i), with polynomials
3775numerator1 and denominator1 and mutually prime numerator2
3776and denominator2, quotients of which give the series.
3777EXAMPLE: example hilbertSeries; shows an example
3778"
3779{
3780
3781  if( !isFreeRepresented() )
3782  {
3783    "Things might happen, since we are not  free.";
3784    //ERROR("SORRY: ONLY TORSION-FREE CASE (POSITIVE GRADING)");
3785  }
3786
3787  int i, j, k, v;
3788
3789  intmat M = getVariableWeights();
3790
3791  int cc = ncols(M);
3792  int n = nrows(M);
3793
3794  if( n == 0 )
3795  {
3796    ERROR("Error: wrong Variable Weights?");
3797  }
3798
3799  list RES = multiDegResolution(I,0,1);
3800
3801  int l = size(RES);
3802
3803  list L; L[l + 1] = 0;
3804
3805  if(typeof(I) == "ideal")
3806  {
3807    intmat zeros[n][1];
3808    L[1] = zeros;
3809  }
3810  else
3811  {
3812    L[1] = getModuleGrading(RES[1]);
3813  }
3814
3815  for( j = 1; j <= l; j++)
3816  {
3817    L[j + 1] = multiDeg(RES[j]);
3818  }
3819
3820  l++;
3821
3822  ring R = 0,(t_(1..n),s_(1..n)),dp;
3823
3824  ideal units;
3825  for( i=n; i>=1; i--)
3826  {
3827    units[i] = (var(i) * var(n + i) - 1);
3828  }
3829
3830  qring Q = std(units);
3831
3832  // TODO: should not it be a quotient ring depending on Torsion???
3833  // I am not sure about what to do in the torsion case, but since
3834  // we want to evaluate the polynomial at certain points to get
3835  // a dimension we need uniqueness for this. I think we would lose
3836  // this uniqueness if switching to this torsion ring.
3837
3838  poly monom, summand, numerator;
3839  poly denominator = 1;
3840
3841  for( i = 1; i <= cc; i++)
3842  {
3843    monom = 1;
3844    for( k = 1; k <= n; k++)
3845    {
3846      v = M[k,i];
3847
3848      if(v >= 0)
3849      {
3850        monom = monom * (var(k)^(v));
3851      }
3852      else
3853      {
3854        monom = monom * (var(n+k)^(-v));
3855      }
3856    }
3857
3858    if( monom == 1)
3859    {
3860      ERROR("Multigrading not positive.");
3861    }
3862
3863    denominator = denominator * (1 - monom);
3864  }
3865
3866  for( j = 1; j<= l; j++)
3867  {
3868    summand = 0;
3869    M = L[j];
3870
3871    for( i = 1; i <= ncols(M); i++)
3872    {
3873      monom = 1;
3874      for( k = 1; k <= n; k++)
3875      {
3876        v = M[k,i];
3877        if( v > 0 )
3878        {
3879          monom = monom * (var(k)^v);
3880        }
3881        else
3882        {
3883          monom = monom * (var(n+k)^(-v));
3884        }
3885      }
3886      summand = summand + monom;
3887    }
3888    numerator = numerator - (-1)^j * summand;
3889  }
3890
3891  if( denominator == 0 )
3892  {
3893    ERROR("Multigrading not positive.");
3894  }
3895
3896  poly denominator1 = denominator;
3897  poly numerator1 = numerator;
3898
3899  export denominator1;
3900  export numerator1;
3901
3902  if( numerator != 0 )
3903  {
3904    poly d = gcd(denominator, numerator);
3905
3906    poly denominator2 = denominator/d;
3907    poly numerator2 = numerator/d;
3908
3909    if( gcd(denominator2, numerator2) != 1 )
3910    {
3911      ERROR("Sorry: gcd should be 1 (after dividing out gcd)! Something went wrong!");
3912    }
3913  }
3914  else
3915  {
3916    poly denominator2 = denominator;
3917    poly numerator2 = numerator;
3918  }
3919
3920
3921  export denominator2;
3922  export numerator2;
3923
3924  " ------------ ";
3925  "This proc returns a ring with polynomials called 'numerator1/2' and 'denominator1/2'!";
3926  "They represent the first and the second Hilbert Series.";
3927  "The s_(i)-variables are defined to be the inverse of the t_(i)-variables.";
3928  " ------------ ";
3929
3930  return(Q);
3931}
3932example
3933{
3934  "EXAMPLE:"; echo=2;
3935
3936  ring r = 0,(x,y,z,w),dp;
3937  intmat g[2][4]=
3938    1,1,1,1,
3939    0,1,3,4;
3940  setBaseMultigrading(g);
3941
3942  module M = ideal(xw-yz, x2z-y3, xz2-y2w, yw2-z3);
3943  intmat V[2][1]=
3944    1,
3945    0;
3946
3947  M = setModuleGrading(M, V);
3948
3949  def h = hilbertSeries(M); setring h;
3950
3951  factorize(numerator2);
3952  factorize(denominator2);
3953
3954  kill g, h; setring r;
3955
3956  intmat g[2][4]=
3957    1,2,3,4,
3958    0,0,5,8;
3959
3960  setBaseMultigrading(g);
3961
3962  ideal I = x^2, y, z^3;
3963  I = std(I);
3964  def L = multiDegResolution(I, 0, 1);
3965
3966  for( int j = 1; j<=size(L); j++)
3967  {
3968    "----------------------------------- ", j, " -----------------------------";
3969    L[j];
3970    "Module Multigrading: "; print( getModuleGrading(L[j]) );
3971    "Multigrading: "; print(multiDeg(L[j]));
3972  }
3973
3974  multiDeg(I);
3975  def h = hilbertSeries(I); setring h;
3976
3977  factorize(numerator2);
3978  factorize(denominator2);
3979
3980  kill r, h, g, V;
3981  ////////////////////////////////////////////////
3982  ring R = 0,(x,y,z),dp;
3983  intmat W[2][3] =
3984     1,1, 1,
3985     0,0,-1;
3986  setBaseMultigrading(W);
3987  ideal I = x3y,yz2,y2z,z4;
3988
3989  def h = hilbertSeries(I); setring h;
3990
3991  factorize(numerator2);
3992  factorize(denominator2);
3993
3994  kill R, W, h;
3995  ////////////////////////////////////////////////
3996  ring R = 0,(x,y,z,a,b,c),dp;
3997  intmat W[2][6] =
3998     1,1, 1,1,1,1,
3999     0,0,-1,0,0,0;
4000  setBaseMultigrading(W);
4001  ideal I = x3y,yz2,y2z,z4;
4002
4003  def h = hilbertSeries(I); setring h;
4004
4005  factorize(numerator2);
4006  factorize(denominator2);
4007
4008  kill R, W, h;
4009  ////////////////////////////////////////////////
4010  // This is example 5.3.9. from Robbianos book.
4011
4012  ring R = 0,(x,y,z,w),dp;
4013  intmat W[1][4] =
4014     1,1, 1,1;
4015  setBaseMultigrading(W);
4016  ideal I = z3,y3zw2,x2y4w2xyz2;
4017
4018  hilb(std(I));
4019
4020  def h = hilbertSeries(I); setring h;
4021
4022  numerator1;
4023  denominator1;
4024
4025  factorize(numerator2);
4026  factorize(denominator2);
4027
4028
4029  kill h;
4030  ////////////////////////////////////////////////
4031  setring R;
4032
4033  ideal I2 = x2,y2,z2; I2;
4034
4035  hilb(std(I2));
4036
4037  def h = hilbertSeries(I2); setring h;
4038
4039  numerator1;
4040  denominator1;
4041
4042
4043  kill h;
4044  ////////////////////////////////////////////////
4045  setring R;
4046
4047  W = 2,2,2,2;
4048
4049  setBaseMultigrading(W);
4050
4051  getVariableWeights();
4052
4053  intvec w = 2,2,2,2;
4054
4055  hilb(std(I2), 1, w);
4056
4057  kill w;
4058
4059
4060  def h = hilbertSeries(I2); setring h;
4061
4062
4063  numerator1; denominator1;
4064  kill h;
4065
4066
4067  kill R, W;
4068
4069  ////////////////////////////////////////////////
4070  ring R = 0,(x),dp;
4071  intmat W[1][1] =
4072     1;
4073  setBaseMultigrading(W);
4074
4075  ideal I;
4076
4077  I = 1; I;
4078
4079  hilb(std(I));
4080
4081  def h = hilbertSeries(I); setring h;
4082
4083  numerator1; denominator1;
4084
4085  kill h;
4086  ////////////////////////////////////////////////
4087  setring R;
4088
4089  I = x; I;
4090
4091  hilb(std(I));
4092
4093  def h = hilbertSeries(I); setring h;
4094
4095  numerator1; denominator1;
4096
4097  kill h;
4098  ////////////////////////////////////////////////
4099  setring R;
4100
4101  I = x^5; I;
4102
4103  hilb(std(I));
4104  hilb(std(I), 1);
4105
4106  def h = hilbertSeries(I); setring h;
4107
4108  numerator1; denominator1;
4109
4110
4111  kill h;
4112  ////////////////////////////////////////////////
4113  setring R;
4114
4115  I = x^10; I;
4116
4117  hilb(std(I));
4118
4119  def h = hilbertSeries(I); setring h;
4120
4121  numerator1; denominator1;
4122
4123  kill h;
4124  ////////////////////////////////////////////////
4125  setring R;
4126
4127  module M = 1;
4128
4129  M = setModuleGrading(M, W);
4130
4131
4132  hilb(std(M));
4133
4134  def h = hilbertSeries(M); setring h;
4135
4136  numerator1; denominator1;
4137
4138  kill h;
4139  ////////////////////////////////////////////////
4140  setring R;
4141
4142  kill M; module M = x^5*gen(1);
4143//  intmat V[1][3] = 0; // TODO: this would lead to a wrong result!!!?
4144  intmat V[1][1] = 0; // all gen(i) of degree 0!
4145
4146  M = setModuleGrading(M, V);
4147
4148  hilb(std(M));
4149
4150  def h = hilbertSeries(M); setring h;
4151
4152  numerator1; denominator1;
4153
4154  kill h;
4155  ////////////////////////////////////////////////
4156  setring R;
4157
4158  module N = x^5*gen(3);
4159
4160  kill V;
4161
4162  intmat V[1][3] = 0; // all gen(i) of degree 0!
4163
4164  N = setModuleGrading(N, V);
4165
4166  hilb(std(N));
4167
4168  def h = hilbertSeries(N); setring h;
4169
4170  numerator1; denominator1;
4171
4172  kill h;
4173  ////////////////////////////////////////////////
4174  setring R;
4175
4176
4177  module S = M + N;
4178
4179  S = setModuleGrading(S, V);
4180
4181  hilb(std(S));
4182
4183  def h = hilbertSeries(S); setring h;
4184
4185  numerator1; denominator1;
4186
4187  kill h;
4188
4189  kill V;
4190  kill R, W;
4191
4192}
4193
4194static proc evalHilbertSeries(def h, intvec v)
4195"
4196   TODO
4197   evaluate hilbert series h by substibuting v[i] for t_(i) (1/v[i] for s_(i))
4198  return: int (h(v))
4199"
4200{
4201  if( 2*size(v) != nvars(h) )
4202  {
4203    ERROR("Wrong input/size!");
4204  }
4205
4206  setring h;
4207
4208  if( defined(numerator2) and defined(denominator2) )
4209  {
4210    poly n = numerator2; poly d = denominator2;
4211  } else
4212  {
4213    poly n = numerator1; poly d = denominator1;
4214  }
4215
4216  int N = size(v);
4217  int i; number k;
4218  ideal V;
4219
4220  for( i = N; i > 0; i -- )
4221  {
4222    k = v[i];
4223    V[i] = var(i) - k;
4224  }
4225
4226  V = groebner(V);
4227
4228  n = NF(n, V);
4229  d = NF(d, V);
4230
4231  n;
4232  d;
4233
4234  if( d == 0 )
4235  {
4236    ERROR("Sorry: denominator is zero!");
4237  }
4238
4239  if( n == 0 )
4240  {
4241    return (0);
4242  }
4243
4244  poly g = gcd(n, d);
4245
4246  if( g != leadcoef(g) )
4247  {
4248    n = n / g;
4249    d = d / g;
4250  }
4251
4252  n;
4253  d;
4254
4255
4256  for( i = N; i > 0; i -- )
4257  {
4258    "i: ", i;
4259    n;
4260    d;
4261
4262    k = v[i];
4263    k;
4264
4265    n = subst(n, var(i), k);
4266    d = subst(d, var(i), k);
4267
4268    if( k != 0 )
4269    {
4270      k = 1/k;
4271      n = subst(n, var(N+i), k);
4272      d = subst(d, var(N+i), k);
4273    }
4274  }
4275
4276  n;
4277  d;
4278
4279  if( d == 0 )
4280  {
4281    ERROR("Sorry: denominator is zero!");
4282  }
4283
4284  if( n == 0 )
4285  {
4286    return (0);
4287  }
4288
4289  poly g = gcd(n, d);
4290
4291  if( g != leadcoef(g) )
4292  {
4293    n = n / g;
4294    d = d / g;
4295  }
4296
4297  n;
4298  d;
4299
4300  if( n != leadcoef(n) || d != leadcoef(d) )
4301  {
4302    ERROR("Sorry cannot completely evaluate. Partial result: (" + string(n) + ")/(" + string(d) + ")");
4303  }
4304
4305  n;
4306  d;
4307
4308  return (leadcoef(n)/leadcoef(d));
4309}
4310example
4311{
4312  "EXAMPLE:"; echo=2;
4313
4314  // TODO!
4315
4316}
4317
4318
4319proc isPositive()
4320"USAGE: isPositive()
4321PURPOSE: Computes whether the multigrading of the ring is positive.
4322For computation theorem 8.6 of the Miller/Sturmfels book is used.
4323RETURNS: true if the multigrading is positive
4324EXAMPLE: example isPositive; shows an example
4325"
4326{
4327ideal I = multiDegBasis(0);
4328ideal J = attrib(I,"ZeroPart");
4329/*
4330I am not quite sure what this ZeroPart is anymore. I thought it
4331should contain all monomials of degree 0, but then apparently 1 should
4332be contained. It makes sense to exclude 1, but was this also the intention?
4333*/
4334return(J==0);
4335}
4336example
4337{
4338  echo = 2; printlevel = 3;
4339  ring r = 0,(x,y),dp;
4340  intmat A[1][2]=-1,1;
4341  setBaseMultigrading(A);
4342  isPositive();
4343
4344  intmat B[1][2]=1,1;
4345  setBaseMultigrading(B);
4346  isPositive(B);
4347}
4348
4349///////////////////////////////////////////////////////////////////////////////
4350// testing for consistency of the library:
4351proc testMultigradingLib ()
4352{
4353  example setBaseMultigrading;
4354  example setModuleGrading;
4355
4356  example getVariableWeights;
4357  example getLattice;
4358  example getGradingGroup;
4359  example getModuleGrading;
4360
4361
4362  example multiDeg;
4363  example multiDegPartition;
4364
4365
4366  example hermiteNormalForm;
4367  example isHomogeneous;
4368  example isTorsionFree;
4369  example pushForward;
4370  example defineHomogeneous;
4371
4372  example equalMultiDeg;
4373  example isZeroElement;
4374
4375  example multiDegResolution;
4376
4377  "// ******************* example hilbertSeries ************************//";
4378  example hilbertSeries;
4379
4380
4381// example multiDegBasis; // needs 4ti2!
4382
4383  "The End!";
4384}
4385
4386
4387static proc multiDegTruncate(def M, intvec md)
4388{
4389  "d: ";
4390  print(md);
4391
4392  "M: ";
4393  module LL = M; // + L for d+1
4394  LL;
4395  print(multiDeg(LL));
4396
4397
4398  intmat V = getModuleGrading(M);
4399  intvec vi;
4400  int s = nrows(M);
4401  int r = nrows(V);
4402  int i;
4403  module L; def B;
4404  for (i=s; i>0; i--)
4405  {
4406    "comp: ", i;
4407    vi = V[1..r, i];
4408    "v[i]: "; vi;
4409
4410    B = multiDegBasis(md - vi); // ZeroPart is always the same...
4411    "B: "; B;
4412
4413    L = L, B*gen(i);
4414  }
4415  L = simplify(L, 2);
4416  L = setModuleGrading(L,V);
4417
4418  "L: "; L;
4419  print(multiDeg(L));
4420
4421  L = multiDegModulo(L, LL);
4422  L = multiDegGroebner(L);
4423//  L = minbase(prune(L));
4424
4425  "??????????";
4426  print(L);
4427  print(multiDeg(L));
4428
4429  V = getModuleGrading(L);
4430
4431  // take out other degrees
4432  for(i = ncols(L); i > 0; i-- )
4433  {
4434    if( !equalMultiDeg( multiDeg(getGradedGenerator(L, i)), md ) )
4435    {
4436      L[i] = 0;
4437    }
4438  }
4439
4440  L = simplify(L, 2);
4441  L = setModuleGrading(L, V);
4442  print(L);
4443  print(multiDeg(L));
4444
4445  return(L);
4446}
4447example
4448{
4449  "EXAMPLE:"; echo=2;
4450
4451  // TODO!
4452  ring r = 32003, (x,y), dp;
4453
4454  intmat M[2][2] =
4455    1, 0,
4456    0, 1;
4457
4458  setBaseMultigrading(M);
4459
4460  intmat V[2][1] =
4461    0,
4462    0;
4463
4464  "X:";
4465  module h1 = x;
4466  h1 = setModuleGrading(h1, V);
4467  multiDegTruncate(h1, multiDeg(x));
4468  multiDegTruncate(h1, multiDeg(y));
4469
4470  "XY:";
4471  module h2 = ideal(x, y);
4472  h2 = setModuleGrading(h2, V);
4473  multiDegTruncate(h2, multiDeg(x));
4474  multiDegTruncate(h2, multiDeg(y));
4475  multiDegTruncate(h2, multiDeg(xy));
4476}
4477
4478
4479/******************************************************/
4480/* Some functions on lattices.
4481TODO Tuebingen: - add functionality (see wiki) and
4482- adjust them to work for groups as well.*/
4483/******************************************************/
4484
4485
4486
4487/******************************************************/
4488proc imageLattice(intmat Q, intmat L)
4489"USAGE: imageLattice(Q,L); Q and L are of type intmat
4490PURPOSE: compute an integral basis for the image of the
4491lattice L under the homomorphism of lattices Q.
4492RETURN: intmat
4493EXAMPLE: example imageLattice; shows an example
4494"
4495{
4496  intmat Mul = Q*L;
4497  intmat LL = latticeBasis(Mul);
4498
4499  return(LL);
4500}
4501example
4502{
4503  "EXAMPLE:"; echo=2;
4504
4505  intmat Q[2][3] =
4506    1,2,3,
4507    3,2,1;
4508
4509  intmat L[3][2] =
4510    1,4,
4511    2,5,
4512    3,6;
4513
4514  // should be a 2x2 matrix with columns
4515  // [2,-14], [0,36]
4516  imageLattice(Q,L);
4517
4518}
4519
4520/******************************************************/
4521proc intRank(intmat A)
4522"USAGE: intRank(A); intmat A
4523PURPOSE: compute the rank of the integral matrix A
4524by computing a hermite normalform.
4525RETURNS: int
4526EXAMPLE: example intRank; shows an example
4527"
4528{
4529  intmat B = hermiteNormalForm(A);
4530
4531  // get number of zero columns
4532  int nzerocols = 0;
4533  int j;
4534  int i;
4535  int iszero;
4536  for ( j = 1; j <= ncols(B); j++ )
4537  {
4538    iszero = 1;
4539
4540    for ( i = 1; i <= nrows(B); i++ )
4541    {
4542      if ( B[i,j] != 0 )
4543      {
4544        iszero = 0;
4545        break;
4546      }
4547    }
4548
4549    if ( iszero == 1 )
4550    {
4551      nzerocols++;
4552    }
4553  }
4554
4555  // get number of zero rows
4556  int nzerorows = 0;
4557
4558  for ( i = 1; i <= nrows(B); i++ )
4559  {
4560    iszero = 1;
4561
4562    for ( j = 1; j <= ncols(B); j++ )
4563    {
4564      if ( B[i,j] != 0 )
4565      {
4566        iszero = 0;
4567        break;
4568      }
4569    }
4570
4571    if ( iszero == 1 )
4572    {
4573      nzerorows++;
4574    }
4575  }
4576
4577  int r = nrows(B) - nzerorows;
4578
4579  if ( ncols(B) - nzerocols < r )
4580  {
4581    r = ncols(B) - nzerocols;
4582  }
4583
4584  return(r);
4585}
4586example
4587{
4588  "EXAMPLE:"; echo=2;
4589
4590  intmat A[3][4] =
4591    1,0,1,0,
4592    1,2,0,0,
4593    0,0,0,0;
4594
4595  int r = intRank(A);
4596
4597  print(A);
4598  print(r); // Should be 2
4599
4600  // another example
4601  intmat B[2][2] =
4602    1,2,
4603    1,2;
4604
4605  int d = intRank(B);
4606
4607  print(B);
4608  print(d); // Should be 1
4609
4610  kill A, B, r, d;
4611
4612}
4613
4614/*****************************************************/
4615
4616proc isSublattice(intmat L, intmat S)
4617"USAGE: isSublattice(L, S); L, S are of tpye intmat
4618PURPOSE: checks whether the lattice created by L is a
4619sublattice of the lattice created by S.
4620The procedure checks whether each generator of L is
4621contained in S.
4622RETURN: integer, 0 if false, 1 if true
4623EXAMPLE: example isSublattice; shows an example
4624"
4625{
4626  int a,b,g,i,j,k;
4627  intmat Ker;
4628
4629  // check whether each column v of L is contained in
4630  // the lattice generated by S
4631  for ( i = 1; i <= ncols(L); i++ )
4632  {
4633
4634    // v is the i-th column of L
4635    intvec v;
4636     for ( j = 1; j <= nrows(L); j++ )
4637    {
4638      v[j] = L[j,i];
4639    }
4640
4641    // concatenate B = [S,v]
4642    intmat B[nrows(L)][ncols(S) + 1];
4643
4644    for ( a = 1; a <= nrows(S); a++ )
4645    {
4646      for ( b = 1; b <= ncols(S); b++ )
4647      {
4648        B[a,b] = S[a,b];
4649      }
4650    }
4651
4652    for ( a = 1; a <= size(v); a++ )
4653    {
4654      B[a,ncols(B)] = v[a];
4655    }
4656
4657
4658    // check gcd
4659    Ker = kernelLattice(B);
4660    k = nrows(Ker);
4661    list R; // R is the last row
4662
4663    for ( j = 1; j <= ncols(Ker); j++ )
4664    {
4665      R[j] = Ker[k,j];
4666    }
4667
4668    g = R[1];
4669
4670    for ( j = 2; j <= size(R); j++ )
4671    {
4672      g = gcd(g,R[j]);
4673    }
4674
4675    if ( g != 1 and g != -1 )
4676    {
4677      return(0);
4678    }
4679
4680    kill B, v, R;
4681
4682  }
4683
4684  return(1);
4685}
4686example
4687{
4688  "EXAMPLE:"; echo=2;
4689
4690  //ring R = 0,(x,y),dp;
4691  intmat S2[3][3]=
4692    0, 2, 3,
4693    0, 1, 1,
4694    3, 0, 2;
4695
4696  intmat S1[3][2]=
4697    0, 6,
4698    0, 2,
4699    3, 4;
4700
4701  isSublattice(S1,S2); // Yes!
4702
4703  intmat S3[3][1] =
4704    0,
4705    0,
4706    1;
4707
4708  not(isSublattice(S3,S2)); // Yes!
4709
4710}
4711
4712/******************************************************/
4713
4714proc latticeBasis(intmat B)
4715"USAGE: latticeBasis(B); intmat B
4716PURPOSE: compute an integral basis for the lattice defined by
4717the columns of B.
4718RETURNS: intmat
4719EXAMPLE: example latticeBasis; shows an example
4720"
4721{
4722  int n = ncols(B);
4723  int r = intRank(B);
4724
4725  if ( r == 0 )
4726  {
4727    intmat H[nrows(B)][1];
4728    int j;
4729
4730    for ( j = 1; j <= nrows(B); j++ )
4731    {
4732      H[j,1] = 0;
4733    }
4734  }
4735  else
4736  {
4737    intmat H = hermiteNormalForm(B);;
4738
4739    if (r < n)
4740    {
4741      // delete columns r+1 to n
4742      // should be identical with the function
4743      // H = submat(H,1..nrows(H),1..r);
4744      // for matrices
4745      intmat Hdel[nrows(H)][r];
4746      int k;
4747      int m;
4748
4749      for ( k = 1; k <= nrows(H); k++ )
4750      {
4751        for ( m = 1; m <= r; m++ )
4752        {
4753          Hdel[k,m] = H[k,m];
4754        }
4755      }
4756
4757      H = Hdel;
4758    }
4759  }
4760
4761  return(H);
4762}
4763example
4764{
4765  "EXAMPLE:"; echo=2;
4766
4767  intmat L[3][3] =
4768    1,4,8,
4769    2,5,10,
4770    3,6,12;
4771
4772  intmat B = latticeBasis(L);
4773  print(B); // should result in a matrix whose columns generate the same lattice as  [1,2,3] and [0,3,6]:
4774
4775   // another example
4776  intmat C[2][4] =
4777    1,1,2,0,
4778    2,3,4,0;
4779
4780  // should result in a matrix whose
4781  // colums create the same  lattice as
4782  // [0,1],[1,0]
4783  intmat D = latticeBasis(C);
4784
4785  print(D);
4786
4787  kill B,L;
4788}
4789
4790/******************************************************/
4791
4792proc kernelLattice(def P)
4793"USAGE: kernelLattice(P); intmat P
4794PURPOSE: compute a integral basis for the kernel of the
4795homomorphism of lattices defined by the intmat P.
4796RETURNS: intmat
4797EXAMPLE: example kernelLattice; shows an example
4798"
4799{
4800  int n = ncols(P);
4801  int r = intRank(P);
4802
4803  if ( r == 0 )
4804  {
4805    intmat U = unitMatrix(n);
4806  }
4807  else
4808  {
4809    if ( r == n )
4810    {
4811      intmat U[n][1];  // now all entries are zero.
4812    }
4813    else
4814    {
4815      list L = hermiteNormalForm(P, "transform"); //hermite(P, "transform");  // now, Hermite = L[1] = A*L[2]
4816      intmat U = L[2];
4817
4818      // delete columns 1 to r
4819      // should be identical with the function
4820      // U = submat(U,1..nrows(U),r+1..);
4821      // for matrices
4822      intmat Udel[nrows(U)][ncols(U) - r];
4823      int k;
4824      int m;
4825
4826      for ( k = 1; k <= nrows(U); k++ )
4827      {
4828        for ( m = r + 1; m <= ncols(U); m++ )
4829        {
4830          Udel[k,m - r] = U[k,m];
4831        }
4832      }
4833
4834      U = Udel;
4835
4836    }
4837  }
4838
4839  return(U);
4840}
4841example
4842{
4843  "EXAMPLE"; echo = 2;
4844
4845  intmat LL[3][4] =
4846    1,4,7,10,
4847    2,5,8,11,
4848    3,6,9,12;
4849
4850  // should be a 4x2 matrix whose columns
4851  // generate the same lattice as [-1,2,-1,0],[2,-3,0,1]
4852  intmat B = kernelLattice(LL);
4853
4854  print(B);
4855
4856  // another example
4857  intmat C[2][4] =
4858    1,0,2,0,
4859    0,1,2,0;
4860
4861  // should result in a matrix whose
4862  // colums create the same  lattice as
4863  // [-2,-2,1,0], [0,0,0,1]
4864  intmat D = kernelLattice(C);
4865
4866  print(D);
4867
4868  kill B;
4869
4870}
4871
4872/*****************************************************/
4873
4874proc preimageLattice(def P, def B)
4875"
4876USAGE: preimageLattice(P, B); intmat P, intmat B
4877PURPOSE: compute an integral basis for the preimage of B under
4878 the homomorphism of lattices defined by the intmat P.
4879RETURNS: intmat
4880EXAMPLE: example preimageLattice; shows an example
4881"
4882{
4883  // concatenate matrices: Con = [P,-B]
4884  intmat Con[nrows(P)][ncols(P) + ncols(B)];
4885  int i;
4886  int j;
4887
4888  for ( i = 1; i <= nrows(Con); i++ )
4889  {
4890    for ( j = 1; j <= ncols(P); j++ ) // P first
4891    {
4892      Con[i,j] = P[i,j];
4893    }
4894  }
4895
4896  for ( i = 1; i <= nrows(Con); i++ )
4897  {
4898    for ( j = 1; j <= ncols(B); j++ ) // now -B
4899    {
4900      Con[i,ncols(P) + j] = - B[i,j];
4901    }
4902  }
4903
4904  intmat L = kernelLattice(Con);
4905
4906  // delete rows ncols(P)+1 to nrows(L) out of L
4907  intmat Del[ncols(P)][ncols(L)];
4908  int k;
4909  int m;
4910
4911  for ( k = 1; k <= nrows(Del); k++ )
4912  {
4913    for ( m = 1; m <= ncols(Del); m++ )
4914    {
4915      Del[k,m] = L[k,m];
4916    }
4917  }
4918
4919  L = latticeBasis(Del);
4920
4921  return(L);
4922
4923}
4924example
4925{
4926  "EXAMPLE"; echo = 2;
4927
4928  intmat P[2][3] =
4929    2,6,10,
4930    4,8,12;
4931
4932  intmat B[2][1] =
4933    1,
4934    0;
4935
4936  // should be a (3x2)-matrix with columns e.g. [1,1,-1] and [0,3,-2] (the generated lattice should be identical)
4937  print(preimageLattice(P,B));
4938
4939  // another example
4940  intmat W[3][3] =
4941    1,0,0,
4942    0,1,1,
4943    0,2,0;
4944
4945  intmat Z[3][2] =
4946    1,0,
4947    0,1,
4948    0,0;
4949
4950  // should be a (3x2)-matrix with columns e.g. [1,0,0] and [0,0,-1] (the generated lattice should be identical)
4951  print(preimageLattice(W,Z));
4952
4953}
4954
4955/******************************************************/
4956proc isPrimitiveSublattice(intmat A);
4957"USAGE: isPrimitiveSublattice(A); intmat A
4958PURPOSE: check whether the given set of integral vectors in ZZ^m,
4959i.e. the columns of A, generate a primitive sublattice in ZZ^m
4960(a direct summand of ZZ^m).
4961RETURNS: int, where 0 is false and 1 is true.
4962EXAMPLE: example isPrimitiveSublattice; shows an example
4963"
4964{
4965  intmat B = smithNormalForm(A);
4966  int r = intRank(B);
4967
4968  if ( r == 0 )
4969  {
4970    return(1);
4971  }
4972
4973  if ( 1 < B[r,r] )
4974  {
4975    return(0);
4976  }
4977
4978  return(1);
4979}
4980example
4981{
4982  "EXAMPLE"; echo = 2;
4983
4984  intmat A[3][2] =
4985    1,4,
4986    2,5,
4987    3,6;
4988
4989  // should be 0
4990  int b = isPrimitiveSublattice(A);
4991  print(b);
4992
4993  // another example
4994
4995  intmat B[2][2] =
4996    1,0,
4997    0,1;
4998
4999  // should be 1
5000  int c = isPrimitiveSublattice(B);
5001  print(c);
5002
5003  kill A, b, B, c;
5004}
5005
5006/******************************************************/
5007proc isIntegralSurjective(intmat P);
5008"USAGE: isIntegralSurjective(P); intmat P
5009PURPOSE: test whether the given linear map P of lattices is
5010surjective.
5011RETURNS: int, where 0 is false and 1 is true.
5012EXAMPLE: example isIntegralSurjective; shows an example
5013"
5014{
5015  int r = intRank(P);
5016
5017  if ( r < nrows(P) )
5018  {
5019    return(0);
5020  }
5021
5022
5023  if ( isPrimitiveSublattice(P) == 1 )
5024  {
5025    return(1);
5026  }
5027
5028  return(0);
5029}
5030example
5031{
5032  "EXAMPLE"; echo = 2;
5033
5034  intmat A[2][3] =
5035    1,3,5,
5036    2,4,6;
5037
5038  // should be 0
5039  int b = isIntegralSurjective(A);
5040  print(b);
5041
5042  // another example
5043  intmat B[2][3] =
5044    1,1,5,
5045    2,3,6;
5046
5047  // should be 1
5048  int c = isIntegralSurjective(B);
5049  print(c);
5050
5051  kill A, b, B, c;
5052}
5053
5054/******************************************************/
5055proc projectLattice(intmat B)
5056"USAGE: projectLattice(B); intmat B
5057PURPOSE: A set of vectors in ZZ^m is given as the columns of B.
5058Then this function provides a linear map ZZ^m --> ZZ^n
5059having the primitive span of B its kernel.
5060RETURNS: intmat
5061EXAMPLE: example projectLattice; shows an example
5062"
5063{
5064  int n = nrows(B);
5065  int r = intRank(B);
5066
5067  if ( r == 0 )
5068  {
5069    intmat U = unitMatrix(n);
5070  }
5071  else
5072  {
5073    if ( r == n )
5074    {
5075      intmat U[1][n]; // U now is the n-dim zero-vector
5076    }
5077    else
5078    {
5079      // we want a matrix with column operations so we transpose
5080      intmat BB = transpose(B);
5081      list L = hermiteNormalForm(BB, "transform");
5082      intmat U = transpose(L[2]);
5083
5084
5085      // delete rows 1 to r
5086      intmat Udel[nrows(U) - r][ncols(U)];
5087      int k;
5088      int m;
5089
5090      for ( k = 1; k <= nrows(U) - r ; k++ )
5091      {
5092        for ( m = 1; m <= ncols(U); m++ )
5093        {
5094          Udel[k,m] = U[k + r,m];
5095        }
5096      }
5097
5098      U = Udel;
5099
5100    }
5101  }
5102
5103  return(U);
5104}
5105example
5106{
5107  "EXAMPLE"; echo = 2;
5108
5109  intmat B[4][2] =
5110    1,5,
5111    2,6,
5112    3,7,
5113    4,8;
5114
5115  // should result in a (2x4)-matrix such that the corresponding lattice is created by
5116  // [-1, 2], [-2, 3], [-1, 0] and [0, 1]
5117  print(projectLattice(B));
5118
5119  // another example
5120
5121  intmat BB[4][2] =
5122    1,0,
5123    0,1,
5124    0,0,
5125    0,0;
5126
5127  // should result in a (2x4)-matrix such that the corresponding lattice is created by
5128  // [0,0],[0,0],[1,0],[0,1]
5129  print(projectLattice(BB));
5130
5131  // another example
5132
5133  intmat BBB[3][4] =
5134    1,0,1,2,
5135    1,1,0,0,
5136    3,0,0,3;
5137
5138  // should result in the (1x3)-matrix that consists of just zeros
5139  print(projectLattice(BBB));
5140
5141}
5142
5143/******************************************************/
5144proc intersectLattices(intmat A, intmat B)
5145"USAGE: intersectLattices(A, B); intmat A, intmat B
5146PURPOSE: compute an integral basis for the intersection of the
5147lattices A and B.
5148RETURNS: intmat
5149EXAMPLE: example intersectLattices; shows an example
5150"
5151{
5152  // concatenate matrices: Con = [A,-B]
5153  intmat Con[nrows(A)][ncols(A) + ncols(B)];
5154  int i;
5155  int j;
5156
5157  for ( i = 1; i <= nrows(Con); i++ )
5158  {
5159    for ( j = 1; j <= ncols(A); j++ ) // A first
5160    {
5161      Con[i,j] = A[i,j];
5162    }
5163  }
5164
5165  for ( i = 1; i <= nrows(Con); i++ )
5166  {
5167    for ( j = 1; j <= ncols(B); j++ ) // now -B
5168    {
5169      Con[i,ncols(A) + j] = - B[i,j];
5170    }
5171  }
5172
5173  intmat K = kernelLattice(Con);
5174
5175  // delete all rows in K from ncols(A)+1 onwards
5176  intmat Bas[ncols(A)][ncols(K)];
5177
5178  for ( i = 1; i <= nrows(Bas); i++ )
5179  {
5180    for ( j = 1; j <= ncols(Bas); j++ )
5181    {
5182      Bas[i,j] = K[i,j];
5183    }
5184  }
5185
5186  // take product in order to obtain the intersection
5187  intmat S = A * Bas;
5188  intmat Cut = hermiteNormalForm(S); //hermite(S);
5189  int r = intRank(Cut);
5190
5191  if ( r == 0 )
5192  {
5193    intmat Cutdel[nrows(Cut)][1]; // is now the zero-vector
5194
5195    Cut = Cutdel;
5196  }
5197  else
5198  {
5199    // delte columns from r+1 onwards
5200    intmat Cutdel[nrows(Cut)][r];
5201
5202    for ( i = 1; i <= nrows(Cutdel); i++ )
5203    {
5204      for ( j = 1; j <= r; j++ )
5205      {
5206        Cutdel[i,j] = Cut[i,j];
5207      }
5208    }
5209
5210    Cut = Cutdel;
5211  }
5212
5213  return(Cut);
5214}
5215example
5216{
5217  "EXAMPLE"; echo = 2;
5218
5219  intmat A[3][2] =
5220    1,4,
5221    2,5,
5222    3,6;
5223
5224  intmat B[3][2] =
5225    6,9,
5226    7,10,
5227    8,11;
5228
5229  // should result in a (3x2)-matrix with columns
5230  //  e.g. [0, 3, 6], [-3, 0, 3] (the lattice should be the same)
5231  print(intersectLattices(A,B));
5232
5233  // another example
5234  intmat C[2][3] =
5235    1,0,0,
5236    3,2,5;
5237
5238  intmat D[2][3] =
5239    4,5,0,
5240    0,5,0;
5241
5242  // should result in a (3x2)-matrix whose columns generate the
5243  // same lattice as [1,5], [0, 20]
5244  print(intersectLattices(C,D));
5245}
5246
5247////////////////////////////////////
5248
5249proc intInverse(intmat A);
5250"USAGE: intInverse(A); intmat A
5251PURPOSE: compute the integral inverse of the intmat A.
5252If det(A) is neither 1 nor -1 an error is returned.
5253RETURNS: intmat
5254EXAMPLE: example intInverse; shows an example
5255"
5256{
5257  int d = det(A);
5258
5259  if ( d * d != 1 ) // is d = 1 or -1? Else: error
5260  {
5261    ERROR("determinant of the given intmat has to be 1 or -1.");
5262  }
5263
5264  int c;
5265  int i,j;
5266  intmat C[nrows(A)][ncols(A)];
5267  intmat Ad;
5268  int s;
5269
5270  for ( i = 1; i <= nrows(C); i++ )
5271  {
5272    for ( j = 1; j <= ncols(C); j++ )
5273    {
5274      Ad = intAdjoint(A,i,j);
5275      s = 1;
5276
5277      if ( ((i + j) % 2) > 0 )
5278      {
5279        s = -1;
5280      }
5281
5282      C[i,j] = d * s * det(Ad); // mult by d is equal to div by det
5283    }
5284  }
5285
5286  C = transpose(C);
5287
5288  return(C);
5289}
5290example
5291{
5292  "EXAMPLE"; echo = 2;
5293
5294  intmat A[3][3] =
5295    1,1,3,
5296    3,2,0,
5297    0,0,1;
5298
5299  intmat B = intInverse(A);
5300
5301  // should be the unit matrix
5302  print(A * B);
5303
5304  // another example
5305  intmat C[2][2] =
5306    2,1,
5307    3,2;
5308
5309  intmat D  = intInverse(C);
5310
5311  // should be the unit matrix
5312  print(C * D);
5313
5314  kill A, B, C, D;
5315}
5316
5317
5318/******************************************************/
5319static proc intAdjoint(intmat A, int indrow, int indcol)
5320"USAGE: intAdjoint(A); intmat A
5321PURPOSE: return the matrix where the given row and column are deleted.
5322RETURNS: intmat
5323EXAMPLE: example intAdjoint; shows an example
5324"
5325{
5326  int n = nrows(A);
5327  int m = ncols(A);
5328  int i, j;
5329  intmat B[n - 1][m - 1];
5330  int a, b;
5331
5332  for ( i = 1; i < indrow; i++ )
5333  {
5334    for ( j = 1; j < indcol; j++ )
5335    {
5336      B[i,j] = A[i,j];
5337    }
5338    for ( j = indcol + 1; j <= ncols(A); j++ )
5339    {
5340      B[i,j - 1] = A[i,j];
5341    }
5342  }
5343
5344  for ( i = indrow + 1; i <= nrows(A); i++ )
5345  {
5346    for ( j = 1; j < indcol; j++ )
5347    {
5348      B[i - 1,j] = A[i,j];
5349    }
5350    for ( j = indcol+1; j <= ncols(A); j++ )
5351    {
5352      B[i - 1,j - 1] = A[i,j];
5353    }
5354  }
5355
5356  return(B);
5357}
5358example
5359{
5360  "EXAMPLE"; echo = 2;
5361
5362  intmat A[2][3] =
5363    1,3,5,
5364    2,4,6;
5365
5366  intmat B = intAdjoint(A,2,2);
5367  print(B);
5368
5369  kill A,B;
5370}
5371
5372/******************************************************/
5373proc integralSection(intmat P);
5374"USAGE: integralSection(P); intmat P
5375PURPOSE: for a given linear surjective map P of lattices
5376 this procedure returns an integral section of P.
5377RETURNS: intmat
5378EXAMPLE: example integralSection; shows an example
5379"
5380{
5381  int m = nrows(P);
5382  int n = ncols(P);
5383
5384  if ( m == n )
5385  {
5386    intmat U = intInverse(P);
5387  }
5388  else
5389  {
5390    intmat U = (hermiteNormalForm(P, "transform"))[2];
5391
5392    // delete columns m+1 to n
5393    intmat Udel[nrows(U)][ncols(U) - (n - m)];
5394    int k;
5395    int z;
5396
5397    for ( k = 1; k <= nrows(U); k++ )
5398    {
5399      for ( z = 1; z <= m; z++ )
5400      {
5401        Udel[k,z] = U[k,z];
5402      }
5403    }
5404
5405    U = Udel;
5406  }
5407
5408  return(U);
5409}
5410example
5411{
5412  "EXAMPLE"; echo = 2;
5413
5414  intmat P[2][4] =
5415    1,3,4,6,
5416    2,4,5,7;
5417
5418  // should be a matrix with two columns
5419  // for example: [-2, 1, 0, 0], [3, -3, 0, 1]
5420  intmat U = integralSection(P);
5421
5422  print(U);
5423  print(P * U);
5424
5425  kill U;
5426}
5427
5428
5429
5430/******************************************************/
5431proc factorgroup(G,H)
5432"USAGE: factorgroup(G,H); list G, list H
5433PURPOSE: returns a representation of the factor group G mod H using the first isomorphism thm
5434RETURNS: list
5435EXAMPLE: example factorgroup(G,H); shows an example
5436"
5437{
5438  intmat S1 = G[1];
5439  intmat L1 = G[2];
5440  intmat S2 = H[1];
5441  intmat L2 = H[2];
5442
5443  // check whether G,H are subgroups of a common group, i.e. whether L1 and L2 span the same lattice
5444  if ( !isSublattice(L1,L2) || !isSublattice(L2,L1))
5445  {
5446    ERROR("G and H are not subgroups of a common group.");
5447  }
5448
5449  // check whether H is a subgroup of G, i.e. whether S2 is a sublattice of S1+L1
5450  intmat B = concatintmat(S1,L1); // check whether this gives the concatinated matrix
5451  if ( !isSublattice(S2,B) )
5452  {
5453    ERROR("H is not a subgroup of G");
5454  }
5455  // use first isomorphism thm to get the factor group
5456  intmat L = concatintmat(L1,S2); // check whether this gives the concatinated matrix
5457  list GmodH;
5458  GmodH[1]=S1;
5459  GmodH[2]=L;
5460  return(GmodH);
5461}
5462example
5463{
5464  "EXAMPLE"; echo = 2;
5465
5466  intmat S1[2][2] =
5467    1,0,
5468    0,1;
5469  intmat L1[2][1] =
5470    2,
5471    0;
5472
5473  intmat S2[2][1] =
5474    1,
5475    0;
5476  intmat L2[2][1] =
5477    2,
5478    0;
5479
5480  list G = createGroup(S1,L1);
5481  list H = createGroup(S2,L2);
5482
5483  list N = factorgroup(G,H);
5484  print(N);
5485
5486  kill G,H,N,S1,L1,S2,L2;
5487
5488}
5489
5490/******************************************************/
5491proc productgroup(G,H)
5492"USAGE: productgroup(G,H); list G, list H
5493PURPOSE: Returns a representation of the group G x H
5494RETURNS: list
5495EXAMPLE: example productgroup(G,H); shows an example
5496"
5497{
5498  intmat S1 = G[1];
5499  intmat L1 = G[2];
5500  intmat S2 = H[1];
5501  intmat L2 = H[2];
5502  intmat OS1[nrows(S1)][ncols(S2)];
5503  intmat OS2[nrows(S2)][ncols(S1)];
5504  intmat OL1[nrows(L1)][ncols(L2)];
5505  intmat OL2[nrows(L2)][ncols(L1)];
5506
5507  // concatinate matrices to get S
5508  intmat A = concatintmat(S1,OS1);
5509  intmat B = concatintmat(OS2,S2);
5510  intmat At = transpose(A);
5511  intmat Bt = transpose(B);
5512  intmat St = concatintmat(At,Bt);
5513  intmat S = transpose(St);
5514
5515  // concatinate matrices to get L
5516  intmat C = concatintmat(L1,OL1);
5517  intmat D = concatintmat(OL2,L2);
5518  intmat Ct = transpose(C);
5519  intmat Dt = transpose(D);
5520  intmat Lt = concatintmat(Ct,Dt);
5521  intmat L = transpose(Lt);
5522
5523  list GxH;
5524  GxH[1]=S;
5525  GxH[2]=L;
5526  return(GxH);
5527}
5528example
5529{
5530  "EXAMPLE"; echo = 2;
5531
5532  intmat S1[2][2] =
5533    1,0,
5534    0,1;
5535  intmat L1[2][1] =
5536    2,
5537    0;
5538
5539  intmat S2[2][2] =
5540    1,0,
5541    0,2;
5542  intmat L2[2][1] =
5543    0,
5544    3;
5545
5546  list G = createGroup(S1,L1);
5547  list H = createGroup(S2,L2);
5548
5549  list N = productgroup(G,H);
5550  print(N);
5551
5552  kill G,H,N,S1,L1,S2,L2;
5553
5554}
5555
5556/******************************************************/
5557proc primitiveSpan(intmat V);
5558"USAGE: primitiveSpan(V); intmat V
5559PURPOSE: compute an integral basis for the minimal primitive
5560sublattice that contains the given vectors, i.e. the columns of V.
5561RETURNS: int, where 0 is false and 1 is true.
5562EXAMPLE: example primitiveSpan; shows an example
5563"
5564{
5565  int n = ncols(V);
5566  int m = nrows(V);
5567  int r = intRank(V);
5568
5569
5570  if ( r == 0 )
5571  {
5572    intmat P[m][1]; //  this is the m-zero-vector now
5573  }
5574  else
5575  {
5576    list L = smithNormalForm(V, "transform"); // L = [A,S,B] where S is the smith-NF and S = A*S*B
5577    intmat P = intInverse(L[1]);
5578
5579//    print(L);
5580
5581    if ( r < m )
5582    {
5583      // delete columns r+1 to m in P:
5584      intmat Pdel[nrows(P)][r];
5585      int i,j;
5586
5587      for ( i = 1; i <= nrows(Pdel); i++ )
5588      {
5589        for ( j = 1; j <= ncols(Pdel); j++ )
5590        {
5591          Pdel[i,j] = P[i,j];
5592        }
5593      }
5594
5595      P = Pdel;
5596    }
5597  }
5598
5599  return(P);
5600}
5601example
5602{
5603  "EXAMPLE"; echo = 2;
5604
5605  intmat V[3][2] =
5606    1,4,
5607    2,5,
5608    3,6;
5609
5610  // should return a (3x2)-matrix whose columns
5611  // generate the same lattice as [1, 2, 3] and [0, 1, 2]
5612  intmat R = primitiveSpan(V);
5613  print(R);
5614
5615  // another example
5616  intmat W[2][2] =
5617    1,0,
5618    0,1;
5619
5620  // should return a (2x2)-matrix whose columns
5621  // generate the same lattice as [1, 0] and [0, 1]
5622  intmat S = primitiveSpan(W);
5623  print(S);
5624
5625  kill V, R, S, W;
5626}
5627
5628/***********************************************************/
Note: See TracBrowser for help on using the repository browser.