1 | /**************************************** |
---|
2 | * Computer Algebra System SINGULAR * |
---|
3 | ****************************************/ |
---|
4 | /* |
---|
5 | * ABSTRACT - Kernel: alg. of Buchberger |
---|
6 | */ |
---|
7 | |
---|
8 | #include "kernel/mod2.h" |
---|
9 | |
---|
10 | // define if no buckets should be used |
---|
11 | // #define NO_BUCKETS |
---|
12 | |
---|
13 | #include "kernel/GBEngine/kutil.h" |
---|
14 | #include "misc/options.h" |
---|
15 | #include "kernel/polys.h" |
---|
16 | #include "kernel/ideals.h" |
---|
17 | #include "kernel/GBEngine/kstd1.h" |
---|
18 | #include "kernel/GBEngine/khstd.h" |
---|
19 | #include "polys/kbuckets.h" |
---|
20 | #include "polys/prCopy.h" |
---|
21 | #include "polys/weight.h" |
---|
22 | #include "misc/intvec.h" |
---|
23 | #ifdef HAVE_PLURAL |
---|
24 | #include "polys/nc/nc.h" |
---|
25 | #endif |
---|
26 | |
---|
27 | static poly kSplitAt(int k,poly p, const ring r) |
---|
28 | { |
---|
29 | if((p==NULL) || (p->next==NULL)) return NULL; |
---|
30 | while(p_GetComp(p->next,r)<=k) |
---|
31 | { |
---|
32 | pIter(p); |
---|
33 | if (p->next==NULL) return NULL; |
---|
34 | } |
---|
35 | poly t=p->next; |
---|
36 | p->next=NULL; |
---|
37 | return t; |
---|
38 | } |
---|
39 | static poly kSplitAt(int k,TObject* h,int *l,kStrategy strat) |
---|
40 | { |
---|
41 | poly p; |
---|
42 | if (h->t_p==NULL) |
---|
43 | { |
---|
44 | if (currRing!=strat->tailRing) |
---|
45 | { |
---|
46 | h->t_p=k_LmInit_currRing_2_tailRing(h->p, strat->tailRing); |
---|
47 | p=h->t_p; |
---|
48 | } |
---|
49 | else |
---|
50 | p=h->p; |
---|
51 | } |
---|
52 | else |
---|
53 | p=h->t_p; |
---|
54 | if (p->next==NULL) return NULL; |
---|
55 | int ll=1; |
---|
56 | const ring tailRing=strat->tailRing; |
---|
57 | while(p_GetComp(p->next,tailRing)<=k) |
---|
58 | { |
---|
59 | pIter(p); |
---|
60 | *l=ll; |
---|
61 | if ((p==NULL)||(p->next==NULL)) return NULL; |
---|
62 | ll++; |
---|
63 | } |
---|
64 | poly t=p->next; |
---|
65 | p->next=NULL; |
---|
66 | *l=ll; |
---|
67 | return t; |
---|
68 | } |
---|
69 | static poly kSplitAt(int k,LObject* h,kStrategy strat) |
---|
70 | { |
---|
71 | poly p,pr; |
---|
72 | int l; |
---|
73 | if (h->bucket!=NULL) |
---|
74 | { |
---|
75 | kBucketClear(h->bucket,&p,&l); |
---|
76 | pr=p; |
---|
77 | } |
---|
78 | else |
---|
79 | { |
---|
80 | if (h->t_p==NULL) |
---|
81 | { |
---|
82 | if (currRing!=strat->tailRing) |
---|
83 | { |
---|
84 | h->t_p=k_LmInit_currRing_2_tailRing(h->p, strat->tailRing); |
---|
85 | p=h->t_p; |
---|
86 | } |
---|
87 | else |
---|
88 | p=h->p; |
---|
89 | } |
---|
90 | else |
---|
91 | p=h->t_p; |
---|
92 | } |
---|
93 | const ring tailRing=strat->tailRing; |
---|
94 | if (p_GetComp(p,tailRing)>k) |
---|
95 | { |
---|
96 | return p; |
---|
97 | } |
---|
98 | if (p->next==NULL) return NULL; |
---|
99 | while(p_GetComp(p->next,tailRing)<=k) pIter(p); |
---|
100 | poly t=p->next; |
---|
101 | p->next=NULL; |
---|
102 | if (h->bucket!=NULL) |
---|
103 | { |
---|
104 | l=pLength(pr); |
---|
105 | kBucketInit(h->bucket,pr,l); |
---|
106 | } |
---|
107 | return t; |
---|
108 | } |
---|
109 | static poly kTailAt(int k,TObject* h,kStrategy strat) |
---|
110 | { |
---|
111 | poly p; |
---|
112 | if (h->t_p!=NULL) |
---|
113 | p=h->t_p; |
---|
114 | else |
---|
115 | p=h->p; |
---|
116 | assume(p_GetComp(p,strat->tailRing)<=k); |
---|
117 | if (p->next==NULL) return NULL; |
---|
118 | const ring tailRing=strat->tailRing; |
---|
119 | while(p_GetComp(p->next,tailRing)<=k) pIter(p); |
---|
120 | poly t=p->next; |
---|
121 | return t; |
---|
122 | } |
---|
123 | static void kAppend(poly t,TObject* h) |
---|
124 | { |
---|
125 | poly p; |
---|
126 | if (h->t_p!=NULL) |
---|
127 | p=h->t_p; |
---|
128 | else |
---|
129 | p=h->p; |
---|
130 | while(p->next!=NULL) pIter(p); |
---|
131 | p->next=t; |
---|
132 | if ((h->p!=NULL)&&(h->t_p!=NULL)) pNext(h->p)=pNext(h->t_p); |
---|
133 | } |
---|
134 | static void kAppend(poly t,LObject* h) |
---|
135 | { |
---|
136 | if (h->bucket!=NULL) |
---|
137 | { |
---|
138 | int l=-1; |
---|
139 | kBucket_Add_q(h->bucket,t,&l); |
---|
140 | } |
---|
141 | else |
---|
142 | { |
---|
143 | poly p; |
---|
144 | if (h->t_p!=NULL) |
---|
145 | p=h->t_p; |
---|
146 | else |
---|
147 | p=h->p; |
---|
148 | while(p->next!=NULL) pIter(p); |
---|
149 | p->next=t; |
---|
150 | if ((h->p!=NULL)&&(h->t_p!=NULL)) pNext(h->p)=pNext(h->t_p); |
---|
151 | } |
---|
152 | } |
---|
153 | |
---|
154 | static poly lazyComp(number* A, poly* M,poly* T,int index,poly s,int *l,const ring tailR) |
---|
155 | { |
---|
156 | if ((TEST_OPT_PROT) && (index>0)) { Print("<%d>",index+1); mflush(); } |
---|
157 | kBucket_pt b=kBucketCreate(tailR); |
---|
158 | kBucketInit(b,s,pLength(s)); |
---|
159 | for(int i=0;i<index;i++) |
---|
160 | { |
---|
161 | kBucket_Mult_n(b,A[i]); |
---|
162 | n_Delete(&A[i],tailR->cf); |
---|
163 | poly tt=T[i]; |
---|
164 | if (tt!=NULL) |
---|
165 | { |
---|
166 | int dummy=pLength(tt); |
---|
167 | kBucket_Minus_m_Mult_p(b,M[i],tt,&dummy); |
---|
168 | } |
---|
169 | p_Delete(&M[i],tailR); |
---|
170 | } |
---|
171 | poly p; |
---|
172 | kBucketClear(b,&p,l); |
---|
173 | kBucketDestroy(&b); |
---|
174 | return p; |
---|
175 | } |
---|
176 | /*2 |
---|
177 | * reduction procedure for the sugar-strategy (honey) |
---|
178 | * reduces h with elements from T choosing first possible |
---|
179 | * element in T with respect to the given ecart |
---|
180 | */ |
---|
181 | int redLiftstd (LObject* h, kStrategy strat) |
---|
182 | { |
---|
183 | if (strat->tl<0) return 1; |
---|
184 | assume(h->FDeg == h->pFDeg()); |
---|
185 | poly h_p; |
---|
186 | int i,j,at,pass,ei, ii, h_d,ci; |
---|
187 | unsigned long not_sev; |
---|
188 | long reddeg,d; |
---|
189 | number A[500]; |
---|
190 | poly C[500]; |
---|
191 | poly T[500]; |
---|
192 | memset(T,0,sizeof(T)); |
---|
193 | memset(C,0,sizeof(T)); |
---|
194 | const ring tailRing=strat->tailRing; |
---|
195 | |
---|
196 | pass = j = 0; |
---|
197 | d = reddeg = h->GetpFDeg() + h->ecart; |
---|
198 | h->SetShortExpVector(); |
---|
199 | int li; |
---|
200 | h_p = h->GetLmTailRing(); |
---|
201 | not_sev = ~ h->sev; |
---|
202 | |
---|
203 | // split h into mina part (h) and tail (h_tail) |
---|
204 | poly h_tail=kSplitAt(strat->syzComp,h,strat); |
---|
205 | // fix h-pLength |
---|
206 | h->pLength=0; |
---|
207 | // remove content |
---|
208 | //number cont; |
---|
209 | //p_Content_n(h_p,cont,strat->tailRing); |
---|
210 | //if (!n_IsOne(cont,strat->tailRing)) |
---|
211 | // h_tail=p_Div_nn(h_tail,cont,tailRing); |
---|
212 | |
---|
213 | h->PrepareRed(strat->use_buckets); |
---|
214 | loop |
---|
215 | { |
---|
216 | j=kFindDivisibleByInT(strat, h); |
---|
217 | if (j < 0) |
---|
218 | { |
---|
219 | // lazy computation: |
---|
220 | int l; |
---|
221 | poly p=lazyComp(A,C,T,pass,h_tail,&l,strat->tailRing); |
---|
222 | kBucket_Add_q(h->bucket,p,&l); |
---|
223 | return 1; |
---|
224 | } |
---|
225 | |
---|
226 | ei = strat->T[j].ecart; |
---|
227 | li = strat->T[j].pLength; |
---|
228 | ci = nSize(pGetCoeff(strat->T[j].p)); |
---|
229 | if (li<=0) li=strat->T[j].GetpLength(); |
---|
230 | ii = j; |
---|
231 | /* |
---|
232 | * the polynomial to reduce with (up to the moment) is; |
---|
233 | * pi with ecart ei (T[ii]) |
---|
234 | */ |
---|
235 | i = j; |
---|
236 | if (TEST_OPT_LENGTH) |
---|
237 | loop |
---|
238 | { |
---|
239 | /*- possible with respect to ecart, minimal nSize -*/ |
---|
240 | i++; |
---|
241 | if (i > strat->tl) |
---|
242 | break; |
---|
243 | //if (ei < h->ecart) |
---|
244 | // break; |
---|
245 | if (li==1) |
---|
246 | break; |
---|
247 | if ((((strat->T[i].ecart < ei) && (ei> h->ecart)) |
---|
248 | || ((strat->T[i].ecart <= h->ecart) |
---|
249 | && (strat->T[i].pLength <= li) |
---|
250 | && (nSize(pGetCoeff(strat->T[i].p)) <ci))) |
---|
251 | && |
---|
252 | p_LmShortDivisibleBy(strat->T[i].GetLmTailRing(), strat->sevT[i], |
---|
253 | h_p, not_sev, tailRing)) |
---|
254 | { |
---|
255 | /* |
---|
256 | * the polynomial to reduce with is now; |
---|
257 | */ |
---|
258 | ei = strat->T[i].ecart; |
---|
259 | li = strat->T[i].pLength; |
---|
260 | if (li<=0) li=strat->T[i].GetpLength(); |
---|
261 | ii = i; |
---|
262 | } |
---|
263 | } |
---|
264 | |
---|
265 | /* |
---|
266 | * end of search: have to reduce with pi |
---|
267 | */ |
---|
268 | #ifdef KDEBUG |
---|
269 | if (TEST_OPT_DEBUG) |
---|
270 | { |
---|
271 | PrintS("red:"); |
---|
272 | h->wrp(); |
---|
273 | Print("\nwith T[%d]:",ii); |
---|
274 | strat->T[ii].wrp(); |
---|
275 | } |
---|
276 | #endif |
---|
277 | assume(strat->fromT == FALSE); |
---|
278 | |
---|
279 | //strat->T[ii].pCleardenom(); |
---|
280 | // split T[ii]: |
---|
281 | // remember pLength of strat->T[ii] |
---|
282 | int l_orig=strat->T[ii].pLength; |
---|
283 | // split strat->T[ii] |
---|
284 | poly T_tail=kSplitAt(strat->syzComp,&strat->T[ii],&strat->T[ii].pLength,strat); |
---|
285 | ksReducePoly(h,&(strat->T[ii]),NULL,&A[pass],&C[pass], strat); |
---|
286 | // restore T[ii]: |
---|
287 | kAppend(T_tail,&strat->T[ii]); |
---|
288 | strat->T[ii].pLength=l_orig; |
---|
289 | // store T_tail |
---|
290 | T[pass]=T_tail; |
---|
291 | // delayed computation: A[pass]*tail-M[pass]*T[pass] |
---|
292 | #ifdef KDEBUG |
---|
293 | if (TEST_OPT_DEBUG) |
---|
294 | { |
---|
295 | PrintS("\nto:"); |
---|
296 | h->wrp(); |
---|
297 | PrintLn(); |
---|
298 | } |
---|
299 | #endif |
---|
300 | if(h->IsNull()) |
---|
301 | { |
---|
302 | // clean up A,C,h_tail: |
---|
303 | for(int i=0;i<=pass;i++) |
---|
304 | { |
---|
305 | n_Delete(&A[i],tailRing->cf); |
---|
306 | p_Delete(&C[i],tailRing); |
---|
307 | } |
---|
308 | p_Delete(&h_tail,tailRing); |
---|
309 | kDeleteLcm(h); |
---|
310 | h->Clear(); |
---|
311 | return 0; |
---|
312 | } |
---|
313 | h->SetShortExpVector(); |
---|
314 | not_sev = ~ h->sev; |
---|
315 | h_d = h->SetpFDeg(); |
---|
316 | /* compute the ecart */ |
---|
317 | if (ei <= h->ecart) |
---|
318 | h->ecart = d-h_d; |
---|
319 | else |
---|
320 | h->ecart = d-h_d+ei-h->ecart; |
---|
321 | |
---|
322 | /* |
---|
323 | * try to reduce the s-polynomial h |
---|
324 | *test first whether h should go to the lazyset L |
---|
325 | *-if the degree jumps |
---|
326 | *-if the number of pre-defined reductions jumps |
---|
327 | */ |
---|
328 | pass++; |
---|
329 | d = h_d + h->ecart; |
---|
330 | if (pass%64==0) kBucketCanonicalize(h->bucket); |
---|
331 | } |
---|
332 | } |
---|