LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
symbolic_factory.cpp
浏览该文件的文档.
3#include <optional>
4
5namespace LMCAS {
6
7std::shared_ptr<const SymbolicNode> SymbolicFactory::create_number(const ::LMCAS::BigInt& v) { return LMCAS::detail::make_node<NumberNode>(v); }
8std::shared_ptr<const SymbolicNode> SymbolicFactory::create_number(const ::LMCAS::Rational& v) { return LMCAS::detail::make_node<NumberNode>(v); }
9std::shared_ptr<const SymbolicNode> SymbolicFactory::create_number(lmmc_real_t v) { return LMCAS::detail::make_node<NumberNode>(v); }
10std::shared_ptr<const SymbolicNode> SymbolicFactory::create_variable(const std::string& name) { return LMCAS::detail::make_node<VariableNode>(name); }
11
12std::shared_ptr<const SymbolicNode> SymbolicFactory::create_add(
13 std::vector<std::shared_ptr<const SymbolicNode>> ops,
14 detail::RewriteBudget* budget) {
15 if (ops.empty()) {
17 return create_number(::LMCAS::BigInt(0));
18 }
19 std::size_t nodes = 0;
20 for (const auto& op : ops) {
21 if (!op) {
22 throw std::invalid_argument("create_add operand cannot be null");
23 }
24 if (budget) {
25 nodes = budget->append_size(nodes, budget->measure(op));
26 }
27 }
28 if (ops.size() == 1) {
29 return ops[0];
30 }
31
32 std::vector<std::shared_ptr<const SymbolicNode>> flat_ops;
33 nodes = 0;
34 flat_ops.reserve(ops.size());
35 for (const auto& op : ops) {
36 if (op->is_zero()) {
37 continue;
38 }
39 if (auto add = std::dynamic_pointer_cast<const AddNode>(op)) {
40 if (budget) {
41 for (const auto& child : add->operands()) {
42 nodes = budget->append_size(nodes, budget->measure(child));
43 }
44 }
45 flat_ops.insert(flat_ops.end(), add->operands().begin(), add->operands().end());
46 } else {
47 normalization_append(budget, nodes, flat_ops, op);
48 }
49 }
50
51 if (flat_ops.empty()) {
53 return create_number(::LMCAS::BigInt(0));
54 }
55 if (flat_ops.size() == 1) {
56 return flat_ops[0];
57 }
58 normalization_check_arithmetic<AddNode>(budget, flat_ops, nodes);
59 return LMCAS::detail::make_node<AddNode>(std::move(flat_ops));
60}
61
62namespace {
63
65 const std::vector<detail::SymbolicNodePtr>& operands, detail::RewriteBudget* budget) {
66 const auto zero = std::find_if(operands.begin(), operands.end(), [](const auto& operand) {
67 return operand->is_zero();
68 });
69 if (zero == operands.end()) { return nullptr; }
70 std::optional<ComputationContext> local_context;
71 if (!budget) { local_context.emplace(); }
72 auto& context = budget ? budget->context() : *local_context;
73 if (std::all_of(operands.begin(), operands.end(), [&](const auto& operand) {
74 return normalization_can_discard(operand, detail::no_facts(), Domain::Real, context);
75 })) {
76 return *zero;
77 }
78 return nullptr;
79}
80
81}
82
83std::shared_ptr<const SymbolicNode> SymbolicFactory::create_multiply(
84 std::vector<std::shared_ptr<const SymbolicNode>> ops,
85 detail::RewriteBudget* budget) {
86 if (ops.empty()) {
88 return create_number(::LMCAS::BigInt(1));
89 }
90
91 std::size_t nodes = 0;
92 for (const auto& op : ops) {
93 if (!op) {
94 throw std::invalid_argument("create_multiply operand cannot be null");
95 }
96 if (budget) {
97 nodes = budget->append_size(nodes, budget->measure(op));
98 }
99 }
100 if (auto zero = discardable_zero_factor(ops, budget)) {
101 return zero;
102 }
103
104 if (ops.size() == 1) {
105 return ops[0];
106 }
107
108 std::vector<std::shared_ptr<const SymbolicNode>> flat_ops;
109 nodes = 0;
110 flat_ops.reserve(ops.size());
111 for (const auto& op : ops) {
112 if (op->is_one()) {
113 continue;
114 }
115 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(op)) {
116 if (budget) {
117 for (const auto& child : mul->operands()) {
118 nodes = budget->append_size(nodes, budget->measure(child));
119 }
120 }
121 flat_ops.insert(flat_ops.end(), mul->operands().begin(), mul->operands().end());
122 } else {
123 normalization_append(budget, nodes, flat_ops, op);
124 }
125 }
126
127 if (flat_ops.empty()) {
129 return create_number(::LMCAS::BigInt(1));
130 }
131 if (flat_ops.size() == 1) {
132 return flat_ops[0];
133 }
134 normalization_check_arithmetic<MultiplyNode>(budget, flat_ops, nodes);
135 return LMCAS::detail::make_node<MultiplyNode>(std::move(flat_ops));
136}
137
138
139std::shared_ptr<const SymbolicNode> SymbolicFactory::create_power(std::shared_ptr<const SymbolicNode> base, std::shared_ptr<const SymbolicNode> exponent) {
140 if (!base || !exponent) {
141 throw std::invalid_argument("create_power operands cannot be null");
142 }
144 if (exponent->is_zero()) {
147 return create_number(::LMCAS::BigInt(1));
148 }
149 return LMCAS::detail::make_node<PowerNode>(std::move(base), std::move(exponent));
150 }
151 if (exponent->is_one()) {
152 return base;
153 }
154 if (base->is_zero()) {
157 return create_number(::LMCAS::BigInt(0));
158 }
159 return LMCAS::detail::make_node<PowerNode>(std::move(base), std::move(exponent));
160 }
162 return create_number(::LMCAS::BigInt(1));
163 }
164 return LMCAS::detail::make_node<PowerNode>(std::move(base), std::move(exponent));
165}
166
167std::shared_ptr<const SymbolicNode> SymbolicFactory::create_complex(std::shared_ptr<const SymbolicNode> real, std::shared_ptr<const SymbolicNode> imag) {
168 if (!real || !imag) {
169 throw std::invalid_argument("create_complex operands cannot be null");
170 }
171 if (imag->is_zero()) {
172 return real;
173 }
174 return LMCAS::detail::make_node<ComplexNode>(std::move(real), std::move(imag));
175}
176
177}
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_variable(const std::string &name)
static std::shared_ptr< const SymbolicNode > create_power(std::shared_ptr< const SymbolicNode > base, std::shared_ptr< const SymbolicNode > exponent)
创建幂运算节点,自动处理指数为 0/1 及底数为 0/1 的情况.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
ComputationContext & context() const noexcept
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
std::size_t append_size(std::size_t current, std::size_t child)
detail::SymbolicNodePtr discardable_zero_factor(const std::vector< detail::SymbolicNodePtr > &operands, detail::RewriteBudget *budget)
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
Result< Tribool > query_positive_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
__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)
bool normalization_can_discard(const std::shared_ptr< const SymbolicNode > &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
@ Complex
Complex numbers (default, least specific)
@ Real
Real numbers
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, 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)
const ExprPtr RelationOp op
const ExprPtr & exponent
void normalization_check_children(detail::RewriteBudget *budget, std::size_t roots, const std::shared_ptr< const Nodes > &... children)
ExprPtr imag
bool normalization_proved(const Result< Tribool > &result)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
void normalization_append(detail::RewriteBudget *budget, std::size_t &nodes, std::vector< std::shared_ptr< const SymbolicNode > > &children, std::shared_ptr< const SymbolicNode > child)
内部 AST 定义。