source: git/dyn_modules/syzextra/syzextra.cc @ 4ca3e3

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