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

spielwiese
Last change on this file since b3594cb was c858487, checked in by Frédéric Chapoton <chapoton@…>, 18 months ago
fix many typos in kernel/
  • Property mode set to 100644
File size: 23.4 KB
Line 
1/***************************************
2 *  Computer Algebra System SINGULAR   *
3 ***************************************/
4/*
5 * ABSTRACT: resolutions
6 * reference: https://arxiv.org/abs/1502.01654
7 */
8
9#include "kernel/GBEngine/syz.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/*
18 * set variables[i] to false if the i-th variable does not appear among the
19 * leading terms of L
20 */
21static void update_variables(std::vector<bool> &variables, const ideal L)
22{
23    const ring R = currRing;
24    const int l = L->ncols-1;
25    int k;
26    for (int j = R->N; j > 0; j--)
27    {
28        if (variables[j-1])
29        {
30            for (k = l; k >= 0; k--)
31            {
32                if (p_GetExp(L->m[k], j, R) > 0)
33                {
34                    break;
35                }
36            }
37            if (k < 0)
38            {   // no break
39                variables[j-1] = false;
40            }
41        }
42    }
43}
44
45/*
46 * If the previous step in the resolution is reduced, then this check can be
47 * used to determine lower order terms.
48 */
49static inline bool check_variables(const std::vector<bool> &variables,
50        const poly m)
51{
52    const ring R = currRing;
53    // variables[R->N] is true iff index == 1, that is, for the first step in
54    // the resolution
55    if (UNLIKELY(variables[R->N]))
56    {
57        return true;
58    }
59    for (int j = R->N; j > 0; j--)
60    {
61        if (UNLIKELY(variables[j-1] && p_GetExp(m, j, R) > 0))
62        {
63            return true;
64        }
65    }
66    return false;
67}
68
69/*
70 * For each step in the resolution, the following data is saved for each of the
71 * induced leading terms: the leading term itself, its short exponent vector,
72 * and its position in the ideal/module.
73 */
74typedef struct {
75    poly lt;
76    unsigned long sev;
77    unsigned long comp;
78} lt_struct;
79
80static void initialize_hash(lt_struct **C, const ideal L)
81{
82    const ring R = currRing;
83    const unsigned long n_elems = L->ncols;
84    unsigned int *count
85        = (unsigned int *)omAlloc0((L->rank+1)*sizeof(unsigned int));
86    unsigned long k = 0;
87    while (k < n_elems)
88    {
89        count[__p_GetComp(L->m[k], R)]++;
90        k++;
91    }
92    for (int i = 0; i <= L->rank; i++)
93    {
94        // do ++count[i] and use C[i][0].comp to save count[i]
95        C[i] = (lt_struct *)omalloc0((++count[i])*sizeof(lt_struct));
96        C[i][0].comp = count[i];
97    }
98    k = n_elems;
99    // the order of the elements in each C[i] matters if check_variables() is
100    // to be used
101    while (k > 0)
102    {
103        const poly a = L->m[k-1];
104        const unsigned long comp = __p_GetComp(a, R);
105        C[comp][--count[comp]]
106            = (lt_struct){a, p_GetShortExpVector(a, R), k};
107        k--;
108    }
109    omFree(count);
110}
111
112/*
113 * compute a new term in the resolution, that is, compute
114 * ( t * multiplier / f ) where f is an induced leading term from the previous
115 * module, or return NULL if no such f dividing t * multiplier exists, that is,
116 * if multiplier is a lower order term
117 */
118static poly find_reducer(const poly multiplier, const poly t,
119        const lt_struct *const *const hash_previous_module)
120{
121    const ring r = currRing;
122    const lt_struct *v = hash_previous_module[__p_GetComp(t, r)];
123    unsigned long count = v[0].comp;
124    if (UNLIKELY(count == 1))
125    {
126        return NULL;
127    }
128    const poly q = p_New(r);
129    pNext(q) = NULL;
130    p_MemSum_LengthGeneral(q->exp, multiplier->exp, t->exp, r->ExpL_Size);
131    const unsigned long q_not_sev = ~p_GetShortExpVector(q, r);
132    for(unsigned long i = 1; i < count; i++)
133    {
134        if (LIKELY(v[i].sev & q_not_sev)
135                || UNLIKELY(!(_p_LmDivisibleByNoComp(v[i].lt, q, r))))
136                {
137            continue;
138        }
139        p_MemAdd_NegWeightAdjust(q, r);
140        p_ExpVectorDiff(q, q, v[i].lt, r);
141        p_SetComp(q, v[i].comp, r);
142        p_Setm(q, r);
143        number n = n_Div(p_GetCoeff(multiplier, r), p_GetCoeff(v[i].lt, r), r->cf);
144        n_InpMult(n, p_GetCoeff(t, r), r->cf);
145        p_SetCoeff0(q, n_InpNeg(n, r->cf), r);
146        return q;
147    }
148    p_LmFree(q, r);
149    return NULL;
150}
151
152static poly traverse_tail(const poly multiplier, const int comp,
153        const ideal previous_module, const std::vector<bool> &variables,
154        const lt_struct *const *const hash_previous_module);
155
156static poly compute_image(const poly multiplier, const int comp,
157        const ideal previous_module, const std::vector<bool> &variables,
158        const lt_struct *const *const hash_previous_module,
159        const bool use_cache);
160
161/*
162 * recursively call traverse_tail() for each new term found by find_reducer()
163 */
164static poly reduce_term(const poly multiplier, const poly term,
165        const ideal previous_module, const std::vector<bool> &variables,
166        const lt_struct *const *const hash_previous_module,
167        const bool use_cache)
168{
169    poly s = find_reducer(multiplier, term, hash_previous_module);
170    if (s == NULL)
171    {
172        return NULL;
173    }
174    const ring r = currRing;
175    const int c = __p_GetComp(s, r) - 1;
176    poly t;
177    if (use_cache)
178    {
179        t = traverse_tail(s, c, previous_module, variables,
180                hash_previous_module);
181    } else {
182        t = compute_image(s, c, previous_module, variables,
183                hash_previous_module, false);
184    }
185    return p_Add_q(s, t, r);
186}
187
188/*
189 * iterating over tail, call reduce_term(multiplier, p, ...) for each term p in
190 * tail and sum up the results
191 */
192static poly compute_image(const poly multiplier, const int comp,
193        const ideal previous_module, const std::vector<bool> &variables,
194        const lt_struct *const *const hash_previous_module,
195        const bool use_cache)
196{
197    const poly tail = previous_module->m[comp]->next;
198    if (UNLIKELY(tail == NULL) || !check_variables(variables, multiplier))
199    {
200        return NULL;
201    }
202    sBucket_pt sum = sBucketCreate(currRing);
203    for (poly p = tail; p != NULL; p = pNext(p))
204    {
205        const poly rt = reduce_term(multiplier, p, previous_module, variables,
206                hash_previous_module, use_cache);
207        sBucket_Add_p(sum, rt, pLength(rt));
208    }
209    poly s;
210    int l;
211    sBucketClearAdd(sum, &s, &l);
212    sBucketDestroy(&sum);
213    return s;
214}
215
216struct cache_compare
217{
218    inline bool operator() (const poly& l, const poly& r) const
219    {
220        return (p_LmCmp(l, r, currRing) == -1);
221        /* For expensive orderings, consider:
222         * return (memcmp(l->exp, r->exp,
223         *         (currRing->CmpL_Size)*sizeof(unsigned long)) < 0);
224         */
225    }
226};
227
228typedef std::map<poly, poly, cache_compare> cache_term;
229
230STATIC_VAR cache_term *Cache;
231
232static void initialize_cache(const int size)
233{
234    Cache = new cache_term[size];
235}
236
237static void delete_cache(const int size)
238{
239    const ring r = currRing;
240    for (int i = 0; i < size; i++)
241    {
242        cache_term *T = &(Cache[i]);
243        for (cache_term::iterator itr = T->begin(); itr != T->end(); ++itr)
244        {
245            p_Delete(&(itr->second), r);
246            p_Delete(const_cast<poly*>(&(itr->first)), r);
247        }
248        T->clear();
249    }
250    delete[](Cache);
251}
252
253static void insert_into_cache_term(cache_term *T, const poly multiplier,
254        const poly p)
255{
256    const ring r = currRing;
257    T->insert(cache_term::value_type(p_Head(multiplier, r), p_Copy(p, r)));
258}
259
260static poly get_from_cache_term(const cache_term::const_iterator itr,
261        const poly multiplier)
262{
263    if (LIKELY(itr->second == NULL))
264    {
265        return NULL;
266    }
267    const ring r = currRing;
268    poly p = p_Copy(itr->second, r);
269    if (LIKELY(!n_Equal(pGetCoeff(multiplier), pGetCoeff(itr->first), r->cf)))
270    {
271        number n = n_Div(pGetCoeff(multiplier), pGetCoeff(itr->first), r->cf);
272        p = p_Mult_nn(p, n, r);
273        n_Delete(&n, r->cf);
274    }
275    return p;
276}
277
278static poly traverse_tail(const poly multiplier, const int comp,
279        const ideal previous_module, const std::vector<bool> &variables,
280        const lt_struct *const *const hash_previous_module)
281{
282    cache_term *T = &(Cache[comp]);
283    cache_term::const_iterator itr = T->find(multiplier);
284    if (LIKELY(itr != T->end()))
285    {
286        return get_from_cache_term(itr, multiplier);
287    }
288    poly p = compute_image(multiplier, comp, previous_module, variables,
289            hash_previous_module, true);
290    insert_into_cache_term(T, multiplier, p);
291    return p;
292}
293
294/*
295 * lift the extended induced leading term a to a syzygy
296 */
297static poly lift_ext_LT(const poly a, const ideal previous_module,
298        const std::vector<bool> &variables,
299        const lt_struct *const *const hash_previous_module,
300        const bool use_cache)
301{
302    const ring R = currRing;
303    // the leading term does not need to be cached
304    poly t1 = compute_image(a, __p_GetComp(a, R)-1, previous_module, variables,
305            hash_previous_module, use_cache);
306    poly t2;
307    if (use_cache)
308    {
309        t2 = traverse_tail(a->next, __p_GetComp(a->next, R)-1,
310                previous_module, variables, hash_previous_module);
311    } else {
312        t2 = compute_image(a->next, __p_GetComp(a->next, R)-1,
313                previous_module, variables, hash_previous_module, false);
314    }
315    t1 = p_Add_q(t1, t2, R);
316    return t1;
317}
318
319/*****************************************************************************/
320
321typedef poly syzHeadFunction(ideal, int, int);
322
323/*
324 * compute the induced leading term corresponding to the index pair (i, j)
325 */
326static poly syzHeadFrame(const ideal G, const int i, const int j)
327{
328    const ring r = currRing;
329    const poly f_i = G->m[i];
330    const poly f_j = G->m[j];
331    poly head = p_Init(r);
332    pSetCoeff0(head, n_Init(1, r->cf));
333    long exp_i, exp_j, lcm;
334    for (int k = (int)r->N; k > 0; k--)
335    {
336        exp_i = p_GetExp(f_i, k, r);
337        exp_j = p_GetExp(f_j, k, r);
338        lcm = si_max(exp_i, exp_j);
339        p_SetExp(head, k, lcm-exp_i, r);
340    }
341    p_SetComp(head, i+1, r);
342    p_Setm(head, r);
343    return head;
344}
345
346/*
347 * compute the _extended_ induced leading term corresponding to the index pair
348 * (i, j), that is, the first two terms w.r.t. the induced order
349 */
350static poly syzHeadExtFrame(const ideal G, const int i, const int j)
351{
352    const ring r = currRing;
353    const poly f_i = G->m[i];
354    const poly f_j = G->m[j];
355    poly head = p_Init(r);
356    pSetCoeff0(head, n_Init(1, r->cf));
357    poly head_ext = p_Init(r);
358    pSetCoeff0(head_ext, n_InpNeg(n_Div(pGetCoeff(f_i), pGetCoeff(f_j), r->cf),
359                r->cf));
360    long exp_i, exp_j, lcm;
361    for (int k = (int)r->N; k > 0; k--)
362    {
363        exp_i = p_GetExp(f_i, k, r);
364        exp_j = p_GetExp(f_j, k, r);
365        lcm = si_max(exp_i, exp_j);
366        p_SetExp(head, k, lcm-exp_i, r);
367        p_SetExp(head_ext, k, lcm-exp_j, r);
368    }
369    p_SetComp(head, i+1, r);
370    p_Setm(head, r);
371    p_SetComp(head_ext, j+1, r);
372    p_Setm(head_ext, r);
373    head->next = head_ext;
374    return head;
375}
376
377typedef ideal syzM_i_Function(ideal, int, syzHeadFunction);
378
379/*
380 * compute the monomial ideal M_i, see reference;
381 * in the first step, we cannot assume that all leading terms which lie in the
382 * component are adjacent to each other
383 */
384static ideal syzM_i_unsorted(const ideal G, const int i,
385        syzHeadFunction *syzHead)
386{
387    const ring r = currRing;
388    ideal M_i = NULL;
389    unsigned long comp = __p_GetComp(G->m[i], r);
390    int ncols = 0;
391    for (int j = i-1; j >= 0; j--)
392    {
393        if (__p_GetComp(G->m[j], r) == comp) ncols++;
394    }
395    if (ncols > 0)
396    {
397        M_i = idInit(ncols, G->ncols);
398        int k = ncols-1;
399        for (int j = i-1; j >= 0; j--)
400        {
401            if (__p_GetComp(G->m[j], r) == comp)
402            {
403                M_i->m[k] = syzHead(G, i, j);
404                k--;
405            }
406        }
407        id_DelDiv(M_i, currRing);
408        idSkipZeroes(M_i);
409    }
410    return M_i;
411}
412
413/*
414 * compute the monomial ideal M_i, see reference;
415 * from step two on, we can assume that all leading terms which lie in the same
416 * component are adjacent to each other
417 */
418static ideal syzM_i_sorted(const ideal G, const int i,
419        syzHeadFunction *syzHead)
420{
421    const ring r = currRing;
422    ideal M_i = NULL;
423    unsigned long comp = __p_GetComp(G->m[i], r);
424    int index = i-1;
425    while (__p_GetComp(G->m[index], r) == comp) index--;
426    index++;
427    int ncols = i-index;
428    if (ncols > 0)
429    {
430        M_i = idInit(ncols, G->ncols);
431        for (int j = ncols-1; j >= 0; j--)
432        {
433            M_i->m[j] = syzHead(G, i, j+index);
434        }
435        id_DelDiv(M_i, currRing);
436        idSkipZeroes(M_i);
437    }
438    return M_i;
439}
440
441/*
442 * concatenate the ideals in M[]
443 */
444static ideal idConcat(const ideal *M, const int size, const int rank)
445{
446    int ncols = 0;
447    for (int i = size-1; i >= 0; i--)
448    {
449        if (M[i] != NULL)
450        {
451            ncols += M[i]->ncols;
452        }
453    }
454    if (ncols == 0) return idInit(1, rank);
455    ideal result = idInit(ncols, rank);
456    int k = ncols-1;
457    for (int i = size-1; i >= 0; i--)
458    {
459        if (M[i] != NULL)
460        {
461            for (int j = M[i]->ncols-1; j >= 0; j--)
462            {
463                result->m[k] = M[i]->m[j];
464                k--;
465            }
466        }
467    }
468    return result;
469}
470
471static int compare_comp(const poly p_a, const poly p_b)
472{
473    const ring r = currRing;
474    long comp_a = __p_GetComp(p_a, r);
475    long comp_b = __p_GetComp(p_b, r);
476    return (comp_a > comp_b) - (comp_a < comp_b);
477}
478
479static int compare_deg(const poly p_a, const poly p_b)
480{
481    const ring r = currRing;
482    long deg_a = p_Deg(p_a, r);
483    long deg_b = p_Deg(p_b, r);
484    return (deg_a > deg_b) - (deg_a < deg_b);
485}
486
487static int compare_lex(const poly p_a, const poly p_b)
488{
489    int cmp;
490    const ring r = currRing;
491    int exp_a[r->N+1];
492    int exp_b[r->N+1];
493    p_GetExpV(p_a, exp_a, r);
494    p_GetExpV(p_b, exp_b, r);
495    for (int i = r->N; i > 0; i--)
496    {
497        cmp = (exp_a[i] > exp_b[i]) - (exp_a[i] < exp_b[i]);
498        if (cmp != 0)
499        {
500            return cmp;
501        }
502    }
503    return 0;
504}
505
506static int compare_Mi(const void* a, const void *b)
507{
508    poly p_a = *((poly *)a);
509    poly p_b = *((poly *)b);
510    int cmp;
511    if ((cmp = compare_comp(p_a, p_b))
512            || (cmp = compare_deg(p_a, p_b))
513            || (cmp = compare_lex(p_a, p_b)))
514            {
515        return cmp;
516    }
517    return 0;
518}
519
520/*
521 * compute the frame, that is, the induced leading terms for the next step in
522 * the resolution
523 */
524static ideal computeFrame(const ideal G, syzM_i_Function syzM_i,
525        syzHeadFunction *syzHead)
526{
527    ideal *M = (ideal *)omalloc((G->ncols-1)*sizeof(ideal));
528    for (int i = G->ncols-2; i >= 0; i--)
529    {
530        M[i] = syzM_i(G, i+1, syzHead);
531    }
532    ideal frame = idConcat(M, G->ncols-1, G->ncols);
533    for (int i = G->ncols-2; i >= 0; i--)
534    {
535        if (M[i] != NULL)
536        {
537            omFreeSize(M[i]->m, M[i]->ncols*sizeof(poly));
538            omFreeBin(M[i], sip_sideal_bin);
539        }
540    }
541    omfree(M);
542    qsort(frame->m, frame->ncols, sizeof(poly), compare_Mi);
543    return frame;
544}
545
546/*
547 * lift each (extended) induced leading term to a syzygy
548 */
549static void computeLiftings(const resolvente res, const int index,
550        const std::vector<bool> &variables, const bool use_cache)
551{
552    if (use_cache)
553    {
554        initialize_cache(res[index-1]->ncols);
555    }
556    lt_struct **hash_previous_module
557        = (lt_struct **)omAlloc((res[index-1]->rank+1)*sizeof(lt_struct *));
558    initialize_hash(hash_previous_module, res[index-1]);
559    for (int j = res[index]->ncols-1; j >= 0; j--)
560    {
561        res[index]->m[j]->next->next = lift_ext_LT(res[index]->m[j],
562                res[index-1], variables, hash_previous_module, use_cache);
563    }
564    for (int i = 0; i <= res[index-1]->rank; i++)
565    {
566        omfree(hash_previous_module[i]);
567    }
568    omFree(hash_previous_module);
569    if (use_cache)
570    {
571        delete_cache(res[index-1]->ncols);
572    }
573}
574
575/*
576 * check if the monomial m contains any of the variables set to false
577 */
578static inline bool contains_unused_variable(const poly m,
579    const std::vector<bool> &variables)
580{
581    const ring R = currRing;
582    for (int j = R->N; j > 0; j--)
583    {
584        if (!variables[j-1] && p_GetExp(m, j, R) > 0)
585        {
586            return true;
587        }
588    }
589    return false;
590}
591
592/*
593 * delete any term in res[index] which contains any of the variables set to
594 * false
595 */
596static void delete_variables(resolvente res, const int index,
597    const std::vector<bool> &variables)
598{
599    for (int i = 0; i < res[index]->ncols; i++)
600    {
601        poly p_iter = res[index]->m[i]->next;
602        if (p_iter != NULL)
603        {
604            while (p_iter->next != NULL)
605            {
606                if (contains_unused_variable(p_iter->next, variables))
607                {
608                    pLmDelete(&p_iter->next);
609                } else {
610                    pIter(p_iter);
611                }
612            }
613        }
614    }
615}
616
617static void delete_tails(resolvente res, const int index)
618{
619    const ring r = currRing;
620    for (int i = 0; i < res[index]->ncols; i++)
621    {
622        if (res[index]->m[i] != NULL)
623        {
624            p_Delete(&(res[index]->m[i]->next), r);
625        }
626    }
627}
628
629/*
630 * for each step in the resolution, compute the corresponding module until
631 * either index == max_index is reached or res[index] is the zero module
632 */
633static int computeResolution_iteration(resolvente res, const int max_index,
634        syzHeadFunction *syzHead, const bool do_lifting,
635        const bool single_module, const bool use_cache,
636        const bool use_tensor_trick, std::vector<bool> &variables)
637{
638    int index = 1;
639    while (!idIs0(res[index]))
640    {
641        if (do_lifting)
642        {
643            computeLiftings(res, index, variables, use_cache);
644            if (single_module)
645            {
646                delete_tails(res, index-1);
647            }
648            // we don't know if the input is a reduced SB:
649            if (index == 1)
650            {
651                variables[currRing->N] = false;
652            }
653            update_variables(variables, res[index]);
654            if (use_tensor_trick)
655            {
656                delete_variables(res, index, variables);
657            }
658        }
659        if (index >= max_index) { break; }
660        index++;
661        res[index] = computeFrame(res[index-1], syzM_i_sorted, syzHead);
662    }
663    return index;
664}
665
666/*
667 * compute the frame of the first syzygy module and set variables, then call
668 * computeResolution_iteration() for the remaining steps
669 */
670static int computeResolution(resolvente res, const int max_index,
671        syzHeadFunction *syzHead, const bool do_lifting,
672        const bool single_module, const bool use_cache,
673        const bool use_tensor_trick)
674{
675    if (idIs0(res[0]))
676    {
677        return 1;
678    }
679    std::vector<bool> variables;
680    variables.resize(currRing->N+1, true);
681    if (do_lifting)
682    {
683        update_variables(variables, res[0]);
684        if (use_tensor_trick)
685        {
686            delete_variables(res, 0, variables);
687        }
688    }
689    int index = 0;
690    if (max_index > 0)
691    {
692        res[1] = computeFrame(res[0], syzM_i_unsorted, syzHead);
693        index = computeResolution_iteration(res, max_index, syzHead,
694                do_lifting, single_module, use_cache, use_tensor_trick,
695                variables);
696    }
697    variables.clear();
698    return index+1;
699}
700
701static void set_options(syzHeadFunction **syzHead_ptr, bool *do_lifting_ptr,
702        bool *single_module_ptr, const char *method)
703{
704    if (strcmp(method, "complete") == 0)
705    {   // default
706        *syzHead_ptr = syzHeadExtFrame;
707        *do_lifting_ptr = true;
708        *single_module_ptr = false;
709    }
710    else if (strcmp(method, "frame") == 0)
711    {
712        *syzHead_ptr = syzHeadFrame;
713        *do_lifting_ptr = false;
714        *single_module_ptr = false;
715    }
716    else if (strcmp(method, "extended frame") == 0)
717    {
718        *syzHead_ptr = syzHeadExtFrame;
719        *do_lifting_ptr = false;
720        *single_module_ptr = false;
721    }
722    else if (strcmp(method, "single module") == 0)
723    {
724        *syzHead_ptr = syzHeadExtFrame;
725        *do_lifting_ptr = true;
726        *single_module_ptr = true;
727    }
728    else {   // "linear strand" (not yet implemented)
729        *syzHead_ptr = syzHeadExtFrame;
730        *do_lifting_ptr = true;
731        *single_module_ptr = false;
732    }
733}
734
735/*
736 * insert the first term of r at the right place
737 */
738#define insert_first_term(r, p, q, R)                             \
739do                                                                \
740{                                                                 \
741    p = r;                                                        \
742    q = p->next;                                                  \
743    if (q != NULL && p_LmCmp(p, q, R) != 1) {                     \
744        while (q->next != NULL && p_LmCmp(p, q->next, R) == -1) { \
745            pIter(q);                                             \
746        }                                                         \
747        r = p->next;                                              \
748        p->next = q->next;                                        \
749        q->next = p;                                              \
750    }                                                             \
751}                                                                 \
752while (0)
753
754/*
755 * For each poly in the resolution, insert the first two terms at their right
756 * places. If single_module is true, then only consider the last module.
757 */
758static void insert_ext_induced_LTs(const resolvente res, const int length,
759        const bool single_module)
760{
761    const ring R = currRing;
762    poly p, q;
763    int index = (single_module ? length-1 : 1);
764    while (index < length && !idIs0(res[index]))
765    {
766        for (int j = res[index]->ncols-1; j >= 0; j--)
767        {
768            insert_first_term(res[index]->m[j]->next, p, q, R);
769            insert_first_term(res[index]->m[j], p, q, R);
770        }
771        index++;
772    }
773}
774
775/*
776 * Compute the Schreyer resolution of arg, see reference at the beginning of
777 * this file.
778 *
779 * If use_cache == true (default), the result of compute_image() is cached for
780 * _every_ term in the current step of the resolution. This corresponds to the
781 * subtree attached to the node which represents this term, see reference.
782 *
783 * If use_tensor_trick == true, the current module is modified after each
784 * lifting step in the resolution: any term which contains a variable which
785 * does not appear among the (induced) leading terms is deleted. Note that the
786 * resulting object is not necessarily a complex anymore. However, constant
787 * entries remain exactly the same. This option does not apply for
788 * method == "frame" and method "extended frame".
789 *
790 * These two options are used in PrymGreen.jl; do not delete!
791 */
792syStrategy syFrank(const ideal arg, const int length, const char *method,
793        const bool use_cache, const bool use_tensor_trick)
794{
795    syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
796    resolvente res = (resolvente)omAlloc0((length+1)*sizeof(ideal));
797    if (strcmp(method, "frame") != 0)
798    {
799        res[0] = id_Copy(arg, currRing);
800    }
801    else
802    {
803        res[0] = id_Head(arg, currRing);
804    }
805    syzHeadFunction *syzHead;
806    bool do_lifting;
807    bool single_module;
808    set_options(&syzHead, &do_lifting, &single_module, method);
809    int new_length = computeResolution(res, length-1, syzHead, do_lifting,
810            single_module, use_cache, use_tensor_trick);
811    if (new_length < length)
812    {
813        res = (resolvente)omReallocSize(res, (length+1)*sizeof(ideal),
814                (new_length+1)*sizeof(ideal));
815    }
816    if (strcmp(method, "frame") != 0)
817    {
818        insert_ext_induced_LTs(res, new_length, single_module);
819    }
820    result->fullres = res;
821    result->length = new_length;
822    result->list_length = new_length;
823    return result;
824}
825
Note: See TracBrowser for help on using the repository browser.