LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
exact_matrix_support.cpp
浏览该文件的文档.
6
7#include <limits>
8#include <new>
9
10namespace LMCAS::detail {
11namespace matrix_kernel {
13 const ExactMatrixData& matrix,
14 const std::string& operation) {
15 if (matrix.rows == 0 || matrix.cols == 0) {
18 "exact matrix dimensions must be non-zero", operation);
19 }
20 if (matrix.rows > std::numeric_limits<std::size_t>::max() / matrix.cols ||
21 matrix.entries.size() != matrix.rows * matrix.cols) {
24 "exact matrix storage does not match its dimensions", operation);
25 }
26 for (const auto& entry : matrix.entries) {
27 if (!entry || !node(entry)) {
30 "exact matrix entries cannot be null", operation);
31 }
32 }
33 return Result<void>::success();
34}
35
36std::optional<Rational> exact_rational(const ExprPtr& expression) {
37 if (!expression || !node(expression)) {
38 return std::nullopt;
39 }
40 return exact_rational_value(node(expression));
41}
42
44
45 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
46 (context).limits().max_ast_nodes, "transform");
47 if (!expression) {
48 return expression;
49 }
50 auto simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(expression), transform_budget));
51 return simplified ? simplified : expression;
52}
53
55 return simplify_expr(SymbolicExpr::add(left, right), context);
56}
57
59 return simplify_expr(SymbolicExpr::multiply(
60 SymbolicExpr::number(-1), expression), context);
61}
62
66
68 return simplify_expr(SymbolicExpr::multiply(left, right), context);
69}
70
72 return simplify_expr(SymbolicExpr::divide(numerator, denominator), context);
73}
74
75void swap_rows(ExactMatrixData& matrix, std::size_t first, std::size_t second) {
76 if (first == second) {
77 return;
78 }
79 for (std::size_t column = 0; column < matrix.cols; ++column) {
80 std::swap(matrix.at(first, column), matrix.at(second, column));
81 }
82}
83
85 const ExactMatrixData& matrix,
86 std::size_t first_row,
87 std::size_t column,
89 const std::string& operation) {
90 bool saw_unknown = false;
91 for (std::size_t row = first_row; row < matrix.rows; ++row) {
92 auto proof = classify_exact_zero(matrix.at(row, column), context, operation);
93 if (!proof) {
94 return Result<std::optional<std::size_t>>::failure(proof.error());
95 }
96 if (proof.value() == ZeroProof::NonZero) {
97 return Result<std::optional<std::size_t>>::success(row);
98 }
99 saw_unknown = saw_unknown || proof.value() == ZeroProof::Unknown;
100 }
101 if (saw_unknown) {
102 return Result<std::optional<std::size_t>>::failure(
104 "exact pivot is not provably zero or non-zero", operation);
105 }
106 return Result<std::optional<std::size_t>>::success(std::nullopt);
107}
108
109}
110using namespace matrix_kernel;
111namespace {
112std::optional<ZeroProof> classify_numeric_power(const ExprPtr& simplified) {
113 if (auto power =
114 std::dynamic_pointer_cast<const PowerNode>(node(simplified))) {
115 auto base = exact_rational(
116 make_expression_ptr(power->base()));
118 make_expression_ptr(power->exponent()));
119 if (base && exponent) {
120 if (*base > Rational(0)) {
121 return ZeroProof::NonZero;
122 }
123 if (*base == Rational(0) && *exponent > Rational(0)) {
124 return ZeroProof::Zero;
125 }
126 }
127 }
128 return std::nullopt;
129}
130
131std::optional<ZeroProof> classify_numeric_sqrt(const ExprPtr& simplified) {
132 auto function =
133 std::dynamic_pointer_cast<const FunctionNode>(node(simplified));
134 if (!function) {
135 return std::nullopt;
136 }
137 if (function->type() != FunctionNode::FuncType::Sqrt ||
138 function->arguments().size() != 1) {
139 return std::nullopt;
140 }
141 auto argument = exact_rational(
142 make_expression_ptr(function->arguments()[0]));
143 if (!argument || *argument < Rational(0)) {
144 return std::nullopt;
145 }
146 return *argument == Rational(0) ? ZeroProof::Zero : ZeroProof::NonZero;
147}
148
149std::optional<ZeroProof> classify_numeric_value(const ExprPtr& expression) {
150 if (auto value = exact_rational(expression)) {
151 return *value == Rational(0) ? ZeroProof::Zero : ZeroProof::NonZero;
152 }
153 if (auto proof = classify_numeric_power(expression)) {
154 return proof;
155 }
156 if (auto proof = classify_numeric_sqrt(expression)) {
157 return proof;
158 }
159 if (auto root = std::dynamic_pointer_cast<const RootOfNode>(node(expression));
160 root && !root->exact_id().polynomial.coeffs.empty() &&
161 root->exact_id().polynomial.coeffs[0] != Rational(0)) {
162 return ZeroProof::NonZero;
163 }
164 return std::nullopt;
165}
166}
167
169 const ExprPtr& expression,
171 const std::string& operation) {
172 auto access = context.consume_steps(1, operation);
173 if (!access) {
174 return Result<ZeroProof>::failure(access.error());
175 }
176 if (!expression || !node(expression)) {
179 "zero classification requires an expression", operation);
180 }
181 try {
182 auto simplified = simplify_expr(expression, context);
183 if (auto proof = classify_numeric_value(simplified)) {
184 return Result<ZeroProof>::success(*proof);
185 }
186 if (!context.assumptions()) {
188 }
189 auto assumption = context.assumptions()->is_nonzero_checked(*simplified, context);
190 if (!assumption) {
191 return Result<ZeroProof>::failure(assumption.error());
192 }
193 if (assumption.value() == Tribool::True) {
195 }
196 if (assumption.value() == Tribool::False) {
198 }
200 } catch (const CasError& error) {
201 return Result<ZeroProof>::failure(error);
202 } catch (const std::length_error& error) {
204 } catch (const std::bad_alloc&) {
207 "zero classification allocation failed", operation);
208 } catch (const std::exception& error) {
211 }
212}
213
214}
AssumptionContext class with scoped push/pop management.
@ Sqrt
对数、绝对值、平方根。
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::optional< ZeroProof > classify_numeric_power(const ExprPtr &simplified)
std::optional< ZeroProof > classify_numeric_value(const ExprPtr &expression)
std::optional< ZeroProof > classify_numeric_sqrt(const ExprPtr &simplified)
ExprPtr simplify_expr(ExprPtr expression, ComputationContext &context)
std::optional< Rational > exact_rational(const ExprPtr &expression)
Result< std::optional< std::size_t > > choose_pivot(const ExactMatrixData &matrix, std::size_t first_row, std::size_t column, ComputationContext &context, const std::string &operation)
ExprPtr exact_multiply(const ExprPtr &left, const ExprPtr &right, ComputationContext &context)
ExprPtr exact_subtract(const ExprPtr &left, const ExprPtr &right, ComputationContext &context)
ExprPtr exact_negate(const ExprPtr &expression, ComputationContext &context)
void swap_rows(ExactMatrixData &matrix, std::size_t first, std::size_t second)
Result< void > validate_matrix(const ExactMatrixData &matrix, const std::string &operation)
ExprPtr exact_add(const ExprPtr &left, const ExprPtr &right, ComputationContext &context)
ExprPtr exact_divide(const ExprPtr &numerator, const ExprPtr &denominator, ComputationContext &context)
多元 Hensel 提升(单变量步)
Result< ZeroProof > classify_exact_zero(const ExprPtr &expression, ComputationContext &context, const std::string &operation)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
ComputationContext const std::string & operation
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
@ True
Property definitely holds
@ False
Property definitely does not hold
const ExprPtr & exponent
std::shared_ptr< SymbolicExpr > ExprPtr
const ExprPtr & right
const std::string const ExprPtr & value
const ExprPtr & denominator
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
const ExprPtr & at(std::size_t row, std::size_t col) const