LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
matrix_decomposition_cholesky.cpp
浏览该文件的文档.
3
4#include <algorithm>
5#include <new>
6
7namespace LMCAS {
8using namespace detail::matrix_decomposition;
9namespace {
11 const std::shared_ptr<const MatrixNode>& matrix,
13 const std::string& operation) {
14 auto values = exact_rational_matrix(matrix, context);
15 if (!values) {
18 "Cholesky input is outside the exact rational SPD support domain",
19 operation);
20 }
21 const size_t n = values->size();
22 for (size_t row = 0; row < n; ++row) {
23 for (size_t col = row + 1; col < n; ++col) {
24 if ((*values)[row][col] != (*values)[col][row]) {
27 "Cholesky input must be symmetric",
28 operation);
29 }
30 }
31 }
32 for (size_t order = 1; order <= n; ++order) {
33 std::vector<Rational> leading;
34 leading.reserve(order * order);
35 for (size_t row = 0; row < order; ++row) {
36 for (size_t col = 0; col < order; ++col) {
37 leading.push_back((*values)[row][col]);
38 }
39 }
40 auto determinant = detail::rational_determinant_exact(
41 order, std::move(leading), context, operation);
42 if (!determinant) return Result<void>::failure(determinant.error());
43 if (determinant.value() <= Rational(0)) {
46 "Cholesky input is not positive definite",
47 operation);
48 }
49 }
50 return Result<void>::success();
51}
53 const std::shared_ptr<SymbolicExpr>& A,
54 std::shared_ptr<SymbolicExpr>& L) {
55 auto mat = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(A));
56 if (!mat || mat->rows() != mat->cols()) return false;
57 size_t n = mat->rows();
58 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> L_grid(n, std::vector<std::shared_ptr<SymbolicExpr>>(n, SymbolicExpr::number(0)));
59 for (size_t i = 0; i < n; i++) {
60 for (size_t j = 0; j <= i; j++) {
61 auto sum = SymbolicExpr::number(0);
62 for (size_t k = 0; k < j; k++) sum = SymbolicExpr::add(sum, SymbolicExpr::multiply(L_grid[i][k], L_grid[j][k]));
63 auto a_ij = LMCAS::detail::make_expression_ptr(mat->get(i, j));
64 auto diff = SymbolicExpr::add(a_ij, SymbolicExpr::multiply(SymbolicExpr::number(-1), sum));
65 if (i == j) L_grid[i][j] = SymbolicExpr::sqrt(diff);
66 else L_grid[i][j] = SymbolicExpr::divide(diff, L_grid[j][j]);
67 }
68 }
69 L = SymbolicExpr::matrix(L_grid);
70 return true;
71}
72}
73
75 const std::shared_ptr<SymbolicExpr>& A,
77{
78 const std::string operation = "cholesky_decomposition";
79 auto matrix = validate_decomposition_matrix(A, true, context, operation);
80 if (!matrix) return CholeskyDecompositionResult::failure(matrix.error());
81 auto budget = context.consume_steps(matrix.value()->rows() * matrix.value()->cols() * 10 + 8,
82 operation);
83 if (!budget) return CholeskyDecompositionResult::failure(budget.error());
84 auto spd = prove_exact_spd(matrix.value(), context, operation);
85 if (!spd) return CholeskyDecompositionResult::failure(spd.error());
86 try {
87 std::shared_ptr<SymbolicExpr> L;
88 if (!cholesky_decomposition_impl(A, L)) {
91 "Cholesky decomposition could not be constructed in the supported symbolic domain",
92 operation);
93 }
94 auto l_check = validate_decomposition_output(L, "L", operation);
95 if (!l_check) return CholeskyDecompositionResult::failure(l_check.error());
97 } catch (const std::bad_alloc&) {
100 "allocation failed while calculating Cholesky decomposition",
101 operation);
102 } catch (const std::exception& ex) {
104 ex.what(),
105 operation);
106 }
107}
108
110 const std::shared_ptr<SymbolicExpr>& A)
111{
114}
115
116}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< void > prove_exact_spd(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context, const std::string &operation)
static bool cholesky_decomposition_impl(const std::shared_ptr< SymbolicExpr > &A, std::shared_ptr< SymbolicExpr > &L)
Result< std::shared_ptr< const MatrixNode > > validate_decomposition_matrix(const std::shared_ptr< SymbolicExpr > &A, bool require_square, ComputationContext &context, const std::string &operation)
Result< void > validate_decomposition_output(const std::shared_ptr< SymbolicExpr > &expr, const std::string &name, const std::string &operation)
std::optional< std::vector< std::vector< Rational > > > exact_rational_matrix(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< Rational > rational_determinant_exact(std::size_t dimension, std::vector< Rational > values, ComputationContext &context, const std::string &operation)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
const std::vector< FGLMPoly > const MonomialOrder & order
CholeskyDecompositionResult cholesky_decomposition_checked(const std::shared_ptr< SymbolicExpr > &A, ComputationContext &context)
Result< CholeskyDecomposition > CholeskyDecompositionResult