LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
property_classification.cpp
浏览该文件的文档.
4#include <algorithm>
5
6namespace LMCAS {
7
8using namespace property_detail;
9
10namespace {
11
13 using D = Definiteness;
14 struct Conflict {
15 D existing;
16 std::initializer_list<D> incoming;
17 };
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}}
25 };
26 for (const auto& conflict : conflicts) {
27 if (existing != conflict.existing) {
28 continue;
29 }
30 return std::find(conflict.incoming.begin(), conflict.incoming.end(), incoming)
31 != conflict.incoming.end();
32 }
33 return false;
34}
35
36}
37
38
39void PropertyStore::declare_transcendental_unchecked(const std::string& symbol) {
40 auto& props = properties_[symbol];
41
42 if (props.transcendental) {
43 return;
44 }
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 " +
49 domain_str(props.most_specific_domain) +
50 " (Transcendental contradicts Algebraic or more specific domains)");
51 }
52
53 if (domain_specificity(props.most_specific_domain) < domain_specificity(Domain::Real)) {
54 props.most_specific_domain = Domain::Real;
55 }
56
57 props.transcendental = true;
58}
59
60PropertyStoreResult PropertyStore::declare_transcendental(
61 const std::string& symbol) {
62 return declare_transcendental_checked(symbol);
63}
64
65PropertyStoreResult PropertyStore::declare_transcendental_checked(
66 const std::string& symbol) {
67 return checked_property_update(*this, symbol, "declare_transcendental",
68 [&](PropertyStore& candidate) {
69 candidate.declare_transcendental_unchecked(symbol);
70 });
71}
72
73bool PropertyStore::is_transcendental(const std::string& symbol) const {
74 auto it = properties_.find(symbol);
75 if (it == properties_.end()) {
76 return false;
77 }
78 return it->second.transcendental;
79}
80
81
82void PropertyStore::declare_finiteness_unchecked(const std::string& symbol, Finiteness f) {
83 auto& props = properties_[symbol];
84
85 if (props.finiteness == f) {
86 return;
87 }
88 if (f == Finiteness::Unknown) {
89 props.finiteness = f;
90 return;
91 }
92 if (props.finiteness != Finiteness::Unknown && props.finiteness != f) {
93 throw std::invalid_argument(
94 "Contradiction for symbol '" + symbol +
95 "': cannot be both Finite and Divergent");
96 }
97
98 props.finiteness = f;
99 if (f == Finiteness::Finite) {
100 declare_bounded_unchecked(symbol, Boundedness::Bounded, std::nullopt);
101 }
102}
103
104PropertyStoreResult PropertyStore::declare_finiteness(
105 const std::string& symbol, Finiteness f) {
106 return declare_finiteness_checked(symbol, f);
107}
108
109PropertyStoreResult PropertyStore::declare_finiteness_checked(
110 const std::string& symbol,
111 Finiteness f) {
112 return checked_property_update(*this, symbol, "declare_finiteness",
113 [&](PropertyStore& candidate) {
114 candidate.declare_finiteness_unchecked(symbol, f);
115 });
116}
117
118Finiteness PropertyStore::get_finiteness(const std::string& symbol) const {
119 auto it = properties_.find(symbol);
120 if (it == properties_.end()) {
121 return Finiteness::Unknown;
122 }
123 return it->second.finiteness;
124}
125
126
127void PropertyStore::declare_definiteness_unchecked(const std::string& symbol, Definiteness d) {
128 auto& props = properties_[symbol];
129
130 if (props.definiteness == d) {
131 return;
132 }
133 if (d == Definiteness::Unknown) {
134 props.definiteness = d;
135 return;
136 }
137
138 if (props.definiteness != Definiteness::Unknown) {
139 if (definiteness_conflicts(props.definiteness, d)) {
140 throw std::invalid_argument(
141 "Contradiction for symbol '" + symbol +
142 "': definiteness conflict between existing and new declaration");
143 }
144 if (props.definiteness == Definiteness::PositiveSemiDefinite &&
146 props.definiteness = d;
147 return;
148 }
149 if (props.definiteness == Definiteness::NegativeSemiDefinite &&
151 props.definiteness = d;
152 return;
153 }
154 if (props.definiteness == Definiteness::PositiveDefinite &&
156 return; /** @brief 保留更强的正定声明。 */
157 }
158 if (props.definiteness == Definiteness::NegativeDefinite &&
160 return; /** @brief 保留更强的负定声明。 */
161 }
162 }
163
164 props.definiteness = d;
165}
166
167PropertyStoreResult PropertyStore::declare_definiteness(
168 const std::string& symbol, Definiteness d) {
169 return declare_definiteness_checked(symbol, d);
170}
171
172PropertyStoreResult PropertyStore::declare_definiteness_checked(
173 const std::string& symbol,
174 Definiteness d) {
175 return checked_property_update(*this, symbol, "declare_definiteness",
176 [&](PropertyStore& candidate) {
177 candidate.declare_definiteness_unchecked(symbol, d);
178 });
179}
180
181Definiteness PropertyStore::get_definiteness(const std::string& symbol) const {
182 auto it = properties_.find(symbol);
183 if (it == properties_.end()) {
185 }
186 return it->second.definiteness;
187}
188
189
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);
194}
195
196PropertyStoreResult PropertyStore::declare_periodic(
197 const std::string& symbol, const std::string& variable,
198 const SymbolicExpr& period) {
199 return declare_periodic_checked(symbol, variable, period);
200}
201
202PropertyStoreResult PropertyStore::declare_periodic_checked(
203 const std::string& symbol, const std::string& variable,
204 const SymbolicExpr& period) {
205 if (symbol.empty() || variable.empty() || !detail::node(period)) {
207 "symbol, independent variable, and period must be nonempty", "declare_periodic");
208 }
210 auto defined = detail::query_definedness(
212 if (!defined) return PropertyStoreResult::failure(defined.error());
213 auto positive = detail::query_positive_value(
215 if (!positive) return PropertyStoreResult::failure(positive.error());
216 if (defined.value() == Tribool::False || positive.value() == Tribool::False) {
218 "period must be a positive defined real value", "declare_periodic");
219 }
220 return checked_property_update(*this, symbol, "declare_periodic",
221 [&](PropertyStore& candidate) {
222 candidate.declare_periodic_unchecked(symbol, variable, period);
223 });
224}
225
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;
231}
232
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;
238 return it->second;
239}
240
241bool PropertyStore::is_periodic(const std::string& symbol, const std::string& variable) const {
242 return get_period(symbol, variable).has_value();
243}
244
245
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);
251 }
252 std::sort(symbols.begin(), symbols.end());
253 return symbols;
254}
255
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});
263 }
264 return result;
265}
266
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});
274 }
275 return result;
276}
277
278}
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
@ Real
Real numbers
@ 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
内部 AST 定义。