LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
limit_visitor_evaluation.cpp
浏览该文件的文档.
3
4namespace LMCAS {
5
6std::shared_ptr<const SymbolicNode> LimitVisitor::singular_ratio_limit(
7 const std::shared_ptr<const SymbolicNode>& num,
8 const std::shared_ptr<const SymbolicNode>& den) {
9 auto ns = determine_sign_near_point(num, direction);
10 auto ds = determine_sign_near_point(den, direction);
11 if (ns && ds && *ns != 0 && *ds != 0) { return signed_infinity(*ns * *ds); }
12 return nullptr;
13}
14
15
16
17bool LimitVisitor::tends_to_zero(const std::shared_ptr<const SymbolicNode>& node) const {
18 EvaluationScope scope;
19 if (!scope) {
20 return false;
21 }
22 LimitVisitor sub_vis(var, point, direction, assumption_ctx_, context_);
23 auto node_copy = node->clone();
24 node_copy->accept(sub_vis);
25 auto val = sub_vis.get_result();
26 if (!val) {
27 return false;
28 }
29 NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real); val->accept(norm); val = norm.get_result();
30 return val && val->is_zero();
31}
32
33std::shared_ptr<const SymbolicNode> LimitVisitor::eval_limit(const std::shared_ptr<const SymbolicNode>& expr) {
34 EvaluationScope scope;
35 if (!scope) {
36 return nullptr;
37 }
38 LimitVisitor sub(var, point, direction, assumption_ctx_, context_);
39 sub.lhopital_depth_ = this->lhopital_depth_;
40 expr->accept(sub);
41 auto r = sub.get_result();
42 if (r) { NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real); r->accept(norm); return norm.get_result(); }
43 return r;
44}
45
46std::shared_ptr<const SymbolicNode> LimitVisitor::derivative_limit(
47 const std::shared_ptr<const SymbolicNode>& node, bool normalize) {
48 LimitVisitor visitor(var, point, direction, assumption_ctx_, context_);
49 visitor.lhopital_depth_ = lhopital_depth_ + 1;
50 node->accept(visitor);
51 auto value = visitor.get_result();
52 if (!value || !normalize) {
53 return value;
54 }
55 NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real);
56 value->accept(norm);
57 return norm.get_result();
58}
59
60std::shared_ptr<const SymbolicNode> LimitVisitor::derivative_ratio_limit(
61 const std::shared_ptr<const SymbolicNode>& num,
62 const std::shared_ptr<const SymbolicNode>& den,
63 const std::shared_ptr<const SymbolicNode>& num_value,
64 const std::shared_ptr<const SymbolicNode>& den_value) {
65 bool numerator_zero = num_value->is_zero();
66 bool denominator_zero = den_value->is_zero();
67 bool numerator_infinity = is_inf(num_value);
68 bool denominator_infinity = is_inf(den_value);
69 bool indeterminate = numerator_zero && denominator_zero;
70 if (!indeterminate) {
71 indeterminate = numerator_infinity && denominator_infinity;
72 }
73 if (!indeterminate) {
74 if (denominator_zero && !numerator_zero) {
75 return singular_ratio_limit(num, den);
76 }
77 if (!denominator_zero && !denominator_infinity) {
79 std::vector<std::shared_ptr<const SymbolicNode>>{
81 den_value, LMCAS::detail::make_node<NumberNode>(BigInt(-1)))});
82 NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real);
83 ratio->accept(norm);
84 return norm.get_result();
85 }
86 if (!numerator_infinity && !numerator_zero && denominator_infinity) {
88 }
89 }
91 std::vector<std::shared_ptr<const SymbolicNode>>{
93 den, LMCAS::detail::make_node<NumberNode>(BigInt(-1)))});
94 return derivative_limit(ratio, false);
95}
96
97std::shared_ptr<const SymbolicNode> LimitVisitor::apply_lhopital(
98 const std::shared_ptr<const SymbolicNode>& num,
99 const std::shared_ptr<const SymbolicNode>& den) {
100 EvaluationScope scope;
101 if (!scope) {
102 return nullptr;
103 }
104 /**
105 * @brief 用解析函数芽的首项判断可去相消,减少嵌套商的递归求导。
106 * 同样适用于由异号无穷项合成的分式。
107 */
108 if (!is_inf(point)) {
109 auto leading = taylor_fallback(num, den);
110 if (leading) return leading;
111 }
112 if (lhopital_depth_ >= max_lhopital_depth) {
113 return taylor_fallback(num, den);
114 }
115 DifferentiationVisitor differentiation(var, *rewrite_budget());
116 num->accept(differentiation);
117 auto numerator = differentiation.get_result();
118 den->accept(differentiation);
119 auto denominator = differentiation.get_result();
120 if (!numerator || !denominator) {
121 return taylor_fallback(num, den);
122 }
123 NormalizationVisitor norm(*rewrite_budget(), detail::no_facts(), Domain::Real);
124 numerator->accept(norm);
125 numerator = norm.get_result();
126 denominator->accept(norm);
127 denominator = norm.get_result();
128 if (denominator->is_zero()) {
129 return taylor_fallback(num, den);
130 }
132 std::vector<std::shared_ptr<const SymbolicNode>>{
135 auto simplified = simplify_and_eval_ratio(ratio);
136 if (simplified) {
137 return simplified;
138 }
139 auto numerator_value = derivative_limit(numerator, true);
140 auto denominator_value = derivative_limit(denominator, true);
141 if (!numerator_value || !denominator_value) {
142 return taylor_fallback(num, den);
143 }
144 return derivative_ratio_limit(numerator, denominator, numerator_value, denominator_value);
145}
146
147}
统一规范化数值幂。 精确操作数保留整数和有理数运算;近似求根要求指数精确等于 1/2。 有限浮点幂直接折叠,省去倒数中间值;非有限结果保留幂表达式。
virtual void accept(LMCAS::detail::SymbolicVisitor &visitor) const =0
virtual std::shared_ptr< const SymbolicNode > clone() const =0
极限访问器,通过代入和 L'Hôpital 法则计算极限。
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const FactsQuery & no_facts() noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
std::shared_ptr< SymbolicExpr > num(int value)
const std::string const LimitExprPtr & point
__attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std std::shared_ptr< SymbolicExpr > r
ExprResult sub(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
@ Real
Real numbers
const std::string const LimitExprPtr LimitDirection direction
const std::string const ExprPtr & value
const ExprPtr & denominator