LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
residual_comparison.cpp
浏览该文件的文档.
1#include <stdexcept>
4
10
11#include <exception>
12#include <new>
13#include <optional>
14
15namespace LMCAS {
16
18 const ExprPtr& left,
19 const ExprPtr& right,
22 if (!left || !right || !detail::node(left) || !detail::node(right)) {
25 "equivalence check requires two expressions",
26 "residual.check_equivalent");
27 }
28 auto access = context.consume_steps(1, "residual.check_equivalent");
29 if (!access) return ResidualCheckResult::failure(access.error());
30 try {
31 detail::RewriteBudget budget(context, context.limits().max_recursion_depth,
32 context.limits().max_ast_nodes,
33 "residual.check_equivalent");
34 budget.measure(detail::node(left));
35 budget.measure(detail::node(right));
36 if (detail::node(left)->equals(*detail::node(right))) {
39 }
40 auto residual = SymbolicExpr::add(
41 left,
42 SymbolicExpr::multiply(SymbolicExpr::number(-1), right));
43 return check_zero_residual(residual, context, options);
44 } catch (const CasError& error) {
45 return ResidualCheckResult::failure(error);
46 } catch (const std::length_error& error) {
48 CasErrc::ResourceLimit, error.what(), "residual.check_equivalent");
49 } catch (const std::bad_alloc&) {
52 "equivalence residual allocation failed",
53 "residual.check_equivalent");
54 } catch (const std::exception& error) {
56 CasErrc::InternalInvariant, error.what(),
57 "residual.check_equivalent");
58 }
59}
60
61namespace {
62
64 const ExprPtr& left, const ExprPtr& right, const FactsQuery& facts,
66 auto left_defined = detail::query_definedness(
67 detail::node(left), facts, domain, context);
68 if (!left_defined) {
69 return Result<bool>::failure(left_defined.error());
70 }
71 auto right_defined = detail::query_definedness(
73 if (!right_defined) {
74 return Result<bool>::failure(right_defined.error());
75 }
76 return left_defined.value() == Tribool::True &&
77 right_defined.value() == Tribool::True;
78}
79
81 const ExprPtr& left, const ExprPtr& right, const FactsQuery& facts,
83 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
84 (context).limits().max_ast_nodes, "transform");
85 if (detail::node(left)->equals(*detail::node(right))) {
86 return Tribool::True;
87 }
88 auto residual = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::add(
89 left,
90 SymbolicExpr::multiply(SymbolicExpr::number(-1), right))), transform_budget));
91 if (!residual) {
94 "value comparison produced no residual",
95 "residual.compare_values");
96 }
97 auto nonzero = detail::query_nonzero_value(
98 detail::node(residual), facts, domain, context);
99 if (!nonzero) {
100 return Result<Tribool>::failure(nonzero.error());
101 }
102 if (nonzero.value() == Tribool::True) {
103 return Tribool::False;
104 }
105 if (nonzero.value() == Tribool::False) {
106 return Tribool::True;
107 }
108 auto identity = check_equivalent(left, right, context);
109 if (!identity) {
110 return Result<Tribool>::failure(identity.error());
111 }
112 return std::holds_alternative<ProvedZeroResidual>(identity.value())
114} catch (const CasError& error) {
115 return Result<Tribool>::failure(error);
116} catch (const std::bad_alloc&) {
117 return Result<Tribool>::failure(CasErrc::ResourceLimit, "allocation failed", "compare_defined_values");
118} catch (const std::length_error& error) {
119 return Result<Tribool>::failure(CasErrc::ResourceLimit, error.what(), "compare_defined_values");
120} catch (const std::exception& error) {
121 return Result<Tribool>::failure(CasErrc::InternalInvariant, error.what(), "compare_defined_values");
122}
123
124}
125
127 const ExprPtr& left, const ExprPtr& right,
129 constexpr const char* operation = "residual.compare_values";
130 auto access = context.consume_steps(1, operation);
131 if (!access) {
132 return Result<Tribool>::failure(access.error());
133 }
134 if (!left || !right || !detail::node(left) || !detail::node(right)) {
137 "value comparison requires two expressions", operation);
138 }
139 try {
140 std::optional<detail::AssumptionFacts> assumed;
141 if (context.assumptions()) {
142 assumed.emplace(*context.assumptions());
143 }
144 const auto& facts = assumed
145 ? static_cast<const FactsQuery&>(*assumed)
147 auto defined = pointwise_values_defined(
148 left, right, facts, domain, context);
149 if (!defined) {
150 return Result<Tribool>::failure(defined.error());
151 }
152 if (!defined.value()) {
153 return Tribool::Unknown;
154 }
155 return compare_defined_values(
156 left, right, facts, context, domain);
157 } catch (const CasError& error) {
158 return Result<Tribool>::failure(error);
159 } catch (const std::bad_alloc&) {
162 "value comparison allocation failed", operation);
163 } catch (const std::exception& error) {
166 }
167}
168
169}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(ResidualCheck value)
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
Result< bool > pointwise_values_defined(const ExprPtr &left, const ExprPtr &right, const FactsQuery &facts, Domain domain, ComputationContext &context)
Result< Tribool > compare_defined_values(const ExprPtr &left, const ExprPtr &right, const FactsQuery &facts, ComputationContext &context, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
RewriteBudget const FactsQuery Domain domain
const FactsQuery & no_facts() noexcept
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
RewriteBudget const FactsQuery & facts
Result< Tribool > compare_pointwise_values(const ExprPtr &left, const ExprPtr &right, ComputationContext &context, Domain domain)
在给定假设的 Real 或 Complex 域内比较逐点值,并保留错误。 True/False 分别证明值处处有定义且相等/不等;定义性未证实也归为 Unknown, 仅有非恒等残差不足以判定 Fals...
ComputationContext const std::string & operation
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ResidualCheckResult check_equivalent(const ExprPtr &left, const ExprPtr &right, ComputationContext &context, const LMCAS::EqvOptions &options)
Domain
Mathematical domain hierarchy (least specific → most specific). Complex ⊃ Real ⊃ Algebraic ⊃ Rational...
const std::string ComputationContext const SolveOptions & options
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
Result< ResidualCheck > ResidualCheckResult
const NumberDomainSet & domain
std::shared_ptr< SymbolicExpr > ExprPtr
const ExprPtr & right
ResidualCheckResult check_zero_residual(const ExprPtr &residual, ComputationContext &context, const LMCAS::EqvOptions &options)
在表达式的原公共定义域上认证值相等;点值定义域与分母条件需另行证明。
内部 AST 定义。