21 const std::shared_ptr<const SymbolicNode>&
num,
22 const std::shared_ptr<const SymbolicNode>& den,
const std::string& var,
26 (
context).limits().max_ast_nodes,
"transform");
28 std::string t_var =
"__lim_t__";
31 names.insert(denominator_names.begin(), denominator_names.end());
32 while (names.count(t_var)) { t_var +=
"_"; }
33 auto t_expr = SymbolicExpr::variable(t_var);
34 auto one_over_t = SymbolicExpr::power(t_expr, SymbolicExpr::number(-1));
46std::shared_ptr<const SymbolicNode> LimitVisitor::divergent_leading_ratio(
47 const std::shared_ptr<SymbolicExpr>& ratio,
int difference) {
49 if (!sign || !*sign) {
return nullptr; }
50 if (difference % 2 &&
direction.empty() && !is_inf(
point)) {
return nullptr; }
52 return signed_infinity(*sign);
67std::shared_ptr<const SymbolicNode> LimitVisitor::simplify_and_eval_ratio(
68 const std::shared_ptr<const SymbolicNode>& ratio_node) {
106std::shared_ptr<const SymbolicNode> LimitVisitor::taylor_fallback(
107 const std::shared_ptr<const SymbolicNode>&
num,
108 const std::shared_ptr<const SymbolicNode>& den,
114 if (!is_inf(
point) && (!analytic_at_point(
num) || !analytic_at_point(den))) {
return nullptr; }
120 bool at_infinity = is_inf(
point);
122 std::string expand_var = var;
123 std::shared_ptr<SymbolicExpr> expand_point;
127 expand_point = SymbolicExpr::number(0);
129 expand_point = point_expr;
132 if (!num_expr || !den_expr || !expand_point) {
136 LimitVisitor analytic(expand_var,
detail::node(expand_point),
"+", assumption_ctx_, context_);
137 if (!analytic.analytic_at_point(
detail::node(num_expr)) ||
138 !analytic.analytic_at_point(
detail::node(den_expr))) {
return nullptr; }
143 auto value = taylor_series_limit(num_expr, den_expr, expand_var, expand_point,
order);
152std::shared_ptr<const SymbolicNode> LimitVisitor::taylor_series_limit(
153 const std::shared_ptr<SymbolicExpr>& numerator,
155 const std::string& expand_var,
156 const std::shared_ptr<SymbolicExpr>& expand_point,
int order) {
157 auto numerator_series = numerator->series(expand_var, expand_point,
order);
158 auto denominator_series =
denominator->series(expand_var, expand_point,
order);
159 if (!numerator_series || !denominator_series) {
164 auto numerator_leading = find_leading_term(numerator_series, expand_var, expand_point,
order);
165 auto denominator_leading = find_leading_term(denominator_series, expand_var, expand_point,
order);
166 return leading_terms_limit(numerator_leading, denominator_leading);
169std::shared_ptr<const SymbolicNode> LimitVisitor::leading_terms_limit(
170 const std::pair<std::shared_ptr<const SymbolicNode>,
int>& numerator,
171 const std::pair<std::shared_ptr<const SymbolicNode>,
int>&
denominator) {
178 if (numerator.first->is_zero() || numerator.second >
denominator.second) {
181 auto ratio = SymbolicExpr::multiply(
184 SymbolicExpr::number(-1)));
187 return divergent_leading_ratio(ratio,
denominator.second - numerator.second);
204std::pair<std::shared_ptr<const SymbolicNode>,
int> LimitVisitor::find_leading_term(
205 const std::shared_ptr<SymbolicExpr>& series_expr,
206 const std::string& expand_var,
207 const std::shared_ptr<SymbolicExpr>& expand_point,
214 auto current = series_expr;
216 for (
int n = 0; n <= max_order; ++n) {
225 if (!sign)
return {
nullptr, 0};
236 return {
nullptr, max_order + 1};
245int LimitVisitor::get_sign(
const std::shared_ptr<const SymbolicNode>& node) {
249 if (
auto num = std::dynamic_pointer_cast<const NumberNode>(node)) {
250 if (std::holds_alternative<BigInt>(
num->value())) {
251 BigInt
v = std::get<BigInt>(
num->value());
260 if (std::holds_alternative<Rational>(
num->value())) {
272 if (
auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
274 for (
auto&
op :
mul->operands()) {
275 int s = get_sign(
op);
极限访问器,通过代入和 L'Hôpital 法则计算极限。
std::string substitute_infinity_series(const std::shared_ptr< const SymbolicNode > &num, const std::shared_ptr< const SymbolicNode > &den, const std::string &var, std::shared_ptr< SymbolicExpr > &num_expr, std::shared_ptr< SymbolicExpr > &den_expr, ComputationContext &context)
int sign(const Rational &value)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, 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
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::set< std::string > all_variable_names(const SymbolicNodePtr &expression, RewriteBudget *budget=nullptr)
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::string const LimitExprPtr & point
__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
const std::vector< FGLMPoly > const MonomialOrder & order
@ Rational
Rational numbers
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const std::string const LimitExprPtr LimitDirection direction
const ExprPtr RelationOp op
const std::string const ExprPtr & value
const ExprPtr & denominator
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.