Macaulay2 Engine
Loading...
Searching...
No Matches
franzi-gb.cpp
Go to the documentation of this file.
1/* This code written by Franziska Hinkelmann is in the public domain */
2
3#include "franzi-brp.hpp"
4#include <sys/time.h>
5#include <set>
6#include <time.h>
7
8//#define DEBBBB false;
9
22// pair of indices
23// negative index -i for field polynomial x_i^2+x_i
24class Pair
25{
26 // order with respect to lcm in lex ordering
27 friend bool operator<(const Pair &pair1, const Pair &pair2)
28 {
29 if (pair1.lcm < pair2.lcm)
30 {
31 return true;
32 }
33 else if (pair1.lcm > pair2.lcm)
34 {
35 return false;
36 }
37 else
38 {
39 if (pair1.j < pair2.j)
40 {
41 return true;
42 }
43 else if (pair1.j > pair2.j)
44 {
45 return false;
46 }
47 else
48 {
49 return pair1.i < pair2.i;
50 }
51 }
52 }
53
54 public:
55 int i;
56 int j;
57 bool good;
58 brMonomial lcm; // lcm of LTs of fi and fj
59
60 Pair(int a, int b, const IntermediateBasis &F)
61 {
62 if (a < b)
63 {
64 i = a;
65 j = b;
66 }
67 else if (b < a)
68 {
69 i = b;
70 j = a;
71 }
72 else
73 {
74 throw "Invalid numbers in Pair";
75 }
76 IntermediateBasis::const_iterator end = F.end();
77 if (F.find(j) == end || (i >= 0 && F.find(i) == end))
78 { // fi or fj are not in F anymore
79 lcm = 0; // constant 1
80 good = false;
81 }
82 else
83 {
84 if (i < 0)
85 { // working with field polynomial
86 lcm = F.find(j)->second.LT();
87 good = true; // BRP::isDivisibleBy(lcm, BRP( 1 << n-(-i) ) );
88 }
89 else
90 {
91 unsigned long a = F.find(i)->second.LT();
92 unsigned long b = F.find(j)->second.LT();
93 lcm = a | b;
95 }
96 }
97 }
98};
99
100// set of index pairs
101// always ordered
102typedef std::set<Pair> Pairs;
103
117// functions f and g, corresponding to index pair j and i, respectively
119{
121
122 public:
123 const BRP *f;
124 const BRP *g;
125 bool good;
126
127 // i < j
128 FunctionPair(const Pair &pair, const IntermediateBasis &F, int n)
129 {
130 int i = pair.i;
131 int j = pair.j;
132
133 IntermediateBasis::const_iterator end = F.end();
134 if (F.find(j) == end || (i >= 0 && F.find(i) == end))
135 {
136 good = false;
137 }
138 else
139 {
140 good = true;
141 if (i < 0)
142 { // working with field polynomial, generate x_(-i)
143 // g = BRP( 1 << n-(-i) );
144 fieldpolynomial = BRP(1 << (n - (-i)));
146 }
147 else
148 {
149 g = &F.find(i)->second;
150 }
151 f = &F.find(j)->second;
152 }
153 }
154};
155
156// generate list of index pairs for given intermediate basis
157// first insert all pairs with FPs, then insert pairs of all other polynomials
158// the list of indices was ordered by increasingly
160{
161 Pairs B;
162 Pairs::iterator position = B.begin();
163 IntermediateBasis::const_iterator end = F.end();
164 for (IntermediateBasis::const_iterator iter = F.begin(); iter != end; ++iter)
165 {
166 int j = iter->first;
167 for (int i = -n; i < 0; i++)
168 {
169 Pair pair = Pair(i, j, F);
170 position = B.insert(position, pair);
171 }
172 for (int i = 0; i < j; i++)
173 {
174 Pair pair = Pair(i, j, F);
175 if (pair.good)
176 {
177 position = B.insert(position, pair);
178 }
179 }
180 }
181 return B;
182}
183
184// generate list of index pairs for a new index and an intermediate basis
185Pairs makeNewPairs(int newIndex, const IntermediateBasis &F, int n)
186{
187 Pairs B;
188 Pairs::iterator position = B.begin();
189 for (int i = -n; i < 0; i++)
190 {
191 Pair pair = Pair(i, newIndex, F);
192 position = B.insert(position, pair);
193 }
194 IntermediateBasis::const_iterator end = F.end();
195 end--;
196 for (IntermediateBasis::const_iterator iter = F.begin(); iter != end; ++iter)
197 {
198 int j = iter->first;
199 Pair pair = Pair(newIndex, j, F);
200 if (pair.good)
201 {
202 position = B.insert(position, pair);
203 }
204 }
205 return B;
206}
207
208// return true if pair (i,j) is in the list of indices
209bool inList(int i, int j, const Pairs &B, const IntermediateBasis &F)
210{
211 Pair p = Pair(i, j, F);
212 return B.find(p) != B.end();
213}
214
215// return true if both functions with indices of pair are in the intermediate
216// basis and their S polynomial should be computed
217bool isGoodPair(const Pair &pair,
218 const IntermediateBasis &F,
219 const Pairs &B,
220 int n)
221{
222 FunctionPair fp = FunctionPair(pair, F, n);
223 if (!fp.good)
224 {
225 return false;
226 }
227
228 // both polynomials are monomials, so their S polynomial reduces to 0
229 if (fp.g->size() == 1 && fp.f->size() == 1)
230 {
231 // cout << "m ";
232 return false;
233 }
234
235 brMonomial g = fp.g->LT();
236 brMonomial f = fp.f->LT();
237 if (BRP::isRelativelyPrime(g, f))
238 {
239 return false;
240 }
241
242 int i = pair.i;
243 int j = pair.j;
244
245 brMonomial lcm = pair.lcm;
246 IntermediateBasis::const_iterator end = F.end();
247 for (IntermediateBasis::const_iterator it = F.begin(); it != end; ++it)
248 {
249 int k = it->first;
250 const BRP *K = &(it->second);
251
252 if ((k != i && k != j && BRP::isDivisibleBy(lcm, K->LT()) &&
253 !inList(i, k, B, F) && !inList(j, k, B, F)))
254 {
255 return false;
256 }
257 }
258
259 // cout << "good pair ";
260 return true;
261}
262
263// compute S polynomial for a pair
264BRP sPolynomial(const Pair &pair, const IntermediateBasis &F, int n)
265{
266 FunctionPair fp = FunctionPair(pair, F, n);
267 if (!fp.good)
268 {
269 return BRP();
270 }
271
272 if (pair.i < 0)
273 {
274 // fp.g = x_i
275 // f = ax + b
276 BRP b = (fp.f)->remainder(*fp.g);
277 return b * *fp.g + b;
278 }
279 brMonomial f = fp.f->LT();
280 brMonomial g = fp.g->LT();
281 brMonomial lcm = f | g;
282 return *fp.f * (lcm ^ f) + *fp.g * (lcm ^ g);
283}
284
285// modifies f, cancels the lead term once, f must be non zero
286void cancelLeadTerm(BRP &f, const BRP &g)
287{
288 brMonomial a = f.LT() ^ g.LT();
289 f + g *a;
290}
291
292// find the first basis element that reduces the leading term of f, if none
293// found return end()
294// return end() if f == 0
295IntermediateBasis::const_iterator findDivisor(
296 const BRP &f,
297 const IntermediateBasis &F,
298 const IntermediateBasis::const_iterator itF)
299{
300 IntermediateBasis::const_iterator end = F.end();
301 for (IntermediateBasis::const_iterator it = F.begin();
302 it != end && !f.isZero();
303 ++it)
304 {
305 if (itF != it)
306 {
307 if (f.isLeadingReducibleBy(it->second))
308 {
309 return it;
310 }
311 }
312 }
313 return end;
314}
315
316// Reduce the leading term of f one step with the first polynomial g_i in the
317// intermediate basis that satisfies isLeadingReducibleBy(f,g_i)
318bool reduceLt(BRP &f,
319 const IntermediateBasis &F,
320 const IntermediateBasis::const_iterator itF)
321{
322 bool ret = false; // true if anything was reduced
323 IntermediateBasis::const_iterator it;
324 IntermediateBasis::const_iterator end = F.end();
325 while (!f.isZero() && (it = findDivisor(f, F, itF)) != end)
326 {
327 ret = true;
328 cancelLeadTerm(f, it->second);
329 }
330 return ret;
331}
332
333// reduce tail of f with leading terms of all polynomials in F
335 const IntermediateBasis &F,
336 const IntermediateBasis::const_iterator itF)
337{
338 IntermediateBasis::const_iterator end = F.end();
339 bool ret = false;
340 for (IntermediateBasis::const_iterator it = F.begin();
341 it != end && !f.isZero();
342 ++it)
343 {
344 if (itF != it)
345 {
346 if (f.reduceTail(it->second))
347 {
348 it = F.begin();
349 ret = true;
350 }
351 }
352 }
353 return ret;
354}
355
356// reduce all terms in f by the leading terms of all polynomials in F
357// first reduce the leading term completely, then the lower terms
358bool reduce(BRP &f,
359 const IntermediateBasis &F,
360 const IntermediateBasis::const_iterator itF)
361{
362 bool ret = false;
363 ret = reduceLt(f, F, itF);
364 if (!f.isZero())
365 {
366 if (reduceTail(f, F, itF))
367 {
368 ret = true;
369 }
370 }
371 return ret;
372}
373
374void reduce(BRP &f, const IntermediateBasis &F) { reduce(f, F, F.end()); }
375// some effort could be saved on average if we arranged the
376// f i so that their leading terms are listed in increasing order with respect
377// to the cho-
378// sen monomial ordering
379void rearrangeBasis(IntermediateBasis &F, int nextIndex)
380{
381 for (IntermediateBasis::iterator j = F.begin(); j != F.end(); ++j)
382 {
383 if (j->first != nextIndex)
384 {
385 for (IntermediateBasis::iterator i = F.begin(); i->first < j->first;
386 ++i)
387 {
388 // if ( funccompGRL(i->second.LT(), j->second.LT() )) {
389 if (i->second.LT() > j->second.LT())
390 {
391 BRP tmp = i->second;
392 i->second = j->second;
393 j->second = tmp;
394 }
395 }
396 }
397 }
398}
399
400// interreduction
402{
403 bool changesHappened = true;
404 IntermediateBasis::iterator end = F.end();
405 unsigned long numChanged = 0;
406 while (changesHappened)
407 {
408 changesHappened = false;
409 for (IntermediateBasis::iterator it = F.begin(); it != end;)
410 {
411 if (reduce(it->second, F, it))
412 {
413 // we changed it
414 numChanged++;
415 if (it->second.isZero())
416 { // reduced an element to 0, remove it from F
417 F.erase(it++);
418 }
419 else
420 {
421 ++it;
422 }
423 changesHappened = true;
424 }
425 else
426 {
427 ++it;
428 }
429 }
430 }
431}
432
433// complete algorithm to compute a Groebner basis F
434void gb(IntermediateBasis &F, int n)
435{
436 int nextIndex = static_cast<int>(F.size());
437 rearrangeBasis(F, -1);
439 Pairs B = makeList(F, n);
440 // unsigned int countAddPoly = 0;
441 // unsigned int numSPoly= 0;
442 int interreductionCounter = 0;
443 while (!B.empty())
444 {
445 Pair pair = *(B.begin());
446 B.erase(B.begin());
447 if (isGoodPair(pair, F, B, n))
448 {
449 // numSPoly++;
450 BRP S = sPolynomial(pair, F, n);
451 reduce(S, F);
452 if (!S.isZero())
453 {
454 // countAddPoly++;
455 F[nextIndex] = S;
456 if (interreductionCounter == 5)
457 {
458 interreductionCounter = 0;
460 B = makeList(F, n);
461 }
462 else
463 {
464 interreductionCounter++;
465 Pairs newList = makeNewPairs(nextIndex, F, n);
466 B.insert(newList.begin(), newList.end());
467 }
468 nextIndex++;
469 }
470 }
471 }
473 // cout << "we computed " << numSPoly << " S Polynomials and added " <<
474 // countAddPoly << " of them to the intermediate basis." << endl;
475}
static bool isDivisibleBy(const brMonomial &a, const brMonomial &b)
bool reduceTail(const BRP &g)
bool isLeadingReducibleBy(const BRP &other) const
brMonomial LT() const
bool isZero() const
static bool isRelativelyPrime(const brMonomial &a, const brMonomial &b)
unsigned int size() const
Boolean (F_2-coefficient) polynomial stored as an ordered list of square-free monomials.
const BRP * g
const BRP * f
FunctionPair(const Pair &pair, const IntermediateBasis &F, int n)
Materialised (f, g) pair of BRP polynomials referenced by a Pair index record.
int i
Definition franzi-gb.cpp:55
bool good
Definition franzi-gb.cpp:57
int j
Definition franzi-gb.cpp:56
Pair(int a, int b, const IntermediateBasis &F)
Definition franzi-gb.cpp:60
friend bool operator<(const Pair &pair1, const Pair &pair2)
Definition franzi-gb.cpp:27
brMonomial lcm
Definition franzi-gb.cpp:58
S-pair record for the Franzi boolean Groebner basis algorithm.
Definition franzi-gb.cpp:25
unsigned long brMonomial
std::map< int, BRP > IntermediateBasis
brMonomial — bit-packed Boolean-ring monomials for the Hinkelmann GB engine.
Pairs makeList(const IntermediateBasis &F, int n)
void cancelLeadTerm(BRP &f, const BRP &g)
void gb(IntermediateBasis &F, int n)
void interreduction(IntermediateBasis &F)
Pairs makeNewPairs(int newIndex, const IntermediateBasis &F, int n)
BRP sPolynomial(const Pair &pair, const IntermediateBasis &F, int n)
bool reduceTail(BRP &f, const IntermediateBasis &F, const IntermediateBasis::const_iterator itF)
IntermediateBasis::const_iterator findDivisor(const BRP &f, const IntermediateBasis &F, const IntermediateBasis::const_iterator itF)
void rearrangeBasis(IntermediateBasis &F, int nextIndex)
bool inList(int i, int j, const Pairs &B, const IntermediateBasis &F)
bool isGoodPair(const Pair &pair, const IntermediateBasis &F, const Pairs &B, int n)
std::set< Pair > Pairs
bool reduceLt(BRP &f, const IntermediateBasis &F, const IntermediateBasis::const_iterator itF)
bool reduce(BRP &f, const IntermediateBasis &F, const IntermediateBasis::const_iterator itF)
int p
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5