12 const std::shared_ptr<const MatrixNode>& matrix,
14 const std::string& operation) {
19 "QR input is outside the exact rational full-column-rank support domain",
22 const size_t rows = values->size();
23 const size_t cols = rows == 0 ? 0 : (*values)[0].size();
27 "QR decomposition requires at least as many rows as columns in the supported domain",
30 std::vector<std::vector<Rational>> gram(
31 cols, std::vector<Rational>(cols, Rational(0)));
32 for (
size_t i = 0; i < cols; ++i) {
33 for (
size_t j = 0; j < cols; ++j) {
35 for (
size_t row = 0; row < rows; ++row) {
36 sum = sum + (*values)[row][i] * (*values)[row][j];
42 std::vector<Rational> leading;
44 for (
size_t row = 0; row <
order; ++row) {
45 for (
size_t col = 0; col <
order; ++col) {
46 leading.push_back(gram[row][col]);
52 if (determinant.value() <= Rational(0)) {
55 "QR decomposition requires proven full column rank",
62 const std::shared_ptr<SymbolicExpr>& A,
63 std::shared_ptr<SymbolicExpr>& Q,
64 std::shared_ptr<SymbolicExpr>& R) {
66 if (!mat)
return false;
67 size_t m = mat->rows();
68 size_t n = mat->cols();
70 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> Q_grid(m, std::vector<std::shared_ptr<SymbolicExpr>>(n, SymbolicExpr::number(0)));
71 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> R_grid(n, std::vector<std::shared_ptr<SymbolicExpr>>(n, SymbolicExpr::number(0)));
73 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> A_cols(n, std::vector<std::shared_ptr<SymbolicExpr>>(m));
74 for (
size_t j = 0; j < n; j++) {
78 for (
size_t j = 0; j < n; j++) {
79 std::vector<std::shared_ptr<SymbolicExpr>> u_j = A_cols[j];
80 for (
size_t i = 0; i < j; i++) {
81 auto dot = SymbolicExpr::number(0);
82 for (
size_t k = 0; k < m; k++) dot = SymbolicExpr::add(dot, SymbolicExpr::multiply(Q_grid[k][i], A_cols[j][k]));
85 for (
size_t k = 0; k < m; k++) {
86 u_j[k] = SymbolicExpr::add(u_j[k], SymbolicExpr::multiply(SymbolicExpr::number(-1), SymbolicExpr::multiply(R_grid[i][j], Q_grid[k][i])));
90 auto norm_sq = SymbolicExpr::number(0);
91 for (
size_t k = 0; k < m; k++) norm_sq = SymbolicExpr::add(norm_sq, SymbolicExpr::multiply(u_j[k], u_j[k]));
92 R_grid[j][j] = SymbolicExpr::sqrt(norm_sq);
94 for (
size_t k = 0; k < m; k++) Q_grid[k][j] = SymbolicExpr::divide(u_j[k], R_grid[j][j]);
97 Q = SymbolicExpr::matrix(Q_grid);
98 R = SymbolicExpr::matrix(R_grid);