LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
vector_calculus_lagrange.cpp
浏览该文件的文档.
4#include "integration.hpp"
6#include "solver.hpp"
8#include "symbolic_matrix.hpp"
11
12#include <cmath>
13#include <exception>
14#include <map>
15#include <memory>
16#include <set>
17#include <stdexcept>
18#include <string>
19#include <vector>
20
21namespace LMCAS {
22
23using namespace vector_calculus_detail;
24
26 const std::shared_ptr<SymbolicExpr>& f,
27 const std::vector<std::string>& vars, const std::string& operation,
28 detail::RewriteBudget& transform_budget)
29{
31 gradient.reserve(vars.size());
32 for (const auto& var : vars) {
33 auto partial = vector_calculus_differentiate_strict(f, var, operation, transform_budget);
34 if (!partial) {
35 return VectorCalculusFieldResult::failure(partial.error());
36 }
37 gradient.push_back(std::move(partial.value()));
38 }
40}
41
42
43static std::vector<std::string> lagrange_multiplier_names(size_t count)
44{
45 std::vector<std::string> names;
46 names.reserve(count);
47 for (size_t k = 0; k < count; ++k) {
48 names.push_back("lambda_" + std::to_string(k + 1));
49 }
50 return names;
51}
52
53static std::shared_ptr<SymbolicExpr> lagrange_stationarity_equation(
54 const VectorField& gradient, const std::vector<VectorField>& constraints,
55 const std::vector<std::string>& multipliers, size_t index)
56{
57 auto equation = gradient[index];
58 for (size_t k = 0; k < multipliers.size(); ++k) {
59 auto multiplier = SymbolicExpr::variable(multipliers[k]);
60 auto term = SymbolicExpr::multiply(multiplier, constraints[k][index]);
61 equation = SymbolicExpr::add(equation,
62 SymbolicExpr::multiply(SymbolicExpr::number(-1), term));
63 }
64 return equation;
65}
66
68 const VectorField& equations, const std::vector<std::string>& all_vars,
69 ComputationContext& context, const std::string& operation)
70{
71 std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>> full_solutions;
72 std::vector<SymbolicExpr> poly_eqs;
73 poly_eqs.reserve(equations.size());
74 for (const auto& eq : equations) {
75 if (!eq || !LMCAS::detail::node(eq)) {
78 "Lagrange equation construction failed in the supported domain",
79 operation);
80 }
81 poly_eqs.push_back(*eq);
82 }
83
84 auto checked_solutions =
85 Solver::solve_polynomial_system_checked(poly_eqs, all_vars, context);
86 if (!checked_solutions) return LagrangeResult::failure(checked_solutions.error());
87 const auto& poly_solutions = checked_solutions.value();
88 for (const auto& sol : poly_solutions) {
89 std::map<std::string, std::shared_ptr<SymbolicExpr>> pt;
90 for (const auto& [name, val] : sol) {
92 }
93 full_solutions.push_back(std::move(pt));
94 }
95
96 return LagrangeResult::success(std::move(full_solutions));
97}
98
100 const std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>>& full_solutions,
101 const VectorField& equations, const std::vector<std::string>& all_vars,
102 const std::vector<std::string>& vars, ComputationContext& context, const std::string& operation,
103 detail::RewriteBudget& transform_budget)
104{
105 std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>> verified;
106 std::set<std::string> var_set(vars.begin(), vars.end());
107 for (const auto& full_solution : full_solutions) {
108 if (!vector_calculus_point_has_vars(full_solution, all_vars)) {
111 "Lagrange candidate omits one or more variables or multipliers",
112 operation);
113 }
114 for (const auto& eq : equations) {
115 auto residual = eq;
116 for (const auto& [variable, value] : full_solution)
118 auto proof = check_zero_residual(residual, context);
119 if (!proof) return LagrangeResult::failure(proof.error());
120 if (!std::holds_alternative<ProvedZeroResidual>(proof.value())) {
123 "Lagrange candidate does not verify against the full stationarity system",
124 operation);
125 }
126 }
127
128 std::map<std::string, std::shared_ptr<SymbolicExpr>> filtered;
129 for (const auto& [name, val] : full_solution) {
130 if (var_set.count(name)) {
131 filtered[name] = val;
132 }
133 }
134 if (!vector_calculus_point_has_vars(filtered, vars)) {
137 "Lagrange candidate omits one or more variables",
138 operation);
139 }
140 verified.push_back(std::move(filtered));
141 }
142
143 return LagrangeResult::success(std::move(verified));
144}
145
146
148 const std::shared_ptr<SymbolicExpr>& f,
149 const std::vector<std::shared_ptr<SymbolicExpr>>& constraints,
150 const std::vector<std::string>& vars, ComputationContext& context, const std::string& operation,
151 detail::RewriteBudget& transform_budget)
152{
153 const size_t n = vars.size();
154 const size_t m = constraints.size();
155 auto gradient = lagrange_gradient_strict(f, vars, operation, transform_budget);
156 if (!gradient) {
157 return LagrangeResult::failure(gradient.error());
158 }
159 std::vector<VectorField> grad_constraints;
160 grad_constraints.reserve(m);
161 for (const auto& constraint : constraints) {
162 auto partials = lagrange_gradient_strict(constraint, vars, operation, transform_budget);
163 if (!partials) {
164 return LagrangeResult::failure(partials.error());
165 }
166 grad_constraints.push_back(std::move(partials.value()));
167 }
168 auto lambda_names = lagrange_multiplier_names(m);
169 VectorField equations;
170 equations.reserve(n + m);
171 for (size_t i = 0; i < n; ++i) {
172 auto equation = lagrange_stationarity_equation(
173 gradient.value(), grad_constraints, lambda_names, i);
174 auto checked = vector_calculus_simplify_strict(equation, operation,
175 "Lagrange stationarity equation is outside the supported domain", transform_budget);
176 if (!checked) {
177 return LagrangeResult::failure(checked.error());
178 }
179 equations.push_back(std::move(checked.value()));
180 }
181 for (const auto& constraint : constraints) equations.push_back(constraint);
182 std::vector<std::string> all_vars;
183 all_vars.reserve(n + m);
184 all_vars.insert(all_vars.end(), vars.begin(), vars.end());
185 all_vars.insert(all_vars.end(), lambda_names.begin(), lambda_names.end());
186 auto solutions = solve_lagrange_strict(equations, all_vars, context, operation);
187 if (!solutions) {
188 return solutions;
189 }
190 return verify_lagrange_solutions(solutions.value(), equations, all_vars, vars, context, operation, transform_budget);
191}
192
194 const std::shared_ptr<SymbolicExpr>& f,
195 const std::vector<std::shared_ptr<SymbolicExpr>>& constraints,
196 const std::vector<std::string>& vars,
198{
199 detail::RewriteBudget transform_budget(context, context.limits().max_recursion_depth,
200 context.limits().max_ast_nodes, "lagrange_multipliers");
201 const std::string operation = "lagrange_multipliers";
202 auto valid = vector_calculus_validate_expr_vars(f, vars, context, operation);
203 if (!valid) {
204 return LagrangeResult::failure(valid.error());
205 }
206 auto distinct = vector_calculus_validate_distinct_vars(vars, vars.size(), context, operation);
207 if (!distinct) {
208 return LagrangeResult::failure(distinct.error());
209 }
210 if (constraints.empty()) {
212 "constraint list cannot be empty",
213 operation);
214 }
215 for (const auto& constraint : constraints) {
216 if (!constraint || !LMCAS::detail::node(constraint)) {
218 "constraint expressions cannot be null",
219 operation);
220 }
221 }
222 auto step = context.consume_steps(vars.size() * constraints.size() * 6 +
223 vars.size() * 6 + constraints.size() * 4 + 8,
224 operation);
225 if (!step) {
226 return LagrangeResult::failure(step.error());
227 }
228
229 try {
230 return lagrange_multipliers_strict(f, constraints, vars, context, operation, transform_budget);
231 } catch (const CasError& error) {
232 return LagrangeResult::failure(error);
233 } catch (const std::bad_alloc&) {
235 "Lagrange multiplier allocation failed",
236 operation);
237 } catch (const std::length_error& error) {
238 return LagrangeResult::failure(CasErrc::ResourceLimit, error.what(), operation);
239 } catch (const std::exception& e) {
240 return LagrangeResult::failure(CasErrc::InternalInvariant, e.what(), operation);
241 }
242}
243
245 const std::shared_ptr<SymbolicExpr>& f,
246 const std::vector<std::shared_ptr<SymbolicExpr>>& constraints,
247 const std::vector<std::string>& vars)
248{
250 return lagrange_multipliers_checked(f, constraints, vars, context);
251}
252std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>> lagrange_multipliers(
253 const std::shared_ptr<SymbolicExpr>& f,
254 const std::vector<std::shared_ptr<SymbolicExpr>>& constraints,
255 const std::vector<std::string>& vars)
256{
257 auto result = lagrange_multipliers_checked(f, constraints, vars);
258 if (!result && result.error().code != CasErrc::Inconclusive &&
259 result.error().code != CasErrc::UnsupportedExpression &&
260 result.error().code != CasErrc::DomainError) {
261 throw result.error();
262 }
263 return result ? std::move(result.value()) :
264 std::vector<std::map<std::string, std::shared_ptr<SymbolicExpr>>>{};
265}
266
267}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(VectorField value)
Symbolic integration APIs.
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
bool vector_calculus_point_has_vars(const std::map< std::string, std::shared_ptr< SymbolicExpr > > &point, const std::vector< std::string > &vars)
Result< void > vector_calculus_validate_distinct_vars(const std::vector< std::string > &vars, std::size_t expected, ComputationContext &context, const std::string &operation)
Result< void > vector_calculus_validate_expr_vars(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation)
VectorCalculusExprResult vector_calculus_differentiate_strict(const std::shared_ptr< SymbolicExpr > &expr, const std::string &variable, const std::string &operation, detail::RewriteBudget &transform_budget)
VectorCalculusExprResult vector_calculus_simplify_strict(const std::shared_ptr< SymbolicExpr > &expr, const std::string &operation, const std::string &message, detail::RewriteBudget &transform_budget)
const std::string & variable
ExprResult eq(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
static LagrangeResult solve_lagrange_strict(const VectorField &equations, const std::vector< std::string > &all_vars, ComputationContext &context, const std::string &operation)
ExprResult e()
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
static VectorCalculusFieldResult lagrange_gradient_strict(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, const std::string &operation, detail::RewriteBudget &transform_budget)
static std::vector< std::string > lagrange_multiplier_names(size_t count)
Result< std::vector< std::map< std::string, std::shared_ptr< SymbolicExpr > > > > LagrangeResult
static LagrangeResult verify_lagrange_solutions(const std::vector< std::map< std::string, std::shared_ptr< SymbolicExpr > > > &full_solutions, const VectorField &equations, const std::vector< std::string > &all_vars, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation, detail::RewriteBudget &transform_budget)
LagrangeResult lagrange_multipliers_checked(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::shared_ptr< SymbolicExpr > > &constraints, const std::vector< std::string > &vars, ComputationContext &context)
std::vector< std::shared_ptr< SymbolicExpr > > VectorField
向量场由标量表达式组成。
Result< VectorField > VectorCalculusFieldResult
static LagrangeResult lagrange_multipliers_strict(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::shared_ptr< SymbolicExpr > > &constraints, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation, detail::RewriteBudget &transform_budget)
ResidualCheckResult check_zero_residual(const ExprPtr &residual, ComputationContext &context, const LMCAS::EqvOptions &options)
const std::string const ExprPtr & value
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
std::vector< std::map< std::string, std::shared_ptr< SymbolicExpr > > > lagrange_multipliers(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::shared_ptr< SymbolicExpr > > &constraints, const std::vector< std::string > &vars)
static std::shared_ptr< SymbolicExpr > lagrange_stationarity_equation(const VectorField &gradient, const std::vector< VectorField > &constraints, const std::vector< std::string > &multipliers, size_t index)
VectorField gradient(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars)
方程求解策略调度器 solve_dispatch 及相关选项结构体.
多项式方程组求解器 Solver,包含 Gröbner 基、线性系统求解。
内部 AST 定义。
符号矩阵运算:乘法、行列式、逆、旋转/反射/缩放矩阵、特征值。