LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
rewrite_engine.cpp
浏览该文件的文档.
1#include "matcher.hpp"
3
4namespace LMCAS {
5
6void RewriteEngine::add_rule(const Rule& rule) {
7 rules.push_back(rule);
8}
9
11public:
12 const RewriteEngine& engine;
14 std::shared_ptr<const SymbolicNode> result;
15 bool changed = false;
16
17 RewriteVisitor(const RewriteEngine& e, ComputationContext& ctx)
18 : engine(e), context(ctx) {}
19
20 std::shared_ptr<const SymbolicNode> get_result() const { return result; }
21
22 std::shared_ptr<const SymbolicNode> try_match(std::shared_ptr<const SymbolicNode> node) {
23 auto current_expr = LMCAS::detail::expression_from_node(node);
24 const auto& rules = engine.get_rules();
25 const AssumptionContext* ctx = context.assumptions().get();
26 for (const auto& rule : rules) {
28
29 if (Matcher::match(rule.pattern, current_expr, rule.wildcards, bindings)) {
30
31 if (rule.condition && !rule.condition(bindings)) {
32 continue;
33 }
34 if (rule.assumption_condition &&
35 (!ctx || !rule.assumption_condition(bindings, ctx))) {
36 continue;
37 }
38
39 SymbolicExpr new_expr = Matcher::replace(rule.replacement, bindings, true);
40
41 changed = true;
42 return LMCAS::detail::node(new_expr);
43 }
44 }
45 return node;
46 }
47
48 std::shared_ptr<const SymbolicNode> visit_child(const std::shared_ptr<const SymbolicNode>& child,
49 bool& child_changed) {
50 bool saved_changed = changed;
51 changed = false;
52 child->accept(*this);
53 auto rewritten = result;
54 if (changed || !rewritten->equals(*child)) {
55 child_changed = true;
56 }
57 changed = saved_changed;
58 return rewritten;
59 }
60
61 void finish_rewrite(std::shared_ptr<const SymbolicNode> node, bool child_changed,
62 bool original_changed) {
63 changed = child_changed;
64 auto matched = try_match(node);
65 if (matched != node && !matched->equals(*node)) changed = true;
66 result = matched;
67
68 if (changed) original_changed = true;
69 changed = original_changed;
70 }
71
72 void visit(const NumberNode& node) override {
73
74 result = try_match(node.clone());
75 }
76
77 void visit(const VariableNode& node) override {
78 result = try_match(node.clone());
79 }
80
81 void visit(const AddNode& node) override {
82
83 std::vector<std::shared_ptr<const SymbolicNode>> new_ops;
84 bool child_changed = false;
85
86 bool original_changed = changed;
87 changed = false;
88
89 for (auto& op : node.operands()) {
90 bool current_changed = changed;
91 changed = false;
92 op->accept(*this);
93 new_ops.push_back(result);
94 if (changed) child_changed = true;
95 else changed = current_changed;
96 }
97
98 std::shared_ptr<const SymbolicNode> node_to_match;
99 if (child_changed) {
100 node_to_match = SymbolicFactory::create_add(new_ops);
101 } else {
102 node_to_match = LMCAS::detail::make_node<AddNode>(node.operands());
103 }
104
105 changed = child_changed;
106 auto matched = try_match(node_to_match);
107 if (matched != node_to_match && !matched->equals(*node_to_match)) changed = true;
108 result = matched;
109
110 if (changed) original_changed = true;
111 changed = original_changed;
112 }
113
114 void visit(const MultiplyNode& node) override {
115 std::vector<std::shared_ptr<const SymbolicNode>> new_ops;
116 bool child_changed = false;
117 bool original_changed = changed;
118 changed = false;
119
120 for (auto& op : node.operands()) {
121 bool current_changed = changed;
122 changed = false;
123 op->accept(*this);
124 new_ops.push_back(result);
125 if (changed) child_changed = true;
126 else changed = current_changed;
127 }
128
129 std::shared_ptr<const SymbolicNode> node_to_match;
130 if (child_changed) {
131 node_to_match = SymbolicFactory::create_multiply(new_ops);
132 } else {
133 node_to_match = LMCAS::detail::make_node<MultiplyNode>(node.operands());
134 }
135
136 changed = child_changed;
137 auto matched = try_match(node_to_match);
138 if (matched != node_to_match && !matched->equals(*node_to_match)) changed = true;
139 result = matched;
140
141 if (changed) original_changed = true;
142 changed = original_changed;
143 }
144
145 void visit(const PowerNode& node) override {
146 bool original_changed = changed;
147 changed = false;
148
149 node.base()->accept(*this);
150 auto new_base = result;
151 bool base_changed = changed;
152
153 changed = false;
154 node.exponent()->accept(*this);
155 auto new_exp = result;
156 bool exp_changed = changed;
157
158 bool child_changed = base_changed || exp_changed;
159 auto node_to_match = LMCAS::detail::make_node<PowerNode>(new_base, new_exp);
160
161 changed = child_changed;
162 auto matched = try_match(node_to_match);
163 if (matched != node_to_match && !matched->equals(*node_to_match)) changed = true;
164 result = matched;
165
166 if (changed) original_changed = true;
167 changed = original_changed;
168 }
169
170 void visit(const FunctionNode& node) override {
171 bool original_changed = changed;
172 changed = false;
173 bool child_changed = false;
174
175 std::vector<std::shared_ptr<const SymbolicNode>> new_args;
176 for (auto& arg : node.arguments()) {
177 bool current_changed = changed;
178 changed = false;
179 arg->accept(*this);
180 new_args.push_back(result);
181 if (changed) child_changed = true;
182 else changed = current_changed;
183 }
184
185 auto node_to_match = LMCAS::detail::make_node<FunctionNode>(node.type(), new_args);
186
187 changed = child_changed;
188 auto matched = try_match(node_to_match);
189 if (matched != node_to_match && !matched->equals(*node_to_match)) changed = true;
190 result = matched;
191
192 if (changed) original_changed = true;
193 changed = original_changed;
194 }
195
196 void visit(const MatrixNode& node) override {
197 bool original_changed = changed;
198 bool child_changed = false;
199 if (const auto* dense =
200 std::get_if<MatrixNode::DenseStorage>(&node.storage())) {
202 entries.reserve(dense->size());
203 for (const auto& entry : *dense) {
204 entries.push_back(visit_child(entry, child_changed));
205 }
207 node.rows(), node.cols(), std::move(entries)),
208 child_changed, original_changed);
209 return;
210 }
212 for (const auto& [index, entry] :
213 std::get<MatrixNode::SparseStorage>(node.storage())) {
214 entries.emplace(index, visit_child(entry, child_changed));
215 }
217 node.rows(), node.cols(), std::move(entries)),
218 child_changed, original_changed);
219 }
220
221 void visit(const RelationalNode& node) override {
222 bool original_changed = changed;
223 bool child_changed = false;
224 auto left = visit_child(node.left(), child_changed);
225 auto right = visit_child(node.right(), child_changed);
227 child_changed, original_changed);
228 }
229
230 void visit(const LogicalNode& node) override {
231 bool original_changed = changed;
232 bool child_changed = false;
233 auto left = visit_child(node.left(), child_changed);
234 std::shared_ptr<const SymbolicNode> right = nullptr;
235 if (node.right()) right = visit_child(node.right(), child_changed);
237 child_changed, original_changed);
238 }
239
240 void visit(const PiecewiseNode& node) override {
241 bool original_changed = changed;
242 bool child_changed = false;
243 std::vector<PiecewiseNode::Branch> branches;
244 branches.reserve(node.branches().size());
245 for (const auto& branch : node.branches()) {
246 auto expression = visit_child(branch.expression, child_changed);
247 auto condition = visit_child(branch.condition, child_changed);
248 branches.push_back({expression, condition});
249 }
250 std::shared_ptr<const SymbolicNode> default_expr = nullptr;
251 if (node.default_expr()) default_expr = visit_child(node.default_expr(), child_changed);
252 finish_rewrite(LMCAS::detail::make_node<PiecewiseNode>(std::move(branches), default_expr),
253 child_changed, original_changed);
254 }
255
256 void visit(const SummationNode& node) override {
257 bool original_changed = changed;
258 bool child_changed = false;
259 auto body = visit_child(node.body(), child_changed);
260 auto lower = visit_child(node.lower_bound(), child_changed);
261 auto upper = visit_child(node.upper_bound(), child_changed);
263 child_changed, original_changed);
264 }
265
266 void visit(const ProductNode& node) override {
267 bool original_changed = changed;
268 bool child_changed = false;
269 auto body = visit_child(node.body(), child_changed);
270 auto lower = visit_child(node.lower_bound(), child_changed);
271 auto upper = visit_child(node.upper_bound(), child_changed);
273 child_changed, original_changed);
274 }
275
276 void visit(const TransformNode& node) override {
277 bool original_changed = changed;
278 bool child_changed = false;
279 auto body = visit_child(node.body(), child_changed);
280 auto target = visit_child(node.target(), child_changed);
282 node.transform_type(), body, node.source_var(), target),
283 child_changed, original_changed);
284 }
285
286 void visit(const QuantifierNode& node) override {
287 bool original_changed = changed;
288 bool child_changed = false;
289 auto domain = visit_child(node.domain(), child_changed);
290 auto predicate = visit_child(node.predicate(), child_changed);
292 node.quantifier_type(), node.bound_var(), domain, predicate),
293 child_changed, original_changed);
294 }
295
296 void visit(const SetBuilderNode& node) override {
297 bool original_changed = changed;
298 bool child_changed = false;
299 auto domain = visit_child(node.domain(), child_changed);
300 auto predicate = visit_child(node.predicate(), child_changed);
302 node.element_var(), domain, predicate),
303 child_changed, original_changed);
304 }
305
306 void visit(const ComplexNode& node) override {
307 bool original_changed = changed;
308 bool child_changed = false;
309 auto real = visit_child(node.real(), child_changed);
310 auto imag = visit_child(node.imag(), child_changed);
312 child_changed, original_changed);
313 }
314 void visit(const FiniteSetNode& node) override {
315 bool original_changed = changed;
316 bool child_changed = false;
317 std::vector<std::shared_ptr<const SymbolicNode>> elements;
318 for (const auto& element : node.elements()) {
319 elements.push_back(visit_child(element, child_changed));
320 }
322 child_changed, original_changed);
323 }
324 void visit(const IntervalNode& node) override {
325 bool original_changed = changed;
326 bool child_changed = false;
327 auto lower = visit_child(node.lower(), child_changed);
328 auto upper = visit_child(node.upper(), child_changed);
330 lower, upper, node.lower_closed(), node.upper_closed()),
331 child_changed, original_changed);
332 }
333 void visit(const MembershipNode& node) override {
334 bool original_changed = changed;
335 bool child_changed = false;
336 auto element = visit_child(node.element(), child_changed);
337 auto set = visit_child(node.set(), child_changed);
339 child_changed, original_changed);
340 }
341 void visit(const UninterpretedFunctionNode& node) override {
342 bool original_changed = changed;
343 bool child_changed = false;
344 std::vector<std::shared_ptr<const SymbolicNode>> arguments;
345 arguments.reserve(node.arguments().size());
346 for (const auto& argument : node.arguments()) {
347 arguments.push_back(visit_child(argument, child_changed));
348 }
350 node.name(), std::move(arguments)),
351 child_changed, original_changed);
352 }
353 void visit(const QuantityNode& node) override {
354 bool original_changed = changed;
355 bool child_changed = false;
356 auto value = visit_child(node.value(), child_changed);
358 value, node.dimension(), node.scale_to_base(), node.display_unit()),
359 child_changed, original_changed);
360 }
361 void visit(const IntegralNode& node) override {
362 bool original_changed = changed;
363 bool child_changed = false;
364 auto body = visit_child(node.body(), child_changed);
365 auto lower = node.lower()
366 ? visit_child(node.lower(), child_changed) : nullptr;
367 auto upper = node.upper()
368 ? visit_child(node.upper(), child_changed) : nullptr;
370 body, node.variable(), lower, upper),
371 child_changed, original_changed);
372 }
373 void visit(const LimitNode& node) override {
374 bool original_changed = changed;
375 bool child_changed = false;
376 auto body = visit_child(node.body(), child_changed);
377 auto point = visit_child(node.point(), child_changed);
379 body, node.variable(), point, node.direction()),
380 child_changed, original_changed);
381 }
382 void visit(const RootOfNode& node) override {
383 const bool original_changed = changed;
384 finish_rewrite(node.clone(), false, original_changed);
385 }
386};
387
388Result<SymbolicExpr> RewriteEngine::apply_step_checked(
389 const SymbolicExpr& expr,
390 ComputationContext& context) const {
391 auto budget = context.consume_steps(1, "rewrite.apply_step");
392 if (!budget) return Result<SymbolicExpr>::failure(budget.error());
393 if (!LMCAS::detail::node(expr)) {
395 CasErrc::InvalidArgument, "rewrite expression must not be null",
396 "rewrite.apply_step");
397 }
398 RewriteVisitor v(*this, context);
402}
403
404Result<SymbolicExpr> RewriteEngine::apply_checked(
405 const SymbolicExpr& expr,
407 int max_iterations) const {
408 if (max_iterations < 0) {
410 CasErrc::InvalidArgument, "rewrite iteration count must be non-negative",
411 "rewrite.apply");
412 }
413 SymbolicExpr current = expr;
414 for (int i = 0; i < max_iterations; ++i) {
415 auto next_result = apply_step_checked(current, context);
416 if (!next_result) return next_result;
417 SymbolicExpr next = std::move(next_result.value());
418 if (LMCAS::detail::node(next)->equals(*LMCAS::detail::node(current))) {
419 return Result<SymbolicExpr>::success(std::move(current));
420 }
421 current = next;
422 }
423 return Result<SymbolicExpr>::success(std::move(current));
424}
425
426Result<SymbolicExpr> RewriteEngine::apply_step(const SymbolicExpr& expr) const {
428 return apply_step_checked(expr, context);
429}
430
431Result<SymbolicExpr> RewriteEngine::apply(
432 const SymbolicExpr& expr,
433 int max_iterations) const {
435 return apply_checked(expr, context, max_iterations);
436}
437
438}
加法节点,表示多个操作数的求和。
复数节点,表示 real + imag * i。
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
矩阵节点,支持稠密和稀疏两种存储方式。
std::map< size_t, std::shared_ptr< const SymbolicNode > > SparseStorage
稀疏存储,索引映射到节点。
std::vector< std::shared_ptr< const SymbolicNode > > DenseStorage
稠密存储,按行优先展开。
乘法节点,表示多个操作数的乘积。
分段函数节点,表示条件分支表达式.
幂运算节点,表示 base^exponent。
连乘节点,表示符号有限/无限连乘 prod_{k=a}^{b} f(k).
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
void visit(const TransformNode &node) override
void visit(const PowerNode &node) override
RewriteVisitor(const RewriteEngine &e, ComputationContext &ctx)
void visit(const FiniteSetNode &node) override
void visit(const ComplexNode &node) override
const RewriteEngine & engine
void visit(const VariableNode &node) override
void visit(const IntegralNode &node) override
void visit(const MatrixNode &node) override
void visit(const IntervalNode &node) override
void visit(const AddNode &node) override
void visit(const UninterpretedFunctionNode &node) override
ComputationContext & context
void visit(const MultiplyNode &node) override
std::shared_ptr< const SymbolicNode > visit_child(const std::shared_ptr< const SymbolicNode > &child, bool &child_changed)
void visit(const NumberNode &node) override
void visit(const SetBuilderNode &node) override
void visit(const RootOfNode &node) override
void visit(const FunctionNode &node) override
void visit(const LogicalNode &node) override
std::shared_ptr< const SymbolicNode > result
void visit(const PiecewiseNode &node) override
void visit(const QuantityNode &node) override
void visit(const ProductNode &node) override
void visit(const MembershipNode &node) override
std::shared_ptr< const SymbolicNode > try_match(std::shared_ptr< const SymbolicNode > node)
void finish_rewrite(std::shared_ptr< const SymbolicNode > node, bool child_changed, bool original_changed)
std::shared_ptr< const SymbolicNode > get_result() const
void visit(const RelationalNode &node) override
void visit(const QuantifierNode &node) override
void visit(const SummationNode &node) override
void visit(const LimitNode &node) override
求和节点,表示符号有限/无限求和 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_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
积分变换节点,表示 Laplace,Fourier,Z 变换及其逆变换.
变量节点,表示一个符号变量。
模式匹配引擎 Matcher 与重写规则系统 RewriteEngine。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
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 e()
__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 std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult real(const ExprPtr &expression, ComputationContext &context)
const ExprPtr & lower
const ExprPtr & set
const ExprPtr RelationOp op
const std::vector< Binding > & bindings
const NumberDomainSet & domain
ExprPtr imag
const ExprPtr & target
const ExprPtr & right
std::unordered_map< std::string, SymbolicExpr > MatchMap
匹配结果映射,通配符名称 → 绑定的表达式
const std::string const ExprPtr & value
内部 AST 定义。