source: git/dyn_modules/syzextra/syzextra.cc @ daa4e5

spielwiese
Last change on this file since daa4e5 was daa4e5, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Using s/k-buckets in TraverseTail and SchreyerSyzygyNF TODO: refine!
  • Property mode set to 100644
File size: 45.4 KB
Line 
1// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2/*****************************************************************************\
3 * Computer Algebra System SINGULAR   
4\*****************************************************************************/
5/** @file syzextra.cc
6 *
7 * Here we implement the Computation of Syzygies
8 *
9 * ABSTRACT: Computation of Syzygies due to Schreyer
10 *
11 * @author Oleksandr Motsak
12 *
13 **/
14/*****************************************************************************/
15
16// include header file
17#include <kernel/mod2.h>
18
19#include "syzextra.h"
20
21#include "DebugPrint.h"
22
23#include <omalloc/omalloc.h>
24
25#include <misc/intvec.h>
26#include <misc/options.h>
27
28#include <coeffs/coeffs.h>
29
30#include <polys/monomials/p_polys.h>
31#include <polys/monomials/ring.h>
32#include <polys/simpleideals.h>
33
34#include <polys/kbuckets.h> // for kBucket*
35#include <polys/nc/summator.h> // for CPolynomialSummator
36#include <polys/operations/p_Mult_q.h> // for MIN_LENGTH_BUCKET
37
38#include <kernel/kstd1.h>
39#include <kernel/polys.h>
40#include <kernel/syz.h>
41#include <kernel/ideals.h>
42
43#include <kernel/timer.h>
44
45
46#include <Singular/tok.h>
47#include <Singular/ipid.h>
48#include <Singular/lists.h>
49#include <Singular/attrib.h>
50
51#include <Singular/ipid.h> 
52#include <Singular/ipshell.h> // For iiAddCproc
53
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57
58// USING_NAMESPACE_SINGULARXX;
59USING_NAMESPACE( SINGULARXXNAME :: DEBUG )
60
61
62BEGIN_NAMESPACE_SINGULARXX     BEGIN_NAMESPACE(SYZEXTRA)
63
64
65BEGIN_NAMESPACE(SORT_c_ds)
66
67
68#ifdef _GNU_SOURCE
69static int cmp_c_ds(const void *p1, const void *p2, void *R)
70{
71#else
72static int cmp_c_ds(const void *p1, const void *p2)
73{
74  void *R = currRing; 
75#endif
76
77  const int YES = 1;
78  const int NO = -1;
79
80  const ring r =  (const ring) R; // TODO/NOTE: the structure is known: C, lp!!!
81
82  assume( r == currRing );
83
84  const poly a = *(const poly*)p1;
85  const poly b = *(const poly*)p2;
86
87  assume( a != NULL );
88  assume( b != NULL );
89
90  assume( p_LmTest(a, r) );
91  assume( p_LmTest(b, r) );
92
93
94  const signed long iCompDiff = p_GetComp(a, r) - p_GetComp(b, r);
95
96  // TODO: test this!!!!!!!!!!!!!!!!
97
98  //return -( compare (c, qsorts) )
99
100#ifndef NDEBUG
101  const int __DEBUG__ = 0;
102  if( __DEBUG__ )
103  {
104    PrintS("cmp_c_ds: a, b: \np1: "); dPrint(a, r, r, 2);
105    PrintS("b: "); dPrint(b, r, r, 2);
106    PrintLn();
107  }
108#endif
109
110
111  if( iCompDiff > 0 )
112    return YES;
113
114  if( iCompDiff < 0 )
115    return  NO;
116
117  assume( iCompDiff == 0 );
118
119  const signed long iDegDiff = p_Totaldegree(a, r) - p_Totaldegree(b, r);
120
121  if( iDegDiff > 0 )
122    return YES;
123
124  if( iDegDiff < 0 )
125    return  NO;
126
127  assume( iDegDiff == 0 );
128
129#ifndef NDEBUG
130  if( __DEBUG__ )
131  {
132    PrintS("cmp_c_ds: a & b have the same comp & deg! "); PrintLn();
133  }
134#endif
135
136  for (int v = rVar(r); v > 0; v--)
137  {
138    assume( v > 0 );
139    assume( v <= rVar(r) );
140
141    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
142
143    if( d > 0 )
144      return YES;
145
146    if( d < 0 )
147      return NO;
148
149    assume( d == 0 );
150  }
151
152  return 0; 
153}
154
155END_NAMESPACE
156/* namespace SORT_c_ds */
157
158/// return a new term: leading coeff * leading monomial of p
159/// with 0 leading component!
160poly leadmonom(const poly p, const ring r, const bool bSetZeroComp)
161{
162  poly m = NULL;
163
164  if( p != NULL )
165  {
166    assume( p != NULL );
167    assume( p_LmTest(p, r) );
168
169    m = p_LmInit(p, r);
170    p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r);
171
172    if( bSetZeroComp )
173      p_SetComp(m, 0, r);
174    p_Setm(m, r);
175
176   
177    assume( m != NULL );
178    assume( pNext(m) == NULL );
179    assume( p_LmTest(m, r) );
180   
181    if( bSetZeroComp )
182      assume( p_GetComp(m, r) == 0 );
183  }
184
185  return m;
186}
187
188
189   
190poly p_Tail(const poly p, const ring r)
191{
192  if( p == NULL)
193    return NULL;
194  else
195    return p_Copy( pNext(p), r );
196}
197
198
199ideal id_Tail(const ideal id, const ring r)
200{
201  if( id == NULL)
202    return NULL;
203
204  const ideal newid = idInit(IDELEMS(id),id->rank);
205 
206  for (int i=IDELEMS(id) - 1; i >= 0; i--)
207    newid->m[i] = p_Tail( id->m[i], r );
208
209  newid->rank = id_RankFreeModule(newid, currRing);
210
211  return newid; 
212}
213
214
215
216void Sort_c_ds(const ideal id, const ring r)
217{
218  const int sizeNew = IDELEMS(id);
219
220#ifdef _GNU_SOURCE
221#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp, r)
222#else
223#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp)
224#endif
225 
226  if( sizeNew >= 2 )
227    qsort_my(id->m, sizeNew, sizeof(poly), r, FROM_NAMESPACE(SORT_c_ds, cmp_c_ds));
228
229#undef qsort_my
230
231  id->rank = id_RankFreeModule(id, r);
232}
233
234/// Clean up all the accumulated data
235void SchreyerSyzygyComputation::CleanUp()
236{
237  extern void id_Delete (ideal*, const ring);
238   
239 id_Delete(const_cast<ideal*>(&m_idTails), m_rBaseRing); // TODO!!!   
240}
241  /*
242  for( TTailTerms::const_iterator it = m_idTailTerms.begin(); it != m_idTailTerms.end(); it++ )
243  {
244    const TTail& v = *it;
245    for(TTail::const_iterator vit = v.begin(); vit != v.end(); vit++ )
246      delete const_cast<CTailTerm*>(*vit);
247  }
248  */
249
250
251
252int CReducerFinder::PreProcessTerm(const poly t, CReducerFinder& syzChecker) const
253{
254  assume( t != NULL );
255
256  if( __DEBUG__ && __TAILREDSYZ__ )
257    assume( !IsDivisible(t) ); // each input term should NOT be in <L>
258
259  const ring r = m_rBaseRing;
260
261
262  if( __TAILREDSYZ__ )
263    if( p_LmIsConstant(t, r) ) // most basic case of baing coprime with L, whatever that is...
264      return 1; // TODO: prove this...?
265
266  //   return false; // appears to be fine
267
268  const long comp = p_GetComp(t, r);
269
270  CReducersHash::const_iterator itr = m_hash.find(comp);
271
272  if ( itr == m_hash.end() ) 
273    return 2; // no such leading component!!!
274
275  const bool bIdealCase = (comp == 0);   
276  const bool bSyzCheck = syzChecker.IsNonempty(); // need to check even in ideal case????? proof?  "&& !bIdealCase"
277
278  if( __TAILREDSYZ__ && (bIdealCase || bSyzCheck) )
279  {
280    const TReducers& v = itr->second;
281    const int N = rVar(r);
282    // TODO: extract exps of t beforehand?!
283    bool coprime = true;
284    for(TReducers::const_iterator vit = v.begin(); (vit != v.end()) && coprime; ++vit )
285    {
286      assume( m_L->m[(*vit)->m_label] == (*vit)->m_lt );
287
288      const poly p = (*vit)->m_lt;
289
290      assume( p_GetComp(p, r) == comp ); 
291
292      // TODO: check if coprime with Leads... if __TAILREDSYZ__ !
293      for( int var = N; var > 0; --var )
294        if( (p_GetExp(p, var, r) != 0) && (p_GetExp(t, var, r) != 0) )
295        {       
296          if( __DEBUG__ || 0)
297          {         
298            PrintS("CReducerFinder::PreProcessTerm, 't' is NOT co-prime with the following leading term: \n");
299            dPrint(p, r, r, 1);
300          }
301          coprime = false; // t not coprime with p!
302          break;
303        }
304
305      if( bSyzCheck && coprime )
306      {
307        poly ss = p_LmInit(t, r);
308        p_SetCoeff0(ss, n_Init(1, r), r); // for delete & printout only!...
309        p_SetComp(ss, (*vit)->m_label + 1, r); // coeff?
310        p_Setm(ss, r);
311
312        coprime = ( syzChecker.IsDivisible(ss) );
313
314        if( __DEBUG__ && !coprime)
315        {         
316          PrintS("CReducerFinder::PreProcessTerm, 't' is co-prime with p but may lead to NOT divisible syz.term: \n");
317          dPrint(ss, r, r, 1);
318        }
319
320        p_LmDelete(&ss, r); // deletes coeff as well???
321      }
322
323    }
324
325    if( __DEBUG__ && coprime )
326      PrintS("CReducerFinder::PreProcessTerm, the following 't' is 'co-prime' with all of leading terms! \n");
327
328    return coprime? 3: 0; // t was coprime with all of leading terms!!!
329
330  }
331  //   return true; // delete the term
332
333  return 0;
334}
335 
336   
337void SchreyerSyzygyComputation::SetUpTailTerms()
338{
339  const ideal idTails = m_idTails; 
340  assume( idTails != NULL );
341  assume( idTails->m != NULL );
342  const ring r = m_rBaseRing;
343
344  if( __DEBUG__ || 0)
345  {
346    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Tails: \n");
347    dPrint(idTails, r, r, 0);
348  }
349
350  unsigned long pp[4] = {0,0,0,0}; // count preprocessed terms...
351
352  for( int p = IDELEMS(idTails) - 1; p >= 0; --p )
353    for( poly* tt = &(idTails->m[p]); (*tt) != NULL;  )
354    {   
355      const poly t = *tt;
356      const int k = m_div.PreProcessTerm(t, m_checker); // 0..3
357      assume( 0 <= k && k <= 3 );
358      pp[k]++;
359      if( k )
360      {
361        if( __DEBUG__)
362        {         
363          Print("SchreyerSyzygyComputation::SetUpTailTerms(): PP (%d) the following TT: \n", k);
364          dPrint(t, r, r, 1);
365        }
366
367        (*tt) = p_LmDeleteAndNext(t, r); // delete the lead and next...
368      }   
369      else 
370        tt = &pNext(t); // go next?
371
372    }
373
374  if( TEST_OPT_PROT || 1)
375    Print("      **!!**      SchreyerSyzygyComputation::SetUpTailTerms()::PreProcessing(): X: {c: %lu, C: %lu, P: %lu} + %lu\n", pp[1], pp[2], pp[3], pp[0]);
376
377  if( __DEBUG__ || 0)
378  {
379    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Preprocessed Tails: \n");
380    dPrint(idTails, r, r, 0);
381  }
382}
383/* 
384  m_idTailTerms.resize( IDELEMS(idTails) );
385 
386  for( unsigned int p = IDELEMS(idTails) - 1; p >= 0; p -- )
387  {
388    TTail& v = m_idTailTerms[p];
389    poly t = idTails->m[p];
390    v.resize( pLength(t) );
391
392    unsigned int pp = 0;
393   
394    while( t != NULL )
395    {
396      assume( t != NULL );
397      // TODO: compute L:t!
398//      ideal reducers;     
399//      CReducerFinder m_reducers
400     
401      CTailTerm* d = v[pp] = new CTailTerm();
402     
403      ++pp; pIter(t);
404    }
405  }
406*/
407
408
409
410ideal SchreyerSyzygyComputation::Compute1LeadingSyzygyTerms()
411{
412  const ideal& id = m_idLeads;
413  const ring& r = m_rBaseRing;
414//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
415
416//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
417//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
418//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
419//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
420//   const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
421
422  assume(!__LEAD2SYZ__);
423
424  // 1. set of components S?
425  // 2. for each component c from S: set of indices of leading terms
426  // with this component?
427  // 3. short exp. vectors for each leading term?
428
429  const int size = IDELEMS(id);
430
431  if( size < 2 )
432  {
433    const ideal newid = idInit(1, 0); newid->m[0] = NULL; // zero ideal...       
434    return newid;
435  }
436
437  // TODO/NOTE: input is supposed to be (reverse-) sorted wrt "(c,ds)"!??
438
439  // components should come in groups: count elements in each group
440  // && estimate the real size!!!
441
442
443  // use just a vector instead???
444  const ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
445
446  int k = 0;
447
448  for (int j = 0; j < size; j++)
449  {
450    const poly p = id->m[j];
451    assume( p != NULL );
452    const int  c = p_GetComp(p, r);
453
454    for (int i = j - 1; i >= 0; i--)
455    {
456      const poly pp = id->m[i];
457      assume( pp != NULL );
458      const int  cc = p_GetComp(pp, r);
459
460      if( c != cc )
461        continue;
462
463      const poly m = p_Init(r); // p_New???
464
465      // m = LCM(p, pp) / p! // TODO: optimize: knowing the ring structure: (C/lp)!
466      for (int v = rVar(r); v > 0; v--)
467      {
468        assume( v > 0 );
469        assume( v <= rVar(r) );
470
471        const short e1 = p_GetExp(p , v, r);
472        const short e2 = p_GetExp(pp, v, r);
473
474        if( e1 >= e2 )
475          p_SetExp(m, v, 0, r);
476        else
477          p_SetExp(m, v, e2 - e1, r);
478
479      }
480
481      assume( (j > i) && (i >= 0) );
482
483      p_SetComp(m, j + 1, r);
484      pNext(m) = NULL;
485      p_SetCoeff0(m, n_Init(1, r->cf), r); // for later...
486
487      p_Setm(m, r); // should not do anything!!!
488
489      newid->m[k++] = m;
490    }
491  }
492
493//   if( __DEBUG__ && FALSE )
494//   {
495//     PrintS("ComputeLeadingSyzygyTerms::Temp0: \n");
496//     dPrint(newid, r, r, 1);
497//   }
498
499  // the rest of newid is assumed to be zeroes...
500
501  // simplify(newid, 2 + 32)??
502  // sort(newid, "C,ds")[1]???
503  id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
504
505//   if( __DEBUG__ && FALSE )
506//   {
507//     PrintS("ComputeLeadingSyzygyTerms::Temp1: \n");
508//     dPrint(newid, r, r, 1);
509//   }
510
511  idSkipZeroes(newid); // #define SIMPL_NULL 2
512
513//   if( __DEBUG__ )
514//   {
515//     PrintS("ComputeLeadingSyzygyTerms::Output: \n");
516//     dPrint(newid, r, r, 1);
517//   }
518
519  Sort_c_ds(newid, r);
520
521  return newid;
522}
523
524ideal SchreyerSyzygyComputation::Compute2LeadingSyzygyTerms()
525{
526  const ideal& id = m_idLeads;
527  const ring& r = m_rBaseRing;
528//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
529 
530//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
531//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
532//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
533//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
534//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
535 
536
537  // 1. set of components S?
538  // 2. for each component c from S: set of indices of leading terms
539  // with this component?
540  // 3. short exp. vectors for each leading term?
541
542  const int size = IDELEMS(id);
543
544  if( size < 2 )
545  {
546    const ideal newid = idInit(1, 1); newid->m[0] = NULL; // zero module...   
547    return newid;
548  }
549
550
551  // TODO/NOTE: input is supposed to be sorted wrt "C,ds"!??
552 
553  // components should come in groups: count elements in each group
554  // && estimate the real size!!!
555
556
557  // use just a vector instead???
558  ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
559
560  int k = 0;
561
562  for (int j = 0; j < size; j++)
563  {
564    const poly p = id->m[j];
565    assume( p != NULL );
566    const int  c = p_GetComp(p, r);
567
568    for (int i = j - 1; i >= 0; i--)
569    {
570      const poly pp = id->m[i];
571      assume( pp != NULL );
572      const int  cc = p_GetComp(pp, r);
573
574      if( c != cc )
575        continue;
576
577        // allocate memory & zero it out!
578      const poly m = p_Init(r); const poly mm = p_Init(r);
579
580
581        // m = LCM(p, pp) / p! mm = LCM(p, pp) / pp!
582        // TODO: optimize: knowing the ring structure: (C/lp)!
583
584      for (int v = rVar(r); v > 0; v--)
585      {
586        assume( v > 0 );
587        assume( v <= rVar(r) );
588
589        const short e1 = p_GetExp(p , v, r);
590        const short e2 = p_GetExp(pp, v, r);
591
592        if( e1 >= e2 )
593          p_SetExp(mm, v, e1 - e2, r); //            p_SetExp(m, v, 0, r);
594        else
595          p_SetExp(m, v, e2 - e1, r); //            p_SetExp(mm, v, 0, r);
596
597      }
598
599      assume( (j > i) && (i >= 0) );
600
601      p_SetComp(m, j + 1, r);
602      p_SetComp(mm, i + 1, r);
603
604      const number& lc1 = p_GetCoeff(p , r);
605      const number& lc2 = p_GetCoeff(pp, r);
606
607      number g = n_Lcm( lc1, lc2, r );
608
609      p_SetCoeff0(m ,       n_Div(g, lc1, r), r);
610      p_SetCoeff0(mm, n_Neg(n_Div(g, lc2, r), r), r);
611
612      n_Delete(&g, r);
613
614      p_Setm(m, r); // should not do anything!!!
615      p_Setm(mm, r); // should not do anything!!!
616
617      pNext(m) = mm; //        pNext(mm) = NULL;
618
619      newid->m[k++] = m;
620    }
621  }
622
623//   if( __DEBUG__ && FALSE )
624//   {
625//     PrintS("Compute2LeadingSyzygyTerms::Temp0: \n");
626//     dPrint(newid, r, r, 1);
627//   }
628
629  if( !__TAILREDSYZ__ )
630  {
631      // simplify(newid, 2 + 32)??
632      // sort(newid, "C,ds")[1]???
633    id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
634
635//     if( __DEBUG__ && FALSE )
636//     {
637//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (deldiv): \n");
638//       dPrint(newid, r, r, 1);
639//     }
640  }
641  else
642  {
643      //      option(redSB); option(redTail);
644      //      TEST_OPT_REDSB
645      //      TEST_OPT_REDTAIL
646    assume( r == currRing );
647 
648    BITSET _save_test; SI_SAVE_OPT1(_save_test);
649    SI_RESTORE_OPT1(Sy_bit(OPT_REDTAIL) | Sy_bit(OPT_REDSB) | _save_test);
650
651    intvec* w=new intvec(IDELEMS(newid));
652    ideal tmp = kStd(newid, currQuotient, isHomog, &w);
653    delete w;
654
655    SI_RESTORE_OPT1(_save_test)
656
657    id_Delete(&newid, r);
658    newid = tmp;
659
660//     if( __DEBUG__ && FALSE )
661//     {
662//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (std): \n");
663//       dPrint(newid, r, r, 1);
664//     }
665
666  }
667
668  idSkipZeroes(newid);
669
670  Sort_c_ds(newid, r);
671 
672  return newid;
673}
674
675poly SchreyerSyzygyComputation::TraverseNF(const poly a, const poly a2) const
676{
677  const ideal& L = m_idLeads;
678  const ideal& T = m_idTails;
679
680  const ring& R = m_rBaseRing;
681
682  const int r = p_GetComp(a, R) - 1; 
683
684  assume( r >= 0 && r < IDELEMS(T) );
685  assume( r >= 0 && r < IDELEMS(L) );
686
687  poly aa = leadmonom(a, R); assume( aa != NULL); // :(
688
689 
690  poly t = TraverseTail(aa, r);
691
692  if( a2 != NULL )
693  {
694    assume( __LEAD2SYZ__ );
695
696    const int r2 = p_GetComp(a2, R) - 1; poly aa2 = leadmonom(a2, R); // :(
697
698    assume( r2 >= 0 && r2 < IDELEMS(T) );
699
700    t = p_Add_q(a2, p_Add_q(t, TraverseTail(aa2, r2), R), R);
701
702    p_Delete(&aa2, R);
703  } else
704    t = p_Add_q(t, ReduceTerm(aa, L->m[r], a), R);
705
706  p_Delete(&aa, R);
707
708  return t;
709}
710
711
712void SchreyerSyzygyComputation::ComputeSyzygy()
713{
714  assume( m_idLeads != NULL );
715  assume( m_idTails != NULL );
716
717  const ideal& L = m_idLeads;
718  const ideal& T = m_idTails;
719
720  ideal& TT = m_syzTails;
721  const ring& R = m_rBaseRing;
722
723  assume( IDELEMS(L) == IDELEMS(T) );
724  int t, r; 
725
726  if( m_syzLeads == NULL )
727  {   
728    if( TEST_OPT_PROT || 1)
729    {
730      t = getTimer(); r = getRTimer();
731      Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: t: %d, r: %d\n", r, t, r);
732    }
733    ComputeLeadingSyzygyTerms( __LEAD2SYZ__ && !__IGNORETAILS__ ); // 2 terms OR 1 term!
734    if( TEST_OPT_PROT || 1)
735    {
736      t = getTimer() - t; r = getRTimer() - r;
737      Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: dt: %d, dr: %d\n", getRTimer(), t, r);
738    }
739
740  }
741
742  assume( m_syzLeads != NULL );
743  ideal& LL = m_syzLeads;
744  const int size = IDELEMS(LL);
745
746  TT = idInit(size, 0);
747
748  if( size == 1 && LL->m[0] == NULL )
749    return;
750
751  // use hybrid method?
752  const bool method = (__HYBRIDNF__ == 1) || (__HYBRIDNF__ == 2 && __SYZNUMBER__ < 3);
753
754  if(  !__IGNORETAILS__)
755  {
756    if( T != NULL )
757    {
758      if( TEST_OPT_PROT || 1 )
759      {
760        t = getTimer(); r = getRTimer();
761        Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): t: %d, r: %d\n", r, t, r);
762      }
763
764      SetUpTailTerms();
765
766      if( TEST_OPT_PROT || 1)
767      {
768        t = getTimer() - t; r = getRTimer() - r;
769        Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): dt: %d, dr: %d\n", getRTimer(), t, r);
770      }
771    }     
772  }
773
774  if( TEST_OPT_PROT || 1)
775  {
776    t = getTimer(); r = getRTimer();
777    Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: t: %d, r: %d\n", r, t, r);
778  }
779
780  for( int k = size - 1; k >= 0; k-- )
781  {
782    const poly a = LL->m[k]; assume( a != NULL );
783
784    poly a2 = pNext(a);   
785
786    // Splitting 2-terms Leading syzygy module
787    if( a2 != NULL )
788      pNext(a) = NULL;
789
790    if( __IGNORETAILS__ )
791    {
792      TT->m[k] = NULL;
793
794      assume( a2 != NULL );
795
796      if( a2 != NULL )
797        p_Delete(&a2, R);
798
799      continue;
800    }
801
802    //    TT->m[k] = a2;
803
804    if( method )
805      TT->m[k] = SchreyerSyzygyNF(a, a2);
806    else
807      TT->m[k] = TraverseNF(a, a2);
808  }
809
810  if( TEST_OPT_PROT || 1)
811  {
812    t = getTimer() - t; r = getRTimer() - r;
813    Print("%5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: dt: %d, dr: %d\n", getRTimer(), t, r);
814  }
815
816  TT->rank = id_RankFreeModule(TT, R); 
817}
818
819void SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms(bool bComputeSecondTerms)
820{
821//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
822
823//  const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
824//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
825
826  assume( m_syzLeads == NULL );
827
828  if( bComputeSecondTerms )
829  {
830    assume( __LEAD2SYZ__ );
831//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _Compute2LeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
832    m_syzLeads = Compute2LeadingSyzygyTerms();
833  }
834  else
835  {
836    assume( !__LEAD2SYZ__ );
837   
838    m_syzLeads = Compute1LeadingSyzygyTerms();
839  }
840//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _ComputeLeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
841 
842  // NOTE: set m_LS if tails are to be reduced!
843  assume( m_syzLeads!= NULL );
844
845  if (__TAILREDSYZ__ && !__IGNORETAILS__ && (IDELEMS(m_syzLeads) > 0) && !((IDELEMS(m_syzLeads) == 1) && (m_syzLeads->m[0] == NULL)))
846  {
847    m_LS = m_syzLeads;
848    m_checker.Initialize(m_syzLeads);
849#ifndef NDEBUG   
850    if( __DEBUG__ )
851    {
852      const ring& r = m_rBaseRing;
853      PrintS("SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms: \n");
854      PrintS("m_syzLeads: \n");
855      dPrint(m_syzLeads, r, r, 1);
856      PrintS("m_checker.Initialize(m_syzLeads) => \n");
857      m_checker.DebugPrint();
858    }
859#endif
860    assume( m_checker.IsNonempty() ); // TODO: this always fails... BUG????
861  }
862}
863
864#define NOPRODUCT 1
865
866poly SchreyerSyzygyComputation::SchreyerSyzygyNF(const poly syz_lead, poly syz_2) const
867{
868 
869  assume( !__IGNORETAILS__ );
870
871  const ideal& L = m_idLeads;
872  const ideal& T = m_idTails;
873  const ring& r = m_rBaseRing;
874
875  assume( syz_lead != NULL );
876
877  if( syz_2 == NULL )
878  {
879    const int rr = p_GetComp(syz_lead, r) - 1; 
880
881    assume( rr >= 0 && rr < IDELEMS(T) );
882    assume( rr >= 0 && rr < IDELEMS(L) );
883
884
885#if NOPRODUCT
886    syz_2 = m_div.FindReducer(syz_lead, L->m[rr], syz_lead, m_checker);
887#else   
888    poly aa = leadmonom(syz_lead, r); assume( aa != NULL); // :(
889    aa = p_Mult_mm(aa, L->m[rr], r);
890
891    syz_2 = m_div.FindReducer(aa, syz_lead, m_checker);
892
893    p_Delete(&aa, r);
894#endif
895   
896    assume( syz_2 != NULL ); // by construction of S-Polynomial   
897  }
898
899
900 
901  assume( syz_2 != NULL );
902
903  assume( L != NULL );
904  assume( T != NULL );
905
906  assume( IDELEMS(L) == IDELEMS(T) );
907
908  int  c = p_GetComp(syz_lead, r) - 1;
909
910  assume( c >= 0 && c < IDELEMS(T) );
911  kBucket_pt bucket = kBucketCreate(r); kbTest(bucket);
912
913//  kBucketInit(bucket, NULL, 0); // not needed!?
914     
915  poly p = leadmonom(syz_lead, r); // :( 
916//  poly spoly = pp_Mult_qq(p, T->m[c], r); 
917  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], pLength(T->m[c])); // TODO: store length of tails separately!?
918  kbTest(bucket); 
919  p_Delete(&p, r);
920
921  c = p_GetComp(syz_2, r) - 1;
922  assume( c >= 0 && c < IDELEMS(T) );
923
924  p = leadmonom(syz_2, r); // :(
925//  spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
926  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], pLength(T->m[c]));
927  kbTest(bucket);
928  p_Delete(&p, r);
929
930  // TODO: use bucket!?
931  const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(spoly) < MIN_LENGTH_BUCKET);
932  CPolynomialSummator tail(r, bUsePolynomial);
933  tail.AddAndDelete(syz_2, 1); 
934
935 
936  kbTest(bucket);
937  for( poly spoly = kBucketExtractLm(bucket); spoly != NULL; p_LmDelete(&spoly, r), spoly = kBucketExtractLm(bucket))
938  {   
939    kbTest(bucket);
940    poly t = m_div.FindReducer(spoly, NULL, m_checker);   
941
942    if( t != NULL )
943    {
944      p = leadmonom(t, r); // :(
945      c = p_GetComp(t, r) - 1;
946
947      assume( c >= 0 && c < IDELEMS(T) );
948
949      kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], pLength(T->m[c])); 
950//      spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
951
952      p_Delete(&p, r);
953
954      tail.AddAndDelete(t, 1); 
955    } // otherwise discard that leading term altogether!
956    kbTest(bucket);
957  }
958
959  // now bucket must be empty!
960  kbTest(bucket);
961  assume( kBucketClear(bucket) == NULL );
962  kBucketDestroy(&bucket); // TODO: reuse the bucket!!!
963     
964  return tail;
965}
966
967poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, const int tail) const
968{
969  // TODO: store (multiplier, tail) -.-^-.-^-.--> !
970  assume(m_idTails !=  NULL && m_idTails->m != NULL);
971  assume( tail >= 0 && tail < IDELEMS(m_idTails) );
972
973  const poly t = m_idTails->m[tail]; // !!!
974
975  if(t != NULL)
976    return TraverseTail(multiplier, t);
977
978  return NULL;
979}
980
981
982poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, poly tail) const
983{
984  assume( !__IGNORETAILS__ );
985
986  const ideal& L = m_idLeads;
987  const ideal& T = m_idTails;
988  const ring& r = m_rBaseRing;
989
990  assume( multiplier != NULL );
991
992  assume( L != NULL );
993  assume( T != NULL );
994
995
996  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
997  {
998    const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(tail) < MIN_LENGTH_BUCKET);
999    CPolynomialSummator sum(r, bUsePolynomial);
1000//    poly s = NULL;
1001    for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
1002      sum += ReduceTerm(multiplier, p, NULL);
1003    return sum;
1004  }
1005
1006  return NULL;
1007
1008}
1009
1010
1011
1012
1013poly SchreyerSyzygyComputation::ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const
1014{
1015  assume( !__IGNORETAILS__ );
1016
1017  const ideal& L = m_idLeads;
1018  const ideal& T = m_idTails;
1019  const ring& r = m_rBaseRing;
1020
1021  assume( multiplier != NULL );
1022  assume( term4reduction != NULL );
1023
1024
1025  assume( L != NULL );
1026  assume( T != NULL );
1027
1028  // simple implementation with FindReducer:
1029  poly s = NULL;
1030
1031  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
1032  {
1033#if NOPRODUCT
1034    s = m_div.FindReducer(multiplier, term4reduction, syztermCheck, m_checker);
1035#else   
1036    // NOTE: only LT(term4reduction) should be used in the following:
1037    poly product = pp_Mult_mm(multiplier, term4reduction, r);
1038    s = m_div.FindReducer(product, syztermCheck, m_checker);
1039    p_Delete(&product, r);
1040#endif
1041  }
1042
1043  if( s == NULL ) // No Reducer?
1044    return s;
1045
1046  poly b = leadmonom(s, r);
1047
1048  const int c = p_GetComp(s, r) - 1;
1049  assume( c >= 0 && c < IDELEMS(T) );
1050
1051  const poly t = TraverseTail(b, c); // T->m[c];
1052
1053  if( t != NULL )
1054    s = p_Add_q(s, t, r); 
1055
1056  return s;
1057}
1058
1059
1060
1061
1062
1063BEGIN_NAMESPACE_NONAME
1064   
1065static inline int atGetInt(idhdl rootRingHdl, const char* attribute, long def)
1066{
1067  return ((int)(long)(atGet(rootRingHdl, attribute, INT_CMD, (void*)def)));
1068}
1069
1070END_NAMESPACE   
1071
1072SchreyerSyzygyComputationFlags::SchreyerSyzygyComputationFlags(idhdl rootRingHdl):
1073#ifndef NDEBUG
1074     __DEBUG__( atGetInt(rootRingHdl,"DEBUG", 0) ),
1075#else
1076    __DEBUG__( atGetInt(rootRingHdl,"DEBUG", 0) ),
1077#endif
1078//    __SYZCHECK__( (BOOLEAN)atGetInt(rootRingHdl, "SYZCHECK", __DEBUG__) ),
1079    __LEAD2SYZ__( atGetInt(rootRingHdl, "LEAD2SYZ", 1) ), 
1080    __TAILREDSYZ__( atGetInt(rootRingHdl, "TAILREDSYZ", 1) ), 
1081    __HYBRIDNF__( atGetInt(rootRingHdl, "HYBRIDNF", 2) ),
1082    __IGNORETAILS__( atGetInt(rootRingHdl, "IGNORETAILS", 0) ),
1083    __SYZNUMBER__( atGetInt(rootRingHdl, "SYZNUMBER", 0) ),
1084    m_rBaseRing( rootRingHdl->data.uring )
1085{   
1086  if( __DEBUG__ )
1087  {
1088    PrintS("SchreyerSyzygyComputationFlags: \n");
1089    Print("        DEBUG: \t%d\n", __DEBUG__);
1090//    Print("   SYZCHECK  : \t%d\n", __SYZCHECK__);
1091    Print("     LEAD2SYZ: \t%d\n", __LEAD2SYZ__);
1092    Print("   TAILREDSYZ: \t%d\n", __TAILREDSYZ__);
1093    Print("  IGNORETAILS: \t%d\n", __IGNORETAILS__);
1094   
1095  }
1096
1097  // TODO: just current setting!
1098  assume( rootRingHdl == currRingHdl );
1099  assume( rootRingHdl->typ == RING_CMD );
1100  assume( m_rBaseRing == currRing );
1101  // move the global ring here inside???
1102}
1103
1104   
1105
1106CLeadingTerm::CLeadingTerm(unsigned int _label,  const poly _lt, const ring R):
1107    m_sev( p_GetShortExpVector(_lt, R) ),  m_label( _label ),  m_lt( _lt )
1108{ }
1109
1110
1111CReducerFinder::~CReducerFinder()
1112{
1113  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ )
1114  {
1115    const TReducers& v = it->second;
1116    for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ )
1117      delete const_cast<CLeadingTerm*>(*vit);
1118  }
1119}
1120
1121
1122void CReducerFinder::Initialize(const ideal L)
1123{
1124  assume( m_L == NULL || m_L == L );
1125  if( m_L == NULL )
1126    m_L = L;
1127
1128  assume( m_L == L );
1129 
1130  if( L != NULL )
1131  {
1132    const ring& R = m_rBaseRing;
1133    assume( R != NULL );
1134   
1135    for( int k = IDELEMS(L) - 1; k >= 0; k-- )
1136    {
1137      const poly a = L->m[k]; // assume( a != NULL );
1138
1139      // NOTE: label is k \in 0 ... |L|-1!!!
1140      if( a != NULL )
1141        m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm(k, a, R) );
1142    }
1143  }
1144}
1145
1146CReducerFinder::CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags):
1147    SchreyerSyzygyComputationFlags(flags),
1148    m_L(const_cast<ideal>(L)), // for debug anyway
1149    m_hash()
1150{
1151  assume( flags.m_rBaseRing == m_rBaseRing );
1152  if( L != NULL )
1153    Initialize(L);
1154}
1155
1156/// _p_LmDivisibleByNoComp for a | b*c
1157static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r)
1158{
1159  int i=r->VarL_Size - 1;
1160  unsigned long divmask = r->divmask;
1161  unsigned long la, lb;
1162
1163  if (r->VarL_LowIndex >= 0)
1164  {
1165    i += r->VarL_LowIndex;
1166    do
1167    {
1168      la = a->exp[i];
1169      lb = b->exp[i] + c->exp[i];
1170      if ((la > lb) ||
1171          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1172      {
1173        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1174        return FALSE;
1175      }
1176      i--;
1177    }
1178    while (i>=r->VarL_LowIndex);
1179  }
1180  else
1181  {
1182    do
1183    {
1184      la = a->exp[r->VarL_Offset[i]];
1185      lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]];
1186      if ((la > lb) ||
1187          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1188      {
1189        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1190        return FALSE;
1191      }
1192      i--;
1193    }
1194    while (i>=0);
1195  }
1196#ifdef HAVE_RINGS
1197  assume( !rField_is_Ring(r) ); // not implemented for rings...!
1198#endif
1199  return TRUE;
1200}
1201
1202bool CLeadingTerm::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const
1203{
1204  const poly p = m_lt;
1205
1206  assume( p_GetComp(p, r) == p_GetComp(product, r) );
1207
1208  const int k = m_label;
1209
1210//  assume( m_L->m[k] == p );
1211
1212  const unsigned long p_sev = m_sev;
1213
1214  assume( p_sev == p_GetShortExpVector(p, r) );     
1215
1216  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1217
1218}
1219
1220/// as DivisibilityCheck(multiplier * t, ...) for monomial 'm'
1221/// and a module term 't'
1222bool CLeadingTerm::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const
1223{
1224  const poly p = m_lt;
1225
1226  assume( p_GetComp(p, r) == p_GetComp(t, r) );
1227// assume( p_GetComp(m, r) == 0 );
1228
1229//  const int k = m_label;
1230//  assume( m_L->m[k] == p );
1231
1232  const unsigned long p_sev = m_sev;
1233  assume( p_sev == p_GetShortExpVector(p, r) );     
1234
1235  if (p_sev & not_sev)
1236    return false;
1237
1238  return _p_LmDivisibleByNoComp(p, m, t, r);
1239
1240//  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1241
1242}
1243
1244
1245
1246/// TODO:
1247class CDivisorEnumerator: public SchreyerSyzygyComputationFlags
1248{
1249  private: 
1250    const CReducerFinder& m_reds;
1251    const poly m_product;
1252    const unsigned long m_not_sev;
1253    const unsigned long m_comp;
1254
1255    CReducerFinder::CReducersHash::const_iterator m_itr;
1256    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1257
1258    bool m_active;
1259
1260  public:
1261    CDivisorEnumerator(const CReducerFinder& self, const poly product):
1262        SchreyerSyzygyComputationFlags(self),
1263        m_reds(self),
1264        m_product(product),
1265        m_not_sev(~p_GetShortExpVector(product, m_rBaseRing)),
1266        m_comp(p_GetComp(product, m_rBaseRing)),
1267        m_itr(), m_current(), m_finish(),
1268        m_active(false)
1269    {
1270      assume( m_comp >= 0 );
1271      assume( m_reds.m_L != NULL ); 
1272    }
1273
1274    inline bool Reset()
1275    {
1276      m_active = false;
1277     
1278      m_itr = m_reds.m_hash.find(m_comp);
1279
1280      if( m_itr == m_reds.m_hash.end() )
1281        return false;
1282
1283      assume( m_itr->first == m_comp );
1284
1285      m_current = (m_itr->second).begin();
1286      m_finish = (m_itr->second).end();
1287
1288      if (m_current == m_finish)
1289        return false;
1290
1291//      m_active = true;
1292      return true;     
1293    }
1294
1295    const CLeadingTerm& Current() const
1296    {
1297      assume( m_active );
1298      assume( m_current != m_finish );
1299
1300      return *(*m_current);
1301    }
1302 
1303    inline bool MoveNext()
1304    {
1305      assume( m_current != m_finish );
1306
1307      if( m_active )
1308        ++m_current;
1309      else
1310        m_active = true; // for Current()
1311     
1312      // looking for the next good entry
1313      for( ; m_current != m_finish; ++m_current )
1314      {
1315        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1316
1317        if( Current().DivisibilityCheck(m_product, m_not_sev, m_rBaseRing) )
1318        {
1319          if( __DEBUG__ )
1320          {
1321            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1322            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1323          }
1324
1325//          m_active = true;
1326          return true;
1327        }
1328      }
1329
1330      // the end... :(
1331      assume( m_current == m_finish );
1332     
1333      m_active = false;
1334      return false;
1335    }
1336};
1337
1338
1339
1340bool CReducerFinder::IsDivisible(const poly product) const
1341{
1342  CDivisorEnumerator itr(*this, product);
1343  if( !itr.Reset() )
1344    return false;
1345
1346  return itr.MoveNext();
1347 
1348/* 
1349  const ring& r = m_rBaseRing;
1350 
1351  const long comp = p_GetComp(product, r);
1352  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
1353
1354  assume( comp >= 0 );
1355
1356  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1357
1358  assume( m_L != NULL ); 
1359
1360  if( it == m_hash.end() )
1361    return false;
1362
1363  const TReducers& reducers = it->second;
1364
1365  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1366  {
1367    assume( m_L->m[(*vit)->m_label] == (*vit)->m_lt );
1368
1369    if( (*vit)->DivisibilityCheck(product, not_sev, r) )
1370    {
1371      if( __DEBUG__ )
1372      {
1373        Print("_FindReducer::Test LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + (*vit)->m_label);
1374        dPrint((*vit)->m_lt, r, r, 1);
1375      }
1376
1377      return true;
1378    }
1379  }
1380
1381  return false;
1382*/ 
1383}
1384
1385
1386#ifndef NDEBUG
1387void CReducerFinder::DebugPrint() const
1388{
1389  const ring& r = m_rBaseRing;
1390
1391  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++)
1392  {
1393    Print("Hash Key: %d, Values: \n", it->first);
1394    const TReducers& reducers = it->second;
1395
1396    for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1397    {
1398      const poly p = (*vit)->m_lt;
1399
1400      assume( p_GetComp(p, r) == it->first );
1401
1402      const int k = (*vit)->m_label;
1403
1404      assume( m_L->m[k] == p );
1405
1406      const unsigned long p_sev = (*vit)->m_sev;
1407
1408      assume( p_sev == p_GetShortExpVector(p, r) );
1409
1410      Print("L[%d]: ", k); dPrint(p, r, r, 0); Print("SEV: %dl\n", p_sev);     
1411    }
1412  }
1413}
1414#endif
1415
1416/// TODO:
1417class CDivisorEnumerator2: public SchreyerSyzygyComputationFlags
1418{
1419  private: 
1420    const CReducerFinder& m_reds;
1421    const poly m_multiplier, m_term;
1422    const unsigned long m_not_sev;
1423    const unsigned long m_comp;
1424
1425    CReducerFinder::CReducersHash::const_iterator m_itr;
1426    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1427
1428    bool m_active;
1429
1430  public:
1431    CDivisorEnumerator2(const CReducerFinder& self, const poly m, const poly t):
1432        SchreyerSyzygyComputationFlags(self),
1433        m_reds(self),
1434        m_multiplier(m), m_term(t),
1435        m_not_sev(~p_GetShortExpVector(m, t, m_rBaseRing)),
1436        m_comp(p_GetComp(t, m_rBaseRing)),
1437        m_itr(), m_current(), m_finish(),
1438        m_active(false)
1439    {
1440      assume( m_comp >= 0 );
1441      assume( m_reds.m_L != NULL ); 
1442      assume( m_multiplier != NULL ); 
1443      assume( m_term != NULL );
1444//      assume( p_GetComp(m_multiplier, m_rBaseRing) == 0 );
1445    }
1446
1447    inline bool Reset()
1448    {
1449      m_active = false;
1450     
1451      m_itr = m_reds.m_hash.find(m_comp);
1452
1453      if( m_itr == m_reds.m_hash.end() )
1454        return false;
1455
1456      assume( m_itr->first == m_comp );
1457
1458      m_current = (m_itr->second).begin();
1459      m_finish = (m_itr->second).end();
1460
1461      if (m_current == m_finish)
1462        return false;
1463
1464      return true;     
1465    }
1466
1467    const CLeadingTerm& Current() const
1468    {
1469      assume( m_active );
1470      assume( m_current != m_finish );
1471
1472      return *(*m_current);
1473    }
1474 
1475    inline bool MoveNext()
1476    {
1477      assume( m_current != m_finish );
1478
1479      if( m_active )
1480        ++m_current;
1481      else 
1482        m_active = true;
1483   
1484     
1485      // looking for the next good entry
1486      for( ; m_current != m_finish; ++m_current )
1487      {
1488        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1489
1490        if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, m_rBaseRing) )
1491        {
1492          if( __DEBUG__ )
1493          {
1494            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1495            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1496          }
1497
1498//          m_active = true;
1499          return true;
1500         
1501        }
1502      }
1503
1504      // the end... :(
1505      assume( m_current == m_finish );
1506     
1507      m_active = false;
1508      return false;
1509    }
1510};
1511   
1512poly CReducerFinder::FindReducer(const poly multiplier, const poly t,
1513                                 const poly syzterm,
1514                                 const CReducerFinder& syz_checker) const
1515{
1516  CDivisorEnumerator2 itr(*this, multiplier, t);
1517  if( !itr.Reset() )
1518    return NULL;
1519
1520  // don't care about the module component of multiplier (as it may be the syzygy term)
1521  // product = multiplier * t?
1522  const ring& r = m_rBaseRing;
1523
1524  assume( multiplier != NULL ); assume( t != NULL );
1525
1526  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
1527
1528  long c = 0;
1529
1530  if (syzterm != NULL)
1531    c = p_GetComp(syzterm, r) - 1;
1532
1533  assume( c >= 0 && c < IDELEMS(L) );
1534
1535  if (__DEBUG__ && (syzterm != NULL))
1536  {
1537    const poly m = L->m[c];
1538
1539    assume( m != NULL ); assume( pNext(m) == NULL );
1540
1541    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
1542
1543    poly pr = p_Mult_q( leadmonom(multiplier, r, false), leadmonom(t, r, false), r);
1544   
1545    assume( p_EqualPolys(lm, pr, r) );
1546
1547    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
1548    //  def @@product = leadmonomial(syzterm) * L[@@r];
1549
1550    p_Delete(&lm, r);   
1551    p_Delete(&pr, r);   
1552  }
1553   
1554  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
1555
1556  const poly q = p_New(r); pNext(q) = NULL;
1557
1558  if( __DEBUG__ )
1559    p_SetCoeff0(q, 0, r); // for printing q
1560
1561  while( itr.MoveNext() )
1562  {
1563    const poly p = itr.Current().m_lt;
1564    const int k  = itr.Current().m_label;
1565     
1566    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t // TODO: do it once?
1567    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
1568   
1569    p_SetComp(q, k + 1, r);
1570    p_Setm(q, r);
1571
1572    // cannot allow something like: a*gen(i) - a*gen(i)
1573    if (syzterm != NULL && (k == c))
1574      if (p_ExpVectorEqual(syzterm, q, r))
1575      {
1576        if( __DEBUG__ )
1577        {
1578          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1579          dPrint(syzterm, r, r, 1);
1580        }   
1581
1582        continue;
1583      }
1584
1585    // while the complement (the fraction) is not reducible by leading syzygies
1586    if( to_check && syz_checker.IsDivisible(q) ) 
1587    {
1588      if( __DEBUG__ )
1589      {
1590        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1591      }
1592
1593      continue;
1594    }
1595
1596    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
1597    p_SetCoeff0(q, n_Neg( n_Div(n, p_GetCoeff(p, r), r), r), r);
1598    n_Delete(&n, r);
1599   
1600    return q;
1601  }
1602   
1603/*
1604  const long comp = p_GetComp(t, r); assume( comp >= 0 );
1605  const unsigned long not_sev = ~p_GetShortExpVector(multiplier, t, r); // !
1606
1607//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
1608//   {
1609//     const poly p = L->m[k];
1610//
1611//     if ( p_GetComp(p, r) != comp )
1612//       continue;
1613//
1614//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
1615
1616   // looking for an appropriate diviser p = L[k]...
1617  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1618
1619  if( it == m_hash.end() )
1620    return NULL;
1621
1622  assume( m_L != NULL );
1623
1624  const TReducers& reducers = it->second;
1625
1626  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1627  {
1628
1629    const poly p = (*vit)->m_lt;
1630    const int k = (*vit)->m_label;
1631
1632    assume( L->m[k] == p );
1633
1634//    const unsigned long p_sev = (*vit)->m_sev;
1635//    assume( p_sev == p_GetShortExpVector(p, r) );     
1636
1637//    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
1638//      continue;     
1639
1640    if( !(*vit)->DivisibilityCheck(multiplier, t, not_sev, r) )
1641      continue;
1642   
1643   
1644//    if (p_sev & not_sev) continue;
1645//    if( !_p_LmDivisibleByNoComp(p, multiplier, t, r) ) continue;     
1646
1647
1648    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t       
1649    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
1650   
1651    p_SetComp(q, k + 1, r);
1652    p_Setm(q, r);
1653
1654    // cannot allow something like: a*gen(i) - a*gen(i)
1655    if (syzterm != NULL && (k == c))
1656      if (p_ExpVectorEqual(syzterm, q, r))
1657      {
1658        if( __DEBUG__ )
1659        {
1660          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1661          dPrint(syzterm, r, r, 1);
1662        }   
1663
1664        continue;
1665      }
1666
1667    // while the complement (the fraction) is not reducible by leading syzygies
1668    if( to_check && syz_checker.IsDivisible(q) )
1669    {
1670      if( __DEBUG__ )
1671      {
1672        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1673      }
1674
1675      continue;
1676    }
1677
1678    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
1679    p_SetCoeff0(q, n_Neg( n_Div(n, p_GetCoeff(p, r), r), r), r);
1680    n_Delete(&n, r);
1681   
1682    return q;
1683  }
1684*/ 
1685
1686  p_LmFree(q, r);
1687
1688  return NULL;
1689 
1690}
1691
1692
1693poly CReducerFinder::FindReducer(const poly product, const poly syzterm, const CReducerFinder& syz_checker) const
1694{
1695  CDivisorEnumerator itr(*this, product);
1696  if( !itr.Reset() )
1697    return NULL;
1698
1699
1700  const ring& r = m_rBaseRing;
1701
1702  assume( product != NULL );
1703
1704  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
1705
1706  long c = 0;
1707
1708  if (syzterm != NULL)
1709    c = p_GetComp(syzterm, r) - 1;
1710
1711  assume( c >= 0 && c < IDELEMS(L) );
1712
1713  if (__DEBUG__ && (syzterm != NULL))
1714  {
1715    const poly m = L->m[c];
1716
1717    assume( m != NULL ); assume( pNext(m) == NULL );
1718
1719    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
1720    assume( p_EqualPolys(lm, product, r) );
1721
1722    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
1723    //  def @@product = leadmonomial(syzterm) * L[@@r];
1724
1725    p_Delete(&lm, r);   
1726  }
1727
1728
1729  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
1730
1731  const poly q = p_New(r); pNext(q) = NULL;
1732
1733  if( __DEBUG__ )
1734    p_SetCoeff0(q, 0, r); // for printing q
1735
1736  while( itr.MoveNext() )
1737  {
1738    const poly p = itr.Current().m_lt;
1739    const int k  = itr.Current().m_label;
1740     
1741    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
1742    p_SetComp(q, k + 1, r);
1743    p_Setm(q, r);
1744
1745    // cannot allow something like: a*gen(i) - a*gen(i)
1746    if (syzterm != NULL && (k == c))
1747      if (p_ExpVectorEqual(syzterm, q, r))
1748      {
1749        if( __DEBUG__ )
1750        {
1751          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1752          dPrint(syzterm, r, r, 1);
1753        }   
1754
1755        continue;
1756      }
1757
1758    // while the complement (the fraction) is not reducible by leading syzygies
1759    if( to_check && syz_checker.IsDivisible(q) ) 
1760    {
1761      if( __DEBUG__ )
1762      {
1763        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1764      }
1765
1766      continue;
1767    }
1768
1769    p_SetCoeff0(q, n_Neg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
1770   
1771    return q;
1772  }
1773   
1774   
1775   
1776/*   
1777  const long comp = p_GetComp(product, r);
1778  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
1779
1780  assume( comp >= 0 );
1781
1782//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
1783//   {
1784//     const poly p = L->m[k];
1785//
1786//     if ( p_GetComp(p, r) != comp )
1787//       continue;
1788//
1789//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
1790 
1791   // looking for an appropriate diviser p = L[k]...
1792  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1793
1794  if( it == m_hash.end() )
1795    return NULL;
1796
1797  assume( m_L != NULL );
1798
1799  const TReducers& reducers = it->second;
1800
1801  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
1802
1803  const poly q = p_New(r); pNext(q) = NULL;
1804
1805  if( __DEBUG__ )
1806    p_SetCoeff0(q, 0, r); // for printing q
1807 
1808  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1809  {
1810    const poly p = (*vit)->m_lt;
1811
1812    assume( p_GetComp(p, r) == comp );
1813
1814    const int k = (*vit)->m_label;
1815
1816    assume( L->m[k] == p );
1817
1818    const unsigned long p_sev = (*vit)->m_sev;
1819
1820    assume( p_sev == p_GetShortExpVector(p, r) );     
1821
1822    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
1823      continue;     
1824
1825//     // ... which divides the product, looking for the _1st_ appropriate one!
1826//     if( !p_LmDivisibleByNoComp(p, product, r) ) // included inside  p_LmShortDivisibleBy!
1827//       continue;
1828
1829    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
1830    p_SetComp(q, k + 1, r);
1831    p_Setm(q, r);
1832
1833    // cannot allow something like: a*gen(i) - a*gen(i)
1834    if (syzterm != NULL && (k == c))
1835      if (p_ExpVectorEqual(syzterm, q, r))
1836      {
1837        if( __DEBUG__ )
1838        {
1839          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1840          dPrint(syzterm, r, r, 1);
1841        }   
1842
1843        continue;
1844      }
1845
1846    // while the complement (the fraction) is not reducible by leading syzygies
1847    if( to_check && syz_checker.IsDivisible(q) )
1848    {
1849      if( __DEBUG__ )
1850      {
1851        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1852      }
1853     
1854      continue;
1855    }
1856
1857    p_SetCoeff0(q, n_Neg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
1858    return q;
1859  }
1860*/
1861
1862  p_LmFree(q, r);
1863
1864  return NULL;
1865}
1866
1867
1868
1869CLCM::CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags):
1870    SchreyerSyzygyComputationFlags(flags), std::vector<bool>(),
1871    m_compute(false), m_N(rVar(flags.m_rBaseRing))
1872{
1873  const ring& R = m_rBaseRing;
1874  assume( flags.m_rBaseRing == R );
1875  assume( R != NULL );
1876
1877  assume( L != NULL );
1878
1879  if( __TAILREDSYZ__ && !__HYBRIDNF__ && (L != NULL))
1880  {
1881    const int l = IDELEMS(L);
1882
1883    assume( l > 0 );
1884
1885    resize(l, false);
1886
1887    for( int k = l - 1; k >= 0; k-- )
1888    {
1889      const poly a = L->m[k]; assume( a != NULL );
1890
1891      for (unsigned int j = m_N; j > 0; j--)
1892        if ( !(*this)[j] )
1893          (*this)[j] = (p_GetExp(a, j, R) > 0);
1894    }
1895
1896    m_compute = true;   
1897  }
1898}
1899
1900
1901bool CLCM::Check(const poly m) const
1902{
1903  assume( m != NULL );
1904  if( m_compute && (m != NULL))
1905  { 
1906    const ring& R = m_rBaseRing;
1907
1908    assume( __TAILREDSYZ__ && !__HYBRIDNF__ );
1909
1910    for (unsigned int j = m_N; j > 0; j--)
1911      if ( (*this)[j] )
1912        if(p_GetExp(m, j, R) > 0)
1913          return true;
1914
1915    return false;
1916
1917  } else return true;
1918}
1919
1920
1921
1922
1923END_NAMESPACE               END_NAMESPACE_SINGULARXX
1924
1925
1926// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
Note: See TracBrowser for help on using the repository browser.