LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
symbolic_core.cpp
浏览该文件的文档.
2#include <string>
3#include <limits>
4#include "symbolic.hpp"
12#include "matcher.hpp"
14#include "root_of_identity.hpp"
15
16namespace LMCAS {
17
18
19bool SymbolicExpr::is_number() const {
20 return impl_->root->is_number();
21}
22
23bool SymbolicExpr::get_number_value_is_zero() const {
24 return impl_->root->is_zero();
25}
26
27bool SymbolicExpr::is_big_int() const {
28 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
29 return number_node &&
30 std::holds_alternative<BigInt>(number_node->value());
31}
32
33bool SymbolicExpr::is_rational() const {
34 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
35 return number_node &&
36 std::holds_alternative<Rational>(number_node->value());
37}
38
39bool SymbolicExpr::is_int() const {
40 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
41 if (!number_node) return false;
42 if (std::holds_alternative<BigInt>(number_node->value())) return true;
43 return std::get<Rational>(number_node->value()).is_integer();
44}
45
46std::variant<int, BigInt, Rational> SymbolicExpr::get_number() const {
47 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
48 if (!number_node) {
49 throw std::runtime_error("Expression is not a number");
50 }
51 if (std::holds_alternative<BigInt>(number_node->value())) {
52 return std::get<BigInt>(number_node->value());
53 }
54 return std::get<Rational>(number_node->value());
55}
56
57int SymbolicExpr::get_int() const {
58 if (!is_int()) {
59 throw std::runtime_error("Expression is not an integer");
60 }
61 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
62 if (std::holds_alternative<BigInt>(number_node->value())) {
63 auto value = std::get<BigInt>(number_node->value()).try_to_int64();
64 if (!value || *value < std::numeric_limits<int>::min() ||
65 *value > std::numeric_limits<int>::max()) {
66 throw std::out_of_range("integer value does not fit in int");
67 }
68 return static_cast<int>(*value);
69 }
70 auto value = std::get<Rational>(number_node->value()).to_bigint().try_to_int64();
71 if (!value || *value < std::numeric_limits<int>::min() ||
72 *value > std::numeric_limits<int>::max()) {
73 throw std::out_of_range("integer value does not fit in int");
74 }
75 return static_cast<int>(*value);
76}
77
78BigInt SymbolicExpr::get_big_int() const {
79 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
80 if (!number_node ||
81 !std::holds_alternative<BigInt>(number_node->value())) {
82 throw std::runtime_error("Expression is not a BigInt");
83 }
84 return std::get<BigInt>(number_node->value());
85}
86
87Rational SymbolicExpr::get_rational() const {
88 auto number_node = std::dynamic_pointer_cast<const NumberNode>(impl_->root);
89 if (!number_node ||
90 !std::holds_alternative<Rational>(number_node->value())) {
91 throw std::runtime_error("Expression is not a Rational");
92 }
93 return std::get<Rational>(number_node->value());
94}
95
96Rational SymbolicExpr::convert_rational() const {
97 if (is_rational()) return get_rational();
98 if (is_big_int()) return Rational(get_big_int());
99 return Rational(0);
100}
101
102
103int SymbolicExpr::compare(const std::shared_ptr<SymbolicExpr>& other) const {
104 if (!impl_->root || !LMCAS::detail::node(other)) return 0;
105
106 return impl_->root->compare(*LMCAS::detail::node(other));
107}
108
109
110std::string SymbolicExpr::to_string() const {
111 PrintVisitor printer;
112 if (impl_->root) {
113 impl_->root->accept(printer);
114 return printer.get_result();
115 }
116 return "null";
117}
118
119lmmc_real_t SymbolicExpr::to_numeric() const {
120 auto evaluated = LMCAS::evaluate_numeric(*this);
121 if (!evaluated) {
122 throw std::runtime_error("numeric evaluation failed: " + evaluated.error().message);
123 }
124 return static_cast<lmmc_real_t>(evaluated.value().value);
125}
126
127bool SymbolicExpr::is_zero() const {
128 if (!impl_->root) return false;
129 if (auto num = std::dynamic_pointer_cast<const NumberNode>(impl_->root)) {
130 if (const auto* integer = std::get_if<BigInt>(&num->value())) {
131 return integer->is_zero();
132 }
133 if (const auto* rational = std::get_if<Rational>(&num->value())) {
134 return rational->is_zero();
135 }
136 }
137 return false;
138}
139
140bool SymbolicExpr::is_one() const {
141 if (!impl_->root) return false;
142 if (auto num = std::dynamic_pointer_cast<const NumberNode>(impl_->root)) {
143 if (const auto* integer = std::get_if<BigInt>(&num->value())) {
144 return *integer == BigInt(1);
145 }
146 if (const auto* rational = std::get_if<Rational>(&num->value())) {
147 return *rational == Rational(1);
148 }
149 }
150 return false;
151}
152
153
154std::shared_ptr<SymbolicExpr> SymbolicExpr::simplify_trig() const {
156 detail::RewriteBudget budget(context, context.limits().max_recursion_depth,
157 context.limits().max_ast_nodes, "simplify_trig");
158 auto res = detail::make_expression_ptr(detail::normalize_node(impl_->root, budget));
159 if (!LMCAS::detail::node(res)) return nullptr;
160
161 static const LMCAS::RewriteEngine engine = [] {
162 LMCAS::RewriteEngine configured;
163 using namespace LMCAS;
164 auto x_val = wildcard("x");
166
167 auto sinx = SymbolicExpr::sin(x);
168 auto cosx = SymbolicExpr::cos(x);
169 auto n2 = SymbolicExpr::number(2);
170 auto sin2 = SymbolicExpr::power(sinx, n2);
171 auto cos2 = SymbolicExpr::power(cosx, n2);
172
173 auto pat1 = SymbolicExpr::add(sin2, cos2);
174 configured.add_rule(Rule(*pat1, *SymbolicExpr::number(1), {"x"}));
175
176 auto pat2 = SymbolicExpr::add(cos2, sin2);
177 configured.add_rule(Rule(*pat2, *SymbolicExpr::number(1), {"x"}));
178
179 auto two_x = SymbolicExpr::multiply(n2, x);
180 auto sin2x = SymbolicExpr::sin(two_x);
181 auto two_sin_cos = SymbolicExpr::multiply(n2,
182 SymbolicExpr::multiply(sinx, cosx));
183 configured.add_rule(Rule(*sin2x, *two_sin_cos, {"x"}));
184
185 auto cos2x = SymbolicExpr::cos(two_x);
186 auto cos2_sub_sin2 = SymbolicExpr::add(cos2,
187 SymbolicExpr::multiply(sin2, SymbolicExpr::number(-1)));
188 configured.add_rule(Rule(*cos2x, *cos2_sub_sin2, {"x"}));
189 return configured;
190 }();
191
192 auto rewritten = engine.apply_checked(*res, context);
193 if (!rewritten) return res;
194 auto simplified = std::move(rewritten.value());
195 auto result_ptr = LMCAS::detail::make_expression_ptr(simplified);
197}
198
199namespace detail {
200
202 const FactsQuery& facts, Domain domain) {
203 budget.consume();
204 if (!node) {
205 throw CasError{CasErrc::InvalidArgument, "simplify argument cannot be null",
206 "LMCAS.simplify"};
207 }
210 node->accept(visitor);
211 auto result = visitor.get_result();
212 if (!result) {
213 throw CasError{CasErrc::InternalInvariant, "simplify returned null",
214 "LMCAS.simplify"};
215 }
216 budget.measure(result);
217 return result;
218}
219
221 const FactsQuery& facts, Domain domain) {
222 budget.consume();
223 if (!node) {
224 throw CasError{CasErrc::InvalidArgument, "expand argument cannot be null",
225 "LMCAS.expand"};
226 }
228 ExpandVisitor visitor(budget);
229 node->accept(visitor);
230 return normalize_node(visitor.get_result(), budget, facts, domain);
231}
232
234 const std::string& variable, RewriteBudget& budget,
235 const FactsQuery& facts, Domain domain) {
236 budget.consume();
237 if (!node || variable.empty()) {
238 throw CasError{CasErrc::InvalidArgument, "invalid differentiation argument",
239 "LMCAS.differentiate"};
240 }
243 node->accept(visitor);
244 return normalize_node(visitor.get_result(), budget, facts, domain);
245}
246
249 const FactsQuery& facts, Domain domain) {
250 budget.consume();
251 if (!node || !replacement || variable.empty()) {
252 throw CasError{CasErrc::InvalidArgument, "invalid substitution argument",
253 "LMCAS.substitute"};
254 }
258 budget.measure(result);
259 return normalize_node(result, budget, facts, domain);
260}
261
262}
263
264
265} // namespace LMCAS
std::shared_ptr< const SymbolicNode > get_result() const
获取求导结果。
std::shared_ptr< const SymbolicNode > get_result() const
统一规范化数值幂。 精确操作数保留整数和有理数运算;近似求根要求指数精确等于 1/2。 有限浮点幂直接折叠,省去倒数中间值;非有限结果保留幂表达式。
std::shared_ptr< const SymbolicNode > get_result() const
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
微分访问器,对 AST 执行符号求导。
展开访问器,将乘积和幂展开为多项式形式。
模式匹配引擎 Matcher 与重写规则系统 RewriteEngine。
多元 Hensel 提升(单变量步)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr expand_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const std::string & variable
const std::string const SymbolicNodePtr & replacement
RewriteBudget const FactsQuery Domain domain
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
RewriteBudget const FactsQuery & facts
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr< SymbolicExpr > num(int value)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult integer(Integer)=delete
SymbolicExpr wildcard(const std::string &name)
Domain
Mathematical domain hierarchy (least specific → most specific). Complex ⊃ Real ⊃ Algebraic ⊃ Rational...
@ Rational
Rational numbers
const std::string const ExprPtr & value
Result< ApproxReal > evaluate_numeric(const SymbolicExpr &expression, const NumericBindings &bindings={})
ExprResult rational(const Rational &value)
detail::SymbolicNodePtr substitute_free(const detail::SymbolicNodePtr &expression, const std::string &variable, const detail::SymbolicNodePtr &replacement, detail::RewriteBudget *budget)
符号规范化访问器接口。
打印访问器,将 AST 转换为可读字符串。
精确 RootOf 标识构造及受检数值求值。
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.
内部 AST 定义。