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

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