LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
expand_visitor.hpp
浏览该文件的文档.
1/**
2 * @file expand_visitor.hpp
3 * @brief 展开访问器,将乘积和幂展开为多项式形式。
4 */
5#pragma once
6
10
11namespace LMCAS {
13public:
14 std::shared_ptr<const SymbolicNode> result; /**< 展开结果节点。 */
15
17 : SymbolicVisitor(&budget), result(nullptr) {}
18 std::shared_ptr<const SymbolicNode> get_result() const { return result; }
19
20 void visit(const NumberNode& node) override {
22 set_result(node.clone(), 1);
23 }
24 void visit(const VariableNode& node) override {
26 set_result(node.clone(), 1);
27 }
28
29 void visit(const AddNode& node) override {
30 std::size_t size = 0;
31 auto new_ops = expand_children(node.operands(), size);
34 }
35
36 void visit(const MultiplyNode& node) override {
37 std::size_t size = 0;
38 auto expanded_ops = expand_children(node.operands(), size);
39 if (expanded_ops.empty()) {
41 return;
42 }
43
45 set_result(expanded_ops[0]);
46 for (size_t i = 1; i < expanded_ops.size(); ++i) {
47 set_result(norm.expand_product(result, expanded_ops[i]));
48 }
49 }
50
51 LMCAS_API void visit(const PowerNode& node) override;
52
53 void visit(const FunctionNode& node) override {
54 std::size_t size = 1;
55 auto new_args = expand_children(node.arguments(), size);
56 set_result(LMCAS::detail::make_node<FunctionNode>(node.type(), new_args), size);
57 }
58 void visit(const UninterpretedFunctionNode& node) override {
59 std::size_t size = 1;
60 auto arguments = expand_children(node.arguments(), size);
62 node.name(), std::move(arguments)), size);
63 }
64
65 void visit(const MatrixNode& node) override {
66 std::size_t size = 1;
67 if (rewrite_budget()) {
68 if (const auto* dense = std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
69 check_child_count(dense->size());
70 for (const auto& element : *dense) {
71 append_child(size, element);
72 }
73 } else {
74 const auto& sparse = std::get<MatrixNode::SparseStorage>(node.storage());
75 check_child_count(sparse.size());
76 for (const auto& entry : sparse) {
77 append_child(size, entry.second);
78 }
79 }
80 }
81 if (const auto* dense = std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
82 set_result(detail::make_node<MatrixNode>(node.rows(), node.cols(), *dense), size);
83 } else {
84 set_result(detail::make_node<MatrixNode>(node.rows(), node.cols(),
85 std::get<MatrixNode::SparseStorage>(node.storage())), size);
86 }
87 }
88 void visit(const IntegralNode& node) override {
89 std::size_t size = 1;
90 auto body = expand_child(node.body(), size);
91 std::shared_ptr<const SymbolicNode> lower;
92 std::shared_ptr<const SymbolicNode> upper;
93 if (node.lower()) {
94 lower = expand_child(node.lower(), size);
95 upper = expand_child(node.upper(), size);
96 }
98 body, node.variable(), lower, upper), size);
99 }
100
101 void visit(const RelationalNode& node) override {
102 std::size_t size = 1;
103 auto head = expand_child(node.left(), size);
104 auto tail = expand_child(node.right(), size);
105 set_result(LMCAS::detail::make_node<RelationalNode>(head, tail, node.op()), size);
106 }
107
108 void visit(const LogicalNode& node) override {
109 std::size_t size = 1;
110 auto head = expand_child(node.left(), size);
111 std::shared_ptr<const SymbolicNode> tail = nullptr;
112 if (node.right()) {
113 tail = expand_child(node.right(), size);
114 }
115 set_result(LMCAS::detail::make_node<LogicalNode>(head, tail, node.op()), size);
116 }
117
118 void visit(const PiecewiseNode& node) override {
119 std::vector<PiecewiseNode::Branch> branches;
120 if (rewrite_budget()) {
121 auto minimum = rewrite_budget()->append_size(1, node.branches().size());
122 rewrite_budget()->append_size(minimum, node.branches().size());
123 }
124 branches.reserve(node.branches().size());
125 std::size_t size = 1;
126 for (const auto& branch : node.branches()) {
127 auto expression = expand_child(branch.expression, size);
128 auto condition = expand_child(branch.condition, size);
129 branches.push_back({expression, condition});
130 }
131 std::shared_ptr<const SymbolicNode> default_expr = nullptr;
132 if (node.default_expr()) {
133 default_expr = expand_child(node.default_expr(), size);
134 }
136 std::move(branches), default_expr), size);
137 }
138
139 void visit(const SummationNode& node) override {
140 std::size_t size = 1;
141 auto body = expand_child(node.body(), size);
142 auto lower = expand_child(node.lower_bound(), size);
143 auto upper = expand_child(node.upper_bound(), size);
145 body, node.index_var(), lower, upper), size);
146 }
147
148 void visit(const ProductNode& node) override {
149 std::size_t size = 1;
150 auto body = expand_child(node.body(), size);
151 auto lower = expand_child(node.lower_bound(), size);
152 auto upper = expand_child(node.upper_bound(), size);
154 body, node.index_var(), lower, upper), size);
155 }
156
157 void visit(const TransformNode& node) override {
158 std::size_t size = 1;
159 auto body = expand_child(node.body(), size);
160 auto target = expand_child(node.target(), size);
162 node.transform_type(), body, node.source_var(), target), size);
163 }
164
165 void visit(const QuantifierNode& node) override {
166 std::size_t size = 1;
167 auto domain = expand_child(node.domain(), size);
168 auto predicate = expand_child(node.predicate(), size);
170 node.quantifier_type(), node.bound_var(), domain, predicate), size);
171 }
172
173 void visit(const SetBuilderNode& node) override {
174 std::size_t size = 1;
175 auto domain = expand_child(node.domain(), size);
176 auto predicate = expand_child(node.predicate(), size);
178 node.element_var(), domain, predicate), size);
179 }
180
181 void visit(const FiniteSetNode& node) override {
182 std::size_t size = 1;
183 auto elements = expand_children(node.elements(), size);
184 set_result(LMCAS::detail::make_node<FiniteSetNode>(std::move(elements)), size);
185 }
186
187 void visit(const IntervalNode& node) override {
188 std::size_t size = 1;
189 auto lower = expand_child(node.lower(), size);
190 auto upper = expand_child(node.upper(), size);
192 lower, upper, node.lower_closed(), node.upper_closed()), size);
193 }
194
195 void visit(const MembershipNode& node) override {
196 std::size_t size = 1;
197 auto element = expand_child(node.element(), size);
198 auto set = expand_child(node.set(), size);
200 }
201
202 void visit(const QuantityNode& node) override {
203 std::size_t size = 1;
204 auto value = expand_child(node.value(), size);
206 value, node.dimension(), node.scale_to_base(), node.display_unit()), size);
207 }
208
209 void visit(const ComplexNode& node) override {
210 std::size_t size = 1;
211 auto expanded_r = expand_child(node.real(), size);
212 auto expanded_i = expand_child(node.imag(), size);
213 set_result(SymbolicFactory::create_complex(expanded_r, expanded_i), size);
214 }
215 void visit(const LimitNode& node) override {
216 std::size_t size = 1;
217 auto body = expand_child(node.body(), size);
218 auto point = expand_child(node.point(), size);
220 body, node.variable(), point, node.direction()), size);
221 }
222
223 void visit(const RootOfNode& node) override {
225 set_result(node.clone(), 1);
226 }
227
228private:
229
230 void check_child_count(std::size_t count, std::size_t roots = 1) const {
231 if (auto* budget = rewrite_budget()) {
232 budget->append_size(roots, count);
233 }
234 }
235
236 void append_child(std::size_t& size,
237 const std::shared_ptr<const SymbolicNode>& child) const {
238 if (auto* budget = rewrite_budget()) {
239 size = budget->append_size(size, budget->measure(child));
240 }
241 }
242
243 std::shared_ptr<const SymbolicNode> expand_child(
244 const std::shared_ptr<const SymbolicNode>& child, std::size_t& size) {
245 child->accept(*this);
246 append_child(size, result);
247 return result;
248 }
249
250 std::vector<std::shared_ptr<const SymbolicNode>> expand_children(
251 const std::vector<std::shared_ptr<const SymbolicNode>>& children, std::size_t& size) {
252 check_child_count(children.size(), size);
253 std::vector<std::shared_ptr<const SymbolicNode>> expanded;
254 expanded.reserve(children.size());
255 for (const auto& child : children) {
256 auto expanded_child = expand_child(child, size);
257 expanded.push_back(std::move(expanded_child));
258 }
259 return expanded;
260 }
261
262 void set_result(std::shared_ptr<const SymbolicNode> candidate, std::size_t size) {
263 if (auto* budget = rewrite_budget()) {
264 budget->require_nodes(size);
265 }
266 result = std::move(candidate);
267 }
268
269 void set_result(std::shared_ptr<const SymbolicNode> candidate) {
270 const auto size = rewrite_budget()->measure_result(candidate);
271 set_result(std::move(candidate), size);
272 }
273};
274
275}
加法节点,表示多个操作数的求和。
复数节点,表示 real + imag * i。
void visit(const IntegralNode &node) override
std::vector< std::shared_ptr< const SymbolicNode > > expand_children(const std::vector< std::shared_ptr< const SymbolicNode > > &children, std::size_t &size)
void visit(const IntervalNode &node) override
void visit(const QuantityNode &node) override
void visit(const ProductNode &node) override
void visit(const TransformNode &node) override
void visit(const VariableNode &node) override
void visit(const LogicalNode &node) override
void append_child(std::size_t &size, const std::shared_ptr< const SymbolicNode > &child) const
void visit(const NumberNode &node) override
void check_child_count(std::size_t count, std::size_t roots=1) const
void visit(const LimitNode &node) override
std::shared_ptr< const SymbolicNode > get_result() const
std::shared_ptr< const SymbolicNode > expand_child(const std::shared_ptr< const SymbolicNode > &child, std::size_t &size)
void visit(const RelationalNode &node) override
void visit(const PiecewiseNode &node) override
void set_result(std::shared_ptr< const SymbolicNode > candidate)
void visit(const MembershipNode &node) override
void visit(const MultiplyNode &node) override
void visit(const MatrixNode &node) override
void visit(const FunctionNode &node) override
ExpandVisitor(detail::RewriteBudget &budget)
void visit(const AddNode &node) override
void visit(const FiniteSetNode &node) override
void visit(const RootOfNode &node) override
void visit(const SummationNode &node) override
void visit(const SetBuilderNode &node) override
std::shared_ptr< const SymbolicNode > result
展开结果节点。
void visit(const QuantifierNode &node) override
void visit(const UninterpretedFunctionNode &node) override
void set_result(std::shared_ptr< const SymbolicNode > candidate, std::size_t size)
void visit(const ComplexNode &node) override
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
矩阵节点,支持稠密和稀疏两种存储方式。
乘法节点,表示多个操作数的乘积。
统一规范化数值幂。 精确操作数保留整数和有理数运算;近似求根要求指数精确等于 1/2。 有限浮点幂直接折叠,省去倒数中间值;非有限结果保留幂表达式。
std::shared_ptr< const SymbolicNode > expand_product(const std::shared_ptr< const SymbolicNode > &lhs, const std::shared_ptr< const SymbolicNode > &rhs)
分段函数节点,表示条件分支表达式.
幂运算节点,表示 base^exponent。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
static std::shared_ptr< const SymbolicNode > create_complex(std::shared_ptr< const SymbolicNode > real, std::shared_ptr< const SymbolicNode > imag)
创建复数节点,自动简化(若虚部为 0,则返回实部).
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
变量节点,表示一个符号变量。
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
void require_nodes(std::size_t nodes) const
std::size_t append_size(std::size_t current, std::size_t child)
std::size_t measure_result(const std::shared_ptr< const SymbolicNode > &node)
RewriteBudget * rewrite_budget() const noexcept
#define LMCAS_API
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
const std::string const LimitExprPtr & point
const ExprPtr & element
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const ExprPtr & lower
@ Real
Real numbers
const ExprPtr & set
std::size_t normalization_check_arithmetic(detail::RewriteBudget *budget, std::size_t extra_nodes, const std::shared_ptr< const Nodes > &... children)
const NumberDomainSet & domain
const ExprPtr & target
ExprSetResult roots(const ExprPtr &expression, const std::string &variable, ComputationContext &context, const SolveOptions &options)
const std::string const ExprPtr & value
符号规范化访问器接口。
内部 AST 定义。