source: git/Singular/dyn_modules/syzextra/syzextra.cc @ 5c0f71

spielwiese
Last change on this file since 5c0f71 was 5c0f71, checked in by Oleksandr Motsak <motsak@…>, 9 years ago
Minor changes to syzextra chg: output details about the terms skipped due to LCM heuristics in debug mode add: rat.d8.g6, bordiga to testSimple add: switch for tree output to testSimple add: pass noCaching option from SSinit to the besering
  • Property mode set to 100644
File size: 73.8 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 * New implementations for the computation of syzygies and resolutions
8 *
9 * ABSTRACT: Computation of Syzygies due to Schreyer
10 *
11 * @author Oleksandr Motsak
12 *
13 **/
14/*****************************************************************************/
15
16#include <string.h>
17
18// include header file
19#include <kernel/mod2.h>
20
21#include "syzextra.h"
22
23#include "DebugPrint.h"
24
25#include <omalloc/omalloc.h>
26
27#include <misc/intvec.h>
28#include <misc/options.h>
29
30#include <coeffs/coeffs.h>
31
32#include <polys/monomials/p_polys.h>
33#include <polys/monomials/ring.h>
34#include <polys/simpleideals.h>
35
36#include <polys/kbuckets.h> // for kBucket*
37#include <polys/sbuckets.h> // for sBucket*
38//#include <polys/nc/summator.h> // for CPolynomialSummator
39#include <polys/operations/p_Mult_q.h> // for MIN_LENGTH_BUCKET
40
41#include <kernel/GBEngine/kstd1.h>
42#include <kernel/polys.h>
43#include <kernel/GBEngine/syz.h>
44#include <kernel/ideals.h>
45
46#include <kernel/oswrapper/timer.h>
47
48
49#include <Singular/tok.h>
50#include <Singular/ipid.h>
51#include <Singular/lists.h>
52#include <Singular/attrib.h>
53
54#include <Singular/ipid.h>
55#include <Singular/ipshell.h> // For iiAddCproc
56
57#include <stdio.h>
58#include <stdlib.h>
59
60#ifndef RTIMER_BENCHMARKING
61# define RTIMER_BENCHMARKING 0
62#endif
63
64// USING_NAMESPACE_SINGULARXX;
65USING_NAMESPACE( SINGULARXXNAME :: DEBUG )
66
67
68BEGIN_NAMESPACE_SINGULARXX     BEGIN_NAMESPACE(SYZEXTRA)
69
70
71BEGIN_NAMESPACE_NONAME
72
73#ifndef SING_NDEBUG
74ring SBucketFactory::_GetBucketRing(const SBucketFactory::Bucket& bt)
75{
76  assume( bt != NULL );
77  return sBucketGetRing(bt);
78}
79
80bool SBucketFactory::_IsBucketEmpty(const SBucketFactory::Bucket& bt)
81{
82  assume( bt != NULL );
83  return sIsEmpty(bt);
84}
85#endif
86
87SBucketFactory::Bucket SBucketFactory::_CreateBucket(const ring r)
88{
89  const Bucket bt = sBucketCreate(r);
90
91  assume( bt != NULL );
92  assume( _IsBucketEmpty(bt) );
93  assume( r == _GetBucketRing(bt) );
94
95  return bt;
96}
97
98void SBucketFactory::_DestroyBucket(SBucketFactory::Bucket & bt)
99{
100  if( bt != NULL )
101  {
102    assume( _IsBucketEmpty(bt) );
103    sBucketDestroy( &bt );
104    bt = NULL;
105  }
106}
107
108class SBucketWrapper
109{
110  typedef SBucketFactory::Bucket Bucket;
111
112  private:
113    Bucket m_bucket;
114
115    SBucketFactory& m_factory;
116  public:
117    SBucketWrapper(const ring r, SBucketFactory& factory):
118        m_bucket( factory.getBucket(r) ),
119        m_factory( factory )
120    {}
121
122    ~SBucketWrapper()
123    {
124      m_factory.putBucket( m_bucket );
125    }
126
127  public:
128
129    /// adds p to the internal bucket
130    /// destroys p, l == length(p)
131    inline void Add( poly p, const int l )
132    {
133      assume( pLength(p) == l );
134      sBucket_Add_p( m_bucket, p, l );
135    }
136
137    /// adds p to the internal bucket
138    /// destroys p
139    inline void Add( poly p ){ Add(p, pLength(p)); }
140
141    poly ClearAdd()
142    {
143      poly p; int l;
144      sBucketClearAdd(m_bucket, &p, &l);
145      assume( pLength(p) == l );
146      return p;
147    }
148};
149
150static FORCE_INLINE poly pp_Add_qq( const poly a, const poly b, const ring R)
151{
152  return p_Add_q( p_Copy(a, R), p_Copy(b, R), R );
153}
154
155static FORCE_INLINE poly p_VectorProductLT( poly s,  const ideal& L, const ideal& T, const ring& R)
156{
157  assume( IDELEMS(L) == IDELEMS(T) );
158  poly vp = NULL; // resulting vector product
159
160  while( s != NULL )
161  {
162    const poly nxt = pNext(s);
163    pNext(s) = NULL;
164
165    if( !n_IsZero( p_GetCoeff(s, R), R) )
166    {
167      const int i = p_GetComp(s, R) - 1;
168      assume( i >= 0 ); assume( i < IDELEMS(L) );
169      p_SetComp(s, 0, R); p_SetmComp(s, R);
170
171      vp = p_Add_q( vp, pp_Mult_qq( s, L->m[i], R ), R);
172      vp = p_Add_q( vp, pp_Mult_qq( s, T->m[i], R ), R);
173    }
174
175    p_Delete(&s, R);
176
177    s = nxt;
178  };
179
180  assume( s == NULL );
181
182  return vp;
183}
184
185static FORCE_INLINE int atGetInt(idhdl rootRingHdl, const char* attribute, long def)
186{
187  return ((int)(long)(atGet(rootRingHdl, attribute, INT_CMD, (void*)def)));
188}
189
190END_NAMESPACE
191
192BEGIN_NAMESPACE(SORT_c_ds)
193
194#if (defined(HAVE_QSORT_R) && (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FreeBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9))
195static int cmp_c_ds(void *R, const void *p1, const void *p2){
196#elif (defined(HAVE_QSORT_R) && (defined _GNU_SOURCE || defined __GNU__ || defined __linux__))
197static int cmp_c_ds(const void *p1, const void *p2, void *R){
198#else
199static int cmp_c_ds(const void *p1, const void *p2){ void *R = currRing;
200#endif
201  assume(R != NULL);
202  const int YES = 1;
203  const int NO = -1;
204
205  const ring r =  (const ring) R; // TODO/NOTE: the structure is known: C, lp!!!
206
207  assume( r == currRing ); // for now...
208
209  const poly a = *(const poly*)p1;
210  const poly b = *(const poly*)p2;
211
212  assume( a != NULL );
213  assume( b != NULL );
214
215  p_LmTest(a, r);
216  p_LmTest(b, r);
217
218
219  const signed long iCompDiff = p_GetComp(a, r) - p_GetComp(b, r);
220
221  // TODO: test this!!!!!!!!!!!!!!!!
222
223  //return -( compare (c, qsorts) )
224
225#ifndef SING_NDEBUG
226  const int OPT__DEBUG = 0;
227  if( OPT__DEBUG )
228  {
229    PrintS("cmp_c_ds: a, b: \np1: "); dPrint(a, r, r, 0);
230    PrintS("b: "); dPrint(b, r, r, 0);
231    PrintLn();
232  }
233#endif
234
235
236  if( iCompDiff > 0 )
237    return YES;
238
239  if( iCompDiff < 0 )
240    return  NO;
241
242  assume( iCompDiff == 0 );
243
244  const signed long iDegDiff = p_Totaldegree(a, r) - p_Totaldegree(b, r);
245
246  if( iDegDiff > 0 )
247    return YES;
248
249  if( iDegDiff < 0 )
250    return  NO;
251
252  assume( iDegDiff == 0 );
253
254#ifndef SING_NDEBUG
255  if( OPT__DEBUG )
256  {
257    PrintS("cmp_c_ds: a & b have the same comp & deg! "); PrintLn();
258  }
259#endif
260
261  for (int v = rVar(r); v > 0; v--)
262  {
263    assume( v > 0 );
264    assume( v <= rVar(r) );
265
266    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
267
268    if( d > 0 )
269      return YES;
270
271    if( d < 0 )
272      return NO;
273
274    assume( d == 0 );
275  }
276
277  return 0;
278}
279
280/*
281static int cmp_poly(const poly &a, const poly &b)
282{
283  const int YES = 1;
284  const int NO = -1;
285
286  const ring r =  (const ring) currRing; // TODO/NOTE: the structure is known: C, lp!!!
287
288  assume( r == currRing );
289
290  assume( a != NULL );
291  assume( b != NULL );
292
293  p_LmTest(a, r);
294  p_LmTest(b, r);
295  assume( p_GetComp(a, r) == 0 );
296  assume( p_GetComp(b, r) == 0 );
297
298#ifndef SING_NDEBUG
299  const int OPT__DEBUG = 0;
300  if( OPT__DEBUG )
301  {
302    PrintS("cmp_lex: a, b: \np1: "); dPrint(a, r, r, 0);
303    PrintS("b: "); dPrint(b, r, r, 0);
304    PrintLn();
305  }
306#endif
307
308  for (int v = rVar(r); v > 0; v--)
309  {
310    assume( v > 0 );
311    assume( v <= rVar(r) );
312
313    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
314
315    if( d > 0 )
316      return YES;
317
318    if( d < 0 )
319      return NO;
320
321    assume( d == 0 );
322  }
323
324  return 0;
325}
326*/
327
328END_NAMESPACE
329/* namespace SORT_c_ds */
330
331/// writes a monomial (p),
332/// uses form x*gen(.) if ko != coloumn number of p
333static void writeLatexTerm(const poly t, const ring r, const bool bCurrSyz = true, const bool bLTonly = true)
334{
335  if( t == NULL )
336  {
337    PrintS(" 0 ");
338    return;
339  }
340
341  assume( r != NULL );
342  const coeffs C = r->cf; assume(C != NULL);
343
344  poly p = t;
345  BOOLEAN writePlus = FALSE;
346
347  do {
348  assume( p != NULL );
349
350  // write coef...
351  number& n = p_GetCoeff(p, r);
352
353  n_Normalize(n, C);
354
355  BOOLEAN writeMult = FALSE; ///< needs * before pp or module generator
356
357  BOOLEAN writeOne = FALSE; ///< need to write something after '-'!
358
359  if( n_IsZero(n, C) )
360  {
361    PrintS( writePlus? " + 0" : " 0 " ); writePlus = TRUE; writeMult = TRUE;
362//    return; // yes?
363  }
364
365  if (n_IsMOne(n, C))
366  {
367    PrintS(" - "); writeOne = TRUE; writePlus = FALSE;
368  }
369  else if (!n_IsOne(n, C))
370  {
371    if( writePlus && n_GreaterZero(n, C) )
372      PrintS(" + ");
373
374    StringSetS(""); n_WriteLong(n, C);
375    if (true)
376    {
377      char *s = StringEndS(); PrintS(s); omFree(s);
378    }
379
380
381    writeMult = TRUE;
382    writePlus = TRUE;
383  } else
384     writeOne = TRUE;
385
386  // missing '1' if no PP and gen...!?
387  // write monom...
388  const short N = rVar(r);
389
390  BOOLEAN wrotePP = FALSE; ///< needs * before module generator?
391
392  for (short i = 0; i < N; i++)
393  {
394    const long ee = p_GetExp(p, i+1, r);
395
396    if (ee!=0L)
397    {
398      if (writeMult)
399      {
400        PrintS(" ");
401        writeMult = FALSE;
402      } else
403      if( writePlus )
404        PrintS(" + ");
405
406      writePlus = FALSE;
407
408      if (ee != 1L)
409        Print(" %s^{%ld} ", rRingVar(i, r), ee);
410      else
411        Print(" %s ", rRingVar(i, r));
412
413      writeOne = FALSE;
414      wrotePP = TRUE;
415    }
416  }
417
418  writePlus = writePlus || wrotePP;
419  writeMult = writeMult || wrotePP;
420
421  // write module gen...
422  const long comp = p_GetComp(p, r);
423
424  if (comp > 0 )
425  {
426    if (writeMult)
427      PrintS("  ");
428     else
429      if( writePlus )
430        PrintS(" + ");
431
432    if (bCurrSyz)
433      Print(" \\\\GEN{%ld} ", comp);
434    else
435      Print(" \\\\GENP{%ld} ", comp);
436
437      writeOne = FALSE;
438  }
439
440  if ( writeOne )
441    PrintS( writePlus? " + 1 " : " 1 " );
442
443
444  pIter(p);
445
446  writePlus = TRUE;
447  } while( (!bLTonly) && (p != NULL) );
448
449}
450
451
452
453static FORCE_INLINE poly myp_Head(const poly p, const bool bIgnoreCoeff, const ring r)
454{
455  assume( p != NULL ); p_LmCheckPolyRing1(p, r);
456
457  poly np; omTypeAllocBin(poly, np, r->PolyBin);
458  p_SetRingOfLm(np, r);
459  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
460  pNext(np) = NULL;
461  pSetCoeff0(np, (bIgnoreCoeff)? NULL : n_Copy(pGetCoeff(p), r->cf));
462
463  p_LmCheckPolyRing1(np, r);
464  return np;
465}
466
467
468/// return a new term: leading coeff * leading monomial of p
469/// with 0 leading component!
470poly leadmonom(const poly p, const ring r, const bool bSetZeroComp)
471{
472  if( UNLIKELY(p == NULL ) )
473     return NULL;
474
475    assume( p != NULL );
476    p_LmTest(p, r);
477
478    poly m = p_LmInit(p, r);
479    p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r);
480
481    if( bSetZeroComp )
482      p_SetComp(m, 0, r);
483
484    p_Setm(m, r);
485
486    assume( m != NULL );
487    assume( pNext(m) == NULL );
488    p_LmTest(m, r);
489
490    if( bSetZeroComp )
491      assume( p_GetComp(m, r) == 0 );
492
493  return m;
494}
495
496
497
498poly p_Tail(const poly p, const ring r)
499{
500  if( UNLIKELY(p == NULL) )
501    return NULL;
502  else
503    return p_Copy( pNext(p), r );
504}
505
506
507ideal id_Tail(const ideal id, const ring r)
508{
509  if( UNLIKELY(id == NULL) )
510    return NULL;
511
512  const ideal newid = idInit(IDELEMS(id),id->rank);
513
514  for (int i=IDELEMS(id) - 1; i >= 0; i--)
515    newid->m[i] = p_Tail( id->m[i], r );
516
517  newid->rank = id_RankFreeModule(newid, currRing);
518
519  return newid;
520}
521
522
523
524void Sort_c_ds(const ideal id, const ring r)
525{
526  const int sizeNew = IDELEMS(id);
527
528#if ( (defined(HAVE_QSORT_R)) && (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FreeBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9) )
529#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, r, cmp)
530#elif ( (defined(HAVE_QSORT_R)) && (defined _GNU_SOURCE || defined __GNU__ || defined __linux__))
531#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp, r)
532#else
533#define qsort_my(m, s, ss, r, cmp) qsort(m, s, ss, cmp)
534#endif
535
536  if( sizeNew >= 2 )
537    qsort_my(id->m, sizeNew, sizeof(poly), r, FROM_NAMESPACE(SORT_c_ds, cmp_c_ds));
538
539#undef qsort_my
540
541  id->rank = id_RankFreeModule(id, r);
542}
543
544/// Clean up all the accumulated data
545void SchreyerSyzygyComputation::CleanUp()
546{
547  extern void id_Delete (ideal*, const ring);
548
549  id_Delete(const_cast<ideal*>(&m_idTails), m_rBaseRing); // TODO!!!
550
551/*if( m_sum_bucket != NULL )
552  {
553    assume ( sIsEmpty(m_sum_bucket) );
554    sBucketDestroy(&m_sum_bucket);
555    m_sum_bucket = NULL;
556  }*/
557
558  if( m_spoly_bucket != NULL )
559  {
560    kBucketDestroy(&m_spoly_bucket);
561    m_spoly_bucket = NULL;
562  }
563
564  for( TCache::iterator it = m_cache.begin(); it != m_cache.end(); it++ )
565  {
566    TP2PCache& T = it->second;
567
568    for(TP2PCache::iterator vit = T.begin(); vit != T.end(); vit++ )
569    {
570      p_Delete( (&(vit->second)), m_rBaseRing);
571      p_Delete( const_cast<poly*>(&(vit->first)), m_rBaseRing);
572    }
573  }
574}
575  /*
576  for( TTailTerms::const_iterator it = m_idTailTerms.begin(); it != m_idTailTerms.end(); it++ )
577  {
578    const TTail& v = *it;
579    for(TTail::const_iterator vit = v.begin(); vit != v.end(); vit++ )
580      delete const_cast<CTailTerm*>(*vit);
581  }
582  */
583
584
585
586int CReducerFinder::PreProcessTerm(const poly t, CReducerFinder& syzChecker) const
587{
588  assume( t != NULL );
589
590  if( UNLIKELY(OPT__DEBUG & OPT__TAILREDSYZ) )
591    assume( !IsDivisible(t) ); // each input term should NOT be in <L>
592
593  const ring r = m_rBaseRing;
594
595
596  if( LIKELY(OPT__TAILREDSYZ) )
597    if( p_LmIsConstant(t, r) ) // most basic case of baing coprime with L, whatever that is...
598      return 1; // TODO: prove this...?
599
600  //   return false; // appears to be fine
601
602  const long comp = p_GetComp(t, r);
603
604  CReducersHash::const_iterator itr = m_hash.find(comp);
605
606  if ( itr == m_hash.end() )
607    return 2; // no such leading component!!!
608
609  assume( itr->first == comp );
610
611  const bool bIdealCase = (comp == 0);
612  const bool bSyzCheck = syzChecker.IsNonempty(); // need to check even in ideal case????? proof?  "&& !bIdealCase"
613
614  if( LIKELY(OPT__TAILREDSYZ && (bIdealCase || bSyzCheck)) )
615  {
616    const TReducers& v = itr->second;
617    const int N = rVar(r);
618    // TODO: extract exps of t beforehand?!
619    bool coprime = true;
620    for(TReducers::const_iterator vit = v.begin(); (vit != v.end()) && coprime; ++vit )
621    {
622      assume( (*vit)->CheckLT( m_L ) );
623
624      const poly p = (*vit)->lt();
625
626      assume( p_GetComp(p, r) == comp );
627
628      // TODO: check if coprime with Leads... if OPT__TAILREDSYZ !
629      for( int var = N; var > 0; --var )
630        if( (p_GetExp(p, var, r) != 0) && (p_GetExp(t, var, r) != 0) )
631        {
632#ifndef SING_NDEBUG
633          if( OPT__DEBUG | 0)
634          {
635            PrintS("CReducerFinder::PreProcessTerm, 't' is NOT co-prime with the following leading term: \n");
636            dPrint(p, r, r, 0);
637          }
638#endif
639          coprime = false; // t not coprime with p!
640          break;
641        }
642
643      if( bSyzCheck && coprime )
644      {
645        poly ss = p_LmInit(t, r);
646        p_SetCoeff0(ss, n_Init(1, r), r); // for delete & printout only!...
647        p_SetComp(ss, (*vit)->label() + 1, r); // coeff?
648        p_Setm(ss, r);
649
650        coprime = ( syzChecker.IsDivisible(ss) );
651
652#ifndef SING_NDEBUG
653        if( OPT__DEBUG && !coprime)
654        {
655          PrintS("CReducerFinder::PreProcessTerm, 't' is co-prime with p but may lead to NOT divisible syz.term: \n");
656          dPrint(ss, r, r, 0);
657        }
658#endif
659
660        p_LmDelete(&ss, r); // deletes coeff as well???
661      }
662
663      assume( p == (*vit)->lt() );
664      assume( (*vit)->CheckLT( m_L ) );
665    }
666
667#ifndef SING_NDEBUG
668    if( OPT__DEBUG && coprime )
669      PrintS("CReducerFinder::PreProcessTerm, the following 't' is 'co-prime' with all of leading terms! \n");
670#endif
671
672    return coprime? 3: 0; // t was coprime with all of leading terms!!!
673
674  }
675  //   return true; // delete the term
676
677  return 0;
678}
679
680
681void SchreyerSyzygyComputation::SetUpTailTerms()
682{
683  const ideal idTails = m_idTails;
684  assume( idTails != NULL );
685  assume( idTails->m != NULL );
686  const ring r = m_rBaseRing;
687
688  unsigned long pp[4] = {0,0,0,0}; // count preprocessed terms...
689
690#ifndef SING_NDEBUG
691  if( OPT__DEBUG | 0)
692  {
693    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Tails: \n");
694    dPrint(idTails, r, r, 0);
695  }
696#endif
697
698  for( int p = IDELEMS(idTails) - 1; p >= 0; --p )
699    for( poly* tt = &(idTails->m[p]); (*tt) != NULL;  )
700    {
701      const poly t = *tt;
702      const int k = m_div.PreProcessTerm(t, m_checker); // 0..3
703      assume( 0 <= k && k <= 3 );
704
705      pp[k]++; // collect stats
706
707      if( k )
708      {
709#ifndef SING_NDEBUG
710        if( OPT__DEBUG)
711        {
712          Print("SchreyerSyzygyComputation::SetUpTailTerms(): PP (%d) the following TT: \n", k);
713          dPrint(t, r, r, 0);
714        }
715#endif
716
717        (*tt) = p_LmDeleteAndNext(t, r); // delete the lead and next...
718      }
719      else
720        tt = &pNext(t); // go next?
721
722    }
723
724#ifndef SING_NDEBUG
725  if( OPT__DEBUG | 0)
726  {
727    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Preprocessed Tails: \n");
728    dPrint(idTails, r, r, 0);
729  }
730#endif
731
732  if( UNLIKELY(OPT__PROT) )
733  {
734    Print("(PP/ST: {c: %lu, C: %lu, P: %lu} + %lu)", pp[1], pp[2], pp[3], pp[0]);
735    m_stat[0] += pp [0]; m_stat[1] += pp [1]; m_stat[2] += pp [2]; m_stat[3] += pp [3];
736  }
737}
738
739/*
740  m_idTailTerms.resize( IDELEMS(idTails) );
741
742  for( unsigned int p = IDELEMS(idTails) - 1; p >= 0; p -- )
743  {
744    TTail& v = m_idTailTerms[p];
745    poly t = idTails->m[p];
746    v.resize( pLength(t) );
747
748    unsigned int pp = 0;
749
750    while( t != NULL )
751    {
752      assume( t != NULL );
753      // TODO: compute L:t!
754//      ideal reducers;
755//      CReducerFinder m_reducers
756
757      CTailTerm* d = v[pp] = new CTailTerm();
758
759      ++pp; pIter(t);
760    }
761  }
762*/
763
764void SchreyerSyzygyComputation::PrintStats() const
765{
766  Print("SchreyerSyzygyComputation Stats: (PP/ST: {c: %lu, C: %lu, P: %lu} + %lu, LOT: %lu, LCM: %lu, ST:%lu, LK: %lu {*: %lu})\n",
767        m_stat[1], m_stat[2], m_stat[3], m_stat[0],
768        m_stat[4], m_stat[5],
769        m_stat[8],
770        m_stat[6] + m_stat[7], m_stat[7]
771       );
772}
773
774
775ideal SchreyerSyzygyComputation::Compute1LeadingSyzygyTerms()
776{
777  const ideal& id = m_idLeads;
778  const ring& r = m_rBaseRing;
779//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
780
781  assume(!OPT__LEAD2SYZ);
782
783  // 1. set of components S?
784  // 2. for each component c from S: set of indices of leading terms
785  // with this component?
786  // 3. short exp. vectors for each leading term?
787
788  const int size = IDELEMS(id);
789
790  if( size < 2 )
791  {
792    const ideal newid = idInit(1, 0); newid->m[0] = NULL; // zero ideal...
793    return newid;
794  }
795
796  // TODO/NOTE: input is supposed to be (reverse-) sorted wrt "(c,ds)"!??
797
798  // components should come in groups: count elements in each group
799  // && estimate the real size!!!
800
801
802  // use just a vector instead???
803  const ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
804
805  int k = 0;
806
807  for (int j = 0; j < size; j++)
808  {
809    const poly p = id->m[j];
810    assume( p != NULL );
811    const int  c = p_GetComp(p, r);
812
813    for (int i = j - 1; i >= 0; i--)
814    {
815      const poly pp = id->m[i];
816      assume( pp != NULL );
817      const int  cc = p_GetComp(pp, r);
818
819      if( c != cc )
820        continue;
821
822      const poly m = p_Init(r); // p_New???
823
824      // m = LCM(p, pp) / p! // TODO: optimize: knowing the ring structure: (C/lp)!
825      for (int v = rVar(r); v > 0; v--)
826      {
827        assume( v > 0 );
828        assume( v <= rVar(r) );
829
830        const short e1 = p_GetExp(p , v, r);
831        const short e2 = p_GetExp(pp, v, r);
832
833        if( e1 >= e2 )
834          p_SetExp(m, v, 0, r);
835        else
836          p_SetExp(m, v, e2 - e1, r);
837
838      }
839
840      assume( (j > i) && (i >= 0) );
841
842      p_SetComp(m, j + 1, r);
843      pNext(m) = NULL;
844      p_SetCoeff0(m, n_Init(1, r->cf), r); // for later...
845
846      p_Setm(m, r); // should not do anything!!!
847
848      newid->m[k++] = m;
849    }
850  }
851
852//   if( OPT__DEBUG & FALSE )
853//   {
854//     PrintS("ComputeLeadingSyzygyTerms::Temp0: \n");
855//     dPrint(newid, r, r, 0);
856//   }
857
858  // the rest of newid is assumed to be zeroes...
859
860  // simplify(newid, 2 + 32)??
861  // sort(newid, "C,ds")[1]???
862  id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
863
864//   if( OPT__DEBUG & FALSE )
865//   {
866//     PrintS("ComputeLeadingSyzygyTerms::Temp1: \n");
867//     dPrint(newid, r, r, 0);
868//   }
869
870  idSkipZeroes(newid); // #define SIMPL_NULL 2
871
872//   if( OPT__DEBUG )
873//   {
874//     PrintS("ComputeLeadingSyzygyTerms::Output: \n");
875//     dPrint(newid, r, r, 0);
876//   }
877
878  Sort_c_ds(newid, r);
879
880  return newid;
881}
882
883ideal SchreyerSyzygyComputation::Compute2LeadingSyzygyTerms()
884{
885  const ideal& id = m_idLeads;
886  const ring& r = m_rBaseRing;
887//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
888
889  // 1. set of components S?
890  // 2. for each component c from S: set of indices of leading terms
891  // with this component?
892  // 3. short exp. vectors for each leading term?
893
894  const int size = IDELEMS(id);
895
896  if( size < 2 )
897  {
898    const ideal newid = idInit(1, 1); newid->m[0] = NULL; // zero module...
899    return newid;
900  }
901
902
903  // TODO/NOTE: input is supposed to be sorted wrt "C,ds"!??
904
905  // components should come in groups: count elements in each group
906  // && estimate the real size!!!
907
908
909  // use just a vector instead???
910  ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
911
912  int k = 0;
913
914  for (int j = 0; j < size; j++)
915  {
916    const poly p = id->m[j];
917    assume( p != NULL );
918    const int  c = p_GetComp(p, r);
919
920    for (int i = j - 1; i >= 0; i--)
921    {
922      const poly pp = id->m[i];
923      assume( pp != NULL );
924      const int  cc = p_GetComp(pp, r);
925
926      if( c != cc )
927        continue;
928
929        // allocate memory & zero it out!
930      const poly m = p_Init(r); const poly mm = p_Init(r);
931
932
933        // m = LCM(p, pp) / p! mm = LCM(p, pp) / pp!
934        // TODO: optimize: knowing the ring structure: (C/lp)!
935
936      for (int v = rVar(r); v > 0; v--)
937      {
938        assume( v > 0 );
939        assume( v <= rVar(r) );
940
941        const short e1 = p_GetExp(p , v, r);
942        const short e2 = p_GetExp(pp, v, r);
943
944        if( e1 >= e2 )
945          p_SetExp(mm, v, e1 - e2, r); //            p_SetExp(m, v, 0, r);
946        else
947          p_SetExp(m, v, e2 - e1, r); //            p_SetExp(mm, v, 0, r);
948
949      }
950
951      assume( (j > i) && (i >= 0) );
952
953      p_SetComp(m, j + 1, r);
954      p_SetComp(mm, i + 1, r);
955
956      const number& lc1 = p_GetCoeff(p , r);
957      const number& lc2 = p_GetCoeff(pp, r);
958
959#if NODIVISION
960      assume( n_IsOne(lc1, r->cf) );
961      assume( n_IsOne(lc2, r->cf) );
962
963      p_SetCoeff0( m, n_Init( 1, r->cf), r );
964      p_SetCoeff0(mm, n_Init(-1, r->cf), r );
965#else
966      number g = n_Lcm( lc1, lc2, r->cf );
967      p_SetCoeff0(m ,       n_Div(g, lc1, r), r);
968      p_SetCoeff0(mm, n_InpNeg(n_Div(g, lc2, r), r), r);
969      n_Delete(&g, r);
970#endif
971
972      p_Setm(m, r); // should not do anything!!!
973      p_Setm(mm, r); // should not do anything!!!
974
975      pNext(m) = mm; //        pNext(mm) = NULL;
976
977      newid->m[k++] = m;
978    }
979  }
980
981//   if( OPT__DEBUG & FALSE )
982//   {
983//     PrintS("Compute2LeadingSyzygyTerms::Temp0: \n");
984//     dPrint(newid, r, r, 0);
985//   }
986
987  if( UNLIKELY(!OPT__TAILREDSYZ) )
988  {
989      // simplify(newid, 2 + 32)??
990      // sort(newid, "C,ds")[1]???
991    id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
992
993//     if( OPT__DEBUG & FALSE )
994//     {
995//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (deldiv): \n");
996//       dPrint(newid, r, r, 0);
997//     }
998  }
999  else
1000  {
1001      //      option(redSB); option(redTail);
1002      //      TEST_OPT_REDSB
1003      //      TEST_OPT_REDTAIL
1004    assume( r == currRing );
1005
1006    BITSET _save_test; SI_SAVE_OPT1(_save_test);
1007    SI_RESTORE_OPT1(Sy_bit(OPT_REDTAIL) | Sy_bit(OPT_REDSB) | _save_test);
1008
1009    intvec* w=new intvec(IDELEMS(newid));
1010    ideal tmp = kStd(newid, currRing->qideal, isHomog, &w);
1011    delete w;
1012
1013    SI_RESTORE_OPT1(_save_test)
1014
1015    id_Delete(&newid, r);
1016    newid = tmp;
1017
1018//     if( OPT__DEBUG & FALSE )
1019//     {
1020//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (std): \n");
1021//       dPrint(newid, r, r, 0);
1022//     }
1023
1024  }
1025
1026  idSkipZeroes(newid);
1027
1028  Sort_c_ds(newid, r);
1029
1030  return newid;
1031}
1032
1033poly SchreyerSyzygyComputation::TraverseNF(const poly a, const poly a2) const
1034{
1035#ifndef SING_NDEBUG
1036  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1037#endif
1038
1039  const ideal& L = m_idLeads;
1040  const ideal& T = m_idTails;
1041
1042  const ring& R = m_rBaseRing;
1043
1044  const int r = p_GetComp(a, R) - 1;
1045
1046  assume( r >= 0 && r < IDELEMS(T) );
1047  assume( r >= 0 && r < IDELEMS(L) );
1048
1049  assume( a != NULL );
1050
1051#ifndef SING_NDEBUG
1052  if( OPT__DEBUG )
1053  {
1054    PrintS("SchreyerSyzygyComputation::TraverseNF(syz_lead, poly syz_2), \n");
1055    PrintS("syz_lead: \n");
1056    dPrint(a, R, R, 0);
1057    PrintS("syz_2: \n");
1058    dPrint(a2, R, R, 0);
1059    PrintLn();
1060  }
1061#endif
1062
1063  if( UNLIKELY(OPT__TREEOUTPUT) )
1064  {
1065     PrintS("{ \"proc\": \"TraverseNF\", \"nodelabel\": \"");
1066     writeLatexTerm(a, R);
1067     PrintS("\", \"children\": [");
1068  }
1069
1070  poly aa = leadmonom(a, R); assume( aa != NULL); // :(
1071
1072#ifndef SING_NDEBUG
1073  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1074#endif
1075
1076  poly t = TraverseTail(aa, r);
1077
1078  if( a2 != NULL )
1079  {
1080    assume( OPT__LEAD2SYZ );
1081
1082    if( UNLIKELY(OPT__TREEOUTPUT) )
1083    {
1084
1085       PrintS("{ \"proc\": \"TraverseNF2\", \"nodelabel\": \"");
1086       writeLatexTerm(a2, R);
1087       PrintS("\", \"children\": [");
1088    }
1089
1090    // replace the following... ?
1091    const int r2 = p_GetComp(a2, R) - 1; poly aa2 = leadmonom(a2, R); // :(
1092
1093    assume( r2 >= 0 && r2 < IDELEMS(T) );
1094
1095    poly s =  TraverseTail(aa2, r2);
1096
1097    p_Delete(&aa2, R);
1098
1099
1100    if( UNLIKELY(OPT__TREEOUTPUT) )
1101    {
1102      PrintS("], \"noderesult\": \"");
1103      writeLatexTerm(s, R, true, false);
1104      PrintS("\" },");
1105    }
1106
1107    t = p_Add_q(a2, p_Add_q(t, s, R), R);
1108
1109#ifndef SING_NDEBUG
1110    if( OPT__DEBUG )    {      m_div.Verify();      m_checker.Verify();    }
1111#endif
1112
1113  } else
1114    t = p_Add_q(t, ReduceTerm(aa, L->m[r], a), R); // should be identical to bove with a2
1115
1116  p_Delete(&aa, R);
1117
1118  if( UNLIKELY(OPT__TREEOUTPUT) )
1119  {
1120//     poly tt = pp_Add_qq( a, t, R);
1121     PrintS("], \"noderesult\": \"");
1122     writeLatexTerm(t, R, true, false);
1123     PrintS("\" },");
1124//     p_Delete(&tt, R);
1125  }
1126#ifndef SING_NDEBUG
1127  if( OPT__DEBUG )
1128  {
1129    PrintS("SchreyerSyzygyComputation::TraverseNF(syz_lead, poly syz_2), ==>>> \n");
1130    dPrint(t, R, R, 0);
1131    PrintLn();
1132  }
1133#endif
1134
1135#ifndef SING_NDEBUG
1136  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1137#endif
1138
1139  return t;
1140}
1141
1142void SchreyerSyzygyComputation::ComputeSyzygy()
1143{
1144#ifndef SING_NDEBUG
1145  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1146#endif
1147
1148  assume( m_idLeads != NULL );
1149  assume( m_idTails != NULL );
1150
1151  const ideal& L = m_idLeads;
1152  const ideal& T = m_idTails;
1153
1154  ideal& TT = m_syzTails;
1155  const ring& R = m_rBaseRing;
1156
1157//  if( m_sum_bucket == NULL )
1158//    m_sum_bucket = sBucketCreate(R);
1159//  assume ( sIsEmpty(m_sum_bucket) );
1160
1161  if( m_spoly_bucket == NULL )
1162    m_spoly_bucket = kBucketCreate(R);
1163
1164
1165  assume( IDELEMS(L) == IDELEMS(T) );
1166
1167#ifdef SING_NDEBUG
1168  int t, r; // for rtimer benchmarking in prot realease mode
1169#endif
1170
1171  if( UNLIKELY(OPT__TREEOUTPUT) )
1172    Print("\n{ \"syzygylayer\": \"%d\", \"hybridnf\": \"%d\", \"diagrams\": \n[", OPT__SYZNUMBER, OPT__HYBRIDNF );
1173
1174  if( UNLIKELY(OPT__PROT) ) Print("\n[%d]", OPT__SYZNUMBER );
1175
1176  if( m_syzLeads == NULL )
1177  {
1178#ifdef SING_NDEBUG
1179    if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) )
1180    {
1181      t = getTimer(); r = getRTimer();
1182      Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: t: %d, r: %d\n", r, t, r);
1183    }
1184#endif
1185
1186    ComputeLeadingSyzygyTerms( OPT__LEAD2SYZ && !OPT__IGNORETAILS ); // 2 terms OR 1 term!
1187
1188#ifdef SING_NDEBUG
1189    if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) )
1190    {
1191      t = getTimer() - t; r = getRTimer() - r;
1192      Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: dt: %d, dr: %d\n", getRTimer(), t, r);
1193    }
1194#endif
1195
1196  }
1197
1198  assume( m_syzLeads != NULL );
1199  ideal& LL = m_syzLeads;
1200  const int size = IDELEMS(LL);
1201
1202  TT = idInit(size, 0);
1203
1204  if( size == 1 && LL->m[0] == NULL )
1205  {
1206     if( UNLIKELY(OPT__TREEOUTPUT) )
1207       PrintS("]},");
1208     return;
1209  }
1210
1211
1212  // use hybrid (Schreyer NF) method?
1213  const bool method = (OPT__HYBRIDNF  == 1); //  || (OPT__HYBRIDNF == 2 && OPT__SYZNUMBER < 3);
1214
1215  if( UNLIKELY(OPT__PROT) ) Print("[%s NF|%s]",(method) ? "PR" : "TT", (NOPRODUCT == 1)? "_,_": "^*^" );
1216
1217
1218  if(  LIKELY(!OPT__IGNORETAILS) )
1219  {
1220    if( T != NULL )
1221    {
1222#ifdef SING_NDEBUG
1223      if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) )
1224      {
1225        t = getTimer(); r = getRTimer();
1226        Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): t: %d, r: %d\n", r, t, r);
1227      }
1228#endif
1229
1230      SetUpTailTerms();
1231
1232#ifdef SING_NDEBUG
1233      if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) )
1234      {
1235        t = getTimer() - t; r = getRTimer() - r;
1236        Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): dt: %d, dr: %d\n", getRTimer(), t, r);
1237      }
1238#endif
1239    }
1240  }
1241
1242#ifdef SING_NDEBUG
1243  if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) )
1244  {
1245    t = getTimer(); r = getRTimer();
1246    Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: t: %d, r: %d\n", r, t, r);
1247  }
1248#endif
1249
1250#ifndef SING_NDEBUG
1251  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1252#endif
1253
1254//  for( int k = 0; k < size; ++k ) // TODO: should be fine now!
1255  for( int k = size - 1; k >= 0; --k )
1256  {
1257    const poly a = LL->m[k]; assume( a != NULL );
1258
1259    poly a2 = pNext(a);
1260
1261    // Splitting 2-terms Leading syzygy module
1262    if( a2 != NULL )
1263      pNext(a) = NULL;
1264
1265    if( UNLIKELY(OPT__IGNORETAILS) )
1266    {
1267      TT->m[k] = NULL;
1268
1269      assume( a2 != NULL );
1270
1271      if( a2 != NULL )
1272        p_Delete(&a2, R);
1273
1274      continue;
1275    }
1276
1277    //    TT->m[k] = a2;
1278
1279#ifndef SING_NDEBUG
1280    if( OPT__DEBUG )    {      m_div.Verify();      m_checker.Verify();    }
1281#endif
1282
1283    poly nf;
1284
1285    if( method )
1286      nf = SchreyerSyzygyNF(a, a2);
1287    else
1288      nf = TraverseNF(a, a2);
1289
1290#ifndef SING_NDEBUG
1291    if( OPT__DEBUG )    {      m_div.Verify();      m_checker.Verify();    }
1292#endif
1293
1294    TT->m[k] = nf;
1295
1296    if( UNLIKELY(OPT__SYZCHECK) )
1297    {
1298      // TODO: check the correctness (syzygy property): a + TT->m[k] should be a syzygy!!!
1299
1300      poly s = pp_Add_qq( a, TT->m[k], R); // current syzygy
1301
1302      poly vp = p_VectorProductLT(s, L, T, R);
1303
1304      if( UNLIKELY( OPT__DEBUG && (vp != NULL) && ! OPT__TREEOUTPUT ) )
1305      {
1306        Warn("SchreyerSyzygyComputation::ComputeSyzygy: failed syzygy property for syzygy [%d], non-zero image is as follows: ", k);
1307        dPrint(vp, R, R, 0);       p_Delete(&vp, R);
1308
1309        PrintS("SchreyerSyzygyComputation::ComputeSyzygy: Wrong syzygy is as follows: ");
1310        s = pp_Add_qq( a, TT->m[k], R);
1311        dPrint(s, R, R, 0); p_Delete(&s, R);
1312
1313        PrintS("SchreyerSyzygyComputation::ComputeSyzygy: Testing with the other method");
1314
1315        if( !method )
1316          s = SchreyerSyzygyNF(a, a2);
1317        else
1318          s = TraverseNF(a, a2);
1319
1320        s = p_Add_q( p_Copy(a, R), s, R); // another syzygy // :((((
1321        PrintS("SchreyerSyzygyComputation::ComputeSyzygy: The other method gives the following  syzygy: ");
1322        dPrint(s, R, R, 0);
1323
1324        vp = p_VectorProductLT(s, L, T, R);
1325
1326        if( vp == NULL )
1327        {
1328          PrintS("SchreyerSyzygyComputation::ComputeSyzygy: .... which is correct!!! ");
1329        } else
1330        {
1331          Warn("SchreyerSyzygyComputation::ComputeSyzygy: failed to compute syzygy tail[%d] with both methods!!! Non-zero image (2nd) is as follows: ", k);
1332          dPrint(vp, R, R, 0);
1333        }
1334
1335#ifndef SING_NDEBUG
1336        if( OPT__DEBUG )        {          m_div.Verify();          m_checker.Verify();         }
1337#endif
1338
1339      } else
1340        assume( vp == NULL );
1341
1342      if( UNLIKELY( OPT__PROT && (vp != NULL) ) ) Warn("ERROR: SyzCheck failed, wrong tail: [%d]\n\n", k); // check k'th syzygy failed
1343
1344      p_Delete(&vp, R);
1345    }
1346
1347#ifndef SING_NDEBUG
1348    if( OPT__DEBUG )    {      m_div.Verify();      m_checker.Verify();    }
1349#endif
1350  }
1351
1352#ifdef SING_NDEBUG
1353  if( UNLIKELY( OPT__PROT & RTIMER_BENCHMARKING ) )
1354  {
1355    t = getTimer() - t; r = getRTimer() - r;
1356    Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: dt: %d, dr: %d\n", getRTimer(), t, r);
1357  }
1358#endif
1359
1360  TT->rank = id_RankFreeModule(TT, R);
1361
1362  if( UNLIKELY(OPT__TREEOUTPUT) )
1363    PrintS("\n]},");
1364
1365  if( UNLIKELY(OPT__PROT) ) PrintLn();
1366}
1367
1368void SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms(bool bComputeSecondTerms)
1369{
1370//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
1371
1372//  const BOOLEAN OPT__LEAD2SYZ   = attributes.OPT__LEAD2SYZ;
1373//  const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ;
1374
1375  assume( m_syzLeads == NULL );
1376
1377  if( UNLIKELY(bComputeSecondTerms) )
1378  {
1379    assume( OPT__LEAD2SYZ );
1380//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _Compute2LeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
1381    m_syzLeads = Compute2LeadingSyzygyTerms();
1382  }
1383  else
1384  {
1385    assume( !OPT__LEAD2SYZ );
1386
1387    m_syzLeads = Compute1LeadingSyzygyTerms();
1388  }
1389//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _ComputeLeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
1390
1391  // NOTE: set m_LS if tails are to be reduced!
1392  assume( m_syzLeads!= NULL );
1393
1394  if ( LIKELY( OPT__TAILREDSYZ && !OPT__IGNORETAILS && (IDELEMS(m_syzLeads) > 0) && !((IDELEMS(m_syzLeads) == 1) && (m_syzLeads->m[0] == NULL)) ) )
1395  {
1396    m_LS = m_syzLeads;
1397    m_checker.Initialize(m_syzLeads);
1398#ifndef SING_NDEBUG
1399    if( OPT__DEBUG )
1400    {
1401      const ring& r = m_rBaseRing;
1402      PrintS("SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms: \n");
1403      PrintS("m_syzLeads: \n");
1404      dPrint(m_syzLeads, r, r, 0);
1405      PrintS("m_checker.Initialize(m_syzLeads) => \n");
1406      m_checker.DebugPrint();
1407    }
1408#endif
1409    assume( m_checker.IsNonempty() ); // TODO: this always fails... BUG????
1410  }
1411
1412  if( UNLIKELY( OPT__PROT ) ) Print("(L%dS:%d)", bComputeSecondTerms ? 2 : 1, IDELEMS(m_syzLeads));
1413
1414}
1415
1416poly SchreyerSyzygyComputation::SchreyerSyzygyNF(const poly syz_lead, poly syz_2) const
1417{
1418  assume( !OPT__IGNORETAILS );
1419
1420  const ideal& L = m_idLeads;
1421  const ideal& T = m_idTails;
1422  const ring& r = m_rBaseRing;
1423
1424  assume( syz_lead != NULL );
1425
1426
1427#ifndef SING_NDEBUG
1428  if( OPT__DEBUG )
1429  {
1430    PrintS("SchreyerSyzygyComputation::SchreyerSyzygyNF(syz_lead, poly syz_2), \n");
1431    PrintS("syz_lead: \n");
1432    dPrint(syz_lead, r, r, 0);
1433    PrintS("syz_2: \n");
1434    dPrint(syz_2, r, r, 0);
1435    PrintLn();
1436  }
1437#endif
1438
1439  if( UNLIKELY( OPT__TREEOUTPUT ) )
1440  {
1441    PrintS("{   \"nodelabel\": \""); writeLatexTerm(syz_lead, r);
1442    PrintS("\", \"children\": [");
1443  }
1444
1445  if( syz_2 == NULL )
1446  {
1447    const int rr = p_GetComp(syz_lead, r) - 1;
1448
1449    assume( rr >= 0 && rr < IDELEMS(T) );
1450    assume( rr >= 0 && rr < IDELEMS(L) );
1451
1452#if NOPRODUCT
1453    syz_2 = m_div.FindReducer(syz_lead, L->m[rr], syz_lead, m_checker);
1454    p_Test(syz_2, r);
1455
1456    if( UNLIKELY( OPT__TREEOUTPUT ) )
1457    {
1458      PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\" },");
1459    }
1460#else
1461    poly aa = leadmonom(syz_lead, r); assume( aa != NULL); // :(
1462    aa = p_Mult_mm(aa, L->m[rr], r);
1463
1464    if( UNLIKELY( OPT__TREEOUTPUT ) )
1465    {
1466      PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(aa, r, false); PrintS("\" },");
1467    }
1468
1469    syz_2 = m_div.FindReducer(aa, syz_lead, m_checker);
1470    p_Test(syz_2, r);
1471
1472    p_Delete(&aa, r);
1473#endif
1474
1475  }
1476
1477  assume( syz_2 != NULL ); // by construction of S-Polynomial
1478
1479  assume( L != NULL );
1480  assume( T != NULL );
1481
1482  assume( IDELEMS(L) == IDELEMS(T) );
1483
1484  int  c = p_GetComp(syz_lead, r) - 1;
1485
1486  assume( c >= 0 && c < IDELEMS(T) );
1487
1488  if( m_spoly_bucket == NULL )
1489    m_spoly_bucket = kBucketCreate(r);
1490
1491  SBucketWrapper tail(r, m_sum_bucket_factory);
1492
1493
1494  kBucket_pt bucket = m_spoly_bucket; assume( bucket != NULL ); kbTest(bucket); m_spoly_bucket = NULL;
1495
1496//  kBucketInit(bucket, NULL, 0); // not needed!?
1497
1498  poly p = leadmonom(syz_lead, r); // :(
1499//  poly spoly = pp_Mult_qq(p, T->m[c], r);
1500  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // TODO: store pLength(T->m[c]) separately!?
1501  p_Delete(&p, r);
1502
1503  kbTest(bucket);
1504
1505  c = p_GetComp(syz_2, r) - 1;
1506  assume( c >= 0 && c < IDELEMS(T) );
1507
1508  p = leadmonom(syz_2, r); // :(
1509//  spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
1510  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])?!
1511  kbTest(bucket);
1512  p_Delete(&p, r);
1513
1514//  const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(spoly) < MIN_LENGTH_BUCKET);
1515//  CPolynomialSummator tail(r, bUsePolynomial);
1516  tail.Add(syz_2, 1);
1517
1518  kbTest(bucket);
1519  for( poly spoly = kBucketExtractLm(bucket); spoly != NULL; p_LmDelete(&spoly, r), spoly = kBucketExtractLm(bucket))
1520  {
1521    kbTest(bucket);
1522    poly t = m_div.FindReducer(spoly, NULL, m_checker);
1523    p_Test(t, r);
1524
1525    if( t != NULL )
1526    {
1527      p = leadmonom(t, r); // :(
1528      c = p_GetComp(t, r) - 1;
1529
1530      assume( c >= 0 && c < IDELEMS(T) );
1531
1532      if(UNLIKELY( OPT__TREEOUTPUT ))
1533      {
1534        PrintS("{ \"nodelabel\": \""); writeLatexTerm(t, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(spoly, r, false); PrintS("\" },");
1535      }
1536
1537      kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])?
1538//      spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
1539
1540      p_Delete(&p, r);
1541
1542      tail.Add(t, 1);
1543    } // otherwise discard that leading term altogether!
1544    else
1545      if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT
1546
1547    kbTest(bucket);
1548  }
1549
1550  kbTest(bucket);
1551
1552  // now bucket must be empty!
1553  assume( kBucketClear(bucket) == NULL );
1554
1555  const poly result = tail.ClearAdd(); // TODO: use Merge with sBucket???
1556
1557
1558  if( m_spoly_bucket == NULL )
1559    m_spoly_bucket = bucket;
1560  else
1561    kBucketDestroy(&bucket);
1562
1563
1564  if( UNLIKELY(OPT__TREEOUTPUT) )
1565  {
1566    PrintS("]},");
1567  }
1568
1569#ifndef SING_NDEBUG
1570  if( OPT__DEBUG )
1571  {
1572    PrintS("SchreyerSyzygyComputation::SchreyerSyzygyNF(syz_lead, poly syz_2) =>>> \n");
1573    dPrint(result, r, r, 0);
1574    PrintLn();
1575    // TODO: Add SyzCheck!!!???
1576  }
1577#endif
1578
1579  return result;
1580}
1581
1582// namespace     {
1583
1584// };
1585
1586
1587bool my_p_LmCmp (poly a, poly b, const ring r) { return p_LmCmp(a, b, r) == -1; } // TODO: change to simple lex. memory compare!
1588
1589// NOTE: need p_Copy?????? for image + multiplier!!???
1590// NOTE: better store complete syz. terms!!?
1591poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, const int tail) const
1592{
1593#ifndef SING_NDEBUG
1594  if( OPT__DEBUG ) {    m_div.Verify();    m_checker.Verify();  }
1595#endif
1596
1597  const ring& r = m_rBaseRing;
1598
1599  assume(m_idTails !=  NULL && m_idTails->m != NULL);
1600  assume( tail >= 0 && tail < IDELEMS(m_idTails) );
1601
1602  p_Test(multiplier, r);
1603
1604  if( UNLIKELY(OPT__NOCACHING) )
1605    return ComputeImage(multiplier, tail);
1606
1607  // TODO: store (multiplier, tail) -.-^-.-^-.--> !
1608  TCache::iterator top_itr = m_cache.find(tail);
1609
1610  if ( top_itr != m_cache.end() )
1611  {
1612     assume( top_itr->first == tail );
1613
1614     TP2PCache& T = top_itr->second;
1615
1616     TP2PCache::iterator itr = T.find(multiplier);
1617
1618     if( itr != T.end() ) // Yey - Reuse!!!
1619     {
1620       assume( p_LmEqual(itr->first, multiplier, r) );
1621
1622       if( itr->second == NULL ) // leadcoeff plays no role if value is NULL!
1623         return (NULL);
1624
1625       if( UNLIKELY( OPT__TREEOUTPUT ) )
1626       {
1627//         PrintS("{ \"nodelabel\": \""); writeLatexTerm(multiplier, r, false);
1628//         Print("  \\\\GEN{%d}\", \"children\": [ ", tail + 1);
1629         PrintS("{ \"proc\": \"TTLookup\", \"nodelabel\": \"");
1630         writeLatexTerm(itr->first, r, false); Print(" \\\\GEN{%d}\", \"Lookup\": \"", tail + 1);
1631         writeLatexTerm(itr->second, r, true, false);
1632         PrintS("\", ");
1633       }
1634
1635       poly p = p_Copy(itr->second, r); // COPY!!!
1636
1637       p_Test(multiplier, r);
1638
1639       if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) ) // normalize coeffs!?
1640       {
1641         number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r); // new number
1642
1643         if( UNLIKELY( OPT__TREEOUTPUT ) )
1644         {
1645           StringSetS("");
1646           n_Write(n, r);
1647           char* s = StringEndS();
1648           Print("\"recale\": \"%s\", ", s);
1649           omFree(s);
1650         }
1651
1652         if( UNLIKELY( OPT__PROT ) ) ++ m_stat[7]; // PrintS("l*"); // lookup & rescale
1653
1654         p = p_Mult_nn(p, n, r); // !
1655         n_Delete(&n, r);
1656       } else
1657         if( UNLIKELY( OPT__PROT ) ) ++ m_stat[6]; // PrintS("l"); // lookup no rescale
1658
1659       if( UNLIKELY(OPT__TREEOUTPUT) )
1660       {
1661         PrintS("\"noderesult\": \"");         writeLatexTerm(p, r, true, false);         PrintS("\" },");
1662       }
1663
1664#ifndef SING_NDEBUG
1665       if( OPT__DEBUG )       {         m_div.Verify();         m_checker.Verify();       }
1666#endif
1667       p_Test(multiplier, r);
1668
1669       return p;
1670     }
1671
1672
1673     if( UNLIKELY(OPT__TREEOUTPUT) )
1674     {
1675       Print("{ \"proc\": \"TTStore%d\", \"nodelabel\": \"", tail + 1); writeLatexTerm(multiplier, r, false); Print(" \\\\GEN{%d}\", \"children\": [", tail + 1);
1676     }
1677
1678     p_Test(multiplier, r);
1679
1680     const poly p = ComputeImage(multiplier, tail);
1681
1682     if( UNLIKELY(OPT__TREEOUTPUT) )
1683     {
1684       PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },");
1685     }
1686
1687     if( UNLIKELY(OPT__PROT) ) ++ m_stat[8]; // PrintS("S"); // store
1688
1689     p_Test(multiplier, r);
1690
1691     T.insert( TP2PCache::value_type(myp_Head(multiplier, (p==NULL), r), p) ); //     T[ multiplier ] = p;
1692
1693     p_Test(multiplier, r);
1694
1695//     if( p == NULL )
1696//        return (NULL);
1697
1698#ifndef SING_NDEBUG
1699     if( OPT__DEBUG )     {       m_div.Verify();       m_checker.Verify();     }
1700#endif
1701
1702     return p_Copy(p, r);
1703  }
1704
1705  CCacheCompare o(r); TP2PCache T(o);
1706
1707  if( UNLIKELY(OPT__TREEOUTPUT) )
1708  {
1709    Print("{ \"proc\": \"TTStore%d\", \"nodelabel\": \"", 0); writeLatexTerm(multiplier, r, false); Print(" \\\\GEN{%d}\", \"children\": [", tail + 1);
1710  }
1711
1712  const poly p = ComputeImage(multiplier, tail);
1713
1714  if( UNLIKELY(OPT__TREEOUTPUT) )
1715  {
1716    PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },");
1717  }
1718
1719  if( UNLIKELY( OPT__PROT ) ) ++ m_stat[8]; // PrintS("S"); // store // %d", tail + 1);
1720
1721  T.insert( TP2PCache::value_type(myp_Head(multiplier, (p==NULL), r), p) );
1722
1723  m_cache.insert( TCache::value_type(tail, T) );
1724
1725//  if( p == NULL )
1726//    return (NULL);
1727
1728#ifndef SING_NDEBUG
1729  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1730#endif
1731
1732  return p_Copy(p, r);
1733}
1734
1735poly SchreyerSyzygyComputation::ComputeImage(poly multiplier, const int tail) const
1736{
1737  const ring& r = m_rBaseRing;
1738
1739  assume(m_idTails !=  NULL && m_idTails->m != NULL);
1740  assume( tail >= 0 && tail < IDELEMS(m_idTails) );
1741
1742  p_Test(multiplier, r);
1743
1744  const poly t = m_idTails->m[tail]; // !!!
1745
1746  if(t != NULL)
1747  {
1748    if( UNLIKELY(OPT__TREEOUTPUT) )
1749    {
1750      PrintS("{ \"proc\": \"ComputeImage\", \"nodelabel\": \"");
1751      writeLatexTerm(multiplier, r, false);
1752      Print(" \\\\GEN{%d}\", \"edgelabel\": \"", tail + 1);
1753      writeLatexTerm(t, r, false);
1754      PrintS("\", \"children\": [");
1755    }
1756
1757    const poly p = TraverseTail(multiplier, t);
1758
1759    p_Test(multiplier, r);
1760
1761    if( UNLIKELY(OPT__TREEOUTPUT) )
1762    {
1763      PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },");
1764    }
1765
1766    return p;
1767
1768  }
1769
1770  return NULL;
1771}
1772
1773
1774poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, poly tail) const
1775{
1776  assume( !OPT__IGNORETAILS );
1777
1778  const ideal& L = m_idLeads;
1779  const ideal& T = m_idTails;
1780  const ring& r = m_rBaseRing;
1781
1782  assume( multiplier != NULL );
1783
1784  assume( L != NULL );
1785  assume( T != NULL );
1786
1787  p_Test(multiplier, r);
1788
1789#ifndef SING_NDEBUG
1790  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1791#endif
1792
1793  if( UNLIKELY( !(  (!OPT__TAILREDSYZ)   ||   m_lcm.Check(multiplier)     )) )
1794  {
1795    if( UNLIKELY(OPT__TAILREDSYZ && OPT__PROT) )
1796    { 
1797      ++ m_stat[5]; // PrintS("%"); // check LCM !
1798#ifndef SING_NDEBUG
1799      if( OPT__DEBUG ) 
1800      { 
1801        PrintS("\nTT,%:"); dPrint(multiplier, r, r, 0); 
1802        PrintS(",  *  :"); dPrint(tail, r, r, 0); 
1803        PrintLn(); 
1804      }
1805#endif
1806    }
1807    return NULL;
1808  }
1809
1810  //    const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(tail) < MIN_LENGTH_BUCKET);
1811
1812  SBucketWrapper sum(r, m_sum_bucket_factory);
1813/*
1814  sBucket_pt sum;
1815
1816  if( m_sum_bucket == NULL )
1817    sum = sBucketCreate(r);
1818  else
1819  {
1820    if( !sIsEmpty(m_sum_bucket) )
1821      sum = sBucketCreate(r);
1822    else
1823    {
1824      sum = m_sum_bucket;
1825      m_sum_bucket = NULL;
1826    }
1827  }
1828
1829
1830  assume( sum != NULL ); assume ( sIsEmpty(sum) );
1831  assume( r == sBucketGetRing(sum) );
1832*/
1833
1834//  poly s; int len;
1835
1836  //    CPolynomialSummator sum(r, bUsePolynomial);
1837  //    poly s = NULL;
1838
1839  if( UNLIKELY( OPT__TREEOUTPUT & 0 ) )
1840  {
1841    Print("{ \"proc\": \"TTPoly\", \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); Print(" * \\\\ldots \", \"children\": [");
1842  }
1843
1844  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1845  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1846  for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
1847  {
1848    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1849    const poly rt = ReduceTerm(multiplier, p, NULL); // TODO: also return/store length?
1850    sum.Add(rt);
1851    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1852    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1853    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1854
1855//    const int lp = pLength(rt);
1856//    if( rt != NULL && lp != 0 )
1857//      sBucket_Add_p(sum, rt, lp);
1858  }
1859  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1860  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1861
1862//  sBucketClearAdd(sum, &s, &len); // Will Not Clear?!?
1863  const poly s = sum.ClearAdd();
1864
1865//  assume( sum != NULL ); assume ( sIsEmpty(sum) );
1866/*
1867  if( m_sum_bucket == NULL )
1868    m_sum_bucket = sum;
1869  else
1870    sBucketDestroy(&sum);
1871
1872  assume( pLength(s) == len );
1873*/
1874
1875#ifndef SING_NDEBUG
1876  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1877#endif
1878
1879  if( UNLIKELY( OPT__TREEOUTPUT & 0 ) )
1880  {
1881    PrintS("], \"noderesult\": \""); writeLatexTerm(s, r, true, false); PrintS("\" },");
1882  }
1883
1884  p_Test(multiplier, r);
1885
1886  return s;
1887}
1888
1889
1890
1891
1892poly SchreyerSyzygyComputation::ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const
1893{
1894#ifndef SING_NDEBUG
1895  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1896#endif
1897
1898  assume( !OPT__IGNORETAILS );
1899
1900  const ideal& L = m_idLeads;
1901  const ideal& T = m_idTails;
1902  const ring& r = m_rBaseRing;
1903
1904  assume( multiplier != NULL );
1905  assume( term4reduction != NULL );
1906
1907
1908  assume( L != NULL );
1909  assume( T != NULL );
1910
1911  p_Test(multiplier, r);
1912
1913  // simple implementation with FindReducer:
1914  poly s = NULL;
1915
1916  if( (!OPT__TAILREDSYZ) || m_lcm.Check(multiplier) ) // TODO: UNLIKELY / LIKELY ????
1917  {
1918#if NOPRODUCT
1919    s = m_div.FindReducer(multiplier, term4reduction, syztermCheck, m_checker); // s ????
1920    p_Test(s, r);
1921
1922    p_Test(multiplier, r);
1923
1924    if( s == NULL ) // No Reducer?
1925    {
1926      if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT
1927      return NULL;
1928    }
1929
1930    if( UNLIKELY( OPT__TREEOUTPUT ) )
1931    {
1932      poly product = pp_Mult_mm(multiplier, term4reduction, r);
1933      PrintS("{ \"proc\": \"RdTrmNoP\", \"nodelabel\": \""); writeLatexTerm(s, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(product, r, false);
1934      p_Delete(&product, r);
1935    }
1936
1937#else
1938    // NOTE: only LT(term4reduction) should be used in the following:
1939    poly product = pp_Mult_mm(multiplier, term4reduction, r);
1940    p_Test(product, r);
1941
1942    s = m_div.FindReducer(product, syztermCheck, m_checker); // ??
1943    p_Test(s, r);
1944
1945    p_Test(multiplier, r);
1946
1947    if( s == NULL ) // No Reducer?
1948    {
1949      if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT
1950      return NULL;
1951    }
1952
1953    if( UNLIKELY(OPT__TREEOUTPUT) )
1954    {
1955      PrintS("{ \"proc\": \"RdTrmP\", \"nodelabel\": \""); writeLatexTerm(s, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(product, r, false);
1956    }
1957
1958    p_Delete(&product, r);
1959#endif
1960  }
1961
1962#ifndef SING_NDEBUG
1963  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
1964#endif
1965
1966  if( s == NULL ) // No Reducer?
1967  {
1968    if( UNLIKELY( OPT__TAILREDSYZ && OPT__PROT) ) 
1969    { 
1970      ++ m_stat[5]; // PrintS("%"); // check LCM !
1971#ifndef SING_NDEBUG
1972      if( OPT__DEBUG ) 
1973      { 
1974        PrintS("\n%: RedTail("); dPrint(multiplier, r, r, 0); 
1975        PrintS(" * : "); dPrint(term4reduction, r,r,0 ); 
1976        PrintS(", {  "); dPrint(syztermCheck,r,r,0 );
1977        PrintS("  }) ");  PrintLn(); 
1978      }
1979#endif
1980    }
1981    return NULL;
1982  }
1983
1984  p_Test(multiplier, r);
1985  p_Test(s, r);
1986
1987  poly b = leadmonom(s, r);
1988
1989  p_Test(b, r);
1990
1991  const int c = p_GetComp(s, r) - 1;
1992  assume( c >= 0 && c < IDELEMS(T) );
1993
1994
1995  if( UNLIKELY( OPT__TREEOUTPUT ) )
1996     PrintS("\", \"children\": [");
1997
1998  const poly t = TraverseTail(b, c); // T->m[c];
1999
2000  if( UNLIKELY( OPT__TREEOUTPUT ) )
2001  {
2002
2003    PrintS("], \"noderesult\": \"");
2004    writeLatexTerm(t, r, true, false);
2005    PrintS("\"");
2006
2007    if( syztermCheck != NULL )
2008    {
2009      PrintS(", \"syztermCheck\":\"" );
2010      writeLatexTerm(syztermCheck, r, true, false);
2011      PrintS("\" },");
2012    } else
2013      PrintS(" },");
2014  }
2015
2016  p_Test(multiplier, r);
2017
2018  if( t != NULL )
2019    s = p_Add_q(s, t, r);
2020
2021
2022#ifndef SING_NDEBUG
2023  if( OPT__DEBUG )  {    m_div.Verify();    m_checker.Verify();  }
2024#endif
2025
2026  p_Test(multiplier, r);
2027
2028  return s;
2029}
2030
2031SchreyerSyzygyComputationFlags::SchreyerSyzygyComputationFlags(idhdl rootRingHdl):
2032    OPT__DEBUG( atGetInt(rootRingHdl,"DEBUG", 0) ),
2033    OPT__LEAD2SYZ( atGetInt(rootRingHdl, "LEAD2SYZ", 0) ),
2034    OPT__TAILREDSYZ( atGetInt(rootRingHdl, "TAILREDSYZ", 1) ),
2035    OPT__HYBRIDNF( atGetInt(rootRingHdl, "HYBRIDNF", 0) ),
2036    OPT__IGNORETAILS( atGetInt(rootRingHdl, "IGNORETAILS", 0) ),
2037    OPT__SYZNUMBER( atGetInt(rootRingHdl, "SYZNUMBER", 0) ),
2038    OPT__TREEOUTPUT( atGetInt(rootRingHdl, "TREEOUTPUT", 0) ),
2039    OPT__SYZCHECK( atGetInt(rootRingHdl, "SYZCHECK", 0) ),
2040    OPT__PROT(TEST_OPT_PROT),
2041    OPT__NOCACHING( atGetInt(rootRingHdl, "NOCACHING", 0) ),
2042    m_rBaseRing( rootRingHdl->data.uring )
2043{
2044#ifndef SING_NDEBUG
2045  if( OPT__DEBUG & 0 )
2046  {
2047    PrintS("SchreyerSyzygyComputationFlags: \n");
2048    Print("        DEBUG: \t%d\n", OPT__DEBUG);
2049//    Print("   SYZCHECK  : \t%d\n", OPT__SYZCHECK);
2050    Print("     LEAD2SYZ: \t%d\n", OPT__LEAD2SYZ);
2051    Print("   TAILREDSYZ: \t%d\n", OPT__TAILREDSYZ);
2052    Print("  IGNORETAILS: \t%d\n", OPT__IGNORETAILS);
2053    Print("   TREEOUTPUT: \t%d\n", OPT__TREEOUTPUT);
2054    Print("     SYZCHECK: \t%d\n", OPT__SYZCHECK);
2055  }
2056#endif
2057
2058  // TODO: just current setting!
2059  assume( rootRingHdl == currRingHdl );
2060  assume( rootRingHdl->typ == RING_CMD );
2061  assume( m_rBaseRing == currRing );
2062  // move the global ring here inside???
2063}
2064
2065
2066
2067CLeadingTerm::CLeadingTerm(unsigned int _label,  const poly _lt, const ring R):
2068    m_sev( p_GetShortExpVector(_lt, R) ),  m_label( _label ),  m_lt( _lt )
2069#ifndef SING_NDEBUG
2070    , _R(R), m_lt_copy( myp_Head(_lt, true, R) ) // note that p_LmEqual only tests exponents!
2071#endif
2072{
2073#ifndef SING_NDEBUG
2074  assume( pNext(m_lt_copy) == NULL );
2075#endif
2076  assume( sev() == p_GetShortExpVector(lt(), R) );
2077}
2078
2079#ifndef SING_NDEBUG
2080CLeadingTerm::~CLeadingTerm()
2081{
2082  assume( p_LmEqual(m_lt, m_lt_copy, _R) );
2083  assume( m_sev == p_GetShortExpVector(m_lt, _R) );
2084
2085  poly p = const_cast<poly>(m_lt_copy);
2086  p_Delete(&p, _R);
2087}
2088poly CLeadingTerm::lt() const
2089{
2090  assume( p_LmEqual(m_lt, m_lt_copy, _R) );
2091  assume( m_sev == p_GetShortExpVector(m_lt, _R) );
2092  return m_lt;
2093}
2094
2095unsigned long CLeadingTerm::sev() const
2096{
2097  assume( p_LmEqual(m_lt, m_lt_copy, _R) );
2098  assume( m_sev == p_GetShortExpVector(m_lt, _R) );
2099  return m_sev;
2100}
2101
2102unsigned int CLeadingTerm::label() const
2103{
2104  assume( p_LmEqual(m_lt, m_lt_copy, _R) );
2105  assume( m_sev == p_GetShortExpVector(m_lt, _R) );
2106  return m_label;
2107}
2108#endif
2109
2110
2111
2112CReducerFinder::~CReducerFinder()
2113{
2114  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ )
2115  {
2116    const TReducers& v = it->second;
2117    for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ )
2118      delete const_cast<CLeadingTerm*>(*vit);
2119  }
2120}
2121
2122
2123void CReducerFinder::Initialize(const ideal L)
2124{
2125  assume( m_L == NULL || m_L == L );
2126  if( m_L == NULL )
2127    m_L = L;
2128
2129  assume( m_L == L );
2130
2131  if( L != NULL )
2132  {
2133    const ring& R = m_rBaseRing;
2134    assume( R != NULL );
2135
2136    for( int k = IDELEMS(L) - 1; k >= 0; k-- )
2137    {
2138      const poly a = L->m[k]; // assume( a != NULL );
2139
2140      // NOTE: label is k \in 0 ... |L|-1!!!
2141      if( a != NULL )
2142        m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm(k, a, R) );
2143    }
2144  }
2145}
2146
2147CReducerFinder::CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags):
2148    SchreyerSyzygyComputationFlags(flags),
2149    m_L(const_cast<ideal>(L)), // for debug anyway
2150    m_hash()
2151{
2152  assume( flags.m_rBaseRing == m_rBaseRing );
2153  if( L != NULL )
2154    Initialize(L);
2155}
2156
2157/// _p_LmDivisibleByNoComp for a | b*c
2158static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r)
2159{
2160  int i=r->VarL_Size - 1;
2161  unsigned long divmask = r->divmask;
2162  unsigned long la, lb;
2163
2164  if (r->VarL_LowIndex >= 0)
2165  {
2166    i += r->VarL_LowIndex;
2167    do
2168    {
2169      la = a->exp[i];
2170      lb = b->exp[i] + c->exp[i];
2171      if ((la > lb) ||
2172          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
2173      {
2174        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
2175        return FALSE;
2176      }
2177      i--;
2178    }
2179    while (i>=r->VarL_LowIndex);
2180  }
2181  else
2182  {
2183    do
2184    {
2185      la = a->exp[r->VarL_Offset[i]];
2186      lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]];
2187      if ((la > lb) ||
2188          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
2189      {
2190        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
2191        return FALSE;
2192      }
2193      i--;
2194    }
2195    while (i>=0);
2196  }
2197#ifdef HAVE_RINGS
2198  assume( !rField_is_Ring(r) ); // not implemented for rings...!
2199#endif
2200  return TRUE;
2201}
2202
2203
2204bool CLeadingTerm::CheckLT( const ideal & L ) const
2205{
2206//  for( int i = IDELEMS(L); i >= 0; --i) assume( pNext(L->m[i]) == NULL ); // ???
2207  return ( L->m[label()] == lt() );
2208}
2209
2210bool CLeadingTerm::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const
2211{
2212  // may have no coeff yet
2213//  assume ( !n_IsZero( p_GetCoeff(product, r), r ) );
2214
2215  assume ( !n_IsZero( p_GetCoeff(lt(), r), r ) );
2216  assume( sev() == p_GetShortExpVector(lt(), r) );
2217
2218  assume( product != NULL );
2219  assume( (p_GetComp(lt(), r) == p_GetComp(product, r)) || (p_GetComp(lt(), r) == 0) );
2220
2221#ifndef SING_NDEBUG
2222  assume( r == _R );
2223#endif
2224
2225//  const int k = label();
2226//  assume( m_L->m[k] == p );
2227
2228  return p_LmShortDivisibleByNoComp(lt(), sev(), product, not_sev, r);
2229
2230}
2231
2232#if NOPRODUCT
2233/// as DivisibilityCheck(multiplier * t, ...) for monomial 'm'
2234/// and a module term 't'
2235bool CLeadingTerm::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const
2236{
2237  assume ( !n_IsZero( p_GetCoeff(lt(), r), r ) );
2238  assume( sev() == p_GetShortExpVector(lt(), r) );
2239
2240  assume( m != NULL );
2241  assume( t != NULL );
2242  assume ( !n_IsZero( p_GetCoeff(m, r), r ) );
2243  assume ( !n_IsZero( p_GetCoeff(t, r), r ) );
2244
2245// assume( p_GetComp(m, r) == 0 );
2246  assume( (p_GetComp(lt(), r) == p_GetComp(t, r))  || (p_GetComp(lt(), r) == 0)  );
2247
2248  p_Test(m, r);
2249  p_Test(t, r);
2250//  const int k = label();
2251//  assume( m_L->m[k] == p );
2252
2253#ifndef SING_NDEBUG
2254  assume( r == _R );
2255#endif
2256
2257  if (sev() & not_sev)
2258    return false;
2259
2260  return _p_LmDivisibleByNoComp(lt(), m, t, r);
2261//  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
2262}
2263#endif
2264
2265
2266/// TODO:
2267class CDivisorEnumerator: public SchreyerSyzygyComputationFlags
2268{
2269  private:
2270    const CReducerFinder& m_reds;
2271    const poly m_product;
2272    const unsigned long m_not_sev;
2273    const long m_comp;
2274
2275    CReducerFinder::CReducersHash::const_iterator m_itr;
2276    CReducerFinder::TReducers::const_iterator m_current, m_finish;
2277
2278    bool m_active;
2279
2280  public:
2281    CDivisorEnumerator(const CReducerFinder& self, const poly product):
2282        SchreyerSyzygyComputationFlags(self),
2283        m_reds(self),
2284        m_product(product),
2285        m_not_sev(~p_GetShortExpVector(product, m_rBaseRing)),
2286        m_comp(p_GetComp(product, m_rBaseRing)),
2287        m_itr(), m_current(), m_finish(),
2288        m_active(false)
2289    {
2290      assume( m_comp >= 0 );
2291      assume( m_reds.m_L != NULL ); /// TODO: m_L should stay the same!!!
2292
2293      assume( product != NULL ); // may have no coeff yet :(
2294//      assume ( !n_IsZero( p_GetCoeff(product, m_rBaseRing), m_rBaseRing ) );
2295#ifndef SING_NDEBUG
2296      if( OPT__DEBUG )        m_reds.Verify();
2297#endif
2298    }
2299
2300    inline bool Reset()
2301    {
2302      m_active = false;
2303
2304      m_itr = m_reds.m_hash.find(m_comp);
2305
2306      if( m_itr == m_reds.m_hash.end() )
2307        return false;
2308
2309      assume( m_itr->first == m_comp );
2310
2311      m_current = (m_itr->second).begin();
2312      m_finish = (m_itr->second).end();
2313
2314      if (m_current == m_finish)
2315        return false;
2316
2317//      m_active = true;
2318      return true;
2319    }
2320
2321    const CLeadingTerm& Current() const
2322    {
2323      assume( m_active );
2324      assume( m_current != m_finish );
2325
2326      return *(*m_current);
2327    }
2328
2329    inline bool MoveNext()
2330    {
2331      assume( m_current != m_finish );
2332
2333      if( m_active )
2334        ++m_current;
2335      else
2336        m_active = true; // for Current()
2337
2338      // looking for the next good entry
2339      for( ; m_current != m_finish; ++m_current )
2340      {
2341        assume( Current().CheckLT( m_reds.m_L ) );
2342
2343        if( Current().DivisibilityCheck(m_product, m_not_sev, m_rBaseRing) )
2344        {
2345#ifndef SING_NDEBUG
2346          if( OPT__DEBUG )
2347          {
2348            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().label());
2349            dPrint(Current().lt(), m_rBaseRing, m_rBaseRing, 0);
2350          }
2351#endif
2352//          m_active = true;
2353          assume( Current().CheckLT( m_reds.m_L ) );
2354          return true;
2355        }
2356        assume( Current().CheckLT( m_reds.m_L ) );
2357      }
2358
2359      // the end... :(
2360      assume( m_current == m_finish );
2361
2362      m_active = false;
2363      return false;
2364    }
2365};
2366
2367
2368
2369bool CReducerFinder::IsDivisible(const poly product) const
2370{
2371#ifndef SING_NDEBUG
2372  if( OPT__DEBUG )    Verify();
2373#endif
2374
2375  assume( product != NULL );
2376
2377  // NOTE: q may have no coeff!!!
2378
2379  CDivisorEnumerator itr(*this, product);
2380  if( !itr.Reset() )
2381    return false;
2382
2383  return itr.MoveNext();
2384
2385/*
2386  const ring& r = m_rBaseRing;
2387
2388  const long comp = p_GetComp(product, r);
2389  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
2390
2391  assume( comp >= 0 );
2392
2393  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
2394
2395  assume( m_L != NULL );
2396
2397  if( it == m_hash.end() )
2398    return false;
2399  // assume comp!
2400
2401  const TReducers& reducers = it->second;
2402
2403  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2404  {
2405    assume( (*vit)->CheckLT( m_L ) );
2406
2407    if( (*vit)->DivisibilityCheck(product, not_sev, r) )
2408    {
2409      if( OPT__DEBUG )
2410      {
2411        Print("_FindReducer::Test LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + (*vit)->label());
2412        dPrint((*vit)->lt(), r, r, 0);
2413      }
2414
2415      return true;
2416    }
2417  }
2418
2419  return false;
2420*/
2421}
2422
2423
2424#ifndef SING_NDEBUG
2425void CReducerFinder::Verify() const
2426{
2427  const ring& r = m_rBaseRing;
2428
2429  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++)
2430  {
2431    const TReducers& reducers = it->second;
2432
2433    for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2434    {
2435      assume( (*vit)->CheckLT( m_L ) );
2436
2437      const poly p = (*vit)->lt();
2438
2439      const unsigned long p_sev = (*vit)->sev();
2440      assume( p_sev == p_GetShortExpVector(p, r) );
2441
2442      assume( p_GetComp(p, r) == it->first );
2443
2444      const int k = (*vit)->label();
2445      assume( m_L->m[k] == p );
2446
2447      pp_Test(p, r, r);
2448    }
2449  }
2450}
2451
2452
2453
2454void CReducerFinder::DebugPrint() const
2455{
2456  const ring& r = m_rBaseRing;
2457
2458  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++)
2459  {
2460    Print("Hash Key: %ld, Values: \n", it->first);
2461    const TReducers& reducers = it->second;
2462
2463    for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2464    {
2465      assume( (*vit)->CheckLT( m_L ) );
2466
2467      const int k = (*vit)->label();
2468      const poly p = (*vit)->lt();
2469
2470      pp_Test(p, r, r);
2471
2472      assume( m_L->m[k] == p );
2473
2474      const unsigned long p_sev = (*vit)->sev();
2475      assume( p_sev == p_GetShortExpVector(p, r) );
2476
2477      assume( p_GetComp(p, r) == it->first );
2478
2479      Print("L[%d]: ", k); dPrint(p, r, r, 0); Print("SEV: %ld\n", p_sev);
2480
2481      assume( m_L->m[k] == p );
2482    }
2483  }
2484}
2485#endif
2486
2487#if NOPRODUCT
2488
2489/// TODO:
2490class CDivisorEnumerator2: public SchreyerSyzygyComputationFlags
2491{
2492  private:
2493    const CReducerFinder& m_reds;
2494    const poly m_multiplier, m_term;
2495    const unsigned long m_not_sev;
2496    const long m_comp;
2497
2498    CReducerFinder::CReducersHash::const_iterator m_itr;
2499    CReducerFinder::TReducers::const_iterator m_current, m_finish;
2500
2501    bool m_active;
2502
2503  public:
2504    CDivisorEnumerator2(const CReducerFinder& self, const poly m, const poly t):
2505        SchreyerSyzygyComputationFlags(self),
2506        m_reds(self),
2507        m_multiplier(m), m_term(t),
2508        m_not_sev(~p_GetShortExpVector(m, t, m_rBaseRing)),
2509        m_comp(p_GetComp(t, m_rBaseRing)),
2510        m_itr(), m_current(), m_finish(),
2511        m_active(false)
2512    {
2513      assume( m_comp >= 0 );
2514      assume( m_reds.m_L != NULL );
2515      assume( m_multiplier != NULL );
2516      assume( m_term != NULL );
2517
2518      assume( m != NULL );
2519      assume( t != NULL );
2520      assume ( !n_IsZero( p_GetCoeff(m, m_rBaseRing), m_rBaseRing ) );
2521      assume ( !n_IsZero( p_GetCoeff(t, m_rBaseRing), m_rBaseRing ) );
2522
2523      p_Test(m, m_rBaseRing);
2524
2525//      assume( p_GetComp(m_multiplier, m_rBaseRing) == 0 );
2526#ifndef SING_NDEBUG
2527      if( OPT__DEBUG ) m_reds.Verify();
2528#endif
2529    }
2530
2531    inline bool Reset()
2532    {
2533      m_active = false;
2534
2535      m_itr = m_reds.m_hash.find(m_comp);
2536
2537      if( m_itr == m_reds.m_hash.end() )
2538        return false;
2539
2540      assume( m_itr->first == m_comp );
2541
2542      m_current = (m_itr->second).begin();
2543      m_finish = (m_itr->second).end();
2544
2545      if (m_current == m_finish)
2546        return false;
2547
2548      return true;
2549    }
2550
2551    const CLeadingTerm& Current() const
2552    {
2553      assume( m_active );
2554      assume( m_current != m_finish );
2555
2556      return *(*m_current);
2557    }
2558
2559    inline bool MoveNext()
2560    {
2561      assume( m_current != m_finish );
2562
2563      if( m_active )
2564        ++m_current;
2565      else
2566        m_active = true;
2567
2568
2569      // looking for the next good entry
2570      for( ; m_current != m_finish; ++m_current )
2571      {
2572        assume( Current().CheckLT( m_reds.m_L ) );
2573
2574        if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, m_rBaseRing) )
2575        {
2576#ifndef SING_NDEBUG
2577          if( OPT__DEBUG )
2578          {
2579            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().label());
2580            dPrint(Current().lt(), m_rBaseRing, m_rBaseRing, 0);
2581          }
2582#endif
2583//          m_active = true;
2584          assume( Current().CheckLT( m_reds.m_L ) );
2585          return true;
2586
2587        }
2588        assume( Current().CheckLT( m_reds.m_L ) );
2589      }
2590
2591      // the end... :(
2592      assume( m_current == m_finish );
2593
2594      m_active = false;
2595      return false;
2596    }
2597};
2598
2599poly CReducerFinder::FindReducer(const poly multiplier, const poly t,
2600                                 const poly syzterm,
2601                                 const CReducerFinder& syz_checker) const
2602{
2603  const ring& r = m_rBaseRing;
2604
2605#ifndef SING_NDEBUG
2606  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
2607#endif
2608
2609  p_Test(multiplier, r);
2610
2611  CDivisorEnumerator2 itr(*this, multiplier, t);
2612  if( !itr.Reset() )
2613    return NULL;
2614
2615  // don't care about the module component of multiplier (as it may be the syzygy term)
2616  // product = multiplier * t?
2617
2618  assume( multiplier != NULL ); assume( t != NULL );
2619
2620  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
2621
2622  long c = 0;
2623
2624  if (syzterm != NULL)
2625    c = p_GetComp(syzterm, r) - 1;
2626
2627  assume( c >= 0 && c < IDELEMS(L) );
2628
2629  p_Test(multiplier, r);
2630
2631  if (UNLIKELY( OPT__DEBUG && (syzterm != NULL) ))
2632  {
2633    const poly m = L->m[c]; assume( m != NULL ); assume( pNext(m) == NULL );
2634
2635    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
2636    //  def @@product = leadmonomial(syzterm) * L[@@r];
2637    poly lm = p_Mult_mm( leadmonom(syzterm, r, true), m, r); // !NC :(
2638    poly pr = p_Mult_q( leadmonom(multiplier, r, true), leadmonom(t, r, false), r); // !NC :(
2639
2640    assume( p_EqualPolys(lm, pr, r) );
2641
2642    p_Delete(&lm, r);
2643    p_Delete(&pr, r);
2644  }
2645
2646#ifndef SING_NDEBUG
2647  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
2648#endif
2649
2650  const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ &&
2651
2652//  const poly q = p_One(r);
2653  const poly q = p_New(r); pNext(q) = NULL;
2654
2655  if( UNLIKELY(OPT__DEBUG) )
2656    p_SetCoeff0(q, 0, r); // for printing q
2657
2658  assume( pNext(q) == NULL );
2659
2660  p_Test(multiplier, r);
2661  while( itr.MoveNext() )
2662  {
2663    assume( itr.Current().CheckLT( L ) ); // ???
2664
2665    const poly p = itr.Current().lt(); // ???
2666    const int k  = itr.Current().label();
2667
2668    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t // TODO: do it once?
2669    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
2670
2671    p_SetComp(q, k + 1, r);
2672    p_Setm(q, r);
2673
2674    p_Test(multiplier, r);
2675
2676    // cannot allow something like: a*gen(i) - a*gen(i)
2677    if (syzterm != NULL && (k == c))
2678      if (p_ExpVectorEqual(syzterm, q, r))
2679      {
2680#ifndef SING_NDEBUG
2681        if( OPT__DEBUG )
2682        {
2683          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2684          dPrint(syzterm, r, r, 0);
2685        }
2686#endif
2687        assume( itr.Current().CheckLT( L ) ); // ???
2688        continue;
2689      }
2690
2691    // while the complement (the fraction) is not reducible by leading syzygies
2692    if( to_check && syz_checker.IsDivisible(q) )
2693    {
2694#ifndef SING_NDEBUG
2695      if( OPT__DEBUG )
2696      {
2697        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2698      }
2699#endif
2700      assume( itr.Current().CheckLT( L ) ); // ???
2701      continue;
2702    }
2703
2704    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
2705
2706#if NODIVISION
2707    // we assume all leading coeffs to be 1!
2708    assume( n_IsOne(p_GetCoeff(p, r), r->cf) );
2709#else
2710    if( !n_IsOne( p_GetCoeff(p, r), r ) )
2711      n = n_Div(n, p_GetCoeff(p, r), r);
2712#endif
2713
2714    p_SetCoeff0(q, n_InpNeg(n, r), r);
2715//    n_Delete(&n, r);
2716
2717#ifndef SING_NDEBUG
2718    if( OPT__DEBUG )    {      Verify();      syz_checker.Verify();    }
2719#endif
2720    p_Test(multiplier, r);
2721    p_Test(q, r);
2722
2723    assume( itr.Current().CheckLT( L ) ); // ???
2724    return q;
2725  }
2726
2727/*
2728  const long comp = p_GetComp(t, r); assume( comp >= 0 );
2729  const unsigned long not_sev = ~p_GetShortExpVector(multiplier, t, r); // !
2730
2731//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
2732//   {
2733//     const poly p = L->m[k];
2734//
2735//     if ( p_GetComp(p, r) != comp )
2736//       continue;
2737//
2738//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
2739
2740   // looking for an appropriate diviser p = L[k]...
2741  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
2742
2743  if( it == m_hash.end() )
2744    return NULL;
2745
2746  // assume comp!
2747
2748  assume( m_L != NULL );
2749
2750  const TReducers& reducers = it->second;
2751
2752  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2753  {
2754
2755    const poly p = (*vit)->lt(); // ??
2756    const int k = (*vit)->label();
2757
2758    assume( L->m[k] == p ); // CheckLT
2759
2760//    const unsigned long p_sev = (*vit)->sev();
2761//    assume( p_sev == p_GetShortExpVector(p, r) );
2762
2763//    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
2764//      continue;
2765
2766    if( !(*vit)->DivisibilityCheck(multiplier, t, not_sev, r) )
2767      continue;
2768
2769
2770//    if (p_sev & not_sev) continue;
2771//    if( !_p_LmDivisibleByNoComp(p, multiplier, t, r) ) continue;
2772
2773
2774    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t
2775    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
2776
2777    p_SetComp(q, k + 1, r);
2778    p_Setm(q, r);
2779
2780    // cannot allow something like: a*gen(i) - a*gen(i)
2781    if (syzterm != NULL && (k == c))
2782      if (p_ExpVectorEqual(syzterm, q, r))
2783      {
2784        if( OPT__DEBUG )
2785        {
2786          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2787          dPrint(syzterm, r, r, 0);
2788        }
2789
2790        continue;
2791      }
2792
2793    // while the complement (the fraction) is not reducible by leading syzygies
2794    if( to_check && syz_checker.IsDivisible(q) )
2795    {
2796      if( OPT__DEBUG )
2797      {
2798        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2799      }
2800
2801      continue;
2802    }
2803
2804    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
2805    p_SetCoeff0(q, n_InpNeg( n_Div(n, p_GetCoeff(p, r), r), r), r);
2806    n_Delete(&n, r);
2807
2808    return q;
2809  }
2810*/
2811
2812  p_LmFree(q, r);
2813
2814#ifndef SING_NDEBUG
2815  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
2816#endif
2817
2818  p_Test(multiplier, r);
2819
2820  return NULL;
2821
2822}
2823#endif
2824
2825
2826poly CReducerFinder::FindReducer(const poly product, const poly syzterm, const CReducerFinder& syz_checker) const
2827{
2828
2829#ifndef SING_NDEBUG
2830  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
2831#endif
2832
2833  CDivisorEnumerator itr(*this, product);
2834  if( !itr.Reset() )
2835    return NULL;
2836
2837
2838
2839  const ring& r = m_rBaseRing;
2840
2841  assume( product != NULL );
2842
2843  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
2844
2845  long c = 0;
2846
2847  if (syzterm != NULL)
2848    c = p_GetComp(syzterm, r) - 1;
2849
2850  assume( c >= 0 && c < IDELEMS(L) );
2851
2852  if (UNLIKELY( OPT__DEBUG && (syzterm != NULL) ))
2853  {
2854    const poly m = L->m[c];
2855
2856    assume( m != NULL ); assume( pNext(m) == NULL );
2857
2858    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
2859    assume( p_EqualPolys(lm, product, r) );
2860
2861    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
2862    //  def @@product = leadmonomial(syzterm) * L[@@r];
2863
2864    p_Delete(&lm, r);
2865  }
2866
2867#ifndef SING_NDEBUG
2868  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
2869#endif
2870
2871  const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ &&
2872
2873  const poly q = p_New(r); pNext(q) = NULL;
2874
2875  if( UNLIKELY(OPT__DEBUG) )
2876    p_SetCoeff0(q, 0, r); // ONLY for printing q
2877
2878  while( itr.MoveNext() )
2879  {
2880    assume( itr.Current().CheckLT( L ) ); // ???
2881
2882    const poly p = itr.Current().lt(); // ??
2883    const int k  = itr.Current().label();
2884
2885    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
2886    p_SetComp(q, k + 1, r);
2887    p_Setm(q, r);
2888
2889    // cannot allow something like: a*gen(i) - a*gen(i)
2890    if (syzterm != NULL && (k == c))
2891      if (p_ExpVectorEqual(syzterm, q, r))
2892      {
2893#ifndef SING_NDEBUG
2894        if( OPT__DEBUG )
2895        {
2896          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2897          dPrint(syzterm, r, r, 0);
2898        }
2899#endif
2900        assume( itr.Current().CheckLT( L ) ); // ???
2901        continue;
2902      }
2903
2904    // while the complement (the fraction) is not reducible by leading syzygies
2905    if( to_check && syz_checker.IsDivisible(q) ) // ?????
2906    {
2907#ifndef SING_NDEBUG
2908      if( OPT__DEBUG )
2909      {
2910        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2911      }
2912#endif
2913      assume( itr.Current().CheckLT( L ) ); // ???
2914      continue;
2915    }
2916
2917
2918#if NODIVISION
2919    assume( n_IsOne(p_GetCoeff(p, r), r->cf) );
2920    p_SetCoeff0(q, n_InpNeg( n_Copy(p_GetCoeff(product, r), r), r), r);
2921#else
2922    p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
2923#endif
2924
2925    assume( itr.Current().CheckLT( L ) ); // ???
2926
2927#ifndef SING_NDEBUG
2928    if( OPT__DEBUG )    {      Verify();      syz_checker.Verify();    }
2929#endif
2930
2931    return q;
2932  }
2933
2934
2935
2936/*
2937  const long comp = p_GetComp(product, r);
2938  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
2939
2940  assume( comp >= 0 );
2941
2942//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
2943//   {
2944//     const poly p = L->m[k];
2945//
2946//     if ( p_GetComp(p, r) != comp )
2947//       continue;
2948//
2949//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
2950
2951   // looking for an appropriate diviser p = L[k]...
2952  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
2953
2954  if( it == m_hash.end() )
2955    return NULL;
2956
2957  assume( m_L != NULL );
2958
2959  const TReducers& reducers = it->second;
2960
2961  const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ &&
2962
2963  const poly q = p_New(r); pNext(q) = NULL;
2964
2965  if( OPT__DEBUG )
2966    p_SetCoeff0(q, 0, r); // for printing q
2967
2968  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2969  {
2970    const poly p = (*vit)->lt(); // ???
2971
2972    assume( p_GetComp(p, r) == comp );
2973
2974    const int k = (*vit)->label();
2975
2976    assume( L->m[k] == p ); // CheckLT
2977
2978    const unsigned long p_sev = (*vit)->sev();
2979
2980    assume( p_sev == p_GetShortExpVector(p, r) );
2981
2982    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
2983      continue;
2984
2985//     // ... which divides the product, looking for the _1st_ appropriate one!
2986//     if( !p_LmDivisibleByNoComp(p, product, r) ) // included inside  p_LmShortDivisibleBy!
2987//       continue;
2988
2989    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
2990    p_SetComp(q, k + 1, r);
2991    p_Setm(q, r);
2992
2993    // cannot allow something like: a*gen(i) - a*gen(i)
2994    if (syzterm != NULL && (k == c))
2995      if (p_ExpVectorEqual(syzterm, q, r))
2996      {
2997        if( OPT__DEBUG )
2998        {
2999          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
3000          dPrint(syzterm, r, r, 0);
3001        }
3002
3003        continue;
3004      }
3005
3006    // while the complement (the fraction) is not reducible by leading syzygies
3007    if( to_check && syz_checker.IsDivisible(q) )
3008    {
3009      if( OPT__DEBUG )
3010      {
3011        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
3012      }
3013
3014      continue;
3015    }
3016
3017    p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
3018    return q;
3019  }
3020*/
3021
3022  p_LmFree(q, r);
3023
3024#ifndef SING_NDEBUG
3025  if( OPT__DEBUG )  {    Verify();    syz_checker.Verify();  }
3026#endif
3027
3028  return NULL;
3029}
3030
3031
3032
3033CLCM::CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags):
3034    SchreyerSyzygyComputationFlags(flags), std::vector<bool>(),
3035    m_compute(false), m_N(rVar(flags.m_rBaseRing))
3036{
3037  const ring& R = m_rBaseRing;
3038  assume( flags.m_rBaseRing == R );
3039  assume( R != NULL );
3040
3041  assume( L != NULL );
3042
3043  if( LIKELY( OPT__TAILREDSYZ && !OPT__HYBRIDNF && (L != NULL) )) // TODO: not hybrid!?
3044  {
3045    const int l = IDELEMS(L);
3046
3047    assume( l > 0 );
3048
3049    resize(l, false);
3050
3051    for( int k = l - 1; k >= 0; k-- )
3052    {
3053      const poly a = L->m[k]; assume( a != NULL );
3054
3055      for (unsigned int j = m_N; j > 0; j--)
3056        if ( !(*this)[j] )
3057          (*this)[j] = (p_GetExp(a, j, R) > 0);
3058    }
3059
3060    m_compute = true;
3061  }
3062}
3063
3064
3065bool CLCM::Check(const poly m) const
3066{
3067  assume( m != NULL );
3068  if( m_compute && (m != NULL))
3069  {
3070    const ring& R = m_rBaseRing;
3071
3072    assume( OPT__TAILREDSYZ && !OPT__HYBRIDNF );
3073
3074    for (unsigned int j = m_N; j > 0; j--)
3075      if ( (*this)[j] )
3076        if(p_GetExp(m, j, R) > 0)
3077          return true;
3078
3079    return false;
3080
3081  } else return true;
3082}
3083
3084CCacheCompare::CCacheCompare(): m_ring(currRing) {}
3085
3086
3087template class std::vector<bool>;
3088template class std::vector<CLeadingTerm const*>;
3089template class std::map< CReducerFinder::TComponentKey, CReducerFinder::TReducers >;
3090
3091template class std::map<TCacheKey, TCacheValue, struct CCacheCompare>;
3092template class std::map<int, TP2PCache>;
3093
3094template class std::stack <sBucket_pt>;
3095
3096END_NAMESPACE               END_NAMESPACE_SINGULARXX
3097
3098
3099// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
Note: See TracBrowser for help on using the repository browser.