source: git/Singular/dyn_modules/syzextra/syzextra.cc @ ec89bb4

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