1 #ifndef __ALGORITHM_BUCHBERGER_EXPLORER_CPP_ 2 #define __ALGORITHM_BUCHBERGER_EXPLORER_CPP_ 24 #include "hilbert_functions.hpp" 26 #include "algorithm_buchberger_basic.hpp" 28 #include "reduction_support.hpp" 30 #include "algorithm_buchberger_explorer.hpp" 34 #define XPLOR_GENERATOR -1 35 #define PROC_UNASSIGNED -1 37 #define HILBERT_COMPARISON 0 38 #define SUGAR_COMPARISON 1 39 #define WHICH_COMPARISON SUGAR_COMPARISON 54 pi = i;
qi = XPLOR_GENERATOR;
proc = PROC_UNASSIGNED;
58 int i,
int j,
StrategyFlags strategy, vector<Abstract_Polynomial *>G
62 pi = i;
qi = j;
proc = PROC_UNASSIGNED;
67 vector<Abstract_Polynomial *>G
71 pi = i;
qi = G.size();
proc = PROC_UNASSIGNED;
82 return (static_cast<Pair_Sugar_Data *>(
key))->pair_sugar();
110 bool second_HF_smaller(
131 i <= h1->
degree() and i <= h2->
degree() and (*h1)[i] == (*h2)[i];
144 if (i > h2->
degree()) result =
false;
145 else result = (*h1)[i] < (*h2)[i];
178 i <= h1->
degree() and i <= h2->
degree() and (*h1)[i] == (*h2)[i];
186 while (i < n and t[i] == u[i]) ++i;
187 if (i == n) result =
false;
195 if (i > h2->
degree()) result =
false;
196 else result = (*h1)[i] < (*h2)[i];
217 void hilbert_chooser(
218 void * firstin,
void * secondin,
int * len, MPI_Datatype * dptr
220 int64_t *
first = (int64_t *)firstin;
221 int64_t *
second = (int64_t *)secondin;
222 bool undecided =
true;
223 bool keep_second =
true;
224 if (first[0] == -1 or second[0] == -1) {
231 int64_t n = first[1];
232 for (i = 0; undecided and i <= n; ++i)
233 undecided = (first[2*i + 2]*second[2*i+3] == second[2*i + 2]*first[2*i+3]);
236 keep_second = (first[2*i + 2]*second[2*i+3] >= second[2*i + 2]*first[2*i+3]);
239 for (i = 2*(n + 1) + 2; undecided and i < *len; ++i)
240 undecided = (first[i] == second[i]);
242 keep_second = undecided or first[i] < second[i];
247 for (
unsigned i = 0; i < *len; ++i)
248 second[i] = first[i];
256 void * firstin,
void * secondin,
int * len, MPI_Datatype * dptr
258 int64_t *
first = (int64_t *)firstin;
259 int64_t *
second = (int64_t *)secondin;
260 int64_t n = first[2];
261 bool keep_second =
true;
262 if (first[1] == -1) {
264 }
else if (second[1] == -1 or first[2] > second[2]) {
266 }
else if (first[1] > second[1]) {
273 for (
unsigned i = 0; i < n; ++i) {
279 if (not keep_second) {
280 for (
unsigned i = 0; i < n + 3; ++i)
281 second[i] = first[i];
297 list<Critical_Pair_XPlor *> & P,
298 list<Critical_Pair_XPlor *> & Pass,
299 list<Critical_Pair_XPlor *> * Pcancel,
300 vector<Abstract_Polynomial *> & G,
305 list<Critical_Pair_XPlor *> C;
310 unsigned m = G.size();
311 for (
unsigned i = 0; i < G.size(); ++i)
315 list<Critical_Pair_XPlor *> D;
316 while (C.size() != 0) {
332 list<Critical_Pair_XPlor *> E;
333 while (D.size() != 0) {
347 list<Critical_Pair_XPlor *> Q;
348 while (P.size() != 0) {
364 list <Critical_Pair_XPlor *> R;
365 while (Pass.size() != 0) {
411 const vector<Abstract_Polynomial *> &F,
414 WT_TYPE * strategy_weights,
418 double r_bcast_time = 0;
419 unsigned number_of_spolys = 0;
420 vector<Abstract_Polynomial *> G;
421 list<Critical_Pair_XPlor *> P;
422 list<Critical_Pair_XPlor *> Pass, * Pdel;
423 list<Critical_Pair_XPlor *> R;
424 list<Constant_Polynomial *> B;
428 MPI_Datatype pair_type, pair_basetypes[2];
429 MPI_Aint pair_offsets[2], extent, lb;
430 int pair_block_counts[2];
431 pair_offsets[0] = 0; pair_basetypes[0] = MPI_INT; pair_block_counts[0] = 2;
432 MPI_Type_get_extent(MPI_INT, &lb, &extent);
433 pair_offsets[1] = 2 * extent; pair_basetypes[1] = MPI_UNSIGNED_LONG_LONG;
434 pair_block_counts[1] = 1;
435 MPI_Type_create_struct(2, pair_block_counts, pair_offsets, pair_basetypes, &pair_type);
436 MPI_Type_commit(&pair_type);
438 MPI_Op comparison_op;
439 #if (WHICH_COMPARISON == HILBERT_COMPARISON) 440 MPI_Op_create(hilbert_chooser,
false, &comparison_op);
442 MPI_Op_create(sugar_chooser,
false, &comparison_op);
445 vector<Abstract_Polynomial *>::const_iterator Fi = F.begin();
446 NVAR_TYPE n = (*Fi)->number_of_variables();
447 for (
unsigned i = 0; i < F.size(); ++i, ++Fi)
457 bool verbose =
false;
458 bool very_verbose =
false;
459 unsigned min_todo = 0;
461 Pdel =
new list<Critical_Pair_XPlor *>[comm_size];
470 MPI_Bcast(&min_todo, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);
476 int number_in_package;
477 while (min_todo != 0) {
487 uint64_t my_sugar = (R.size() == 0) ? 0 : R.front()->
sugar();
489 MPI_Reduce(&my_sugar, &curr_sugar, 1, MPI_UINT64_T, MPI_MAX, 0, MPI_COMM_WORLD);
493 cout <<
"estimate " << min_todo <<
" steps left\n";
497 if (curr_sugar == 0 and !P.empty()) {
498 curr_sugar = P.front()->
sugar();
499 for (list<Critical_Pair_XPlor *>::iterator
pi = P.begin();
pi != P.end(); ++
pi)
500 if ((*pi)->sugar() < curr_sugar)
501 curr_sugar = (*pi)->sugar();
503 cout <<
"current sugar: " << curr_sugar << endl;
504 unsigned num_of_curr_sugar = 0;
505 for (list<Critical_Pair_XPlor *>::iterator
pi = P.begin();
509 if ((*pi)->sugar() == curr_sugar) ++num_of_curr_sugar;
511 number_in_package = 0;
512 if (num_of_curr_sugar == 0)
513 for (
unsigned i = 1; i < comm_size; ++i)
514 MPI_Send(&number_in_package, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
516 unsigned distrib_size = num_of_curr_sugar / comm_size + 1;
518 list<Critical_Pair_XPlor *> Q;
519 for (
unsigned i = 1; i < comm_size; ++i) {
520 number_in_package = 0;
521 while (!P.empty() and number_in_package < distrib_size)
525 if (p->
sugar() != curr_sugar)
536 MPI_Send(&number_in_package, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
537 if (number_in_package > 0)
538 MPI_Send(Pnew, number_in_package, pair_type, i, 0, MPI_COMM_WORLD);
540 number_in_package = 0;
541 while (!P.empty() and number_in_package < distrib_size)
545 if (p->
sugar() != curr_sugar)
593 MPI_Barrier(MPI_COMM_WORLD);
595 MPI_Recv(&number_in_package, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
596 if (number_in_package > 0) {
598 MPI_Recv(Pnew, number_in_package, pair_type, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
601 for (
unsigned i = 0; i < number_in_package; ++i) {
603 if (Pin.
second == XPLOR_GENERATOR)
605 Pin.
first, StrategyFlags::SUGAR_STRATEGY, F[Pin.
first]
609 Pin.
first, Pin.
second, StrategyFlags::SUGAR_STRATEGY, G
612 if (number_in_package > 0)
634 double start_time = MPI_Wtime();
637 if ((s =
p->s_polynomial()) ==
nullptr) {
638 s =
p->s_polynomial(method, strategy);
655 r_bcast_time += MPI_Wtime() - start_time;
664 unsigned winning_index = R.size() + 1;
666 #if (WHICH_COMPARISON == HILBERT_COMPARISON) 676 list<Critical_Pair_XPlor *>::iterator Rbest = R.end();
679 list<Critical_Pair_XPlor *>::iterator Ri = R.begin();
683 s = (*Ri)->s_polynomial();
688 if (Ri == R.begin()) {
692 list<Critical_Pair_XPlor *>::iterator Rdel = Ri;
698 #if (WHICH_COMPARISON == HILBERT_COMPARISON) 700 unsigned n = T.front().num_vars();
709 if (second_HF_smaller(wHP, wHS, hp, hn)) {
755 #if (WHICH_COMPARISON == HILBERT_COMPARISON) 756 int hp_deg = (wt ==
nullptr) ? -1 : hp->
degree();
758 MPI_Allreduce(&hp_deg, &recv_hp_deg, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
760 if (recv_hp_deg != -1) {
761 int hn_deg = (wHP ==
nullptr) ? -1 : wHS->
degree();
763 MPI_Allreduce(&hn_deg, &recv_hn_deg, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
764 int xfer_size = 2*(recv_hp_deg +1) + (recv_hn_deg + 1) + 2;
765 int64_t * send_data =
new int64_t[xfer_size];
769 send_data[0] = comm_id; send_data[1] = recv_hp_deg;
771 for ( ; hi < recv_hp_deg - wHP->
degree(); ++hi)
772 send_data[2*hi + 2] = send_data[2*hi + 3] = 0;
773 for ( ; hi <= recv_hp_deg; ++hi) {
774 send_data[2*hi + 2] = wHP->
numerator(recv_hp_deg - hi);
775 send_data[2*hi + 3] = wHP->
denominator(recv_hp_deg - hi);
777 for (hi = 0; hi <= wHS->
degree(); ++hi)
778 send_data[2 + 2*(recv_hp_deg + 1) + hi] = wHS->
coeff(hi);
780 hi = 2 + 2*(recv_hp_deg + 1) + wHS->
degree() + 1;
787 int64_t * recv_data =
new int64_t[xfer_size];
789 send_data, recv_data, xfer_size, MPI_INT64_T, comparison_op,
792 winners_id = recv_data[0];
793 delete [] send_data;
delete [] recv_data;
796 int64_t * send_data =
new int64_t[n + 3];
797 int64_t * recv_data =
new int64_t[n + 3];
798 send_data[0] = comm_id; send_data[1] = wd; send_data[2] = n;
800 for (
unsigned i = 0; i < n; ++i)
801 send_data[i + 3] = wt->
degree(i);
804 send_data, recv_data, n + 3, MPI_INT64_T, comparison_op,
807 winners_id = (recv_data[1] == -1) ? -1 : recv_data[0];
808 delete [] send_data;
delete [] recv_data;
815 if (winners_id >= 0) {
817 uint64_t r_bcast_size;
818 uint64_t r_bcast_sugar;
820 if (comm_id == winners_id) {
823 pair_data[0] = (*Rbest)->first_index();
824 pair_data[1] = (*Rbest)->second_index();
826 MPI_Send(pair_data, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
828 s = (*Rbest)->s_polynomial();
833 cout <<
"selected " << (*Rbest)->first_index()
835 <<
',' << sd->
poly_sugar() <<
" from " << winners_id << endl;
844 if (comm_id == 0 and winners_id != 0) {
846 MPI_Recv(pair_data, 2, MPI_INT, winners_id, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
848 list<Critical_Pair_XPlor *>::iterator Ri;
849 for (Ri = Pass.begin(); not found and Ri != Pass.end(); ) {
850 if ((*Ri)->first_index() == pair_data[0] and (*Ri)->second_index() == pair_data[1])
862 MPI_Bcast(&r_bcast_size, 1, MPI_UINT64_T, winners_id, MPI_COMM_WORLD);
863 if (comm_id != winners_id)
864 r_bcast =
new uint64_t [r_bcast_size];
866 MPI_Bcast(r_bcast, r_bcast_size, MPI_UINT64_T, winners_id, MPI_COMM_WORLD);
868 MPI_Bcast(&r_bcast_sugar, 1, MPI_UINT64_T, winners_id, MPI_COMM_WORLD);
870 if (comm_id != winners_id) {
871 r_bcast_size /= n + 1;
884 very_verbose =
false;
885 if (very_verbose) { cout <<
"\tin full "; r->println(); }
886 very_verbose =
false;
889 for (
int i = 1; i < comm_size; ++i) {
890 int outgoing = Pdel[i].size();
891 MPI_Send(&outgoing, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
892 while (Pdel[i].size() > 0) {
898 MPI_Send(&p_new, 1, pair_type, i, 0, MPI_COMM_WORLD);
903 while (Pdel[0].size() > 0) {
906 list<Critical_Pair_XPlor *>::iterator Ri = R.begin();
922 MPI_Recv(&incoming, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
923 for (
int j = 0; j < incoming; ++j) {
924 MPI_Recv(&p_in, 1, pair_type, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
925 list<Critical_Pair_XPlor *>::iterator Ri = R.begin();
928 ((*Ri)->first_index() != p_in.
first or
929 (*Ri)->second_index() != p_in.
second)
956 if (comm_id == 0) min_todo = P.size();
957 unsigned my_todo = R.size();
959 MPI_Reduce(&my_todo, &all_todo, 1, MPI_UNSIGNED, MPI_MAX, 0, MPI_COMM_WORLD);
961 min_todo = min_todo < all_todo ? all_todo : min_todo;
962 MPI_Bcast(&min_todo, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);
977 MPI_Type_free(&pair_type);
978 cout << comm_id <<
" reduced " << number_of_spolys << endl;
981 MPI_Reduce(&number_of_spolys, &total_spolys, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
982 double max_bcast_time;
983 MPI_Reduce(&r_bcast_time, &max_bcast_time, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
984 for (
unsigned i = 0; i < comm_size; ++i) {
986 cout << comm_id <<
" took " << r_bcast_time <<
" milliseconds on timed segment(s).\n";
987 MPI_Barrier(MPI_COMM_WORLD);
990 cout << total_spolys <<
" s-polynomials computed and reduced\n";
991 cout << max_bcast_time <<
" seconds spent on timed segment(s)\n";
993 cout << G.size() <<
" polynomials before interreduction\n";
995 list<Abstract_Polynomial *> G_final;
997 G_final.push_back(g);
999 cout << G_final.size() <<
" polynomials after interreduction\n";
The general class of a polynomial.
list< Constant_Polynomial * > buchberger_explorer(const vector< Abstract_Polynomial *> &F, SPolyCreationFlags method, StrategyFlags strategy, WT_TYPE *strategy_weights, const int comm_id, const int comm_size)
Alternate implementation of Buchberger’s algorithm, for parallelization.
virtual bool is_zero() const =0
is this polynomial zero?
MPZCOEF_TYPE numerator(DEG_TYPE k) const
returns the th numerator
int second
index of second polynomial in the pair
A Constant_Polynomial is a polynomial that should not change.
void sort_pairs_by_strategy(list< T *> &P)
Applies the strategy to find the “smallest” critical pair.
int first
index of first polynomial in the pair
Dense_Univariate_Rational_Polynomial * hilbert_polynomial(NVAR_TYPE n, unsigned int pole_order, const list< Monomial > T, Dense_Univariate_Integer_Polynomial *hn, Dense_Univariate_Integer_Polynomial *hn2)
computes the Hilbert polynomial for an ideal
bool is_zero() const
indicates whether the polynomial is zero
Critical_Pair_XPlor(int i, int j, StrategyFlags strategy, vector< Abstract_Polynomial *>G)
create critical pair (f,g) where f, g are at indices i, j
const Abstract_Polynomial * second() const
second polynomial in pair
void gm_update_explorer(list< Critical_Pair_XPlor *> &P, list< Critical_Pair_XPlor *> &Pass, list< Critical_Pair_XPlor *> *Pcancel, vector< Abstract_Polynomial *> &G, Abstract_Polynomial *r, StrategyFlags strategy)
Implementation of Gebauer-Moeller algorithm, with XPLOR critical pairs. Based on description in Becke...
Mutable_Polynomial * s
S-polynomial.
int first_index()
returns index of first polynomial in pair
used to pass inforation on a critical pair from one polynomial to another
virtual Monomial & leading_monomial() const =0
leading monomial – call after sort_by_order()!
const Monomial & lcm() const
lcm of leading monomials of polynomials
int get_processor()
query whether this pair is assigned to a processor, and which (nonnegative value indicates assignment...
Dense_Univariate_Integer_Polynomial * hilbert_second_numerator(NVAR_TYPE n, Dense_Univariate_Integer_Polynomial *first, const WT_TYPE *grading)
computes the second Hilbert numerator (after reduction by )
void set_exponent(NVAR_TYPE i, DEG_TYPE e)
change th exponent to
void set_processor(int i)
record that this pair is assigned to processor i
int second_index()
returns index of second polynomial in pair
COEF_TYPE coeff(DEG_TYPE k) const
the th coefficient
uint64_t * serialized(uint64_t &size)
Dense_Univariate_Integer_Polynomial * hilbert_numerator_bigatti(const list< Monomial > &T, const WT_TYPE *grading)
the Bigatti algorithm to compute the Hilbert numerator
quick-’n-dirty Dense_Univariate integer polynomial class
DEG_TYPE poly_sugar() const
the sugar itself
void reduce_over_basis(Mutable_Polynomial **sp, const T &G, int comm_id=0)
Reduce the polynomial r over the basis G.
virtual void at_generation_tasks()
hook called while first generating polynomial
StrategyFlags
flag indicating which strategy to use for computation
list< Abstract_Polynomial * > reduce_basis(list< Abstract_Polynomial *>G)
Remove redundant polynomials from G.
SPolyCreationFlags
flag indicating which structure to use for an s-polynomial
DEG_TYPE size
number of slots for coefficients
Critical_Pair_XPlor(int i, Abstract_Polynomial *g, StrategyFlags strategy, vector< Abstract_Polynomial *>G)
create critical pair (f,g) where f is at index i
int qi
second polynomial in the critical pair
bool lcm_alike(const Monomial &t, const Monomial &u, const Critical_Pair_Basic *p)
Checks if the lcm of t and u is like the lcm stored in p.
NVAR_TYPE num_vars() const
number of variables
Polynomials that need arithmetic typically descend from this class.
const Abstract_Polynomial * first() const
first polynomial in pair
virtual Monomial & leading_monomial() const override
Implementation of monomials.
interface to a monomial ordering
polynomial-related data for a sugar strategy
Encapsulates information about a polynomial ring for easy access: ground field, number of indetermina...
int pi
first polynomial in the critical pair
Critical_Pair_XPlor(int i, StrategyFlags strategy, Abstract_Polynomial *f)
create critical pair (f,0) where f is at index i
bool is_coprime(const Monomial &other) const
true iff this has no common factor with other.
DEG_TYPE degree(NVAR_TYPE i) const
Degree of th variable.
Pair_Strategy_Data * key
strategy used to sort critical pairs
void top_reduce(Mutable_Polynomial *s, Abstract_Polynomial *g, int comm_id)
reduce the polynomial **sp by *g
void set_strategy(Poly_Strategy_Data *psd)
sets the polynomial’s strategy to psd
DEG_TYPE sugar()
returns sugar of this pair; use ONLY if with sugar strategy
void force_sugar(DEG_TYPE new_sugar)
for those times when a different sugar is appropriate
DEG_TYPE degree() const
the polynomial’s degree (exponent of largest nonzero term)
bool no_triplet(const T *p, const list< T *>C)
Checks whether p is in danger of forming a Buchberger triple with some pair listed in C...
quick-’n-dirty Dense_Univariate rational polynomial class
int proc
processor to which this pair has been assigned
MPZCOEF_TYPE denominator(DEG_TYPE k) const
returns the th denominator
DEG_TYPE degree() const
returns the polynomial’s degree
Controls the creation of s-polynomials.
unsigned ideal_dimension(NVAR_TYPE n, const Dense_Univariate_Integer_Polynomial *h1, const Dense_Univariate_Integer_Polynomial *h2)
computes the dimension of the ideal by subtracting the Hilbert numerators
DEG_TYPE sugar
pair’s sugar
Abstract_Polynomial * p
first polynomial in the critical pair
Abstract_Polynomial * find_reducer(Abstract_Polynomial *r, const T &G)
Find a polynomial in the basis G that can reduce r.
contains information on critical pairs by their index in the basis, in addition to the usual informat...
virtual Poly_Strategy_Data * strategy() const
strategy related information