LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
symbolic_set.cpp
浏览该文件的文档.
1#include "symbolic_set.hpp"
2
3#include <algorithm>
4#include <exception>
5#include <optional>
6#include <utility>
7
9
10namespace LMCAS {
11namespace {
12
13constexpr const char* kOperation = "symbolic_set";
14
15SymbolicSetResult failure(CasErrc code, std::string message) {
16 return SymbolicSetResult::failure(code, std::move(message), kOperation);
17}
18
20 return context.consume_steps(1, kOperation);
21}
22
23std::shared_ptr<const FiniteSetNode> finite_set_node(const SymbolicExpr& expression) {
24 return std::dynamic_pointer_cast<const FiniteSetNode>(detail::node(expression));
25}
26
27bool exact_value(const std::shared_ptr<const SymbolicNode>& node, Rational& value) {
28 auto number = std::dynamic_pointer_cast<const NumberNode>(node);
29 if (!number) return false;
30 if (std::holds_alternative<BigInt>(number->value())) {
31 value = Rational(std::get<BigInt>(number->value()));
32 return true;
33 }
34 if (std::holds_alternative<Rational>(number->value())) {
35 value = std::get<Rational>(number->value());
36 return true;
37 }
38 return false;
39}
40
41SymbolicSetResult from_nodes(std::vector<std::shared_ptr<const SymbolicNode>> elements) {
42 try {
44 detail::make_node<FiniteSetNode>(std::move(elements))));
45 } catch (const std::bad_alloc&) {
46 return failure(CasErrc::ResourceLimit, "finite set allocation failed");
47 } catch (const std::exception& error) {
48 return failure(CasErrc::InvalidArgument, error.what());
49 }
50}
51
52std::optional<bool> exact_interval_membership(
53 const std::shared_ptr<const SymbolicNode>& element, const IntervalNode& interval) {
54 Rational value;
55 Rational lower;
56 Rational upper;
57 if (!exact_value(element, value)) {
58 return std::nullopt;
59 }
60 if (!exact_value(interval.lower(), lower) || !exact_value(interval.upper(), upper)) {
61 return std::nullopt;
62 }
63 if (value < lower || upper < value) {
64 return false;
65 }
66 if (value == lower && !interval.lower_closed()) {
67 return false;
68 }
69 return value != upper || interval.upper_closed();
70}
71
72} // namespace
73
75 std::vector<std::shared_ptr<SymbolicExpr>> elements,
77 auto step = consume(context);
78 if (!step) return SymbolicSetResult::failure(step.error());
79 std::vector<std::shared_ptr<const SymbolicNode>> nodes;
80 nodes.reserve(elements.size());
81 for (const auto& element : elements) {
82 if (!element || !detail::node(element)) {
83 return failure(CasErrc::InvalidArgument,
84 "finite set elements cannot be null");
85 }
86 nodes.push_back(detail::node(element));
87 }
88 return from_nodes(std::move(nodes));
89}
90
92 const std::shared_ptr<SymbolicExpr>& lower,
93 const std::shared_ptr<SymbolicExpr>& upper,
94 bool lower_closed,
95 bool upper_closed,
97 auto step = consume(context);
98 if (!step) {
99 return SymbolicSetResult::failure(step.error());
100 }
101 if (!lower || !upper || !detail::node(lower) || !detail::node(upper)) {
102 return failure(CasErrc::InvalidArgument, "interval endpoints cannot be null");
103 }
104 Rational lower_value;
105 Rational upper_value;
106 if (exact_value(detail::node(lower), lower_value) &&
107 exact_value(detail::node(upper), upper_value) &&
108 upper_value < lower_value) {
109 return failure(CasErrc::InvalidArgument,
110 "interval lower endpoint exceeds upper endpoint");
111 }
112 try {
116 } catch (const std::bad_alloc&) {
117 return failure(CasErrc::ResourceLimit, "interval allocation failed");
118 }
119}
120
122 const std::shared_ptr<SymbolicExpr>& element,
123 const std::shared_ptr<SymbolicExpr>& set,
125 auto step = consume(context);
126 if (!step) {
127 return SymbolicSetResult::failure(step.error());
128 }
129 if (!element || !set || !detail::node(element) || !detail::node(set)) {
130 return failure(CasErrc::InvalidArgument, "membership operands cannot be null");
131 }
132 if (auto finite = finite_set_node(*set)) {
133 return SymbolicSetResult::success(SymbolicExpr::number(
134 finite->contains(*detail::node(element)) ? 1 : 0));
135 }
136 if (auto interval = std::dynamic_pointer_cast<const IntervalNode>(detail::node(set))) {
137 if (auto contained = exact_interval_membership(detail::node(element), *interval)) {
138 return SymbolicSetResult::success(SymbolicExpr::number(*contained ? 1 : 0));
139 }
140 }
143}
144
146 const SymbolicExpr& lhs, const SymbolicExpr& rhs,
148 auto step = consume(context);
149 if (!step) return SymbolicSetResult::failure(step.error());
150 auto left = finite_set_node(lhs);
151 auto right = finite_set_node(rhs);
152 if (!left || !right) return failure(CasErrc::SetOperandTypeMismatch,
153 "set union requires two finite sets");
154 auto elements = left->elements();
155 elements.insert(elements.end(), right->elements().begin(), right->elements().end());
156 return from_nodes(std::move(elements));
157}
158
160 const SymbolicExpr& lhs, const SymbolicExpr& rhs,
162 auto step = consume(context);
163 if (!step) return SymbolicSetResult::failure(step.error());
164 auto left = finite_set_node(lhs);
165 auto right = finite_set_node(rhs);
166 if (!left || !right) return failure(CasErrc::SetOperandTypeMismatch,
167 "set intersection requires two finite sets");
168 std::vector<std::shared_ptr<const SymbolicNode>> elements;
169 for (const auto& element : left->elements()) {
170 if (right->contains(*element)) elements.push_back(element);
171 }
172 return from_nodes(std::move(elements));
173}
174
176 const SymbolicExpr& lhs, const SymbolicExpr& rhs,
178 auto step = consume(context);
179 if (!step) return SymbolicSetResult::failure(step.error());
180 auto left = finite_set_node(lhs);
181 auto right = finite_set_node(rhs);
182 if (!left || !right) return failure(CasErrc::SetOperandTypeMismatch,
183 "set difference requires two finite sets");
184 std::vector<std::shared_ptr<const SymbolicNode>> elements;
185 for (const auto& element : left->elements()) {
186 if (!right->contains(*element)) elements.push_back(element);
187 }
188 return from_nodes(std::move(elements));
189}
190
192 const SymbolicExpr& lhs, const SymbolicExpr& rhs,
194 auto left = finite_set_difference(lhs, rhs, context);
195 if (!left) return left;
197 if (!right) return right;
198 return finite_set_union(*left.value(), *right.value(), context);
199}
200
201} // namespace LMCAS
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(std::shared_ptr< SymbolicExpr > value)
std::shared_ptr< const FiniteSetNode > finite_set_node(const SymbolicExpr &expression)
std::optional< bool > exact_interval_membership(const std::shared_ptr< const SymbolicNode > &element, const IntervalNode &interval)
SymbolicSetResult from_nodes(std::vector< std::shared_ptr< const SymbolicNode > > elements)
Result< void > consume(ComputationContext &context)
SymbolicSetResult failure(CasErrc code, std::string message)
bool exact_value(const std::shared_ptr< const SymbolicNode > &node, Rational &value)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicSetResult make_membership(const std::shared_ptr< SymbolicExpr > &element, const std::shared_ptr< SymbolicExpr > &set, ComputationContext &context)
const ExprPtr & element
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
SymbolicSetResult make_interval(const std::shared_ptr< SymbolicExpr > &lower, const std::shared_ptr< SymbolicExpr > &upper, bool lower_closed, bool upper_closed, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
const ExprPtr & lower
const ExprPtr & set
SymbolicSetResult finite_set_difference(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr bool lower_closed
SymbolicSetResult make_finite_set(std::vector< std::shared_ptr< SymbolicExpr > > elements, ComputationContext &context)
const ExprPtr & right
const std::string const ExprPtr & value
SymbolicSetResult finite_set_intersection(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context)
const ExprPtr & rhs
Result< std::shared_ptr< SymbolicExpr > > SymbolicSetResult
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr bool bool upper_closed
SymbolicSetResult finite_set_symmetric_difference(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context)
SymbolicSetResult finite_set_union(const SymbolicExpr &lhs, const SymbolicExpr &rhs, ComputationContext &context)
内部 AST 定义。