LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
series_sequence_limits.cpp
浏览该文件的文档.
1#include <stdexcept>
3#include "limit_result.hpp"
4#include "series_engine.hpp"
5#include "symbolic.hpp"
8#include <memory>
9#include <string>
10
11namespace LMCAS {
12
14
16 const std::shared_ptr<const SymbolicNode>& node, const std::string& n) {
17 auto power = std::dynamic_pointer_cast<const PowerNode>(node);
18 if (!power) {
19 return false;
20 }
21 auto base = std::dynamic_pointer_cast<const NumberNode>(power->base());
22 auto exponent = std::dynamic_pointer_cast<const VariableNode>(power->exponent());
23 if (!base || !exponent || exponent->is_constant() || exponent->name() != n) {
24 return false;
25 }
26 return base->is_negative_one();
27}
28
29static std::shared_ptr<SymbolicExpr> product_without_factor(
30 const MultiplyNode& product, size_t omitted) {
31 std::vector<std::shared_ptr<const SymbolicNode>> rest;
32 for (size_t j = 0; j < product.operands().size(); ++j) {
33 if (j != omitted) {
34 rest.push_back(product.operands()[j]);
35 }
36 }
37 if (rest.empty()) {
38 return SymbolicExpr::number(1);
39 }
40 if (rest.size() == 1) {
41 return detail::make_expression_ptr(rest[0]);
42 }
44}
45
47 const std::shared_ptr<const SymbolicNode>& node,
48 const std::string& n, std::shared_ptr<SymbolicExpr>& remainder) {
49 if (is_alternating_factor(node, n)) {
50 remainder = SymbolicExpr::number(1);
51 return true;
52 }
53 auto product = std::dynamic_pointer_cast<const MultiplyNode>(node);
54 if (!product) {
55 return false;
56 }
57 for (size_t i = 0; i < product->operands().size(); ++i) {
58 if (is_alternating_factor(product->operands()[i], n)) {
59 remainder = product_without_factor(*product, i);
60 return true;
61 }
62 }
63 return false;
64}
65
66
67static std::shared_ptr<SymbolicExpr> series_abs(const std::shared_ptr<SymbolicExpr>& expr, ComputationContext& context) {
68
69 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
70 (context).limits().max_ast_nodes, "transform");
71 if (!expr) {
72 return nullptr;
73 }
75 std::vector<std::shared_ptr<const SymbolicNode>>{LMCAS::detail::node(expr)}), transform_budget));
76}
77
78static std::shared_ptr<SymbolicExpr> series_negate(const std::shared_ptr<SymbolicExpr>& expr, ComputationContext& context) {
79
80 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
81 (context).limits().max_ast_nodes, "transform");
82 if (!expr) {
83 return nullptr;
84 }
85 return detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(SymbolicExpr::number(-1), expr)), transform_budget));
86}
87
89 const std::shared_ptr<SymbolicExpr>& remainder, const std::string& n,
90 bool upper, ComputationContext& context) try {
91 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
92 (context).limits().max_ast_nodes, "transform");
93 auto limited = limit_expression_checked(
94 remainder, n, SymbolicExpr::infinity(), LimitDirection::Both, context);
95 if (!limited) {
96 return limited;
97 }
98 auto limit = std::move(limited.value());
99 auto simplified = limit ? detail::make_expression_ptr(detail::normalize_node(detail::node(limit), transform_budget)) : nullptr;
100 if (simplified && !series_is_infinity(simplified)) {
101 auto magnitude = series_abs(simplified, context);
102 return upper ? magnitude : series_negate(magnitude, context);
103 }
104 if (series_is_infinity(simplified)) {
105 return upper ? SymbolicExpr::infinity() : SymbolicExpr::infinity(-1);
106 }
107 auto magnitude = series_abs(limit, context);
108 return upper ? magnitude : series_negate(magnitude, context);
109} catch (const CasError& error) {
110 return ExpressionResult::failure(error);
111} catch (const std::bad_alloc&) {
112 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", "alternating_sequence_bound");
113} catch (const std::length_error& error) {
114 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), "alternating_sequence_bound");
115} catch (const std::exception& error) {
116 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), "alternating_sequence_bound");
117}
118
119
121 const std::shared_ptr<SymbolicExpr>& a_n, const std::string& n,
122 bool upper, ComputationContext& context) try {
123 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
124 (context).limits().max_ast_nodes, "transform");
125 std::shared_ptr<SymbolicExpr> remainder;
126 if (series_extract_alternating(detail::node(a_n), n, remainder)) {
127 return alternating_sequence_bound(remainder, n, upper, context);
128 }
129 auto limited = limit_expression_checked(
130 a_n, n, SymbolicExpr::infinity(),
132 if (!limited) {
133 return limited;
134 }
135 auto limit = std::move(limited.value());
136 auto simplified = limit ? detail::make_expression_ptr(detail::normalize_node(detail::node(limit), transform_budget)) : nullptr;
138 simplified ? std::move(simplified) : std::move(limit));
139} catch (const CasError& error) {
140 return ExpressionResult::failure(error);
141} catch (const std::bad_alloc&) {
142 return ExpressionResult::failure(CasErrc::ResourceLimit, "allocation failed", "sequence_extreme_limit");
143} catch (const std::length_error& error) {
144 return ExpressionResult::failure(CasErrc::ResourceLimit, error.what(), "sequence_extreme_limit");
145} catch (const std::exception& error) {
146 return ExpressionResult::failure(CasErrc::InternalInvariant, error.what(), "sequence_extreme_limit");
147}
148
150 const std::shared_ptr<SymbolicExpr>& a_n, const std::string& n,
152 constexpr const char* operation = "lim_sup";
153 if (!a_n || !detail::node(a_n) || n.empty()) {
156 "upper limit requires a sequence term and index variable",
157 operation);
158 }
159 auto budget = context.consume_steps(1, operation);
160 if (!budget) {
161 return ExpressionResult::failure(budget.error());
162 }
163 try {
164 return sequence_extreme_limit(a_n, n, true, context);
165 } catch (const std::bad_alloc&) {
168 "allocation failed while calculating upper limit", operation);
169 } catch (const std::exception& ex) {
171 CasErrc::InternalInvariant, ex.what(), operation);
172 }
173}
174
176 const std::shared_ptr<SymbolicExpr>& a_n, const std::string& n) {
178 return lim_sup_checked(a_n, n, context);
179}
180
182 const std::shared_ptr<SymbolicExpr>& a_n, const std::string& n,
184 constexpr const char* operation = "lim_inf";
185 if (!a_n || !detail::node(a_n) || n.empty()) {
188 "lower limit requires a sequence term and index variable",
189 operation);
190 }
191 auto budget = context.consume_steps(1, operation);
192 if (!budget) {
193 return ExpressionResult::failure(budget.error());
194 }
195 try {
196 return sequence_extreme_limit(a_n, n, false, context);
197 } catch (const std::bad_alloc&) {
200 "allocation failed while calculating lower limit", operation);
201 } catch (const std::exception& ex) {
203 CasErrc::InternalInvariant, ex.what(), operation);
204 }
205}
206
208 const std::shared_ptr<SymbolicExpr>& a_n, const std::string& n) {
210 return lim_inf_checked(a_n, n, context);
211}
212}
乘法节点,表示多个操作数的乘积。
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(std::shared_ptr< SymbolicExpr > value)
bool series_is_infinity(const std::shared_ptr< SymbolicExpr > &expression)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
static std::shared_ptr< SymbolicExpr > series_negate(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
static ExpressionResult alternating_sequence_bound(const std::shared_ptr< SymbolicExpr > &remainder, const std::string &n, bool upper, ComputationContext &context)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExpressionResult lim_inf_checked(const std::shared_ptr< SymbolicExpr > &a_n, const std::string &n, ComputationContext &context)
LimitExpressionResult limit_expression_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
bool series_is_infinity(const std::shared_ptr< SymbolicExpr > &expression)
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
static std::shared_ptr< SymbolicExpr > series_abs(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context)
static std::shared_ptr< SymbolicExpr > product_without_factor(const MultiplyNode &product, size_t omitted)
const ExprPtr & exponent
ExpressionResult lim_sup_checked(const std::shared_ptr< SymbolicExpr > &a_n, const std::string &n, ComputationContext &context)
static bool is_alternating_factor(const std::shared_ptr< const SymbolicNode > &node, const std::string &n)
static ExpressionResult sequence_extreme_limit(const std::shared_ptr< SymbolicExpr > &a_n, const std::string &n, bool upper, ComputationContext &context)
static bool series_extract_alternating(const std::shared_ptr< const SymbolicNode > &node, const std::string &n, std::shared_ptr< SymbolicExpr > &remainder)
级数引擎模块:收敛性判定,幂级数运算,傅里叶级数,洛朗级数,渐近展开,符号求和与乘积.
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.
内部 AST 定义。