LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
exact_matrix_solve.cpp
浏览该文件的文档.
3
4#include <algorithm>
5#include <limits>
6#include <new>
7#include <set>
8
9namespace LMCAS::detail {
10using namespace matrix_kernel;
11namespace {
12template <typename Entry>
14 std::size_t coefficient_columns,
15 const std::vector<std::optional<std::size_t>>& pivot_row, Entry entry) {
16 std::vector<std::size_t> free_columns;
17 for (std::size_t column = 0; column < coefficient_columns; ++column) {
18 if (!pivot_row[column]) free_columns.push_back(column);
19 }
20 std::vector<ExprPtr> particular(
21 coefficient_columns, SymbolicExpr::number(0));
22 for (std::size_t column = 0; column < coefficient_columns; ++column) {
23 if (pivot_row[column]) {
24 particular[column] = entry(*pivot_row[column], coefficient_columns, false);
25 }
26 }
27 if (free_columns.empty()) {
29 UniqueLinearSolution{std::move(particular)});
30 }
31
32 std::vector<std::vector<ExprPtr>> basis;
33 basis.reserve(free_columns.size());
34 for (const auto free_column : free_columns) {
35 std::vector<ExprPtr> vector(
36 coefficient_columns, SymbolicExpr::number(0));
37 vector[free_column] = SymbolicExpr::number(1);
38 for (std::size_t column = 0; column < coefficient_columns; ++column) {
39 if (pivot_row[column]) {
40 vector[column] = entry(*pivot_row[column], free_column, true);
41 }
42 }
43 basis.push_back(std::move(vector));
44 }
46 std::move(particular), std::move(basis), std::move(free_columns)});
47}
48
50 const ExactMatrixData& rref, std::size_t coefficient_columns,
51 ComputationContext& context, const std::string& operation) {
52 for (std::size_t row = 0; row < rref.rows; ++row) {
53 bool coefficients_zero = true;
54 for (std::size_t column = 0; column < coefficient_columns; ++column) {
55 auto proof = classify_exact_zero(rref.at(row, column), context, operation);
56 if (!proof) return Result<bool>::failure(proof.error());
57 if (proof.value() == ZeroProof::Unknown) {
60 "linear-system consistency is not provable", operation);
61 }
62 coefficients_zero = coefficients_zero && proof.value() == ZeroProof::Zero;
63 }
64 if (!coefficients_zero) continue;
66 rref.at(row, coefficient_columns), context, operation);
67 if (!rhs) return Result<bool>::failure(rhs.error());
68 if (rhs.value() == ZeroProof::Unknown) {
71 "linear-system right-hand side is not provably zero", operation);
72 }
73 if (rhs.value() == ZeroProof::NonZero) {
74 return Result<bool>::success(true);
75 }
76 }
77 return Result<bool>::success(false);
78}
79
81 const ExactMatrixData& augmented,
82 std::size_t coefficient_columns,
84 const std::string& operation) {
85 auto budget = context.consume_steps(
86 augmented.rows * augmented.cols, operation);
87 if (!budget) {
89 }
90 std::vector<Rational> matrix;
91 matrix.reserve(augmented.entries.size());
92 for (const auto& entry : augmented.entries) {
93 auto value = exact_rational(entry);
94 if (!value) {
97 "rational specialization received a symbolic entry",
98 operation);
99 }
100 matrix.push_back(*value);
101 }
102 auto pivot_rows = reduce_rational_rows(
103 augmented.rows, coefficient_columns, matrix, false);
104 if (rational_system_inconsistent(augmented.rows, coefficient_columns, matrix)) {
106 }
107 return assemble_linear_solution(coefficient_columns, pivot_rows,
108 [&](std::size_t row, std::size_t column, bool negate) {
109 const auto& value = matrix[row * augmented.cols + column];
110 return SymbolicExpr::number(negate ? -value : value);
111 });
112}
113
114}
115
117 ExactMatrixData augmented,
118 std::size_t coefficient_columns,
120 const std::string& operation) {
121 auto valid = validate_matrix(augmented, operation);
122
123 if (!valid) return Result<ExactLinearSolution>::failure(valid.error());
124 if (augmented.cols != coefficient_columns + 1) {
127 "linear solve requires one augmented right-hand side", operation);
128 }
129 bool all_rational = true;
130 for (const auto& entry : augmented.entries) {
131 all_rational = all_rational && exact_rational(entry).has_value();
132 }
133 if (all_rational) {
134 return rational_linear_solve(
135 augmented, coefficient_columns, context, operation);
136 }
137 auto eliminated = eliminate_exact(
138 std::move(augmented), coefficient_columns,
140 if (!eliminated) return Result<ExactLinearSolution>::failure(eliminated.error());
141 auto& rref = eliminated.value().matrix;
142
143 auto inconsistent = inconsistent_symbolic_system(
144 rref, coefficient_columns, context, operation);
145 if (!inconsistent) return Result<ExactLinearSolution>::failure(inconsistent.error());
146 if (inconsistent.value()) {
148 }
149 std::vector<std::optional<std::size_t>> pivot_row(coefficient_columns);
150 for (std::size_t index = 0;
151 index < eliminated.value().pivot_columns.size(); ++index) {
152 const auto column = eliminated.value().pivot_columns[index];
153 if (column < coefficient_columns) pivot_row[column] = index;
154 }
155 return assemble_linear_solution(coefficient_columns, pivot_row,
156 [&](std::size_t row, std::size_t column, bool negate) {
157 const auto& value = rref.at(row, column);
159 });
160}
161
163 ExactMatrixData coefficients,
165 const std::string& operation) {
166 auto valid = validate_matrix(coefficients, operation);
167 if (!valid) {
168 return Result<std::vector<std::vector<ExprPtr>>>::failure(valid.error());
169 }
170 const std::size_t columns = coefficients.cols;
171 auto eliminated = eliminate_exact(
172 std::move(coefficients), columns,
174 if (!eliminated) {
176 eliminated.error());
177 }
178 std::set<std::size_t> pivots(
179 eliminated.value().pivot_columns.begin(),
180 eliminated.value().pivot_columns.end());
181 std::vector<std::vector<ExprPtr>> basis;
182 for (std::size_t free_column = 0; free_column < columns; ++free_column) {
183 if (pivots.count(free_column) != 0) continue;
184 std::vector<ExprPtr> vector(columns, SymbolicExpr::number(0));
185 vector[free_column] = SymbolicExpr::number(1);
186 for (std::size_t row = 0;
187 row < eliminated.value().pivot_columns.size(); ++row) {
188 vector[eliminated.value().pivot_columns[row]] = exact_negate(
189 eliminated.value().matrix.at(row, free_column), context);
190 }
191 basis.push_back(std::move(vector));
192 }
194 std::move(basis));
195}
196
197}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< bool > inconsistent_symbolic_system(const ExactMatrixData &rref, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
Result< ExactLinearSolution > assemble_linear_solution(std::size_t coefficient_columns, const std::vector< std::optional< std::size_t > > &pivot_row, Entry entry)
Result< ExactLinearSolution > rational_linear_solve(const ExactMatrixData &augmented, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
std::optional< Rational > exact_rational(const ExprPtr &expression)
ExprPtr exact_negate(const ExprPtr &expression, ComputationContext &context)
Result< void > validate_matrix(const ExactMatrixData &matrix, const std::string &operation)
多元 Hensel 提升(单变量步)
Result< std::vector< std::vector< ExprPtr > > > nullspace_exact(ExactMatrixData coefficients, ComputationContext &context, const std::string &operation)
Result< EliminationResult > eliminate_exact(ExactMatrixData input, std::size_t coefficient_columns, EliminationForm form, ComputationContext &context, const std::string &operation)
Result< ZeroProof > classify_exact_zero(const ExprPtr &expression, ComputationContext &context, const std::string &operation)
ExactRealAlgebraic rhs
bool rational_system_inconsistent(std::size_t rows, std::size_t coefficient_columns, const std::vector< Rational > &matrix)
Result< ExactLinearSolution > solve_linear_exact(ExactMatrixData augmented, std::size_t coefficient_columns, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
std::size_t std::size_t ComputationContext & context
std::vector< std::optional< std::size_t > > reduce_rational_rows(std::size_t rows, std::size_t coefficient_columns, std::vector< Rational > &matrix, bool start_at_pivot)
std::shared_ptr< SymbolicExpr > negate(const std::shared_ptr< SymbolicExpr > &expr)
const std::vector< FGLMPoly > & basis
const std::string const ExprPtr & value
const ExprPtr & at(std::size_t row, std::size_t col) const
内部 AST 定义。