LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
ode_support.cpp
浏览该文件的文档.
1/**
2 * @file ode_support.cpp
3 * @brief ODE 输入检查与结果处理的共享约定。
4 */
7#include "symbolic.hpp"
8#include "lmmc/config.h"
10#include <cmath>
11#include <memory>
12#include <string>
13#include <limits>
14#include <vector>
15
16namespace LMCAS {
17
18
19/**
20 * @internal
21 * @brief 尝试将表达式求值为 double。
22 * @return 若表达式为纯数值返回其值,否则返回 NaN。
23 */
24double try_eval_double(const std::shared_ptr<SymbolicExpr>& expr) {
25 if (!expr || !LMCAS::detail::node(expr)) {
26 return std::numeric_limits<double>::quiet_NaN();
27 }
28 if (expr->is_number()) {
29 auto node = std::dynamic_pointer_cast<const NumberNode>(LMCAS::detail::node(expr));
30 if (!node) {
31 return std::numeric_limits<double>::quiet_NaN();
32 }
33 if (std::holds_alternative<BigInt>(node->value())) {
34 return std::get<BigInt>(node->value()).to_double();
35 }
36 return std::get<Rational>(node->value()).to_double();
37 }
38 return std::numeric_limits<double>::quiet_NaN();
39}
40
42 const std::shared_ptr<SymbolicExpr>& expr,
43 const std::string& x,
44 const std::string& y,
46 const std::string& operation)
47{
48 auto step = context.consume_steps(1, operation);
49 if (!step) {
50 return step;
51 }
52 if (!expr || !LMCAS::detail::node(expr)) {
54 "ODE expression cannot be null",
55 operation);
56 }
57 if (x.empty() || y.empty()) {
59 "ODE variable names cannot be empty",
60 operation);
61 }
62 if (x == y) {
64 "ODE independent and dependent variables must be distinct",
65 operation);
66 }
67 return Result<void>::success();
68}
69
71 const std::shared_ptr<SymbolicExpr>& first,
72 const std::shared_ptr<SymbolicExpr>& second,
73 const std::string& x,
74 const std::string& y,
76 const std::string& operation)
77{
78 auto step = context.consume_steps(1, operation);
79 if (!step) {
80 return step;
81 }
82 if (!first || !LMCAS::detail::node(first) || !second || !LMCAS::detail::node(second)) {
84 "ODE expressions cannot be null",
85 operation);
86 }
87 if (x.empty() || y.empty()) {
89 "ODE variable names cannot be empty",
90 operation);
91 }
92 if (x == y) {
94 "ODE independent and dependent variables must be distinct",
95 operation);
96 }
97 return Result<void>::success();
98}
99
101 ODEType expected_method,
102 const std::string& operation)
103{
104 if (!solution.general_solution || !LMCAS::detail::node(solution.general_solution)) {
107 "ODE solver produced no solution in the supported domain",
108 operation);
109 }
110 if (solution.method_used != expected_method) {
113 "ODE solver reported an unexpected method",
114 operation);
115 }
116 return ODESolutionResult::success(std::move(solution));
117}
118
120 const std::string& x,
121 const std::string& y,
123 const std::string& operation)
124{
125 auto step = context.consume_steps(1, operation);
126 if (!step) {
127 return step;
128 }
129 if (x.empty() || y.empty()) {
131 "ODE variable names cannot be empty",
132 operation);
133 }
134 if (x == y) {
136 "ODE independent and dependent variables must be distinct",
137 operation);
138 }
139 return Result<void>::success();
140}
141
143 const std::vector<double>& coeffs,
144 std::size_t min_size,
145 std::size_t max_size,
146 const std::string& operation)
147{
148 if (coeffs.size() < min_size || coeffs.size() > max_size) {
150 "ODE coefficient list has unsupported size",
151 operation);
152 }
153 if (!std::isfinite(coeffs.front()) || coeffs.front() == 0.0) {
155 "ODE leading coefficient must be finite and nonzero",
156 operation);
157 }
158 for (double coeff : coeffs) {
159 if (!std::isfinite(coeff)) {
161 "ODE coefficients must be finite",
162 operation);
163 }
164 }
165 return Result<void>::success();
166}
167
169 const std::shared_ptr<SymbolicExpr>& first,
170 const std::shared_ptr<SymbolicExpr>& second,
171 const std::shared_ptr<SymbolicExpr>& third,
172 const std::string& x,
174 const std::string& operation)
175{
176 auto step = context.consume_steps(1, operation);
177 if (!step) {
178 return step;
179 }
180 if (!first || !LMCAS::detail::node(first) || !second || !LMCAS::detail::node(second) ||
181 !third || !LMCAS::detail::node(third)) {
183 "ODE expressions cannot be null",
184 operation);
185 }
186 if (x.empty()) {
188 "ODE variable name cannot be empty",
189 operation);
190 }
191 return Result<void>::success();
192}
193
195 const std::shared_ptr<SymbolicExpr>& p,
196 const std::shared_ptr<SymbolicExpr>& q,
197 const std::shared_ptr<SymbolicExpr>& x0,
198 const std::string& x,
200 const std::string& operation)
201{
202 auto step = context.consume_steps(1, operation);
203 if (!step) {
204 return step;
205 }
206 if (!p || !LMCAS::detail::node(p) || !q || !LMCAS::detail::node(q) || !x0 || !LMCAS::detail::node(x0)) {
208 "Frobenius inputs cannot be null",
209 operation);
210 }
211 if (x.empty()) {
213 "ODE variable name cannot be empty",
214 operation);
215 }
216 return Result<void>::success();
217}
218
219}
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
Result< void > validate_ode_expr_var_pair(const std::shared_ptr< SymbolicExpr > &expr, const std::string &x, const std::string &y, ComputationContext &context, const std::string &operation)
ODESolutionResult wrap_ode_solution(ODESolution solution, ODEType expected_method, const std::string &operation)
ODEType method_used
使用的求解方法
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ODEType
ODE 类型枚举,标识方程所属的求解类别.
double try_eval_double(const std::shared_ptr< SymbolicExpr > &expression)
尝试将表达式求值为 double。
Result< void > validate_ode_three_expr_one_var(const std::shared_ptr< SymbolicExpr > &first, const std::shared_ptr< SymbolicExpr > &second, const std::shared_ptr< SymbolicExpr > &third, const std::string &x, ComputationContext &context, const std::string &operation)
std::shared_ptr< SymbolicExpr > general_solution
通解表达式
Result< void > validate_numeric_ode_coefficients(const std::vector< double > &coefficients, std::size_t minimum_size, std::size_t maximum_size, const std::string &operation)
Result< void > validate_ode_variables(const std::string &x, const std::string &y, ComputationContext &context, const std::string &operation)
Result< void > validate_ode_two_expr_point(const std::shared_ptr< SymbolicExpr > &p, const std::shared_ptr< SymbolicExpr > &q, const std::shared_ptr< SymbolicExpr > &x0, const std::string &x, ComputationContext &context, const std::string &operation)
Result< void > validate_ode_pair_var_pair(const std::shared_ptr< SymbolicExpr > &first, const std::shared_ptr< SymbolicExpr > &second, const std::string &x, const std::string &y, ComputationContext &context, const std::string &operation)
Result< ODESolution > ODESolutionResult
符号表达式主类 SymbolicExpr 及其工厂方法,运算接口.
内部 AST 定义。
统一 ODE 求解引擎:分类,分派,多种求解方法.