LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
inference_engine_core.cpp
浏览该文件的文档.
1#define _USE_MATH_DEFINES
3
4namespace LMCAS {
5
6InferenceEngine::InferenceEngine(const AssumptionContext& ctx)
7 : impl_(std::make_unique<Impl>(ctx)) {}
8
9InferenceEngine::~InferenceEngine() = default;
10InferenceEngine::InferenceEngine(InferenceEngine&&) noexcept = default;
11InferenceEngine& InferenceEngine::operator=(InferenceEngine&&) noexcept = default;
12
13void InferenceEngine::set_max_depth(int depth) {
14 if (depth > 0) {
15 impl_->max_depth = depth;
16 }
17}
18
19int InferenceEngine::get_max_depth() const {
20 return impl_->max_depth;
21}
22
24 const InferenceEngine& engine, const SymbolicNode& node)
25 : engine_(engine), node_(&node) {
26 engine_.impl_->current_depth++;
27
28 if (engine_.impl_->current_depth > engine_.impl_->max_depth) {
29 abort_ = true;
30 return;
31 }
32
33 // Insert and detect cycles atomically. If allocation throws, restore the
34 // depth counter because a throwing constructor has no matching destructor.
35 try {
36 inserted_ = engine_.impl_->visited.insert(node_).second;
37 } catch (...) {
38 engine_.impl_->current_depth--;
39 if (engine_.impl_->current_depth == 0) {
40 engine_.impl_->visited.clear();
41 }
42 throw;
43 }
44 if (!inserted_) {
45 abort_ = true;
46 }
47}
48
50 if (inserted_) {
51 engine_.impl_->visited.erase(node_);
52 }
53
54 engine_.impl_->current_depth--;
55
56 if (engine_.impl_->current_depth == 0) {
57 engine_.impl_->visited.clear();
58 }
59}
60
61
62InferenceTriboolResult InferenceEngine::query_sign_of_checked(const SymbolicExpr& expr, Sign sign, ComputationContext& context) const {
63 switch (sign) {
64 case Sign::Positive: return query_positive_checked(expr, context);
65 case Sign::Negative: return query_negative_checked(expr, context);
66 case Sign::NonNegative: return query_nonnegative_checked(expr, context);
67 case Sign::NonPositive: return query_nonpositive_checked(expr, context);
68 case Sign::Zero:
69 // Zero means both NonNegative and NonPositive
70 return impl_->query_zero(*this, expr, context);
71 case Sign::NonZero: return query_nonzero_checked(expr, context);
72 }
74}
76 const InferenceEngine& engine,
77 const SymbolicExpr& expr, ComputationContext& context) const {
78 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
79 auto result =
80 engine.infer_add_sign_checked(*add, Sign::Positive, context);
81 if (!result) {
82 return result;
83 }
84 if (result.value() != Tribool::Unknown) {
85 return result;
86 }
87 return engine.infer_sign_from_relations_checked(expr, Sign::Positive, context);
88 }
89 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
90 auto result =
91 engine.infer_multiply_sign_checked(*mul, Sign::Positive, context);
92 if (!result) {
93 return result;
94 }
95 if (result.value() != Tribool::Unknown) {
96 return result;
97 }
98 return engine.infer_sign_from_relations_checked(expr, Sign::Positive, context);
99 }
100 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
101 return engine.infer_power_property_checked(*pow, Sign::Positive, context);
102 }
103 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
104 return engine.infer_function_property_checked(*func, Sign::Positive, context);
105 }
106 return engine.infer_sign_from_relations_checked(expr, Sign::Positive, context);
107}
108
110 const InferenceEngine& engine,
111 const SymbolicExpr& expr, ComputationContext& context) const {
112 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
113 return engine.infer_add_sign_checked(*add, Sign::Negative, context);
114 }
115 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
116 return engine.infer_multiply_sign_checked(*mul, Sign::Negative, context);
117 }
118 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
119 return engine.infer_power_property_checked(*pow, Sign::Negative, context);
120 }
121 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
122 return engine.infer_function_property_checked(*func, Sign::Negative, context);
123 }
124 return Tribool::Unknown;
125}
126
128 const InferenceEngine& engine,
129 const SymbolicExpr& expr, ComputationContext& context) const {
130 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
131 auto result =
132 engine.infer_add_sign_checked(*add, Sign::NonNegative, context);
133 if (!result) {
134 return result;
135 }
136 if (result.value() != Tribool::Unknown) {
137 return result;
138 }
139 return engine.infer_sign_from_relations_checked(expr, Sign::NonNegative, context);
140 }
141 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
142 auto result =
143 engine.infer_multiply_sign_checked(*mul, Sign::NonNegative, context);
144 if (!result) {
145 return result;
146 }
147 if (result.value() != Tribool::Unknown) {
148 return result;
149 }
150 return engine.infer_sign_from_relations_checked(expr, Sign::NonNegative, context);
151 }
152 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
153 return engine.infer_power_property_checked(*pow, Sign::NonNegative, context);
154 }
155 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
156 return engine.infer_function_property_checked(*func, Sign::NonNegative, context);
157 }
158 return Tribool::Unknown;
159}
160
162 const InferenceEngine& engine,
163 const SymbolicExpr& expr, ComputationContext& context) const {
164 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
165 return engine.infer_add_sign_checked(*add, Sign::NonPositive, context);
166 }
167 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
168 return engine.infer_multiply_sign_checked(*mul, Sign::NonPositive, context);
169 }
170 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
171 return engine.infer_power_property_checked(*pow, Sign::NonPositive, context);
172 }
173 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
174 return engine.infer_function_property_checked(*func, Sign::NonPositive, context);
175 }
176 return Tribool::Unknown;
177}
178
180 const InferenceEngine& engine,
181 const SymbolicExpr& expr, ComputationContext& context) const {
182 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
183 return engine.infer_add_domain_checked(*add, Domain::Real, context);
184 }
185 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
186 return engine.infer_multiply_domain_checked(*mul, Domain::Real, context);
187 }
188 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
189 return engine.infer_power_domain_checked(*pow, Domain::Real, context);
190 }
191 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
192 return engine.infer_function_domain_checked(*func, Domain::Real, context);
193 }
194 return Tribool::Unknown;
195}
196
198 const InferenceEngine& engine,
199 const SymbolicExpr& expr, ComputationContext& context) const {
200 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
201 return engine.infer_add_domain_checked(*add, Domain::Integer, context);
202 }
203 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
204 return engine.infer_multiply_domain_checked(*mul, Domain::Integer, context);
205 }
206 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
207 return engine.infer_power_domain_checked(*pow, Domain::Integer, context);
208 }
209 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
210 return engine.infer_function_domain_checked(*func, Domain::Integer, context);
211 }
212 return Tribool::Unknown;
213}
214
216 const InferenceEngine& engine,
217 const AddNode& add, ComputationContext& context) const {
218 auto positive =
219 engine.infer_add_sign_checked(add, Sign::Positive, context);
220 if (!positive) {
221 return positive;
222 }
223 if (positive.value() == Tribool::True) {
224 return Tribool::True;
225 }
226 auto negative =
227 engine.infer_add_sign_checked(add, Sign::Negative, context);
228 if (!negative) {
229 return negative;
230 }
231 if (negative.value() == Tribool::True) {
232 return Tribool::True;
233 }
234 return Tribool::Unknown;
235}
236
238 const InferenceEngine& engine,
239 const SymbolicExpr& expr, ComputationContext& context) const {
240 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(LMCAS::detail::node(expr))) {
241 return engine.infer_multiply_sign_checked(*mul, Sign::NonZero, context);
242 }
243 if (auto pow = std::dynamic_pointer_cast<const PowerNode>(LMCAS::detail::node(expr))) {
244 return engine.infer_power_property_checked(*pow, Sign::NonZero, context);
245 }
246 if (auto func = std::dynamic_pointer_cast<const FunctionNode>(LMCAS::detail::node(expr))) {
247 return engine.infer_function_property_checked(*func, Sign::NonZero, context);
248 }
249 if (auto add = std::dynamic_pointer_cast<const AddNode>(LMCAS::detail::node(expr))) {
250 return sum_nonzero(engine, *add, context);
251 }
252 return Tribool::Unknown;
253}
254
256 const InferenceEngine& engine,
257 const SymbolicExpr& expr, ComputationContext& context) const {
258 auto nn = engine.query_nonnegative_checked(expr, context);
259 if (!nn) {
260 return nn;
261 }
262 auto np = engine.query_nonpositive_checked(expr, context);
263 if (!np) {
264 return np;
265 }
266 if (nn.value() == Tribool::True && np.value() == Tribool::True) {
268 }
269 if (nn.value() == Tribool::False || np.value() == Tribool::False) {
271 }
272 auto nonzero = engine.query_nonzero_checked(expr, context);
273 if (!nonzero) return nonzero;
274 if (nonzero.value() == Tribool::True) return Tribool::False;
276}
277
278InferenceTriboolResult InferenceEngine::query_domain_of_checked(const SymbolicExpr& expr, Domain domain, ComputationContext& context) const {
279 switch (domain) {
280 case Domain::Integer: return query_integer_checked(expr, context);
281 case Domain::Real: return query_real_checked(expr, context);
282 case Domain::Rational: {
283 return impl_->query_rational(*this, expr, context);
284 }
285 case Domain::Natural: {
286 return impl_->query_natural(expr, context);
287 }
288 default:
290 }
291}
292
293} // namespace LMCAS
加法节点,表示多个操作数的求和。
DepthGuard(const InferenceEngine &engine, const SymbolicNode &node)
static Result success(Tribool value)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
ExprResult pow(const ExprPtr &base, const ExprPtr &exponent, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
Domain
Mathematical domain hierarchy (least specific → most specific). Complex ⊃ Real ⊃ Algebraic ⊃ Rational...
@ Rational
Rational numbers
@ Natural
Non-negative integers (0, 1, 2, ...)
@ Real
Real numbers
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
@ Unknown
Property cannot be determined
@ True
Property definitely holds
@ False
Property definitely does not hold
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
std::size_t std::size_t depth
const NumberDomainSet & domain
Result< Tribool > InferenceTriboolResult
Sign
Sign classification for symbols and expressions.
InferenceTriboolResult sum_nonzero(const InferenceEngine &engine, const AddNode &add, ComputationContext &context) const
InferenceTriboolResult composite_nonpositive(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_real(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_integer(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult query_zero(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_negative(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_positive(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_nonzero(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const
InferenceTriboolResult composite_nonnegative(const InferenceEngine &engine, const SymbolicExpr &expr, ComputationContext &context) const