LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
sets.hpp
浏览该文件的文档.
1#pragma once
3
4namespace LMCAS {
6public:
7 enum class Type {
8 ForAll, /**< 全称量词 forall。 */
9 Exists /**< 存在量词 exists。 */
10 };
11
12private:
14
16 const std::string bound_var_;
17 const std::shared_ptr<const SymbolicNode> domain_;
18 const std::shared_ptr<const SymbolicNode> predicate_;
19
20 /**
21 * @brief 构造量词节点。
22 * @param qt 量词类型
23 * @param var 约束变量名
24 * @param dom 定义域表达式
25 * @param pred 谓词表达式
26 */
27 QuantifierNode(Type qt, std::string var,
28 std::shared_ptr<const SymbolicNode> dom, std::shared_ptr<const SymbolicNode> pred)
29 : quantifier_type_(qt), bound_var_(std::move(var)),
30 domain_(std::move(dom)), predicate_(std::move(pred)) {
31 if (!domain_ || !predicate_) {
32 throw std::invalid_argument("QuantifierNode domain and predicate cannot be null");
33 }
34 if (bound_var_.empty()) {
35 throw std::invalid_argument("QuantifierNode bound variable cannot be empty");
36 }
37 }
38
39public:
40 Type quantifier_type() const noexcept { return quantifier_type_; }
41 const std::string& bound_var() const noexcept { return bound_var_; }
42 const std::shared_ptr<const SymbolicNode>& domain() const noexcept { return domain_; }
43 const std::shared_ptr<const SymbolicNode>& predicate() const noexcept {
44 return predicate_;
45 }
46
47 int type_priority() const override { return 102; }
48
49protected:
50 std::size_t compute_hash() const override {
51 std::size_t seed = 0;
53 hash_combine(seed, static_cast<std::size_t>(quantifier_type_));
54 hash_combine(seed, std::hash<std::string>{}(bound_var_));
55 hash_combine(seed, domain_->hash());
56 hash_combine(seed, predicate_->hash());
57 return seed;
58 }
59
60 int compare_same_type(const SymbolicNode& other) const override {
61 const auto& o = static_cast<const QuantifierNode&>(other);
62 if (quantifier_type_ != o.quantifier_type_) {
63 return static_cast<int>(quantifier_type_) < static_cast<int>(o.quantifier_type_) ? -1 : 1;
64 }
65 int cmp = bound_var_.compare(o.bound_var_);
66 if (cmp != 0) return cmp;
67 cmp = domain_->compare(*o.domain_);
68 if (cmp != 0) return cmp;
69 return predicate_->compare(*o.predicate_);
70 }
71
72public:
73 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
74
75 std::shared_ptr<const SymbolicNode> clone() const override {
77 quantifier_type_, bound_var_, domain_->clone(), predicate_->clone());
78 }
79};
81private:
83
84 const std::string element_var_;
85 const std::shared_ptr<const SymbolicNode> domain_;
86 const std::shared_ptr<const SymbolicNode> predicate_;
87
88 /**
89 * @brief 构造集合构造器节点。
90 * @param var 元素变量名
91 * @param dom 定义域表达式
92 * @param pred 成员条件表达式
93 */
94 SetBuilderNode(std::string var, std::shared_ptr<const SymbolicNode> dom,
95 std::shared_ptr<const SymbolicNode> pred)
96 : element_var_(std::move(var)), domain_(std::move(dom)),
97 predicate_(std::move(pred)) {
98 if (!domain_ || !predicate_) {
99 throw std::invalid_argument("SetBuilderNode domain and predicate cannot be null");
100 }
101 if (element_var_.empty()) {
102 throw std::invalid_argument("SetBuilderNode element variable cannot be empty");
103 }
104 }
105
106public:
107 const std::string& element_var() const noexcept { return element_var_; }
108 const std::shared_ptr<const SymbolicNode>& domain() const noexcept { return domain_; }
109 const std::shared_ptr<const SymbolicNode>& predicate() const noexcept {
110 return predicate_;
111 }
112
113 int type_priority() const override { return 103; }
114
115protected:
116 std::size_t compute_hash() const override {
117 std::size_t seed = 0;
119 hash_combine(seed, std::hash<std::string>{}(element_var_));
120 hash_combine(seed, domain_->hash());
121 hash_combine(seed, predicate_->hash());
122 return seed;
123 }
124
125 int compare_same_type(const SymbolicNode& other) const override {
126 const auto& o = static_cast<const SetBuilderNode&>(other);
127 int cmp = element_var_.compare(o.element_var_);
128 if (cmp != 0) return cmp;
129 cmp = domain_->compare(*o.domain_);
130 if (cmp != 0) return cmp;
131 return predicate_->compare(*o.predicate_);
132 }
133
134public:
135 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override { LMCAS::detail::SymbolicVisitor::DepthGuard guard(visitor); visitor.visit(*this); }
136
137 std::shared_ptr<const SymbolicNode> clone() const override {
139 element_var_, domain_->clone(), predicate_->clone());
140 }
141};
143private:
145 const std::vector<std::shared_ptr<const SymbolicNode>> elements_;
146
147 explicit FiniteSetNode(std::vector<std::shared_ptr<const SymbolicNode>> elements)
148 : elements_(canonicalize(std::move(elements))) {}
149
150 static std::vector<std::shared_ptr<const SymbolicNode>> canonicalize(
151 std::vector<std::shared_ptr<const SymbolicNode>> elements) {
152 for (const auto& element : elements) {
153 if (!element) throw std::invalid_argument("finite set elements cannot be null");
154 }
155 std::sort(elements.begin(), elements.end(),
156 [](const auto& lhs, const auto& rhs) { return lhs->compare(*rhs) < 0; });
157 elements.erase(std::unique(elements.begin(), elements.end(),
158 [](const auto& lhs, const auto& rhs) {
159 return lhs->equals(*rhs);
160 }),
161 elements.end());
162 return elements;
163 }
164
165public:
166 const std::vector<std::shared_ptr<const SymbolicNode>>& elements() const noexcept {
167 return elements_;
168 }
169 bool contains(const SymbolicNode& element) const {
170 return std::any_of(elements_.begin(), elements_.end(),
171 [&](const auto& candidate) { return candidate->equals(element); });
172 }
173 int type_priority() const override { return 104; }
174
175protected:
176 std::size_t compute_hash() const override {
177 std::size_t seed = static_cast<std::size_t>(type_priority());
178 for (const auto& element : elements_) hash_combine(seed, element->hash());
179 return seed;
180 }
181 int compare_same_type(const SymbolicNode& other) const override {
182 const auto& set = static_cast<const FiniteSetNode&>(other);
183 const auto count = std::min(elements_.size(), set.elements_.size());
184 for (std::size_t index = 0; index < count; ++index) {
185 const int comparison = elements_[index]->compare(*set.elements_[index]);
186 if (comparison != 0) return comparison;
187 }
188 if (elements_.size() == set.elements_.size()) return 0;
189 return elements_.size() < set.elements_.size() ? -1 : 1;
190 }
191
192public:
193 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
195 visitor.visit(*this);
196 }
197 std::shared_ptr<const SymbolicNode> clone() const override {
198 std::vector<std::shared_ptr<const SymbolicNode>> elements;
199 elements.reserve(elements_.size());
200 for (const auto& element : elements_) elements.push_back(element->clone());
202 }
203};
205private:
207 const std::shared_ptr<const SymbolicNode> lower_;
208 const std::shared_ptr<const SymbolicNode> upper_;
209 const bool lower_closed_;
210 const bool upper_closed_;
211
212 IntervalNode(std::shared_ptr<const SymbolicNode> lower,
213 std::shared_ptr<const SymbolicNode> upper,
214 bool lower_closed, bool upper_closed)
215 : lower_(std::move(lower)), upper_(std::move(upper)),
217 if (!lower_ || !upper_) throw std::invalid_argument("interval endpoints cannot be null");
218 }
219
220public:
221 const auto& lower() const noexcept { return lower_; }
222 const auto& upper() const noexcept { return upper_; }
223 bool lower_closed() const noexcept { return lower_closed_; }
224 bool upper_closed() const noexcept { return upper_closed_; }
225 int type_priority() const override { return 105; }
226
227protected:
228 std::size_t compute_hash() const override {
229 std::size_t seed = static_cast<std::size_t>(type_priority());
230 hash_combine(seed, lower_->hash());
231 hash_combine(seed, upper_->hash());
234 return seed;
235 }
236 int compare_same_type(const SymbolicNode& other) const override;
237
238public:
239 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
241 visitor.visit(*this);
242 }
243 std::shared_ptr<const SymbolicNode> clone() const override {
245 lower_->clone(), upper_->clone(), lower_closed_, upper_closed_);
246 }
247};
249private:
251 const std::shared_ptr<const SymbolicNode> element_;
252 const std::shared_ptr<const SymbolicNode> set_;
253 MembershipNode(std::shared_ptr<const SymbolicNode> element,
254 std::shared_ptr<const SymbolicNode> set)
255 : element_(std::move(element)), set_(std::move(set)) {
256 if (!element_ || !set_) throw std::invalid_argument("membership operands cannot be null");
257 }
258
259public:
260 const auto& element() const noexcept { return element_; }
261 const auto& set() const noexcept { return set_; }
262 int type_priority() const override { return 106; }
263
264protected:
265 std::size_t compute_hash() const override {
266 std::size_t seed = static_cast<std::size_t>(type_priority());
267 hash_combine(seed, element_->hash());
268 hash_combine(seed, set_->hash());
269 return seed;
270 }
271 int compare_same_type(const SymbolicNode& other) const override {
272 const auto& membership = static_cast<const MembershipNode&>(other);
273 const int comparison = element_->compare(*membership.element_);
274 return comparison != 0 ? comparison : set_->compare(*membership.set_);
275 }
276
277public:
278 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
280 visitor.visit(*this);
281 }
282 std::shared_ptr<const SymbolicNode> clone() const override {
283 return LMCAS::detail::make_node<MembershipNode>(element_->clone(), set_->clone());
284 }
285};
287private:
289 const std::shared_ptr<const SymbolicNode> value_;
290 const LMCAS::DimensionSignature dimension_;
291 const Rational scale_to_base_;
292 const std::string display_unit_;
293
294 QuantityNode(std::shared_ptr<const SymbolicNode> value,
295 LMCAS::DimensionSignature dimension,
296 Rational scale_to_base, std::string display_unit)
297 : value_(std::move(value)), dimension_(std::move(dimension)),
298 scale_to_base_(std::move(scale_to_base)),
299 display_unit_(std::move(display_unit)) {
300 if (!value_) throw std::invalid_argument("quantity value cannot be null");
301 if (scale_to_base_.is_zero()) throw std::invalid_argument("quantity scale cannot be zero");
302 }
303
304public:
305 const auto& value() const noexcept { return value_; }
306 const auto& dimension() const noexcept { return dimension_; }
307 const Rational& scale_to_base() const noexcept { return scale_to_base_; }
308 const std::string& display_unit() const noexcept { return display_unit_; }
309 int type_priority() const override { return 107; }
310
311protected:
312 std::size_t compute_hash() const override {
313 std::size_t seed = static_cast<std::size_t>(type_priority());
314 hash_combine(seed, value_->hash());
315 hash_combine(seed, std::hash<std::string>{}(dimension_.to_string()));
316 hash_combine(seed, scale_to_base_.hash());
317 hash_combine(seed, std::hash<std::string>{}(display_unit_));
318 return seed;
319 }
320 int compare_same_type(const SymbolicNode& other) const override {
321 const auto& quantity = static_cast<const QuantityNode&>(other);
322 int comparison = dimension_.to_string().compare(quantity.dimension_.to_string());
323 if (comparison != 0) return comparison;
324 if (scale_to_base_ < quantity.scale_to_base_) return -1;
325 if (quantity.scale_to_base_ < scale_to_base_) return 1;
326 comparison = display_unit_.compare(quantity.display_unit_);
327 return comparison != 0 ? comparison : value_->compare(*quantity.value_);
328 }
329
330public:
331 void accept(LMCAS::detail::SymbolicVisitor& visitor) const override {
333 visitor.visit(*this);
334 }
335 std::shared_ptr<const SymbolicNode> clone() const override {
338 }
339};
340
341}
const std::vector< std::shared_ptr< const SymbolicNode > > & elements() const noexcept
static std::vector< std::shared_ptr< const SymbolicNode > > canonicalize(std::vector< std::shared_ptr< const SymbolicNode > > elements)
const std::vector< std::shared_ptr< const SymbolicNode > > elements_
int compare_same_type(const SymbolicNode &other) const override
std::size_t compute_hash() const override
int type_priority() const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
FiniteSetNode(std::vector< std::shared_ptr< const SymbolicNode > > elements)
bool contains(const SymbolicNode &element) const
std::shared_ptr< const SymbolicNode > clone() const override
int compare_same_type(const SymbolicNode &other) const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
std::size_t compute_hash() const override
bool upper_closed() const noexcept
const std::shared_ptr< const SymbolicNode > lower_
int type_priority() const override
const bool lower_closed_
const bool upper_closed_
IntervalNode(std::shared_ptr< const SymbolicNode > lower, std::shared_ptr< const SymbolicNode > upper, bool lower_closed, bool upper_closed)
std::shared_ptr< const SymbolicNode > clone() const override
bool lower_closed() const noexcept
const std::shared_ptr< const SymbolicNode > upper_
const auto & lower() const noexcept
const auto & upper() const noexcept
int type_priority() const override
std::shared_ptr< const SymbolicNode > clone() const override
int compare_same_type(const SymbolicNode &other) const override
const auto & set() const noexcept
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
const std::shared_ptr< const SymbolicNode > set_
MembershipNode(std::shared_ptr< const SymbolicNode > element, std::shared_ptr< const SymbolicNode > set)
const auto & element() const noexcept
const std::shared_ptr< const SymbolicNode > element_
std::size_t compute_hash() const override
std::size_t compute_hash() const override
int compare_same_type(const SymbolicNode &other) const override
std::shared_ptr< const SymbolicNode > clone() const override
Type quantifier_type() const noexcept
const std::string & bound_var() const noexcept
const std::shared_ptr< const SymbolicNode > & predicate() const noexcept
const std::shared_ptr< const SymbolicNode > predicate_
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
const std::string bound_var_
QuantifierNode(Type qt, std::string var, std::shared_ptr< const SymbolicNode > dom, std::shared_ptr< const SymbolicNode > pred)
构造量词节点。
int type_priority() const override
const std::shared_ptr< const SymbolicNode > domain_
const Type quantifier_type_
const std::shared_ptr< const SymbolicNode > & domain() const noexcept
const auto & value() const noexcept
const Rational & scale_to_base() const noexcept
int compare_same_type(const SymbolicNode &other) const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
std::size_t compute_hash() const override
int type_priority() const override
const std::string & display_unit() const noexcept
const std::shared_ptr< const SymbolicNode > value_
const Rational scale_to_base_
QuantityNode(std::shared_ptr< const SymbolicNode > value, LMCAS::DimensionSignature dimension, Rational scale_to_base, std::string display_unit)
const std::string display_unit_
const auto & dimension() const noexcept
std::shared_ptr< const SymbolicNode > clone() const override
const LMCAS::DimensionSignature dimension_
int compare_same_type(const SymbolicNode &other) const override
const std::shared_ptr< const SymbolicNode > & domain() const noexcept
std::shared_ptr< const SymbolicNode > clone() const override
const std::shared_ptr< const SymbolicNode > & predicate() const noexcept
const std::string element_var_
SetBuilderNode(std::string var, std::shared_ptr< const SymbolicNode > dom, std::shared_ptr< const SymbolicNode > pred)
构造集合构造器节点。
const std::shared_ptr< const SymbolicNode > domain_
std::size_t compute_hash() const override
const std::shared_ptr< const SymbolicNode > predicate_
int type_priority() const override
void accept(LMCAS::detail::SymbolicVisitor &visitor) const override
const std::string & element_var() const noexcept
SymbolicNode()=default
virtual void visit(const NumberNode &node)=0
std::shared_ptr< const Node > make_node(Args &&... args)
const ExprPtr & element
void hash_combine(std::size_t &seed, std::size_t value)
将一个哈希值混合到种子中,用于组合多个字段的哈希.
const ExprPtr & set
ExprResult membership(const ExprPtr &element, const ExprPtr &set, bool negated)
const ExprPtr & rhs