source: git/kernel/GBEngine/syz4.cc @ 576ba7

spielwiese
Last change on this file since 576ba7 was 576ba7, checked in by Andreas Steenpass <steenpass@…>, 8 years ago
chg: get rid of _p_LmDivisibleByNoComp for a | b*c
  • Property mode set to 100644
File size: 16.7 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 TraverseNF_test(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  const int r = p_GetComp(a, R) - 1;
324  poly t = TraverseTail_test(a, r, previous_module, variables, m_div,
325      m_checker);
326  if (check_variables(variables, a)) {
327    t = p_Add_q(t, ReduceTerm_test(a, previous_module->m[r], a,
328        previous_module, variables, m_div, m_checker), R);
329  }
330  return t;
331}
332
333/*****************************************************************************/
334
335typedef poly syzHeadFunction(ideal, int, int);
336
337static poly syzHeadFrame(const ideal G, const int i, const int j)
338{
339    const ring r = currRing;
340    const poly f_i = G->m[i];
341    const poly f_j = G->m[j];
342    poly head = p_Init(r);
343    pSetCoeff0(head, n_Init(1, r->cf));
344    long exp_i, exp_j, lcm;
345    for (int k = (int)r->N; k > 0; k--) {
346        exp_i = p_GetExp(f_i, k, r);
347        exp_j = p_GetExp(f_j, k, r);
348        lcm = si_max(exp_i, exp_j);
349        p_SetExp(head, k, lcm-exp_i, r);
350    }
351    p_SetComp(head, i+1, r);
352    p_Setm(head, r);
353    return head;
354}
355
356static poly syzHeadExtFrame(const ideal G, const int i, const int j)
357{
358    const ring r = currRing;
359    const poly f_i = G->m[i];
360    const poly f_j = G->m[j];
361    poly head = p_Init(r);
362    pSetCoeff0(head, n_Init(1, r->cf));
363    poly head_ext = p_Init(r);
364    pSetCoeff0(head_ext, n_InpNeg(n_Div(pGetCoeff(f_j), pGetCoeff(f_i), r->cf),
365        r->cf));
366    long exp_i, exp_j, lcm;
367    for (int k = (int)r->N; k > 0; k--) {
368        exp_i = p_GetExp(f_i, k, r);
369        exp_j = p_GetExp(f_j, k, r);
370        lcm = si_max(exp_i, exp_j);
371        p_SetExp(head, k, lcm-exp_i, r);
372        p_SetExp(head_ext, k, lcm-exp_j, r);
373    }
374    p_SetComp(head, i+1, r);
375    p_Setm(head, r);
376    p_SetComp(head_ext, j+1, r);
377    p_Setm(head_ext, r);
378    head->next = head_ext;
379    return head;
380}
381
382typedef ideal syzM_i_Function(ideal, int, syzHeadFunction);
383
384static ideal syzM_i_unsorted(const ideal G, const int i,
385    const syzHeadFunction *syzHead)
386{
387    ideal M_i = NULL;
388    int comp = pGetComp(G->m[i]);
389    int ncols = 0;
390    for (int j = i-1; j >= 0; j--) {
391        if (pGetComp(G->m[j]) == comp) ncols++;
392    }
393    if (ncols > 0) {
394        M_i = idInit(ncols, G->ncols);
395        int k = ncols-1;
396        for (int j = i-1; j >= 0; j--) {
397            if (pGetComp(G->m[j]) == comp) {
398                M_i->m[k] = syzHead(G, i, j);
399                k--;
400            }
401        }
402        id_DelDiv(M_i, currRing);
403        idSkipZeroes(M_i);
404    }
405    return M_i;
406}
407
408static ideal syzM_i_sorted(const ideal G, const int i,
409    const syzHeadFunction *syzHead)
410{
411    ideal M_i = NULL;
412    int comp = pGetComp(G->m[i]);
413    int index = i-1;
414    while (pGetComp(G->m[index]) == comp) index--;
415    index++;
416    int ncols = i-index;
417    if (ncols > 0) {
418        M_i = idInit(ncols, G->ncols);
419        for (int j = ncols-1; j >= 0; j--) {
420            M_i->m[j] = syzHead(G, i, j+index);
421        }
422        id_DelDiv(M_i, currRing);
423        idSkipZeroes(M_i);
424    }
425    return M_i;
426}
427
428static ideal idConcat(const ideal* M, const int size, const int rank)
429{
430    int ncols = 0;
431    for (int i = size-1; i >= 0; i--) {
432        if (M[i] != NULL) {
433            ncols += M[i]->ncols;
434        }
435    }
436    if (ncols == 0) return idInit(1, rank);
437    ideal result = idInit(ncols, rank);
438    int k = ncols-1;
439    for (int i = size-1; i >= 0; i--) {
440        if (M[i] != NULL) {
441            for (int j = M[i]->ncols-1; j >= 0; j--) {
442                result->m[k] = M[i]->m[j];
443                k--;
444            }
445        }
446    }
447    return result;
448}
449
450#define SORT_MI 1
451
452#if SORT_MI
453static int compare_Mi(const void* a, const void *b)
454{
455    const ring r = currRing;
456    poly p_a = *((poly *)a);
457    poly p_b = *((poly *)b);
458    int cmp;
459    int deg_a = p_Deg(p_a, r);
460    int deg_b = p_Deg(p_b, r);
461    cmp = (deg_a > deg_b) - (deg_a < deg_b);
462    if (cmp != 0) {
463         return cmp;
464    }
465    int comp_a = p_GetComp(p_a, r);
466    int comp_b = p_GetComp(p_b, r);
467    cmp = (comp_a > comp_b) - (comp_a < comp_b);
468    if (cmp != 0) {
469         return cmp;
470    }
471    int exp_a[r->N+1];
472    int exp_b[r->N+1];
473    p_GetExpV(p_a, exp_a, r);
474    p_GetExpV(p_b, exp_b, r);
475    for (int i = r->N; i > 0; i--) {
476        cmp = (exp_a[i] > exp_b[i]) - (exp_a[i] < exp_b[i]);
477        if (cmp != 0) {
478            return cmp;
479        }
480    }
481    return 0;
482}
483#endif   // SORT_MI
484
485static ideal computeFrame(const ideal G, const syzM_i_Function syzM_i,
486    const syzHeadFunction *syzHead)
487{
488    ideal* M = (ideal *)omalloc((G->ncols-1)*sizeof(ideal));
489    for (int i = G->ncols-2; i >= 0; i--) {
490        M[i] = syzM_i(G, i+1, syzHead);
491    }
492    ideal frame = idConcat(M, G->ncols-1, G->ncols);
493    for (int i = G->ncols-2; i >= 0; i--) {
494        if (M[i] != NULL) {
495            omFreeSize(M[i]->m, IDELEMS(M[i])*sizeof(poly));
496            omFreeBin(M[i], sip_sideal_bin);
497        }
498    }
499    omFree(M);
500#if SORT_MI
501    qsort(frame->m, IDELEMS(frame), sizeof(poly), compare_Mi);
502#endif
503    return frame;
504}
505
506static void computeLiftings(const resolvente res, const int index,
507    std::vector<bool> &variables, lts_hash *&hash_previous_module)
508{
509    update_variables(variables, res[index-1]);
510    lts_hash *hash_current_module = new lts_hash();
511    initialize_lts_hash(*hash_current_module, res[index]);
512    poly p;
513    for (int j = res[index]->ncols-1; j >= 0; j--) {
514        p = res[index]->m[j];
515        pDelete(&res[index]->m[j]->next);
516        p->next = NULL;
517        res[index]->m[j]->next = TraverseNF_test(p, res[index-1], variables,
518            hash_previous_module, hash_current_module);
519    }
520    delete_lts_hash(hash_previous_module);
521    delete(hash_previous_module);
522    hash_previous_module = hash_current_module;
523#if CACHE
524    delete_cache();
525#endif   // CACHE
526}
527
528static int computeResolution(resolvente &res, const int length,
529    const syzHeadFunction *syzHead)
530{
531    int max_index = length-1;
532    int index = 0;
533    if (!idIs0(res[index]) && index < max_index) {
534        index++;
535        res[index] = computeFrame(res[index-1], syzM_i_unsorted, syzHead);
536        std::vector<bool> variables;
537        variables.resize(currRing->N, true);
538        lts_hash *hash_previous_module = new lts_hash();
539        initialize_lts_hash(*hash_previous_module, res[index-1]);
540        while (!idIs0(res[index])) {
541#if 1
542            computeLiftings(res, index, variables, hash_previous_module);
543#endif   // LIFT
544            if (index < max_index) {
545                index++;
546                res[index] = computeFrame(res[index-1], syzM_i_sorted,
547                    syzHead);
548            }
549            else {
550                break;
551            }
552        }
553        delete_lts_hash(hash_previous_module);
554        delete(hash_previous_module);
555        variables.clear();
556    }
557    max_index = index+1;
558    if (max_index < length) {
559        res = (resolvente)omReallocSize(res, (length+1)*sizeof(ideal),
560            (max_index+1)*sizeof(ideal));
561    }
562    return max_index;
563}
564
565static void insert_induced_LTs(const resolvente res, const int length)
566{
567    const ring r = currRing;
568    poly p, q;
569    for (int i = length-2; i > 0; i--) {
570        for (int j = res[i]->ncols-1; j >= 0; j--) {
571            p = res[i]->m[j];
572            q = res[i]->m[j]->next;
573            if (p_LmCmp(p, q, r) == 1) continue;
574            while (q->next != NULL && p_LmCmp(p, q->next, r) == -1) pIter(q);
575            res[i]->m[j] = p->next;
576            p->next = q->next;
577            q->next = p;
578        }
579    }
580}
581
582syStrategy syFrank(const ideal arg, int &length, const char *method)
583{
584    syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
585    resolvente res = (resolvente)omAlloc0((length+1)*sizeof(ideal));
586    res[0] = id_Copy(arg, currRing);
587    syzHeadFunction *syzHead;
588    if (strcmp(method, "frame") == 0 || strcmp(method, "linear strand") == 0) {
589        syzHead = syzHeadFrame;
590    }
591    else {
592        syzHead = syzHeadExtFrame;
593    }
594    length = computeResolution(res, length, syzHead);
595    insert_induced_LTs(res, length);
596    result->fullres = res;
597    result->length = length;
598    return result;
599}
600
Note: See TracBrowser for help on using the repository browser.