LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
traversal.hpp
浏览该文件的文档.
1/** @file internal/symbolic_ast/traversal.hpp */
2#pragma once
3
5
6#include <optional>
7#include <string_view>
8#include <utility>
9
10namespace LMCAS::detail {
11struct BinderView {
12 std::string_view bound_name;
14 std::vector<SymbolicNodePtr> outside_scope;
15};
16
17inline std::optional<BinderView> binder_view(const SymbolicNode& node) {
18 if (const auto* sum = dynamic_cast<const SummationNode*>(&node)) {
19 return BinderView{sum->index_var(), sum->body(),
20 {sum->lower_bound(), sum->upper_bound()}};
21 }
22 if (const auto* product = dynamic_cast<const ProductNode*>(&node)) {
23 return BinderView{product->index_var(), product->body(),
24 {product->lower_bound(), product->upper_bound()}};
25 }
26 if (const auto* integral = dynamic_cast<const IntegralNode*>(&node)) {
27 std::vector<SymbolicNodePtr> bounds;
28 if (integral->lower()) bounds.push_back(integral->lower());
29 if (integral->upper()) bounds.push_back(integral->upper());
30 return BinderView{integral->variable(), integral->body(), std::move(bounds)};
31 }
32 if (const auto* transform = dynamic_cast<const TransformNode*>(&node)) {
33 return BinderView{transform->source_var(), transform->body(),
34 {transform->target()}};
35 }
36 if (const auto* quantifier = dynamic_cast<const QuantifierNode*>(&node)) {
37 return BinderView{quantifier->bound_var(), quantifier->predicate(),
38 {quantifier->domain()}};
39 }
40 if (const auto* set_builder = dynamic_cast<const SetBuilderNode*>(&node)) {
41 return BinderView{set_builder->element_var(), set_builder->predicate(),
42 {set_builder->domain()}};
43 }
44 if (const auto* limit = dynamic_cast<const LimitNode*>(&node)) {
45 return BinderView{limit->variable(), limit->body(), {limit->point()}};
46 }
47 return std::nullopt;
48}
50protected:
51 virtual void visit_child(const SymbolicNodePtr& child) {
52 if (child) child->accept(*this);
53 }
54
55 template <class Range>
56 void visit_children(const Range& children) {
57 for (const auto& child : children) visit_child(child);
58 }
59
60public:
62 void visit(const NumberNode&) override {}
63 void visit(const VariableNode&) override {}
64 void visit(const AddNode& node) override { visit_children(node.operands()); }
65 void visit(const MultiplyNode& node) override { visit_children(node.operands()); }
66 void visit(const PowerNode& node) override {
67 visit_child(node.base());
68 visit_child(node.exponent());
69 }
70 void visit(const FunctionNode& node) override { visit_children(node.arguments()); }
71 void visit(const UninterpretedFunctionNode& node) override {
72 visit_children(node.arguments());
73 }
74 void visit(const MatrixNode& node) override {
75 if (const auto* dense = std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
76 visit_children(*dense);
77 return;
78 }
79 for (const auto& [index, value] :
80 std::get<MatrixNode::SparseStorage>(node.storage())) {
81 (void)index;
83 }
84 }
85 void visit(const RelationalNode& node) override {
86 visit_child(node.left());
87 visit_child(node.right());
88 }
89 void visit(const LogicalNode& node) override {
90 visit_child(node.left());
91 visit_child(node.right());
92 }
93 void visit(const PiecewiseNode& node) override {
94 for (const auto& branch : node.branches()) {
95 visit_child(branch.expression);
96 visit_child(branch.condition);
97 }
98 visit_child(node.default_expr());
99 }
100 void visit(const SummationNode& node) override {
101 visit_child(node.lower_bound());
102 visit_child(node.upper_bound());
103 visit_child(node.body());
104 }
105 void visit(const ProductNode& node) override {
106 visit_child(node.lower_bound());
107 visit_child(node.upper_bound());
108 visit_child(node.body());
109 }
110 void visit(const TransformNode& node) override {
111 visit_child(node.target());
112 visit_child(node.body());
113 }
114 void visit(const QuantifierNode& node) override {
115 visit_child(node.domain());
116 visit_child(node.predicate());
117 }
118 void visit(const SetBuilderNode& node) override {
119 visit_child(node.domain());
120 visit_child(node.predicate());
121 }
122 void visit(const FiniteSetNode& node) override { visit_children(node.elements()); }
123 void visit(const IntervalNode& node) override {
124 visit_child(node.lower());
125 visit_child(node.upper());
126 }
127 void visit(const MembershipNode& node) override {
128 visit_child(node.element());
129 visit_child(node.set());
130 }
131 void visit(const QuantityNode& node) override { visit_child(node.value()); }
132 void visit(const ComplexNode& node) override {
133 visit_child(node.real());
134 visit_child(node.imag());
135 }
136 void visit(const IntegralNode& node) override {
137 visit_child(node.lower());
138 visit_child(node.upper());
139 visit_child(node.body());
140 }
141 void visit(const LimitNode& node) override {
142 visit_child(node.point());
143 visit_child(node.body());
144 }
145 void visit(const RootOfNode&) override {}
146};
147
148template <class Node>
150public:
151 bool found() const noexcept { return found_; }
152 void visit(const Node&) override { found_ = true; }
153
154private:
155 bool found_ = false;
156};
157
158template <class Node>
160 if (!root) return false;
161 NodeTypeDetector<Node> detector;
162 root->accept(detector);
163 return detector.found();
164}
166public:
169 if (!node) return nullptr;
170 const auto previous_current = current_;
171 const auto previous_result = result_;
172 current_ = node;
173 result_.reset();
174 node->accept(*this);
175 auto rewritten = result_;
176 current_ = previous_current;
177 result_ = previous_result;
178 if (!rewritten) throw std::logic_error("SymbolicRewriter visit did not set a result");
179 return rewritten;
180 }
181
182protected:
183 SymbolicNodePtr current() const noexcept { return current_; }
184 void set_result(SymbolicNodePtr result) { result_ = std::move(result); }
185
186 SymbolicNodePtr rewrite_child(const SymbolicNodePtr& child, bool& changed) {
187 auto rewritten = rewrite(child);
188 changed = changed || rewritten != child;
189 return rewritten;
190 }
191
192 template <class Range>
193 std::vector<SymbolicNodePtr> rewrite_children(const Range& children, bool& changed) {
194 std::vector<SymbolicNodePtr> rewritten;
195 rewritten.reserve(children.size());
196 for (const auto& child : children) {
197 rewritten.push_back(rewrite_child(child, changed));
198 }
199 return rewritten;
200 }
201
202public:
203 void visit(const NumberNode&) override { set_result(current()); }
204 void visit(const VariableNode&) override { set_result(current()); }
205 void visit(const AddNode& node) override {
206 bool changed = false;
207 auto operands = rewrite_children(node.operands(), changed);
208 set_result(changed ? SymbolicFactory::create_add(std::move(operands), rewrite_budget()) : current());
209 }
210 void visit(const MultiplyNode& node) override {
211 bool changed = false;
212 auto operands = rewrite_children(node.operands(), changed);
213 set_result(changed ? SymbolicFactory::create_multiply(std::move(operands), rewrite_budget()) : current());
214 }
215 void visit(const PowerNode& node) override {
216 bool changed = false;
217 auto base = rewrite_child(node.base(), changed);
218 auto exponent = rewrite_child(node.exponent(), changed);
220 }
221 void visit(const FunctionNode& node) override {
222 bool changed = false;
223 auto arguments = rewrite_children(node.arguments(), changed);
224 set_result(changed ? make_node<FunctionNode>(node.type(), std::move(arguments)) : current());
225 }
226 void visit(const UninterpretedFunctionNode& node) override {
227 bool changed = false;
228 auto arguments = rewrite_children(node.arguments(), changed);
229 set_result(changed ? make_node<UninterpretedFunctionNode>(node.name(), std::move(arguments))
230 : current());
231 }
232 void visit(const MatrixNode& node) override {
233 bool changed = false;
234 if (const auto* dense = std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
235 auto entries = rewrite_children(*dense, changed);
236 set_result(changed ? make_node<MatrixNode>(node.rows(), node.cols(), std::move(entries))
237 : current());
238 return;
239 }
240 auto entries = std::get<MatrixNode::SparseStorage>(node.storage());
241 for (auto& [index, value] : entries) {
242 (void)index;
243 value = rewrite_child(value, changed);
244 }
245 set_result(changed ? make_node<MatrixNode>(node.rows(), node.cols(), std::move(entries))
246 : current());
247 }
248 void visit(const RelationalNode& node) override {
249 bool changed = false;
250 auto left = rewrite_child(node.left(), changed);
251 auto right = rewrite_child(node.right(), changed);
252 set_result(changed ? make_node<RelationalNode>(left, right, node.op()) : current());
253 }
254 void visit(const LogicalNode& node) override {
255 bool changed = false;
256 auto left = rewrite_child(node.left(), changed);
257 auto right = node.right() ? rewrite_child(node.right(), changed) : nullptr;
258 set_result(changed ? make_node<LogicalNode>(left, right, node.op()) : current());
259 }
260 void visit(const PiecewiseNode& node) override {
261 bool changed = false;
262 std::vector<PiecewiseNode::Branch> branches;
263 branches.reserve(node.branches().size());
264 for (const auto& branch : node.branches()) {
265 branches.push_back({rewrite_child(branch.expression, changed),
266 rewrite_child(branch.condition, changed)});
267 }
268 auto fallback = node.default_expr()
269 ? rewrite_child(node.default_expr(), changed) : nullptr;
270 set_result(changed ? make_node<PiecewiseNode>(std::move(branches), fallback) : current());
271 }
272 void visit(const SummationNode& node) override {
273 bool changed = false;
274 auto body = rewrite_child(node.body(), changed);
275 auto lower = rewrite_child(node.lower_bound(), changed);
276 auto upper = rewrite_child(node.upper_bound(), changed);
277 set_result(changed ? make_node<SummationNode>(body, node.index_var(), lower, upper)
278 : current());
279 }
280 void visit(const ProductNode& node) override {
281 bool changed = false;
282 auto body = rewrite_child(node.body(), changed);
283 auto lower = rewrite_child(node.lower_bound(), changed);
284 auto upper = rewrite_child(node.upper_bound(), changed);
285 set_result(changed ? make_node<ProductNode>(body, node.index_var(), lower, upper)
286 : current());
287 }
288 void visit(const TransformNode& node) override {
289 bool changed = false;
290 auto body = rewrite_child(node.body(), changed);
291 auto target = rewrite_child(node.target(), changed);
292 set_result(changed ? make_node<TransformNode>(node.transform_type(), body,
293 node.source_var(), target)
294 : current());
295 }
296 void visit(const QuantifierNode& node) override {
297 bool changed = false;
298 auto domain = rewrite_child(node.domain(), changed);
299 auto predicate = rewrite_child(node.predicate(), changed);
300 set_result(changed ? make_node<QuantifierNode>(node.quantifier_type(), node.bound_var(),
301 domain, predicate)
302 : current());
303 }
304 void visit(const SetBuilderNode& node) override {
305 bool changed = false;
306 auto domain = rewrite_child(node.domain(), changed);
307 auto predicate = rewrite_child(node.predicate(), changed);
308 set_result(changed ? make_node<SetBuilderNode>(node.element_var(), domain, predicate)
309 : current());
310 }
311 void visit(const FiniteSetNode& node) override {
312 bool changed = false;
313 auto elements = rewrite_children(node.elements(), changed);
314 set_result(changed ? make_node<FiniteSetNode>(std::move(elements)) : current());
315 }
316 void visit(const IntervalNode& node) override {
317 bool changed = false;
318 auto lower = rewrite_child(node.lower(), changed);
319 auto upper = rewrite_child(node.upper(), changed);
321 node.lower_closed(), node.upper_closed())
322 : current());
323 }
324 void visit(const MembershipNode& node) override {
325 bool changed = false;
326 auto element = rewrite_child(node.element(), changed);
327 auto set = rewrite_child(node.set(), changed);
329 }
330 void visit(const QuantityNode& node) override {
331 bool changed = false;
332 auto value = rewrite_child(node.value(), changed);
333 set_result(changed ? make_node<QuantityNode>(value, node.dimension(),
334 node.scale_to_base(), node.display_unit())
335 : current());
336 }
337 void visit(const ComplexNode& node) override {
338 bool changed = false;
339 auto real = rewrite_child(node.real(), changed);
340 auto imag = rewrite_child(node.imag(), changed);
342 }
343 void visit(const IntegralNode& node) override {
344 bool changed = false;
345 auto body = rewrite_child(node.body(), changed);
346 auto lower = node.lower() ? rewrite_child(node.lower(), changed) : nullptr;
347 auto upper = node.upper() ? rewrite_child(node.upper(), changed) : nullptr;
348 set_result(changed ? make_node<IntegralNode>(body, node.variable(), lower, upper)
349 : current());
350 }
351 void visit(const LimitNode& node) override {
352 bool changed = false;
353 auto body = rewrite_child(node.body(), changed);
354 auto point = rewrite_child(node.point(), changed);
356 body, node.variable(), point, node.direction())
357 : current());
358 }
359 void visit(const RootOfNode&) override { set_result(current()); }
360
361private:
364};
365
366}
加法节点,表示多个操作数的求和。
复数节点,表示 real + imag * i。
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
矩阵节点,支持稠密和稀疏两种存储方式。
乘法节点,表示多个操作数的乘积。
分段函数节点,表示条件分支表达式.
幂运算节点,表示 base^exponent。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
求和节点,表示符号有限/无限求和 sum_{k=a}^{b} f(k).
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_complex(std::shared_ptr< const SymbolicNode > real, std::shared_ptr< const SymbolicNode > imag)
创建复数节点,自动简化(若虚部为 0,则返回实部).
static std::shared_ptr< const SymbolicNode > create_power(std::shared_ptr< const SymbolicNode > base, std::shared_ptr< const SymbolicNode > exponent)
创建幂运算节点,自动处理指数为 0/1 及底数为 0/1 的情况.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
变量节点,表示一个符号变量。
void visit(const Node &) override
void visit(const LogicalNode &node) override
void visit(const MultiplyNode &node) override
void visit(const NumberNode &) override
void visit(const VariableNode &) override
void visit(const RootOfNode &) override
void visit(const LimitNode &node) override
void visit(const PiecewiseNode &node) override
void visit(const ComplexNode &node) override
void visit(const FiniteSetNode &node) override
void visit(const SetBuilderNode &node) override
void visit(const IntegralNode &node) override
void visit(const QuantifierNode &node) override
void visit(const MatrixNode &node) override
void visit(const AddNode &node) override
void visit(const ProductNode &node) override
void visit(const UninterpretedFunctionNode &node) override
void visit(const RelationalNode &node) override
void visit(const IntervalNode &node) override
void visit(const QuantityNode &node) override
void visit(const TransformNode &node) override
void visit(const SummationNode &node) override
void visit(const FunctionNode &node) override
virtual void visit_child(const SymbolicNodePtr &child)
void visit_children(const Range &children)
void visit(const MembershipNode &node) override
void visit(const PowerNode &node) override
void visit(const FunctionNode &node) override
void visit(const AddNode &node) override
void visit(const IntegralNode &node) override
void visit(const MultiplyNode &node) override
void visit(const SetBuilderNode &node) override
void set_result(SymbolicNodePtr result)
void visit(const QuantityNode &node) override
SymbolicNodePtr rewrite(const SymbolicNodePtr &node)
void visit(const FiniteSetNode &node) override
void visit(const IntervalNode &node) override
void visit(const ComplexNode &node) override
void visit(const TransformNode &node) override
void visit(const RootOfNode &) override
void visit(const LimitNode &node) override
void visit(const UninterpretedFunctionNode &node) override
void visit(const NumberNode &) override
void visit(const LogicalNode &node) override
void visit(const MatrixNode &node) override
void visit(const SummationNode &node) override
void visit(const VariableNode &) override
void visit(const QuantifierNode &node) override
void visit(const PowerNode &node) override
SymbolicNodePtr rewrite_child(const SymbolicNodePtr &child, bool &changed)
void visit(const RelationalNode &node) override
void visit(const ProductNode &node) override
void visit(const PiecewiseNode &node) override
std::vector< SymbolicNodePtr > rewrite_children(const Range &children, bool &changed)
void visit(const MembershipNode &node) override
SymbolicNodePtr current() const noexcept
RewriteBudget * rewrite_budget() const noexcept
多元 Hensel 提升(单变量步)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::vector< SymbolicNodePtr > outside_scope
std::optional< BinderView > binder_view(const SymbolicNode &node)
std::shared_ptr< const SymbolicNode > Node
bool contains_node_type(const SymbolicNodePtr &root)
RewriteBudget const FactsQuery Domain domain
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
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
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const ExprPtr & lower
const ExprPtr & set
const ExprPtr & exponent
ExprPtr imag
const ExprPtr & target
const ExprPtr & right
const std::string const ExprPtr & value