LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
assumption_conditionals.cpp
浏览该文件的文档.
5
6namespace LMCAS {
7
8namespace {
9
10
11Tribool evaluate_symbol_sign(const AssumptionContext& ctx,
12 const std::string& name, RelationOp op) {
13 struct SignRule {
15 std::initializer_list<Sign> true_signs;
16 std::initializer_list<Sign> false_signs;
17 };
18 const SignRule rules[] = {
28 {Sign::Zero}},
31 };
32 for (const auto& rule : rules) {
33 if (rule.op != op) continue;
34 for (Sign sign : rule.true_signs) {
35 if (ctx.has_sign(name, sign)) return Tribool::True;
36 }
37 for (Sign sign : rule.false_signs) {
38 if (ctx.has_sign(name, sign)) return Tribool::False;
39 }
40 break;
41 }
42 return Tribool::Unknown;
43}
44
45Tribool evaluate_zero_comparison(const AssumptionContext& ctx,
46 const RelationalNode& relation) {
47 const auto lhs_var = std::dynamic_pointer_cast<const VariableNode>(relation.left());
48 const auto rhs_num = std::dynamic_pointer_cast<const NumberNode>(relation.right());
49 if (lhs_var && !lhs_var->is_constant() && rhs_num && rhs_num->is_zero()) {
50 return evaluate_symbol_sign(ctx, lhs_var->name(), relation.op());
51 }
52 const auto lhs_num = std::dynamic_pointer_cast<const NumberNode>(relation.left());
53 const auto rhs_var = std::dynamic_pointer_cast<const VariableNode>(relation.right());
54 if (lhs_num && lhs_num->is_zero() && rhs_var && !rhs_var->is_constant()) {
56 ctx, rhs_var->name(), detail::reversed_relation(relation.op()));
57 }
58 return Tribool::Unknown;
59}
60
61}
62
63
64AssumptionVoidResult AssumptionContext::assume_conditional(
65 const SymbolicExpr& condition,
66 const SymbolicExpr& conclusion) {
67 return assume_conditional_checked(condition, conclusion);
68}
69
70AssumptionVoidResult AssumptionContext::assume_conditional_checked(
71 const SymbolicExpr& condition,
72 const SymbolicExpr& conclusion) {
73 constexpr const char* operation = "assume_conditional";
74 if (!std::dynamic_pointer_cast<const RelationalNode>(LMCAS::detail::node(condition))) {
76 CasErrc::InvalidArgument, "condition expression must be relational", operation);
77 }
78 if (!std::dynamic_pointer_cast<const RelationalNode>(LMCAS::detail::node(conclusion))) {
80 CasErrc::InvalidArgument, "conclusion expression must be relational", operation);
81 }
82 try {
83 Tribool cond_result = evaluate_condition(condition);
84 if (cond_result == Tribool::True &&
85 evaluate_condition(conclusion) == Tribool::False) {
88 "condition is satisfied but conclusion contradicts the current assumption state",
89 operation);
90 }
91 scope_stack_.back().conditionals.push_back({condition, conclusion});
92 ++cache_generation_;
93 } catch (const std::bad_alloc&) {
95 CasErrc::ResourceLimit, "assumption allocation failed", operation);
96 } catch (const std::invalid_argument& ex) {
97 return AssumptionVoidResult::failure(CasErrc::InvalidArgument, ex.what(), operation);
98 } catch (const std::exception& ex) {
100 }
102}
103
104std::vector<AssumptionContext::ConditionalAssumption> AssumptionContext::get_active_conditionals() const {
105 std::vector<ConditionalAssumption> result;
106 for (auto it = scope_stack_.rbegin(); it != scope_stack_.rend(); ++it) {
107 for (const auto& cond : it->conditionals) {
108 result.push_back(cond);
109 }
110 }
111 return result;
112}
113
114Tribool AssumptionContext::evaluate_condition(const SymbolicExpr& condition) const {
115 if (!LMCAS::detail::node(condition)) {
116 return Tribool::Unknown;
117 }
118 auto rel_node = std::dynamic_pointer_cast<const RelationalNode>(LMCAS::detail::node(condition));
119 if (!rel_node) {
120 return Tribool::Unknown;
121 }
122 const auto* lhs_number = dynamic_cast<const NumberNode*>(rel_node->left().get());
123 const auto* rhs_number = dynamic_cast<const NumberNode*>(rel_node->right().get());
124 if (lhs_number && rhs_number) {
125 const auto lhs = exact_number_as_rational(*lhs_number);
126 const auto rhs = exact_number_as_rational(*rhs_number);
127 bool value = false;
128 switch (rel_node->op()) {
129 case RelationOp::GT: { value = lhs > rhs; break; }
130 case RelationOp::GEQ: { value = lhs >= rhs; break; }
131 case RelationOp::LT: { value = lhs < rhs; break; }
132 case RelationOp::LEQ: { value = lhs <= rhs; break; }
133 case RelationOp::EQ: { value = lhs == rhs; break; }
134 case RelationOp::NEQ: { value = lhs != rhs; break; }
135 }
137 }
138
139 auto lhs = LMCAS::detail::expression_from_node(rel_node->left());
140 auto rhs = LMCAS::detail::expression_from_node(rel_node->right());
141 RelationalNode::Op op = rel_node->op();
142 if (has_relation(lhs, rhs, op)) { return Tribool::True; }
143 return evaluate_zero_comparison(*this, *rel_node);
144}
145
146}
AssumptionContext class with scoped push/pop management.
LMCAS::RelationOp Op
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success()
Tribool evaluate_symbol_sign(const AssumptionContext &ctx, const std::string &name, RelationOp op)
Tribool evaluate_zero_comparison(const AssumptionContext &ctx, const RelationalNode &relation)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
ComputationContext const std::string & operation
constexpr RelationOp reversed_relation(RelationOp op) noexcept
Tribool
Tri-state logic value for property queries.
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
RelationOp
Stable relational operator used by public APIs.
const ExprPtr RelationOp op
Result< void > AssumptionVoidResult
ExprResult relation(const ExprPtr &lhs, const ExprPtr &rhs, RelationOp op)
const std::string const ExprPtr & value
const ExprPtr & rhs
Rational exact_number_as_rational(const NumberNode &node)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
Sign
Sign classification for symbols and expressions.
内部 AST 定义。