1 //
2 // FGLMStrategy.cc
3 // PolyBoRi
4 //
5 // Created by Michael Brickenstein on 2008-11-13.
6 // Copyright 2008 The PolyBoRi Team.
7 //
8 #include <exception>
9 #include <polybori/groebner/FGLMStrategy.h>
10 #include <polybori/groebner/nf.h>
11 #include <polybori/groebner/add_up.h>
12 #include <polybori/groebner/interpolate.h>
13 #include <polybori/groebner/draw_matrix.h>
14
15 using namespace std;
16 BEGIN_NAMESPACE_PBORIGB
17
18
19 #if 0
20 static void mult_by_combining_rows(mzd_t* dest, mzd_t* A, packedmatrix* B, packedmatrix* acc1, packedmatrix* acc2, FGLMStrategy::IndexVector& row_is_monomial){
21
22 int i,j;
23 const int m=A->nrows;
24 const int n=A->ncols;
25 //const int nblocks=A->width;
26 mzd_t* res_row=acc1;
27 mzd_t* dest_row=acc2;
28 PBORI_ASSERT(acc1->ncols==B->ncols);
29 PBORI_ASSERT(acc2->ncols==B->ncols);
30 PBORI_ASSERT(dest->nrows==A->nrows);
31 PBORI_ASSERT(dest->ncols==B->ncols);
32
33 for(i=0;i<m;i++){
34 mzd_row_clear_offset(acc1, 0,0);
35 mzd_row_clear_offset(acc2, 0,0);
36 mzd_row_clear_offset(dest,i,0);
37
38 for(j=0;j<n;j+=RADIX){
39 if (mzd_read_block(A,i,j)!=0){
40 const int j_bak=j;
41 for(j=j_bak;(j<j_bak+RADIX) && (j<n);j++){
42 if (mzd_read_bit(A,i,j)==1){
43 int monomial_idx;
44 if ((monomial_idx=row_is_monomial[j])>=0){
45 mzd_write_bit(res_row, 0, monomial_idx, (1+ mzd_read_bit(res_row,0,monomial_idx))%2);
46 } else {
47 mzd_combine(dest_row,0,0,B,j,0,res_row,0,0);
48 std::swap(res_row,dest_row);
49 }
50 }
51 }
52 j=j_bak;
53
54 }
55 }
56
57 //how to do that most efficiently?
58 //copy res_row to dest
59
60 //mzd_row_clear_offset(dest_row,0,0);
61 //mzd_combine(dest,i,0,res_row,0,0,dest_row,0,0);
62
63 mzd_copy_row(dest,i,res_row,0);
64 }
65
66
67 //if 0
68 int i,j;
69 const int m=A->nrows;
70 const int n=A->ncols;
71 mzd_t* res_row=acc1;
72 mzd_t* dest_row=acc2;
73 PBORI_ASSERT(acc1->ncols==B->ncols);
74 PBORI_ASSERT(acc2->ncols==B->ncols);
75 PBORI_ASSERT(dest->nrows==A->nrows);
76 PBORI_ASSERT(dest->ncols==B->ncols);
77 for(i=0;i<m;i++){
78 mzd_row_clear_offset(acc1, 0,0);
79 mzd_row_clear_offset(acc2, 0,0);
80 mzd_row_clear_offset(dest,i,0);
81 for(j=0;j<n;j++){
82 if (mzd_read_bit(A,i,j)){
83 mzd_combine(dest_row,0,0,B,j,0,res_row,0,0);
84 std::swap(res_row,dest_row);
85 }
86 }
87 //how to do that most efficiently?
88 //copy res_row to dest
89
90 //mzd_row_clear_offset(dest_row,0,0);
91 //mzd_combine(dest,i,0,res_row,0,0,dest_row,0,0);
92
93 mzd_copy_row(dest,i,res_row,0);
94 }
95
96 //endif
97
98 }
99 #endif
100
101
setupStandardMonomialsFromTables()102 void FGLMStrategy::setupStandardMonomialsFromTables(){
103
104 standardMonomialsFromVector.resize(varietySize, from);
105 MonomialSet::const_iterator it_set=standardMonomialsFrom.begin();
106 MonomialSet::const_iterator end_set=standardMonomialsFrom.end();
107 //assume only that iteration is descending w.r.t. divisibility
108
109 int i=standardMonomialsFrom.size()-1;
110 while(it_set!=end_set){
111 Monomial m=*it_set;
112 standardMonomialsFrom2Index[m]=i;
113 standardExponentsFrom2Index[m.exp()]=i;
114 standardMonomialsFromVector[i]=m;
115 it_set++;
116 i--;
117 }
118
119 }
120 #if 0
121 void FGLMStrategy::writeTailToRow(MonomialSet tail, mzd_t* row){
122
123 MonomialSet::const_iterator it=tail.begin();
124 MonomialSet::const_iterator end=tail.end();
125 //optimize that;
126 while(it!=end){
127 idx_type tail_idx=standardMonomialsFrom2Index[*it];
128 mzd_write_bit(row,0, tail_idx,1);
129 it++;
130 }
131 }
132 #else
writeTailToRow(MonomialSet tail,mzd_t * row)133 void FGLMStrategy::writeTailToRow(MonomialSet tail, mzd_t* row){
134
135 MonomialSet::exp_iterator it=tail.expBegin();
136 MonomialSet::exp_iterator end=tail.expEnd();
137 //optimize that;
138 while(it!=end){
139 idx_type tail_idx=standardExponentsFrom2Index[*it];
140 mzd_write_bit(row,0, tail_idx,1);
141 it++;
142 }
143 }
144 #endif
writeRowToVariableDivisors(mzd_t * row,Monomial lm)145 void FGLMStrategy::writeRowToVariableDivisors(mzd_t* row, Monomial lm){
146 Monomial::const_iterator it_lm=lm.begin();
147 Monomial::const_iterator end_lm=lm.end();
148 Exponent exp=lm.exp();
149 bool first=true;
150 while(it_lm!=end_lm){
151 idx_type ring_var_index=*it_lm;
152 idx_type our_var_index=ring2Index[ring_var_index];
153 Exponent divided=exp.removeConst(ring_var_index);
154 if (standardMonomialsFrom.owns(divided)){
155 mzd_t* mat=multiplicationTables[our_var_index];
156 size_t divided_index=standardExponentsFrom2Index[divided];
157
158 if (first){
159 monomial2MultiplicationMatrix[lm]=our_var_index;
160 monomial2MultiplicationMatrixRowIndex[lm]=divided_index;
161 first=false;
162 }
163 if (transposed){
164 for(std::size_t j=0;j<varietySize;j++){
165 mzd_write_bit(mat, j, divided_index, mzd_read_bit(row,0,j));
166 }
167 } else {
168
169 /*mzd_t* window=mzd_init_window(mat,divided_index,0,divided_index+1,varietySize);
170 mzd_copy(window,row);
171 mzd_free_window(window);*/
172
173 mzd_copy_row(mat, divided_index, row,0);
174
175 /*for(j=0;j<varietySize;j++){
176 mzd_write_bit(mat, divided_index, j, mzd_read_bit(row,0,j));
177 }*/
178 }
179 }
180 it_lm++;
181 }
182 }
183
transpose_window_to_row(mzd_t * transposed_vec,mzd_t * window)184 void transpose_window_to_row(mzd_t* transposed_vec, mzd_t* window){
185 int i;
186 const int n=window->nrows;
187 for(i=0;i<n;i++){
188 mzd_write_bit(transposed_vec,0,i, mzd_read_bit(window,i,0));
189 }
190 }
rowToPoly(mzd_t * row)191 Polynomial FGLMStrategy::rowToPoly(mzd_t* row){
192 MonomialVector vec;
193 for(std::size_t i=0;i<varietySize;i++){
194 if (mzd_read_bit(row,0,i)==1){
195 vec.push_back(standardMonomialsFromVector[i]);
196 }
197 }
198 return add_up_monomials(vec, to);
199 }
200
setupMultiplicationTables()201 void FGLMStrategy::setupMultiplicationTables(){
202
203 //first we write into rows, later we transpose
204 //algorithm here
205 multiplicationTables.resize(nVariables);
206 tableXRowYIsMonomialFromWithIndex.resize(nVariables);
207 for(std::size_t i=0; i < nVariables;i++){
208 multiplicationTables[i]=mzd_init(varietySize,varietySize);
209 tableXRowYIsMonomialFromWithIndex[i].resize(varietySize);
210 for(std::size_t j=0;j<varietySize;j++){
211 tableXRowYIsMonomialFromWithIndex[i][j]=-1;
212 }
213 }
214
215 //standard monomials
216
217 for(std::size_t i=0;i<standardMonomialsFromVector.size();i++){
218 Monomial m=standardMonomialsFromVector[i];
219 Monomial::const_iterator it=m.begin();
220 Monomial::const_iterator end=m.end();
221 while(it!=end){
222 idx_type ring_var_index=*it;
223 idx_type our_var_index=ring2Index[ring_var_index];
224 Monomial divided=m / Variable(ring_var_index, m.ring());
225 size_t divided_index=standardMonomialsFrom2Index[divided];
226 mzd_t* mat=multiplicationTables[our_var_index];
227 mzd_write_bit(mat, divided_index,i, 1);
228 tableXRowYIsMonomialFromWithIndex[our_var_index][divided_index]=i;
229 //finally treat the "edge" case: m*v->m, where v divides m
230 mzd_write_bit(mat,i,i,1);
231 tableXRowYIsMonomialFromWithIndex[our_var_index][i]=i;
232 it++;
233 }
234
235
236 }
237
238 //leading monomials from gb: vertices/
239 mzd_t* row=mzd_init(1, varietySize);
240 ReductionStrategy::const_iterator start(gbFrom.begin()),
241 finish(gbFrom.end());
242 while (start != finish){
243 Monomial lm = start->lead;
244 MonomialSet tail = start->tail.set();
245 mzd_row_clear_offset(row,0,0);
246 writeTailToRow(tail, row);
247 writeRowToVariableDivisors(row,lm);
248
249 ++start;
250 }
251 mzd_free(row);
252 //edges
253 MonomialSet edges=standardMonomialsFrom.cartesianProduct(varsSet).
254 diff(standardMonomialsFrom).diff(leadingTermsFrom);
255 Polynomial edges_poly=edges;
256 MonomialVector edges_vec(edges.size(), from);
257 std::copy(edges_poly.orderedBegin(), edges_poly.orderedEnd(), edges_vec.begin());
258
259 //reverse is important, so that divisors and elements in the tail have already been treated
260
261
262
263 MonomialVector::reverse_iterator it_edges=edges_vec.rbegin();
264 MonomialVector::reverse_iterator end_edges=edges_vec.rend();
265 edgesUnitedVerticesFrom=edges.unite(leadingTermsFrom);
266
267 mzd_t* multiplied_row=mzd_init(1,varietySize);
268 mzd_t* reduced_problem_to_row=mzd_init(1,varietySize);
269
270 mzd_t* acc1=mzd_init(1, varietySize);
271 mzd_t* acc2=mzd_init(1, varietySize);
272
273 while(it_edges!=end_edges){
274 mzd_row_clear_offset(multiplied_row, 0, 0);
275 Monomial m=*it_edges;
276
277 MonomialSet candidates=Polynomial(edgesUnitedVerticesFrom.divisorsOf(m)).gradedPart(m.deg()-1).set();
278
279 Monomial reduced_problem_to=*(candidates.begin());
280
281 Monomial v_m=m/reduced_problem_to;
282
283 PBORI_ASSERT (v_m.deg()==1);
284 Variable var=*v_m.variableBegin();
285 mzd_t* mult_table=multiplicationTableForVariable(var);
286
287 findVectorInMultTables(reduced_problem_to_row, reduced_problem_to);
288
289 if (!(transposed)){
290
291 //standardMonomialsFrom2Index[reduced_problem_to];
292
293 //highly inefficient/far to many allocations
294
295 //mzd_mul expects second arg to be transposed
296 //which is a little bit tricky as we multiply from left
297 //mzd_t* transposed_mult_table=mzd_transpose(NULL, mult_table);
298
299 //mzd_mul_naiv(multiplied_row,reduced_problem_to_row, mult_table);
300 #if 0
301 mult_by_combining_rows(multiplied_row, reduced_problem_to_row,
302 mult_table, acc1, acc2,tableXRowYIsMonomialFromWithIndex[ring2Index[var.index()]]);
303 #else
304 _mzd_mul_va(multiplied_row, reduced_problem_to_row, mult_table, 1);
305 #endif
306 } else {
307 //mzd_t* transposed_vec=mzd_init(1,varietySize);
308 //PBORI_ASSERT (window->nrows==varietySize);
309 //PBORI_ASSERT (window->ncols==1);
310 //transpose_window_to_row(transposed_vec, window);
311 _mzd_mul_va(multiplied_row, reduced_problem_to_row, mult_table, FALSE);
312 //mzd_free(transposed_vec);
313 }
314
315 writeRowToVariableDivisors(multiplied_row, m);
316 //matrices are transposed, so now we have write to columns
317
318 //mzd_free(transposed_mult_table);
319 //mzd_free_window(window);
320 it_edges++;
321 }
322 mzd_free(reduced_problem_to_row);
323
324 mzd_free(multiplied_row);
325
326 mzd_free(acc1);
327 mzd_free(acc2);
328
329 //transposeMultiplicationTables();
330
331 {
332 #ifdef DRAW_MATRICES
333 for(std::size_t i=0;i<multiplicationTables.size();i++){
334 char matname[255];
335 sprintf(matname,"mult_table%d.png",(int)i);
336
337 draw_matrix(multiplicationTables[i],matname);
338 }
339 #endif
340 }
341 }
findVectorInMultTables(mzd_t * dst,Monomial m)342 void FGLMStrategy::findVectorInMultTables(mzd_t* dst, Monomial m){
343 mzd_t* mat=multiplicationTables[monomial2MultiplicationMatrix[m]];
344 size_t idx=monomial2MultiplicationMatrixRowIndex[m];
345 if (!(transposed))
346 mzd_submatrix(dst, mat, idx, 0, idx+1, varietySize);
347 else{
348 const int n=varietySize;
349 int i;
350 for(i=0;i<n;i++){
351 mzd_write_bit(dst, 0, i, mzd_read_bit(mat,i,idx));
352 }
353 }
354 }
clear_mat(mzd_t * mat)355 void clear_mat(mzd_t* mat) {
356 for(int i = 0; i < mat->nrows; ++i) {
357 mzd_row_clear_offset(mat,i,0);
358 }
359 }
transposeMultiplicationTables()360 void FGLMStrategy::transposeMultiplicationTables(){
361 //From now on, we multiply, so here we transpose
362 mzd_t* new_mat=mzd_init(varietySize,varietySize);
363 mzd_t* swap;
364 for(std::size_t i=0;i<multiplicationTables.size();i++){
365 //unnecassary many allocations of matrices
366 //mzd_t* new_mat=mzd_init(varietySize,varietySize);
367 clear_mat(new_mat);
368 mzd_transpose(new_mat, multiplicationTables[i]);
369
370 swap=new_mat;
371 new_mat=multiplicationTables[i];
372 multiplicationTables[i]=swap;
373 //mzd_free(new_mat);
374
375 }
376 mzd_free(new_mat);
377 transposed=(!(transposed));
378 }
analyzeGB(const ReductionStrategy & gb)379 void FGLMStrategy::analyzeGB(const ReductionStrategy& gb){
380
381 vars=gb.leadingTerms.usedVariables();
382 for (std::size_t i=0;i<gb.size();i++){
383 vars=vars * Monomial(gb[i].usedVariables, from);
384 }
385
386 Monomial::variable_iterator it_var=vars.variableBegin();
387 Monomial::variable_iterator end_var=vars.variableEnd();
388 while (it_var!=end_var){
389 varsVector.push_back(*it_var);
390 it_var++;
391 }
392 VariableVector::reverse_iterator it_varvec=varsVector.rbegin();
393 VariableVector::reverse_iterator end_varvec=varsVector.rend();
394 while(it_varvec!=end_varvec){
395 varsSet=varsSet.unite(Monomial(*it_varvec).diagram());
396 it_varvec++;
397 }
398
399
400 nVariables=vars.size();
401 ring2Index.resize(from.nVariables());
402 index2Ring.resize(nVariables);
403 idx_type ring_index;
404 idx_type our_index=0;
405 Monomial::const_iterator it=vars.begin();
406 Monomial::const_iterator end=vars.end();
407 while(it!=end){
408 ring_index=*it;
409 ring2Index[ring_index]=our_index;
410 index2Ring[our_index]=ring_index;
411
412 our_index++;
413 it++;
414 }
415
416 standardMonomialsFrom=mod_mon_set(vars.divisors(), gb.leadingTerms);
417
418 leadingTermsFrom=gb.leadingTerms;
419 varietySize=standardMonomialsFrom.size();
420 }
421
422 class FGLMNoLinearCombinationException: public std::exception
423 {
424 public:
425 size_t firstNonZeroIndex;
FGLMNoLinearCombinationException(size_t firstNonZeroIndex)426 FGLMNoLinearCombinationException(size_t firstNonZeroIndex){
427 this->firstNonZeroIndex=firstNonZeroIndex;
428 }
429 };
430 #if 0
431 FGLMStrategy::IndexVector FGLMStrategy::rowVectorIsLinearCombinationOfRows(mzd_t* mat, mzd_t* v){
432 //returns vector with indices, where the coefficients in this linear combination are 1
433 //if no such combination exists, raises Exception
434 #ifdef DRAW_MATRICES
435 static int round=0;
436 round++;
437 PBORI_ASSERT (mat->ncols==varietySize);
438 PBORI_ASSERT (v->ncols==varietySize);
439 PBORI_ASSERT (v->nrows==1);
440 #endif
441 mzd_t* row_combined=mzd_stack(NULL, mat, v);
442 {
443 #ifdef DRAW_MATRICES
444 char matname[255];
445 sprintf(matname,"row_combined%d.png",round);
446
447 draw_matrix(row_combined,matname);
448 #endif
449 }
450 mzd_t* col_combined=mzd_transpose(NULL, row_combined);
451 mzd_free(row_combined);
452
453 mzd_echelonize_m4ri(col_combined,TRUE,0,NULL,NULL);
454 {
455 #ifdef DRAW_MATRICES
456 char matname[255];
457 sprintf(matname,"col_reduced%d.png",round);
458
459 draw_matrix(col_combined,matname);
460 #endif
461 }
462 const int cols=col_combined->ncols;
463 const int rows=col_combined->nrows;
464 PBORI_ASSERT (rows>=cols-1);
465 const int ngenerators=cols-1;
466 const int last_col=cols-1;
467 int i;
468 IndexVector res;
469
470 //first col-1 cols are linear independend -> reduced row echelon form has unimat het
471 for(i=rows-1;i>ngenerators-1;i--){
472 PBORI_ASSERT(i>=last_col);
473 if (mzd_read_bit(col_combined,i,last_col)==1){
474 //no inhomgeneous solution exists
475 mzd_free(col_combined);
476 FGLMNoLinearCombinationException ex;
477 throw ex;
478
479 }
480 }
481 for(i=ngenerators-1;i>=0;i--){
482 PBORI_ASSERT(i<last_col);
483 if (mzd_read_bit(col_combined,i, last_col)==1){
484 PBORI_ASSERT(mzd_read_bit(col_combined,i,i)==1);
485 res.push_back(i);
486 }
487 }
488 mzd_free(col_combined);
489
490 return res;
491 }
492 #else
rowVectorIsLinearCombinationOfRows(mzd_t * mat,mzd_t * v)493 FGLMStrategy::IndexVector FGLMStrategy::rowVectorIsLinearCombinationOfRows(mzd_t* mat, mzd_t* v){
494 const int d=mat->nrows-1;
495 mzd_row_clear_offset(mat,d,0);
496 PBORI_ASSERT (mat->ncols==2*varietySize);
497
498 //mzd_t* copy_v_into=mzd_init_window(mat,d,0,d+1,varietySize);
499 //mzd_copy(copy_v_into,v);
500 //mzd_free_window(copy_v_into);
501
502 mzd_copy_row(mat,d,v,0);
503 //mzd_row_clear_offset(mat,d,varietySize);//might be random data at the end as mat is wider
504
505
506 for(std::size_t i=0;i<varietySize;i++){
507 if (mzd_read_bit(mat,d,i)==1){
508 bool succ=false;
509 int row_idx=rowStartingWithIndex[i];
510 if (row_idx>=0){
511 succ=true;
512 int standard_idx;
513 if ((standard_idx=rowIsStandardMonomialToWithIndex[row_idx])>=0){
514 mzd_write_bit(mat,d,i,0);
515 const int standard_idx_with_offset=varietySize+standard_idx;
516 mzd_write_bit(mat,d,standard_idx_with_offset,(1+mzd_read_bit(mat,d,standard_idx_with_offset))%2);
517 } else {
518 mzd_row_add_offset(mat, d, row_idx, i);
519 }
520
521 }
522
523 if (!(succ)){
524 FGLMNoLinearCombinationException ex(i);
525 throw ex;
526
527 }
528 }
529 }
530 IndexVector res;
531 for(int i=0;i<d;i++){
532 if (mzd_read_bit(mat,d,i+varietySize)==1){
533 res.push_back(i);
534 }
535 }
536 return res;
537 }
538 #endif
main()539 PolynomialVector FGLMStrategy::main(){
540 PolynomialVector F;
541 const Monomial monomial_one(to);
542
543 if (leadingTermsFrom.owns(monomial_one)){
544 F.push_back(monomial_one);
545 return F;
546 }
547 //variables are oriented at Tim Wichmanns Diploma thesis
548
549 mzd_t* acc1=mzd_init(1, varietySize);
550 mzd_t* acc2=mzd_init(1, varietySize);
551
552
553 typedef std::set<Monomial> MonomialSetSTL;
554
555 MonomialSetSTL C;
556
557 lm2Index_map_type mon2index;
558 Exponent::idx_map_type exp2index;
559 //initialize with one monomial
560 mzd_t* v=mzd_init(varietySize, varietySize);//write vectors in rows;
561 mzd_t* w=mzd_init(varietySize+1, varietySize*2);
562 IndexVector w_start_indices;
563 rowStartingWithIndex.resize(varietySize);
564 rowIsStandardMonomialToWithIndex.resize(varietySize);
565 for(std::size_t i=0;i<rowStartingWithIndex.size();i++){
566 rowStartingWithIndex[i]=-1;
567 rowIsStandardMonomialToWithIndex[i]=-1;
568 }
569 MonomialSet b_set=monomial_one.set();
570 MonomialVector b;
571 b.push_back(monomial_one);
572 mzd_write_bit(v,0,0,1);
573 mzd_write_bit(w,0,0,1);
574 mzd_write_bit(w,0,varietySize+0,1);
575 w_start_indices.push_back(0);
576 rowStartingWithIndex[0]=0;
577 rowIsStandardMonomialToWithIndex[0]=0;
578
579 VariableVector varsVectorTo;
580 varsVectorTo.reserve(varsVector.size());
581 for(std::size_t i=0;i<varsVector.size();i++){
582 varsVectorTo.push_back(to.coerce(varsVector[i]));
583 C.insert(varsVectorTo.back());
584 }
585
586 mon2index[monomial_one]=0;
587 exp2index[monomial_one.exp()]=0;
588 mzd_t* v_d=mzd_init(1,varietySize);
589
590 while(!(C.empty())){
591 const int d=b.size();
592 Monomial m=*(C.begin());
593
594 C.erase(C.begin());
595
596 PBORI_ASSERT(m!=monomial_one);
597 Polynomial divisors(to);
598 PBORI_ASSERT(b_set.containsDivisorsOfDecDeg(m)==(Polynomial(b_set.divisorsOf(m)).gradedPart(m.deg()-1).length()==m.deg()));
599 if (b_set.containsDivisorsOfDecDeg(m)/*varsM=Zm,Ecke oder Standard Monom*/) {
600 Polynomial divisors=Polynomial(b_set.divisorsOf(m)).gradedPart(m.deg()-1);
601 mzd_row_clear_offset(v_d,0,0);
602 PBORI_ASSERT(varietySize>0);
603 bool is_standard_monomial_from=false;
604
605 if (edgesUnitedVerticesFrom.owns(m)){
606 findVectorInMultTables(v_d, m);
607 } else {
608 if (standardMonomialsFrom.owns(m)){
609 mzd_write_bit(v_d,0, standardMonomialsFrom2Index[m],1);
610 is_standard_monomial_from=true;
611 } else{
612 Exponent b_j=*divisors.expBegin();
613 int j=exp2index[b_j];
614 Exponent x_i_m=(m.exp()-b_j);
615 PBORI_ASSERT (x_i_m.deg()==1);
616 //Variable x_i=*x_i_m.variableBegin();
617 idx_type our_x_i_index=ring2Index[*x_i_m.begin()];
618 mzd_t* mult_table=multiplicationTables[our_x_i_index];//multiplicationTableForVariable(x_i);
619 mzd_t* v_j=mzd_init_window(v,j,0,j+1,varietySize);
620
621 PBORI_ASSERT (v_j->nrows==1);
622 PBORI_ASSERT ( v_j->ncols==varietySize);
623 if (transposed)
624 v_d=_mzd_mul_va(v_d, v_j, mult_table, FALSE);
625 else{
626 #if 0
627 mult_by_combining_rows(v_d, v_j, mult_table, acc1, acc2, tableXRowYIsMonomialFromWithIndex[our_x_i_index]);
628 #else
629 _mzd_mul_va(v_d, v_j, mult_table, 1);
630 #endif
631 }
632 mzd_free_window(v_j);
633 }
634
635 }
636
637 PBORI_ASSERT (v_d->nrows==1);
638 PBORI_ASSERT (v_d->ncols==varietySize);
639 mzd_t* w_window=mzd_init_window(w,0,0,d+1,2*varietySize);
640 //mzd_t* w_row_window=mzd_init_window(w,d,0,d+1,varietySize);
641 try
642 {
643
644
645 IndexVector lin_combination=rowVectorIsLinearCombinationOfRows(w_window, v_d);
646 MonomialVector p_vec;
647 for(std::size_t i=0;i<lin_combination.size();i++){
648 PBORI_ASSERT (lin_combination[i]<b.size());
649 p_vec.push_back(b[lin_combination[i]]);
650 }
651 Polynomial p=add_up_monomials(p_vec, to.zero())+m;
652 F.push_back(p);
653
654
655 }
656 catch (FGLMNoLinearCombinationException& e)
657 {
658
659 b_set=b_set.unite(m.diagram());
660 b.push_back(m);
661
662 rowStartingWithIndex[e.firstNonZeroIndex]=d;
663 mzd_write_bit(w,d,varietySize+d,1);
664 if (is_standard_monomial_from){
665 std::size_t from_idx=standardMonomialsFrom2Index[m];
666 if (e.firstNonZeroIndex==from_idx){
667 //we assume, the row is untached
668 rowIsStandardMonomialToWithIndex[d]=d;
669 //might swap rows and use a vector of bools
670 } else {
671 const int reduced_with_this_row=rowStartingWithIndex[from_idx];
672 PBORI_ASSERT(reduced_with_this_row>=0);
673 mzd_row_clear_offset(w, reduced_with_this_row,0);
674 mzd_write_bit(w, reduced_with_this_row, from_idx,1);
675 mzd_write_bit(w, reduced_with_this_row, varietySize+d,1);
676 rowIsStandardMonomialToWithIndex[reduced_with_this_row]=d;
677 //still generate the same vector space
678 }
679 }
680 /*mzd_t* copy_window=mzd_init_window(v,d,0,d+1,varietySize);
681 mzd_copy(copy_window, v_d);
682 mzd_free_window(copy_window);*/
683 mzd_copy_row(v,d,v_d,0);
684
685 idx_type m_begin=*m.begin();
686 for(std::size_t i=0;(i<varsVectorTo.size())&&(index2Ring[i]<m_begin);i++){
687 Variable var=varsVectorTo[i];
688 if (!(m.reducibleBy(var))){
689 Monomial m_v= var*m;
690 C.insert(m_v);
691 }
692 }
693 mon2index[m]=b.size()-1;
694 exp2index[m.exp()]=b.size()-1;
695 }
696
697 mzd_free_window(w_window);
698 }
699
700 }
701 mzd_free(w);
702 mzd_free(v_d);
703 mzd_free(v);
704
705 for(std::size_t i=0;i<addTheseLater.size();i++){
706 F.push_back(to.coerce(addTheseLater[i]));
707 }
708
709 mzd_free(acc1);
710 mzd_free(acc2);
711
712 #ifndef PBORI_NDEBUG
713 for (std::size_t idx = 0; idx < F.size(); ++idx) {
714 PBORI_ASSERT(to.id() == F[idx].ring().id());
715 }
716 #endif
717
718 return F;
719 }
720
testMultiplicationTables()721 void FGLMStrategy::testMultiplicationTables(){
722 #ifndef PBORI_NDEBUG
723
724 for(std::size_t i=0;i<varsVector.size();i++){
725 Variable v=varsVector[i];
726 PBORI_ASSERT (v.index()>=i);
727 for (std::size_t j=0;j<standardMonomialsFromVector.size(); j++){
728 Monomial m=standardMonomialsFromVector[j];
729 mzd_t* table=multiplicationTableForVariable(v);
730 if (m==v){continue;}
731
732 Polynomial product=reducedNormalFormInFromRing(m*v);
733
734 MonomialSet product_set=product.diagram();
735 Polynomial sum(0, product.ring());
736 for(std::size_t k=0;k<varietySize;k++){
737 Monomial m2=standardMonomialsFromVector[k];
738
739 if (mzd_read_bit(table,j,k)==1){
740 sum+=m2;
741 }
742
743 }
744 if (sum!=product)
745 cout<<"v:"<<v<<"\tm:"<<m<<"\tsum:"<<sum<<"\tproduct:"<<product<<endl;
746 PBORI_ASSERT(sum==product);
747 }
748 }
749 #endif
750 }
reducedNormalFormInFromRing(Polynomial f)751 Polynomial FGLMStrategy::reducedNormalFormInFromRing(Polynomial f){
752 Polynomial res=gbFrom.reducedNormalForm(f);
753 return res;
754 }
755
canAddThisElementLaterToGB(Polynomial p)756 bool FGLMStrategy::canAddThisElementLaterToGB(Polynomial p){
757 Monomial lm_from=from.ordering().lead(p);
758 size_t length=p.length();
759 if ((lm_from.deg()==1)&& ((length==1)||((length==2) && (p.hasConstantPart())))){
760 return true;
761 }/*
762 if (lm_from.deg()==1){
763 Monomial lm_to=to.ordering().lead(p);
764 if (lm_from==lm_to){
765 return true;
766 }
767 }*/
768 return false;
769 }
FGLMStrategy(const ring_with_ordering_type & from_ring,const ring_with_ordering_type & to_ring,const PolynomialVector & gb)770 FGLMStrategy::FGLMStrategy(const ring_with_ordering_type& from_ring, const ring_with_ordering_type& to_ring, const PolynomialVector& gb)
771 : vars(from_ring),
772
773 standardMonomialsFrom(from_ring),
774 leadingTermsFrom(from_ring),
775 varsSet(from_ring),
776 gbFrom(from_ring), edgesUnitedVerticesFrom(from_ring), from(from_ring), to(to_ring){
777
778 prot=false;
779 transposed=false;
780
781 PolynomialVector::const_iterator it=gb.begin();
782 PolynomialVector::const_iterator end=gb.end();
783
784 while(it!=end){
785 Polynomial gen=*it;
786 if (canAddThisElementLaterToGB(gen)){
787 addTheseLater.push_back(gen);
788 } else{
789 this->gbFrom.addGenerator(gen);
790 }
791 it++;
792 }
793
794 Monomial monomial_one(from_ring);
795 if (prot)
796 cout<<"analyzing gb..."<<endl;
797 analyzeGB(this->gbFrom);
798 if (!(this->gbFrom.leadingTerms.owns(monomial_one))){
799 //cout<<standardMonomialsFrom2Index[monomial_one]<<endl;
800
801 if (prot){
802 cout<<"varietySize:"<<varietySize<<endl;
803 cout<<"standard monomials tables..."<<endl;
804 }
805 setupStandardMonomialsFromTables();
806 if (prot)
807 cout<<"multiplication tables..."<<endl;
808 setupMultiplicationTables();
809
810 #ifndef PBORI_NDEBUG
811 if (prot)
812 cout<<"test multiplication table..."<<endl;
813 testMultiplicationTables();
814 #endif
815 PBORI_ASSERT(standardMonomialsFrom2Index[monomial_one]==0);
816 }
817 if (prot)
818 cout<<"initialization finished"<<endl;
819 }
820
821
822 END_NAMESPACE_PBORIGB
823