LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
solver_groebner_builder.cpp
浏览该文件的文档.
2#include <algorithm>
3#include <cmath>
4#include <limits>
5#include <optional>
6
8namespace {
9std::optional<BigInt> integer_exponent(const PowerNode& node) {
10 if (!node.exponent()->is_number()) {
11 return std::nullopt;
12 }
13 auto number = std::dynamic_pointer_cast<const NumberNode>(node.exponent());
14 if (!number) {
15 return std::nullopt;
16 }
17 const auto& value = number->value();
18 if (std::holds_alternative<BigInt>(value)) {
19 return std::get<BigInt>(value);
20 }
21 if (std::holds_alternative<Rational>(value)) {
22 const auto& rational = std::get<Rational>(value);
23 if (rational.is_integer()) {
24 return rational.to_bigint();
25 }
26 }
27 return std::nullopt;
28}
29
30bool power_degrees_fit(const Poly& base, int exponent) {
31 for (const auto& [monomial, coefficient] : base.terms) {
32 (void)coefficient;
33 for (int degree : monomial) {
34 if (degree > std::numeric_limits<int>::max() / exponent) return false;
35 }
36 }
37 return true;
38}
39}
40
41 PolyBuilder::PolyBuilder(const std::vector<std::string>& v, PolyContext& ctx, bool strict)
42 : SymbolicVisitor(&ctx.budget), vars(v), ext_vars(ctx.ext_vars),
44 result(ctx.ext_vars.size()), strict_mode(strict) {}
45
46 void PolyBuilder::visit(const NumberNode& node) {
47 result = Poly(ext_vars.size());
48
49 if (std::holds_alternative<Rational>(node.value())) {
50 result.add_term(std::vector<int>(ext_vars.size(), 0), std::get<Rational>(node.value()));
51 } else if (std::holds_alternative<BigInt>(node.value())) {
52 result.add_term(std::vector<int>(ext_vars.size(), 0), Rational(std::get<BigInt>(node.value())));
53 }
54 }
55
56 void PolyBuilder::visit(const VariableNode& node) {
57 result = Poly(ext_vars.size());
58
59 auto it = node.is_constant() ? ext_vars.end() :
60 std::find(ext_vars.begin(), ext_vars.end(), node.name());
61 if (it != ext_vars.end()) {
62 Monomial m(ext_vars.size(), 0);
63 m[std::distance(ext_vars.begin(), it)] = 1;
64 result.add_term(m, Rational(1));
65 } else {
66
67 if (strict_mode) {
68 failed = true;
69 return;
70 }
71 size_t idx = get_or_create_aux_var(LMCAS::detail::make_node<VariableNode>(node.name(), node.is_constant()));
72
73 result = Poly(ext_vars.size());
74 Monomial m(ext_vars.size(), 0);
75 m[idx] = 1;
76 result.add_term(m, Rational(1));
77 }
78 }
79
80 void PolyBuilder::visit(const AddNode& node) {
81 Poly sum(ext_vars.size());
82 for (auto& op : node.operands()) {
85 op->accept(b);
86 if (b.failed) { failed = true; return; }
87
88 Poly b_res = b.get_result();
89 align_variables(sum, b_res);
90 sum = add_poly(sum, b_res);
91 }
92 result = sum;
93 }
94
95 void PolyBuilder::visit(const MultiplyNode& node) {
96 Poly prod(ext_vars.size());
97 prod.add_term(std::vector<int>(ext_vars.size(), 0), Rational(1));
98
99 for (auto& op : node.operands()) {
102 op->accept(b);
103 if (b.failed) { failed = true; return; }
104 Poly b_res = b.get_result();
105
106 align_variables(prod, b_res);
107 prod = mul_poly(prod, b_res);
108 }
109 result = prod;
110 }
111
112void PolyBuilder::visit(const PowerNode& node) {
115 node.base()->accept(builder);
116 if (builder.failed) {
117 failed = true;
118 return;
119 }
120 Poly base = builder.get_result();
121 auto exponent = integer_exponent(node);
122 if (!exponent || *exponent > BigInt(std::numeric_limits<int>::max()) ||
123 *exponent < 0) {
124 if (strict_mode) {
125 failed = true;
126 return;
127 }
129 LMCAS::detail::make_node<PowerNode>(node.base(), node.exponent()));
130 return;
131 }
132 if (*exponent == 0) {
133 result = Poly(ext_vars.size());
134 result.add_term(Monomial(ext_vars.size(), 0), Rational(1));
135 return;
136 }
137 const int count = static_cast<int>(exponent->try_to_int64().value());
138 if (!power_degrees_fit(base, count)) {
139 represent_as_aux_or_fail(node.clone());
140 return;
141 }
142 Poly product(ext_vars.size());
143 product.add_term(Monomial(ext_vars.size(), 0), Rational(1));
144 for (int index = 0; index < count; ++index) {
145 extend_variables(product, base.num_vars);
146 product = mul_poly(product, base);
147 }
148 result = product;
149}
150}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
幂运算节点,表示 base^exponent。
变量节点,表示一个符号变量。
RewriteBudget * rewrite_budget() const noexcept
size_t get_or_create_aux_var(const std::shared_ptr< const SymbolicNode > &node)
PolyBuilder(const std::vector< std::string > &v, PolyContext &ctx, bool strict=false)
std::unordered_map< std::string, size_t > & transcendental_map
std::unordered_map< size_t, std::shared_ptr< const SymbolicNode > > * aux_to_node
void visit(const NumberNode &node) override
void represent_as_aux_or_fail(const std::shared_ptr< const SymbolicNode > &node)
std::shared_ptr< const Node > make_node(Args &&... args)
Poly mul_poly(const Poly &a, const Poly &b)
void extend_variables(Poly &polynomial, size_t count)
void align_variables(Poly &a, Poly &b)
Poly add_poly(const Poly &a, const Poly &b)
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
const MultiPoly & b
const ExprPtr RelationOp op
const ExprPtr & exponent
const std::string const ExprPtr & value
ExprResult rational(const Rational &value)
void add_term(const Monomial &monomial, const Rational &coefficient)