source: git/Singular/LIB/schreyer.lib @ b1645e

spielwiese
Last change on this file since b1645e was b1645e, checked in by Oleksandr Motsak <motsak@…>, 9 years ago
Moved general descriptiomn to the header + references
  • Property mode set to 100644
File size: 32.0 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2version="version schreyer.lib 4.0.0.0 Jun_2013 "; // $Id$
3category="General purpose";
4info="
5LIBRARY: schreyer.lib     Helpers for computing a Schreyer resolution in @code{derham.lib}
6AUTHOR:  Oleksandr Motsak <U@D>, where U={motsak}, D={mathematik.uni-kl.de}
7KEYWORDS: Schreyer ordering; Schreyer resolution; syzygy
8OVERVIEW:
9@* The library contains helper procedures for computing a Schreyer resultion (cf. [SFO])
10   for @code{derham.lib} also in non-commutative setting (cf. [MO]).
11   We call a free resulution a Schreyer resolution if any higher syzygy is a Goebner base of a previous one
12   with respect to the corresponding Schreyer ordering.
13   Schreyer resolution can be much bigger than a minimal resolution of the same module one but can be easier to construct.
14@* Input for resolution computations is a set of vectors @code{M} in form of a module over some basering @code{R}.
15   The ring @code{R} may be non-commutative, in which case the ring ordering should be global.
16@* These procedures produce/work with partial Schreyer resolutions of @code{(R^rank(M))/M} in form of
17   a ring (endowed with a special ring ordering that will be extended in the course of a resolution computation)
18   containing a list of modules @code{RES} and a module @code{MRES}:
19@* The list of modules @code{RES} contains the images of maps (also called syzygies) substituting the
20   computed beginning of a Schreyer resolution, that is, each syzygy module is a Groebner Basis
21   of the previous one with respect to corresponding Schreyer induced ordering.
22@* The list @code{RES} starts with a zero map given by @code{rank(M)} zero generators indicating that the image of
23   the first differential map is zero. The second map @code{RES[2]} is given by @code{M}, which indicates that
24   the resolution is of @code{(R^rank(M))/M} is being computed.
25@* The module @code{MRES} is a direct sum of modules from @code{RES} and thus comprises all computed differentials.
26@* Syzygies are shifted so that @code{gen(i)} is mapped to @code{MRES[i]} under the differential map.
27@* Schreyer ordering extends the starting module ordering on @code{M} (defined in Singular by the basering @code{R})
28   and is extended to higher syzygies using the following definition:
29@*        a < b if and only if (d(a) < d(b)) OR ( (d(a) = d(b) AND (comp(a) < comp(b)) ),
30@* where @code{d(a)} is the image of a under the differential (given by @code{MRES}),
31   and @code{comp(a)} is the mod. component, for any module terms @code{a} and @code{b} from the same free module.
32REFERENCES:
33[SFO] Schreyer, F.O.: Die Berechnung von Syzygien mit dem verallgemeinerten Weierstrassschen Divisionssatz,
34      Master's thesis, Univ. Hamburg, 1980.
35[MO]  Motsak, O.: Non-commutative Computer Algebra with applications: Graded commutative algebra and related
36      structures in Singular with applications, Ph.D. thesis, TU Kaiserslautern, 2010
37
38NOTE:  requires the dynamic or built-in module @code{syzextra}
39
40PROCEDURES:
41  Sres(M,len)     compute Schreyer resolution of module M of maximal length len
42  Ssyz(M)         compute Schreyer resolution of module M of length 1
43  Scontinue(len)  extend currently active resolution by (at most) len syszygies
44";
45
46static proc prepareSyz( module I, list # )
47{
48  int i;
49  int k = 0;
50  int r = nrows(I);
51  int c = ncols(I);
52
53
54  if( size(#) > 0 )
55  {
56    if( typeof(#[1]) == "int" || typeof(#[1]) == "bigint" )
57    {
58      k = #[1];
59    }
60  }
61
62  if( k < r )
63  {
64    "// *** Wrong k: ", k, " < nrows: ", r, " => setting k = r = ", r;
65    k = r;
66  }
67
68//   "k: ", k;  "c: ", c;   "I: ", I;
69
70  for( i = c; i > 0; i-- )
71  {
72    I[i] = I[i] + gen(k + i);
73  }
74
75//  DetailedPrint(I);
76
77  return(I);
78}
79
80static proc separateSyzGB( module J, int c )
81{
82  module II, G; vector v; int i;
83
84  J = simplify(J, 2);
85
86  for( i = ncols(J); i > 0; i-- )
87  {
88    v = J[i];
89    if( leadcomp(v) > c )
90    {
91      II[i] = v;
92    } else
93    {
94      G[i] = v; // leave only gen(i): i <= c
95    }
96  }
97
98  II = simplify(II, 2);
99  G = simplify(G, 2);
100
101  return (list(G, II));
102}
103
104static proc splitSyzGB( module J, int c )
105{
106  module JJ; vector v, vv; int i;
107
108  for( i = ncols(J); i > 0; i-- )
109  {
110    v = J[i];
111
112    vv = 0;
113   
114    while( leadcomp(v) <= c )
115    {
116      vv = vv + lead(v);
117      v  = v  - lead(v);
118    }
119
120    J[i] = vv;
121    JJ[i] = v;
122  }
123
124  J = simplify(J, 2);
125  JJ = simplify(JJ, 2);
126
127  return (list(J, JJ));
128}
129
130
131static proc Sinit(module M)
132{
133  def @save = basering;
134 
135  int @DEBUG = !system("with", "ndebug");
136  if( @DEBUG )
137  {
138    "Sinit::Input";
139    type(M);
140    DetailedPrint(M);
141    attrib(M);
142  }
143
144  int @RANK = nrows(M); int @SIZE = ncols(M);
145
146  int @IS_A_SB = attrib(M, "isSB"); // ??? only if all weights were zero?!
147
148  if( !@IS_A_SB )
149  {
150    M = std(M); // this should be faster than computing std in S (later on)
151  }
152
153  def S = MakeInducedSchreyerOrdering(1); // 1 puts history terms to the back
154  // TODO: NOTE: +1 causes trouble to Singular interpreter!!!???
155  setring S; // a new ring with a Schreyer ordering
156
157  if( @DEBUG )
158  {
159    "Sinit::StartingISRing";
160    basering;
161//    DetailedPrint(basering);
162  }
163
164  // Setup the leading syzygy^{-1} module to zero:
165  module Z = 0; Z[@RANK] = 0; attrib(Z, "isHomog", intvec(0)); 
166
167  module MRES = Z;
168 
169  list RES; RES[1] = Z;
170
171  module F = freemodule(@RANK);
172  intvec @V = deg(F[1..@RANK]);
173 
174  module M = imap(@save, M);
175 
176  attrib(M, "isHomog", @V);
177  attrib(M, "isSB", 1);
178
179 
180  if( @DEBUG )
181  {
182    "Sinit::SB_Input: ";
183    type(M);
184    attrib(M);
185    attrib(M, "isHomog");
186    DetailedPrint(M);
187  }
188
189  if( @DEBUG )
190  {
191    // 0^th syz. property
192    if( size(module(transpose( transpose(M) * transpose(MRES) ))) > 0 )
193    {
194      transpose( transpose(M) * transpose(MRES) );
195      "transpose( transpose(M) * transpose(MRES) ) != 0!!!";
196      $
197    }
198  }
199
200  RES[size(RES)+1] = M; // list of all syzygy modules
201  MRES = MRES, M;
202
203  attrib(MRES, "isHomog", @V); 
204
205  attrib(S, "InducionLeads", lead(M));
206  attrib(S, "InducionStart", @RANK); 
207 
208  if( @DEBUG )
209  {
210    "Sinit::MRES";
211    DetailedPrint(MRES);
212    attrib(MRES, "isHomog");
213    attrib(S);
214  }
215
216  export RES;
217  export MRES;
218  return (S);
219}
220
221static proc Sstep()
222{
223  int @DEBUG = !system("with", "ndebug");
224
225  if( @DEBUG )
226  {
227    "Sstep::NextInducedRing";
228    DetailedPrint(basering);
229
230    attrib(basering, "InducionLeads");
231    attrib(basering, "InducionStart");
232
233    GetInducedData();
234  }
235
236  // syzygy step:
237
238/*
239  // is initial weights are all zeroes!
240  def L =  lead(M);
241  intvec @V = deg(M[1..ncols(M)]);  @W;  @V;  @W = @V;  attrib(L, "isHomog", @W); 
242  SetInducedReferrence(L, @RANK, 0);
243*/
244
245//  def L =  lead(MRES);
246//  @W = @W, @V;
247//  attrib(L, "isHomog", @W); 
248
249
250  // General setting:
251//  SetInducedReferrence(MRES, 0, 0); // limit: 0!
252  int @l = size(RES);
253
254  module M = RES[@l];
255
256  module L = attrib(basering, "InducionLeads");
257  int limit = attrib(basering, "InducionStart");
258
259//  L;  limit;
260 
261  int @RANK = ncols(MRES) - ncols(M); // nrows(M); // what if M is zero?!
262
263/*
264  if( @RANK !=  nrows(M) )
265  {
266    type(MRES);
267    @RANK;
268    type(M);
269    pause();
270  }
271*/
272 
273  intvec @W = attrib(M, "isHomog");
274  intvec @V = deg(M[1..ncols(M)]);
275  @V = @W, @V;
276   
277  if( @DEBUG )
278  {
279    "Sstep::NextInput: ";
280    M;
281    deg(M[1..ncols(M)]); // no use of @W :(?
282    @RANK;   
283    DetailedPrint(MRES);
284    attrib(MRES, "isHomog"); @W;
285    deg(MRES[1..ncols(MRES)]);
286  }
287
288 
289     
290  SetInducedReferrence(L, limit, 0);
291 
292  def K = prepareSyz(M, @RANK);
293//  K;
294 
295//   attrib(K, "isHomog", @V);   DetailedPrint(K, 1000);
296
297//  pause();
298 
299  K = idPrepare(K, @RANK); // std(K); // ?
300  K = simplify(K, 2);
301
302//  K;
303
304  module N = separateSyzGB(K, @RANK)[2]; // 1^st syz. module: vectors which start in lower part (comp >= @RANK)
305
306// "N_0: "; N; DetailedPrint(N, 10);
307
308//  basering; print(@V); type(N);
309//  attrib(N, "isHomog", @V);  // TODO: fix "wrong weights"!!!? deg is wrong :(((
310  N = std(N);
311  attrib(N, "isHomog", @V);
312
313//  N;
314 
315  if( @DEBUG )
316  {
317    if( size(N) > 0 )
318    {
319      // next syz. property
320      if( size(module(transpose( transpose(N) * transpose(MRES) ))) > 0 )
321      {
322        MRES;
323
324        "N: "; N; DetailedPrint(N, 10);
325
326        "K:"; K; DetailedPrint(K, 10);
327
328        "RANKS: ", @RANK;
329
330        "transpose( transpose(N) * transpose(MRES) ) != 0!!!";
331        transpose( transpose(N) * transpose(MRES) );
332
333        "transpose(N) * transpose(MRES): ";
334        transpose(N) * transpose(MRES);
335        DetailedPrint(module(_), 2);
336        $
337      }
338    }
339  }
340 
341  RES[@l + 1] = N; // list of all syzygy modules
342 
343  MRES = MRES, N;
344  attrib(MRES, "isHomog", @V);
345
346
347  L = L, lead(N);
348  attrib(basering, "InducionLeads", L);
349
350  if( @DEBUG )
351  {
352    "Sstep::NextSyzOutput: ";
353    DetailedPrint(N);
354    attrib(N, "isHomog");
355  }
356
357}
358
359proc Scontinue(int l)
360"USAGE:  Scontinue(int len)
361RETURN:  nothing, instead it changes the currently active resolution
362PURPOSE: extends the currently active resolution by at most len syzygies
363ASSUME:  must be used within a ring returned by Sres or Ssyz
364EXAMPLE: example Scontinue; shows an example
365"
366{
367  def data = GetInducedData();
368           
369  if( (!defined(RES)) || (!defined(MRES)) || (typeof(data) != "list") || (size(data) != 2) )
370  {
371    ERROR("Sorry, but basering does not seem to be returned by Sres or Ssyz");
372  }
373  for (;  (l != 0) && (size(RES[size(RES)]) > 0); l-- )
374  {
375    Sstep();
376  }
377}
378example
379{ "EXAMPLE:"; echo = 2;
380  ring r;
381  module M = maxideal(1); M;
382  def S = Ssyz(M); setring S; S;
383  "Only the first syzygy: ";
384  RES; MRES;
385  "More syzygies: ";
386  Scontinue(10);
387  RES; MRES;
388}
389
390proc Ssyz(module M)
391"USAGE:  Ssyz(module M)
392RETURN:  ring, containing a Schreyer resolution
393PURPOSE: computes a Schreyer resolution of M of length 1 (see the library overview)
394SEE ALSO: Sres
395EXAMPLE: example Ssyz; shows an example
396"
397{
398  def S = Sinit(M); setring S;
399 
400  Sstep(); // NOTE: what if M is zero?
401
402  return (S);
403}
404example
405{ "EXAMPLE:"; echo = 2;
406  ring r;
407  module M = maxideal(1); M;
408  def S = Ssyz(M); setring S; S;
409  "Only the first syzygy: ";
410  RES;
411  MRES; // Note gen(i)
412  kill S;
413  setring r; kill M;
414
415  module M = 0;
416  def S = Ssyz(M); setring S; S;
417  "Only the first syzygy: ";
418  RES;
419  MRES;
420}
421
422proc Sres(module M, int l)
423"USAGE:  Sres(module M, int len)
424RETURN:  ring, containing a Schreyer resolution
425PURPOSE: computes a Schreyer resolution of M of length at most len (see the library overview)
426NOTE:    If given len is zero then nvars(basering) + 1 is used instead.
427SEE ALSO: Ssyz
428EXAMPLE: example Sres; shows an example
429"
430{
431  def S = Sinit(M); setring S;
432
433  if (l == 0)
434  {
435    l = nvars(basering) + 1; // not really an estimate...?!
436  }
437 
438  Sstep(); l = l - 1;
439 
440  Scontinue(l);
441 
442  return (S);
443}
444example
445{ "EXAMPLE:"; echo = 2;
446  ring r;
447  module M = maxideal(1); M;
448  def S = Sres(M, 0); setring S; S;
449  RES;
450  MRES;
451  kill S;
452  setring r; kill M;
453
454  def A = nc_algebra(-1,0); setring A;
455  ideal Q = var(1)^2, var(2)^2, var(3)^2;
456  qring SCA = twostd(Q);
457  basering;
458
459  module M = maxideal(1);
460  def S = Sres(M, 2); setring S; S;
461  RES;
462  MRES;
463}
464
465
466
467// ================================================================== //
468
469
470LIB "general.lib"; // for sort
471
472/* static proc Tail(def M) // DONE: in C++ (dyn. module: syzextra)!
473{
474  int i = ncols(M); def m;
475  while (i > 0)
476  {
477    m = M[i];
478    m = m - lead(m); // m = tail(m)   
479    M[i] = m;   
480    i--;
481  }
482  return (M);
483}*/
484
485
486/* static */ proc SSinit(def M)
487{
488  if( (typeof(M) != "module") && (typeof(M) != "ideal") )
489  {
490    ERROR("Sorry: need an ideal or a module for input");
491  }
492
493  // TODO! DONE?
494  def @save = basering;
495 
496  int @DEBUG = !system("with", "ndebug");
497  int @SYZCHECK = 1 || @DEBUG; // TODO: only for now!!
498 
499  if( @DEBUG )
500  {
501    "SSinit::Input";
502    type(M);
503//    DetailedPrint(M);
504    attrib(M);
505  }
506
507  int @RANK = nrows(M); int @SIZE = ncols(M);
508
509  int @IS_A_SB = attrib(M, "isSB"); // ??? only if all weights were zero?!
510
511  if( !@IS_A_SB )
512  {
513    def opts = option(get);
514    option(redSB); option(redTail);
515    M = std(M);
516    option(set, opts);
517    kill opts;
518  } else
519  {
520    M = simplify(M, 2 + 4 + 32);
521  }
522
523  def LEAD = lead(M);
524
525  // sort wrt neg.deg.rev.lex!
526  intvec iv_ds = sort(LEAD, "ds", 1)[2]; // ,1 => reversed!
527
528  M = M[iv_ds]; // sort M wrt ds on current leading terms
529  LEAD = LEAD[iv_ds];
530 
531  def TAIL = Tail(M);
532 
533  intvec @DEGS = deg(M[1..@SIZE]); // store actuall degrees of input elements
534 
535  // TODO: what about real modules? weighted ones?
536 
537  list @l = ringlist(@save);
538
539  int @z = 0; ideal @m = maxideal(1); intvec @wdeg = deg(@m[1..ncols(@m)]);
540
541  // NOTE: @wdeg will be ignored anyway :(
542  @l[3] = list(list("C", @z), list("lp", @wdeg));
543
544  kill @z, @wdeg; // since these vars are ring independent!
545
546  def S = ring(@l); // --MakeInducedSchreyerOrdering(1);
547
548  module F = freemodule(@RANK);
549  intvec @V = deg(F[1..@RANK]);
550 
551  setring S; // ring with an easy divisibility test ("C, lex")
552
553  if( @DEBUG )
554  {
555    "SSinit::NewRing(C, lex)";
556    basering;
557//    DetailedPrint(basering);
558  }
559
560  // Setup the leading syzygy^{-1} module to zero:
561  module Z = 0; Z[@RANK] = 0; attrib(Z, "isHomog", intvec(0)); 
562
563  module MRES = Z;
564 
565  list RES;  RES[1] = Z;
566  list LRES; LRES[1] = Z;
567  list TRES; TRES[1] = Z;
568 
569  def M = imap(@save, M);
570
571  attrib(M, "isHomog", @V);
572  attrib(M, "isSB", 1);
573  attrib(M, "degrees", @DEGS); 
574 
575  def LEAD = imap(@save, LEAD);
576 
577  attrib(LEAD, "isHomog", @V);
578  attrib(LEAD, "isSB", 1); 
579 
580  def TAIL = imap(@save, TAIL);
581
582  if( @DEBUG )
583  {
584    "SSinit::(sorted) SB_Input: ";
585    type(M);
586    attrib(M);
587    attrib(M, "isHomog");
588//    DetailedPrint(M);
589  }
590
591  if( @SYZCHECK )
592  {
593    // 0^th syz. property
594    if( size(module(transpose( transpose(M) * transpose(MRES) ))) > 0 )
595    {
596      transpose( transpose(M) * transpose(MRES) );
597      "ERROR: transpose( transpose(M) * transpose(MRES) ) != 0!!!";
598      $
599    }
600  }
601
602  RES[size(RES)+1] = M; // list of all syzygy modules
603  LRES[size(LRES)+1] = LEAD; // list of all syzygy modules
604  TRES[size(TRES)+1] = TAIL; // list of all syzygy modules
605 
606  MRES = MRES, M; //?
607
608  attrib(MRES, "isHomog", @V);
609 
610//  attrib(S, "InducionStart", @RANK);
611  attrib(S, "LEAD2SYZ", 1);
612  attrib(S, "TAILREDSYZ", 0);
613  attrib(S, "DEBUG", @DEBUG);
614  attrib(S, "SYZCHECK", @SYZCHECK);
615 
616  if( @DEBUG )
617  {
618    "SSinit::MRES";
619    MRES;
620//    DetailedPrint(MRES);
621    attrib(MRES, "isHomog");
622    attrib(S);
623  }
624
625  export RES;
626  export MRES;
627  export LRES;
628  export TRES;
629  return (S);
630}
631example
632{ "EXAMPLE:"; echo = 2;
633  ring R = 0, (w, x, y, z), dp;
634
635  def M = maxideal(1);
636  def S = SSinit(M); setring S; S;
637 
638  "Only the first initialization: ";
639  RES; LRES; TRES;
640  MRES;
641
642  kill S; setring R; kill M;
643 
644  ideal M = w^2 - x*z,  w*x - y*z,  x^2 - w*y, x*y - z^2, y^2 - w*z;
645  def S = SSinit(M); setring S; S;
646
647  "Only the first initialization: ";
648  RES; LRES; TRES;
649  MRES;
650
651  kill S; setring R; kill M;
652}
653
654
655LIB "poly.lib"; // for lcm
656
657
658
659/// Compute L(Syz(L))
660proc SSComputeLeadingSyzygyTerms(def L)
661{
662  if( typeof( attrib(basering, "DEBUG") ) == "int" )
663  {
664    int @DEBUG = attrib(basering, "DEBUG");
665  } else
666  {
667    int @DEBUG = !system("with", "ndebug");
668  }
669
670  if( @DEBUG )
671  {
672    "SSComputeLeadingSyzygyTerms::Input: ";
673    L;
674  }
675
676  int i, j, r; intvec iv_ds;
677  int N = ncols(L);
678  def a, b;
679  poly aa, bb;
680
681  bigint c;
682
683  ideal M;
684
685  module S = 0;
686 
687  for(i = 1; i <= N; i++)
688  {
689    a = L[i];
690//    "a: ", a;
691    c = leadcomp(a);
692    r = int(c);
693
694    if(r > 0)
695    {
696      aa = a[r];
697    } else
698    {
699      aa = a;
700    }
701
702    M = 0;
703   
704    for(j = i-1; j > 0; j--)
705    {
706      b = L[j];
707//      "b: ", b;
708
709      if( leadcomp(b) == c )
710      {
711        if(r > 0)
712        {
713          bb = b[r];
714        } else
715        {
716          bb = b;
717        }
718
719        M[j] = (lcm(aa, bb) / aa);
720      }
721    }
722   
723    // TODO: add quotient relations here...
724
725    M = simplify(M, 1 + 2 + 32);
726
727    iv_ds = sort(M, "ds", 1)[2]; // ,1 => reversed!
728
729    M = M[iv_ds];
730   
731    S = S, M * gen(i);
732  }
733
734  S = simplify(S, 2);
735
736  S = sort(S, "ds", 1)[1]; // ,1 => reversed! // TODO: not needed?
737 
738  if( @DEBUG )
739  {
740    "SSComputeLeadingSyzygyTerms::Output: ";
741    S;
742  } 
743
744  attrib(S, "isSB", 1);
745
746  return (S);
747}
748
749/// Compute Syz(L), where L is a monomial (leading) module
750proc SSCompute2LeadingSyzygyTerms(def L, int @TAILREDSYZ)
751{
752  if( typeof( attrib(basering, "DEBUG") ) == "int" )
753  {
754    int @DEBUG = attrib(basering, "DEBUG");
755  } else
756  {
757    int @DEBUG = !system("with", "ndebug");
758  }
759
760  if( typeof( attrib(basering, "SYZCHECK") ) == "int" )
761  {
762    int @SYZCHECK = attrib(basering, "SYZCHECK");
763  } else
764  {
765    int @SYZCHECK = @DEBUG;
766  }
767 
768
769  if( @DEBUG )
770  {
771    "SSCompute2LeadingSyzygyTerms::Input: ";
772    L;
773    "@TAILREDSYZ: ", @TAILREDSYZ;
774  }
775
776  int i, j, r;
777  int N = ncols(L);
778  def a, b;
779
780  poly aa, bb, @lcm;
781
782  bigint c;
783
784  module M;
785
786  module S = 0;
787
788  for(i = 1; i <= N; i++)
789  {
790    a = L[i];
791//    "a: ", a;
792    c = leadcomp(a);
793    r = int(c);
794
795    aa = leadmonomial(a);
796
797    M = 0;
798
799    for(j = i-1; j > 0; j--)
800    {
801      b = L[j];
802//      "b: ", b;
803
804      if( leadcomp(b) == c )
805      {
806        bb = leadmonomial(b);
807        @lcm = lcm(aa, bb);
808
809        M[j] = (@lcm / aa)* gen(i) - (@lcm / bb)* gen(j);
810      }
811    }
812   
813    M = simplify(M, 2);
814
815    // TODO: add quotient relations here...
816    S = S, M;
817  }
818
819  if( @TAILREDSYZ )
820  {
821    // Make sure that 2nd syzygy terms are not reducible by 1st
822    def opts = option(get);
823    option(redSB); option(redTail);
824    S = std(S); // binomial module
825    option(set, opts);
826    //  kill opts;
827  } else
828  {
829    S = simplify(S, 2 + 32);
830  }
831
832  S = sort(S, "ds", 1)[1]; // ,1 => reversed!
833
834  if( @DEBUG )
835  {
836    "SSCompute2LeadingSyzygyTerms::Syz(LEAD): "; S;
837  }
838
839  if( @SYZCHECK )
840  {
841    if( size(S) > 0 and size(L) > 0 )
842    {
843      if( size(module(transpose( transpose(S) * transpose(L) ))) > 0 )
844      {
845        transpose( transpose(S) * transpose(L) );
846        "ERROR: transpose( transpose(S) * transpose(L) ) != 0!!!";
847        $
848      }
849    }
850  }
851
852  module S2 = Tail(S);
853  S = lead(S); // (C,lp) on base ring!
854             
855  if( @DEBUG )
856  {
857    "SSCompute2LeadingSyzygyTerms::Output: "; S; S2;
858  } 
859 
860  attrib(S, "isSB", 1);
861
862  return (S, S2);
863}
864
865// -------------------------------------------------------- //
866
867/// TODO: save shortcut LM(m) * "t" -> ?
868proc SSReduceTerm(poly m, def t, def L, def T, list #)
869{
870  if( typeof( attrib(basering, "DEBUG") ) == "int" )
871  {
872    int @DEBUG = attrib(basering, "DEBUG");
873  } else
874  {
875    int @DEBUG = !system("with", "ndebug");
876  }
877
878  if( @DEBUG )
879  {
880    "SSReduce::Input: ";
881
882    "mult: ", m;
883    "term: ", t;
884    "L: ", L;
885    "T: ", T;
886    if( size(#) > 0 )
887    {
888      "LSyz: ", #;
889    }
890//    "attrib(LS, 'isSB')", attrib(LS, "isSB");
891  }
892 
893  vector s = 0;
894
895  if( t == 0 )
896  {
897    return (s);
898  }
899
900  def product = m * t;
901
902  bigint c = leadcomp(t);
903  int r = int(c);
904 
905  def a, b, nf, bb;
906
907  // looking for an appropriate reducer
908  for( int k = ncols(L); k > 0; k-- )
909  {
910    a = L[k];
911    // with the same mod. component
912    if( leadcomp(a) == c )
913    {
914      b = - (leadmonomial(product) / leadmonomial(L[k]));
915     
916      // which divides the product
917      if( b != 0 )
918      {
919//        "b: ", b;
920        bb = b * gen(k);
921        nf = bb;
922
923        if( size(#) > 0 )
924        {
925          if( typeof(#[1]) == "module" )
926          {
927            nf = NF(bb, #[1]);
928//        "NF: ", nf;
929          }
930        }
931
932        // while the complement (the fraction) is not reducible by leading syzygies
933        if( nf != 0 )
934        {
935          /// TODO: save shortcut LM(m) * T[i] -> ?
936
937          // choose ANY such reduction... (with the biggest index?)
938          s = bb + SSTraverseTail(b, T[k], L, T, #);
939          break;
940        }
941      }
942    }
943  } 
944  if( @DEBUG )
945  {
946    "SSReduceTerm::Output: ", s;
947  }
948  return (s);
949}
950
951// TODO: store m * @tail -.-^-.-^-.--> ?
952proc SSTraverseTail(poly m, def @tail, def L, def T, list #)
953{
954  if( typeof( attrib(basering, "DEBUG") ) == "int" )
955  {
956    int @DEBUG = attrib(basering, "DEBUG");
957  } else
958  {
959    int @DEBUG = !system("with", "ndebug");
960  }
961
962  if( @DEBUG )
963  {
964    "SSTraverse::Input: ";
965
966    "mult: ", m;
967    "tail: ", @tail; // T[i];
968
969    if( size(#) > 0 )
970    {
971      "LSyz: "; #[1];
972    }
973  }
974
975  vector s = 0;
976
977  def @l;
978
979  // iterate tail-terms in ANY order!
980  while( size(@tail) > 0 )
981  {
982    @l = lead(@tail);
983    s = s + SSReduceTerm(m, @l, L, T, #);
984    @tail = @tail - @l;
985  }
986
987  if( @DEBUG )
988  {
989    "SSTraverseTail::Output: ", s;
990  }
991  return (s);
992}
993
994// -------------------------------------------------------- //
995
996// module (N, LL, TT) = SSComputeSyzygy(L, T);
997// Compute Syz(L ++ T) = N = LL ++ TT
998proc SSComputeSyzygy(def L, def T)
999{
1000  if( typeof( attrib(basering, "DEBUG") ) == "int" )
1001  {
1002    int @DEBUG = attrib(basering, "DEBUG");
1003  } else
1004  {
1005    int @DEBUG = !system("with", "ndebug");
1006  }
1007 
1008  if( @DEBUG )
1009  {
1010    "SSComputeSyzygy::Input";
1011    "basering: ", basering; attrib(basering);
1012//    DetailedPrint(basering);
1013
1014//    "iCompShift: ", iCompShift;
1015
1016    "L: "; L;
1017    "T: "; T;
1018  }
1019
1020  def a; bigint c; int r, k; poly aa;
1021
1022  int @LEAD2SYZ = 0;
1023  if( typeof( attrib(basering, "LEAD2SYZ") ) == "int" )
1024  {
1025    @LEAD2SYZ = attrib(basering, "LEAD2SYZ");
1026  }
1027
1028  int @TAILREDSYZ = 1;
1029  if( typeof( attrib(basering, "TAILREDSYZ") ) == "int" )
1030  {
1031    @TAILREDSYZ = attrib(basering, "TAILREDSYZ");
1032//    @TAILREDSYZ;
1033  }
1034 
1035  /// Get the critical leading syzygy terms
1036  if( @LEAD2SYZ ) // & 2nd syz. term
1037  {
1038    def a2; int r2; poly aa2; 
1039    module LL, LL2;
1040    (LL, LL2) = SSCompute2LeadingSyzygyTerms(L, @TAILREDSYZ); // ++
1041  } else
1042  {
1043    module LL = SSComputeLeadingSyzygyTerms(L);
1044  }
1045
1046  module TT, SYZ;
1047
1048  if( size(LL) > 0 )
1049  {
1050    list LS;
1051
1052    if( @TAILREDSYZ )
1053    {
1054      LS = list(LL);
1055    }
1056   
1057    vector @tail;
1058
1059    for(k = ncols(LL); k > 0; k-- )
1060    {
1061      // leading syz. term:
1062      a = LL[k]; c = leadcomp(a); r = int(c); aa = leadmonomial(a);
1063      //    "A: ", a, " --->>>> ", aa, " **** [", r, "]: ";
1064
1065      /// TODO: save shortcut (aa) * T[r] -> ?
1066      @tail = SSTraverseTail(aa, T[r], L, T, LS);
1067             
1068      // get the 2nd syzygy term...
1069     
1070      if( @LEAD2SYZ ) // with the 2nd syz. term:
1071      {     
1072        a2 = LL2[k]; c = leadcomp(a2); r2 = int(c); aa2 = leadmonomial(a2);
1073        @tail = @tail +
1074             /// TODO: save shortcut (aa2) * T[r2] -> ?
1075             a2 + SSTraverseTail(aa2, T[r2], L, T, LS);
1076      } else
1077      {
1078        @tail = @tail + SSReduceTerm(aa, L[r], L, T, LS);
1079      }
1080     
1081     
1082      TT[k] = @tail;
1083      SYZ[k] = a + @tail;
1084    }
1085  }
1086
1087/*
1088  def opts = option(get); option(redSB); option(redTail);
1089  module SYZ = std(syz(M));
1090  option(set, opts); kill opts;
1091 
1092  module LL = lead(SYZ); // TODO: WRONG ORDERING!!!!!!!!
1093  module TT = Tail(SYZ);
1094*/
1095 
1096  if( @DEBUG )
1097  {
1098    "SSComputeSyzygy::Output";
1099
1100    "SYZ: "; SYZ;
1101    "LL: "; LL;
1102    "TT: "; TT;
1103  }
1104
1105  return (SYZ, LL, TT);
1106}
1107
1108// resolution/syzygy step:
1109static proc SSstep()
1110{
1111  if( typeof( attrib(basering, "DEBUG") ) == "int" )
1112  {
1113    int @DEBUG = attrib(basering, "DEBUG");
1114  } else
1115  {
1116    int @DEBUG = !system("with", "ndebug");
1117  }
1118
1119
1120  if( typeof( attrib(basering, "SYZCHECK") ) == "int" )
1121  {
1122    int @SYZCHECK = attrib(basering, "SYZCHECK");
1123  } else
1124  {
1125    int @SYZCHECK = @DEBUG;
1126  }
1127
1128  if( @DEBUG )
1129  {
1130    "SSstep::NextInducedRing";
1131    "basering: ", basering; attrib(basering);
1132  }
1133
1134/*
1135  // is initial weights are all zeroes!
1136  def L =  lead(M);
1137  intvec @V = deg(M[1..ncols(M)]);  @W;  @V;  @W = @V;  attrib(L, "isHomog", @W); 
1138  SetInducedReferrence(L, @RANK, 0);
1139*/
1140
1141//  def L =  lead(MRES);
1142//  @W = @W, @V;
1143//  attrib(L, "isHomog", @W); 
1144
1145
1146  // General setting:
1147//  SetInducedReferrence(MRES, 0, 0); // limit: 0!
1148  int @l = size(RES);
1149
1150  def M =  RES[@l];
1151
1152  def L = LRES[@l];
1153  def T = TRES[@l];
1154
1155
1156  //// TODO: wrong !!!!!
1157  int @RANK = ncols(MRES) - ncols(M); // nrows(M); // what if M is zero?!
1158
1159 
1160
1161/*
1162  if( @RANK !=  nrows(M) )
1163  {
1164    type(MRES);
1165    @RANK;
1166    type(M);
1167    pause();
1168  }
1169*/
1170 
1171  intvec @W = attrib(M, "isHomog"); intvec @V = attrib(M, "degrees"); @V = @W, @V;
1172   
1173  if( @DEBUG )
1174  {
1175    "Sstep::NextInput: ";
1176    M;
1177    L;
1178    @V;
1179    @RANK;
1180//    DetailedPrint(MRES);
1181    attrib(MRES, "isHomog");
1182  }
1183
1184     
1185  // TODO: N  = SYZ( M )!!!
1186  module N, LL, TT;
1187  (N, LL, TT) = SSComputeSyzygy(/*M, */L, T/*, @RANK*/);
1188
1189  // shift syz.comp by @RANK:
1190  module Z;
1191  Z = 0; Z[@RANK] = 0; Z = Z, transpose(LL);   LL = transpose(Z);
1192  Z = 0; Z[@RANK] = 0; Z = Z, transpose(TT);   TT = transpose(Z);
1193  Z = 0; Z[@RANK] = 0; Z = Z, transpose(N);     N = transpose(Z);
1194
1195
1196  if( @SYZCHECK )
1197  {
1198    if( size(N) > 0 )
1199    {
1200      // next syz. property
1201      if( size(module(transpose( transpose(N) * transpose(MRES) ))) > 0 )
1202      {
1203        "MRES", MRES;
1204
1205        "N: "; N; // DetailedPrint(N, 2);
1206
1207        "LL:"; LL; // DetailedPrint(LL, 1);
1208        "TT:"; TT; // DetailedPrint(TT, 10);
1209
1210        "RANKS: ", @RANK;
1211
1212        "transpose( transpose(N) * transpose(MRES) ) != 0!!!";
1213        transpose( transpose(N) * transpose(MRES) );
1214
1215        "transpose(N) * transpose(MRES): ";
1216        transpose(N) * transpose(MRES);
1217        // DetailedPrint(module(_), 2);
1218        $
1219      }
1220    }
1221  }
1222
1223  attrib(N, "isHomog", @V);
1224
1225  // TODO: correct the following:
1226  intvec @DEGS = deg(N[1..ncols(N)]); // no mod. comp. weights :(
1227
1228 
1229  attrib(N, "degrees", @DEGS);
1230 
1231   RES[@l + 1] = N; // list of all syzygy modules
1232  LRES[@l + 1] = LL; // list of all syzygy modules
1233  TRES[@l + 1] = TT; // list of all syzygy modules
1234
1235  MRES = MRES, N;
1236 
1237  attrib(MRES, "isHomog", @V);
1238
1239//  L = L, lead(N);  attrib(basering, "InducionLeads", L);
1240
1241  if( @DEBUG )
1242  {
1243    "SSstep::NextSyzOutput: ";
1244    N;
1245//    DetailedPrint(N);
1246    attrib(N);
1247  }
1248
1249}
1250
1251proc SScontinue(int l)
1252"USAGE:  SScontinue(l)
1253RETURN:  nothing, instead it changes RES and MRES variables in the current ring
1254PURPOSE: computes further (at most l) syzygies
1255NOTE:    must be used within a ring returned by Sres or Ssyz. RES and MRES are
1256         explained in Sres
1257EXAMPLE: example Scontinue; shows an example
1258"
1259{
1260
1261  /// TODO!
1262//  def data = GetInducedData();
1263
1264  if( (!defined(RES)) || (!defined(MRES)) ) /* || (typeof(data) != "list") || (size(data) != 2) */
1265  {
1266    ERROR("Sorry, but basering does not seem to be returned by Sres or Ssyz");
1267  }
1268  for (;  (l != 0) && (size(RES[size(RES)]) > 0); l-- )
1269  {
1270    SSstep();
1271  }
1272}
1273example
1274{ "EXAMPLE:"; echo = 2;
1275  ring r;
1276  module M = maxideal(1); M;
1277  def S = SSsyz(M); setring S; S;
1278  "Only the first syzygy: ";
1279  RES; MRES;
1280  "More syzygies: ";
1281  SScontinue(10);
1282  RES; MRES;
1283}
1284
1285proc SSsyz(def M)
1286"USAGE:  SSsyz(M)
1287RETURN:  ring, containing a list of modules RES and a module MRES
1288PURPOSE: computes the first syzygy module of M (wrt some Schreyer ordering)?
1289NOTE:    The output is explained in Sres
1290EXAMPLE: example Ssyz; shows an example
1291"
1292{
1293  if( (typeof(M) != "module") && (typeof(M) != "ideal") )
1294  {
1295    ERROR("Sorry: need an ideal or a module for input");
1296  }
1297
1298  def SS = SSinit(M); setring SS;
1299 
1300  SSstep(); // NOTE: what if M is zero?
1301
1302  return (SS);
1303}
1304example
1305{ "EXAMPLE:"; echo = 2;
1306  ring r;
1307
1308/*  ideal M = 0;
1309  def S = SSsyz(M); setring S; S;
1310  "Only the first syzygy: ";
1311  RES; LRES; TRES;
1312  MRES;
1313 
1314  kill S; setring r; kill M;
1315*/ 
1316
1317  module M = maxideal(1); M;
1318  def S = SSres(M, 0); setring S; S;
1319  MRES;
1320  RES;
1321  "";
1322  LRES;
1323  "";
1324  TRES;
1325
1326  kill S; setring r; kill M;
1327
1328  kill r;
1329 
1330  ring R = 0, (w, x, y, z), dp;
1331  ideal M = w^2 - x*z,  w*x - y*z,  x^2 - w*y, x*y - z^2, y^2 - w*z;
1332 
1333  def S = SSres(M, 0); setring S; S;
1334  MRES;
1335  RES;
1336  "";
1337  LRES;
1338  "";
1339  TRES;
1340}
1341
1342proc SSres(def M, int l)
1343"USAGE:  SSres(I, l)
1344RETURN:  ring, containing a list of modules RES and a module MRES
1345PURPOSE: computes (at most l) syzygy modules of M wrt the classical Schreyer
1346         induced ordering with gen(i) > gen(j) if i > j, provided both gens
1347         are from the same syzygy level.???
1348NOTE:    RES contains the images of maps subsituting the beginning of the
1349         Schreyer free resolution of baseRing^r/M, while MRES is a sum of
1350         these images in a big free sum, containing all the syzygy modules.
1351         The syzygy modules are shifted so that gen(i) correspons to MRES[i].
1352         The leading zero module RES[0] indicates the fact that coker of the
1353         first map is zero. The number of zeroes inducates the rank of input.
1354NOTE:    If l == 0 then l is set to be nvars(basering) + 1
1355EXAMPLE: example SSres; shows an example
1356"
1357{
1358  if( (typeof(M) != "module") && (typeof(M) != "ideal") )
1359  {
1360    ERROR("Sorry: need an ideal or a module for input");
1361  }
1362
1363  def SS = SSinit(M); setring SS;
1364
1365  if (l == 0)
1366  {
1367    l = nvars(basering) + 1; // not really an estimate...?!
1368  }
1369
1370  SSstep(); l = l - 1;
1371
1372  SScontinue(l);
1373
1374  return (SS);
1375}
1376example
1377{ "EXAMPLE:"; echo = 2;
1378  ring r;
1379  module M = maxideal(1); M;
1380  def S = SSres(M, 0); setring S; S;
1381  RES;
1382  MRES;
1383  kill S;
1384  setring r; kill M;
1385
1386  def A = nc_algebra(-1,0); setring A;
1387  ideal Q = var(1)^2, var(2)^2, var(3)^2;
1388  qring SCA = twostd(Q);
1389  basering;
1390
1391  module M = maxideal(1);
1392  def S = SSres(M, 2); setring S; S;
1393  RES;
1394  MRES;
1395}
1396
1397
1398
1399static proc loadme()
1400{
1401  int @DEBUG = !system("with", "ndebug");
1402
1403  if( @DEBUG )
1404  {
1405   
1406    "ndebug?: ", system("with", "ndebug");
1407    "om_ndebug?: ", system("with", "om_ndebug");
1408
1409    listvar(Top);
1410    listvar(Schreyer);
1411  }
1412//  listvar(Syzextra); listvar(Syzextra_g);
1413
1414  if( !defined(DetailedPrint) )
1415  {
1416    if( 1 )
1417    {
1418
1419      if( @DEBUG )
1420      {
1421        "Loading the Release version!";
1422      }
1423      load("syzextra.so");
1424
1425      if( @DEBUG )
1426      {
1427        listvar(Syzextra);
1428      }
1429
1430      exportto(Top, Syzextra::ClearContent);
1431      exportto(Top, Syzextra::ClearDenominators);
1432     
1433//      export Syzextra;
1434
1435//      exportto(Schreyer, Syzextra::noop);
1436      exportto(Schreyer, Syzextra::DetailedPrint);
1437      exportto(Schreyer, Syzextra::leadmonomial);
1438      exportto(Schreyer, Syzextra::leadcomp);
1439//      exportto(Schreyer, Syzextra::leadrawexp);
1440//      exportto(Schreyer, Syzextra::ISUpdateComponents);
1441      exportto(Schreyer, Syzextra::SetInducedReferrence);
1442      exportto(Schreyer, Syzextra::GetInducedData);
1443//      exportto(Schreyer, Syzextra::GetAMData);
1444//      exportto(Schreyer, Syzextra::SetSyzComp);
1445      exportto(Schreyer, Syzextra::MakeInducedSchreyerOrdering);
1446//      exportto(Schreyer, Syzextra::MakeSyzCompOrdering);
1447      exportto(Schreyer, Syzextra::idPrepare);
1448//      exportto(Schreyer, Syzextra::reduce_syz);
1449//      exportto(Schreyer, Syzextra::p_Content);
1450
1451      exportto(Schreyer, Syzextra::ProfilerStart); exportto(Schreyer, Syzextra::ProfilerStop);
1452
1453      exportto(Schreyer, Syzextra::Tail);
1454
1455      exportto(Schreyer, Syzextra::m2_end);
1456    }
1457/*
1458    else
1459    {
1460      if( @DEBUG )
1461      {
1462        "Loading the Debug version!";
1463      }
1464
1465      load("syzextra.so");
1466
1467      if( @DEBUG )
1468      {     
1469        listvar(Syzextra_g);
1470      }
1471     
1472      exportto(Top, Syzextra_g::ClearContent);
1473      exportto(Top, Syzextra_g::ClearDenominators);
1474
1475//      export Syzextra_g;
1476//      exportto(Schreyer, Syzextra_g::noop);
1477      exportto(Schreyer, Syzextra_g::DetailedPrint);
1478      exportto(Schreyer, Syzextra_g::leadmonomial);
1479      exportto(Schreyer, Syzextra_g::leadcomp);
1480//      exportto(Schreyer, Syzextra_g::leadrawexp);
1481//      exportto(Schreyer, Syzextra_g::ISUpdateComponents);
1482      exportto(Schreyer, Syzextra_g::SetInducedReferrence);
1483      exportto(Schreyer, Syzextra_g::GetInducedData);
1484//      exportto(Schreyer, Syzextra_g::GetAMData);
1485//      exportto(Schreyer, Syzextra_g::SetSyzComp);
1486      exportto(Schreyer, Syzextra_g::MakeInducedSchreyerOrdering);
1487//      exportto(Schreyer, Syzextra_g::MakeSyzCompOrdering);
1488      exportto(Schreyer, Syzextra_g::idPrepare);
1489//      exportto(Schreyer, Syzextra_g::reduce_syz);
1490//      exportto(Schreyer, Syzextra_g::p_Content);
1491
1492      exportto(Schreyer, Syzextra_g::ProfilerStart); exportto(Schreyer, Syzextra_g::ProfilerStop);
1493
1494      exportto(Schreyer, Syzextra_g::Tail);
1495     
1496     
1497      exportto(Schreyer, Syzextra_g::m2_end);
1498    }
1499*/
1500
1501    exportto(Top, DetailedPrint);
1502    exportto(Top, GetInducedData);
1503
1504    if( @DEBUG )
1505    {
1506      listvar(Top);
1507      listvar(Schreyer);
1508    }
1509  }
1510 
1511  if( !defined(GetInducedData) )
1512  {
1513    ERROR("Sorry but we are missing the dynamic module (syzextra.so)...");
1514  }
1515
1516}
1517
1518static proc mod_init()
1519{
1520  loadme();
1521}
1522
1523
1524proc testallSexamples()
1525{
1526  example Ssyz;
1527  example Scontinue;
1528  example Sres; 
1529}
1530
1531proc testallSSexamples()
1532{
1533  example SSsyz;
1534  example SScontinue;
1535  example SSres; 
1536}
1537
1538example
1539{ "EXAMPLE:"; echo = 2;
1540  testallSexamples();
1541  testallSSexamples();
1542}
Note: See TracBrowser for help on using the repository browser.