Macaulay2 Engine
Loading...
Searching...
No Matches
FreeMonoid.cpp
Go to the documentation of this file.
2
3#include "MemoryBlock.hpp" // for MemoryBlock
4#include "NCAlgebras/Word.hpp" // for Word
5#include "buffer.hpp" // for buffer
6#include "monoid.hpp" // for Monoid
7
8#include <cassert> // for assert
9#include <algorithm> // for copy
10#include <ostream> // for string, operator<<, ostream
11#include <utility> // for pair
12
14
15std::ostream& operator<<(std::ostream& o, FreeMonoidLogger a)
16{
17 o << "# compares: " << a.mCompares;
18 return o;
19}
20
22 const std::vector<std::string>& variableNames,
24 const std::vector<int>& degrees,
25 const std::vector<int>& wtvecs,
26 const std::vector<int>& heftVector)
29 mDegrees(degrees),
30 mWeightVectors(wtvecs),
31 mHeftVector(heftVector),
32 mNumWeights(wtvecs.size() / variableNames.size())
33{
34 auto ndegrees = degreeMonoid().n_vars();
35 [[maybe_unused]] auto nvars = variableNames.size();
36 assert(nvars * ndegrees == mDegrees.size());
37
38 for (const int* i = mDegrees.data(); i != mDegrees.data() + mDegrees.size(); i += ndegrees)
39 {
42 mDegreeOfVar.push_back(deg);
43 }
44 for (auto deg : mDegreeOfVar)
45 mHeftDegrees.push_back(degreeMonoid().degree_weights(deg, mHeftVector));
46}
47
49{
50 m.push_back(mNumWeights+1);
51 for (int i=0; i<mNumWeights; ++i) m.push_back(0);
52}
53
54void FreeMonoid::var(int v, MonomialInserter& m) const
55{
56 m.push_back(mNumWeights+2);
57 for (int i=0; i<mNumWeights; ++i)
58 m.push_back(weightOfVar(v,i));
59 m.push_back(v);
60}
61
62bool FreeMonoid::is_one(const Monom& m) const
63{
64 return m[0] == mNumWeights+1;
65}
66
68{
69 if (m[0] != mNumWeights+2) return -1;
70 return m[mNumWeights+1];
71}
72
74{
75 result.insert(result.end(),m.begin(),m.end());
76}
77
78void FreeMonoid::mult(const Monom& m1, const Monom& m2, MonomialInserter& result) const
79{
80 int sz = m1[0] + wordLength(m2);
81 result.push_back(sz);
82 for (int i=1; i<=mNumWeights; ++i)
83 result.push_back(m1[i] + m2[i]);
84 result.insert(result.end(),m1.begin()+mNumWeights+1,m1.end());
85 result.insert(result.end(),m2.begin()+mNumWeights+1,m2.end());
86}
87
88void FreeMonoid::mult3(const Monom& m1, const Monom& m2, const Monom& m3, MonomialInserter& result) const
89{
90 int sz = m1[0] + wordLength(m2) + wordLength(m3);
91 result.push_back(sz);
92 for (int i=1; i<=mNumWeights; ++i)
93 result.push_back(m1[i] + m2[i] + m3[i]);
94 result.insert(result.end(),m1.begin()+mNumWeights+1,m1.end());
95 result.insert(result.end(),m2.begin()+mNumWeights+1,m2.end());
96 result.insert(result.end(),m3.begin()+mNumWeights+1,m3.end());
97}
98
99int FreeMonoid::compare(const Monom& m1, const Monom& m2) const
100{
101 // order of events:
102 // compare weights first
103 // then compare word length
104 // then compare with lex
105
106 // is this thread-safe?
107 //FreeMonoidLogger::logCompare();
108
109 // compare weights first
110 for (int j = 1; j <= mNumWeights; ++j)
111 {
112 if (m1[j] > m2[j]) return GT;
113 if (m1[j] < m2[j]) return LT;
114 }
115
116 // at this point, the weights are the same.
117 // the total length is just mNumWeights + 1 + wordLength, so just
118 // compare the total length (i.e. m1[0] and m2[0]
119 if (m1.size() > m2.size()) return GT;
120 if (m1.size() < m2.size()) return LT;
121
122 // at this stage, they have the same weights and word length, so use lex order
123 for (int j = mNumWeights+1; j < m1.size(); ++j)
124 {
125 if (m1[j] > m2[j]) return LT;
126 if (m1[j] < m2[j]) return GT;
127 }
128 // if we are here, the monomials are the same.
129 return EQ;
130}
131
132int FreeMonoid::compare(const Word& w1, const Word& w2) const
133{
134 int weight1;
135 int weight2;
136
137 // compute and compare weights
138 for (int i = 0; i < mNumWeights; ++i)
139 {
140 weight1 = 0;
141 weight2 = 0;
142 for (int j = 0; j < w1.size(); ++j)
143 weight1 += weightOfVar(w1[j],i);
144 for (int j = 0; j < w2.size(); ++j)
145 weight2 += weightOfVar(w2[j],i);
146 if (weight1 > weight2) return GT;
147 if (weight1 < weight2) return LT;
148 }
149
150 if (w1.size() > w2.size()) return GT;
151 if (w1.size() < w2.size()) return LT;
152 // at this stage, they have the same weights and word length, so use lex order
153 for (int i = 0; i < w1.size(); ++i)
154 {
155 if (w1[i] > w2[i]) return LT;
156 if (w1[i] < w2[i]) return GT;
157 }
158 // if we are here, the monomials corresponding to the words are the same.
159 return EQ;
160}
161
162bool FreeMonoid::isEqual(const Monom& m1, const Monom&m2) const
163{
164 //if (wordLength(m1) != wordLength(m2)) return false;
165 return std::equal(m1.begin(),m1.end(),m2.begin(),m2.end());
166}
167
168void FreeMonoid::multi_degree(const Monom& m, int* already_allocated_degree_vector) const
169{
170 int* result = already_allocated_degree_vector; // just to use a smaller name...
171 degreeMonoid().one(result); // reset value
172
173 auto word_length = wordLength(m);
174 auto word_ptr = m + mNumWeights+1;
175 for (auto j = 0; j < word_length; j++)
176 {
177 degreeMonoid().mult(result, mDegreeOfVar[word_ptr[j]], result);
178 }
179}
180
181void FreeMonoid::elem_text_out(buffer& o, const Monom& m) const
182{
183 auto word_length = wordLength(m);
184 auto word_ptr = m + mNumWeights + 1;
185 for (auto j = 0; j < word_length; j++)
186 {
187 // for now, just output the string.
188 int curvar = word_ptr[j];
189 int curvarPower = 0;
190 o << mVariableNames[curvar];
191 while ((j < word_length) && (word_ptr[j] == curvar))
192 {
193 j++;
194 curvarPower++;
195 }
196 if (curvarPower > 1) o << "^" << curvarPower;
197 // back j up one since we went too far looking ahead.
198 j--;
199 }
200}
201
202// This function should reverse the order of the varpower terms.
203// as the front end reverses the order of terms in a monomial.
204void FreeMonoid::getMonomial(Monom m, std::vector<int>& result) const
205// Input is of the form: [len wt1 .. wtm v1 v2 ... vn]
206// where len = m + n + 1, wt are the weights, and vs are the variables in the word
207// The output is of the following form, and appended to result.
208// [2n+1 v1 e1 v2 e2 ... vn en], where each ei > 0, (in 'varpower' format)
209// and the order is that of m. that is: a*b is encoded as [5, 0 1, 1 1] (commas are only for clarity)
210{
211 auto start = result.size();
212 result.push_back(0);
213
214 auto word_length = wordLength(m);
215 auto word_ptr = m + mNumWeights + 1;
216 for (auto j = 0; j < word_length; j++)
217 {
218 int curvar = word_ptr[j];
219 int curvarPower = 0;
220 result.push_back(curvar);
221 while ((j < word_length) && (word_ptr[j] == curvar))
222 {
223 j++;
224 curvarPower++;
225 }
226 result.push_back(curvarPower);
227 // back j up one since we went too far looking ahead.
228 --j;
229 }
230 result[start] = static_cast<int>(result.size() - start);
231}
232
233void FreeMonoid::getMonomialReversed(Monom m, std::vector<int>& result) const
234// Input is of the form: [len wt1 .. wtm v1 v2 ... vn]
235// where len = m + n + 1, wt are the weights, and vs are the variables in the word
236// The output is of the following form, and appended to result.
237// [2n+1 v1 e1 v2 e2 ... vn en], where each ei > 0, (in 'varpower' format)
238// and the order is the OPPOSITE of m. that is: a*b is encoded as [5, 1 1, 0 1] (commas are only for clarity)
239{
240 auto start = result.size();
241 result.push_back(0);
242 auto word_length = wordLength(m);
243 auto word_ptr = m + mNumWeights + 1;
244 for (auto j = word_length-1; j >= 0; --j)
245 {
246 int curvar = word_ptr[j];
247 int curvarPower = 0;
248 result.push_back(curvar);
249 while ((j >= 0) && (word_ptr[j] == curvar))
250 {
251 --j;
252 curvarPower++;
253 }
254 result.push_back(curvarPower);
255 // back j up one since we went too far looking ahead.
256 j++;
257 }
258 result[start] = static_cast<int>(result.size() - start);
259}
260
261// This function should reverse the order of the varpower terms
263 // Input is of the form: [2n+1 v1 e1 v2 e2 ... vn en] (in 'varpower' format)
264 // The output is of the following form, and stored in result.
265 // [len wt1 wt2 ... wtm v1 v2 v3 ... vn]
266 // where len = m+n+1 and wt1 .. wtm are the weights and v1 .. vn is the word
267{
268 int inputMonomLength = *monom;
269 int startMon = static_cast<int>(result.size());
270 // make space for the length and the weights
271 for (int i=0; i<mNumWeights+1; ++i)
272 result.push_back(0);
273 for (int j = inputMonomLength-2; j >= 1; j -= 2)
274 {
275 auto v = monom[j];
276 for (int k = 0; k < monom[j+1]; k++)
277 {
278 result.push_back(v);
279 }
280 }
281 result[startMon] = static_cast<int>(result.size() - startMon);
282 Monom tmpMon(result.data()+startMon);
283 setWeights(tmpMon);
284}
285
286// these functions create a Word from the (prefix/suffix of) a Monom
288{
289 // just call the prefix command on the word length of the monom
290 result.init(m.begin() + mNumWeights + 1, m.end());
291 //wordPrefixFromMonom(result,m,wordLength(m));
292}
293
294void FreeMonoid::wordPrefixFromMonom(Word& result, const Monom& m, int endIndex) const
295{
296 result.init(m.begin() + mNumWeights + 1, m.begin() + mNumWeights + 1 + endIndex);
297}
298
299void FreeMonoid::wordSuffixFromMonom(Word& result, const Monom& m, int beginIndex) const
300{
301 result.init(m.begin() + mNumWeights + 1 + beginIndex, m.end());
302}
303
305{
306 result.push_back(word.size() + mNumWeights + 1);
307 for (int j = 0; j < mNumWeights; ++j)
308 result.push_back(0);
309 for (auto a : word) result.push_back(a);
310 Monom tmpMonom(&*(result.end()-1-mNumWeights-word.size()));
311 setWeights(tmpMonom);
312}
313
315{
316 // since Monoms are wrappers to const ints, it seems we need
317 // this line so we can set the weights, but I'm not 100% sure
318 auto monom = const_cast<int*>(m.begin());
319
320 int word_len = wordLength(m);
321 for (int j = 1; j <= mNumWeights; ++j)
322 monom[j] = 0;
323 // eventually replace both for loops with:
324 // word = Word(m)
325 //for (int k = 0; k < mNumWeights; ++k)
326 // monom[k+1] = wordWeight(word,iterator to beginning of kth weight)
327 for (int j = 0; j < word_len; ++j)
328 {
329 for (int k = 0; k < mNumWeights; ++k)
330 {
331 monom[k+1] += weightOfVar(m[mNumWeights+1+j],k);
332 }
333 }
334}
335
336int FreeMonoid::wordWeight(Word& word, const std::vector<int>& weight, int start_index) const
337{
338 assert(start_index <= word.size());
339 int result = 0;
340 for (int j = start_index; j < word.size(); ++j)
341 result += weight[word.begin()[j]];
342 return result;
343}
344
345 // some functions to create monoms from words and monoms
346Monom FreeMonoid::wordProductAsMonom(const Word& left, const Word& right, MemoryBlock& memBlock) const
347{
348 int monomOffset = numWeights() + 1;
349 int sz = left.size() + right.size() + numWeights() + 1;
350 auto rg = memBlock.allocateArray<int>(sz);
351 rg.first[0] = sz;
352 std::copy(left.begin(), left.end(), rg.first + monomOffset);
353 std::copy(right.begin(), right.end(), rg.first + monomOffset + left.size());
354 Monom newmon = Monom(rg.first);
355 setWeights(newmon);
356 return newmon;
357}
358
359Word FreeMonoid::wordProductAsWord(const Word& left, const Word& right, MemoryBlock& memBlock) const
360{
361 int sz = left.size() + right.size();
362 auto rg = memBlock.allocateArray<int>(sz);
363 std::copy(left.begin(), left.end(), rg.first);
364 std::copy(right.begin(), right.end(), rg.first + left.size());
365 Word newword(rg.first, rg.second);
366 return newword;
367}
368
369Monom FreeMonoid::wordProductAsMonom(const Word& left, const Word& mid, const Word& right, MemoryBlock & memBlock) const
370{
371 int monomOffset = numWeights() + 1;
372 int sz = left.size() + mid.size() + right.size() + monomOffset;
373 auto rg = memBlock.allocateArray<int>(sz);
374 rg.first[0] = sz;
375 std::copy(left.begin(), left.end(), rg.first + monomOffset);
376 std::copy(mid.begin(), mid.end(), rg.first + left.size() + monomOffset);
377 std::copy(right.begin(), right.end(), rg.first + left.size() + mid.size() + monomOffset);
378 Monom newmon = Monom(rg.first);
379 setWeights(newmon);
380 return newmon;
381}
382
384 const Word& mid,
385 const Word& right,
386 MemoryBlock& memBlock) const
387{
388 int sz = left.size() + mid.size() + right.size();
389 auto rg = memBlock.allocateArray<int>(sz);
390 std::copy(left.begin(), left.end(), rg.first);
391 std::copy(mid.begin(), mid.end(), rg.first + left.size());
392 std::copy(right.begin(), right.end(), rg.first + left.size() + mid.size());
393 Word newword(rg.first, rg.second);
394 return newword;
395}
396
398 const Monom& mid,
399 const Word& right,
400 MemoryBlock & memBlock) const
401{
402 int monomOffset = numWeights() + 1;
403 int sz = left.size() + mid.size() + right.size();
404 auto rg = memBlock.allocateArray<int>(sz);
405 rg.first[0] = sz;
406 std::copy(left.begin(), left.end(), rg.first + monomOffset);
407 std::copy(mid.begin()+monomOffset, mid.end(), rg.first + left.size() + monomOffset);
408 std::copy(right.begin(), right.end(), rg.first + left.size() + mid.size());
409 Monom newmon = Monom(rg.first);
410 setWeights(newmon);
411 return newmon;
412}
413
414// we are just placing the answer in result. it is up to the caller
415// to clean it up.
416void FreeMonoid::support(const Monom& m, std::vector<int> &result) const
417{
418 int numVarsFound = 0;
419 int monomOffset = numWeights() + 1;
420 result.clear();
421 std::vector<int> varsFound;
422 for (auto i = 0; i < numVars(); i++)
423 varsFound.push_back(0);
424 for (auto i = m.begin() + monomOffset; i < m.end(); i++)
425 {
426 if (varsFound[*i] == 0) numVarsFound++;
427 varsFound[*i]++;
428 if (numVarsFound == numVars()) break;
429 }
430 for (auto i = 0; i < numVars(); i++)
431 if (varsFound[i] > 0) result.push_back(i);
432}
433
434// Local Variables:
435// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
436// indent-tabs-mode: nil
437// End:
std::ostream & operator<<(std::ostream &o, FreeMonoidLogger a)
FreeMonoid — monoid of length-prefixed non-commutative words with weight-vector prefix.
Bump-pointer arena allocator for transient inner-loop allocations.
std::vector< int > word
Word and WordWithData — non-owning views over the flat-int encoding of a non-commutative word.
Append-only GC-backed byte buffer used throughout the engine for text output.
const Monoid & degreeMonoid() const
const int mNumWeights
bool isEqual(const Monom &m1, const Monom &m2) const
int wordWeight(Word &word, const std::vector< int > &weight, int start_index) const
void getMonomialReversed(Monom monom, std::vector< int > &result) const
gc_vector< int > MonomialInserter
const PolynomialRing * mDegreeRing
Word wordProductAsWord(const Word &left, const Word &right, MemoryBlock &memBlock) const
void mult3(const Monom &m1, const Monom &m2, const Monom &m3, MonomialInserter &result) const
std::vector< int > mHeftDegrees
void setWeights(Monom &m) const
unsigned int numWeights() const
void getMonomial(Monom monom, std::vector< int > &result) const
const std::vector< int > mWeightVectors
const std::vector< int > mHeftVector
FreeMonoid(const std::vector< std::string > &variableNames, const PolynomialRing *degreeRing, const std::vector< int > &degrees, const std::vector< int > &wtvecs, const std::vector< int > &heftVector)
void support(const Monom &m, std::vector< int > &result) const
Monom wordProductAsMonom(const Word &left, const Word &right, MemoryBlock &memBlock) const
void fromMonomial(const_monomial monom, MonomialInserter &result) const
const std::vector< int > mDegrees
const std::vector< std::string > & variableNames() const
const PolynomialRing * degreeRing() const
const std::vector< std::string > mVariableNames
int compare(const Monom &m1, const Monom &m2) const
void monomInsertFromWord(MonomialInserter &result, const Word &w) const
void copy(const Monom &m, MonomialInserter &result) const
void elem_text_out(buffer &o, const Monom &m1) const
void wordFromMonom(Word &result, const Monom &m) const
void mult(const Monom &m1, const Monom &m2, MonomialInserter &result) const
gc_vector< const int * > mDegreeOfVar
int weightOfVar(int v, int wt) const
void multi_degree(const Monom &m, monomial already_allocated_degree_vector) const
void one(MonomialInserter &m) const
int index_of_variable(const Monom &m) const
void var(int v, MonomialInserter &result) const
void wordPrefixFromMonom(Word &result, const Monom &m, int endIndex) const
unsigned int numVars() const
void wordSuffixFromMonom(Word &result, const Monom &m, int beginIndex) const
bool is_one(const Monom &m) const
int wordLength(const Monom &m) const
static size_t mCompares
Static counter for non-commutative monomial comparisons.
std::pair< T *, T * > allocateArray(size_t nelems)
Thin RAII wrapper around memtailor::Arena providing bump-pointer array allocation with optional mutex...
int n_vars() const
Definition monoid.hpp:207
monomial make_one() const
Definition monoid.cpp:455
void one(monomial result) const
Definition monoid.cpp:470
void mult(const_monomial m, const_monomial n, monomial result) const
Definition monoid.cpp:363
void from_expvector(const_exponents exp, monomial result) const
Definition monoid.cpp:742
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
const int * begin() const
Definition Word.hpp:72
const int * end() const
Definition Word.hpp:73
int size() const
Definition Word.hpp:74
Non-owning view of a non-commutative word: [begin, end) of int variable indices.
Definition Word.hpp:56
#define monomial
Definition gb-toric.cpp:11
VALGRIND_MAKE_MEM_DEFINED & result(result)
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
const int * end() const
const int * begin() const
int size() const
Non-owning view onto a [length, degree, v1, v2, ..., vn] packed monomial in some externally managed b...
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39