LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
fglm.cpp
浏览该文件的文档.
2#include <map>
3#include <stdexcept>
4#include <string>
5
6namespace LMCAS {
7namespace {
8using namespace fglm_detail;
9
10void generate_standard_degree(Monomial& current, size_t variable, int remaining,
11 const std::vector<Monomial>& leading,
12 std::vector<Monomial>& standard) {
13 if (variable == current.size() - 1) {
14 current[variable] = remaining;
15 if (is_standard(current, leading)) standard.push_back(current);
16 current[variable] = 0;
17 return;
18 }
19 for (int exponent = 0; exponent <= remaining; ++exponent) {
20 current[variable] = exponent;
21 generate_standard_degree(current, variable + 1, remaining - exponent,
22 leading, standard);
23 }
24 current[variable] = 0;
25}
26
27std::vector<Monomial> standard_basis(const std::vector<FGLMPoly>& source_basis,
28 size_t num_vars, int dimension) {
29 auto leading = leading_monomials(source_basis);
30 std::vector<Monomial> standard;
31 for (int degree = 0;
32 degree <= dimension + 2 && static_cast<int>(standard.size()) < dimension;
33 ++degree) {
34 Monomial current(num_vars, 0);
35 generate_standard_degree(current, 0, degree, leading, standard);
36 }
37 return standard;
38}
39
40std::vector<Rational> coordinates(const FGLMPoly& polynomial,
41 const std::map<Monomial, size_t>& index) {
42 std::vector<Rational> vector(index.size(), Rational(0));
43 for (const auto& [monomial, coefficient] : polynomial.terms) {
44 auto found = index.find(monomial);
45 if (found != index.end()) vector[found->second] = coefficient;
46 }
47 return vector;
48}
49
50FGLMPoly dependent_polynomial(const Monomial& monomial,
51 const std::vector<Rational>& combination,
52 const std::vector<Monomial>& basis,
53 const MonomialOrder& order, size_t num_vars) {
54 FGLMPoly result(num_vars);
55 result.add_term(monomial, Rational(1));
56 for (size_t index = 0; index < combination.size() && index < basis.size(); ++index) {
57 if (!combination[index].is_zero()) {
58 result.add_term(basis[index], -combination[index]);
59 }
60 }
61 result.sort_terms(order);
62 result.normalize();
63 if (!result.is_zero()) {
64 Rational leading = result.lead_coeff();
65 if (!(leading == Rational(1))) {
66 for (auto& term : result.terms) term.second = term.second / leading;
67 }
68 }
69 return result;
70}
71
72int checked_dimension(const std::vector<FGLMPoly>& source_basis, size_t num_vars) {
73 if (!is_zero_dimensional(source_basis, num_vars)) {
74 throw std::runtime_error(
75 "FGLM: ideal is not zero-dimensional. "
76 "FGLM only works for zero-dimensional ideals.");
77 }
78 int dimension = quotient_dimension(source_basis, num_vars);
79 if (dimension <= 0 || dimension > 1000) {
80 throw std::runtime_error(
81 "FGLM: quotient dimension is too large or could not be determined. "
82 "dim = " + std::to_string(dimension));
83 }
84 return dimension;
85}
86}
87
88std::vector<FGLMPoly> fglm_convert(const std::vector<FGLMPoly>& source_basis,
89 const MonomialOrder& source_order,
90 const MonomialOrder& target_order,
91 size_t num_vars) {
92 int dimension = checked_dimension(source_basis, num_vars);
93 std::vector<FGLMPoly> target_basis;
94 std::vector<Monomial> basis_monomials;
95 auto standard = standard_basis(source_basis, num_vars, dimension);
96 std::map<Monomial, size_t> monomial_index;
97 for (size_t index = 0; index < standard.size(); ++index) {
98 monomial_index[standard[index]] = index;
99 }
101 fglm_detail::MonomialEnumerator enumerator(num_vars, target_order, dimension + 5);
102 std::vector<Monomial> target_leading;
103 const int max_iterations = dimension * 10 + 50;
104 int iterations = 0;
105 Monomial monomial;
106 while (iterations < max_iterations && enumerator.next(monomial)) {
107 ++iterations;
108 if (!fglm_detail::is_standard(monomial, target_leading)) continue;
109 auto polynomial = FGLMPoly::from_monomial(monomial, num_vars);
110 auto normal = normal_form(polynomial, source_basis, source_order);
111 auto vector = coordinates(normal, monomial_index);
112 std::vector<Rational> combination;
113 if (gauss.add_vector(vector, combination)) {
114 basis_monomials.push_back(monomial);
115 } else {
116 auto dependent = dependent_polynomial(monomial, combination,
117 basis_monomials, target_order,
118 num_vars);
119 if (!dependent.is_zero()) {
120 target_leading.push_back(dependent.lead_monomial());
121 target_basis.push_back(std::move(dependent));
122 }
123 }
124 if (static_cast<int>(basis_monomials.size()) == dimension &&
125 fglm_detail::has_pure_generators(target_leading, num_vars)) {
126 return target_basis;
127 }
128 }
129 throw std::runtime_error(
130 "FGLM: enumeration ended before the target basis was complete");
131}
132
133std::vector<FGLMPoly> grevlex_to_lex(const std::vector<FGLMPoly>& grevlex_basis,
134 size_t num_vars) {
135 return fglm_convert(grevlex_basis, MonomialOrder::grevlex(),
136 MonomialOrder::lex(), num_vars);
137}
138}
单项式序比较器,支持 Lex、GrevLex、DegLex、DegRevLex
static MonomialOrder lex()
创建字典序
static MonomialOrder grevlex()
创建分次逆字典序
bool add_vector(const std::vector< Rational > &vector, std::vector< Rational > &combination)
std::vector< Monomial > standard_basis(const std::vector< FGLMPoly > &source_basis, size_t num_vars, int dimension)
FGLMPoly dependent_polynomial(const Monomial &monomial, const std::vector< Rational > &combination, const std::vector< Monomial > &basis, const MonomialOrder &order, size_t num_vars)
int checked_dimension(const std::vector< FGLMPoly > &source_basis, size_t num_vars)
void generate_standard_degree(Monomial &current, size_t variable, int remaining, const std::vector< Monomial > &leading, std::vector< Monomial > &standard)
std::vector< Rational > coordinates(const FGLMPoly &polynomial, const std::map< Monomial, size_t > &index)
std::vector< Monomial > leading_monomials(const std::vector< FGLMPoly > &basis)
bool is_standard(const Monomial &monomial, const std::vector< Monomial > &leading)
bool has_pure_generators(const std::vector< Monomial > &leading, size_t num_vars)
const std::string & variable
std::vector< int > Monomial
单项式类型,以整数向量表示各变量的指数
const std::vector< FGLMPoly > const MonomialOrder & order
std::vector< FGLMPoly > fglm_convert(const std::vector< FGLMPoly > &source_basis, const MonomialOrder &source_order, const MonomialOrder &target_order, size_t num_vars)
bool is_zero_dimensional(const std::vector< FGLMPoly > &basis, size_t num_vars)
int quotient_dimension(const std::vector< FGLMPoly > &basis, size_t num_vars, int max_degree)
const ExprPtr & exponent
std::vector< FGLMPoly > grevlex_to_lex(const std::vector< FGLMPoly > &grevlex_basis, size_t num_vars)
const std::vector< FGLMPoly > & basis
FGLMPoly normal_form(const FGLMPoly &f, const std::vector< FGLMPoly > &basis, const MonomialOrder &order)