1 // Copyright (c) 2015 Mario Albert 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/TmpJBAlgorithm.H" 19 #include "CoCoA/TmpGOperations.H" 20 #include "CoCoA/FractionField.H" 21 22 23 namespace CoCoA 24 { 25 namespace Involutive 26 { 27 using std::make_pair; 28 using std::pair; 29 using std::vector; 30 myTrivialIdeal()31 void TQAlgorithm::myTrivialIdeal() { 32 myJTree.myDelete(); 33 myGetSets().myClearSets(); 34 JanetTriple trivalTriple(one(myPolyRing)); 35 myGetSets().myInsertSetT(trivalTriple); 36 } 37 myComputer(std::vector<RingElem>::const_iterator beginInput,std::vector<RingElem>::const_iterator endInput)38 void DegreeTQ::myComputer(std::vector<RingElem>::const_iterator beginInput, 39 std::vector<RingElem>::const_iterator endInput) { 40 //initialization of janet-triples 41 myInitialization(beginInput, endInput); 42 43 std::list<JanetTriple>::iterator iter(mySets.myMinimizeAndInsertSetT(myJTree)); 44 //exit if there is a constant input 45 // ?????? 46 if (IsConstant(iter->myGetPol())) { 47 myTrivialIdeal(); 48 return; 49 } 50 // adding first element to janet tree 51 JanetTree tree(JanetTree::OneLeafTree(myPolyRing, iter, 0, one(myPPMValue))); 52 myJTree.myAddAtBegin(tree); 53 //main loop 54 while (mySets.myHeadReduceSetQ(myJTree)) { 55 long SizeT(mySets.mySizeSetT()); 56 //insert element to setT and minimize setT 57 std::list<JanetTriple>::iterator iter(mySets.myMinimizeAndInsertSetT(myJTree)); 58 // exit if we get a constant element 59 if (IsConstant(iter->myGetPol())) { 60 myTrivialIdeal(); 61 return; 62 } 63 //if we 'lost' an element in setT rebuild janet tree 64 //otherwise add new element to setT and tailreduce setT 65 if (mySets.mySizeSetT() <= SizeT) { 66 myJTree.myDelete(); 67 for (TQSets::MultisetIterator IterT(mySets.myBeginSetT()); IterT != mySets.myEndSetT(); ++IterT) { 68 std::list<JanetTriple>::iterator ListIter(*IterT); 69 mySets.myJTailNormalForm(myJTree, ListIter); 70 mySets.myJInsert(ListIter, myJTree); 71 } 72 } else { 73 mySets.myJInsert(iter, myJTree); 74 mySets.myTailReduceSetT(myJTree, iter); 75 } 76 } 77 } 78 myOutputResult()79 JanetContainer TQAlgorithm::myOutputResult() 80 { 81 std::list<JanetTriple> jBasis; 82 for (TQSets::MultisetIterator IterT(myGetSets().myBeginSetT()); IterT != myGetSets().myEndSetT(); ++IterT) { 83 jBasis.push_back(*(*IterT)); 84 } 85 return JanetContainer(myPolyRing, jBasis); 86 } 87 myInitialization(std::vector<RingElem>::const_iterator beginInput,std::vector<RingElem>::const_iterator endInput)88 void TQAlgorithm::myInitialization(std::vector<RingElem>::const_iterator beginInput, 89 std::vector<RingElem>::const_iterator endInput) { 90 //initialization 91 for (std::vector<RingElem>::const_iterator iter = beginInput; iter != endInput; ++iter) { 92 if (IsZero(*iter)) { 93 continue; 94 } 95 RingElem elem(*iter); 96 if (IsFractionField(CoeffRing(myPolyRing))) { 97 // myPolyRing->myDivByCoeff(raw(*iter),raw(LC(*iter))); 98 myPolyRing->myDivByCoeff(raw(elem), raw(LC(elem))); 99 elem = ClearDenom(elem); 100 } 101 JanetTriple triple(elem, myPolyRing->myLPP(raw(elem))); 102 myGetSets().myInsertSetQ(triple); 103 } 104 } 105 myComputer(std::vector<RingElem>::const_iterator beginInput,std::vector<RingElem>::const_iterator endInput)106 void BlockTQ::myComputer(std::vector<RingElem>::const_iterator beginInput, 107 std::vector<RingElem>::const_iterator endInput) { 108 //initialization 109 myInitialization(beginInput, endInput); 110 std::list<JanetTriple>::iterator iter(mySets.myMinimizeAndInsertSetT(myJTree)); 111 //return if constant input 112 if (IsConstant(iter->myGetPol())) { 113 myTrivialIdeal(); 114 return; 115 } 116 JanetTree tree(JanetTree::OneLeafTree(myPolyRing, iter, 0, one(myPPMValue))); 117 myJTree.myAddAtBegin(tree); 118 //main loop 119 while (!mySets.IamEmptySetQ()) { 120 //construct mySetP 121 mySets.myMoveFromQtoP(myJTree); 122 // update mySetP 123 bool ModifySetT = mySets.IamJUpdate(); 124 // if mySetP empty continue 125 if (mySets.myBeginSetP() == mySets.myEndSetP()) { 126 continue; 127 } 128 if (ModifySetT) { 129 //recompute janettree 130 long SizeT(mySets.mySizeSetT()); 131 mySets.myMinimizeSetT(); 132 if (mySets.mySizeSetT() < SizeT) { 133 myJTree.myDelete(); 134 for (TQSets::MultisetIterator IterT(mySets.myBeginSetT()); IterT != mySets.myEndSetT(); ++IterT) { 135 std::list<JanetTriple>::iterator ListIter(*IterT); 136 mySets.myJInsert(ListIter, myJTree); 137 } 138 } 139 // mySets.myTailReduceSetTAll(myJTree); 140 } 141 TQSets::MultisetIterator IterP = mySets.myEndSetP(); 142 //constant input -> retun 143 if (IsConstant((*(mySets.myBeginSetP()))->myGetPol())) { 144 myTrivialIdeal(); 145 return; 146 } 147 // insert elements from mySetP into janet tree 148 do { 149 --IterP; 150 std::list<JanetTriple>::iterator ListIter(*IterP); 151 // mySets.myJTailNormalForm(myJTree, ListIter); 152 mySets.myJInsert(ListIter, myJTree); 153 } while (IterP != mySets.myBeginSetP()); 154 //tail reduce set T if necessary 155 // if (!ModifySetT) { 156 // mySets.myTailReduceSetTAll(myJTree); 157 // } 158 mySets.myInsertSetPInSetT(); 159 mySets.myTailReduceSetTAll(myJTree); 160 } 161 } 162 myBuildInitialTree(std::vector<RingElem>::const_iterator beginInput,std::vector<RingElem>::const_iterator endInput)163 void CompletionGB::myBuildInitialTree(std::vector<RingElem>::const_iterator beginInput, 164 std::vector<RingElem>::const_iterator endInput) { 165 std::vector<RingElem> inputVec(beginInput, endInput); 166 std::vector<RingElem> groebnerBasis; 167 std::vector<RingElem> minGens; 168 // computation of GBasis 169 ComputeGBasis(groebnerBasis, minGens, inputVec); 170 // if GBasis is one our ideal is trivial an we can skip everything else. 171 if(groebnerBasis.size() == 1 && IsConstant(groebnerBasis[0])) 172 { 173 myJBasis.push_front(JanetTriple(one(myPolyRing))); 174 return; 175 } 176 // add GBasis to JanetTree and JBasis 177 // for(std::vector<RingElem>::iterator i = groebnerBasis.begin(); i != groebnerBasis.end(); ++i) 178 for (const RingElem& g: groebnerBasis) 179 { 180 myJBasis.push_front(JanetTriple(g)); 181 myJTree.myInsert(myJBasis.begin()); 182 } 183 } 184 myElemIsNonMultForIndex(const PPMonoidElem & m,long index)185 bool CompletionGB::myElemIsNonMultForIndex(const PPMonoidElem& m, long index) 186 { 187 CoCoA_ASSERT(NumIndets(myPolyRing) > index); 188 CoCoA_ASSERT(index >= 0); 189 JanetIterator iter(myJTree); 190 std::vector<long> expv; 191 exponents(expv, m); 192 193 while(iter.myCurrentVar() < index) { 194 while(iter.myCurrentDeg() < expv[iter.myCurrentVar()]) 195 { 196 long degDis(iter.myNextDeg()); 197 (void) degDis; 198 CoCoA_ASSERT(degDis > 0); 199 } 200 CoCoA_ASSERT(iter.myCurrentDeg() == expv[iter.myCurrentVar()]); 201 long varDis(iter.myNextVar()); 202 if (varDis == 0) { 203 return true; 204 } 205 CoCoA_ASSERT(varDis > 0); 206 } 207 if(iter.myCurrentVar() > index) { 208 CoCoA_ASSERT(expv[index] == 0); 209 return true; 210 } 211 while(iter.myNextDeg() != 0) { /* do nothing */ } 212 CoCoA_ASSERT(iter.myCurrentVar() == index); 213 CoCoA_ASSERT(iter.myCurrentDeg() >= expv[index]); 214 return iter.myCurrentDeg() != expv[index]; 215 } 216 myComputer(std::vector<RingElem>::const_iterator beginInput,std::vector<RingElem>::const_iterator endInput)217 void CompletionGB::myComputer(std::vector<RingElem>::const_iterator beginInput, std::vector<RingElem>::const_iterator endInput) { 218 // first build initial JTree out of GBasis 219 myBuildInitialTree(beginInput, endInput); 220 // skip everything if the ideal is trivial 221 if(myJBasis.size() == 1 && IsConstant(myJBasis.front().myGetPol())) 222 { 223 return; 224 } 225 // iterating over number of vars 226 for(long i = 0; i != NumIndets(myPolyRing); ++i) 227 { 228 elemPairList prolongSet; 229 // identify elements for which i is nonmultiplicative 230 // if it is the case add a prolongation 231 // for(std::list<JanetTriple>::iterator iter = myJBasis.begin(); iter != myJBasis.end(); ++iter) 232 for (const JanetTriple& JT: myJBasis) 233 { 234 if (myElemIsNonMultForIndex(LPP(JT.myGetPol()), i)) 235 myPushToProlongList(prolongSet, JT.myGetPol() * indet(myPolyRing, i), LPP(JT.myGetPol())); 236 } 237 238 // sort the prolongSet after LPP of elemPair.first 239 prolongSet.sort(myLPPComparison); 240 // repeat until prolongSet is empty 241 while(!prolongSet.empty()) { 242 elemPair pair(prolongSet.front()); 243 // if pair has no involutive divisor add this element to JBasis 244 // after that remove the current element from the prolongSet 245 // and add new ones which arises from the newly inserted element 246 if(myJTree.myJDivisor(LPP(pair.first)) == 0) 247 { 248 myJBasis.push_front(JanetTriple(pair.first, pair.second)); 249 // std::cout << "new_jb_elem = " << pair.first << std::endl; 250 // if the new element would be not a leaf node we have to remove 251 // everything behind it. 252 if(myJTree.IamInternalNode(LPP(pair.first))) { 253 std::vector<nodeData> removedNodes(myJTree.myInsertInTreeStructure(myJBasis.begin())); 254 // for (std::vector<nodeData>::iterator remove = removedNodes.begin(); remove != removedNodes.end(); ++remove) { 255 for (const nodeData& remove: removedNodes) 256 myJBasis.erase(remove); 257 } else { 258 myJTree.myInsert(myJBasis.begin()); 259 } 260 prolongSet.pop_front(); 261 if(myElemIsNonMultForIndex(LPP(pair.first), i)) { 262 myInsertToProlongList(prolongSet, pair.first * indet(myPolyRing, i), pair.second); 263 } 264 } else { 265 prolongSet.pop_front(); 266 } 267 } 268 } 269 mySortAndMinimizeJanetBasis(); 270 } 271 mySortAndMinimizeJanetBasis()272 void CompletionGB::mySortAndMinimizeJanetBasis() 273 { 274 myJTree.myDelete(); 275 std::list<JanetTriple> TmpBasis; 276 TmpBasis.swap(myJBasis); 277 std::list<JanetTriple>::iterator iter = TmpBasis.end(); 278 --iter; 279 // build initial tree out of Groebner basis elements 280 // They are at the end of the list & the ancestor is equal 281 // to the leading polynomial 282 while (!TmpBasis.empty() && LPP(iter->myGetPol()) == iter->myGetAnc()) 283 { 284 std::list<JanetTriple>::iterator TmpIter(iter); 285 --iter; 286 myJBasis.splice(myJBasis.begin(), TmpBasis, TmpIter); 287 myJTree.myInsert(myJBasis.begin()); 288 } 289 // sort rest of TmpBasis by degree 290 TmpBasis.sort(myLPPTripleComparison); 291 // Insert the rest of TmpBasis to Janet basis: 292 // We take an element out of the sorted list and check j-divisibility. 293 // If it is j-divisible we skip this element. If it is not j-divisible 294 // we insert it to the Janet basis and return to the beginning of the list 295 // to ensure minimality of the Janet basis. 296 bool EverythingReducedToZero = true; 297 do { 298 std::list<JanetTriple>::iterator iter = TmpBasis.begin(); 299 EverythingReducedToZero = true; 300 while (iter != TmpBasis.end()) 301 { 302 std::list<JanetTriple>::iterator TmpIter(iter); 303 ++iter; 304 JanetTriple* divisor(myJTree.myJDivisor(LPP(TmpIter->myGetPol()))); 305 if(divisor == 0) 306 { 307 EverythingReducedToZero = false; 308 myJBasis.splice(myJBasis.begin(), TmpBasis, TmpIter); 309 myJTree.myInsert(myJBasis.begin()); 310 myJTree.myJTailNormalForm(myJBasis.begin()->myGetPol()); 311 break; 312 } 313 } 314 } while (!EverythingReducedToZero); 315 // perform tail normal form computation 316 // for (std::list<JanetTriple>::iterator i = myJBasis.begin(); i != myJBasis.end(); ++i) 317 for (JanetTriple& JT: myJBasis) 318 { 319 myJTree.myJTailNormalForm(JT.myGetPol()); 320 } 321 // sort myJBasis 322 myJBasis.sort(myLPPTripleComparison); 323 } 324 myPushToProlongList(elemPairList & list,const RingElem & elem,const PPMonoidElem & anc)325 void CompletionGB::myPushToProlongList(elemPairList& list, const RingElem& elem, const PPMonoidElem& anc) 326 { 327 list.push_back(make_pair(elem, anc)); 328 } 329 myInsertToProlongList(elemPairList & list,const RingElem & elem,const PPMonoidElem & anc)330 void CompletionGB::myInsertToProlongList(elemPairList& list, const RingElem& elem, const PPMonoidElem& anc) 331 { 332 elemPair pair(elem, anc); 333 elemPairIter posIter(lower_bound(list.begin(), list.end(), pair, myLPPComparison)); 334 list.insert(posIter, pair); 335 } 336 myOutputResult()337 JanetContainer CompletionGB::myOutputResult() { 338 return JanetContainer(myPolyRing, myJBasis); 339 } 340 341 } // end of namespace Involutive 342 } // end of namespace CoCoA 343