1 //   Copyright (c)  2005-2013  John Abbott, Anna M. Bigatti
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 
19 // Implementation file for the class SubmoduleImpl
20 
21 #include "CoCoA/submodule.H"
22 
23 #include "CoCoA/BigIntOps.H"
24 #include "CoCoA/DenseMatrix.H" // for GensAsRows, GensAsCols
25 #include "CoCoA/FreeModule.H"
26 #include "CoCoA/MemPool.H"
27 #include "CoCoA/OpenMath.H"
28 #include "CoCoA/SparsePolyOps-RingElem.H"
29 #include "CoCoA/TmpGOperations.H"  // for ComputeGBasis
30 #include "CoCoA/VectorOps.H"  // for HasUniqueOwner
31 #include "CoCoA/ideal.H" // for syzygies
32 #include "CoCoA/matrix.H" // for ConstMatrixView
33 #include "CoCoA/ring.H"
34 //#include "CoCoA/MatrixView.H"
35 
36 #include <iostream>
37 using std::ostream;
38 //#include <vector>
39 using std::vector;
40 
41 
42 namespace CoCoA
43 {
44 
45   class SubmoduleImpl: public FGModuleBase
46   {
47     // Two typedefs to save typing.
48     typedef ModuleBase::RawPtr RawPtr;
49     typedef const ModuleBase::RawPtr& ConstRawPtr;
50 
51   public:
52     SubmoduleImpl(const module& M, const std::vector<ModuleElem>& gens);
myNumCompts()53     long myNumCompts() const       {return NumCompts(myM);}
myRing()54     const ring& myRing() const {return RingOf(myM);}
myAmbientFreeModule()55     const FreeModule& myAmbientFreeModule() const {return myM;}
myGens()56     const std::vector<ModuleElem>& myGens() const {return myGensValue;}
57     const std::vector<ModuleElem>& myMinGens(const CpuTimeLimit& CheckForTimeOut) const;
58     const std::vector<ModuleElem>& myTidyGens(const CpuTimeLimit& CheckForTimeOut) const;
59     const std::vector<ModuleElem>& myGBasis(const CpuTimeLimit& CheckForTimeOut) const; // for SparsePolyRing
60 
myZero()61     const ModuleElem& myZero() const   {return zero(myM);}
myNew(RawPtr & rawv)62     void myNew(RawPtr& rawv) const     {myM->myNew(rawv);}
myNew(RawPtr & rawv,ConstRawPtr rawt)63     void myNew(RawPtr& rawv, ConstRawPtr rawt) const {myM->myNew(rawv, rawt);}
myDelete(RawPtr & rawv)64     void myDelete(RawPtr& rawv) const  {myM->myDelete(rawv);}  // destroys v (incl all resources)
mySwap(RawPtr & rawv,RawPtr & raww)65     void mySwap(RawPtr& rawv, RawPtr& raww) const {myM->mySwap(rawv, raww);}
myAssign(RawPtr & rawlhs,ConstRawPtr rawv)66     void myAssign(RawPtr& rawlhs, ConstRawPtr rawv) const {myM->myAssign(rawlhs, rawv);} // lhs = v;
67     ConstRefRingElem myCompt(const RawPtr& rawv, long pos) const;            ///< v[pos] (READ ONLY)
myNegate(RawPtr & rawlhs,ConstRawPtr rawv)68     void myNegate(RawPtr& rawlhs, ConstRawPtr rawv) const {myM->myNegate(rawlhs, rawv);} // lhs = -v
myAdd(RawPtr & rawlhs,ConstRawPtr rawv,ConstRawPtr raww)69     void myAdd(RawPtr& rawlhs, ConstRawPtr rawv, ConstRawPtr raww) const {myM->myAdd(rawlhs, rawv, raww);} // lhs = v+w;
mySub(RawPtr & rawlhs,ConstRawPtr rawv,ConstRawPtr raww)70     void mySub(RawPtr& rawlhs, ConstRawPtr rawv, ConstRawPtr raww) const {myM->mySub(rawlhs, rawv, raww);} // lhs = v-w;
71 
myMul(RawPtr & rawlhs,RingElemConstRawPtr rawx,ConstRawPtr rawv)72     void myMul(RawPtr& rawlhs, RingElemConstRawPtr rawx, ConstRawPtr rawv) const {myM->myMul(rawlhs, rawx, rawv);} // lhs = r*v;
myDiv(RawPtr & rawlhs,RingElemConstRawPtr rawx,ConstRawPtr rawv)73     void myDiv(RawPtr& rawlhs, RingElemConstRawPtr rawx, ConstRawPtr rawv) const {myM->myDiv(rawlhs, rawx, rawv);} // lhs = (1/r)*v;
myOutput(std::ostream & out,ConstRawPtr rawv)74     void myOutput(std::ostream& out, ConstRawPtr rawv) const {myM->myOutput(out, rawv);} // out << v
75     void myOutputSelf(std::ostream& out) const;                   // out << M
76     void myOutput(OpenMathOutput& OMOut, ConstRawPtr rawv) const; // OMOut << v
77     void myOutputSelf(OpenMathOutput& OMOut) const;               // OMOut << M
myIsZero(ConstRawPtr rawv)78     bool myIsZero(ConstRawPtr rawv) const {return myM->myIsZero(rawv);} // v == 0
79 //???    bool IsZeroAddMul(RawPtr& rawlhs, RingElemConstRawPtr rawy, ConstRawPtr rawz) const;  // lhs += y*z, result says whether lhs == 0.
myIsEqual(ConstRawPtr rawx,ConstRawPtr rawy)80     bool myIsEqual(ConstRawPtr rawx, ConstRawPtr rawy) const {return myM->myIsEqual(rawx, rawy);}
81 
82   private: // data members
83     const FreeModule myM;
84     std::vector<ModuleElem> myGensValue;
85     // mutable member fields
86     mutable bool myTidyGensIsValid;
87     mutable std::vector<ModuleElem> myMinGensValue;
88     mutable std::vector<ModuleElem> myTidyGensValue;
89 //???    std::vector<ModuleElem>& ComputeTidyGens() const;
90   };
91 
92 
93 
SubmoduleImpl(const module & M,const std::vector<ModuleElem> & gens)94   SubmoduleImpl::SubmoduleImpl(const module& M, const std::vector<ModuleElem>& gens):
95       myM(M),
96       myGensValue(gens),
97       myTidyGensIsValid(false)
98   {
99     CoCoA_ASSERT(IsFreeModule(M));
100     for (long i=0; i < len(gens); ++i)
101       if (owner(gens[i]) != M)
102         CoCoA_ERROR(ERR::MixedModules, "SubmoduleImpl(M, gens)");
103     myRefCountZero();
104   }
105 
106 
107 //   ideal::ideal(const std::vector<RingElem>& gens)
108 //   {
109 //     if (gens.empty()) CoCoA_ERROR("Empty list of generators: need ring", "ideal(gens)");
110 //     if (!HasUniqueOwner(gens)) CoCoA_ERROR(ERR::MixedRings, "ideal(gens)");
111 //     ideal tmp = owner(gens[0])->myIdealCtor(gens);
112 //     myPtr = tmp.myPtr;
113 //     myPtr->myRefCountInc();
114 //   }
115 
116 
myGBasis(const CpuTimeLimit & CheckForTimeOut)117   const std::vector<ModuleElem>& SubmoduleImpl::myGBasis(const CpuTimeLimit& CheckForTimeOut) const
118   {
119     CoCoA_ASSERT(IsSparsePolyRing(myRing()));
120     if (!IsField(CoeffRing(myRing())))
121       CoCoA_ERROR("ERR:NYI coeffs not in a field", "SubmoduleImpl::myGBasis");//???
122 
123     //    if (IhaveMonomialGens()) return myGBasisMonId();
124     if (myTidyGensIsValid) return myTidyGensValue;
125     CoCoA_ASSERT(myTidyGensValue.empty());
126     //    if (IamZero()) return myTidyGensValue;
127     ComputeGBasis(myTidyGensValue, myMinGensValue, myGens(), CheckForTimeOut);
128     myTidyGensIsValid = true;
129     return myTidyGensValue;
130   }
131 
132 
myMinGens(const CpuTimeLimit & CheckForTimeOut)133   const std::vector<ModuleElem>& SubmoduleImpl::myMinGens(const CpuTimeLimit& CheckForTimeOut) const
134   {
135     if (!myMinGensValue.empty()) return myMinGensValue;
136     if (GradingDim(myRing())==0 || !IsHomog(myGensValue))
137       CoCoA_ERROR("Input is not homogeneous", "myMinGens");
138     myGBasis(CheckForTimeOut);
139     return myMinGensValue;
140   }
141 
142 
myTidyGens(const CpuTimeLimit & CheckForTimeOut)143   const std::vector<ModuleElem>& SubmoduleImpl::myTidyGens(const CpuTimeLimit& CheckForTimeOut) const
144   {
145     //    if (!myTidyGensIsValid)
146     if (!IsSparsePolyRing(myRing()))
147       CoCoA_ERROR(ERR::NYI, "SubmoduleImpl::myTidyGens");
148     return myGBasis(CheckForTimeOut);
149   }
150 
151 
myCompt(const RawPtr & rawv,long pos)152   ConstRefRingElem SubmoduleImpl::myCompt(const RawPtr& rawv, long pos) const
153   {
154     CoCoA_ASSERT(0 <= pos && pos < myNumCompts());
155     return myM->myCompt(rawv, pos);
156   }
157 
158 
159   namespace{  // anonymous
160   //??? the following functions to compute NR will be replaced by GBMill
161 
FindReducerIndex(ConstRefPPMonoidElem pp,long posn,const vector<ModuleElem> & g)162     int FindReducerIndex(ConstRefPPMonoidElem pp, long posn, const vector<ModuleElem>& g)
163   {
164     const long nelems = len(g);
165     long posn_gi;
166     for (long i=0; i < nelems; ++i)
167       if (posn == (posn_gi=LPosn(g[i])))
168         if (IsDivisible(pp, LPP(g[i][posn_gi])))
169           return i;
170     return -1;
171   }
172 
173 
FindReducerIndex(const ModuleElem & F,const vector<ModuleElem> & g)174   inline int FindReducerIndex(const ModuleElem& F, const vector<ModuleElem>& g)
175   {
176     if ( IsZero(F) ) return -1;
177     return FindReducerIndex(LPP(F), LPosn(F), g);
178   }
179 
180 
ReduceLM(ModuleElem & F,const vector<ModuleElem> & g)181   void ReduceLM(ModuleElem& F, const vector<ModuleElem>& g)
182   {
183     long i, pg, pF;
184     while ( (i = FindReducerIndex(F, g) ) != -1)
185     {
186       pg = LPosn(g[i]);
187       pF = LPosn(g[i]);
188       F -= g[i]*monomial(RingOf(owner(F)),
189                          LC(F[pF])/LC(g[i][pg]), LPP(F[pF])/LPP(g[i][pg]));
190     }
191   }
192 
193 
reduce(ModuleElem & F,const vector<ModuleElem> & g)194   void reduce(ModuleElem& F, const vector<ModuleElem>& g)
195   {
196     ReduceLM(F, g);
197 //     while ( !IsActiveZero(F) )
198 //     {
199 //       F->myMoveToNextLM();
200 //       ReduceActiveLM(F, v);
201 //     }
202   }
203 
NR(const ModuleElem & f,const vector<ModuleElem> & g)204   ModuleElem NR(const ModuleElem& f, const vector<ModuleElem>& g)
205   {
206     if (!IsField(CoeffRing(RingOf(owner(f)))))
207       CoCoA_ERROR("ERR:NYI coeffs not in a field", "NR");//???
208     if ( IsZero(f) ) return f;
209     ModuleElem F=f;
210     reduce(F, g);
211     return F;
212   }
213 
214   } // anonymous namespace
215 
216 
IsElem(const ModuleElem & v,const module & M)217   bool IsElem(const ModuleElem& v, const module& M)
218   {
219     CoCoA_ASSERT(IsFGModule(M));
220     if (owner(v) != AmbientFreeModule(M))
221       CoCoA_ERROR(ERR::MixedModules, "IsElem(v, M)");
222     //    return I->IhaveElem(raw(r));
223     //??? for FGmodule only
224     return IsZero(NR(v, TidyGens(M)));
225   }
226 
227 
myOutputSelf(std::ostream & out)228   void SubmoduleImpl::myOutputSelf(std::ostream& out) const
229   {
230     if (!out) return;  // short-cut for bad ostreams
231 
232     out << "submodule(" << myM << ", [";
233     if (!myGensValue.empty()) out << myGensValue[0];
234     for (long i=1; i < len(myGensValue); ++i)
235     {
236       out << ", " << myGensValue[i];
237     }
238     out << "])";
239   }
240 
241 
myOutput(OpenMathOutput & OMOut,ConstRawPtr rawv)242   void SubmoduleImpl::myOutput(OpenMathOutput& OMOut, ConstRawPtr rawv) const
243   {
244     OMOut->mySendApplyStart();
245     OMOut << OpenMathSymbol("???", "ModuleElement"); // BUG: what should this OMSymbol be???
246     OMOut << myM;
247     OMOut->mySendApplyStart();
248     OMOut << OpenMathSymbol("???", "list"); // BUG: what should this OMSymbol be???
249     OMOut << myNumCompts();
250     myM->myOutput(OMOut, rawv); // BUG: this should be a "naked" output???
251     OMOut->mySendApplyEnd();
252     OMOut->mySendApplyEnd();
253   }
254 
255 
myOutputSelf(OpenMathOutput & OMOut)256   void SubmoduleImpl::myOutputSelf(OpenMathOutput& OMOut) const
257   {
258     OMOut->mySendApplyStart();
259     OMOut << OpenMathSymbol("???", "submodule"); // BUG: what should this OMSymbol be???
260     OMOut << myM;
261     OMOut->mySendApplyStart();
262     OMOut << OpenMathSymbol("???", "list"); // BUG: what should this OMSymbol be???
263     OMOut << len(myGensValue);
264     for (long i=0; i < len(myGensValue); ++i)
265       OMOut << myGensValue[i];  // BUG: this should be a "naked" output???
266     OMOut->mySendApplyEnd();
267     OMOut->mySendApplyEnd();
268   }
269 
270 
271  //???    bool IsZeroAddMul(RawPtr& rawlhs, RingElemConstRawPtr rawy, ConstRawPtr rawz) const;  // lhs += y*z, result says whether lhs == 0.
272 
273   //-- pseudo-ctors
274 
submodule(const FGModule & M,const std::vector<ModuleElem> & gens)275   FGModule submodule(const FGModule& M, const std::vector<ModuleElem>& gens)
276   {return FGModule(new SubmoduleImpl(M, gens));}
277 
278 
submodule(const std::vector<ModuleElem> & gens)279   FGModule submodule(const std::vector<ModuleElem>& gens)
280   {
281     if (gens.empty()) CoCoA_ERROR(ERR::Empty, "submodule(gens)");
282     if (!HasUniqueOwner(gens)) CoCoA_ERROR(ERR::MixedModules, "submodule(gens)");
283     return submodule(owner(gens[0]), gens);
284   }
285 
286 
submodule(const ModuleElem & v1)287   FGModule submodule(const ModuleElem& v1)
288   {
289     vector<ModuleElem> gens;
290     gens.push_back(v1);
291     return submodule(gens);
292   }
293 
294 
submodule(const ModuleElem & v1,const ModuleElem & v2)295   FGModule submodule(const ModuleElem& v1, const ModuleElem& v2)
296   {
297     vector<ModuleElem> gens;
298     gens.push_back(v1);gens.push_back(v2);
299     return submodule(gens);
300   }
301 
302 
submodule(const ModuleElem & v1,const ModuleElem & v2,const ModuleElem & v3)303   FGModule submodule(const ModuleElem& v1, const ModuleElem& v2, const ModuleElem& v3)
304   {
305     vector<ModuleElem> gens;
306     gens.push_back(v1);gens.push_back(v2);gens.push_back(v3);
307     return submodule(gens);
308   }
309 
310 
submodule(const ModuleElem & v1,const ModuleElem & v2,const ModuleElem & v3,const ModuleElem & v4)311   FGModule submodule(const ModuleElem& v1, const ModuleElem& v2, const ModuleElem& v3, const ModuleElem& v4)
312   {
313     vector<ModuleElem> gens;
314     gens.push_back(v1);gens.push_back(v2);gens.push_back(v3);gens.push_back(v4);
315     return submodule(gens);
316   }
317 
318 
SubmoduleCols(const FGModule & F,ConstMatrixView M)319   FGModule SubmoduleCols(const FGModule& F, ConstMatrixView M)
320   {
321     const std::vector<ModuleElem>& e = gens(F);
322     if (len(e)!=NumRows(M))
323       CoCoA_ERROR(ERR::IncompatDims,"SubmoduleCols");
324     std::vector<ModuleElem> g(NumCols(M), zero(F));
325     for (long i=0; i<NumRows(M); ++i)
326       for (long j=0; j<NumCols(M); ++j)
327         g[j] += M(i,j) * e[i];
328     return FGModule(new SubmoduleImpl(F, g));
329   }
330 
331 
SubmoduleRows(const FGModule & F,ConstMatrixView M)332   FGModule SubmoduleRows(const FGModule& F, ConstMatrixView M)
333   {
334     const std::vector<ModuleElem>& e = gens(F);
335     if (len(e)!=NumCols(M))
336       CoCoA_ERROR(ERR::IncompatDims,"SubmoduleRows");
337     std::vector<ModuleElem> g(NumRows(M), zero(F));
338     for (long i=0; i<NumRows(M); ++i)
339       for (long j=0; j<NumCols(M); ++j)
340         g[i] += M(i,j) * e[j];
341     return submodule(F, g);
342   }
343 
344 
SubmoduleOfMinGens(const FGModule & F)345   FGModule SubmoduleOfMinGens(const FGModule& F)
346   {
347     if (IsFreeModule(F)) return F;
348     return submodule(AmbientFreeModule(F), MinGens(F));
349   }
350 
351 
GensAsRows(const FGModule & Mod)352   matrix GensAsRows(const FGModule& Mod)
353   {
354     const std::vector<ModuleElem>& g = gens(Mod);
355     matrix M = NewDenseMat(RingOf(Mod), len(g), NumCompts(Mod));
356     for (long i=0; i<NumRows(M); ++i)
357       for (long j=0; j<NumCols(M); ++j)
358         SetEntry(M,i,j, g[i][j]);
359     return M;
360   }
361 
362 
GensAsCols(const FGModule & Mod)363   matrix GensAsCols(const FGModule& Mod)
364   {
365     const std::vector<ModuleElem>& g = gens(Mod);
366     matrix M = NewDenseMat(RingOf(Mod), NumCompts(Mod), len(g));
367     for (long i=0; i<NumRows(M); ++i)
368       for (long j=0; j<NumCols(M); ++j)
369         SetEntry(M,i,j, g[j][i]);
370     return M;
371   }
372 
373 
374   namespace // anonymous
375   {
376     // template? ???
377 
InsertZeroes(const FreeModule & F,const vector<RingElem> & L,const ModuleElem & v)378     ModuleElem InsertZeroes(const FreeModule& F, const vector<RingElem>& L, const ModuleElem& v)
379     {
380       const std::vector<ModuleElem>& e = gens(F);
381       ModuleElem w(F);
382       long j=0;
383       for (long i=0; i<len(L); ++i)
384         if (IsZero(L[i]))   ++j;  else  w += v[i-j]*e[i];
385       return w;
386     }
387 
InsertZeroes(const FreeModule & F,const vector<ModuleElem> & L,const ModuleElem & v)388     ModuleElem InsertZeroes(const FreeModule& F, const vector<ModuleElem>& L, const ModuleElem& v)
389     {
390       const std::vector<ModuleElem>& e = gens(F);
391       ModuleElem w(F);
392       long j=0;
393       for (long i=0; i<len(L); ++i)
394         if (IsZero(L[i]))   ++j;  else  w += v[i-j]*e[i];
395       return w;
396     }
397 
398   }
399 
400 
SyzOfGens(const FreeModule & F,const ideal & I)401   FGModule SyzOfGens(const FreeModule& F, const ideal& I)
402   {
403     if (!IsField(CoeffRing(RingOf(F))))
404       CoCoA_ERROR("ERR:NYI coeffs not in a field", "SyzOfGens");//???
405     if (NumCompts(F)!=len(gens(I)))
406       CoCoA_ERROR("wrong number of components in free module", "SyzOfGens");
407     const vector<RingElem>& g = gens(I);
408     vector<RingElem> g_non0;
409     //-- remove zero gens
410     for (long i=0; i<len(g); ++i)
411       if (!IsZero(g[i]))  g_non0.push_back(g[i]);
412     vector<ModuleElem> SyzVec_non0;
413     ComputeSyz(SyzVec_non0, F, g_non0);
414     if (len(g_non0)==len(g))  return submodule(F, SyzVec_non0);
415     const std::vector<ModuleElem>& e = gens(F);
416     //-- syzygies of zero gens
417     vector<ModuleElem> SyzVec;
418     for (long i=0; i<len(g); ++i)
419       if (IsZero(g[i]))  SyzVec.push_back(e[i]);
420     //-- interweave 0 in SyzVec_non0
421     for (long i=0; i<len(SyzVec_non0); ++i)
422       SyzVec.push_back(InsertZeroes(F, g, SyzVec_non0[i]));
423     return submodule(SyzVec);
424   }
425 
426 
SyzOfGens(const FreeModule & F,const FGModule & N)427   FGModule SyzOfGens(const FreeModule& F, const FGModule& N)
428   {
429     if (!IsField(CoeffRing(RingOf(F))))
430       CoCoA_ERROR("ERR:NYI coeffs not in a field", "SyzOfGens");//???
431     if (NumCompts(F)!=len(gens(N)))
432       CoCoA_ERROR("wrong number of components in free module", "SyzOfGens");
433     const vector<ModuleElem>& g = gens(N);
434     vector<ModuleElem> g_non0;
435     //-- remove zero gens
436     for (long i=0; i<len(g); ++i)
437       if (!IsZero(g[i]))  g_non0.push_back(g[i]);
438     vector<ModuleElem> SyzVec_non0;
439     ComputeSyz(SyzVec_non0, F, g_non0);
440     if (len(g_non0)==len(g))  return submodule(F, SyzVec_non0);
441     const std::vector<ModuleElem>& e = gens(F);
442     //-- syzygies of zero gens
443     vector<ModuleElem> SyzVec;
444     for (long i=0; i<len(g); ++i)
445       if (IsZero(g[i]))  SyzVec.push_back(e[i]);
446     //-- interweave 0 in SyzVec_non0
447     for (long i=0; i<len(SyzVec_non0); ++i)
448       SyzVec.push_back(InsertZeroes(F, g, SyzVec_non0[i]));
449     return submodule(SyzVec);
450   }
451 
452 
SyzOfGens(const ideal & I)453   FGModule SyzOfGens(const ideal& I)
454   {
455     if (!IsField(CoeffRing(RingOf(I))))
456       CoCoA_ERROR("ERR:NYI coeffs not in a field", "SyzOfGens");//???
457     const vector<RingElem>& g = gens(I);
458     for (long i=0; i<len(g); ++i)
459       if (IsZero(g[i]))
460         CoCoA_ERROR("Zero generator(s): first arg must be the output free module",
461                     "SyzOfGens");
462     vector<ModuleElem> syzvec;
463     FreeModule F = NewFreeModuleForSyz(gens(I));
464     return SyzOfGens(F, I);
465   }
466 
467 
SyzOfGens(const FGModule & N)468   FGModule SyzOfGens(const FGModule& N)
469   {
470     if (!IsField(CoeffRing(RingOf(N))))
471       CoCoA_ERROR("ERR:NYI coeffs not in a field", "SyzOfGens");//???
472     const vector<ModuleElem>& g = gens(N);
473     for (long i=0; i<len(g); ++i)
474       if (IsZero(g[i]))
475         CoCoA_ERROR("Zero generator(s): first arg must be the output free module",
476                     "SyzOfGens");
477     vector<ModuleElem> syzvec;
478     FreeModule F = NewFreeModuleForSyz(gens(N));
479     return SyzOfGens(F, N);
480   }
481 
482 
IsContained(const module & M,const module & N)483   bool IsContained(const module& M, const module& N)
484   {
485     if (!IsSparsePolyRing(RingOf(M)))
486       CoCoA_ERROR(ERR::NYI, "SubmoduleImpl::IsContained");
487     const vector<ModuleElem>& g = gens(M);
488     for (long i=0; i < len(g); ++i)
489       if (!IsElem(g[i], N)) return false;
490     return true;
491   }
492 
493 
IsHomog(const module & M)494   bool IsHomog(const module& M)
495   {
496     if (!IsSparsePolyRing(RingOf(M)))
497       CoCoA_ERROR(ERR::NotSparsePolyRing, "IsHomog(submodule)");
498     if (GradingDim(RingOf(M))==0)
499       CoCoA_ERROR(ERR::ZeroGradingDim, "IsHomog(submodule)");
500     if (IsZero(M)) return true;
501     // Now we know I is non-trivial.
502     const vector<ModuleElem>& GB = TidyGens(M);
503     const long GBsize = len(GB); // MUST BE A REDUCED GBASIS !!!
504     for (long i=0; i < GBsize; ++i)
505       if (!IsHomog(GB[i]))  return false;
506     return true;
507   }
508 
509 
510   // intersection
511 
512 
LT(const module & M)513   FGModule LT(const module& M)
514   {
515     if (!IsSparsePolyRing(RingOf(M)))
516       CoCoA_ERROR(ERR::NotSparsePolyRing, "LT(submodule)");
517     const SparsePolyRing P = RingOf(M);
518     if (GradingDim(P)==0)
519       CoCoA_ERROR(ERR::ZeroGradingDim, "LT(submodule)");
520     const vector<ModuleElem>& e = gens(AmbientFreeModule(M));
521     const vector<ModuleElem>& GB = TidyGens(M);
522     vector<ModuleElem> LTs;
523     const long GBsize = len(GB);
524     for (long i=0; i < GBsize; ++i)
525     {
526       long j = LPosn(GB[i]);
527       LTs.push_back(monomial(P, LPP(GB[i][j]))*e[j]);
528     }
529     return submodule(AmbientFreeModule(M), LTs);
530   }
531 
532 
533 //   FGModule SubmoduleOfGBasis(const module& M)
534 //   {
535 //     ideal J(RingOf(I), GBasis(I));
536 //     SetGBasisAsGens(J);
537 //     return J;
538 //   }
539 
540 
541 }  // end of namespace CoCoA
542 
543 // RCS header/log in the next few lines
544 // $Header: /Volumes/Home_1/cocoa/cvs-repository/CoCoALib-0.99/src/AlgebraicCore/submodule.C,v 1.39 2020/02/11 16:56:43 abbott Exp $
545 // $Log: submodule.C,v $
546 // Revision 1.39  2020/02/11 16:56:43  abbott
547 // Summary: Corrected last update (see redmine 969)
548 //
549 // Revision 1.38  2020/02/11 16:12:20  abbott
550 // Summary: Added some checks for bad ostream (even to mem fns myOutput); see redmine 969
551 //
552 // Revision 1.37  2018/08/02 16:48:43  bigatti
553 // -- just cleaned up some commented code
554 //
555 // Revision 1.36  2018/08/01 15:12:15  bigatti
556 // -- fixed SyzOfGens in case of generators = 0
557 //
558 // Revision 1.35  2018/05/25 09:24:47  abbott
559 // Summary: Major redesign of CpuTimeLimit (many consequences)
560 //
561 // Revision 1.34  2018/05/18 16:42:11  bigatti
562 // -- added include SparsePolyOps-RingElem.H
563 //
564 // Revision 1.33  2018/05/18 12:25:54  bigatti
565 // -- renamed IntOperations --> BigIntOps
566 //
567 // Revision 1.32  2018/05/17 15:58:40  bigatti
568 // -- renamed VectorOperations --> VectorOps
569 //
570 // Revision 1.31  2017/12/21 12:19:41  bigatti
571 // -- added check for coeffs in a field on some operations
572 //
573 // Revision 1.30  2017/11/20 20:10:26  bigatti
574 // -- mimimalized --> SubmoduleOfMinGens
575 //
576 // Revision 1.29  2015/06/11 16:57:24  bigatti
577 // -- using new functions monomial(ring, pp) and monomial(ring, expv)
578 //
579 // Revision 1.28  2015/04/13 15:44:46  abbott
580 // Summary: Changed error code in IsIn and submodule (pseudo-ctor)
581 // Author: JAA
582 //
583 // Revision 1.27  2014/07/31 14:45:19  abbott
584 // Summary: Merged io.H and UtilsTemplate.H into new header VectorOperations.H
585 // Author: JAA
586 //
587 // Revision 1.26  2014/07/30 14:13:56  abbott
588 // Summary: Changed BaseRing into RingOf; myBaseRing --> myRing
589 // Author: JAA
590 //
591 // Revision 1.25  2014/07/14 15:10:05  abbott
592 // Summary: Changed include of tmp.H into UtilsTemplate.H
593 // Author: JAA
594 //
595 // Revision 1.24  2014/07/09 14:27:53  abbott
596 // Summary: Removed AsFreeModule and AsFGModule
597 // Author: JAA
598 //
599 // Revision 1.23  2014/07/07 13:29:54  abbott
600 // Summary: Removed AsSparsePolyRing
601 // Author: JAA
602 //
603 // Revision 1.22  2014/04/17 13:39:54  bigatti
604 // -- MatrixViews --> MatrixView
605 //
606 // Revision 1.21  2014/04/10 13:04:55  bigatti
607 // -- minimalized(FGModule)
608 //
609 // Revision 1.20  2014/04/09 13:11:06  bigatti
610 // -- added submodule(vector<ModuleElem>)
611 //
612 // Revision 1.19  2014/03/26 15:23:44  bigatti
613 // -- added MinGens for submodules
614 //
615 // Revision 1.18  2013/08/02 14:41:41  bigatti
616 // -- changed LPos --> LPosn
617 //
618 // Revision 1.17  2013/07/31 14:47:17  bigatti
619 // added LT(module)
620 //
621 // Revision 1.16  2013/07/31 10:20:33  bigatti
622 // -- added IsZero, IsHomog
623 // -- move inliners into class definition
624 //
625 // Revision 1.15  2013/06/06 05:47:34  bigatti
626 // -- pseudoctor is now called "submodule" instead of "NewSubmodule"
627 // -- added pseudoctor with 1,2,3,4 generators
628 //
629 // Revision 1.14  2013/06/03 10:05:59  bigatti
630 // -- added IsElem, IsContained for modules
631 //
632 // Revision 1.13  2013/03/26 14:57:18  abbott
633 // Corrected silly typo.
634 //
635 // Revision 1.12  2013/03/25 17:29:59  abbott
636 // Changed formal parameter names (M for matrix, N for submodule).
637 //
638 // Revision 1.11  2013/03/15 14:58:48  bigatti
639 // -- added SyzOfGens for modules (something inside is not working though)
640 //
641 // Revision 1.10  2013/02/21 16:56:16  bigatti
642 // -- added GensAsRows, GensAsRows, SyzOfGens
643 //
644 // Revision 1.9  2013/01/30 15:46:11  bigatti
645 // -- added NewSubmoduleCols/Rows
646 //
647 // Revision 1.8  2013/01/25 16:15:06  bigatti
648 // -- added function myGBasis (for SparsePolyRing)
649 // -- modified myTidyGens
650 // -- changed myGensArray/myTidyGensArray --> myGensValue/myTidyGensValue
651 // -- fixed myTidyGensIsValid in constructor
652 //
653 // Revision 1.7  2012/10/12 12:38:18  abbott
654 // Removed element accessor (via operator[]) and non-const mem fn  ModuleBase::myCompt.
655 //
656 // Revision 1.6  2012/05/28 09:18:20  abbott
657 // Created IntOperations which gathers together all operations on
658 // integers (both big and small).  Many consequential changes.
659 //
660 // Revision 1.5  2011/03/10 16:39:33  abbott
661 // Replaced (very many) size_t by long in function interfaces (for rings,
662 // PPMonoids and modules).  Also replaced most size_t inside fn defns.
663 //
664 // Revision 1.4  2009/12/03 17:26:34  abbott
665 // Renamed EFGModule to FGModule.
666 // Renamed ModuleBase member fns  myInit -> myNew, myKill -> myDelete.
667 // Removed some cruft (old code that was not used by anyone).
668 //
669 // Revision 1.3  2008/05/30 12:50:48  abbott
670 // Aligned some comments.
671 //
672 // Revision 1.2  2007/10/30 17:14:06  abbott
673 // Changed licence from GPL-2 only to GPL-3 or later.
674 // New version for such an important change.
675 //
676 // Revision 1.1.1.1  2007/03/09 15:16:11  abbott
677 // Imported files
678 //
679 // Revision 1.5  2007/03/08 18:22:28  cocoa
680 // Just whitespace cleaning.
681 //
682 // Revision 1.4  2007/01/15 14:39:12  bigatti
683 // -- added prefix "raw" to RawPtr arguments names
684 //
685 // Revision 1.3  2006/11/02 13:25:43  cocoa
686 // Simplification of header files: the OpenMath classes have been renamed.
687 // Many minor consequential changes.
688 //
689 // Revision 1.2  2006/10/06 10:15:52  cocoa
690 // In response to Susan's bug: a fiasco when compiling with CoCoA_MEMPOOL_DEBUG
691 // set wrongly.  Moved several implementation classes out of their header files
692 // into the implementation files.  Several functions had to be uninlined.
693 // Also corrected position of #include, etc.
694 //
695 // Revision 1.1.1.1  2006/05/30 11:39:37  cocoa
696 // Imported files
697 //
698 // Revision 1.7  2006/05/12 16:10:58  cocoa
699 // Added OpenMathFwd.H, and tidied OpenMath.H.
700 // Many consequential but trivial changes.
701 //
702 // Revision 1.6  2006/04/21 14:56:33  cocoa
703 // Changed return type of myCompt member function: now it returns a
704 // ConstRefRingElem instead of a RingElem (i.e. a copy).
705 //
706 // Revision 1.5  2006/03/15 18:09:31  cocoa
707 // Changed names of member functions which print out their object
708 // into myOutputSelf -- hope this will appease the Intel C++ compiler.
709 //
710 // Revision 1.4  2006/03/12 21:28:33  cocoa
711 // Major check in after many changes
712 //
713 // Revision 1.3  2005/11/29 13:04:47  cocoa
714 // -- added "const" to myCompt argument
715 //
716 // Revision 1.2  2005/11/24 16:09:38  cocoa
717 // -- added operator[] for ModuleElem
718 //
719 // Revision 1.1.1.1  2005/10/17 10:46:54  cocoa
720 // Imported files
721 //
722 // Revision 1.1.1.1  2005/05/03 15:47:31  cocoa
723 // Imported files
724 //
725 // Revision 1.4  2005/04/20 15:40:47  cocoa
726 // Major change: modified the standard way errors are to be signalled
727 // (now via a macro which records filename and line number).  Updated
728 // documentation in error.txt accordingly.
729 //
730 // Improved the documentation in matrix.txt (still more work to be done).
731 //
732 // Revision 1.3  2005/04/19 14:06:03  cocoa
733 // Added GPL and GFDL licence stuff.
734 //
735 // Revision 1.2  2005/02/11 14:15:20  cocoa
736 // New style ring elements and references to ring elements;
737 // I hope I have finally got it right!
738 //
739 // Revision 1.1.1.1  2005/01/27 15:12:13  cocoa
740 // Imported files
741 //
742 // Revision 1.6  2004/11/12 15:49:29  cocoa
743 // Tidying prior to 0.90 release.
744 // (a) documentation improved (or marked as poor)
745 // (b) sundry minor improvements to the code
746 //
747 // Revision 1.5  2004/11/11 14:06:20  cocoa
748 // -- moved CVS log to the bottom
749 // -- minor changes for doxygen
750 //
751 // Revision 1.4  2004/06/29 17:10:22  cocoa
752 // Partially tidied use of "protected" and "private" in various
753 // base classes.  Checking in at the end of the day -- it works,
754 // and I wouldn't want it to be lost next time point's disk
755 // misbehaves.
756 //
757 // Revision 1.3  2004/05/24 15:52:13  cocoa
758 // Major update:
759 //   new error mechanism
760 //   many fixes
761 //   RingHoms almost work now
762 //   RingFloat much improved
763 //
764 // Revision 1.2  2004/01/28 15:37:58  cocoa
765 // Fairly major update: resuscitated "old style" code which didn't compile
766 // under the current organization.
767 //
768 // Revision 1.1.1.1  2003/09/24 12:55:43  cocoa
769 // Imported files
770 //
771