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

fieker-DuValspielwiese
Last change on this file since efcad1 was efcad1, checked in by Andreas Steenpass <steenpass@…>, 8 years ago
chg: simplify caching code
  • Property mode set to 100644
File size: 15.0 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
78poly FindReducer(const poly multiplier, const poly t, const lts_hash *m_div)
79{
80  const ring r = currRing;
81  lts_hash::const_iterator m_itr = m_div->find(p_GetComp(t, currRing));
82  if (m_itr == m_div->end()) {
83    return NULL;
84  }
85  lts_vector::const_iterator m_current = (m_itr->second).begin();
86  lts_vector::const_iterator m_finish  = (m_itr->second).end();
87  const poly q = p_New(r);
88  pNext(q) = NULL;
89  p_MemSum_LengthGeneral(q->exp, multiplier->exp, t->exp, r->ExpL_Size);
90  const unsigned long m_not_sev = ~p_GetShortExpVector(q, r);
91  for( ; m_current != m_finish; ++m_current) {
92    if (m_current->sev & m_not_sev
93        || unlikely(!(_p_LmDivisibleByNoComp(m_current->lt, q, r)))) {
94        continue;
95    }
96    const poly p = m_current->lt;
97    const int k  = m_current->comp;
98    p_MemAdd_NegWeightAdjust(q, r);
99    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
100    p_SetComp(q, k + 1, r);
101    p_Setm(q, r);
102    number n = n_Mult(p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
103    p_SetCoeff0(q, n_InpNeg(n, r), r);
104    return q;
105  }
106  p_LmFree(q, r);
107  return NULL;
108}
109
110static poly TraverseTail_test(poly multiplier, const int tail,
111   const ideal previous_module, const std::vector<bool> &variables,
112   const lts_hash *m_div);
113
114static inline poly ReduceTerm_test(poly multiplier, poly term4reduction,
115    const ideal previous_module, const std::vector<bool> &variables,
116    const lts_hash *m_div)
117{
118  const ring r = currRing;
119  poly s = FindReducer(multiplier, term4reduction, m_div);
120  if( s == NULL )
121  {
122    return NULL;
123  }
124  const int c = p_GetComp(s, r) - 1;
125  const poly t
126      = TraverseTail_test(s, c, previous_module, variables, m_div);
127  if( t != NULL )
128    s = p_Add_q(s, t, r);
129  return s;
130}
131
132static poly ComputeImage_test(poly multiplier, const int t,
133    const ideal previous_module, const std::vector<bool> &variables,
134    const lts_hash *m_div)
135{
136  const poly tail = previous_module->m[t]->next;
137  if(tail != NULL)
138  {
139    if (!check_variables(variables, multiplier))
140    {
141      return NULL;
142    }
143    sBucket_pt sum = sBucketCreate(currRing);
144    for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
145    {
146      const poly rt = ReduceTerm_test(multiplier, p, previous_module,
147          variables, m_div);
148      sBucket_Add_p(sum, rt, pLength(rt));
149    }
150    poly s;
151    int l;
152    sBucketClearAdd(sum, &s, &l);
153    sBucketDestroy(&sum);
154    return s;
155  }
156  return NULL;
157}
158
159#define CACHE 1
160
161#if CACHE
162struct CCacheCompare_test
163{
164  inline bool operator() (const poly& l, const poly& r)
165    const
166  {
167    return (p_LmCmp(l, r, currRing) == -1);
168  }
169};
170
171typedef std::map<poly, poly, CCacheCompare_test>
172  TP2PCache_test;
173typedef std::map<int, TP2PCache_test> TCache_test;
174
175static TCache_test m_cache_test;
176
177// note: we don't need to keep the coeffs of those terms which are lifted to 0
178
179static void delete_cache()
180{
181    for (TCache_test::iterator it = m_cache_test.begin();
182        it != m_cache_test.end(); it++) {
183        TP2PCache_test& T = it->second;
184        for (TP2PCache_test::iterator vit = T.begin(); vit != T.end(); vit++) {
185            p_Delete((&(vit->second)), currRing);
186            p_Delete(const_cast<poly*>(&(vit->first)), currRing);
187        }
188        T.clear();
189    }
190    m_cache_test.clear();
191}
192#endif   // CACHE
193
194static poly TraverseTail_test(poly multiplier, const int tail,
195    const ideal previous_module, const std::vector<bool> &variables,
196    const lts_hash *m_div)
197{
198  const ring& r = currRing;
199#if CACHE
200  TCache_test::iterator top_itr = m_cache_test.find(tail);
201  if ( top_itr != m_cache_test.end() )
202  {
203     TP2PCache_test& T = top_itr->second;
204     TP2PCache_test::iterator itr = T.find(multiplier);
205     if( itr != T.end() )
206     {
207       if( itr->second == NULL )
208         return (NULL);
209       poly p = p_Copy(itr->second, r);
210       if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) )
211       {
212         number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r);
213         p = p_Mult_nn(p, n, r);
214         n_Delete(&n, r);
215       }
216       return p;
217     }
218     const poly p = ComputeImage_test(multiplier, tail, previous_module,
219         variables, m_div);
220     itr = T.find(multiplier);
221     if( itr == T.end() )
222     {
223       T.insert(TP2PCache_test::value_type(p_Head(multiplier,
224         r), p) );
225       return p_Copy(p, r);
226     }
227     return p;
228  }
229#endif   // CACHE
230  const poly p = ComputeImage_test(multiplier, tail, previous_module,
231      variables, m_div);
232#if CACHE
233  top_itr = m_cache_test.find(tail);
234  if ( top_itr != m_cache_test.end() )
235  {
236    TP2PCache_test& T = top_itr->second;
237    TP2PCache_test::iterator itr = T.find(multiplier);
238    if( itr == T.end() )
239    {
240      T.insert(TP2PCache_test::value_type(p_Head(multiplier,
241          r), p));
242      return p_Copy(p, r);
243    }
244    return p;
245  }
246  TP2PCache_test T;
247  T.insert(TP2PCache_test::value_type(p_Head(multiplier, r),
248    p));
249  m_cache_test.insert( TCache_test::value_type(tail, T) );
250  return p_Copy(p, r);
251#else
252  return p;
253#endif   // CACHE
254}
255
256static poly lift_ext_LT(const poly a, const ideal previous_module,
257    const std::vector<bool> &variables, const lts_hash *m_div)
258{
259  const ring R = currRing;
260  poly t1 = ComputeImage_test(a, p_GetComp(a, R)-1,
261      previous_module, variables, m_div);
262  poly t2 = TraverseTail_test(a->next, p_GetComp(a->next, R)-1,
263      previous_module, variables, m_div);
264  t1 = p_Add_q(t1, t2, R);
265  return t1;
266}
267
268/*****************************************************************************/
269
270typedef poly syzHeadFunction(ideal, int, int);
271
272static poly syzHeadFrame(const ideal G, const int i, const int j)
273{
274    const ring r = currRing;
275    const poly f_i = G->m[i];
276    const poly f_j = G->m[j];
277    poly head = p_Init(r);
278    pSetCoeff0(head, n_Init(1, r->cf));
279    long exp_i, exp_j, lcm;
280    for (int k = (int)r->N; k > 0; k--) {
281        exp_i = p_GetExp(f_i, k, r);
282        exp_j = p_GetExp(f_j, k, r);
283        lcm = si_max(exp_i, exp_j);
284        p_SetExp(head, k, lcm-exp_i, r);
285    }
286    p_SetComp(head, i+1, r);
287    p_Setm(head, r);
288    return head;
289}
290
291static poly syzHeadExtFrame(const ideal G, const int i, const int j)
292{
293    const ring r = currRing;
294    const poly f_i = G->m[i];
295    const poly f_j = G->m[j];
296    poly head = p_Init(r);
297    pSetCoeff0(head, n_Init(1, r->cf));
298    poly head_ext = p_Init(r);
299    pSetCoeff0(head_ext, n_InpNeg(n_Div(pGetCoeff(f_j), pGetCoeff(f_i), r->cf),
300        r->cf));
301    long exp_i, exp_j, lcm;
302    for (int k = (int)r->N; k > 0; k--) {
303        exp_i = p_GetExp(f_i, k, r);
304        exp_j = p_GetExp(f_j, k, r);
305        lcm = si_max(exp_i, exp_j);
306        p_SetExp(head, k, lcm-exp_i, r);
307        p_SetExp(head_ext, k, lcm-exp_j, r);
308    }
309    p_SetComp(head, i+1, r);
310    p_Setm(head, r);
311    p_SetComp(head_ext, j+1, r);
312    p_Setm(head_ext, r);
313    head->next = head_ext;
314    return head;
315}
316
317typedef ideal syzM_i_Function(ideal, int, syzHeadFunction);
318
319static ideal syzM_i_unsorted(const ideal G, const int i,
320    const syzHeadFunction *syzHead)
321{
322    ideal M_i = NULL;
323    int comp = pGetComp(G->m[i]);
324    int ncols = 0;
325    for (int j = i-1; j >= 0; j--) {
326        if (pGetComp(G->m[j]) == comp) ncols++;
327    }
328    if (ncols > 0) {
329        M_i = idInit(ncols, G->ncols);
330        int k = ncols-1;
331        for (int j = i-1; j >= 0; j--) {
332            if (pGetComp(G->m[j]) == comp) {
333                M_i->m[k] = syzHead(G, i, j);
334                k--;
335            }
336        }
337        id_DelDiv(M_i, currRing);
338        idSkipZeroes(M_i);
339    }
340    return M_i;
341}
342
343static ideal syzM_i_sorted(const ideal G, const int i,
344    const syzHeadFunction *syzHead)
345{
346    ideal M_i = NULL;
347    int comp = pGetComp(G->m[i]);
348    int index = i-1;
349    while (pGetComp(G->m[index]) == comp) index--;
350    index++;
351    int ncols = i-index;
352    if (ncols > 0) {
353        M_i = idInit(ncols, G->ncols);
354        for (int j = ncols-1; j >= 0; j--) {
355            M_i->m[j] = syzHead(G, i, j+index);
356        }
357        id_DelDiv(M_i, currRing);
358        idSkipZeroes(M_i);
359    }
360    return M_i;
361}
362
363static ideal idConcat(const ideal* M, const int size, const int rank)
364{
365    int ncols = 0;
366    for (int i = size-1; i >= 0; i--) {
367        if (M[i] != NULL) {
368            ncols += M[i]->ncols;
369        }
370    }
371    if (ncols == 0) return idInit(1, rank);
372    ideal result = idInit(ncols, rank);
373    int k = ncols-1;
374    for (int i = size-1; i >= 0; i--) {
375        if (M[i] != NULL) {
376            for (int j = M[i]->ncols-1; j >= 0; j--) {
377                result->m[k] = M[i]->m[j];
378                k--;
379            }
380        }
381    }
382    return result;
383}
384
385#define SORT_MI 1
386
387#if SORT_MI
388static int compare_Mi(const void* a, const void *b)
389{
390    const ring r = currRing;
391    poly p_a = *((poly *)a);
392    poly p_b = *((poly *)b);
393    int cmp;
394    int deg_a = p_Deg(p_a, r);
395    int deg_b = p_Deg(p_b, r);
396    cmp = (deg_a > deg_b) - (deg_a < deg_b);
397    if (cmp != 0) {
398         return cmp;
399    }
400    int comp_a = p_GetComp(p_a, r);
401    int comp_b = p_GetComp(p_b, r);
402    cmp = (comp_a > comp_b) - (comp_a < comp_b);
403    if (cmp != 0) {
404         return cmp;
405    }
406    int exp_a[r->N+1];
407    int exp_b[r->N+1];
408    p_GetExpV(p_a, exp_a, r);
409    p_GetExpV(p_b, exp_b, r);
410    for (int i = r->N; i > 0; i--) {
411        cmp = (exp_a[i] > exp_b[i]) - (exp_a[i] < exp_b[i]);
412        if (cmp != 0) {
413            return cmp;
414        }
415    }
416    return 0;
417}
418#endif   // SORT_MI
419
420static ideal computeFrame(const ideal G, const syzM_i_Function syzM_i,
421    const syzHeadFunction *syzHead)
422{
423    ideal* M = (ideal *)omalloc((G->ncols-1)*sizeof(ideal));
424    for (int i = G->ncols-2; i >= 0; i--) {
425        M[i] = syzM_i(G, i+1, syzHead);
426    }
427    ideal frame = idConcat(M, G->ncols-1, G->ncols);
428    for (int i = G->ncols-2; i >= 0; i--) {
429        if (M[i] != NULL) {
430            omFreeSize(M[i]->m, IDELEMS(M[i])*sizeof(poly));
431            omFreeBin(M[i], sip_sideal_bin);
432        }
433    }
434    omFree(M);
435#if SORT_MI
436    qsort(frame->m, IDELEMS(frame), sizeof(poly), compare_Mi);
437#endif
438    return frame;
439}
440
441static void computeLiftings(const resolvente res, const int index,
442    std::vector<bool> &variables)
443{
444    if (index > 1) {   // we don't know if the input is a reduced SB
445        update_variables(variables, res[index-1]);
446    }
447    lts_hash *hash_previous_module = new lts_hash();
448    initialize_lts_hash(*hash_previous_module, res[index-1]);
449    for (int j = res[index]->ncols-1; j >= 0; j--) {
450        res[index]->m[j]->next->next = lift_ext_LT(res[index]->m[j],
451            res[index-1], variables, hash_previous_module);
452    }
453    delete_lts_hash(hash_previous_module);
454    delete(hash_previous_module);
455#if CACHE
456    delete_cache();
457#endif   // CACHE
458}
459
460static int computeResolution(resolvente &res, const int length,
461    const syzHeadFunction *syzHead)
462{
463    int max_index = length-1;
464    int index = 0;
465    if (!idIs0(res[index]) && index < max_index) {
466        index++;
467        res[index] = computeFrame(res[index-1], syzM_i_unsorted, syzHead);
468        std::vector<bool> variables;
469        variables.resize(currRing->N, true);
470        while (!idIs0(res[index])) {
471#if 1
472            computeLiftings(res, index, variables);
473#endif   // LIFT
474            if (index < max_index) {
475                index++;
476                res[index] = computeFrame(res[index-1], syzM_i_sorted,
477                    syzHead);
478            }
479            else {
480                break;
481            }
482        }
483        variables.clear();
484    }
485    max_index = index+1;
486    if (max_index < length) {
487        res = (resolvente)omReallocSize(res, (length+1)*sizeof(ideal),
488            (max_index+1)*sizeof(ideal));
489    }
490    return max_index;
491}
492
493#define insert_first_term(r, p, q, R)                             \
494do                                                                \
495{                                                                 \
496    p = r;                                                        \
497    q = p->next;                                                  \
498    if (q != NULL && p_LmCmp(p, q, R) != 1) {                     \
499        while (q->next != NULL && p_LmCmp(p, q->next, R) == -1) { \
500            pIter(q);                                             \
501        }                                                         \
502        r = p->next;                                              \
503        p->next = q->next;                                        \
504        q->next = p;                                              \
505    }                                                             \
506}                                                                 \
507while (0)
508
509static void insert_ext_induced_LTs(const resolvente res, const int length)
510{
511    const ring R = currRing;
512    poly p, q;
513    for (int i = length-2; i > 0; i--) {
514        for (int j = res[i]->ncols-1; j >= 0; j--) {
515            insert_first_term(res[i]->m[j]->next, p, q, R);
516            insert_first_term(res[i]->m[j], p, q, R);
517        }
518    }
519}
520
521syStrategy syFrank(const ideal arg, int &length, const char *method)
522{
523    syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
524    resolvente res = (resolvente)omAlloc0((length+1)*sizeof(ideal));
525    res[0] = id_Copy(arg, currRing);
526    syzHeadFunction *syzHead;
527    if (strcmp(method, "frame") == 0 || strcmp(method, "linear strand") == 0) {
528        syzHead = syzHeadFrame;
529    }
530    else {
531        syzHead = syzHeadExtFrame;
532    }
533    length = computeResolution(res, length, syzHead);
534    insert_ext_induced_LTs(res, length);
535    result->fullres = res;
536    result->length = length;
537    return result;
538}
539
Note: See TracBrowser for help on using the repository browser.