15 std::initializer_list<Sign> true_signs;
16 std::initializer_list<Sign> false_signs;
18 const SignRule rules[] = {
32 for (
const auto& rule : rules) {
33 if (rule.op !=
op)
continue;
34 for (
Sign sign : rule.true_signs) {
37 for (
Sign sign : rule.false_signs) {
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()) {
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()) {
65 const SymbolicExpr& condition,
66 const SymbolicExpr& conclusion) {
67 return assume_conditional_checked(condition, conclusion);
71 const SymbolicExpr& condition,
72 const SymbolicExpr& conclusion) {
73 constexpr const char*
operation =
"assume_conditional";
83 Tribool cond_result = evaluate_condition(condition);
88 "condition is satisfied but conclusion contradicts the current assumption state",
91 scope_stack_.back().conditionals.push_back({condition, conclusion});
93 }
catch (
const std::bad_alloc&) {
96 }
catch (
const std::invalid_argument& ex) {
98 }
catch (
const std::exception& ex) {
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);
114Tribool AssumptionContext::evaluate_condition(
const SymbolicExpr& condition)
const {
118 auto rel_node = std::dynamic_pointer_cast<const RelationalNode>(
LMCAS::detail::node(condition));
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) {
128 switch (rel_node->op()) {
AssumptionContext class with scoped push/pop management.
static Result failure(CasErrc code, std::string message, std::string operation={})
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
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.