LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
normalization_utils.cpp
浏览该文件的文档.
2
3#include <limits>
4
5namespace LMCAS {
6
7void normalization_append(detail::RewriteBudget* budget, std::size_t& nodes,
8 std::vector<std::shared_ptr<const SymbolicNode>>& children,
9 std::shared_ptr<const SymbolicNode> child) {
10 if (budget) {
11 nodes = budget->append_size(nodes, budget->measure(child));
12 }
13 children.push_back(std::move(child));
14}
15
17 std::size_t rows, std::size_t cols, bool wrapped) {
18 if (budget) {
19 const auto maximum = std::numeric_limits<std::size_t>::max();
20 if (cols != 0 && rows > maximum / cols) {
21 budget->append_size(maximum, 1);
22 }
23 budget->append_size(wrapped ? 1 : 0, rows * cols);
24 }
25 return rows * cols;
26}
27
28
29bool normalization_factor_less(const std::shared_ptr<const SymbolicNode>& left,
30 const std::shared_ptr<const SymbolicNode>& right) {
31 const BigInt a = get_node_degree_helper(left);
32 const BigInt b = get_node_degree_helper(right);
33 if (a != b) {
34 return a > b;
35 }
36 return left->compare(*right) < 0;
37}
38
40 const std::shared_ptr<const NumberNode>& node, BigInt& value) {
41 if (!node) {
42 return false;
43 }
44 if (const auto* integer = std::get_if<BigInt>(&node->value())) {
45 value = *integer;
46 return true;
47 }
48 const auto& rational = std::get<Rational>(node->value());
49 if (rational.get_denominator() != BigInt(1)) {
50 return false;
51 }
52 value = rational.get_numerator();
53 return true;
54}
55
56/**
57 * @brief 计算 AST 节点的多项式次数
58 * @param node 输入节点
59 * @return 节点对应的多项式次数
60 */
61BigInt get_node_degree_helper(const std::shared_ptr<const SymbolicNode>& node) {
62 if (!node) {
63 return BigInt(0);
64 }
65 if (std::dynamic_pointer_cast<const VariableNode>(node)) {
66 return BigInt(1);
67 }
68 if (auto p = std::dynamic_pointer_cast<const PowerNode>(node)) {
69 const auto e = std::dynamic_pointer_cast<const NumberNode>(p->exponent());
70 BigInt degree;
71 if (try_get_integer_value(e, degree)) {
72 return degree;
73 }
74 return BigInt(1);
75 }
76 if (auto m = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
77 BigInt d(0);
78 for (auto& op : m->operands()) d += get_node_degree_helper(op);
79 return d;
80 }
81 return BigInt(0);
82}
83std::shared_ptr<const SymbolicNode> make_normalized_multiply_node(
84 const std::vector<std::shared_ptr<const SymbolicNode>>& ops,
85 detail::RewriteBudget* budget) {
86 std::size_t nodes = 0;
87 if (budget) {
88 for (const auto& op : ops) {
89 nodes = budget->append_size(nodes, budget->measure(op));
90 }
91 }
92 normalization_check_arithmetic<MultiplyNode>(budget, ops, nodes, ops.size() != 1);
93 if (ops.empty()) {
95 }
96 if (ops.size() == 1) {
97 return ops[0];
98 }
100}
101std::shared_ptr<const SymbolicNode> norm_subst_index(
102 const std::shared_ptr<const SymbolicNode>& node,
103 const std::string& index_var,
104 const std::shared_ptr<const SymbolicNode>& value, detail::RewriteBudget* budget) {
105 normalization_check_children(budget, 0, node);
106 return LMCAS::substitute_free(node, index_var, value, budget);
107}
108bool NodeCompare::operator()(const std::shared_ptr<const SymbolicNode>& lhs, const std::shared_ptr<const SymbolicNode>& rhs) const {
109 if (!lhs && !rhs) {
110 return false;
111 }
112 if (!lhs) {
113 return true;
114 }
115 if (!rhs) {
116 return false;
117 }
118
119 const BigInt d1 = get_node_degree_helper(lhs);
120 const BigInt d2 = get_node_degree_helper(rhs);
121 if (d1 != d2) {
122 return d1 > d2;
123 }
124
125 bool isNum1 = std::dynamic_pointer_cast<const NumberNode>(lhs) != nullptr;
126 bool isNum2 = std::dynamic_pointer_cast<const NumberNode>(rhs) != nullptr;
127 if (isNum1 != isNum2) {
128 return isNum1;
129 }
130
131 if (lhs->type_priority() != rhs->type_priority()) {
132 return lhs->type_priority() < rhs->type_priority();
133 }
134
135 return lhs->compare(*rhs) < 0;
136 }
138 if (const auto* rational = std::get_if<Rational>(&node.value())) {
139 return *rational;
140 }
141 return Rational(std::get<BigInt>(node.value()));
142}
143
144/**
145 * @brief 两个数值节点相加
146 * @param a 加数节点
147 * @param b 加数节点
148 * @return 和的数值节点
149 */
150std::shared_ptr<const NumberNode> add_numbers(const std::shared_ptr<const NumberNode>& a, const std::shared_ptr<const NumberNode>& b) {
151 if (std::holds_alternative<Rational>(a->value()) || std::holds_alternative<Rational>(b->value())) {
152 const Rational r1 = exact_number_as_rational(*a);
153 const Rational r2 = exact_number_as_rational(*b);
155 }
156
158 std::get<BigInt>(a->value()) + std::get<BigInt>(b->value()));
159}
160
161/**
162 * @brief 两个数值节点相乘
163 * @param a 乘数节点
164 * @param b 乘数节点
165 * @return 积的数值节点
166 */
167std::shared_ptr<const NumberNode> multiply_numbers(const std::shared_ptr<const NumberNode>& a, const std::shared_ptr<const NumberNode>& b) {
168 if (std::holds_alternative<Rational>(a->value()) || std::holds_alternative<Rational>(b->value())) {
169 const Rational r1 = exact_number_as_rational(*a);
170 const Rational r2 = exact_number_as_rational(*b);
172 }
173
175 std::get<BigInt>(a->value()) * std::get<BigInt>(b->value()));
176}
178 return variable.is_constant() &&
179 (variable.name() == "pi" || variable.name() == "π");
180}
181
182bool get_pi_coeff(const std::shared_ptr<const SymbolicNode>& node, Rational& k) {
183 const auto variable = std::dynamic_pointer_cast<const VariableNode>(node);
185 k = Rational(1);
186 return true;
187 }
188 const auto multiply = std::dynamic_pointer_cast<const MultiplyNode>(node);
189 if (!multiply) {
190 return false;
191 }
192 bool has_pi = false;
193 k = Rational(1);
194 for (const auto& operand : multiply->operands()) {
195 if (const auto variable = std::dynamic_pointer_cast<const VariableNode>(operand)) {
196 if (has_pi || !is_pi_variable(*variable)) return false;
197 has_pi = true;
198 continue;
199 }
200 const auto number = std::dynamic_pointer_cast<const NumberNode>(operand);
201 if (!number) {
202 return false;
203 }
204 if (const auto* rational = std::get_if<Rational>(&number->value())) {
205 k = k * *rational;
206 continue;
207 }
208 const auto* integer = std::get_if<BigInt>(&number->value());
209 if (!integer) {
210 return false;
211 }
212 k = k * Rational(*integer);
213 }
214 return has_pi;
215}
216
217}
变量节点,表示一个符号变量。
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
std::size_t append_size(std::size_t current, std::size_t child)
std::shared_ptr< const Node > make_node(Args &&... args)
std::shared_ptr< const NumberNode > add_numbers(const std::shared_ptr< const NumberNode > &left, const std::shared_ptr< const NumberNode > &right)
两个数值节点相加
const std::string & variable
ExprResult e()
ExprResult integer(Integer)=delete
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
std::size_t normalization_check_arithmetic(detail::RewriteBudget *budget, std::size_t extra_nodes, const std::shared_ptr< const Nodes > &... children)
std::size_t normalization_check_count(detail::RewriteBudget *budget, std::size_t rows, std::size_t cols=1, bool wrapped=true)
std::shared_ptr< const SymbolicNode > norm_subst_index(const std::shared_ptr< const SymbolicNode > &node, const std::string &index_var, const std::shared_ptr< const SymbolicNode > &value, detail::RewriteBudget *budget=nullptr)
const MultiPoly & b
std::shared_ptr< const NumberNode > multiply_numbers(const std::shared_ptr< const NumberNode > &left, const std::shared_ptr< const NumberNode > &right)
两个数值节点相乘
const ExprPtr RelationOp op
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
void normalization_check_children(detail::RewriteBudget *budget, std::size_t roots, const std::shared_ptr< const Nodes > &... children)
const ExprPtr & right
static bool is_pi_variable(const VariableNode &variable)
BigInt get_node_degree_helper(const std::shared_ptr< const SymbolicNode > &node)
计算 AST 节点的多项式次数
const std::string const ExprPtr & value
const ExprPtr & rhs
bool normalization_factor_less(const std::shared_ptr< const SymbolicNode > &left, const std::shared_ptr< const SymbolicNode > &right)
std::shared_ptr< const SymbolicNode > make_normalized_multiply_node(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, detail::RewriteBudget *budget=nullptr)
Rational exact_number_as_rational(const NumberNode &node)
bool get_pi_coeff(const std::shared_ptr< const SymbolicNode > &node, Rational &coefficient)
ExprResult rational(const Rational &value)
void normalization_append(detail::RewriteBudget *budget, std::size_t &nodes, std::vector< std::shared_ptr< const SymbolicNode > > &children, std::shared_ptr< const SymbolicNode > child)
detail::SymbolicNodePtr substitute_free(const detail::SymbolicNodePtr &expression, const std::string &variable, const detail::SymbolicNodePtr &replacement, detail::RewriteBudget *budget)
bool operator()(const std::shared_ptr< const SymbolicNode > &left, const std::shared_ptr< const SymbolicNode > &right) const