LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
matcher.cpp
浏览该文件的文档.
1#include "matcher.hpp"
4#include <algorithm>
5#include <type_traits>
6
7namespace LMCAS {
8
9SymbolicExpr wildcard(const std::string& name) {
11}
12
13static bool match_recursive(const std::shared_ptr<const SymbolicNode>& p_node,
14 const std::shared_ptr<const SymbolicNode>& t_node,
15 const std::unordered_set<std::string>& wildcards,
16 MatchMap& results);
17
18static bool match_commutative_recursive(const std::vector<std::shared_ptr<const SymbolicNode>>& p_ops,
19 const std::vector<std::shared_ptr<const SymbolicNode>>& t_ops,
20 std::vector<bool>& used_t,
21 size_t p_index,
22 const std::unordered_set<std::string>& wildcards,
23 MatchMap& results) {
24
25 if (p_index == p_ops.size()) {
26 return true;
27 }
28
29 for (size_t j = 0; j < t_ops.size(); ++j) {
30 if (!used_t[j]) {
31
32 MatchMap saved_results = results;
33
34 if (match_recursive(p_ops[p_index], t_ops[j], wildcards, results)) {
35 used_t[j] = true;
36 if (match_commutative_recursive(p_ops, t_ops, used_t, p_index + 1, wildcards, results)) {
37 return true;
38 }
39
40 used_t[j] = false;
41 results = saved_results;
42 } else {
43
44 results = saved_results;
45 }
46 }
47 }
48
49 return false;
50}
51
52static bool is_wildcard(const std::shared_ptr<const SymbolicNode>& node,
53 const std::unordered_set<std::string>& wildcards,
54 std::string& name_out) {
55 if (!node) return false;
56
57 auto var = std::dynamic_pointer_cast<const VariableNode>(node);
58 if (var && !var->is_constant()) {
59 if (wildcards.count(var->name())) {
60 name_out = var->name();
61 return true;
62 }
63 }
64 return false;
65}
66
67template <typename Operation>
68static std::shared_ptr<const SymbolicNode> combine_operands(
69 std::vector<std::shared_ptr<const SymbolicNode>> operands) {
70 if constexpr (std::is_same_v<Operation, AddNode>) {
71 return SymbolicFactory::create_add(std::move(operands));
72 } else {
73 return SymbolicFactory::create_multiply(std::move(operands));
74 }
75}
76
77template <typename Operation>
78static void record_remainder(const Operation& target, const std::vector<bool>& used,
79 const char* key, MatchMap& results) {
80 std::vector<std::shared_ptr<const SymbolicNode>> rest;
81 for (size_t index = 0; index < used.size(); ++index) {
82 if (!used[index]) {
83 rest.push_back(target.operands()[index]);
84 }
85 }
86 if (rest.empty()) {
87 return;
88 }
89 auto remainder = rest.size() == 1 ? rest.front() : combine_operands<Operation>(std::move(rest));
90 const auto found = results.find(key);
91 if (found == results.end()) {
92 results.emplace(key, detail::expression_from_node(remainder));
93 return;
94 }
95 std::vector<std::shared_ptr<const SymbolicNode>> operands;
96 if (const auto* existing = dynamic_cast<const Operation*>(detail::node(found->second).get())) {
97 operands.insert(operands.end(), existing->operands().begin(), existing->operands().end());
98 } else {
99 operands.push_back(detail::node(found->second));
100 }
101 operands.push_back(remainder);
102 found->second = detail::expression_from_node(combine_operands<Operation>(std::move(operands)));
103}
104
105template <typename Operation>
106static bool match_operation(const Operation& pattern, const Operation& target,
107 const std::unordered_set<std::string>& wildcards,
108 const char* rest_key, MatchMap& results) {
109 if (pattern.operands().size() > target.operands().size()) {
110 return false;
111 }
112 std::vector<bool> used(target.operands().size(), false);
113 if (!match_commutative_recursive(pattern.operands(), target.operands(), used, 0, wildcards, results)) {
114 return false;
115 }
116 record_remainder(target, used, rest_key, results);
117 return true;
118}
119
120static bool match_function(const FunctionNode& pattern, const FunctionNode& target,
121 const std::unordered_set<std::string>& wildcards, MatchMap& results) {
122 if (pattern.type() != target.type() || pattern.arguments().size() != target.arguments().size()) {
123 return false;
124 }
125 for (size_t index = 0; index < pattern.arguments().size(); ++index) {
126 if (!match_recursive(pattern.arguments()[index], target.arguments()[index], wildcards, results)) {
127 return false;
128 }
129 }
130 return true;
131}
132
133static bool match_recursive(const std::shared_ptr<const SymbolicNode>& pattern,
134 const std::shared_ptr<const SymbolicNode>& target,
135 const std::unordered_set<std::string>& wildcards, MatchMap& results) {
136 if (!pattern) {
137 return !target;
138 }
139 if (!target) {
140 return false;
141 }
142 std::string name;
143 if (is_wildcard(pattern, wildcards, name)) {
144 const auto existing = results.find(name);
145 if (existing != results.end()) {
146 return detail::node(existing->second)->equals(*target);
147 }
148 results.emplace(name, detail::expression_from_node(target));
149 return true;
150 }
151 if (pattern->type_priority() != target->type_priority()) {
152 return false;
153 }
154 if (pattern->is_number() || dynamic_cast<const VariableNode*>(pattern.get())) {
155 return pattern->equals(*target);
156 }
157 if (const auto* add = dynamic_cast<const AddNode*>(pattern.get())) {
158 return match_operation(*add, static_cast<const AddNode&>(*target), wildcards, "__Add_REST__", results);
159 }
160 if (const auto* multiply = dynamic_cast<const MultiplyNode*>(pattern.get())) {
161 return match_operation(*multiply, static_cast<const MultiplyNode&>(*target), wildcards, "__Mul_REST__", results);
162 }
163 if (const auto* power = dynamic_cast<const PowerNode*>(pattern.get())) {
164 const auto& other = static_cast<const PowerNode&>(*target);
165 return match_recursive(power->base(), other.base(), wildcards, results) &&
166 match_recursive(power->exponent(), other.exponent(), wildcards, results);
167 }
168 if (const auto* function = dynamic_cast<const FunctionNode*>(pattern.get())) {
169 return match_function(*function, static_cast<const FunctionNode&>(*target), wildcards, results);
170 }
171 return pattern->equals(*target);
172}
173
174bool Matcher::match(const SymbolicExpr& pattern, const SymbolicExpr& target,
175 const std::unordered_set<std::string>& wildcards,
176 MatchMap& results) {
177 if (!LMCAS::detail::node(pattern)) return !LMCAS::detail::node(target);
179}
180
181
182SymbolicExpr Matcher::replace(const SymbolicExpr& template_expr, const MatchMap& bindings, bool use_rest) {
183 if (!LMCAS::detail::node(template_expr)) return template_expr;
184
185 auto replaced = LMCAS::detail::node(template_expr);
186 std::set<std::string> occupied = LMCAS::free_variables(replaced);
187 for (const auto& [name, expression] : bindings) {
188 const auto names = LMCAS::free_variables(LMCAS::detail::node(expression));
189 occupied.insert(names.begin(), names.end());
190 }
191
192 std::vector<std::pair<std::string, std::string>> placeholders;
193 placeholders.reserve(bindings.size());
194 std::size_t suffix = 0;
195 for (const auto& [name, expression] : bindings) {
196 (void)expression;
197 std::string placeholder;
198 do {
199 placeholder = "__lmcas_match_binding_" + std::to_string(suffix++);
200 } while (!occupied.insert(placeholder).second);
201 replaced = LMCAS::substitute_free(
202 replaced, name, SymbolicFactory::create_variable(placeholder));
203 placeholders.emplace_back(name, std::move(placeholder));
204 }
205 for (const auto& [name, placeholder] : placeholders) {
206 replaced = LMCAS::substitute_free(
207 replaced, placeholder, LMCAS::detail::node(bindings.at(name)));
208 }
209
210 auto res = LMCAS::detail::expression_from_node(std::move(replaced));
211 if (use_rest) {
212
213 if (bindings.find("__Add_REST__") != bindings.end()) {
214 auto rest = bindings.at("__Add_REST__");
215
216 std::vector<std::shared_ptr<const SymbolicNode>> ops;
217 if (auto add_node = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(res))) {
218 ops = add_node->operands();
219 } else {
220 ops.push_back(LMCAS::detail::node(res));
221 }
222
223 if (auto rest_add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(rest))) {
224 ops.insert(ops.end(), rest_add->operands().begin(), rest_add->operands().end());
225 } else {
226 ops.push_back(LMCAS::detail::node(rest));
227 }
229 }
230
231 if (bindings.find("__Mul_REST__") != bindings.end()) {
232 auto rest = bindings.at("__Mul_REST__");
233
234 std::vector<std::shared_ptr<const SymbolicNode>> ops;
235 if (auto mul_node = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(res))) {
236 ops = mul_node->operands();
237 } else {
238 ops.push_back(LMCAS::detail::node(res));
239 }
240
241 if (auto rest_mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(rest))) {
242 ops.insert(ops.end(), rest_mul->operands().begin(), rest_mul->operands().end());
243 } else {
244 ops.push_back(LMCAS::detail::node(rest));
245 }
247 }
248 }
249
250 return res;
251}
252
253}
加法节点,表示多个操作数的求和。
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
FuncType type() const noexcept
const std::vector< std::shared_ptr< const SymbolicNode > > & arguments() const noexcept
乘法节点,表示多个操作数的乘积。
幂运算节点,表示 base^exponent。
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_variable(const std::string &name)
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
bool equals(const SymbolicNode &other) const
判断两个节点是否结构相等.
变量节点,表示一个符号变量。
模式匹配引擎 Matcher 与重写规则系统 RewriteEngine。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
static bool match_operation(const Operation &pattern, const Operation &target, const std::unordered_set< std::string > &wildcards, const char *rest_key, MatchMap &results)
static bool match_commutative_recursive(const std::vector< std::shared_ptr< const SymbolicNode > > &p_ops, const std::vector< std::shared_ptr< const SymbolicNode > > &t_ops, std::vector< bool > &used_t, size_t p_index, const std::unordered_set< std::string > &wildcards, MatchMap &results)
SymbolicExpr wildcard(const std::string &name)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
static void record_remainder(const Operation &target, const std::vector< bool > &used, const char *key, MatchMap &results)
const std::vector< Binding > & bindings
std::set< std::string > free_variables(const detail::SymbolicNodePtr &expression, detail::RewriteBudget *budget)
const ExprPtr & target
const ExprPtr const std::vector< std::string > & wildcards
std::unordered_map< std::string, SymbolicExpr > MatchMap
匹配结果映射,通配符名称 → 绑定的表达式
static std::shared_ptr< const SymbolicNode > combine_operands(std::vector< std::shared_ptr< const SymbolicNode > > operands)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
static bool match_function(const FunctionNode &pattern, const FunctionNode &target, const std::unordered_set< std::string > &wildcards, MatchMap &results)
static bool is_wildcard(const std::shared_ptr< const SymbolicNode > &node, const std::unordered_set< std::string > &wildcards, std::string &name_out)
detail::SymbolicNodePtr substitute_free(const detail::SymbolicNodePtr &expression, const std::string &variable, const detail::SymbolicNodePtr &replacement, detail::RewriteBudget *budget)
static bool match_recursive(const std::shared_ptr< const SymbolicNode > &p_node, const std::shared_ptr< const SymbolicNode > &t_node, const std::unordered_set< std::string > &wildcards, MatchMap &results)
内部 AST 定义。