source: git/kernel/GBEngine/syz4.cc @ d1cc666

fieker-DuValspielwiese
Last change on this file since d1cc666 was d1cc666, checked in by Andreas Steenpass <steenpass@…>, 8 years ago
add: integrate the lifting from syzextra
  • Property mode set to 100644
File size: 23.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: resolutions
6*/
7
8#include <kernel/GBEngine/syz.h>
9#include <omalloc/omalloc.h>
10#include <coeffs/numbers.h>
11#include <kernel/polys.h>
12#include <kernel/ideals.h>
13
14#include <vector>
15#include <map>
16
17static poly TraverseTail_test(poly multiplier, const int tail);
18static poly ComputeImage_test(poly multiplier, const int tail);
19static poly TraverseTail_test(poly multiplier, poly tail);
20static poly ReduceTerm_test(poly multiplier, poly term4reduction, poly syztermCheck);
21static poly leadmonom_test(const poly p, const ring r, const bool bSetZeroComp = true);
22
23static ideal m_idLeads_test;
24static ideal m_idTails_test;
25
26class CLCM_test: public std::vector<bool>
27{
28  public:
29    CLCM_test(const ideal& L);
30    void redefine(const ideal L);
31    bool Check(const poly m) const;
32
33  private:
34    bool m_compute;
35    unsigned int m_N;   // number of ring variables
36};
37
38CLCM_test::CLCM_test(const ideal& L):
39    std::vector<bool>(),
40    m_compute(false), m_N(0)   // m_N(rVar(currRing))
41{
42  const ring R = currRing;
43  if( L != NULL )
44  {
45    const int l = IDELEMS(L);
46    resize(l, false);
47    for( int k = l - 1; k >= 0; k-- )
48    {
49      const poly a = L->m[k];
50      for (unsigned int j = m_N; j > 0; j--)
51        if ( !(*this)[j] )
52          (*this)[j] = (p_GetExp(a, j, R) > 0);
53    }
54    m_compute = true;
55  }
56}
57
58void CLCM_test::redefine(const ideal L)
59{
60  resize(0); // std::vector<bool>()
61  m_compute = false;
62  m_N = rVar(currRing);
63  const ring R = currRing;
64  if( L != NULL )
65  {
66    const int l = IDELEMS(L);
67    resize(l, false);
68    for( int k = l - 1; k >= 0; k-- )
69    {
70      const poly a = L->m[k];
71      for (unsigned int j = m_N; j > 0; j--)
72        if ( !(*this)[j] )
73          (*this)[j] = (p_GetExp(a, j, R) > 0);
74    }
75    m_compute = true;
76  }
77}
78
79bool CLCM_test::Check(const poly m) const
80{
81  if( m_compute && (m != NULL))
82  {
83    const ring R = currRing;
84    for (unsigned int j = m_N; j > 0; j--)
85      if ( (*this)[j] )
86        if(p_GetExp(m, j, R) > 0)
87          return true;
88    return false;
89  } else return true;
90}
91
92static CLCM_test m_lcm(NULL);
93
94static poly TraverseNF_test(const poly a, const poly a2)
95{
96  const ideal& L = m_idLeads_test;
97  const ring R = currRing;
98  const int r = p_GetComp(a, R) - 1;
99  poly aa = leadmonom_test(a, R);
100  poly t = TraverseTail_test(aa, r);
101  if( a2 != NULL )
102  {
103    const int r2 = p_GetComp(a2, R) - 1;
104    poly aa2 = leadmonom_test(a2, R);
105    poly s =  TraverseTail_test(aa2, r2);
106    p_Delete(&aa2, R);
107    t = p_Add_q(a2, p_Add_q(t, s, R), R);
108  } else
109    t = p_Add_q(t, ReduceTerm_test(aa, L->m[r], a), R);
110  p_Delete(&aa, R);
111  return t;
112}
113
114#define CACHE 1
115
116#if CACHE
117typedef poly TCacheKey_test;
118typedef poly TCacheValue_test;
119
120bool my_p_LmCmp_test (poly a, poly b, const ring r)
121{
122  return p_LmCmp(a, b, r) == -1;
123}
124
125struct CCacheCompare_test
126{
127  const ring& m_ring_test;
128  CCacheCompare_test(): m_ring_test(currRing) {}
129  CCacheCompare_test(const ring& r): m_ring_test(r) {}
130  CCacheCompare_test(const CCacheCompare_test& lhs):
131    m_ring_test(lhs.m_ring_test) {}
132  CCacheCompare_test& operator=(const CCacheCompare_test& lhs)
133  {
134    return (const_cast<CCacheCompare_test&>(lhs));
135  }
136  inline bool operator() (const TCacheKey_test& l, const TCacheKey_test& r)
137    const
138  {
139    return my_p_LmCmp_test(l, r, m_ring_test);
140  }
141};
142
143typedef std::map<TCacheKey_test, TCacheValue_test, CCacheCompare_test>
144  TP2PCache_test;
145typedef std::map<int, TP2PCache_test> TCache_test;
146
147static TCache_test m_cache_test;
148
149static FORCE_INLINE poly myp_Head_test(const poly p, const bool bIgnoreCoeff,
150  const ring r)
151{
152  p_LmCheckPolyRing1(p, r);
153  poly np;
154  omTypeAllocBin(poly, np, r->PolyBin);
155  p_SetRingOfLm(np, r);
156  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
157  pNext(np) = NULL;
158  pSetCoeff0(np, (bIgnoreCoeff)? NULL : n_Copy(pGetCoeff(p), r->cf));
159  p_LmCheckPolyRing1(np, r);
160  return np;
161}
162#endif   // CACHE
163
164static poly TraverseTail_test(poly multiplier, const int tail)
165{
166  const ring& r = currRing;
167#if CACHE
168  TCache_test::iterator top_itr = m_cache_test.find(tail);
169  if ( top_itr != m_cache_test.end() )
170  {
171     TP2PCache_test& T = top_itr->second;
172     TP2PCache_test::iterator itr = T.find(multiplier);
173     if( itr != T.end() )
174     {
175       if( itr->second == NULL )
176         return (NULL);
177       poly p = p_Copy(itr->second, r);
178       if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) )
179       {
180         number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r);
181         p = p_Mult_nn(p, n, r);
182         n_Delete(&n, r);
183       }
184       return p;
185     }
186     const poly p = ComputeImage_test(multiplier, tail);
187     T.insert(TP2PCache_test::value_type(myp_Head_test(multiplier, (p==NULL),
188       r), p) );
189     return p_Copy(p, r);
190  }
191  CCacheCompare_test o(r);
192  TP2PCache_test T(o);
193#endif   // CACHE
194  const poly p = ComputeImage_test(multiplier, tail);
195#if CACHE
196  T.insert(TP2PCache_test::value_type(myp_Head_test(multiplier, (p==NULL), r),
197    p));
198  m_cache_test.insert( TCache_test::value_type(tail, T) );
199  return p_Copy(p, r);
200#else
201  return p;
202#endif   // CACHE
203}
204
205static poly ComputeImage_test(poly multiplier, const int tail)
206{
207  const poly t = m_idTails_test->m[tail];
208  if(t != NULL)
209  {
210    const poly p = TraverseTail_test(multiplier, t);
211    return p;
212  }
213  return NULL;
214}
215
216#define BUCKETS 1
217/* 0: use original code (not implemented)
218 * 1: use Singular's SBuckets
219 * 2: use Singular's polynomial arithmetic
220 */
221
222static poly TraverseTail_test(poly multiplier, poly tail)
223{
224  const ring r = currRing;
225  if( !m_lcm.Check(multiplier) )
226  {
227    return NULL;
228  }
229#if BUCKETS == 0
230  SBucketWrapper sum(r, m_sum_bucket_factory);
231#elif BUCKETS == 1
232  sBucket_pt sum = sBucketCreate(currRing);
233#else   // BUCKETS == 2
234  poly s = NULL;
235#endif   // BUCKETS
236  for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
237  {
238    const poly rt = ReduceTerm_test(multiplier, p, NULL);
239#if BUCKETS == 0
240    sum.Add(rt);
241#elif BUCKETS == 1
242    sBucket_Add_p(sum, rt, pLength(rt));
243#else   // BUCKETS == 2
244    s = p_Add_q(s, rt, r);
245#endif   // BUCKETS
246  }
247#if BUCKETS == 0
248  const poly s = sum.ClearAdd();
249#elif BUCKETS == 1
250  poly s;
251  int l;
252  sBucketClearAdd(sum, &s, &l);
253#else   // BUCKETS == 2
254  // nothing to do
255#endif   // BUCKETS
256  return s;
257}
258
259static poly leadmonom_test(const poly p, const ring r, const bool bSetZeroComp)
260{
261  if( p == NULL )
262    return NULL;
263  poly m = p_LmInit(p, r);
264  p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r);
265  if( bSetZeroComp )
266    p_SetComp(m, 0, r);
267  p_Setm(m, r);
268  return m;
269}
270
271// _p_LmDivisibleByNoComp for a | b*c
272static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r)
273{
274  int i=r->VarL_Size - 1;
275  unsigned long divmask = r->divmask;
276  unsigned long la, lb;
277
278  if (r->VarL_LowIndex >= 0)
279  {
280    i += r->VarL_LowIndex;
281    do
282    {
283      la = a->exp[i];
284      lb = b->exp[i] + c->exp[i];
285      if ((la > lb) ||
286          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
287      {
288        return FALSE;
289      }
290      i--;
291    }
292    while (i>=r->VarL_LowIndex);
293  }
294  else
295  {
296    do
297    {
298      la = a->exp[r->VarL_Offset[i]];
299      lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]];
300      if ((la > lb) ||
301          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
302      {
303        return FALSE;
304      }
305      i--;
306    }
307    while (i>=0);
308  }
309  return TRUE;
310}
311
312class CLeadingTerm_test
313{
314  public:
315    CLeadingTerm_test(unsigned int label,  const poly lt, const ring);
316
317    bool DivisibilityCheck(const poly multiplier, const poly t, const unsigned long not_sev, const ring r) const;
318    bool DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const;
319
320    bool CheckLT( const ideal & L ) const;
321
322    inline poly lt() const { return m_lt; };
323    inline unsigned long sev() const { return m_sev; };
324    inline unsigned int label() const { return m_label; };
325
326  private:
327    const unsigned long m_sev; ///< not short exp. vector
328
329    // NOTE/TODO: either of the following should be enough:
330    const unsigned int  m_label; ///< index in the main L[] + 1
331
332    const poly          m_lt; ///< the leading term itself L[label-1]
333
334    // disable the following:
335    CLeadingTerm_test();
336    CLeadingTerm_test(const CLeadingTerm_test&);
337    void operator=(const CLeadingTerm_test&);
338};
339
340CLeadingTerm_test::CLeadingTerm_test(unsigned int _label,  const poly _lt, const ring R):
341    m_sev( p_GetShortExpVector(_lt, R) ),  m_label( _label ),  m_lt( _lt )
342{
343}
344
345bool CLeadingTerm_test::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const
346{
347  return p_LmShortDivisibleByNoComp(lt(), sev(), product, not_sev, r);
348}
349
350bool CLeadingTerm_test::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const
351{
352  if (sev() & not_sev) {
353    return false;
354  }
355  return _p_LmDivisibleByNoComp(lt(), m, t, r);
356}
357
358class CReducerFinder_test
359{
360  friend class CDivisorEnumerator_test;
361  friend class CDivisorEnumerator2_test;
362
363  public:
364    typedef long TComponentKey;
365    typedef std::vector<const CLeadingTerm_test*> TReducers;
366
367  private:
368    typedef std::map< TComponentKey, TReducers> CReducersHash;
369
370  public:
371    /// goes over all leading terms
372    CReducerFinder_test(const ideal L);
373
374    void redefine(const ideal L);
375
376    void Initialize(const ideal L);
377
378    ~CReducerFinder_test();
379
380    static poly FindReducer(const poly multiplier, const poly monom, const poly syzterm, const CReducerFinder_test& checker);
381
382    bool IsDivisible(const poly q) const;
383
384    inline bool IsNonempty() const { return !m_hash.empty(); }
385
386    int PreProcessTerm(const poly t, CReducerFinder_test& syzChecker) const;
387
388  private:
389    ideal m_L; ///< only for debug
390
391    CReducersHash m_hash; // can also be replaced with a vector indexed by components
392
393  private:
394    CReducerFinder_test(const CReducerFinder_test&);
395    void operator=(const CReducerFinder_test&);
396};
397
398CReducerFinder_test::CReducerFinder_test(const ideal L):
399    m_L(const_cast<ideal>(L)), // for debug anyway
400    m_hash()
401{
402  if( L != NULL )
403    Initialize(L);
404}
405
406CReducerFinder_test::~CReducerFinder_test()
407{
408  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ )
409  {
410    const TReducers& v = it->second;
411    for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ )
412      delete const_cast<CLeadingTerm_test*>(*vit);
413  }
414}
415
416void CReducerFinder_test::redefine(const ideal L)
417{
418  m_L = const_cast<ideal>(L); // for debug anyway
419  m_hash.clear();
420  if( L != NULL )
421    Initialize(L);
422}
423
424CReducerFinder_test m_checker(NULL);
425CReducerFinder_test m_div(NULL);
426
427class CDivisorEnumerator_test
428{
429  private:
430    const CReducerFinder_test& m_reds;
431    const poly m_product;
432    const unsigned long m_not_sev;
433    const long m_comp;
434
435    CReducerFinder_test::CReducersHash::const_iterator m_itr;
436    CReducerFinder_test::TReducers::const_iterator m_current, m_finish;
437
438    bool m_active;
439
440  public:
441    CDivisorEnumerator_test(const CReducerFinder_test& self, const poly product):
442        m_reds(self),
443        m_product(product),
444        m_not_sev(~p_GetShortExpVector(product, currRing)),
445        m_comp(p_GetComp(product, currRing)),
446        m_itr(), m_current(), m_finish(),
447        m_active(false)
448    {
449    }
450
451    inline bool Reset()
452    {
453      m_active = false;
454      m_itr = m_reds.m_hash.find(m_comp);
455      if( m_itr == m_reds.m_hash.end() )
456        return false;
457      m_current = (m_itr->second).begin();
458      m_finish = (m_itr->second).end();
459      if (m_current == m_finish)
460        return false;
461      return true;
462    }
463
464    const CLeadingTerm_test& Current() const
465    {
466      return *(*m_current);
467    }
468
469    inline bool MoveNext()
470    {
471      if( m_active )
472        ++m_current;
473      else
474        m_active = true; // for Current()
475      for( ; m_current != m_finish; ++m_current )
476      {
477        if( Current().DivisibilityCheck(m_product, m_not_sev, currRing) )
478        {
479          return true;
480        }
481      }
482      m_active = false;
483      return false;
484    }
485};
486
487class CDivisorEnumerator2_test
488{
489  private:
490    const CReducerFinder_test& m_reds;
491    const poly m_multiplier, m_term;
492    const unsigned long m_not_sev;
493    const long m_comp;
494
495    CReducerFinder_test::CReducersHash::const_iterator m_itr;
496    CReducerFinder_test::TReducers::const_iterator m_current, m_finish;
497
498    bool m_active;
499
500  public:
501    CDivisorEnumerator2_test(const CReducerFinder_test& self, const poly m, const poly t):
502        m_reds(self),
503        m_multiplier(m), m_term(t),
504        m_not_sev(~p_GetShortExpVector(m, t, currRing)),
505        m_comp(p_GetComp(t, currRing)),
506        m_itr(), m_current(), m_finish(),
507        m_active(false)
508    {
509    }
510
511    inline bool Reset()
512    {
513      m_active = false;
514      m_itr = m_reds.m_hash.find(m_comp);
515      if( m_itr == m_reds.m_hash.end() )
516        return false;
517      m_current = (m_itr->second).begin();
518      m_finish = (m_itr->second).end();
519      if (m_current == m_finish)
520        return false;
521      return true;
522    }
523
524    const CLeadingTerm_test& Current() const
525    {
526      return *(*m_current);
527    }
528
529    inline bool MoveNext()
530    {
531      if( m_active )
532        ++m_current;
533      else
534        m_active = true;
535      // looking for the next good entry
536      for( ; m_current != m_finish; ++m_current )
537      {
538        if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, currRing) )
539        {
540          return true;
541        }
542      }
543      m_active = false;
544      return false;
545    }
546};
547
548poly CReducerFinder_test::FindReducer(const poly multiplier, const poly t,
549                                 const poly syzterm,
550                                 const CReducerFinder_test& syz_checker)
551{
552  const ring r = currRing;
553  CDivisorEnumerator2_test itr(m_div, multiplier, t);
554  if( !itr.Reset() )
555    return NULL;
556  long c = 0;
557  if (syzterm != NULL)
558    c = p_GetComp(syzterm, r) - 1;
559  const BOOLEAN to_check = (syz_checker.IsNonempty());
560  const poly q = p_New(r);
561  pNext(q) = NULL;
562  while( itr.MoveNext() )
563  {
564    const poly p = itr.Current().lt();
565    const int k  = itr.Current().label();
566    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t
567    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
568    p_SetComp(q, k + 1, r);
569    p_Setm(q, r);
570    // cannot allow something like: a*gen(i) - a*gen(i)
571    if (syzterm != NULL && (k == c))
572    if (p_ExpVectorEqual(syzterm, q, r))
573    {
574      continue;
575    }
576    // while the complement (the fraction) is not reducible by leading syzygies
577    if( to_check && syz_checker.IsDivisible(q) )
578    {
579      continue;
580    }
581    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
582    p_SetCoeff0(q, n_InpNeg(n, r), r);
583    return q;
584  }
585  p_LmFree(q, r);
586  return NULL;
587}
588
589bool CReducerFinder_test::IsDivisible(const poly product) const
590{
591  CDivisorEnumerator_test itr(*this, product);
592  if( !itr.Reset() )
593    return false;
594  return itr.MoveNext();
595}
596
597static poly ReduceTerm_test(poly multiplier, poly term4reduction, poly syztermCheck)
598{
599  const ring r = currRing;
600  poly s = NULL;
601  if( m_lcm.Check(multiplier) )
602  {
603    s = CReducerFinder_test::FindReducer(multiplier, term4reduction, syztermCheck, m_checker);
604  }
605  if( s == NULL )
606  {
607    return NULL;
608  }
609  poly b = leadmonom_test(s, r);
610  const int c = p_GetComp(s, r) - 1;
611  const poly t = TraverseTail_test(b, c);
612  if( t != NULL )
613    s = p_Add_q(s, t, r);
614  return s;
615}
616
617void CReducerFinder_test::Initialize(const ideal L)
618{
619  if( m_L == NULL )
620    m_L = L;
621  if( L != NULL )
622  {
623    const ring R = currRing;
624    for( int k = IDELEMS(L) - 1; k >= 0; k-- )
625    {
626      const poly a = L->m[k];
627      if( a != NULL )
628      {
629        m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm_test(k, a, R) );
630      }
631    }
632  }
633}
634
635/*****************************************************************************/
636
637typedef poly syzHeadFunction(ideal, int, int);
638
639static poly syzHeadFrame(const ideal G, const int i, const int j)
640{
641    const ring r = currRing;
642    const poly f_i = G->m[i];
643    const poly f_j = G->m[j];
644    poly head = p_Init(r);
645    pSetCoeff0(head, n_Init(1, r->cf));
646    long exp_i, exp_j, lcm;
647    for (int k = (int)r->N; k > 0; k--) {
648        exp_i = p_GetExp(f_i, k, r);
649        exp_j = p_GetExp(f_j, k, r);
650        lcm = si_max(exp_i, exp_j);
651        p_SetExp(head, k, lcm-exp_i, r);
652    }
653    p_SetComp(head, i+1, r);
654    p_Setm(head, r);
655    return head;
656}
657
658static poly syzHeadExtFrame(const ideal G, const int i, const int j)
659{
660    const ring r = currRing;
661    const poly f_i = G->m[i];
662    const poly f_j = G->m[j];
663    poly head = p_Init(r);
664    pSetCoeff0(head, n_Init(1, r->cf));
665    poly head_ext = p_Init(r);
666    pSetCoeff0(head_ext, n_InpNeg(n_Div(pGetCoeff(f_j), pGetCoeff(f_i), r->cf),
667        r->cf));
668    long exp_i, exp_j, lcm;
669    for (int k = (int)r->N; k > 0; k--) {
670        exp_i = p_GetExp(f_i, k, r);
671        exp_j = p_GetExp(f_j, k, r);
672        lcm = si_max(exp_i, exp_j);
673        p_SetExp(head, k, lcm-exp_i, r);
674        p_SetExp(head_ext, k, lcm-exp_j, r);
675    }
676    p_SetComp(head, i+1, r);
677    p_Setm(head, r);
678    p_SetComp(head_ext, j+1, r);
679    p_Setm(head_ext, r);
680    head->next = head_ext;
681    return head;
682}
683
684typedef ideal syzM_i_Function(ideal, int, syzHeadFunction);
685
686static ideal syzM_i_unsorted(const ideal G, const int i,
687    const syzHeadFunction *syzHead)
688{
689    ideal M_i = NULL;
690    int comp = pGetComp(G->m[i]);
691    int ncols = 0;
692    for (int j = i-1; j >= 0; j--) {
693        if (pGetComp(G->m[j]) == comp) ncols++;
694    }
695    if (ncols > 0) {
696        M_i = idInit(ncols, G->ncols);
697        int k = ncols-1;
698        for (int j = i-1; j >= 0; j--) {
699            if (pGetComp(G->m[j]) == comp) {
700                M_i->m[k] = syzHead(G, i, j);
701                k--;
702            }
703        }
704        id_DelDiv(M_i, currRing);
705        idSkipZeroes(M_i);
706    }
707    return M_i;
708}
709
710static ideal syzM_i_sorted(const ideal G, const int i,
711    const syzHeadFunction *syzHead)
712{
713    ideal M_i = NULL;
714    int comp = pGetComp(G->m[i]);
715    int index = i-1;
716    while (pGetComp(G->m[index]) == comp) index--;
717    index++;
718    int ncols = i-index;
719    if (ncols > 0) {
720        M_i = idInit(ncols, G->ncols);
721        for (int j = ncols-1; j >= 0; j--) {
722            M_i->m[j] = syzHead(G, i, j+index);
723        }
724        id_DelDiv(M_i, currRing);
725        idSkipZeroes(M_i);
726    }
727    return M_i;
728}
729
730static ideal idConcat(const ideal* M, const int size, const int rank)
731{
732    int ncols = 0;
733    for (int i = size-1; i >= 0; i--) {
734        if (M[i] != NULL) {
735            ncols += M[i]->ncols;
736        }
737    }
738    if (ncols == 0) return idInit(1, rank);
739    ideal result = idInit(ncols, rank);
740    int k = ncols-1;
741    for (int i = size-1; i >= 0; i--) {
742        if (M[i] != NULL) {
743            for (int j = M[i]->ncols-1; j >= 0; j--) {
744                result->m[k] = M[i]->m[j];
745                k--;
746            }
747        }
748    }
749    return result;
750}
751
752#define SORT_MI 1
753
754#if SORT_MI
755static int compare_Mi(const void* a, const void *b)
756{
757    const ring r = currRing;
758    poly p_a = *((poly *)a);
759    poly p_b = *((poly *)b);
760    int cmp;
761    int deg_a = p_Deg(p_a, r);
762    int deg_b = p_Deg(p_b, r);
763    cmp = (deg_a > deg_b) - (deg_a < deg_b);
764    if (cmp != 0) {
765         return cmp;
766    }
767    int comp_a = p_GetComp(p_a, r);
768    int comp_b = p_GetComp(p_b, r);
769    cmp = (comp_a > comp_b) - (comp_a < comp_b);
770    if (cmp != 0) {
771         return cmp;
772    }
773    int exp_a[r->N+1];
774    int exp_b[r->N+1];
775    p_GetExpV(p_a, exp_a, r);
776    p_GetExpV(p_b, exp_b, r);
777    for (int i = r->N; i > 0; i--) {
778        cmp = (exp_a[i] > exp_b[i]) - (exp_a[i] < exp_b[i]);
779        if (cmp != 0) {
780            return cmp;
781        }
782    }
783    return 0;
784}
785#endif   // SORT_MI
786
787static ideal computeFrame(const ideal G, const syzM_i_Function syzM_i,
788    const syzHeadFunction *syzHead)
789{
790    ideal* M = (ideal *)omalloc((G->ncols-1)*sizeof(ideal));
791    for (int i = G->ncols-2; i >= 0; i--) {
792        M[i] = syzM_i(G, i+1, syzHead);
793    }
794    ideal frame = idConcat(M, G->ncols-1, G->ncols);
795    for (int i = G->ncols-2; i >= 0; i--) {
796        if (M[i] != NULL) {
797            omFreeSize(M[i]->m, IDELEMS(M[i])*sizeof(poly));
798            omFreeBin(M[i], sip_sideal_bin);
799        }
800    }
801    omFree(M);
802#if SORT_MI
803    qsort(frame->m, IDELEMS(frame), sizeof(poly), compare_Mi);
804#endif
805    return frame;
806}
807
808static void setGlobalVariables(const resolvente res, const int index)
809{
810    m_idLeads_test = idCopy(res[index-1]);
811    m_idTails_test = idInit(IDELEMS(res[index-1]), 1);
812    for (int i = IDELEMS(res[index-1])-1; i >= 0; i--) {
813        m_idTails_test->m[i] = m_idLeads_test->m[i]->next;
814        m_idLeads_test->m[i]->next = NULL;
815    }
816    m_div.redefine(m_idLeads_test);
817    m_lcm.redefine(m_idLeads_test);
818    ideal m_syzLeads_test = idCopy(res[index]);
819    for (int i = IDELEMS(res[index])-1; i >= 0; i--) {
820        pDelete(&m_syzLeads_test->m[i]->next);
821    }
822    m_checker.redefine(m_syzLeads_test);
823#if CACHE
824    for (TCache_test::iterator it = m_cache_test.begin();
825        it != m_cache_test.end(); it++) {
826        TP2PCache_test& T = it->second;
827        for (TP2PCache_test::iterator vit = T.begin(); vit != T.end(); vit++) {
828            p_Delete((&(vit->second)), currRing);
829            p_Delete(const_cast<poly*>(&(vit->first)), currRing);
830        }
831        T.erase(T.begin(), T.end());
832    }
833    m_cache_test.erase(m_cache_test.begin(), m_cache_test.end());
834#endif   // CACHE
835}
836
837#define MYLIFT 0
838
839static void computeLiftings(const resolvente res, const int index)
840{
841#if MYLIFT
842    for (int j = res[index]->ncols-1; j >= 0; j--) {
843        liftTree(res[index]->m[j], res[index-1]);
844    }
845#else
846    setGlobalVariables(res, index);
847    poly p;
848    for (int j = res[index]->ncols-1; j >= 0; j--) {
849        p = res[index]->m[j];
850        p->next = NULL;
851        pDelete(&res[index]->m[j]->next);
852        res[index]->m[j]->next = TraverseNF_test(p, NULL);
853    }
854#endif   // MYLIFT
855}
856
857static void sortPolysTails(const resolvente res, const int index)
858{
859    const ring r = currRing;
860    for (int j = res[index]->ncols-1; j >= 0; j--) {
861        if (res[index]->m[j]->next != NULL) {
862            res[index]->m[j]->next->next
863                = p_SortAdd(res[index]->m[j]->next->next, r);
864        }
865    }
866}
867
868static int computeResolution(resolvente &res, const int length,
869    const syzHeadFunction *syzHead)
870{
871    int index = 0;
872    if (!idIs0(res[index]) && index < length) {
873        index++;
874        res[index] = computeFrame(res[index-1], syzM_i_unsorted, syzHead);
875    }
876    while (!idIs0(res[index]) && index < length) {
877#if 1
878        computeLiftings(res, index);
879        sortPolysTails(res, index);
880#endif   // LIFT
881        index++;
882        res[index] = computeFrame(res[index-1], syzM_i_sorted, syzHead);
883    }
884    if (index < length) {
885        res = (resolvente)omReallocSize(res, (length+1)*sizeof(ideal),
886            (index+1)*sizeof(ideal));
887    }
888    return index;
889}
890
891static void sortPolys(const resolvente res, const int length)
892{
893    const ring r = currRing;
894    for (int i = length; i > 0; i--) {
895        for (int j = res[i]->ncols-1; j >= 0; j--) {
896            res[i]->m[j] = p_SortAdd(res[i]->m[j], r, TRUE);
897        }
898    }
899}
900
901syStrategy syFrank(const ideal arg, int &length, const char *method)
902{
903    syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
904    resolvente res = (resolvente)omAlloc0((length+1)*sizeof(ideal));
905    res[0] = id_Copy(arg, currRing);
906    syzHeadFunction *syzHead;
907    if (strcmp(method, "frame") == 0 || strcmp(method, "linear strand") == 0) {
908        syzHead = syzHeadFrame;
909    }
910    else {
911        syzHead = syzHeadExtFrame;
912    }
913    length = computeResolution(res, length, syzHead);
914    sortPolys(res, length);
915    result->fullres = res;
916    result->length = length+1;
917    return result;
918}
919
Note: See TracBrowser for help on using the repository browser.