source: git/Singular/LIB/multigrading.lib @ 199cd68

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