LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
transform_convolution.cpp
浏览该文件的文档.
1#include <stdexcept>
5#include <cmath>
6#include <exception>
7
8namespace LMCAS {
9using namespace transform_detail;
10
12 const std::shared_ptr<SymbolicExpr>& f,
13 const std::shared_ptr<SymbolicExpr>& g,
14 const std::string& var,
16 const std::string& operation) {
17 auto step = context.consume_steps(1, operation);
18 if (!step) return step;
19 if (!f || !LMCAS::detail::node(f) || !g || !LMCAS::detail::node(g)) {
21 "convolution expressions cannot be null",
22 operation);
23 }
24 if (var.empty()) {
26 "convolution variable name cannot be empty",
27 operation);
28 }
29 return Result<void>::success();
30}
31
33 const std::shared_ptr<SymbolicExpr>& f, const std::shared_ptr<SymbolicExpr>& g,
34 const std::string& variable, ComputationContext& context);
35
37 const AddNode& addition, const std::shared_ptr<SymbolicExpr>& other,
38 bool sum_is_left, const std::string& variable, ComputationContext& context) try {
39 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
40 (context).limits().max_ast_nodes, "transform");
41 std::shared_ptr<SymbolicExpr> accumulated;
42 for (const auto& operand : addition.operands()) {
43 auto term = detail::make_expression_ptr(operand);
44 auto transformed = sum_is_left
45 ? te_convolve_core(term, other, variable, context)
46 : te_convolve_core(other, term, variable, context);
47 if (!transformed) return transformed;
48 auto expression = transformed.value().value.expression;
49 accumulated = accumulated ? SymbolicExpr::add(accumulated, expression) : expression;
50 }
52 accumulated ? detail::make_expression_ptr(detail::normalize_node(detail::node(accumulated), transform_budget)) : SymbolicExpr::number(0), "convolve");
53} catch (const CasError& error) {
55} catch (const std::bad_alloc&) {
56 return TransformEngineResult::failure(CasErrc::ResourceLimit, "allocation failed", "te_convolve_sum");
57} catch (const std::length_error& error) {
58 return TransformEngineResult::failure(CasErrc::ResourceLimit, error.what(), "te_convolve_sum");
59} catch (const std::exception& error) {
60 return TransformEngineResult::failure(CasErrc::InternalInvariant, error.what(), "te_convolve_sum");
61}
62
64 const std::shared_ptr<SymbolicExpr>& f,
65 const std::shared_ptr<SymbolicExpr>& g,
66 const std::string& variable,
68try {
69 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
70 (context).limits().max_ast_nodes, "transform");
71 constexpr const char* operation = "convolve";
72 auto step = context.consume_steps(1, operation);
73 if (!step) return TransformEngineResult::failure(step.error());
74
75 if (te_is_zero(f) || te_is_zero(g)) {
76 return te_wrap_transform_result(SymbolicExpr::number(0), operation);
77 }
78
79 auto left_sum = std::dynamic_pointer_cast<const AddNode>(detail::node(f));
80 if (left_sum) {
81 return te_convolve_sum(*left_sum, g, true, variable, context);
82 }
83 auto right_sum = std::dynamic_pointer_cast<const AddNode>(detail::node(g));
84 if (right_sum) {
85 return te_convolve_sum(*right_sum, f, false, variable, context);
86 }
87
88 auto left_parts = te_split_coeff(f, variable);
89 if (te_depends_on(left_parts.second, variable) &&
90 left_parts.second->to_string() != f->to_string()) {
91 auto inner =
92 te_convolve_core(left_parts.second, g, variable, context);
93 if (!inner) return inner;
94 auto scaled = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(
95 left_parts.first, inner.value().value.expression)), transform_budget));
96 return te_wrap_transform_result(scaled, operation);
97 }
98 auto right_parts = te_split_coeff(g, variable);
99 if (te_depends_on(right_parts.second, variable) &&
100 right_parts.second->to_string() != g->to_string()) {
101 auto inner =
102 te_convolve_core(f, right_parts.second, variable, context);
103 if (!inner) return inner;
104 auto scaled = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(
105 right_parts.first, inner.value().value.expression)), transform_budget));
106 return te_wrap_transform_result(scaled, operation);
107 }
108
109 const auto left = te_match_scaled_gaussian(f, variable);
110 const auto right = te_match_scaled_gaussian(g, variable);
111 if (!left || !right) {
114 "当前双边卷积规则不支持该表达式对", operation);
115 }
116
117 const Rational rate_sum = left->rate + right->rate;
118 const Rational output_rate = left->rate * right->rate / rate_sum;
119 auto scale = SymbolicExpr::multiply(
120 SymbolicExpr::multiply(left->coefficient, right->coefficient),
121 SymbolicExpr::sqrt(SymbolicExpr::divide(
124 SymbolicExpr::number(rate_sum))));
125 auto square = SymbolicExpr::power(
126 SymbolicExpr::variable(variable), SymbolicExpr::number(2));
127 auto exponent = SymbolicExpr::multiply(
128 SymbolicExpr::number(-output_rate), square);
129 auto gaussian = SymbolicExpr::exp(exponent);
131 detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(scale, gaussian)), transform_budget)), operation);
132} catch (const CasError& error) {
133 return TransformEngineResult::failure(error);
134} catch (const std::bad_alloc&) {
135 return TransformEngineResult::failure(CasErrc::ResourceLimit, "allocation failed", "convolve");
136} catch (const std::length_error& error) {
137 return TransformEngineResult::failure(CasErrc::ResourceLimit, error.what(), "convolve");
138} catch (const std::exception& error) {
139 return TransformEngineResult::failure(CasErrc::InternalInvariant, error.what(), "convolve");
140}
141
143 const std::shared_ptr<SymbolicExpr>& f,
144 const std::shared_ptr<SymbolicExpr>& g,
145 const std::string& var,
147 const std::string operation = "convolve";
148 auto valid =
149 te_validate_convolution_inputs(f, g, var, context, operation);
150 if (!valid) return TransformEngineResult::failure(valid.error());
151 try {
152 return te_convolve_core(f, g, var, context);
153 } catch (const std::bad_alloc&) {
155 CasErrc::ResourceLimit, "双边卷积分配失败", operation);
156 } catch (const std::exception& error) {
158 CasErrc::InternalInvariant, error.what(), operation);
159 }
160}
161
163 const std::shared_ptr<SymbolicExpr>& f,
164 const std::shared_ptr<SymbolicExpr>& g,
165 const std::string& var) {
167 return convolve_checked(f, g, var, context);
168}
169
170}
加法节点,表示多个操作数的求和。
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::pair< std::shared_ptr< SymbolicExpr >, std::shared_ptr< SymbolicExpr > > te_split_coeff(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable)
bool te_is_zero(const std::shared_ptr< SymbolicExpr > &expression)
bool te_depends_on(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable)
TransformEngineResult te_wrap_transform_result(std::shared_ptr< SymbolicExpr > expression, const std::string &operation)
std::optional< GaussianMatch > te_match_scaled_gaussian(const std::shared_ptr< SymbolicExpr > &expression, const std::string &variable)
const std::string & variable
static Result< void > te_validate_convolution_inputs(const std::shared_ptr< SymbolicExpr > &f, const std::shared_ptr< SymbolicExpr > &g, const std::string &var, ComputationContext &context, const std::string &operation)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
static TransformEngineResult te_convolve_sum(const AddNode &addition, const std::shared_ptr< SymbolicExpr > &other, bool sum_is_left, const std::string &variable, ComputationContext &context)
static TransformEngineResult te_convolve_core(const std::shared_ptr< SymbolicExpr > &f, const std::shared_ptr< SymbolicExpr > &g, const std::string &variable, ComputationContext &context)
TransformEngineResult convolve_checked(const std::shared_ptr< SymbolicExpr > &f, const std::shared_ptr< SymbolicExpr > &g, const std::string &var, ComputationContext &context)
const ExprPtr & exponent
Result< Verified< EvaluatedTransform > > TransformEngineResult
const ExprPtr & right