source: git/kernel/GBEngine/syz4.cc @ 2204ea

spielwiese
Last change on this file since 2204ea was 2204ea, checked in by Andreas Steenpass <steenpass@…>, 8 years ago
fix: check for NULL pointer in insert_first_term()
  • Property mode set to 100644
File size: 17.4 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
17#ifdef __GNUC__
18#define likely(X)   (__builtin_expect(X, 1))
19#define unlikely(X) (__builtin_expect(X, 0))
20#else
21#define likely(X)   (X)
22#define unlikely(X) (X)
23#endif
24
25static inline void update_variables(std::vector<bool> &variables,
26    const ideal L)
27{
28    const ring R = currRing;
29    const int l = IDELEMS(L)-1;
30    int k;
31    for (int j = R->N; j > 0; j--) {
32        if (variables[j-1]) {
33            for (k = l; k >= 0; k--) {
34                if (p_GetExp(L->m[k], j, R) > 0) {
35                    break;
36                }
37            }
38            if (k < 0) {   // no break
39                variables[j-1] = false;
40            }
41        }
42    }
43}
44
45static inline bool check_variables(const std::vector<bool> &variables,
46    const poly m)
47{
48    const ring R = currRing;
49    for (int j = R->N; j > 0; j--) {
50        if (variables[j-1] && p_GetExp(m, j, R) > 0) {
51            return true;
52        }
53    }
54    return false;
55}
56
57typedef struct {
58    poly lt;
59    unsigned long sev;
60    unsigned int comp;
61} lt_struct;
62
63typedef std::vector<lt_struct> lts_vector;
64typedef std::map<long, lts_vector> lts_hash;
65
66static void initialize_lts_hash(lts_hash &C, const ideal L)
67{
68    const ring R = currRing;
69    const unsigned int n_elems = IDELEMS(L);
70    for (unsigned int k = 0; k < n_elems; k++) {
71        const poly a = L->m[k];
72        C[p_GetComp(a, R)].push_back({a, p_GetShortExpVector(a, R), k});
73    }
74}
75
76#define delete_lts_hash(C) C->clear()
77
78bool is_divisible(const lts_hash *C, const poly p)
79{
80    const ring R = currRing;
81    lts_hash::const_iterator itr = C->find(p_GetComp(p, R));
82    if (itr == C->end()) {
83        return false;
84    }
85    lts_vector::const_iterator v_current = itr->second.begin();
86    lts_vector::const_iterator v_finish  = itr->second.end();
87    const unsigned long not_sev = ~p_GetShortExpVector(p, R);
88    for ( ; v_current != v_finish; ++v_current) {
89        if (p_LmShortDivisibleByNoComp(v_current->lt, v_current->sev,
90                p, not_sev, R)) {
91            return true;
92        }
93    }
94    return false;
95}
96
97poly FindReducer(const poly multiplier, const poly t, const poly syzterm,
98    const lts_hash *syz_checker, const lts_hash *m_div)
99{
100  const ring r = currRing;
101  lts_hash::const_iterator m_itr = m_div->find(p_GetComp(t, currRing));
102  if (m_itr == m_div->end()) {
103    return NULL;
104  }
105  lts_vector::const_iterator m_current = (m_itr->second).begin();
106  lts_vector::const_iterator m_finish  = (m_itr->second).end();
107  if (m_current == m_finish) {
108    return NULL;
109  }
110  const poly q = p_New(r);
111  pNext(q) = NULL;
112  const unsigned long m_not_sev = ~p_GetShortExpVector(multiplier, t, r);
113  for( ; m_current != m_finish; ++m_current) {
114    if (m_current->sev & m_not_sev) {
115        continue;
116    }
117    p_MemSum_LengthGeneral(q->exp, multiplier->exp, t->exp, r->ExpL_Size);
118    if (unlikely(!(_p_LmDivisibleByNoComp(m_current->lt, q, r)))) {
119        continue;
120    }
121    const poly p = m_current->lt;
122    const int k  = m_current->comp;
123    p_MemAdd_NegWeightAdjust(q, r);
124    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
125    p_SetComp(q, k + 1, r);
126    p_Setm(q, r);
127    // cannot allow something like: a*gen(i) - a*gen(i)
128    if (syzterm != NULL && (k == p_GetComp(syzterm, r) - 1)
129        && p_ExpVectorEqual(syzterm, q, r)) {
130      continue;
131    }
132    if (is_divisible(syz_checker, q)) {
133      continue;
134    }
135    number n = n_Mult(p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
136    p_SetCoeff0(q, n_InpNeg(n, r), r);
137    return q;
138  }
139  p_LmFree(q, r);
140  return NULL;
141}
142
143static poly TraverseTail_test(poly multiplier, const int tail,
144   const ideal previous_module, const std::vector<bool> &variables,
145   const lts_hash *m_div, const lts_hash *m_checker);
146
147static inline poly ReduceTerm_test(poly multiplier, poly term4reduction,
148    poly syztermCheck, const ideal previous_module,
149    const std::vector<bool> &variables, const lts_hash *m_div,
150    const lts_hash *m_checker)
151{
152  const ring r = currRing;
153  poly s = FindReducer(multiplier, term4reduction, syztermCheck, m_checker,
154        m_div);
155  if( s == NULL )
156  {
157    return NULL;
158  }
159  const int c = p_GetComp(s, r) - 1;
160  const poly t
161      = TraverseTail_test(s, c, previous_module, variables, m_div, m_checker);
162  if( t != NULL )
163    s = p_Add_q(s, t, r);
164  return s;
165}
166
167static poly ComputeImage_test(poly multiplier, const int t,
168    const ideal previous_module, const std::vector<bool> &variables,
169    const lts_hash *m_div, const lts_hash *m_checker)
170{
171  const poly tail = previous_module->m[t]->next;
172  if(tail != NULL)
173  {
174    if (!check_variables(variables, multiplier))
175    {
176      return NULL;
177    }
178    sBucket_pt sum = sBucketCreate(currRing);
179    for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
180    {
181      const poly rt = ReduceTerm_test(multiplier, p, NULL, previous_module,
182          variables, m_div, m_checker);
183      sBucket_Add_p(sum, rt, pLength(rt));
184    }
185    poly s;
186    int l;
187    sBucketClearAdd(sum, &s, &l);
188    sBucketDestroy(&sum);
189    return s;
190  }
191  return NULL;
192}
193
194#define CACHE 1
195
196#if CACHE
197bool my_p_LmCmp_test (poly a, poly b, const ring r)
198{
199  return p_LmCmp(a, b, r) == -1;
200}
201
202struct CCacheCompare_test
203{
204  const ring& m_ring_test;
205  CCacheCompare_test(): m_ring_test(currRing) {}
206  CCacheCompare_test(const ring& r): m_ring_test(r) {}
207  CCacheCompare_test(const CCacheCompare_test& lhs):
208    m_ring_test(lhs.m_ring_test) {}
209  CCacheCompare_test& operator=(const CCacheCompare_test& lhs)
210  {
211    return (const_cast<CCacheCompare_test&>(lhs));
212  }
213  inline bool operator() (const poly& l, const poly& r)
214    const
215  {
216    return my_p_LmCmp_test(l, r, m_ring_test);
217  }
218};
219
220typedef std::map<poly, poly, CCacheCompare_test>
221  TP2PCache_test;
222typedef std::map<int, TP2PCache_test> TCache_test;
223
224static TCache_test m_cache_test;
225
226static FORCE_INLINE poly myp_Head_test(const poly p, const bool bIgnoreCoeff,
227  const ring r)
228{
229  p_LmCheckPolyRing1(p, r);
230  poly np;
231  omTypeAllocBin(poly, np, r->PolyBin);
232  p_SetRingOfLm(np, r);
233  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
234  pNext(np) = NULL;
235  pSetCoeff0(np, (bIgnoreCoeff)? NULL : n_Copy(pGetCoeff(p), r->cf));
236  p_LmCheckPolyRing1(np, r);
237  return np;
238}
239
240static void delete_cache()
241{
242    for (TCache_test::iterator it = m_cache_test.begin();
243        it != m_cache_test.end(); it++) {
244        TP2PCache_test& T = it->second;
245        for (TP2PCache_test::iterator vit = T.begin(); vit != T.end(); vit++) {
246            p_Delete((&(vit->second)), currRing);
247            p_Delete(const_cast<poly*>(&(vit->first)), currRing);
248        }
249        T.erase(T.begin(), T.end());
250    }
251    m_cache_test.erase(m_cache_test.begin(), m_cache_test.end());
252}
253#endif   // CACHE
254
255static poly TraverseTail_test(poly multiplier, const int tail,
256    const ideal previous_module, const std::vector<bool> &variables,
257    const lts_hash *m_div, const lts_hash *m_checker)
258{
259  const ring& r = currRing;
260#if CACHE
261  TCache_test::iterator top_itr = m_cache_test.find(tail);
262  if ( top_itr != m_cache_test.end() )
263  {
264     TP2PCache_test& T = top_itr->second;
265     TP2PCache_test::iterator itr = T.find(multiplier);
266     if( itr != T.end() )
267     {
268       if( itr->second == NULL )
269         return (NULL);
270       poly p = p_Copy(itr->second, r);
271       if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) )
272       {
273         number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r);
274         p = p_Mult_nn(p, n, r);
275         n_Delete(&n, r);
276       }
277       return p;
278     }
279     const poly p = ComputeImage_test(multiplier, tail, previous_module,
280         variables, m_div, m_checker);
281     itr = T.find(multiplier);
282     if( itr == T.end() )
283     {
284       T.insert(TP2PCache_test::value_type(myp_Head_test(multiplier, (p==NULL),
285         r), p) );
286       return p_Copy(p, r);
287     }
288     return p;
289  }
290#endif   // CACHE
291  const poly p = ComputeImage_test(multiplier, tail, previous_module,
292      variables, m_div, m_checker);
293#if CACHE
294  top_itr = m_cache_test.find(tail);
295  if ( top_itr != m_cache_test.end() )
296  {
297    TP2PCache_test& T = top_itr->second;
298    TP2PCache_test::iterator itr = T.find(multiplier);
299    if( itr == T.end() )
300    {
301      T.insert(TP2PCache_test::value_type(myp_Head_test(multiplier, (p==NULL),
302          r), p));
303      return p_Copy(p, r);
304    }
305    return p;
306  }
307  CCacheCompare_test o(r);
308  TP2PCache_test T(o);
309  T.insert(TP2PCache_test::value_type(myp_Head_test(multiplier, (p==NULL), r),
310    p));
311  m_cache_test.insert( TCache_test::value_type(tail, T) );
312  return p_Copy(p, r);
313#else
314  return p;
315#endif   // CACHE
316}
317
318static poly lift_ext_LT(const poly a, const ideal previous_module,
319    const std::vector<bool> &variables, const lts_hash *m_div,
320    const lts_hash *m_checker)
321{
322  const ring R = currRing;
323  poly t1 = TraverseTail_test(a, p_GetComp(a, R)-1,
324      previous_module, variables, m_div, m_checker);
325  poly t2 = TraverseTail_test(a->next, p_GetComp(a->next, R)-1,
326      previous_module, variables, m_div, m_checker);
327  t1 = p_Add_q(t1, t2, R);
328  return t1;
329}
330
331/*****************************************************************************/
332
333typedef poly syzHeadFunction(ideal, int, int);
334
335static poly syzHeadFrame(const ideal G, const int i, const int j)
336{
337    const ring r = currRing;
338    const poly f_i = G->m[i];
339    const poly f_j = G->m[j];
340    poly head = p_Init(r);
341    pSetCoeff0(head, n_Init(1, r->cf));
342    long exp_i, exp_j, lcm;
343    for (int k = (int)r->N; k > 0; k--) {
344        exp_i = p_GetExp(f_i, k, r);
345        exp_j = p_GetExp(f_j, k, r);
346        lcm = si_max(exp_i, exp_j);
347        p_SetExp(head, k, lcm-exp_i, r);
348    }
349    p_SetComp(head, i+1, r);
350    p_Setm(head, r);
351    return head;
352}
353
354static poly syzHeadExtFrame(const ideal G, const int i, const int j)
355{
356    const ring r = currRing;
357    const poly f_i = G->m[i];
358    const poly f_j = G->m[j];
359    poly head = p_Init(r);
360    pSetCoeff0(head, n_Init(1, r->cf));
361    poly head_ext = p_Init(r);
362    pSetCoeff0(head_ext, n_InpNeg(n_Div(pGetCoeff(f_j), pGetCoeff(f_i), r->cf),
363        r->cf));
364    long exp_i, exp_j, lcm;
365    for (int k = (int)r->N; k > 0; k--) {
366        exp_i = p_GetExp(f_i, k, r);
367        exp_j = p_GetExp(f_j, k, r);
368        lcm = si_max(exp_i, exp_j);
369        p_SetExp(head, k, lcm-exp_i, r);
370        p_SetExp(head_ext, k, lcm-exp_j, r);
371    }
372    p_SetComp(head, i+1, r);
373    p_Setm(head, r);
374    p_SetComp(head_ext, j+1, r);
375    p_Setm(head_ext, r);
376    head->next = head_ext;
377    return head;
378}
379
380typedef ideal syzM_i_Function(ideal, int, syzHeadFunction);
381
382static ideal syzM_i_unsorted(const ideal G, const int i,
383    const syzHeadFunction *syzHead)
384{
385    ideal M_i = NULL;
386    int comp = pGetComp(G->m[i]);
387    int ncols = 0;
388    for (int j = i-1; j >= 0; j--) {
389        if (pGetComp(G->m[j]) == comp) ncols++;
390    }
391    if (ncols > 0) {
392        M_i = idInit(ncols, G->ncols);
393        int k = ncols-1;
394        for (int j = i-1; j >= 0; j--) {
395            if (pGetComp(G->m[j]) == comp) {
396                M_i->m[k] = syzHead(G, i, j);
397                k--;
398            }
399        }
400        id_DelDiv(M_i, currRing);
401        idSkipZeroes(M_i);
402    }
403    return M_i;
404}
405
406static ideal syzM_i_sorted(const ideal G, const int i,
407    const syzHeadFunction *syzHead)
408{
409    ideal M_i = NULL;
410    int comp = pGetComp(G->m[i]);
411    int index = i-1;
412    while (pGetComp(G->m[index]) == comp) index--;
413    index++;
414    int ncols = i-index;
415    if (ncols > 0) {
416        M_i = idInit(ncols, G->ncols);
417        for (int j = ncols-1; j >= 0; j--) {
418            M_i->m[j] = syzHead(G, i, j+index);
419        }
420        id_DelDiv(M_i, currRing);
421        idSkipZeroes(M_i);
422    }
423    return M_i;
424}
425
426static ideal idConcat(const ideal* M, const int size, const int rank)
427{
428    int ncols = 0;
429    for (int i = size-1; i >= 0; i--) {
430        if (M[i] != NULL) {
431            ncols += M[i]->ncols;
432        }
433    }
434    if (ncols == 0) return idInit(1, rank);
435    ideal result = idInit(ncols, rank);
436    int k = ncols-1;
437    for (int i = size-1; i >= 0; i--) {
438        if (M[i] != NULL) {
439            for (int j = M[i]->ncols-1; j >= 0; j--) {
440                result->m[k] = M[i]->m[j];
441                k--;
442            }
443        }
444    }
445    return result;
446}
447
448#define SORT_MI 1
449
450#if SORT_MI
451static int compare_Mi(const void* a, const void *b)
452{
453    const ring r = currRing;
454    poly p_a = *((poly *)a);
455    poly p_b = *((poly *)b);
456    int cmp;
457    int deg_a = p_Deg(p_a, r);
458    int deg_b = p_Deg(p_b, r);
459    cmp = (deg_a > deg_b) - (deg_a < deg_b);
460    if (cmp != 0) {
461         return cmp;
462    }
463    int comp_a = p_GetComp(p_a, r);
464    int comp_b = p_GetComp(p_b, r);
465    cmp = (comp_a > comp_b) - (comp_a < comp_b);
466    if (cmp != 0) {
467         return cmp;
468    }
469    int exp_a[r->N+1];
470    int exp_b[r->N+1];
471    p_GetExpV(p_a, exp_a, r);
472    p_GetExpV(p_b, exp_b, r);
473    for (int i = r->N; i > 0; i--) {
474        cmp = (exp_a[i] > exp_b[i]) - (exp_a[i] < exp_b[i]);
475        if (cmp != 0) {
476            return cmp;
477        }
478    }
479    return 0;
480}
481#endif   // SORT_MI
482
483static ideal computeFrame(const ideal G, const syzM_i_Function syzM_i,
484    const syzHeadFunction *syzHead)
485{
486    ideal* M = (ideal *)omalloc((G->ncols-1)*sizeof(ideal));
487    for (int i = G->ncols-2; i >= 0; i--) {
488        M[i] = syzM_i(G, i+1, syzHead);
489    }
490    ideal frame = idConcat(M, G->ncols-1, G->ncols);
491    for (int i = G->ncols-2; i >= 0; i--) {
492        if (M[i] != NULL) {
493            omFreeSize(M[i]->m, IDELEMS(M[i])*sizeof(poly));
494            omFreeBin(M[i], sip_sideal_bin);
495        }
496    }
497    omFree(M);
498#if SORT_MI
499    qsort(frame->m, IDELEMS(frame), sizeof(poly), compare_Mi);
500#endif
501    return frame;
502}
503
504static void computeLiftings(const resolvente res, const int index,
505    std::vector<bool> &variables, lts_hash *&hash_previous_module)
506{
507    update_variables(variables, res[index-1]);
508    lts_hash *hash_current_module = new lts_hash();
509    initialize_lts_hash(*hash_current_module, res[index]);
510    for (int j = res[index]->ncols-1; j >= 0; j--) {
511        res[index]->m[j]->next->next = lift_ext_LT(res[index]->m[j],
512            res[index-1], variables, hash_previous_module,
513            hash_current_module);
514    }
515    delete_lts_hash(hash_previous_module);
516    delete(hash_previous_module);
517    hash_previous_module = hash_current_module;
518#if CACHE
519    delete_cache();
520#endif   // CACHE
521}
522
523static int computeResolution(resolvente &res, const int length,
524    const syzHeadFunction *syzHead)
525{
526    int max_index = length-1;
527    int index = 0;
528    if (!idIs0(res[index]) && index < max_index) {
529        index++;
530        res[index] = computeFrame(res[index-1], syzM_i_unsorted, syzHead);
531        std::vector<bool> variables;
532        variables.resize(currRing->N, true);
533        lts_hash *hash_previous_module = new lts_hash();
534        initialize_lts_hash(*hash_previous_module, res[index-1]);
535        while (!idIs0(res[index])) {
536#if 1
537            computeLiftings(res, index, variables, hash_previous_module);
538#endif   // LIFT
539            if (index < max_index) {
540                index++;
541                res[index] = computeFrame(res[index-1], syzM_i_sorted,
542                    syzHead);
543            }
544            else {
545                break;
546            }
547        }
548        delete_lts_hash(hash_previous_module);
549        delete(hash_previous_module);
550        variables.clear();
551    }
552    max_index = index+1;
553    if (max_index < length) {
554        res = (resolvente)omReallocSize(res, (length+1)*sizeof(ideal),
555            (max_index+1)*sizeof(ideal));
556    }
557    return max_index;
558}
559
560#define insert_first_term(r, p, q, R)                             \
561do                                                                \
562{                                                                 \
563    p = r;                                                        \
564    q = p->next;                                                  \
565    if (q != NULL && p_LmCmp(p, q, R) != 1) {                     \
566        while (q->next != NULL && p_LmCmp(p, q->next, R) == -1) { \
567            pIter(q);                                             \
568        }                                                         \
569        r = p->next;                                              \
570        p->next = q->next;                                        \
571        q->next = p;                                              \
572    }                                                             \
573}                                                                 \
574while (0)
575
576static void insert_ext_induced_LTs(const resolvente res, const int length)
577{
578    const ring R = currRing;
579    poly p, q;
580    for (int i = length-2; i > 0; i--) {
581        for (int j = res[i]->ncols-1; j >= 0; j--) {
582            insert_first_term(res[i]->m[j]->next, p, q, R);
583            insert_first_term(res[i]->m[j], p, q, R);
584        }
585    }
586}
587
588syStrategy syFrank(const ideal arg, int &length, const char *method)
589{
590    syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
591    resolvente res = (resolvente)omAlloc0((length+1)*sizeof(ideal));
592    res[0] = id_Copy(arg, currRing);
593    syzHeadFunction *syzHead;
594    if (strcmp(method, "frame") == 0 || strcmp(method, "linear strand") == 0) {
595        syzHead = syzHeadFrame;
596    }
597    else {
598        syzHead = syzHeadExtFrame;
599    }
600    length = computeResolution(res, length, syzHead);
601    insert_ext_induced_LTs(res, length);
602    result->fullres = res;
603    result->length = length;
604    return result;
605}
606
Note: See TracBrowser for help on using the repository browser.