source: git/Singular/LIB/multigrading.lib @ 166ebd2

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