11QueryInterface::QueryInterface(
const AssumptionContext& ctx)
12 : ctx_(ctx), observed_generation_(ctx.cache_generation()) {}
16void QueryInterface::invalidate_cache()
const {
18 observed_generation_ = ctx_.cache_generation();
23 const SymbolicExpr& expr,
25 const std::string& operation,
27 const std::string& variable)
const {
29 return QueryTriboolResult::failure(
30 CasErrc::InvalidArgument,
"query expression must not be null", operation);
35 uint64_t current_gen = ctx_.cache_generation();
36 if (current_gen != observed_generation_) {
38 observed_generation_ = current_gen;
42 auto it = cache_.find(key);
43 if (it != cache_.end()) {
44 for (
const auto& entry : it->second) {
46 return QueryTriboolResult::success(entry.result);
51 auto result = compute();
52 if (!result)
return result;
53 cache_[key].push_back(CacheEntry{expr, result.value()});
59 return query_positive_checked(expr);
62QueryTriboolResult QueryInterface::query_positive_checked(
const SymbolicExpr& expr)
const {
63 return query_detail::checked_expression_result(expr,
"query_positive_checked",
65 auto result = cached_query_checked(
66 expr, PropType::Positive,
"query_positive_checked", [&]() -> QueryTriboolResult {
67 if (is_unhandled_type(expr)) {
68 return Tribool::Unknown;
70 if (is_infinity_node(expr)) {
71 int sign = get_infinity_sign(expr);
72 if (sign > 0)
return Tribool::True;
73 if (sign < 0)
return Tribool::False;
74 return Tribool::Unknown;
76 InferenceEngine engine(ctx_);
77 return engine.query_positive_checked(expr);
84 return query_negative_checked(expr);
87QueryTriboolResult QueryInterface::query_negative_checked(
const SymbolicExpr& expr)
const {
88 return query_detail::checked_expression_result(expr,
"query_negative_checked",
90 auto result = cached_query_checked(
91 expr, PropType::Negative,
"query_negative_checked", [&]() -> QueryTriboolResult {
92 if (is_unhandled_type(expr)) {
93 return Tribool::Unknown;
95 if (is_infinity_node(expr)) {
96 int sign = get_infinity_sign(expr);
97 if (sign < 0)
return Tribool::True;
98 if (sign > 0)
return Tribool::False;
99 return Tribool::Unknown;
101 InferenceEngine engine(ctx_);
102 return engine.query_negative_checked(expr);
109 return query_nonnegative_checked(expr);
112QueryTriboolResult QueryInterface::query_nonnegative_checked(
const SymbolicExpr& expr)
const {
113 return query_detail::checked_expression_result(expr,
"query_nonnegative_checked",
115 auto result = cached_query_checked(
116 expr, PropType::NonNegative,
"query_nonnegative_checked", [&]() -> QueryTriboolResult {
117 if (is_unhandled_type(expr)) {
118 return Tribool::Unknown;
120 if (is_infinity_node(expr)) {
121 int sign = get_infinity_sign(expr);
122 if (sign > 0)
return Tribool::True;
123 if (sign < 0)
return Tribool::False;
124 return Tribool::Unknown;
126 InferenceEngine engine(ctx_);
127 return engine.query_nonnegative_checked(expr);
134 return query_real_checked(expr);
137QueryTriboolResult QueryInterface::query_real_checked(
const SymbolicExpr& expr)
const {
138 return query_detail::checked_expression_result(expr,
"query_real_checked",
140 auto result = cached_query_checked(
141 expr, PropType::Real,
"query_real_checked", [&]() -> QueryTriboolResult {
142 if (is_unhandled_type(expr)) {
143 return Tribool::Unknown;
145 if (is_infinity_node(expr)) {
146 return Tribool::Unknown;
148 InferenceEngine engine(ctx_);
149 return engine.query_real_checked(expr);
156 return query_integer_checked(expr);
159QueryTriboolResult QueryInterface::query_integer_checked(
const SymbolicExpr& expr)
const {
160 return query_detail::checked_expression_result(expr,
"query_integer_checked",
162 auto result = cached_query_checked(
163 expr, PropType::Integer,
"query_integer_checked", [&]() -> QueryTriboolResult {
164 if (is_unhandled_type(expr)) {
165 return Tribool::Unknown;
167 if (is_infinity_node(expr)) {
168 return Tribool::False;
170 InferenceEngine engine(ctx_);
171 return engine.query_integer_checked(expr);
178 return query_nonzero_checked(expr);
181QueryTriboolResult QueryInterface::query_nonzero_checked(
const SymbolicExpr& expr)
const {
182 return query_detail::checked_expression_result(expr,
"query_nonzero_checked",
184 auto result = cached_query_checked(
185 expr, PropType::NonZero,
"query_nonzero_checked", [&]() -> QueryTriboolResult {
186 if (is_unhandled_type(expr)) {
187 return Tribool::Unknown;
189 if (is_infinity_node(expr)) {
190 return Tribool::True;
192 InferenceEngine engine(ctx_);
193 return engine.query_nonzero_checked(expr);
202 return query_algebraic_checked(expr);
205QueryTriboolResult QueryInterface::query_algebraic_checked(
const SymbolicExpr& expr)
const {
206 return query_detail::checked_expression_result(expr,
"query_algebraic_checked",
208 auto result = cached_query_checked(
209 expr, PropType::Algebraic,
"query_algebraic_checked", [&]() -> QueryTriboolResult {
210 if (is_unhandled_type(expr)) {
211 return Tribool::Unknown;
213 if (is_infinity_node(expr)) {
214 return Tribool::False;
216 InferenceEngine engine(ctx_);
217 return engine.query_algebraic_checked(expr);
223QueryTriboolResult QueryInterface::query_transcendental(
const SymbolicExpr& expr)
const {
224 return query_transcendental_checked(expr);
227QueryTriboolResult QueryInterface::query_transcendental_checked(
const SymbolicExpr& expr)
const {
228 return query_detail::checked_expression_result(expr,
"query_transcendental_checked",
230 auto result = cached_query_checked(
231 expr, PropType::Transcendental,
"query_transcendental_checked", [&]() -> QueryTriboolResult {
232 if (is_unhandled_type(expr)) {
233 return Tribool::Unknown;
235 if (is_infinity_node(expr)) {
236 return Tribool::False;
238 InferenceEngine engine(ctx_);
239 return engine.query_transcendental_checked(expr);
246 return query_finite_checked(expr);
249QueryTriboolResult QueryInterface::query_finite_checked(
const SymbolicExpr& expr)
const {
250 return query_detail::checked_expression_result(expr,
"query_finite_checked",
252 auto result = cached_query_checked(
253 expr, PropType::Finite,
"query_finite_checked", [&]() -> QueryTriboolResult {
254 if (is_unhandled_type(expr)) {
255 return Tribool::Unknown;
257 if (is_infinity_node(expr)) {
258 return Tribool::False;
260 InferenceEngine engine(ctx_);
261 return engine.query_finite_checked(expr);
268 return query_divergent_checked(expr);
271QueryTriboolResult QueryInterface::query_divergent_checked(
const SymbolicExpr& expr)
const {
272 return query_detail::checked_expression_result(expr,
"query_divergent_checked",
274 auto result = cached_query_checked(
275 expr, PropType::Divergent,
"query_divergent_checked", [&]() -> QueryTriboolResult {
276 if (is_unhandled_type(expr)) {
277 return Tribool::Unknown;
279 if (is_infinity_node(expr)) {
280 return Tribool::True;
282 InferenceEngine engine(ctx_);
283 return engine.query_divergent_checked(expr);
290 const SymbolicExpr& expr,
const std::string& variable)
const {
291 return query_periodic_checked(expr, variable);
295 const SymbolicExpr& expr,
const std::string& variable)
const {
297 return QueryTriboolResult::failure(CasErrc::InvalidArgument,
298 "independent variable must not be empty",
"query_periodic_checked");
300 return query_detail::checked_expression_result(expr,
"query_periodic_checked", [&]() {
301 return cached_query_checked(expr, PropType::Periodic,
"query_periodic_checked",
302 [&]() -> QueryTriboolResult {
303 InferenceEngine engine(ctx_);
304 return engine.query_periodic_checked(expr, variable);
310 const SymbolicExpr& expr,
const std::string& variable)
const {
311 return get_period_checked(expr, variable);
315 const SymbolicExpr& expr,
const std::string& variable)
const {
316 InferenceEngine engine(ctx_);
317 return engine.infer_period_checked(expr, variable);
321 const SymbolicExpr& expr)
const {
322 return query_positive_definite_checked(expr);
325QueryTriboolResult QueryInterface::query_positive_definite_checked(
const SymbolicExpr& expr)
const {
326 return query_detail::checked_expression_result(expr,
"query_positive_definite_checked",
328 auto result = cached_query_checked(
330 PropType::PositiveDefinite,
331 "query_positive_definite_checked",
332 [&]() -> QueryTriboolResult {
333 if (
auto var = std::dynamic_pointer_cast<const VariableNode>(
335 if (var->is_constant())
return Tribool::Unknown;
336 const auto& props = ctx_;
338 if (d == Definiteness::PositiveDefinite)
return Tribool::True;
339 if (d == Definiteness::NegativeDefinite ||
340 d == Definiteness::NegativeSemiDefinite ||
341 d == Definiteness::Indefinite)
return Tribool::False;
342 return Tribool::Unknown;
344 return Tribool::Unknown;
351 const SymbolicExpr& expr)
const {
352 return query_positive_semidefinite_checked(expr);
355QueryTriboolResult QueryInterface::query_positive_semidefinite_checked(
const SymbolicExpr& expr)
const {
356 return query_detail::checked_expression_result(expr,
"query_positive_semidefinite_checked",
358 auto result = cached_query_checked(
360 PropType::PositiveSemiDefinite,
361 "query_positive_semidefinite_checked",
362 [&]() -> QueryTriboolResult {
363 if (
auto var = std::dynamic_pointer_cast<const VariableNode>(
365 if (var->is_constant())
return Tribool::Unknown;
366 const auto& props = ctx_;
368 if (d == Definiteness::PositiveDefinite ||
369 d == Definiteness::PositiveSemiDefinite)
return Tribool::True;
370 if (d == Definiteness::NegativeDefinite ||
371 d == Definiteness::NegativeSemiDefinite ||
372 d == Definiteness::Indefinite)
return Tribool::False;
373 return Tribool::Unknown;
375 return Tribool::Unknown;
AssumptionContext class with scoped push/pop management.
InferenceEngine class for deriving properties of composite expressions.
int sign(const Rational &value)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const std::string & variable
Result< Tribool > QueryTriboolResult
Definiteness
Matrix definiteness classification.
Result< std::optional< SymbolicExpr > > QueryPeriodResult
QueryInterface class - unified tri-state query API for property questions on arbitrary expressions.