LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
inference_engine_relations.cpp
浏览该文件的文档.
1#define _USE_MATH_DEFINES
4#include <limits>
5
6namespace LMCAS {
7
8bool InferenceEngine::Impl::operand_sign(const std::shared_ptr<const SymbolicNode>& operand, Sign target, ComputationContext& context) const {
9 auto step = context.consume_steps(0, "inference.relations");
10 if (!step) throw step.error();
11 if (auto var = std::dynamic_pointer_cast<const VariableNode>(operand)) {
12 return var->is_constant()
14 : ctx.has_sign(var->name(), target);
15 }
16 if (auto num = std::dynamic_pointer_cast<const NumberNode>(operand)) {
17 if (target == Sign::Positive) {
18 return num->is_positive();
19 }
20 return num->is_zero() || num->is_positive();
21 }
22 return false;
23}
24
26 const std::shared_ptr<const SymbolicNode>& operand, const SymbolicExpr& zero_expr,
27 bool& all_gt_zero, bool& all_geq_zero, ComputationContext& context) const {
28 auto step = context.consume_steps(1, "inference.relations");
29 if (!step) {
30 throw step.error();
31 }
32 auto op_expr = detail::expression_from_node(operand);
33 auto gt = ctx.has_relation_checked(
34 op_expr, zero_expr, RelationalNode::Op::GT, context);
35 if (!gt) {
37 }
38 auto geq = ctx.has_relation_checked(
39 op_expr, zero_expr, RelationalNode::Op::GEQ, context);
40 if (!geq) {
41 return Result<void>::failure(geq.error());
42 }
43 bool op_gt = gt.value();
44 bool op_geq = geq.value();
45 if (!op_gt) {
46 op_gt = operand_sign(operand, Sign::Positive, context);
47 }
48 if (!op_geq && !op_gt) {
49 op_geq = operand_sign(operand, Sign::NonNegative, context);
50 }
51 if (!op_gt) {
52 all_gt_zero = false;
53 }
54 if (!op_gt && !op_geq) {
55 all_geq_zero = false;
56 }
57 return Result<void>::success();
58}
59
61 const AddNode& add,
62 const SymbolicExpr& zero_expr,
64 if (add.operands().empty()) {
66 }
67
68 bool all_gt_zero = true;
69 bool all_geq_zero = true;
70
71 for (const auto& operand : add.operands()) {
72 auto result = accumulate_sum_relation_sign(
73 operand, zero_expr, all_gt_zero, all_geq_zero, context);
74 if (!result) {
75 return InferenceTriboolResult::failure(result.error());
76 }
77 }
78
79 if (target == Sign::Positive && all_gt_zero) {
81 }
82 if (target == Sign::NonNegative && all_geq_zero) {
84 }
86}
87
89 const MultiplyNode& mul,
90 const SymbolicExpr& zero_expr,
92 const auto& rel_store = ctx;
93 if (mul.operands().empty()) {
95 }
96
97 if (target == Sign::Positive) {
98 bool all_gt_zero = true;
99
100 for (const auto& operand : mul.operands()) {
101 auto step = context.consume_steps(1, "inference.relations");
102 if (!step) throw step.error();
103 auto op_expr = LMCAS::detail::expression_from_node(operand);
104 auto gt = rel_store.has_relation_checked(
105 op_expr, zero_expr, RelationalNode::Op::GT, context);
107 bool op_gt = gt.value();
108
109 if (!op_gt) {
110 op_gt = operand_sign(operand, Sign::Positive, context);
111 }
112
113 if (!op_gt) {
114 all_gt_zero = false;
115 break;
116 }
117 }
118
119 if (all_gt_zero) {
121 }
122 }
124}
125
127 auto step = context.consume_steps(1, "inference.relations");
128 if (!step) return Result<bool>::failure(step.error());
129 const auto& rel_store = ctx;
130 if (auto rhs_num = std::dynamic_pointer_cast<const NumberNode>(LMCAS::detail::node(rel.rhs))) {
131 if (rhs_num->is_zero() || rhs_num->is_positive()) {
132 return true;
133 }
134 }
135
136 if (auto rhs_var = std::dynamic_pointer_cast<const VariableNode>(LMCAS::detail::node(rel.rhs))) {
137 if (rhs_var->is_constant() ||
138 ctx.has_sign(rhs_var->name(), Sign::NonNegative)) {
139 return true;
140 }
141 }
142
143 auto geq = rel_store.has_relation_checked(
144 rel.rhs, zero_expr, RelationalNode::Op::GEQ, context);
145 if (!geq || geq.value()) return geq;
146 return rel_store.has_relation_checked(
147 rel.rhs, zero_expr, RelationalNode::Op::GT, context);
148}
149
151 const SymbolicExpr& expr,
152 const SymbolicExpr& zero_expr, ComputationContext& context) const {
153 auto relations = ctx.get_visible_relations_checked(context);
154 if (!relations) return InferenceTriboolResult::failure(relations.error());
155 detail::RewriteBudget budget(context, context.limits().max_recursion_depth,
156 std::numeric_limits<std::size_t>::max(), "inference.relations");
157 budget.measure(detail::node(expr));
158 for (const auto& rel : relations.value()) {
159 auto step = context.consume_steps(1, "inference.relations");
160 if (!step) throw step.error();
161 if (rel.op != RelationalNode::Op::GT) {
162 continue;
163 }
164
165 if (!LMCAS::detail::node(rel.lhs) || !LMCAS::detail::node(expr)) {
166 continue;
167 }
168 budget.measure(detail::node(rel.lhs));
169 if (!LMCAS::detail::node(rel.lhs)->equals(*LMCAS::detail::node(expr))) {
170 continue;
171 }
172 if (!LMCAS::detail::node(rel.rhs)) {
173 continue;
174 }
175
176 auto nonnegative = relation_rhs_nonnegative(rel, zero_expr, context);
177 if (!nonnegative) return InferenceTriboolResult::failure(nonnegative.error());
178 if (nonnegative.value()) {
180 }
181 }
183}
184
185InferenceTriboolResult InferenceEngine::infer_sign_from_relations_checked(
186 const SymbolicExpr& expr, Sign target, ComputationContext& context) const {
187 if (!LMCAS::detail::node(expr)) {
190 "relation sign inference expression must not be null",
191 "infer_sign_from_relations_checked");
192 }
193
194 try {
197
198 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
199 if (add->operands().empty()) {
201 }
202 auto result = impl_->sum_relation_sign(*add, zero_expr, target, context);
203 if (!result || result.value() != Tribool::Unknown) {
204 return result;
205 }
206 }
207
208 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
209 if (mul->operands().empty()) {
211 }
212 auto result = impl_->product_relation_sign(*mul, zero_expr, target, context);
213 if (!result || result.value() != Tribool::Unknown) {
214 return result;
215 }
216 }
217
218 if (target == Sign::Positive) {
219 return impl_->positive_relation_chain(expr, zero_expr, context);
220 }
221
223 } catch (const CasError& error) {
225 } catch (const std::bad_alloc&) {
228 "relation sign inference allocation failed",
229 "infer_sign_from_relations_checked");
230 } catch (const std::exception& ex) {
233 ex.what(),
234 "infer_sign_from_relations_checked");
235 }
236}
237
238}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
CasError & error()
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
std::shared_ptr< const Node > make_node(Args &&... args)
std::shared_ptr< SymbolicExpr > num(int value)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
@ Unknown
Property cannot be determined
@ True
Property definitely holds
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const ExprPtr & target
ExprResult gt(const ExprPtr &lhs, const ExprPtr &rhs)
Result< Tribool > InferenceTriboolResult
SymbolicExpr rhs
Right-hand side expression
Sign
Sign classification for symbols and expressions.
A stored relational constraint between two symbolic expressions.
InferenceTriboolResult positive_relation_chain(const SymbolicExpr &expr, const SymbolicExpr &zero_expr, ComputationContext &context) const
InferenceTriboolResult sum_relation_sign(const AddNode &add, const SymbolicExpr &zero_expr, Sign target, ComputationContext &context) const
bool operand_sign(const std::shared_ptr< const SymbolicNode > &operand, Sign target, ComputationContext &context) const
Result< bool > relation_rhs_nonnegative(const Relation &rel, const SymbolicExpr &zero_expr, ComputationContext &context) const
Result< void > accumulate_sum_relation_sign(const std::shared_ptr< const SymbolicNode > &operand, const SymbolicExpr &zero_expr, bool &all_gt_zero, bool &all_geq_zero, ComputationContext &context) const
InferenceTriboolResult product_relation_sign(const MultiplyNode &mul, const SymbolicExpr &zero_expr, Sign target, ComputationContext &context) const