1 // Copyright (c) 2007 Alberto Arri 2 3 // This file is part of the source of CoCoALib, the CoCoA Library. 4 5 // CoCoALib is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 10 // CoCoALib is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 15 // You should have received a copy of the GNU General Public License 16 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>. 17 18 #include "CoCoA/SparsePolyOps-RingElem.H" 19 //#include "CoCoA/SparsePolyRing.H" 20 #include "CoCoA/PPMonoidOv.H" 21 #include "CoCoA/symbol.H" 22 #include "CoCoA/TmpF5.H" 23 24 #include <cmath> 25 26 #include <algorithm> 27 #include <utility> 28 #include <numeric> 29 30 #include <vector> 31 #include <list> 32 #include <set> 33 #include <map> 34 #include <queue> 35 36 #include <cassert> 37 #include <ctime> 38 #include <iostream> 39 40 #include <iterator> 41 #include <sstream> 42 43 #include <iomanip> 44 45 46 using namespace std; 47 48 namespace CoCoA{ 49 50 namespace F5ns{ 51 52 class PPdiv_t { 53 typedef PPMonoidElem ppme; 54 int nind; 55 vector<ppme> pp; 56 vector<map<int, vector<int> > > indval; 57 58 public: PPdiv_t(int n)59 PPdiv_t(int n):nind(n),indval(n){} 60 insert(ppme p)61 void insert(ppme p){ 62 vector<long> x; 63 exponents(x,p); 64 pp.push_back(p); 65 int cidx = pp.size() - 1; 66 for(unsigned int i = 0; i < x.size(); i++){ 67 indval[i][x[i]].push_back(cidx); 68 } 69 } 70 71 private: 72 prj2grid(vector<long> & x)73 bool prj2grid(vector<long> &x)const{ 74 for (unsigned int i = 0; i < x.size(); i++){ 75 map<int, vector<int> >::const_iterator it = indval[i].lower_bound(x[i]); 76 //if (it == indval[i].end()) return false; 77 if (it != indval[i].end() && it->first == x[i]) continue; 78 if (it == indval[i].begin()) return false; 79 --it; 80 x[i] = it->first; 81 } 82 return true; 83 } 84 85 public: grid_size()86 long grid_size()const{ 87 long res = 1; 88 for(unsigned int i = 0; i<indval.size(); i++) res *= indval[i].size(); 89 return res; 90 } 91 div(const ppme & p,int lc)92 bool div(const ppme &p, int lc)const{ 93 vector<long> x; 94 exponents(x,p); 95 int o = x[lc]; 96 if (!prj2grid(x)) return false; 97 if (x[lc]!=o) return false; 98 // vector<int> &v = indval[lc][x[lc]]; 99 // cout << "lc = " << lc << ", x[lc] = " << x[lc] << endl; 100 map<int, vector<int> >::const_iterator it = indval[lc].find(x[lc]); 101 assert( it != indval[lc].end() ); 102 const vector<int> &v = it->second; 103 for (unsigned int j = 0; j < v.size(); j++) { 104 if (IsDivisible(p,pp[v[j]])) return true; 105 } 106 return false; 107 108 } 109 }; 110 111 112 class PolyRingElemCmp{ 113 private: 114 const SparsePolyRing& env; 115 const PPMonoid& myPPM; 116 public: PolyRingElemCmp(const SparsePolyRing & e)117 PolyRingElemCmp(const SparsePolyRing &e):env(e),myPPM(PPM(e)){} operator()118 bool operator()(const RingElem &x, const RingElem &y) const { 119 // assert(LPP(x)!=LPP(y)); 120 return myPPM->myCmp(raw(env->myLPP(raw(x))),raw(env->myLPP(raw(y))))<0; 121 } 122 }; 123 124 125 F5opt_t opt; 126 127 struct deg_cmp_t{ operatordeg_cmp_t128 bool operator()(const RingElem &x, const RingElem &y) const { 129 return StdDeg(x)<StdDeg(y); 130 } 131 }; 132 133 PPMonoid *mtPPM = nullptr; 134 135 PPMonoidElem ppe2ppm(const PPMonoidElem &pm, const PPMonoid &ppm = *mtPPM){ 136 vector<long> x; 137 exponents(x,pm); 138 return PPMonoidElem(ppm,x); 139 } 140 141 class module_term_t{ 142 143 public: 144 PPMonoidElem term; 145 146 int index; module_term_t(int i)147 module_term_t(int i):term(*mtPPM), index(i){}; module_term_t(ConstRefPPMonoidElem PPMel,int i)148 module_term_t(ConstRefPPMonoidElem PPMel, int i):term(*mtPPM), index(i){ 149 term = ppe2ppm(PPMel); 150 }; 151 bool operator < (const module_term_t & rhs) const { //REVPOS + TO 152 if (index!=rhs.index) return index<rhs.index; 153 return term<rhs.term; 154 } 155 module_term_t operator * (const PPMonoidElem &rhs) const { return module_term_t( term * ppe2ppm(rhs), index); } 156 bool operator == (const module_term_t &rhs) const { return term == rhs.term && index == rhs.index; } 157 friend ostream &operator <<( ostream &os, const module_term_t &mt); 158 }; 159 160 class labeled_RingElem_t: public RingElem, public module_term_t{ 161 public: labeled_RingElem_t(ConstRefRingElem e,int i)162 labeled_RingElem_t(ConstRefRingElem e, int i):RingElem(e), module_term_t(i) {}; labeled_RingElem_t(ConstRefRingElem e,const module_term_t & mt)163 labeled_RingElem_t(ConstRefRingElem e, const module_term_t &mt):RingElem(e), module_term_t(mt) {}; 164 165 using module_term_t::operator <; 166 }; 167 168 struct row_t{ //inherit order from labels ie module_terms 169 PPMonoidElem LT; //this is the LT of *re 170 mutable bool touched; 171 172 private: 173 mutable RingElem *re; compute_rerow_t174 void compute_re()const{} 175 public: 176 row_trow_t177 row_t(const row_t &r):LT(r.LT){ 178 179 if (r.re) re = new RingElem(*r.re); else re = nullptr; 180 touched=false; 181 } 182 row_trow_t183 row_t(const RingElem *_base, const RefPPMonoidElem& _coeff): 184 LT(owner(_coeff)),re(nullptr){ 185 186 SparsePolyRing env = owner(*_base); 187 re = new RingElem (monomial(env,one(CoeffRing(env)),_coeff) * *_base); 188 LT = LPP(*_base) * _coeff; 189 touched=false; 190 } 191 ~row_trow_t192 ~row_t(){ 193 if (re) delete re; 194 } 195 196 row_t &operator =(const row_t &r){ 197 LT = r.LT; 198 touched=r.touched; 199 if (re) delete re; 200 if (r.re) re = new RingElem(*r.re); else re = nullptr; 201 return *this; 202 } 203 204 row_t &operator *=(const PPMonoidElem &ppme){ 205 LT *= ppme; 206 assert(re); 207 SparsePolyRingPtr(owner(*re))->myMulByPP(raw(*re),raw(ppme)); 208 touched = false; 209 return *this; 210 } 211 elemrow_t212 const RingElem &elem()const{ compute_re(); return *re; } elemrow_t213 RingElem &elem(){ compute_re(); return *re; } 214 215 bool operator <(const row_t &rhs)const{ return LT<rhs.LT; } is_evaluatedrow_t216 bool is_evaluated()const{ return true; } 217 reducerow_t218 bool reduce(const row_t &r){ //returns false when result is Zero 219 assert(LT==r.LT); 220 touched = true; 221 r.touched = true; 222 SparsePolyRingPtr(owner(elem()))->myReductionStep(raw(*re),raw(r.elem())); 223 if (!IsZero(elem())) { 224 LT = LPP(elem()); 225 return true; 226 } else return false; 227 } 228 friend ostream &operator <<( ostream &os, const row_t &r); 229 }; 230 231 ostream &operator <<( ostream &os, const module_term_t &mt){ 232 return os << "(" << mt.term << "," << mt.index << ")"; 233 } 234 235 ostream &operator <<( ostream &os, const row_t &r){ 236 return os << r.elem(); 237 } 238 239 ostream &operator <<( ostream &os, const labeled_RingElem_t &r){ 240 return os << (const module_term_t&)r << " - " << (const RingElem&) r; 241 } 242 243 struct cpair_t{ 244 PPMonoidElem lcm,u1,u2; 245 set<labeled_RingElem_t>::iterator r1,r2; cpair_tcpair_t246 cpair_t(set<labeled_RingElem_t>::iterator &_r1, set<labeled_RingElem_t>::iterator &_r2): 247 lcm( CoCoA::lcm(LPP(*_r1),LPP(*_r2))), 248 u1(PPM(owner(*_r1))), 249 u2(PPM(owner(*_r1))), 250 r1(_r1),r2(_r2) 251 { 252 u1 = lcm / LPP(*r1); 253 u2 = lcm / LPP(*r2); 254 } mtcpair_t255 module_term_t mt(int i)const{ // returns the mt/label of ui*ri 256 assert(i==1 || i==2); 257 if (i==1) return static_cast<const module_term_t&>(*r1)*u1; 258 return static_cast<const module_term_t&>(*r2)*u2; 259 } labelcpair_t260 module_term_t label()const{ 261 return max(mt(1),mt(2)); 262 } degcpair_t263 long deg()const{ return StdDeg(lcm); } 264 }; 265 266 ostream &operator << (ostream &os, const cpair_t &p){ 267 os << p.label() << " " << p.lcm; 268 return os; 269 } 270 271 typedef map<module_term_t,row_t> matrix_t; 272 typedef matrix_t::value_type mmvt_t; //mmvt = map matrix value type = pair<module_term_t,row_t> 273 typedef matrix_t::iterator mit_t; 274 275 ostream &operator <<( ostream &os, const matrix_t &m){ 276 for (matrix_t::const_iterator it = m.begin(); it != m.end(); ++it){ 277 os << it->first << ";\t " << it->second << endl; 278 } 279 return os; 280 } 281 282 class GB_t{ 283 unsigned long maxdeg, npoly; 284 public: 285 int nind; GB_t(int n,int m)286 GB_t(int n, int m):maxdeg(0), npoly(m), nind(n), GB(),lastNRi(-1){}; 287 set<labeled_RingElem_t> GB; 288 typedef set<labeled_RingElem_t>::iterator GBit_t; 289 vector<set<PPMonoidElem> > lt_I_i; //lt_set[i] contains the leading terms of I_i 290 291 vector<set<PPMonoidElem> > lt_Syz_i; //lt_set[i] contains the leading terms of Syz_i \ LT( I_i ) 292 293 vector<PPdiv_t> PPdiv; 294 295 vector<vector<cpair_t> > pairs; 296 LPPinsert(const PPMonoidElem & PPM,unsigned int idx)297 void LPPinsert(const PPMonoidElem &PPM, unsigned int idx){ 298 if (idx >= lt_I_i.size()) { 299 lt_I_i.resize(idx+1); 300 lt_Syz_i.resize(idx+1); //just to keep them the same len 301 } 302 if (idx >= PPdiv.size()){ 303 PPdiv.resize(idx+1,PPdiv_t(nind)); 304 if (idx!=0) PPdiv[idx] = PPdiv[idx-1]; 305 } 306 lt_I_i[idx].insert(PPM); 307 PPdiv[idx].insert(PPM); 308 } 309 Syz_LPPinsert(const PPMonoidElem & PPM,unsigned int idx)310 void Syz_LPPinsert(const PPMonoidElem &PPM, unsigned int idx){ 311 if (idx >= lt_Syz_i.size()) { 312 lt_Syz_i.resize(idx+1); 313 lt_I_i.resize(idx+1); 314 } 315 if (idx >= PPdiv.size()){ 316 PPdiv.resize(idx+1,PPdiv_t(nind)); 317 if (idx!=0) PPdiv[idx] = PPdiv[idx-1]; 318 } 319 lt_Syz_i[idx].insert(PPM); 320 PPdiv[idx].insert(PPM); 321 } 322 323 void NR(RingElem &e, int i = 5000){ 324 // cout << "NR " << i << " " << e; 325 if ( lastNRi != i || (i==5000 && vecGB.size() != GB.size()) ){ 326 // cout << "NR f"; 327 vecGB.clear(); 328 vecGB.reserve(GB.size()); 329 for (GBit_t it = GB.begin(); it != GB.end(); ++it) 330 if (it->index <= i) vecGB.push_back(*it); 331 // copy(GB.begin(),GB.end(),back_inserter(vecGB)); 332 } 333 lastNRi = i; 334 335 e = CoCoA::NR(e, vecGB); 336 // cout << " -> " << e << endl; 337 } 338 339 private: 340 int lastNRi; 341 vector<RingElem> vecGB; 342 add_pair(GBit_t i1,GBit_t i2)343 bool add_pair(GBit_t i1,GBit_t i2){ 344 cpair_t pair(i1,i2); 345 unsigned int deg = pair.deg(); 346 // cout << "add_pair" << pair.mt(1) << "; " << pair.mt(2) << endl; 347 if (pair.mt(1) == pair.mt(2) || is_syz_reducible(pair.mt(1)) || is_syz_reducible(pair.mt(2))) return false; //F5-pair criterion 348 // cout << "ok" << endl; 349 if (deg >= pairs.size()) pairs.resize(deg+1); 350 pairs[deg].push_back(pair); 351 // cout << endl << "Pair in deg = " << deg << endl; 352 return true; 353 } 354 pair_update(GBit_t & in)355 void pair_update(GBit_t &in){ 356 unsigned int mp = max_pair(); 357 PPMonoidElem LPin = LPP(*in); 358 for (GBit_t it = GB.begin(); it!= GB.end(); ++it) if (it!=in) { 359 unsigned int ndeg = StdDeg(lcm(LPP(*it),LPin)); 360 if ( ndeg > mp ) 361 add_pair(it,in); 362 } 363 } 364 public: min_pair()365 unsigned int min_pair()const{ 366 for (unsigned int i = 0; i<pairs.size();i++) if (pairs[i].size()!=0) return i; 367 return 0; //ie pairs is empty 368 } 369 max_pair()370 unsigned int max_pair()const{ 371 if (pairs.size()==0) return 0; 372 for (unsigned int i = pairs.size()-1; i>0; i--) if (pairs[i].size()!=0) return i; 373 return 0; 374 } 375 insert(ConstRefRingElem re,unsigned int pos)376 GBit_t insert(ConstRefRingElem re, unsigned int pos){ 377 GBit_t lit = GB.insert(labeled_RingElem_t(re,pos)).first; 378 if (opt.GBLT2SYZLT) LPPinsert(ppe2ppm(LPP(re)),pos); 379 if (static_cast<unsigned long>(StdDeg(re))>maxdeg) maxdeg = StdDeg(re); 380 pair_update(lit); 381 return lit; 382 } 383 insert(const labeled_RingElem_t & lre)384 GBit_t insert(const labeled_RingElem_t &lre){ 385 pair<GBit_t, bool> in = GB.insert(lre); 386 if (!in.second){//this is tricky. 387 GB.erase(lre); 388 in = GB.insert(lre); 389 assert(in.second); 390 } 391 if (opt.GBLT2SYZLT) LPPinsert(ppe2ppm(LPP(lre)),lre.index); 392 if (static_cast<unsigned long>(StdDeg(lre))>maxdeg) maxdeg = StdDeg(lre); 393 pair_update(in.first); 394 return in.first; 395 } 396 max_deg()397 long max_deg() const { return maxdeg; } 398 is_syz_reducible(const PPMonoidElem & PPE,int index)399 bool is_syz_reducible(const PPMonoidElem &PPE, int index)const{ 400 if (index<0) return false; 401 402 403 assert(static_cast<unsigned int>(index) <= lt_I_i.size()); 404 if (static_cast<unsigned int>(index) < lt_Syz_i.size()) 405 for (set<PPMonoidElem>::const_iterator it = lt_Syz_i[index].begin(); it!= lt_Syz_i[index].end(); ++it) 406 if (IsDivisible(PPE,*it)) return true; 407 408 if (static_cast<unsigned int>(index) < lt_I_i.size()) 409 for (set<PPMonoidElem>::const_iterator it = lt_I_i[index].begin(); it!= lt_I_i[index].end(); ++it) 410 if (IsDivisible(PPE,*it)) return true; 411 412 return false; 413 } 414 is_syz_reducible_gen(const module_term_t & mt,int lc)415 bool is_syz_reducible_gen(const module_term_t& mt, int lc)const{ 416 if (mt.index<1) return false; 417 return PPdiv[mt.index-1].div(mt.term,lc); 418 } 419 is_syz_reducible(const module_term_t & mt)420 bool is_syz_reducible(const module_term_t& mt)const{ return mt.index==0?false:is_syz_reducible(mt.term,mt.index-1);} 421 422 const labeled_RingElem_t *is_reducible(const PPMonoidElem &PPE, int idx = 5000)const{ 423 for (GBit_t it = GB.begin(); it!= GB.end(); ++it) 424 if (it->index <= idx && IsDivisible(PPE, LPP(*it))) return &*it; 425 return nullptr; 426 } 427 LT_print()428 void LT_print(){ 429 for(unsigned int i = 0; i<lt_I_i.size(); i++){ 430 cout << "Set #" << i << " = { "; 431 for (set<PPMonoidElem>::const_iterator it = lt_I_i[i].begin(); it!=lt_I_i[i].end(); ++it){ 432 cout << *it << ", "; 433 } 434 cout << " }" << endl; 435 } 436 } 437 }; 438 439 class matrF5_t{ 440 private: 441 const PPMonoid& myPPM; 442 SparsePolyRing env; 443 public: 444 unsigned int curr_deg,curr_poly,red2zero,n_indets,max_gen_deg; 445 const vector<PPMonoidElem> &PPMindets; 446 vector<PPMonoidElem> mtPPMindets; 447 vector<RingElem> gens; 448 GB_t GB; 449 450 matrF5_t(const vector<RingElem> &I); 451 void do_it(); 452 453 private: 454 void do_poly_step(); 455 map<int, map<int, matrix_t> > matrix_hist; 456 // PPmap<RingElem *> fast_reductor; 457 bool do_deg_step(); 458 459 mmvt_t * matrix_insert_row(matrix_t &mtr, module_term_t mt, row_t row)const; 460 461 bool gen_macaulay_rows(matrix_t &mtr, const set<labeled_RingElem_t>::iterator &set_it, RefPPMonoidElem& ppme, 462 unsigned int d, unsigned int ri = 0); 463 void generate_macaulay( matrix_t &matrix, int mini = -1, int max1 = 5000 ); 464 465 void generate_macaulay_xx( matrix_t &matrix ); 466 467 struct gauss_stat_t{ 468 int r2z,sums; gauss_stat_tgauss_stat_t469 gauss_stat_t():r2z(0),sums(0){}; 470 }; 471 472 gauss_stat_t gauss( matrix_t &m); 473 int pNF(RingElem &p, int idx); 474 map<PPMonoidElem,int> red_frq; 475 }; 476 matrF5_t(const vector<RingElem> & I)477 matrF5_t::matrF5_t(const vector<RingElem> &I): myPPM(PPM(owner(I[0]))), 478 env(owner(I[0])), 479 PPMindets(indets(PPM(owner(I[0])))), 480 gens(I), 481 GB(NumIndets(PPM(owner(I[0]))),I.size()) 482 { 483 red2zero = curr_deg = curr_poly = 0; 484 n_indets = NumIndets(myPPM); 485 486 mtPPM = new PPMonoid(NewPPMonoidOv(symbols(myPPM), StdDegRevLex)); // :( 487 488 mtPPMindets = indets(*mtPPM); 489 490 sort(gens.begin(),gens.end(),deg_cmp_t()); 491 492 for(unsigned int i = 0; i<gens.size(); i++) assert(IsHomog(gens[i])); 493 max_gen_deg = 0; 494 for(unsigned int i=0;i<gens.size();i++) max_gen_deg = max<unsigned int>(max_gen_deg,StdDeg(gens[i])); 495 496 GB.lt_I_i.reserve(gens.size()); 497 498 if (opt.incremental) { GB.insert(gens[0],0); /*fast_reductor[LPP(gens[0])] = &gens[0];*/ } 499 } 500 do_it()501 void matrF5_t::do_it(){ 502 if (opt.verbose) cout << "poly\t" << "deg\t" << "Rows\t" << "CoeffLen\t" << 503 "rsteps\t" << "Ctime\t" << "Gtime\t" << "R2Z\t" << "Sums\t" 504 << "Touched\t" << "New\t" << endl; 505 if (opt.incremental){ 506 curr_poly = 1; 507 while(curr_poly < gens.size()) do_poly_step(); 508 } else {//non inc. 509 GB.lt_I_i.resize(gens.size()); 510 GB.lt_Syz_i.resize(gens.size()); 511 512 // GB.PPdiv.resize(gens.size(),PPdiv_t(GB.nind)); 513 for (unsigned int i=0; i<gens.size();i++) { 514 RingElem pnf(env); //pnf = poly normal form 515 pnf = gens[i]; 516 GB.NR(pnf); 517 GB.insert(pnf,i); 518 gens[i] = pnf; 519 // fast_reductor[LPP(gens[i])] = &gens[i]; 520 } 521 522 curr_poly = gens.size(); 523 curr_deg = 100; 524 for (unsigned int i=0; i<gens.size();i++) curr_deg = min<int>(curr_deg,StdDeg(gens[i])); 525 // GB.pairs.resize(max_gen_deg+1); 526 matrix_t &m = matrix_hist[curr_poly][curr_deg]; 527 528 generate_macaulay(m,0,curr_poly); 529 curr_deg++; 530 531 while(curr_deg <= max(GB.min_pair(),max_gen_deg)) { 532 do_deg_step(); 533 if (opt.verbose) cout << "GBmin = " << GB.min_pair() << endl; 534 if (GB.min_pair()==0) break; 535 } 536 } 537 538 /* 539 for (unsigned int i = 0; i < GB.lt_I_i.size(); i++){ 540 cout << "lt_I_" << i << "\t"; 541 copy(GB.lt_I_i[i].begin(), GB.lt_I_i[i].end() ,ostream_iterator<PPMonoidElem>(cout,", ")); 542 cout << " NPSZ "; 543 copy(GB.lt_Syz_i[i].begin(), GB.lt_Syz_i[i].end() ,ostream_iterator<PPMonoidElem>(cout,", ")); 544 cout << endl; 545 } 546 */ 547 548 // vector<int> frq; 549 // frq.resize(100); 550 // for (map<PPMonoidElem,int>::iterator it = red_frq.begin(); it != red_frq.end(); ++it) frq[it->second]++; 551 // copy(frq.begin(),frq.end(),ostream_iterator<int>(cout, " ")); 552 // cout << endl << accumulate(frq.begin(),frq.end(),0) << endl; 553 } 554 do_poly_step()555 void matrF5_t::do_poly_step(){ 556 RingElem pnf(env); //pnf = poly normal form 557 do { 558 pnf = gens[curr_poly]; 559 GB.NR(pnf); 560 if (IsZero(pnf)) { 561 gens.erase(gens.begin()+curr_poly); 562 if (curr_poly == gens.size()) return; 563 } 564 } while(IsZero(pnf)); 565 566 GB.insert(pnf,curr_poly); 567 curr_deg = StdDeg(pnf); 568 matrix_t &m = matrix_hist[curr_poly][curr_deg]; 569 generate_macaulay(m,opt.skip_rows?curr_poly:0,curr_poly); 570 curr_deg++; 571 while(GB.min_pair()!=0) if (!do_deg_step()) break; 572 matrix_hist[curr_poly].clear(); 573 curr_poly++; 574 } 575 576 struct matrixrow_sorter: public binary_function<bool,mmvt_t *,mmvt_t *>{ 577 const SparsePolyRing &env; 578 const PPMonoid& myPPM; matrixrow_sortermatrixrow_sorter579 matrixrow_sorter(const SparsePolyRing &e):env(e),myPPM(PPM(e)){} operatormatrixrow_sorter580 bool operator () (const mmvt_t *x,const mmvt_t *y){ 581 int cmp = myPPM->myCmp(raw(x->second.LT),raw(y->second.LT)); 582 // if (x->second.LT != y->second.LT) return x->second.LT < y->second.LT; 583 if (cmp!=0) return cmp<0; 584 return !(x->first < y->first); 585 } 586 }; 587 pNF(RingElem & p,int idx)588 int matrF5_t::pNF(RingElem &p, int idx){ 589 const labeled_RingElem_t *rrle = nullptr; 590 int loop_cnt = 0; 591 PPMonoidElem LPPp = LPP(p); 592 593 for(;;){ 594 rrle = GB.is_reducible(LPPp, idx); 595 if (!rrle) return loop_cnt; 596 env->myReductionStep(raw(p),raw(*rrle)); 597 if (IsZero(p)) return loop_cnt; 598 LPPp = LPP(p); 599 loop_cnt++; 600 } 601 602 // while ( (!IsZero(p)) && (rrle = GB.is_reducible(LPPp, idx) )) { 603 // bool didit = false; 604 // //red_frq[LPP(p)]++; 605 // if (opt.prev_red){ 606 // int idl = rrle->index; 607 // for(; idl>=0; idl--) { 608 // map<int, matrix_t>::iterator it = matrix_hist[idl].find(curr_deg); 609 // if (it != matrix_hist[idl].end() ) { 610 // for(mit_t mit = it->second.begin(); mit!=it->second.end(); ++mit) if (!IsZero(mit->second.elem())){ 611 // if (mit->second.LT == LPPp) { 612 // env->myReductionStep(raw(p),raw(mit->second.elem())); 613 // if (IsZero(p)) return loop_cnt; 614 // LPPp = LPP(p); 615 // didit = true; 616 // break; 617 // } 618 // } 619 // if (didit) break; 620 // } 621 // } 622 // } 623 // if (!didit) env->myReductionStep(raw(p),raw(*rrle)); 624 // if (IsZero(p)) return loop_cnt; 625 // LPPp = LPP(p); 626 // loop_cnt++; 627 // } 628 return loop_cnt; 629 } 630 gauss(matrix_t & m)631 matrF5_t::gauss_stat_t matrF5_t::gauss( matrix_t &m) { 632 gauss_stat_t gs; 633 if (m.size() < 1) { if (opt.verbose) cout << "gauss: empty matrix"; return gs; } 634 matrixrow_sorter mrs(env); 635 priority_queue< mmvt_t *, vector<mmvt_t*>, matrixrow_sorter> pq(mrs); 636 int realred = 0, rsteps = 0; 637 long ml = 0; 638 // for (mit_t it = m.begin(); it!=m.end(); ++it) { 639 // for (SparsePolyIter sit = BeginIter(it->second.elem()); sit != EndIter(it->second.elem());++sit) { 640 // ostringstream oss; 641 // oss << coeff(sit); 642 // ml = max(ml,len(oss.str())); 643 // } 644 // } 645 if (opt.verbose) cout << "\t&" << ml; 646 for (mit_t it = m.begin(); it!=m.end(); ++it) { 647 if (opt.skip_rows){ 648 int loop_cnt=0; 649 if (opt.use_NR) GB.NR(it->second.elem(),curr_poly - 1); else loop_cnt=pNF(it->second.elem(),curr_poly - 1); 650 if (loop_cnt!=0 || opt.use_NR) { 651 it->second.touched = true; 652 realred++; 653 rsteps+=loop_cnt; 654 if (IsZero(it->second.elem())) { gs.r2z++; continue; } 655 it->second.LT = LPP(it->second.elem()); 656 } 657 } 658 pq.push(&*it); 659 } 660 // cout << "\t" << realred; 661 if (pq.size() <= 1) { if (opt.verbose) cout << "one liner"; return gs; } 662 do{ 663 mmvt_t *i = pq.top(); 664 pq.pop(); 665 PPMonoidElem cLT = i->second.LT; 666 //???SET BUT NOT USED (JAA,2013-03-13) bool did_loop = false; 667 while ( ( !pq.empty()) && pq.top()->second.LT == cLT ){ 668 //???SET BUT NOT USED (JAA,2013-03-13) did_loop = true; 669 mmvt_t *j = pq.top(); 670 //cout << endl << "P1 = " << i->second.elem() << ";" << endl << "P2 = " << j->second.elem() << endl; 671 pq.pop(); // cout << i->first << " " << j->first << endl; 672 assert(i->first < j->first); //*i has smaller label 673 gs.sums++; 674 if (j->second.reduce(i->second)){ //*i won't be changed 675 assert(j->second.LT < i->second.LT); 676 if (opt.skip_rows && !opt.use_NR) rsteps += pNF(j->second.elem(),curr_poly - 1); 677 if (!IsZero(j->second.elem())) { 678 j->second.LT = LPP(j->second.elem()); 679 assert(j->second.elem()!=0); 680 pq.push(j); 681 } else { gs.r2z++; } 682 } else { gs.r2z++; } //we had a reduction to zero :( 683 } 684 } while(! pq.empty()); 685 if (opt.verbose) cout << "\t&" << rsteps + realred; 686 return gs; 687 } 688 matrix_insert_row(matrix_t & mtr,module_term_t mt,row_t row)689 mmvt_t * matrF5_t::matrix_insert_row(matrix_t &mtr, module_term_t mt, row_t row)const{ 690 mit_t it = mtr.find(mt); 691 692 PPMonoidElem rwc(myPPM); 693 if (it == mtr.end()){ //new row 694 it = mtr.insert(make_pair(mt,row)).first; 695 return &*it; 696 } 697 else return nullptr; 698 return &*it; 699 } 700 gen_macaulay_rows(matrix_t & mtr,const set<labeled_RingElem_t>::iterator & set_it,RefPPMonoidElem & ppme,unsigned int d,unsigned int ri)701 bool matrF5_t::gen_macaulay_rows(matrix_t &mtr, const set<labeled_RingElem_t>::iterator &set_it, 702 RefPPMonoidElem& ppme, 703 unsigned int d, unsigned int ri){ 704 705 if (GB.is_syz_reducible(ppme,set_it->index - 1)) { 706 // cout << "F5 criteria killed " << ppme << " idx " << set_it->index << endl; 707 return false; 708 } 709 if (d == 0) { //try adding row 710 module_term_t mt(ppme, set_it->index); 711 row_t row(&*set_it,ppe2ppm(ppme/set_it->term,myPPM)); 712 return matrix_insert_row(mtr,mt,row); 713 } 714 unsigned int i=d; 715 if (ri != n_indets - 1) { 716 if (gen_macaulay_rows(mtr,set_it,ppme,d,ri+1)) 717 for (i = 1; i<=d; i++) { 718 ppme *= mtPPMindets[ri]; 719 if (!gen_macaulay_rows(mtr,set_it,ppme,d-i,ri+1)) break; 720 } 721 } else { 722 ppme *= power(mtPPMindets[ri],d); 723 gen_macaulay_rows(mtr,set_it,ppme,0,ri+1); 724 i=d; 725 } 726 ppme /= power(mtPPMindets[ri], i>=d ? d : i); 727 return true; 728 } 729 generate_macaulay(matrix_t & matrix,int mini,int maxi)730 void matrF5_t::generate_macaulay( matrix_t &matrix, int mini, int maxi){ 731 if (GB.pairs.size()>=curr_deg) GB.pairs[curr_deg].clear(); 732 for(GB_t::GBit_t it = GB.GB.begin(); it != GB.GB.end(); ++it) if (mini <= it->index && it->index <= maxi){ 733 int delta_deg = curr_deg - StdDeg(*it); 734 PPMonoidElem wt = it->term; 735 if (delta_deg >= 0) gen_macaulay_rows(matrix,it,wt,delta_deg); 736 } 737 } 738 generate_macaulay_xx(matrix_t & matrix)739 void matrF5_t::generate_macaulay_xx( matrix_t &matrix){ 740 if (GB.pairs.size()>=curr_deg) GB.pairs[curr_deg].clear(); 741 matrix_t &oldm = matrix_hist[curr_poly][curr_deg-1]; 742 matrix.clear(); 743 if (!opt.incremental){ 744 for(unsigned int i = 0; i < gens.size(); ++i ) 745 if ((!IsZero(gens[i])) && static_cast<unsigned long>(StdDeg(gens[i])) == curr_deg) { 746 //GB.NR(gens[i], curr_poly - 1); 747 if (!IsZero(gens[i])){ 748 // cout << "New gen " << i << endl; 749 GB_t::GBit_t it = GB.insert(gens[i],i); 750 matrix.insert(mmvt_t(*it,row_t(&*it,PPMonoidElem(myPPM)))); 751 } else { 752 if (opt.verbose) cout << "Gen #" << i << " is useless" << endl; 753 } 754 } 755 } 756 757 RingElem TheOne(one(env)); 758 PPMonoidElem TheId(one(myPPM)); 759 row_t TheOtherOne(&TheOne,TheId); 760 761 for (mit_t it = oldm.begin(); it!=oldm.end(); ++it) if (!IsZero(it->second.elem())) { 762 for (unsigned int i=0; i<n_indets; i++){ 763 module_term_t mt = it->first; 764 assert(static_cast<unsigned long>(StdDeg(it->second.LT)) + 1 == curr_deg); 765 mt.term *= mtPPMindets[i]; 766 if (!GB.is_syz_reducible_gen(mt,i)){ 767 mit_t ip = matrix.find(mt); 768 if (ip==matrix.end()) { //new row/label 769 ip = matrix.insert(mmvt_t(mt,TheOtherOne )).first; 770 //ip = matrix.insert(mmvt_t(mt,it->second )).first; 771 ip->second = it->second; 772 ip->second *= PPMindets[i]; 773 }else { 774 //if (1 + StdDeg(it->second.coeff) <= StdDeg(ip->second.coeff)){ 775 if (PPMindets[i]*it->second.LT < ip->second.LT){ 776 ip->second = it->second; 777 ip->second *= PPMindets[i]; 778 // cout << "** delta = " << 1 + StdDeg(it->second.coeff) << "; Old lt = " << ip->second.LT 779 // << "; NewLT = " << nrw.LT << endl; 780 } //else 781 } 782 // } else { 783 // cout << mt << i << " killed" << endl; 784 }//if us syz etc.. 785 }//end for indet 786 }//end for it 787 oldm.clear(); 788 } 789 do_deg_step()790 bool matrF5_t::do_deg_step(){ 791 matrix_t &matrix = matrix_hist[curr_poly][curr_deg]; 792 if (curr_deg==0) return false; 793 if (opt.verbose) cout << curr_poly << "\t&" << setw(2) << curr_deg; //<< "\t" << GB.pairs[curr_deg].size(); 794 795 // copy(GB.pairs[curr_deg].begin(),GB.pairs[curr_deg].end(),ostream_iterator<cpair_t>(cout, "\n")); 796 clock_t timeb4 = clock(),timeafter; 797 double gtime = 0; 798 generate_macaulay_xx(matrix); 799 if (opt.verbose){ 800 timeafter = clock(); 801 gtime = static_cast<double>(timeafter - timeb4) / CLOCKS_PER_SEC; 802 cout << "\t&" << setw(5) << matrix.size() << flush; 803 // cout << endl << "Before Gauss:" << endl << matrix; 804 timeb4 = clock(); 805 } 806 gauss_stat_t gs = gauss(matrix); 807 if (opt.verbose) { 808 timeafter = clock(); 809 cout << "\t&" << gtime << "\t& " << static_cast<double>(timeafter - timeb4) / CLOCKS_PER_SEC ; 810 } 811 int newel=0,touched=0; 812 if (opt.verbose) cout << " \t&" << gs.r2z << " \t&" << setw(5) << gs.sums << flush; 813 // cout << endl << "After Gauss:" << endl << matrix; 814 815 for( mit_t it = matrix.begin(); it != matrix.end(); ++it) 816 if (it->second.is_evaluated()) { 817 if (it->second.touched) touched++; 818 RingElem &rre = it->second.elem(); 819 if (rre == 0) { 820 GB.Syz_LPPinsert(it->first.term,it->first.index-1); // *non Faugere extension* 821 continue; 822 } 823 if (!GB.is_reducible(LPP(rre))) { 824 // cout << "New poly :" << it->first << " : " << LPP(rre) << endl; 825 newel++; 826 GB.insert(labeled_RingElem_t(rre,it->first)); 827 } 828 // fast_reductor[LPP(rre)] = &it->second.elem(); 829 } 830 if (opt.verbose) cout << "\t& " << setw(5) << touched << "\t& " << newel << "\\\\" << endl; 831 curr_deg++; 832 // if (touched==0) return false; //?? why ?? 833 return true; 834 } 835 836 837 interreduce(vector<RingElem> & v)838 void interreduce(vector<RingElem> &v){ 839 SparsePolyRing env = owner(v[0]); 840 for(unsigned int i = 0; i < v.size(); i++){ 841 vector<RingElem> rl; 842 for(unsigned int j = 0; j < v.size(); j++) if (i!=j && !IsZero(v[j])) rl.push_back(v[j]); 843 v[i] = NR(v[i],rl); 844 } 845 vector<RingElem>::iterator nend = remove(v.begin(),v.end(),zero(env)); 846 v.erase(nend,v.end()); 847 for(unsigned int i = 0; i < v.size(); i++) v[i] /= monomial(env,LC(v[i]),one(PPM(env))); 848 849 } 850 GBtest(vector<RingElem> & v)851 bool GBtest(vector<RingElem> &v){ 852 SparsePolyRing env = owner(v[0]); 853 vector<RingElem> GB = TidyGens(ideal(env,v)); 854 for(unsigned int i = 0; i < GB.size(); i++) GB[i] /= monomial(env,LC(GB[i]),one(PPM(env))); 855 F5ns::PolyRingElemCmp prec(env); 856 if (v.size() != GB.size() ) { cout << "sizes differ"; return false; } 857 sort(GB.begin(),GB.end(),prec); 858 sort(v.begin(),v.end(),prec); 859 // copy(GB.begin(),GB.end(),ostream_iterator<RingElem>(cout,"\n")); 860 // cout << endl << " ^^^^ Real GB. F5GB vvvvv" << endl; 861 // copy(v.begin(),v.end(),ostream_iterator<RingElem>(cout,"\n")); 862 return v == GB; 863 } 864 865 }//end of namespace F5ns 866 F5(vector<RingElem> & GB,const vector<RingElem> & I,const F5ns::F5opt_t &)867 void F5(vector<RingElem> &GB, const vector<RingElem> &I, const F5ns::F5opt_t &/*F5opt*/ ){ 868 869 if (F5ns::opt.verbose) { 870 cout << "F5 starting "; 871 copy(I.begin(),I.end(),ostream_iterator<RingElem>(cout,"\n")); 872 cout << endl; 873 } 874 F5ns::matrF5_t F5i(I); 875 876 F5i.do_it(); 877 GB.clear(); 878 GB.reserve(F5i.GB.GB.size()); 879 if (F5ns::opt.verbose) cout << "GB size = " << F5i.GB.GB.size() << endl; 880 // copy(F5i.GB.GB.begin(),F5i.GB.GB.end(),back_inserter(GB)); 881 GB.insert(GB.end(), F5i.GB.GB.begin(), F5i.GB.GB.end()); 882 883 //check answer 884 if (F5ns::opt.checkGB) { 885 cout << "Checking GB .... " << flush; 886 F5ns::interreduce(GB); 887 cout << (F5ns::GBtest(GB) ? "ok" : "not ok") << endl; 888 } 889 } 890 891 } 892 893 // RCS header/log in the next few lines 894 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/TmpF5Mat.C,v 1.17 2019/03/19 11:07:08 abbott Exp $ 895 // $Log: TmpF5Mat.C,v $ 896 // Revision 1.17 2019/03/19 11:07:08 abbott 897 // Summary: Replaced 0 by nullptr where appropriate 898 // 899 // Revision 1.16 2018/05/18 16:38:51 bigatti 900 // -- added include SparsePolyOps-RingElem.H 901 // 902 // Revision 1.15 2018/03/15 14:39:20 bigatti 903 // -- new file SparsePolyOps-ideal.H 904 // 905 // Revision 1.14 2017/11/10 16:02:27 abbott 906 // Summary: Removed NewLexOrdering, NewStdDegLexOrdering, NewStdDegRevLexOrdering; consequential changes 907 // 908 // Revision 1.13 2014/07/07 14:12:17 abbott 909 // Summary: Corrected silly typo 910 // Author: JAA 911 // 912 // Revision 1.12 2014/07/07 12:51:09 abbott 913 // Summary: Removed AsSparsePolyRing 914 // Author: JAA 915 // 916 // Revision 1.11 2014/04/30 16:14:12 abbott 917 // Summary: Replaced size_t by long 918 // Author: JAA 919 // 920 // Revision 1.10 2014/01/16 16:13:57 abbott 921 // Replaced RingElem(env,0) by zero(env) 922 // 923 // Revision 1.9 2013/03/15 17:49:57 abbott 924 // Commented out unused variable. 925 // 926 // Revision 1.8 2012/10/16 10:15:43 abbott 927 // Replaced RefRingElem by RingElem& (in an old style cast?!?) 928 // 929 // Revision 1.7 2012/01/26 16:47:49 bigatti 930 // -- changed back_inserter into insert 931 // 932 // Revision 1.6 2012/01/26 16:37:10 abbott 933 // Removed an apparently totally pointless CPP symbol definition (NDEBUG). 934 // 935 // Revision 1.5 2008/06/30 17:15:41 abbott 936 // Used const_iterator instead of iterator (where appropriate). 937 // 938 // Revision 1.4 2008/05/30 12:50:31 abbott 939 // Comment out some unused formal parameters (to avoid compiler warnings) 940 // 941 // Revision 1.3 2008/03/12 16:35:18 bigatti 942 // -- changed: IsHomogeneous --> IsHomog 943 // -- changed: ERR:ZeroPoly --> ERR::ZeroRingElem 944 // 945 // Revision 1.2 2007/12/11 14:39:25 bigatti 946 // -- 947 // 948 // Revision 1.1 2007/11/20 10:01:26 bigatti 949 // -- change: TmpF5.C --> TmpF5Mat.C (by Alberto Arri) 950 // -- updated and improved test-F5.C 951 // 952