LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
integration_rational.cpp
浏览该文件的文档.
1#include <stdexcept>
4
5namespace LMCAS {
6
7namespace {
9 if (!P.is_zero() && P.degree() > 0 && P.degree() < Q.degree()) {
10 auto [reduced_denominator, remainder] = Q.div_mod(P);
11 if (remainder.is_zero()) {
13 std::vector<Rational>{Rational(1)}, P.variable_name);
14 Q = std::move(reduced_denominator);
15 }
16 }
17}
18
19std::shared_ptr<SymbolicExpr> rd_integrate_polynomial(
20 const Polynomial<Rational>& quot, const std::string& var) {
21 auto result = SymbolicExpr::number(0);
22 if (!quot.is_zero()) {
23 for (size_t k = 0; k < quot.coeffs.size(); ++k) {
24 if (quot.coeffs[k] == Rational(0)) { continue; }
25 const BigInt integrated_power = BigInt(k) + BigInt(1);
26 Rational coeff = quot.coeffs[k] / Rational(integrated_power);
27 std::shared_ptr<SymbolicExpr> term;
28 auto v = SymbolicExpr::variable(var);
29 auto pw = SymbolicExpr::power(v, SymbolicExpr::number(integrated_power));
30 if (coeff == Rational(1)) {
31 term = pw;
32 } else {
33 term = SymbolicExpr::multiply(SymbolicExpr::number(coeff), pw);
34 }
35 result = SymbolicExpr::add(result, term);
36 }
37 }
38 return result;
39}
40
42 const std::string& var,
43 const std::vector<std::pair<Polynomial<Rational>, int>>& factors,
44 const std::vector<Polynomial<Rational>>& numerators,
46 detail::RewriteBudget transform_budget(context, context.limits().max_recursion_depth,
47 context.limits().max_ast_nodes, "transform");
48 size_t idx = 0;
49 for (const auto& [factor, mult] : factors) {
50 for (int power = 1; power <= mult; ++power, ++idx) {
51 auto term = detail::integrate_rational_term(numerators[idx], factor, power, var);
52 result.primitive = *SymbolicExpr::add(
54 detail::make_expression_ptr(term.primitive));
55 result.remainder = *SymbolicExpr::add(
57 detail::make_expression_ptr(term.remainder));
58 }
59 }
61 detail::normalize_node(detail::node(result.primitive), transform_budget));
63 detail::normalize_node(detail::node(result.remainder), transform_budget));
64 return result;
65}
66
68 const std::string& var,
70 const SymbolicExpr& zero, ComputationContext& computation) {
71 Polynomial<Rational> quot(Q.variable_name), rem = P;
72 if (P.degree() >= Q.degree()) {
73 auto divided = P.div_mod(Q);
74 quot = std::move(divided.first);
75 rem = std::move(divided.second);
76 }
77
78 detail::IntegralParts result{*rd_integrate_polynomial(quot, var), zero};
79 if (rem.is_zero()) { return result; }
80
81 std::vector<std::pair<Polynomial<Rational>, int>> factors;
82 if (!detail::factor_denominator(Q, factors)) {
83 result.remainder = *SymbolicExpr::divide(poly_to_symbolic(rem), poly_to_symbolic(Q));
84 return result;
85 }
86
87 std::vector<Polynomial<Rational>> numerators;
88 auto coefficients = detail::solve_coefficients(rem, Q, factors, numerators, computation);
89 if (!coefficients) {
90 return Result<detail::IntegralParts>::failure(coefficients.error());
91 }
92 if (!coefficients.value()) {
93 result.remainder = *SymbolicExpr::divide(poly_to_symbolic(rem), poly_to_symbolic(Q));
94 return result;
95 }
96 return rd_add_fraction_primitives(var, factors, numerators, std::move(result), computation);
97}
98}
99
100Result<std::optional<detail::IntegralParts>> Integrator::try_rational_decomposition(
101 const SymbolicExpr& expr, const std::string& var,
102 ComputationContext& computation, int depth) try {
103 detail::RewriteBudget transform_budget(computation, computation.limits().max_recursion_depth,
104 computation.limits().max_ast_nodes, "transform");
105 (void)depth;
106
107 Polynomial<Rational> P, Q;
108 auto extracted = detail::extract_rational(expr, var, P, Q);
109 if (!extracted) {
110 return Result<std::optional<detail::IntegralParts>>::failure(extracted.error());
111 }
112 if (!extracted.value()) { return std::optional<detail::IntegralParts>{}; }
114 if (Q.is_zero() || Q.degree() < 1) { return std::optional<detail::IntegralParts>{}; }
115
116 if (Q.degree() == 1 && P.degree() <= 0 &&
117 !P.coeffs.empty() && Q.coeffs.size() > 1 &&
118 Q.coeffs[1] != Rational(0)) {
119 auto coefficient = SymbolicExpr::number(P.coeffs[0] / Q.coeffs[1]);
120 auto logarithm = SymbolicExpr::ln(poly_to_symbolic(Q));
122 detail::node(SymbolicExpr::multiply(coefficient, logarithm)), transform_budget));
123 return std::optional<detail::IntegralParts>{{std::move(primitive), zero_}};
124 }
125 auto integrated = rd_integrate_proper_fraction(var, P, Q, zero_, computation);
126 if (!integrated) {
127 return Result<std::optional<detail::IntegralParts>>::failure(integrated.error());
128 }
129 return std::optional<detail::IntegralParts>{std::move(integrated.value())};
130} catch (const CasError& error) {
131 return Result<std::optional<detail::IntegralParts>>::failure(error);
132} catch (const std::bad_alloc&) {
134 CasErrc::ResourceLimit, "allocation failed", "integrate.rational");
135} catch (const std::length_error& error) {
137 CasErrc::ResourceLimit, error.what(), "integrate.rational");
138} catch (const std::exception& error) {
140 CasErrc::InternalInvariant, error.what(), "integrate.rational");
141}
142
143}
一元多项式模板类
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::string variable_name
变量名
bool is_zero() const
判断是否为零多项式
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
static Result failure(CasErrc code, std::string message, std::string operation={})
Result< detail::IntegralParts > rd_integrate_proper_fraction(const std::string &var, const Polynomial< Rational > &P, const Polynomial< Rational > &Q, const SymbolicExpr &zero, ComputationContext &computation)
std::shared_ptr< SymbolicExpr > rd_integrate_polynomial(const Polynomial< Rational > &quot, const std::string &var)
void rd_reduce_reciprocal(Polynomial< Rational > &P, Polynomial< Rational > &Q)
detail::IntegralParts rd_add_fraction_primitives(const std::string &var, const std::vector< std::pair< Polynomial< Rational >, int > > &factors, const std::vector< Polynomial< Rational > > &numerators, detail::IntegralParts result, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
IntegralParts integrate_rational_term(const Polynomial< Rational > &numerator, const Polynomial< Rational > &factor, int power, const std::string &var)
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
bool factor_denominator(const Polynomial< Rational > &denominator, std::vector< std::pair< Polynomial< Rational >, int > > &factors)
Result< bool > extract_rational(const SymbolicExpr &expr, const std::string &var, Polynomial< Rational > &numerator, Polynomial< Rational > &denominator)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
Result< bool > solve_coefficients(const Polynomial< Rational > &numerator, const Polynomial< Rational > &denominator, const std::vector< std::pair< Polynomial< Rational >, int > > &factors, std::vector< Polynomial< Rational > > &numerators, ComputationContext &context)
__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
@ Rational
Rational numbers
std::size_t std::size_t depth