LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
matrix_quadratic_form.cpp
浏览该文件的文档.
6
7#include <optional>
8#include <utility>
9
10namespace LMCAS {
11namespace {
12
13bool valid_variables(const std::vector<std::string>& variables) {
14 if (variables.empty()) return false;
15 for (std::size_t index = 0; index < variables.size(); ++index) {
16 if (variables[index].empty()) return false;
17 for (std::size_t previous = 0; previous < index; ++previous) {
18 if (variables[index] == variables[previous]) return false;
19 }
20 }
21 return true;
22}
23
25 const std::shared_ptr<SymbolicExpr>& expression,
26 const std::vector<std::string>& variables) {
27 if (!expression || !detail::node(expression)) return false;
28 for (const auto& variable : variables) {
30 detail::node(expression), variable)) {
31 return false;
32 }
33 }
34 return true;
35}
36
37std::shared_ptr<SymbolicExpr> reconstruct_quadratic_form(
38 const std::vector<std::vector<std::shared_ptr<SymbolicExpr>>>& matrix,
39 const std::vector<std::shared_ptr<SymbolicExpr>>& variables) {
40 auto reconstructed = SymbolicExpr::number(0);
41 for (std::size_t row = 0; row < matrix.size(); ++row) {
42 for (std::size_t column = 0; column < matrix.size(); ++column) {
43 if (detail::node(matrix[row][column])->is_zero()) continue;
44 auto term = SymbolicExpr::multiply(
45 matrix[row][column],
46 SymbolicExpr::multiply(variables[row], variables[column]));
47 reconstructed = SymbolicExpr::add(reconstructed, term);
48 }
49 }
50 return reconstructed;
51}
52
54 std::vector<std::vector<std::shared_ptr<SymbolicExpr>>>;
55
56std::vector<std::shared_ptr<SymbolicExpr>> make_variables(
57 const std::vector<std::string>& names) {
58 std::vector<std::shared_ptr<SymbolicExpr>> variables;
59 variables.reserve(names.size());
60 for (const auto& name : names) {
61 variables.push_back(SymbolicExpr::variable(name));
62 }
63 return variables;
64}
65
66std::optional<SymbolicMatrix> quadratic_coefficients(
67 const std::shared_ptr<SymbolicExpr>& expanded,
68 const std::vector<std::string>& variables, ComputationContext& context) {
69
70 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
71 (context).limits().max_ast_nodes, "transform");
72 const auto half = SymbolicExpr::number(Rational(1, 2));
73 SymbolicMatrix matrix(
74 variables.size(),
75 std::vector<std::shared_ptr<SymbolicExpr>>(variables.size()));
76 for (std::size_t row = 0; row < variables.size(); ++row) {
77 auto first_derivative = detail::make_expression_ptr(detail::differentiate_node(detail::node(expanded), variables[row], transform_budget));
78 if (!first_derivative) {
79 return std::nullopt;
80 }
81 for (std::size_t column = 0; column < variables.size(); ++column) {
82 auto second_derivative =
83 detail::make_expression_ptr(detail::differentiate_node(detail::node(first_derivative), variables[column], transform_budget));
84 if (!second_derivative) {
85 return std::nullopt;
86 }
87 auto coefficient =
88 detail::make_expression_ptr(detail::normalize_node(detail::node(SymbolicExpr::multiply(half, second_derivative)), transform_budget));
89 if (!independent_of_variables(coefficient, variables)) {
90 return std::nullopt;
91 }
92 matrix[row][column] = std::move(coefficient);
93 }
94 }
95 return matrix;
96}
97
99 const std::shared_ptr<SymbolicExpr>& expanded,
100 const SymbolicMatrix& matrix,
101 const std::vector<std::shared_ptr<SymbolicExpr>>& variables, ComputationContext& context) {
102
103 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
104 (context).limits().max_ast_nodes, "transform");
105 auto reconstructed = reconstruct_quadratic_form(matrix, variables);
106 auto residual = SymbolicExpr::add(
107 expanded,
108 SymbolicExpr::multiply(
109 SymbolicExpr::number(-1), reconstructed));
110 residual = detail::make_expression_ptr(detail::expand_node(detail::node(residual), transform_budget));
111 if (residual) {
112 residual = detail::make_expression_ptr(detail::normalize_node(detail::node(residual), transform_budget));
113 }
114 return residual && detail::node(residual) &&
115 detail::node(residual)->is_zero();
116}
117
118}
119
120std::shared_ptr<SymbolicExpr> quadratic_form_matrix(
121 const std::shared_ptr<SymbolicExpr>& expr,
122 const std::vector<std::string>& vars) {
124 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
125 (context).limits().max_ast_nodes, "transform");
126 if (!expr || !valid_variables(vars)) {
127 return nullptr;
128 }
129
130 try {
131 auto expanded = detail::make_expression_ptr(detail::expand_node(detail::node(expr), transform_budget));
132 if (!expanded) {
133 return nullptr;
134 }
135 auto variables = make_variables(vars);
136 auto matrix = quadratic_coefficients(expanded, vars, context);
137 if (!matrix ||
138 !reconstructs_expression(expanded, *matrix, variables, context)) {
139 return nullptr;
140 }
141 return SymbolicExpr::matrix(*matrix);
142 } catch (const CasError& error) {
143 if (error.code != CasErrc::UnsupportedExpression) throw;
144 return nullptr;
145 }
146}
147
148}
virtual bool is_zero() const
微分访问器,对 AST 执行符号求导。
Extraction of symmetric matrices from homogeneous quadratic forms.
bool reconstructs_expression(const std::shared_ptr< SymbolicExpr > &expanded, const SymbolicMatrix &matrix, const std::vector< std::shared_ptr< SymbolicExpr > > &variables, ComputationContext &context)
std::shared_ptr< SymbolicExpr > reconstruct_quadratic_form(const std::vector< std::vector< std::shared_ptr< SymbolicExpr > > > &matrix, const std::vector< std::shared_ptr< SymbolicExpr > > &variables)
std::optional< SymbolicMatrix > quadratic_coefficients(const std::shared_ptr< SymbolicExpr > &expanded, const std::vector< std::string > &variables, ComputationContext &context)
std::vector< std::vector< std::shared_ptr< SymbolicExpr > > > SymbolicMatrix
std::vector< std::shared_ptr< SymbolicExpr > > make_variables(const std::vector< std::string > &names)
bool independent_of_variables(const std::shared_ptr< SymbolicExpr > &expression, const std::vector< std::string > &variables)
bool valid_variables(const std::vector< std::string > &variables)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr expand_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
__attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorField gradient(const std const std::vector< std::string > & vars
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
std::shared_ptr< SymbolicExpr > quadratic_form_matrix(const std::shared_ptr< SymbolicExpr > &expr, const std::vector< std::string > &vars)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
内部 AST 定义。