16 std::initializer_list<D> incoming;
18 const Conflict conflicts[] = {
19 {D::PositiveDefinite, {D::NegativeDefinite, D::NegativeSemiDefinite, D::Indefinite}},
20 {D::NegativeDefinite, {D::PositiveDefinite, D::PositiveSemiDefinite, D::Indefinite}},
21 {D::PositiveSemiDefinite, {D::NegativeDefinite, D::Indefinite}},
22 {D::NegativeSemiDefinite, {D::PositiveDefinite, D::Indefinite}},
23 {D::Indefinite, {D::PositiveDefinite, D::NegativeDefinite,
24 D::PositiveSemiDefinite, D::NegativeSemiDefinite}}
26 for (
const auto& conflict : conflicts) {
27 if (existing != conflict.existing) {
30 return std::find(conflict.incoming.begin(), conflict.incoming.end(), incoming)
31 != conflict.incoming.end();
39void PropertyStore::declare_transcendental_unchecked(
const std::string& symbol) {
40 auto& props = properties_[symbol];
42 if (props.transcendental) {
45 if (domain_specificity(props.most_specific_domain) > domain_specificity(
Domain::Real)) {
46 throw std::invalid_argument(
47 "Contradiction for symbol '" + symbol +
48 "': cannot declare Transcendental because existing domain is " +
50 " (Transcendental contradicts Algebraic or more specific domains)");
53 if (domain_specificity(props.most_specific_domain) < domain_specificity(
Domain::Real)) {
57 props.transcendental =
true;
61 const std::string& symbol) {
62 return declare_transcendental_checked(symbol);
66 const std::string& symbol) {
68 [&](PropertyStore& candidate) {
69 candidate.declare_transcendental_unchecked(symbol);
73bool PropertyStore::is_transcendental(
const std::string& symbol)
const {
74 auto it = properties_.find(symbol);
75 if (it == properties_.end()) {
78 return it->second.transcendental;
82void PropertyStore::declare_finiteness_unchecked(
const std::string& symbol,
Finiteness f) {
83 auto& props = properties_[symbol];
85 if (props.finiteness == f) {
93 throw std::invalid_argument(
94 "Contradiction for symbol '" + symbol +
95 "': cannot be both Finite and Divergent");
106 return declare_finiteness_checked(symbol, f);
110 const std::string& symbol,
113 [&](PropertyStore& candidate) {
114 candidate.declare_finiteness_unchecked(symbol, f);
118Finiteness PropertyStore::get_finiteness(
const std::string& symbol)
const {
119 auto it = properties_.find(symbol);
120 if (it == properties_.end()) {
123 return it->second.finiteness;
127void PropertyStore::declare_definiteness_unchecked(
const std::string& symbol,
Definiteness d) {
128 auto& props = properties_[symbol];
130 if (props.definiteness == d) {
134 props.definiteness = d;
140 throw std::invalid_argument(
141 "Contradiction for symbol '" + symbol +
142 "': definiteness conflict between existing and new declaration");
146 props.definiteness = d;
151 props.definiteness = d;
164 props.definiteness = d;
169 return declare_definiteness_checked(symbol, d);
173 const std::string& symbol,
176 [&](PropertyStore& candidate) {
177 candidate.declare_definiteness_unchecked(symbol, d);
181Definiteness PropertyStore::get_definiteness(
const std::string& symbol)
const {
182 auto it = properties_.find(symbol);
183 if (it == properties_.end()) {
186 return it->second.definiteness;
190void PropertyStore::declare_periodic_unchecked(
191 const std::string& symbol,
const std::string&
variable,
192 const SymbolicExpr& period) {
193 properties_[symbol].periods.insert_or_assign(
variable, period);
197 const std::string& symbol,
const std::string&
variable,
198 const SymbolicExpr& period) {
199 return declare_periodic_checked(symbol,
variable, period);
203 const std::string& symbol,
const std::string&
variable,
204 const SymbolicExpr& period) {
207 "symbol, independent variable, and period must be nonempty",
"declare_periodic");
218 "period must be a positive defined real value",
"declare_periodic");
221 [&](PropertyStore& candidate) {
222 candidate.declare_periodic_unchecked(symbol,
variable, period);
226const PropertyStore::PeriodDeclarations& PropertyStore::get_period_decls(
227 const std::string& symbol)
const {
228 static const PeriodDeclarations empty;
229 const auto it = properties_.find(symbol);
230 return it == properties_.end() ? empty : it->second.periods;
233std::optional<SymbolicExpr> PropertyStore::get_period(
234 const std::string& symbol,
const std::string&
variable)
const {
235 const auto& declarations = get_period_decls(symbol);
236 const auto it = declarations.find(
variable);
237 if (it == declarations.end())
return std::nullopt;
241bool PropertyStore::is_periodic(
const std::string& symbol,
const std::string&
variable)
const {
242 return get_period(symbol,
variable).has_value();
246std::vector<std::string> PropertyStore::get_all_symbols()
const {
247 std::vector<std::string> symbols;
248 symbols.reserve(properties_.size());
249 for (
const auto& [
name, _] : properties_) {
250 symbols.push_back(
name);
252 std::sort(symbols.begin(), symbols.end());
256std::vector<PropertyStore::ContinuityInfo> PropertyStore::get_continuity_decls(
257 const std::string& symbol)
const {
258 auto it = properties_.find(symbol);
259 if (it == properties_.end())
return {};
260 std::vector<ContinuityInfo> result;
261 for (
const auto& decl : it->second.continuity_decls) {
262 result.push_back({decl.interval, decl.is_differentiable});
267std::vector<PropertyStore::MonotonicityInfo> PropertyStore::get_monotonicity_decls(
268 const std::string& symbol)
const {
269 auto it = properties_.find(symbol);
270 if (it == properties_.end())
return {};
271 std::vector<MonotonicityInfo> result;
272 for (
const auto& decl : it->second.monotonicity_decls) {
273 result.push_back({decl.variable, decl.interval, decl.type});
static Result failure(CasErrc code, std::string message, std::string operation={})
bool definiteness_conflicts(Definiteness existing, Definiteness incoming)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
const FactsQuery & no_facts() noexcept
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
Result< Tribool > query_positive_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
PropertyStoreResult checked_property_update(PropertyStore &store, const std::string &symbol, const std::string &operation, F &&update)
std::string domain_str(Domain domain)
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
Result< void > PropertyStoreResult
@ Bounded
Symbol has finite bounds
@ False
Property definitely does not hold
Definiteness
Matrix definiteness classification.
@ NegativeSemiDefinite
All eigenvalues non-positive
@ NegativeDefinite
All eigenvalues negative
@ PositiveSemiDefinite
All eigenvalues non-negative
@ PositiveDefinite
All eigenvalues positive
@ Unknown
Definiteness not determined
Finiteness
Finiteness classification for limits and sequences.
@ Finite
Has a finite value or limit
@ Unknown
Finiteness not determined
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name