LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
rational_polynomial_recognition.cpp
浏览该文件的文档.
1
#include "
polynomial_conversion.hpp
"
2
#include "
internal/symbolic_ast.hpp
"
3
#include <cstdint>
4
#include <utility>
5
6
namespace
LMCAS
{
7
namespace
{
8
9
constexpr
const
char
*
kOperation
=
"recognize_rational_polynomial"
;
10
11
class
RecursionScope
{
12
public
:
13
explicit
RecursionScope
(
ComputationContext
&
context
) :
context_
(
context
) {}
14
~RecursionScope
() {
context_
.leave_recursion(); }
15
16
private
:
17
ComputationContext
&
context_
;
18
};
19
20
Result<OptionalRationalPolynomial>
recognize_node
(
21
const
std::shared_ptr<const SymbolicNode>& node,
22
const
std::string&
variable
,
ComputationContext
&
context
);
23
24
Result<OptionalRationalPolynomial>
recognize_number
(
25
const
NumberNode
& number,
const
std::string&
variable
) {
26
if
(std::holds_alternative<BigInt>(number.
value
())) {
27
return
Result<OptionalRationalPolynomial>::success
(
Polynomial<Rational>
(
28
Rational(std::get<BigInt>(number.
value
())),
variable
));
29
}
30
if
(std::holds_alternative<Rational>(number.
value
())) {
31
return
Result<OptionalRationalPolynomial>::success
(
Polynomial<Rational>
(
32
std::get<Rational>(number.
value
()),
variable
));
33
}
34
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
35
}
36
37
Result<OptionalRationalPolynomial>
recognize_sum
(
38
const
AddNode
&
add
,
const
std::string&
variable
,
ComputationContext
&
context
) {
39
Polynomial<Rational>
result(
variable
);
40
for
(
const
auto
& operand :
add
.operands()) {
41
auto
child =
recognize_node
(operand,
variable
,
context
);
42
if
(!child)
return
child;
43
if
(!child.value()) {
44
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
45
}
46
result = result + *child.value();
47
if
(result.
coeffs
.size() >
context
.limits().max_expansion_terms) {
48
return
Result<OptionalRationalPolynomial>::failure
(
49
CasErrc::ResourceLimit
,
"polynomial term budget exhausted"
,
kOperation
);
50
}
51
}
52
return
Result<OptionalRationalPolynomial>::success
(std::move(result));
53
}
54
55
Result<OptionalRationalPolynomial>
recognize_product
(
56
const
MultiplyNode
& multiply,
const
std::string&
variable
,
ComputationContext
&
context
) {
57
Polynomial<Rational>
result({Rational(1)},
variable
);
58
for
(
const
auto
& operand : multiply.operands()) {
59
auto
child =
recognize_node
(operand,
variable
,
context
);
60
if
(!child)
return
child;
61
if
(!child.value()) {
62
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
63
}
64
const
std::size_t projected_terms = result.is_zero() || child.value()->is_zero()
65
? 0
66
: result.coeffs.size() + child.value()->coeffs.size() - 1;
67
if
(projected_terms >
context
.limits().max_expansion_terms) {
68
return
Result<OptionalRationalPolynomial>::failure
(
69
CasErrc::ResourceLimit
,
70
"polynomial expansion term budget exhausted"
,
71
kOperation
);
72
}
73
result = result * *child.value();
74
}
75
return
Result<OptionalRationalPolynomial>::success
(std::move(result));
76
}
77
78
Result<OptionalRationalPolynomial>
recognize_power
(
79
const
PowerNode
& power,
const
std::string&
variable
,
ComputationContext
&
context
) {
80
auto
exponent_node = std::dynamic_pointer_cast<const NumberNode>(power.
exponent
());
81
if
(!exponent_node) {
82
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
83
}
84
85
BigInt
exponent
;
86
if
(std::holds_alternative<BigInt>(exponent_node->value())) {
87
exponent
= std::get<BigInt>(exponent_node->value());
88
}
else
{
89
const
Rational&
rational
= std::get<Rational>(exponent_node->value());
90
if
(!
rational
.is_integer()) {
91
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
92
}
93
exponent
=
rational
.to_bigint();
94
}
95
96
auto
exponent_value =
exponent
.try_to_int64();
97
if
(!exponent_value || *exponent_value <= 0) {
98
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
99
}
100
if
(
static_cast<
std::uint64_t
>
(*exponent_value) >=
101
context
.limits().max_expansion_terms) {
102
return
Result<OptionalRationalPolynomial>::failure
(
103
CasErrc::ResourceLimit
,
104
"polynomial exponent exceeds the expansion term budget"
,
105
kOperation
);
106
}
107
108
auto
base =
recognize_node
(power.
base
(),
variable
,
context
);
109
if
(!base)
return
base;
110
if
(!base.value()) {
111
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
112
}
113
114
Polynomial<Rational>
result({Rational(1)},
variable
);
115
for
(std::int64_t i = 0; i < *exponent_value; ++i) {
116
auto
step =
context
.consume_steps(1,
kOperation
);
117
if
(!step)
return
Result<OptionalRationalPolynomial>::failure
(step.error());
118
const
std::size_t projected_terms = result.is_zero() || base.value()->is_zero()
119
? 0
120
: result.coeffs.size() + base.value()->coeffs.size() - 1;
121
if
(projected_terms >
context
.limits().max_expansion_terms) {
122
return
Result<OptionalRationalPolynomial>::failure
(
123
CasErrc::ResourceLimit
,
124
"polynomial expansion term budget exhausted"
,
125
kOperation
);
126
}
127
result = result * *base.value();
128
}
129
return
Result<OptionalRationalPolynomial>::success
(std::move(result));
130
}
131
132
Result<OptionalRationalPolynomial>
recognize_node
(
133
const
std::shared_ptr<const SymbolicNode>& node,
134
const
std::string&
variable
,
135
ComputationContext
&
context
) {
136
auto
entered =
context
.enter_recursion(
kOperation
);
137
if
(!entered)
return
Result<OptionalRationalPolynomial>::failure
(entered.error());
138
RecursionScope
scope(
context
);
139
140
if
(!node) {
141
return
Result<OptionalRationalPolynomial>::failure
(
142
CasErrc::InternalInvariant
,
143
"polynomial recognition encountered a null AST node"
,
144
kOperation
);
145
}
146
147
if
(
auto
number = std::dynamic_pointer_cast<const NumberNode>(node)) {
148
return
recognize_number
(*number,
variable
);
149
}
150
if
(
auto
symbol = std::dynamic_pointer_cast<const VariableNode>(node)) {
151
if
(symbol->is_constant() || symbol->name() !=
variable
) {
152
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
153
}
154
return
Result<OptionalRationalPolynomial>::success
(
155
Polynomial<Rational>
({Rational(0), Rational(1)},
variable
));
156
}
157
if
(
auto
add
= std::dynamic_pointer_cast<const AddNode>(node)) {
158
return
recognize_sum
(*
add
,
variable
,
context
);
159
}
160
if
(
auto
multiply = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
161
return
recognize_product
(*multiply,
variable
,
context
);
162
}
163
if
(
auto
power = std::dynamic_pointer_cast<const PowerNode>(node)) {
164
return
recognize_power
(*power,
variable
,
context
);
165
}
166
return
Result<OptionalRationalPolynomial>::success
(std::nullopt);
167
}
168
169
}
170
171
Result<OptionalRationalPolynomial>
recognize_rational_polynomial
(
172
const
SymbolicExpr& expression,
173
const
std::string&
variable
,
174
ComputationContext
&
context
) {
175
if
(!
LMCAS::detail::node
(expression)) {
176
return
Result<OptionalRationalPolynomial>::failure
(
177
CasErrc::InvalidArgument
,
"expression cannot be null"
, kOperation);
178
}
179
if
(
variable
.empty()) {
180
return
Result<OptionalRationalPolynomial>::failure
(
181
CasErrc::InvalidArgument
,
"polynomial variable cannot be empty"
, kOperation);
182
}
183
return
recognize_node(
LMCAS::detail::node
(expression),
variable
,
context
);
184
}
185
186
}
LMCAS::AddNode
加法节点,表示多个操作数的求和。
定义
arithmetic.hpp:55
LMCAS::ComputationContext
定义
computation_context.hpp:99
LMCAS::MultiplyNode
乘法节点,表示多个操作数的乘积。
定义
arithmetic.hpp:134
LMCAS::NumberNode
定义
numbers.hpp:8
LMCAS::NumberNode::value
const std::variant< BigInt, Rational > & value() const noexcept
定义
numbers.hpp:21
LMCAS::Polynomial
一元多项式模板类
定义
polynomial.hpp:52
LMCAS::Polynomial::coeffs
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
定义
polynomial.hpp:55
LMCAS::PowerNode
幂运算节点,表示 base^exponent。
定义
arithmetic.hpp:218
LMCAS::PowerNode::exponent
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
定义
arithmetic.hpp:234
LMCAS::PowerNode::base
const std::shared_ptr< const SymbolicNode > & base() const noexcept
定义
arithmetic.hpp:233
LMCAS::Result
定义
result.hpp:39
LMCAS::Result::failure
static Result failure(CasErrc code, std::string message, std::string operation={})
定义
result.hpp:52
LMCAS::Result::success
static Result success(T value)
定义
result.hpp:48
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::RecursionScope
定义
rational_polynomial_recognition.cpp:11
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::RecursionScope::~RecursionScope
~RecursionScope()
定义
rational_polynomial_recognition.cpp:14
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::RecursionScope::RecursionScope
RecursionScope(ComputationContext &context)
定义
rational_polynomial_recognition.cpp:13
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::RecursionScope::context_
ComputationContext & context_
定义
rational_polynomial_recognition.cpp:17
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::recognize_product
Result< OptionalRationalPolynomial > recognize_product(const MultiplyNode &multiply, const std::string &variable, ComputationContext &context)
定义
rational_polynomial_recognition.cpp:55
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::recognize_node
Result< OptionalRationalPolynomial > recognize_node(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable, ComputationContext &context)
定义
rational_polynomial_recognition.cpp:132
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::recognize_number
Result< OptionalRationalPolynomial > recognize_number(const NumberNode &number, const std::string &variable)
定义
rational_polynomial_recognition.cpp:24
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::recognize_sum
Result< OptionalRationalPolynomial > recognize_sum(const AddNode &add, const std::string &variable, ComputationContext &context)
定义
rational_polynomial_recognition.cpp:37
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::kOperation
constexpr const char * kOperation
定义
rational_polynomial_recognition.cpp:9
LMCAS::anonymous_namespace{rational_polynomial_recognition.cpp}::recognize_power
Result< OptionalRationalPolynomial > recognize_power(const PowerNode &power, const std::string &variable, ComputationContext &context)
定义
rational_polynomial_recognition.cpp:78
LMCAS::detail::node
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
定义
base.hpp:91
LMCAS
定义
assumption.hpp:11
LMCAS::variable
const std::string & variable
定义
expr.hpp:286
LMCAS::context
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
定义
exact_factorization.hpp:65
LMCAS::CasErrc::InvalidArgument
@ InvalidArgument
定义
result.hpp:13
LMCAS::CasErrc::InternalInvariant
@ InternalInvariant
定义
result.hpp:28
LMCAS::CasErrc::ResourceLimit
@ ResourceLimit
定义
result.hpp:25
LMCAS::add
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
定义
expr_arithmetic.cpp:18
LMCAS::exponent
const ExprPtr & exponent
定义
expr.hpp:215
LMCAS::recognize_rational_polynomial
Result< OptionalRationalPolynomial > recognize_rational_polynomial(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
定义
rational_polynomial_recognition.cpp:171
LMCAS::rational
ExprResult rational(const Rational &value)
定义
expr_values.cpp:82
polynomial_conversion.hpp
符号表达式与一元多项式的转换。
symbolic_ast.hpp
内部 AST 定义。
src
rational_polynomial_recognition.cpp
生成于
, 为 LMCAS使用
1.18.0