LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
matrix_decomposition_support.cpp
浏览该文件的文档.
4
7 const std::shared_ptr<SymbolicExpr>& A,
8 bool require_square,
10 const std::string& operation)
11{
12 auto step = context.consume_steps(1, operation);
13 if (!step) return Result<std::shared_ptr<const MatrixNode>>::failure(step.error());
14 if (!A || !LMCAS::detail::node(A)) {
17 "matrix input cannot be null",
18 operation);
19 }
20 auto matrix = std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(A));
21 if (!matrix) {
24 "input must be a matrix",
25 operation);
26 }
27 if (require_square && matrix->rows() != matrix->cols()) {
30 "matrix must be square",
31 operation);
32 }
33 return Result<std::shared_ptr<const MatrixNode>>::success(matrix);
34}
35
37 const std::shared_ptr<SymbolicExpr>& expr,
38 const std::string& name,
39 const std::string& operation)
40{
41 if (!expr || !LMCAS::detail::node(expr) ||
42 !std::dynamic_pointer_cast<const MatrixNode>(LMCAS::detail::node(expr))) {
45 name + " output is not a matrix",
46 operation);
47 }
48 return Result<void>::success();
49}
50namespace {
51std::optional<Rational> exact_rational_sum(const AddNode& add) {
52 Rational sum(0);
53 for (const auto& operand : add.operands()) {
54 auto value = exact_rational_expr(operand);
55 if (!value) return std::nullopt;
56 sum = sum + *value;
57 }
58 return sum;
59}
60
61std::optional<Rational> exact_rational_product(const MultiplyNode& mul) {
62 Rational product(1);
63 for (const auto& operand : mul.operands()) {
64 auto value = exact_rational_expr(operand);
65 if (!value) return std::nullopt;
66 product = product * *value;
67 }
68 return product;
69}
70}
71
72std::optional<Rational> exact_rational_expr(const std::shared_ptr<const SymbolicNode>& node) {
73 if (!node) return std::nullopt;
74 if (auto number = std::dynamic_pointer_cast<const NumberNode>(node)) {
76 }
77 if (auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
78 return exact_rational_sum(*add);
79 }
80 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
81 return exact_rational_product(*mul);
82 }
83 if (auto fn = std::dynamic_pointer_cast<const FunctionNode>(node)) {
84 if (fn->type() == FunctionNode::FuncType::Abs && fn->arguments().size() == 1) {
85 auto value = exact_rational_expr(fn->arguments()[0]);
86 if (!value) return std::nullopt;
87 return (*value < Rational(0)) ? (Rational(0) - *value) : *value;
88 }
89 }
90 return std::nullopt;
91}
92
93namespace {
94std::optional<Rational> simplify_exact_rational_expr(
95 const std::shared_ptr<const SymbolicNode>& node, ComputationContext& context) {
96
97 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
98 (context).limits().max_ast_nodes, "transform");
100 auto simplified = detail::make_expression_ptr(detail::normalize_node(detail::node(expression), transform_budget));
101 return simplified
103 : std::nullopt;
104}
105}
106
107std::optional<Rational> exact_rational_expr(const std::shared_ptr<SymbolicExpr>& expr, ComputationContext& context) {
108 if (!expr || !LMCAS::detail::node(expr)) return std::nullopt;
109 const auto& node = LMCAS::detail::node(expr);
110 if (auto direct = exact_rational_expr(node)) return direct;
111 return simplify_exact_rational_expr(node, context);
112}
113
114std::shared_ptr<SymbolicExpr> exact_number_expr(const Rational& value) {
115 if (value.get_denominator() == BigInt(1)) {
118 }
121}
122
123std::optional<std::vector<std::vector<Rational>>> exact_rational_matrix(
124 const std::shared_ptr<const MatrixNode>& matrix, ComputationContext& context) {
125 if (!matrix) return std::nullopt;
126 std::vector<std::vector<Rational>> values(
127 matrix->rows(), std::vector<Rational>(matrix->cols(), Rational(0)));
128 for (size_t row = 0; row < matrix->rows(); ++row) {
129 for (size_t col = 0; col < matrix->cols(); ++col) {
130 const auto& node = matrix->get(row, col);
132 if (!value) {
133 value = simplify_exact_rational_expr(node, context);
134 }
135 if (!value) return std::nullopt;
136 values[row][col] = *value;
137 }
138 }
139 return values;
140}
141std::shared_ptr<SymbolicExpr> identity_matrix_expr(size_t n) {
142 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> grid(
143 n, std::vector<std::shared_ptr<SymbolicExpr>>(n, SymbolicExpr::number(0)));
144 for (size_t i = 0; i < n; ++i) {
145 grid[i][i] = SymbolicExpr::number(1);
146 }
147 return SymbolicExpr::matrix(grid);
148}
149
150std::optional<std::vector<Rational>> exact_rectangular_diagonal_entries(
151 const std::shared_ptr<const MatrixNode>& matrix, ComputationContext& context) {
152 auto values = exact_rational_matrix(matrix, context);
153 if (!values) return std::nullopt;
154 const size_t rows = values->size();
155 const size_t cols = rows == 0 ? 0 : (*values)[0].size();
156 const size_t diag_count = std::min(rows, cols);
157 std::vector<Rational> diagonal(diag_count, Rational(0));
158 for (size_t row = 0; row < rows; ++row) {
159 for (size_t col = 0; col < cols; ++col) {
160 const bool is_diag = row == col && row < diag_count;
161 if (!is_diag && (*values)[row][col] != Rational(0)) {
162 return std::nullopt;
163 }
164 if (is_diag) {
165 diagonal[row] = (*values)[row][col];
166 }
167 }
168 }
169 return diagonal;
170}
171
172std::optional<std::vector<Rational>> exact_diagonal_entries(
173 const std::shared_ptr<const MatrixNode>& matrix, ComputationContext& context) {
174 auto values = exact_rational_matrix(matrix, context);
175 if (!values) return std::nullopt;
176 const size_t rows = values->size();
177 const size_t cols = rows == 0 ? 0 : (*values)[0].size();
178 if (rows != cols) return std::nullopt;
179 std::vector<Rational> diagonal(rows, Rational(0));
180 for (size_t row = 0; row < rows; ++row) {
181 for (size_t col = 0; col < cols; ++col) {
182 if (row == col) {
183 diagonal[row] = (*values)[row][col];
184 } else if ((*values)[row][col] != Rational(0)) {
185 return std::nullopt;
186 }
187 }
188 }
189 return diagonal;
190}
191
192std::shared_ptr<SymbolicExpr> rectangular_diagonal_expr(
193 size_t rows,
194 size_t cols,
195 const std::vector<Rational>& diagonal) {
196 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>> grid(
197 rows, std::vector<std::shared_ptr<SymbolicExpr>>(cols, SymbolicExpr::number(0)));
198 for (size_t i = 0; i < diagonal.size(); ++i) {
199 grid[i][i] = exact_number_expr(diagonal[i]);
200 }
201 return SymbolicExpr::matrix(grid);
202}
203
204}
加法节点,表示多个操作数的求和。
乘法节点,表示多个操作数的乘积。
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
std::optional< Rational > simplify_exact_rational_expr(const std::shared_ptr< const SymbolicNode > &node, ComputationContext &context)
std::shared_ptr< SymbolicExpr > identity_matrix_expr(std::size_t n)
std::shared_ptr< SymbolicExpr > exact_number_expr(const Rational &value)
std::optional< Rational > exact_rational_expr(const std::shared_ptr< const SymbolicNode > &node)
std::optional< std::vector< Rational > > exact_diagonal_entries(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
std::shared_ptr< SymbolicExpr > rectangular_diagonal_expr(std::size_t rows, std::size_t cols, const std::vector< Rational > &diagonal)
Result< std::shared_ptr< const MatrixNode > > validate_decomposition_matrix(const std::shared_ptr< SymbolicExpr > &A, bool require_square, ComputationContext &context, const std::string &operation)
std::optional< std::vector< Rational > > exact_rectangular_diagonal_entries(const std::shared_ptr< const MatrixNode > &matrix, ComputationContext &context)
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
std::shared_ptr< const Node > make_node(Args &&... args)
ComputationContext const std::string & operation
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::size_t std::size_t ComputationContext & context
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const std::string const ExprPtr & value
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name