LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
equivalence_complex.cpp
浏览该文件的文档.
2
4
5#include <stdexcept>
6#include <utility>
7#include <vector>
8
10
12 const detail::SymbolicNodePtr& original,
13 detail::RewriteBudget& budget) {
14 budget.append_size(budget.append_size(1, budget.measure(detail::node(real))),
15 budget.measure(detail::node(imag)));
17 try {
20 } catch (const std::invalid_argument&) {
21 return detail::make_expression_ptr(original);
22 }
23 return normalize_equivalence(value, budget);
24}
25
26namespace {
27
28
30 const detail::SymbolicNodePtr& original,
31 detail::RewriteBudget& budget) {
32 std::vector<detail::SymbolicNodePtr> operands;
33 bool changed = false;
34 operands.reserve(add.operands().size());
35 for (const auto& operand : add.operands()) {
36 auto canonical = canonicalize_complex_product(
37 *detail::make_expression_ptr(operand), budget);
38 changed = changed || detail::node(canonical) != operand;
39 operands.push_back(detail::node(canonical));
40 }
41 if (!changed) {
42 budget.measure(original);
43 return detail::make_expression_ptr(original);
44 }
45 std::size_t size = 0;
46 for (const auto& operand : operands) {
47 size = budget.append_size(size, budget.measure(operand));
48 }
50 SymbolicFactory::create_add(std::move(operands), &budget)), budget);
51}
52
54 const detail::SymbolicNodePtr& original,
55 detail::RewriteBudget& budget) {
56 auto exponent = exact_small_integer_node(power.exponent(), 0, 16);
57 if (exponent) {
59 *detail::make_expression_ptr(power.base()), budget);
60 if (std::dynamic_pointer_cast<const ComplexNode>(detail::node(base))) {
61 budget.require_nodes(1);
62 auto result = SymbolicExpr::number(1);
63 for (int index = 0; index < *exponent; ++index) {
65 &budget, 0, detail::node(result), detail::node(base));
67 *SymbolicExpr::multiply(result, base), budget);
68 }
69 return normalize_equivalence(result, budget);
70 }
71 }
72 budget.measure(original);
73 return detail::make_expression_ptr(original);
74}
75
77 ExprPtr real = SymbolicExpr::number(1);
78 ExprPtr imag = SymbolicExpr::number(0);
79 bool saw_complex = false;
80
81 void accumulate(const ExprPtr& factor, detail::RewriteBudget& budget) {
82 ExprPtr factor_real;
83 ExprPtr factor_imag;
84 if (auto complex = std::dynamic_pointer_cast<const ComplexNode>(
85 detail::node(factor))) {
86 saw_complex = true;
87 factor_real = detail::make_expression_ptr(complex->real());
88 factor_imag = detail::make_expression_ptr(complex->imag());
89 } else {
90 factor_real = factor;
91 budget.require_nodes(1);
92 factor_imag = SymbolicExpr::number(0);
93 }
95 &budget, 0, detail::node(real), detail::node(factor_real));
96 auto ac = SymbolicExpr::multiply(real, factor_real);
98 &budget, 0, detail::node(imag), detail::node(factor_imag));
99 auto bd = SymbolicExpr::multiply(imag, factor_imag);
101 &budget, 0, detail::node(real), detail::node(factor_imag));
102 auto ad = SymbolicExpr::multiply(real, factor_imag);
104 &budget, 0, detail::node(imag), detail::node(factor_real));
105 auto bc = SymbolicExpr::multiply(imag, factor_real);
106 const auto negative_size = budget.append_size(1, bd_size);
107 budget.append_size(budget.append_size(1, ac_size), negative_size);
108 auto next_real = normalize_equivalence(SymbolicExpr::add(
109 ac, SymbolicExpr::multiply(SymbolicExpr::number(-1), bd)), budget);
110 budget.append_size(budget.append_size(1, ad_size), bc_size);
111 auto next_imag = normalize_equivalence(SymbolicExpr::add(ad, bc), budget);
112 real = std::move(next_real);
113 imag = std::move(next_imag);
114 }
115};
116
118 const detail::SymbolicNodePtr& original,
119 detail::RewriteBudget& budget) {
120 std::vector<ExprPtr> factors;
121 bool changed = false;
122 bool saw_complex = false;
123 factors.reserve(multiply.operands().size());
124 for (const auto& operand : multiply.operands()) {
125 auto canonical = canonicalize_complex_product(
126 *detail::make_expression_ptr(operand), budget);
127 changed = changed || detail::node(canonical) != operand;
128 saw_complex = saw_complex ||
129 static_cast<bool>(std::dynamic_pointer_cast<const ComplexNode>(
130 detail::node(canonical)));
131 factors.push_back(std::move(canonical));
132 }
133 if (!changed && !saw_complex) {
134 budget.measure(original);
135 return detail::make_expression_ptr(original);
136 }
137 if (!saw_complex) {
138 std::vector<detail::SymbolicNodePtr> operands;
139 std::size_t size = 0;
140 operands.reserve(factors.size());
141 for (const auto& factor : factors) {
142 size = budget.append_size(size, budget.measure(detail::node(factor)));
143 operands.push_back(detail::node(factor));
144 }
146 SymbolicFactory::create_multiply(std::move(operands), &budget)), budget);
147 }
148 ComplexProduct product;
149 for (const auto& factor : factors) {
150 product.accumulate(factor, budget);
151 }
152 return rewritten_complex(product.real, product.imag, original, budget);
153}
154
155}
156
157ExprPtr canonicalize_complex_product(const SymbolicExpr& expression,
158 detail::RewriteBudget& budget) {
159 detail::RewriteScope scope(&budget);
160 const auto& node = detail::node(expression);
161 if (auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
162 return canonicalize_sum(*add, node, budget);
163 }
164 if (auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
165 return canonicalize_power(*power, node, budget);
166 }
167 if (auto complex = std::dynamic_pointer_cast<const ComplexNode>(node)) {
169 *detail::make_expression_ptr(complex->real()), budget);
171 *detail::make_expression_ptr(complex->imag()), budget);
172 return rewritten_complex(real, imag, node, budget);
173 }
174 if (auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
175 return canonicalize_product(*multiply, node, budget);
176 }
177 budget.measure(node);
178 return detail::make_expression_ptr(node);
179}
180
181}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
幂运算节点,表示 base^exponent。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
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)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
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::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
ExprPtr canonicalize_power(const PowerNode &power, const detail::SymbolicNodePtr &original, detail::RewriteBudget &budget)
ExprPtr canonicalize_product(const MultiplyNode &multiply, const detail::SymbolicNodePtr &original, detail::RewriteBudget &budget)
ExprPtr canonicalize_sum(const AddNode &add, const detail::SymbolicNodePtr &original, detail::RewriteBudget &budget)
ExprPtr normalize_equivalence(const ExprPtr &expression, detail::RewriteBudget &budget)
ExprPtr canonicalize_complex_product(const SymbolicExpr &expression, detail::RewriteBudget &budget)
ExprPtr rewritten_complex(const ExprPtr &real, const ExprPtr &imag, const detail::SymbolicNodePtr &original, detail::RewriteBudget &budget)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
std::size_t normalization_check_arithmetic(detail::RewriteBudget *budget, std::size_t extra_nodes, const std::shared_ptr< const Nodes > &... children)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult complex(ExprPtr real, ExprPtr imag)
const ExprPtr & exponent
std::optional< int > exact_small_integer_node(const detail::SymbolicNodePtr &node, int min_value, int max_value)
ExprPtr imag
std::shared_ptr< SymbolicExpr > ExprPtr
const std::string const ExprPtr & value