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