source: git/dyn_modules/syzextra/syzextra.cc @ 68fedf

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