LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
matrix_decomposition.cpp
浏览该文件的文档.
3
4#include <algorithm>
5#include <new>
6
7namespace LMCAS {
8using namespace detail::matrix_decomposition;
9namespace {
10std::shared_ptr<SymbolicExpr> abs_expression(const std::shared_ptr<SymbolicExpr>& e) {
12 std::vector<std::shared_ptr<const SymbolicNode>>{detail::node(e)});
13 return detail::make_expression_ptr(node);
14}
15
16struct NormSum {
17 std::shared_ptr<SymbolicExpr> expression;
18 std::optional<Rational> exact;
19};
20
21NormSum matrix_axis_sum(const MatrixNode& matrix, std::size_t axis, bool columns, ComputationContext& context) {
22
23 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
24 (context).limits().max_ast_nodes, "transform");
25 auto sum = SymbolicExpr::number(0);
26 std::optional<Rational> exact_sum = Rational(0);
27 const auto count = columns ? matrix.rows() : matrix.cols();
28 for (std::size_t index = 0; index < count; ++index) {
29 auto entry = detail::make_expression_ptr(columns
30 ? matrix.get(index, axis) : matrix.get(axis, index));
31 sum = SymbolicExpr::add(sum, abs_expression(entry));
32 if (exact_sum) {
33 auto exact_entry = exact_rational_expr(entry, context);
34 if (exact_entry) {
35 *exact_sum = *exact_sum + ((*exact_entry < Rational(0))
36 ? (Rational(0) - *exact_entry) : *exact_entry);
37 } else {
38 exact_sum.reset();
39 }
40 }
41 }
43 return {sum, exact_sum ? exact_sum : exact_rational_expr(sum, context)};
44}
45
46std::shared_ptr<SymbolicExpr> maximum_axis_sum(const MatrixNode& matrix, bool columns, ComputationContext& context) {
47 std::optional<Rational> maximum_exact;
48 std::vector<std::shared_ptr<const SymbolicNode>> candidates;
49 const auto count = columns ? matrix.cols() : matrix.rows();
50 for (std::size_t axis = 0; axis < count; ++axis) {
51 auto candidate = matrix_axis_sum(matrix, axis, columns, context);
52 if (candidate.exact) {
53 if (!maximum_exact || *candidate.exact > *maximum_exact)
54 maximum_exact = *candidate.exact;
55 } else {
56 candidates.push_back(detail::node(candidate.expression));
57 }
58 }
59 if (maximum_exact)
60 candidates.push_back(detail::node(exact_number_expr(*maximum_exact)));
61 if (candidates.empty()) return nullptr;
62 if (candidates.size() == 1) return detail::make_expression_ptr(candidates.front());
64 FunctionNode::FuncType::Max, std::move(candidates)));
65}
66}
67
68std::shared_ptr<SymbolicExpr> matrix_trace(const std::shared_ptr<SymbolicExpr>& A) {
70 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
71 (context).limits().max_ast_nodes, "transform");
72 auto mat = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(A));
73 if (!mat || mat->rows() != mat->cols()) {
74 return nullptr;
75 }
76 auto sum = SymbolicExpr::number(0);
77 for (size_t i = 0; i < mat->rows(); ++i) {
78 sum = SymbolicExpr::add(sum, LMCAS::detail::make_expression_ptr(mat->get(i, i)));
79 }
81}
82std::shared_ptr<SymbolicExpr> kronecker(const std::shared_ptr<SymbolicExpr>& A,
83 const std::shared_ptr<SymbolicExpr>& B) {
85 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
86 (context).limits().max_ast_nodes, "transform");
87 auto a = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(A));
88 auto b = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(B));
89 if (!a || !b) {
90 return nullptr;
91 }
92 size_t m = a->rows(), n = a->cols(), p = b->rows(), q = b->cols();
93 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> grid(m * p,
94 std::vector<std::shared_ptr<SymbolicExpr>>(n * q));
95 for (size_t i = 0; i < m; ++i)
96 for (size_t j = 0; j < n; ++j) {
97 auto aij = LMCAS::detail::make_expression_ptr(a->get(i, j));
98 for (size_t k = 0; k < p; ++k)
99 for (size_t l = 0; l < q; ++l) {
100 auto bkl = LMCAS::detail::make_expression_ptr(b->get(k, l));
101 grid[i * p + k][j * q + l] = detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(aij, bkl)), transform_budget));
102 }
103 }
104 return SymbolicExpr::matrix(grid);
105}
106std::shared_ptr<SymbolicExpr> matrix_norm(const std::shared_ptr<SymbolicExpr>& A,
107 const std::string& type) {
109 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
110 (context).limits().max_ast_nodes, "transform");
111 auto mat = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(A));
112 if (!mat) {
113 return nullptr;
114 }
115 size_t m = mat->rows(), n = mat->cols();
116
117 if (type == "frobenius") {
118 auto sum = SymbolicExpr::number(0);
119 for (size_t i = 0; i < m; ++i)
120 for (size_t j = 0; j < n; ++j) {
121 auto e = LMCAS::detail::make_expression_ptr(mat->get(i, j));
122 sum = SymbolicExpr::add(sum, SymbolicExpr::multiply(e, e));
123 }
124 return detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::sqrt(sum)), transform_budget));
125 }
126 if (type == "1") {
127 return maximum_axis_sum(*mat, true, context);
128 }
129 if (type == "inf") {
130 return maximum_axis_sum(*mat, false, context);
131 }
132 return nullptr;
133}
134
135}
@ Max
最大值 max(a, b)。
矩阵节点,支持稠密和稀疏两种存储方式。
size_t cols() const noexcept
size_t rows() const noexcept
std::shared_ptr< const SymbolicNode > get(size_t r, size_t c) const
获取指定位置的矩阵元素。
std::shared_ptr< SymbolicExpr > maximum_axis_sum(const MatrixNode &matrix, bool columns, ComputationContext &context)
std::shared_ptr< SymbolicExpr > abs_expression(const std::shared_ptr< SymbolicExpr > &e)
NormSum matrix_axis_sum(const MatrixNode &matrix, std::size_t axis, bool columns, ComputationContext &context)
std::shared_ptr< SymbolicExpr > exact_number_expr(const Rational &value)
std::optional< Rational > exact_rational_expr(const std::shared_ptr< const SymbolicNode > &node)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
ExprResult e()
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
std::shared_ptr< SymbolicExpr > matrix_norm(const std::shared_ptr< SymbolicExpr > &A, const std::string &type)
std::shared_ptr< SymbolicExpr > matrix_trace(const std::shared_ptr< SymbolicExpr > &A)
const MultiPoly & b
std::shared_ptr< SymbolicExpr > kronecker(const std::shared_ptr< SymbolicExpr > &A, const std::shared_ptr< SymbolicExpr > &B)
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a