LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
calculus_continuity.cpp
浏览该文件的文档.
1#include <stdexcept>
3#include "limit_result.hpp"
10
11namespace LMCAS {
12using namespace calculus_utils_detail;
13
14namespace {
16 const PiecewiseNode& piecewise, const FactsQuery& facts,
17 const AssumptionContext& assumptions, ComputationContext& context) {
18 for (const auto& branch : piecewise.branches()) {
19 auto access = context.consume_steps(1, "continuity_at");
20 if (!access) { return Result<detail::SymbolicNodePtr>::failure(access.error()); }
21 auto defined = detail::query_definedness(branch.condition, facts, Domain::Real, context);
22 if (!defined) { return Result<detail::SymbolicNodePtr>::failure(defined.error()); }
23 const auto truth = defined.value() == Tribool::True
24 ? assumptions.evaluate_condition(detail::expression_from_node(branch.condition))
26 if (truth == Tribool::Unknown) {
28 "point-value branch is undecided", "continuity_at");
29 }
30 if (truth == Tribool::True) { return branch.expression; }
31 }
32 return piecewise.default_expr();
33}
34
37 const AssumptionContext empty_assumptions;
38 const auto& assumptions = context.assumptions() ? *context.assumptions() : empty_assumptions;
39 while (const auto piecewise = std::dynamic_pointer_cast<const PiecewiseNode>(detail::node(value))) {
40 auto selected = select_continuity_branch(*piecewise, facts, assumptions, context);
41 if (!selected) { return Result<ExprPtr>::failure(selected.error()); }
42 if (!selected.value()) { return ExprPtr{}; }
43 value = detail::make_expression_ptr(selected.value());
44 }
45 return value;
46}
47
49 const ExprPtr& limit, const ExprPtr& value,
50 const FactsQuery& facts, ComputationContext& context) {
52 if (!defined) { return ContinuityResult::failure(defined.error()); }
53 if (defined.value() == Tribool::False) {
55 }
56 if (defined.value() != Tribool::True) {
58 "point-value definedness is unknown", "continuity_at");
59 }
61 if (!same) { return ContinuityResult::failure(same.error()); }
62 if (same.value() == Tribool::True) {
64 }
65 if (same.value() == Tribool::False) {
67 }
69 "point value could not be compared with the limit", "continuity_at");
70}
71
73 const ExprPtr& f, const std::string& var, const ExprPtr& point,
74 const ExprPtr& limit, ComputationContext& context) try {
75 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
76 (context).limits().max_ast_nodes, "transform");
78 if (!value) {
80 "substitution produced no value", "continuity_at");
81 }
82 std::optional<detail::AssumptionFacts> assumed;
83 if (context.assumptions()) { assumed.emplace(*context.assumptions()); }
84 const auto& facts = assumed ? static_cast<const FactsQuery&>(*assumed) : detail::no_facts();
85 auto selected = continuity_point_value(value, facts, context);
86 if (!selected) { return ContinuityResult::failure(selected.error()); }
87 if (!selected.value()) { return ContinuityResult::success(ContinuityType::Removable); }
88 return classify_continuity_point_value(limit, selected.value(), facts, context);
89} catch (const CasError& error) {
90 return ContinuityResult::failure(error);
91} catch (const std::bad_alloc&) {
92 return ContinuityResult::failure(CasErrc::ResourceLimit, "allocation failed", "continuity_with_limit");
93} catch (const std::length_error& error) {
94 return ContinuityResult::failure(CasErrc::ResourceLimit, error.what(), "continuity_with_limit");
95} catch (const std::exception& error) {
96 return ContinuityResult::failure(CasErrc::InternalInvariant, error.what(), "continuity_with_limit");
97}
98
100 const ExprPtr& f, const std::string& var, const ExprPtr& point,
102 const auto* left_finite = std::get_if<FiniteLimit>(&left);
103 const auto* right_finite = std::get_if<FiniteLimit>(&right);
104 if (!left_finite || !right_finite) {
106 }
108 left_finite->value, right_finite->value, context, Domain::Real);
109 if (!sides) { return ContinuityResult::failure(sides.error()); }
110 if (sides.value() == Tribool::False) {
112 }
113 if (sides.value() != Tribool::True) {
115 "one-sided values could not be compared", "continuity_at");
116 }
117 return continuity_with_limit(f, var, point, left_finite->value, context);
118}
119}
120
122 const std::shared_ptr<SymbolicExpr>& f, const std::string& var,
123 const std::shared_ptr<SymbolicExpr>& point, ComputationContext& context) {
124 const std::string operation = "continuity_at";
125 try {
126 if (!f || !point || var.empty()) {
128 "continuity analysis requires an expression, point, and variable", operation);
129 }
130 auto input = calculus_utils_validate_expr(f, var, context, operation);
131 if (!input) { return ContinuityResult::failure(input.error()); }
133 if (!left) { return ContinuityResult::failure(left.error()); }
135 if (!right) { return ContinuityResult::failure(right.error()); }
136 return continuity_from_limits(f, var, point, left.value().value, right.value().value, context);
137 } catch (const std::bad_alloc&) {
138 return ContinuityResult::failure(CasErrc::ResourceLimit, "continuity analysis allocation failed", operation);
139 } catch (const std::exception& ex) {
140 return ContinuityResult::failure(CasErrc::InternalInvariant, ex.what(), operation);
141 }
142}
143
145 const std::shared_ptr<SymbolicExpr>& f, const std::string& var,
146 const std::shared_ptr<SymbolicExpr>& point) {
148 return continuity_at_checked(f, var, point, context);
149}
150}
AssumptionContext class with scoped push/pop management.
分段函数节点,表示条件分支表达式.
const std::shared_ptr< const SymbolicNode > & default_expr() const noexcept
const std::vector< Branch > & branches() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(ContinuityType value)
Result< detail::SymbolicNodePtr > select_continuity_branch(const PiecewiseNode &piecewise, const FactsQuery &facts, const AssumptionContext &assumptions, ComputationContext &context)
ContinuityResult classify_continuity_point_value(const ExprPtr &limit, const ExprPtr &value, const FactsQuery &facts, ComputationContext &context)
ContinuityResult continuity_with_limit(const ExprPtr &f, const std::string &var, const ExprPtr &point, const ExprPtr &limit, ComputationContext &context)
Result< ExprPtr > continuity_point_value(ExprPtr value, const FactsQuery &facts, ComputationContext &context)
ContinuityResult continuity_from_limits(const ExprPtr &f, const std::string &var, const ExprPtr &point, const LimitOutcome &left, const LimitOutcome &right, ComputationContext &context)
Result< void > calculus_utils_validate_expr(const std::shared_ptr< SymbolicExpr > &expr, const std::string &var, ComputationContext &context, const std::string &operation)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const FactsQuery & no_facts() noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
Result< Tribool > compare_pointwise_values(const ExprPtr &left, const ExprPtr &right, ComputationContext &context, Domain domain)
在给定假设的 Real 或 Complex 域内比较逐点值,并保留错误。 True/False 分别证明值处处有定义且相等/不等;定义性未证实也归为 Unknown, 仅有非恒等残差不足以判定 Fals...
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::string const LimitExprPtr & point
LimitResult limit_checked(const LimitExprPtr &expression, const std::string &variable, const LimitExprPtr &point, LimitDirection direction, ComputationContext &context, Domain domain)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
@ Real
Real numbers
ContinuityResult continuity_at_checked(const std::shared_ptr< SymbolicExpr > &f, const std::string &var, const std::shared_ptr< SymbolicExpr > &point, ComputationContext &context)
@ Jump
跳跃间断点:左极限 != 右极限,但两侧极限均存在
@ Continuous
连续:左极限 = 右极限 = 函数值
@ Essential
本性间断点:至少一侧极限不存在或为无穷
@ Removable
可去间断点:左极限 = 右极限 != 函数值(或函数无定义)
Result< ContinuityType > ContinuityResult
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
std::variant< FiniteLimit, PositiveInfinityLimit, NegativeInfinityLimit, LimitDoesNotExist > LimitOutcome
std::shared_ptr< SymbolicExpr > ExprPtr
const ExprPtr & right
const std::string const ExprPtr & value
内部 AST 定义。