LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
transcendental_polynomial.cpp
浏览该文件的文档.
1#include <stdexcept>
5#include "poly_utils.hpp"
8
9#include <string>
10#include <vector>
11#include <unordered_set>
12#include <limits>
13#include <cstdint>
14
15namespace LMCAS {
16
17static int tf_power_degree(const PowerNode& power, const std::string& var) {
18 auto exp_num = std::dynamic_pointer_cast<const NumberNode>(power.exponent());
19 if (!exp_num) return -1;
20
21 BigInt exponent(-1);
22 if (std::holds_alternative<BigInt>(exp_num->value())) {
23 exponent = std::get<BigInt>(exp_num->value());
24 } else {
25 const auto& r = std::get<Rational>(exp_num->value());
26 if (r.is_integer()) exponent = r.to_bigint();
27 }
28
29 if (exponent.is_negative() || exponent > BigInt(std::numeric_limits<int>::max())) {
30 return -1;
31 }
32 const int e_val = static_cast<int>(exponent.try_to_int64().value());
33
34 int base_deg = tf_degree_in(power.base(), var);
35 if (base_deg < 0 ||
36 (e_val != 0 && base_deg > std::numeric_limits<int>::max() / e_val)) return -1;
37 return base_deg * e_val;
38}
39
40int tf_degree_in(const std::shared_ptr<const SymbolicNode>& node, const std::string& var) {
41 if (!node) return 0;
42
43 if (!expression_depends_on_variable(node, var)) return 0;
44
45 if (auto v = std::dynamic_pointer_cast<const VariableNode>(node)) {
46 return (!v->is_constant() && v->name() == var) ? 1 : 0;
47 }
48
49 if (auto add = std::dynamic_pointer_cast<const AddNode>(node)) {
50 int max_deg = 0;
51 for (const auto& op : add->operands()) {
52 int d = tf_degree_in(op, var);
53 if (d < 0) return -1;
54 max_deg = std::max(max_deg, d);
55 }
56 return max_deg;
57 }
58
59 if (auto mul = std::dynamic_pointer_cast<const MultiplyNode>(node)) {
60 int total_deg = 0;
61 for (const auto& op : mul->operands()) {
62 int d = tf_degree_in(op, var);
63 if (d < 0) return -1;
64 if (d > std::numeric_limits<int>::max() - total_deg) return -1;
65 total_deg += d;
66 }
67 return total_deg;
68 }
69
70 if (auto power = std::dynamic_pointer_cast<const PowerNode>(node)) {
71 return tf_power_degree(*power, var);
72 }
73 if (std::dynamic_pointer_cast<const FunctionNode>(node)) {
74 return -1;
75 }
76
77 return 0;
78}
79
80/**
81 * @brief 判断换元式是否为候选变量的多项式。
82 * 各候选变量的次数须可确定为非负整数,且超越函数不得依赖不定元或原始变量。
83 * @param[in] poly_expr 换元后的表达式。
84 * @param[in] all_variables 所有候选变量名,包括不定元和原始变量。
85 * @return 有效多项式返回 true。
86 * @internal
87 */
89 const std::shared_ptr<SymbolicExpr>& poly_expr,
90 const std::vector<std::string>& all_variables) {
91
92 if (!poly_expr || !LMCAS::detail::node(poly_expr)) return false;
93
94 for (const auto& var : all_variables) {
96 int deg = tf_degree_in(LMCAS::detail::node(poly_expr), var);
97 if (deg < 0) return false;
98 }
99 }
100 return true;
101}
102
103static std::vector<std::string> tf_polynomial_variables(
104 const std::shared_ptr<SymbolicExpr>& expression,
105 const std::vector<std::string>& indeterminates, const std::string& original_var) {
106 std::vector<std::string> variables;
107 for (const auto& variable : indeterminates) {
109 variables.push_back(variable);
110 }
111 }
112 if (expression_depends_on_variable(detail::node(expression), original_var)) {
113 variables.push_back(original_var);
114 }
115 return variables;
116}
117
119 const std::shared_ptr<SymbolicExpr>& expanded,
120 const std::vector<std::string>& variables, int& max_degree) {
121 for (const auto& variable : variables) {
122 const int degree = tf_degree_in(detail::node(expanded), variable);
123 if (degree > max_degree) {
124 max_degree = degree;
125 result.main_variable = variable;
126 }
127 }
128 for (const auto& variable : variables) {
129 if (variable != result.main_variable) result.param_variables.push_back(variable);
130 }
131}
132
134 TfPolyBuildResult result, const std::shared_ptr<SymbolicExpr>& expanded,
135 const std::vector<std::string>& all_variables) {
136 const auto main_var = result.main_variable;
137 auto converted = symbolic_to_poly<Rational>(expanded, main_var);
138 if (converted) {
139 result.poly = std::move(converted.value());
140 result.success = true;
141 return result;
142 }
143 if (converted.error().code != CasErrc::UnsupportedExpression) {
144 return Result<TfPolyBuildResult>::failure(converted.error());
145 }
146 for (const auto& var : all_variables) {
147 if (var == main_var) continue;
148 auto trial = symbolic_to_poly<Rational>(expanded, var);
149 if (!trial) {
150 if (trial.error().code == CasErrc::UnsupportedExpression) continue;
151 return Result<TfPolyBuildResult>::failure(trial.error());
152 }
153 result.main_variable = var;
154 result.poly = std::move(trial.value());
155 result.param_variables.clear();
156 for (const auto& other : all_variables) {
157 if (other != var) result.param_variables.push_back(other);
158 }
159 result.success = true;
160 return result;
161 }
162 result.success = false;
163 return result;
164}
165
167 const std::shared_ptr<SymbolicExpr>& poly_expr,
168 const std::vector<std::string>& indeterminates,
169 const std::string& original_var) {
171 return tf_build_polynomial_impl(poly_expr, indeterminates, original_var, context);
172}
173
175 const std::shared_ptr<SymbolicExpr>& poly_expr,
176 const std::vector<std::string>& indeterminates,
177 const std::string& original_var, ComputationContext& context) try {
178 detail::RewriteBudget transform_budget(context, context.limits().max_recursion_depth,
179 context.limits().max_ast_nodes,
180 "tf_build_polynomial");
181 TfPolyBuildResult result;
182 result.success = false;
183
184 if (!poly_expr || !LMCAS::detail::node(poly_expr) || original_var.empty()) {
186 "expression and variable must be nonempty", "tf_build_polynomial");
187 }
188
189 auto before = tf_polynomial_variables(poly_expr, indeterminates, original_var);
190 if (!before.empty() && !tf_validate_polynomial(poly_expr, before)) return result;
191 auto expanded = detail::make_expression_ptr(detail::expand_node(detail::node(poly_expr), transform_budget));
192 if (!expanded || !LMCAS::detail::node(expanded)) {
193 expanded = poly_expr;
194 }
195 auto all_variables = tf_polynomial_variables(expanded, indeterminates, original_var);
196 if (all_variables.empty()) {
197 auto c = extract_coeff_value<Rational>(expanded);
198 if (!c) {
199 if (c.error().code == CasErrc::UnsupportedExpression) return result;
201 }
202 result.poly = Polynomial<Rational>({std::move(c.value())}, "x");
203 result.main_variable = "x";
204 result.success = true;
205 return result;
206 }
207
208 if (!tf_validate_polynomial(expanded, all_variables)) {
209 return result;
210 }
211 int max_degree = -1;
212 tf_select_main_variable(result, expanded, all_variables, max_degree);
213 if (result.main_variable.empty() || max_degree < 0) return result;
214 return tf_convert_main_variable(std::move(result), expanded, all_variables);
215}
216catch (const CasError& error) { return Result<TfPolyBuildResult>::failure(error); } catch (const std::bad_alloc&) {
218 "allocation failed while constructing polynomial", "tf_build_polynomial");
219} catch (const std::length_error& error) { return Result<TfPolyBuildResult>::failure(CasErrc::ResourceLimit, error.what(), "tf_build_polynomial"); } catch (const std::exception& ex) {
221 ex.what(), "tf_build_polynomial");
222}
223
224}
一元多项式模板类
幂运算节点,表示 base^exponent。
const std::shared_ptr< const SymbolicNode > & exponent() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
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
const std::string & variable
__attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std std::shared_ptr< SymbolicExpr > r
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
Result< TfPolyBuildResult > tf_build_polynomial_impl(const std::shared_ptr< SymbolicExpr > &expression, const std::vector< std::string > &indeterminates, const std::string &original_variable, ComputationContext &context)
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const VectorField const VectorField & c
static bool tf_validate_polynomial(const std::shared_ptr< SymbolicExpr > &poly_expr, const std::vector< std::string > &all_variables)
判断换元式是否为候选变量的多项式。 各候选变量的次数须可确定为非负整数,且超越函数不得依赖不定元或原始变量。
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
Result< T > extract_coeff_value(const std::shared_ptr< SymbolicExpr > &coefficient)
精确提取系数;不支持的值返回错误,保持数值完整。
static int tf_power_degree(const PowerNode &power, const std::string &var)
static std::vector< std::string > tf_polynomial_variables(const std::shared_ptr< SymbolicExpr > &expression, const std::vector< std::string > &indeterminates, const std::string &original_var)
const ExprPtr RelationOp op
const ExprPtr & exponent
int tf_degree_in(const std::shared_ptr< const SymbolicNode > &node, const std::string &variable)
const std::string const ExprPtr & value
static Result< TfPolyBuildResult > tf_convert_main_variable(TfPolyBuildResult result, const std::shared_ptr< SymbolicExpr > &expanded, const std::vector< std::string > &all_variables)
static void tf_select_main_variable(TfPolyBuildResult &result, const std::shared_ptr< SymbolicExpr > &expanded, const std::vector< std::string > &variables, int &max_degree)
const std::string & main_var
Result< TfPolyBuildResult > tf_build_polynomial(const std::shared_ptr< SymbolicExpr > &poly_expr, const std::vector< std::string > &indeterminates, const std::string &original_var)
多项式转换与精确符号多项式代数。
分解含 sin、cos、exp、ln 等超越函数的表达式。
std::vector< std::string > param_variables
参数变量列表(非主变量的不定元)
Polynomial< Rational > poly
主变量多项式(单变量或主变量策略)
std::string main_variable
选定的主变量名
内部 AST 定义。
混合超越方程不可约因式分解器公共 API.