LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
exact_matrix_determinant.cpp
浏览该文件的文档.
3
4#include <algorithm>
5#include <limits>
6#include <new>
7#include <set>
8
9namespace LMCAS::detail {
10using namespace matrix_kernel;
11namespace {
13 const ExactMatrixData& input,
15 const std::string& operation) {
16 std::vector<Rational> values;
17 values.reserve(input.entries.size());
18 for (const auto& entry : input.entries) {
19 auto value = exact_rational(entry);
20 if (!value) {
23 "matrix is not entirely rational",
24 operation);
25 }
26 values.push_back(*value);
27 }
28 auto determinant = rational_determinant_value_impl(
29 input.rows, std::move(values), context, operation);
30 if (!determinant) return Result<ExprPtr>::failure(determinant.error());
32 SymbolicExpr::number(determinant.value()));
33}
34
36 const ExactMatrixData& matrix,
38 const std::string& operation) {
39 auto budget = context.consume_steps(1, operation);
40 if (!budget) return Result<ExprPtr>::failure(budget.error());
41 if (matrix.rows == 1) {
42 return Result<ExprPtr>::success(matrix.entries[0]);
43 }
44 auto sum = SymbolicExpr::number(0);
45 for (std::size_t column = 0; column < matrix.cols; ++column) {
46 if (auto coefficient = exact_rational(matrix.at(0, column));
47 coefficient && *coefficient == Rational(0)) {
48 continue;
49 }
50 ExactMatrixData minor{
51 matrix.rows - 1, matrix.cols - 1, {}};
52 minor.entries.reserve(minor.rows * minor.cols);
53 for (std::size_t row = 1; row < matrix.rows; ++row) {
54 for (std::size_t source = 0; source < matrix.cols; ++source) {
55 if (source != column) {
56 minor.entries.push_back(matrix.at(row, source));
57 }
58 }
59 }
60 auto minor_determinant = determinant_cofactor(
61 minor, context, operation);
62 if (!minor_determinant) {
63 return Result<ExprPtr>::failure(minor_determinant.error());
64 }
65 auto term = exact_multiply(
66 matrix.at(0, column), minor_determinant.value(), context);
67 if (column % 2 != 0) term = exact_negate(term, context);
68 sum = exact_add(sum, term, context);
69 }
71}
72
75 const std::string& operation) {
76 ExactMatrixData matrix = input;
77 const std::size_t n = matrix.rows;
78 if (n == 1) return Result<ExprPtr>::success(matrix.entries[0]);
79 auto previous = SymbolicExpr::number(1);
80 std::size_t swaps = 0;
81 for (std::size_t column = 0; column + 1 < n; ++column) {
82 auto pivot = choose_pivot(matrix, column, column, context, operation);
83 if (!pivot) {
84 if (pivot.error().code == CasErrc::Inconclusive) {
86 }
87 return Result<ExprPtr>::failure(pivot.error());
88 }
89 if (!pivot.value()) {
90 return Result<ExprPtr>::success(SymbolicExpr::number(0));
91 }
92 if (*pivot.value() != column) {
93 swap_rows(matrix, *pivot.value(), column);
94 ++swaps;
95 }
96 auto pivot_value = matrix.at(column, column);
97 for (std::size_t row = column + 1; row < n; ++row) {
98 for (std::size_t target = column + 1; target < n; ++target) {
99 auto numerator = exact_subtract(
100 exact_multiply(matrix.at(row, target), pivot_value, context),
101 exact_multiply(matrix.at(row, column), matrix.at(column, target), context), context);
102 matrix.at(row, target) = exact_divide(numerator, previous, context);
103 }
104 matrix.at(row, column) = SymbolicExpr::number(0);
105 }
106 previous = pivot_value;
107 }
108 auto determinant = matrix.at(n - 1, n - 1);
109 if (swaps % 2 != 0) determinant = exact_negate(determinant, context);
110 return Result<ExprPtr>::success(simplify_expr(determinant, context));
111}
112
113}
114
116 const ExactMatrixData& input,
118 const std::string& operation) {
119 auto valid = validate_matrix(input, operation);
120 if (!valid) return Result<ExprPtr>::failure(valid.error());
121 if (input.rows != input.cols) {
124 "determinant requires a square matrix", operation);
125 }
126 bool all_rational = true;
127 for (const auto& entry : input.entries) {
128 all_rational = all_rational && exact_rational(entry).has_value();
129 }
130 if (all_rational) return rational_determinant(input, context, operation);
131
132 try {
133 return symbolic_determinant_value(input, context, operation);
134 } catch (const std::bad_alloc&) {
137 "exact determinant allocation failed", operation);
138 } catch (const std::exception& error) {
141 }
142}
143
144}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< ExprPtr > symbolic_determinant_value(const ExactMatrixData &input, ComputationContext &context, const std::string &operation)
Result< ExprPtr > determinant_cofactor(const ExactMatrixData &matrix, ComputationContext &context, const std::string &operation)
Result< ExprPtr > rational_determinant(const ExactMatrixData &input, ComputationContext &context, const std::string &operation)
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< ExprPtr > determinant_exact(const ExactMatrixData &input, ComputationContext &context, const std::string &operation)
Result< Rational > rational_determinant_value_impl(std::size_t dimension, std::vector< Rational > values, ComputationContext &context, const std::string &operation)
ComputationContext const std::string & operation
std::size_t std::size_t ComputationContext & context
const ExprPtr & target
const std::string const ExprPtr & value
const ExprPtr & at(std::size_t row, std::size_t col) const
内部 AST 定义。