source: git/Singular/LIB/multigrading.lib @ e7c67af

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