LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
solver_groebner_basis.cpp
浏览该文件的文档.
2#include <algorithm>
3#include <functional>
4#include <queue>
5
7namespace {
8using PairQueue = std::priority_queue<SugarPair, std::vector<SugarPair>, std::greater<SugarPair>>;
9
10void initialize_sugar(std::vector<Poly>& basis) {
11 for (auto& polynomial : basis) {
12 if (polynomial.is_zero()) continue;
13 int maximum = 0;
14 for (const auto& [monomial, coefficient] : polynomial.terms) {
15 (void)coefficient;
16 int degree = 0;
17 for (int exponent : monomial) degree += exponent;
18 maximum = std::max(maximum, degree);
19 }
20 polynomial.sugar = maximum;
21 }
22}
23
24PairQueue initial_pairs(const std::vector<Poly>& basis) {
25 PairQueue pairs;
26 for (size_t i = 0; i < basis.size(); ++i) {
27 for (size_t j = i + 1; j < basis.size(); ++j) {
28 pairs.push({i, j, compute_spoly_sugar(basis[i], basis[j])});
29 }
30 }
31 return pairs;
32}
33
34std::vector<Poly> minimal_basis(const std::vector<Poly>& basis) {
35 std::vector<bool> marked(basis.size(), false);
36 for (size_t i = 0; i < basis.size(); ++i) {
37 if (marked[i]) continue;
38 for (size_t j = 0; j < basis.size(); ++j) {
39 if (i == j || marked[j]) continue;
40 if (divides_mono(basis[j].lead_monomial(), basis[i].lead_monomial())) {
41 marked[i] = true;
42 break;
43 }
44 }
45 }
46 std::vector<Poly> minimal;
47 for (size_t i = 0; i < basis.size(); ++i) {
48 if (!marked[i]) minimal.push_back(basis[i]);
49 }
50 return minimal;
51}
52
53void make_monic(Poly& polynomial) {
54 Rational leading = polynomial.lead_coeff();
55 if (leading == Rational(0) || leading == Rational(1)) return;
56 Rational inverse = Rational(1) / leading;
57 Poly monic(polynomial.num_vars);
58 for (const auto& [monomial, coefficient] : polynomial.terms) {
59 monic.add_term(monomial, coefficient * inverse);
60 }
61 polynomial = std::move(monic);
62}
63}
64
65void buchberger(std::vector<Poly>& basis, size_t num_vars) {
66 initialize_sugar(basis);
67 auto pairs = initial_pairs(basis);
68 std::set<std::pair<size_t, size_t>> processed_pairs;
69 while (!pairs.empty()) {
70 auto [i, j, sugar_degree] = pairs.top();
71 pairs.pop();
72 auto canonical_pair = i < j ? std::make_pair(i, j) : std::make_pair(j, i);
73 processed_pairs.insert(canonical_pair);
74 if (coprime_leading_monomials(basis[i], basis[j])) continue;
75 if (chain_criterion(basis, i, j, processed_pairs)) continue;
76 Poly polynomial = s_poly(basis[i], basis[j]);
77 extend_variables(polynomial, num_vars);
78 Poly remainder = reduce(polynomial, basis);
79 if (remainder.is_zero()) continue;
80 remainder.sugar = sugar_degree;
81 size_t new_index = basis.size();
82 basis.push_back(remainder);
83 for (size_t k = 0; k < new_index; ++k) {
84 pairs.push({k, new_index, compute_spoly_sugar(basis[k], basis[new_index])});
85 }
86 }
87}
88
89void reduce_basis(std::vector<Poly>& basis) {
90 auto minimal = minimal_basis(basis);
91 for (size_t i = 0; i < minimal.size(); ++i) {
92 std::vector<Poly> others;
93 for (size_t j = 0; j < minimal.size(); ++j) {
94 if (j != i) others.push_back(minimal[j]);
95 }
96 minimal[i] = reduce(minimal[i], others);
97 }
98 std::vector<Poly> reduced;
99 for (const auto& polynomial : minimal) {
100 if (!polynomial.is_zero()) reduced.push_back(polynomial);
101 }
102 for (auto& polynomial : reduced) make_monic(polynomial);
103 basis = std::move(reduced);
104}
105}
std::priority_queue< SugarPair, std::vector< SugarPair >, std::greater< SugarPair > > PairQueue
bool chain_criterion(const std::vector< Poly > &basis, size_t i, size_t j, const std::set< std::pair< size_t, size_t > > &processed_pairs)
bool coprime_leading_monomials(const Poly &f, const Poly &g)
void extend_variables(Poly &polynomial, size_t count)
Poly s_poly(const Poly &f, const Poly &g)
Poly reduce(Poly polynomial, const std::vector< Poly > &basis)
int compute_spoly_sugar(const Poly &f, const Poly &g)
void reduce_basis(std::vector< Poly > &basis)
bool divides_mono(const Monomial &a, const Monomial &b)
void buchberger(std::vector< Poly > &basis, size_t num_vars)
const ExprPtr & exponent
const std::vector< FGLMPoly > & basis