LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
integration_definite.cpp
浏览该文件的文档.
1#include <stdexcept>
5
6namespace LMCAS {
7namespace {
8using namespace detail::definite;
9
11 SymbolicExpr lo;
12 SymbolicExpr hi;
15 bool reversed = false;
16
17 DefiniteInterval(const SymbolicExpr& lower, const SymbolicExpr& upper,
20};
21
23 const std::string& var_name, const SymbolicExpr& lower, const SymbolicExpr& upper) {
25 var_name, detail::node(lower), detail::node(upper)));
26}
27
29 const std::string& var_name, const SymbolicExpr& lower, const SymbolicExpr& upper,
31 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
32 (context).limits().max_ast_nodes, "transform");
33 if (interval.a.value().infinity) { return unresolved_integral(expr, var_name, lower, upper); }
34 auto assumptions = real_assumptions(var_name, context);
35 if (!assumptions) { return Result<SymbolicExpr>::failure(assumptions.error()); }
36 detail::AssumptionFacts facts(assumptions.value());
37 auto value = detail::make_expression_ptr(detail::substitute_node(detail::node(expr), var_name, detail::node(interval.lo), transform_budget));
39 if (!defined) { return Result<SymbolicExpr>::failure(defined.error()); }
40 if (defined.value() == Tribool::False) { return divergent<SymbolicExpr>(); }
41 return defined.value() == Tribool::True ? Result<SymbolicExpr>(*SymbolicExpr::number(0)) : unresolved_integral(expr, var_name, lower, upper);
42} catch (const CasError& error) {
44} catch (const std::bad_alloc&) {
45 return Result<SymbolicExpr>::failure(CasErrc::ResourceLimit, "allocation failed", "equal_endpoint_integral");
46} catch (const std::length_error& error) {
47 return Result<SymbolicExpr>::failure(CasErrc::ResourceLimit, error.what(), "equal_endpoint_integral");
48} catch (const std::exception& error) {
49 return Result<SymbolicExpr>::failure(CasErrc::InternalInvariant, error.what(), "equal_endpoint_integral");
50}
51
52Result<Tribool> certify_partition(const SymbolicExpr& expr, const std::string& var_name,
53 const std::vector<SymbolicExpr>& partition, ComputationContext& context) {
54 for (std::size_t i = 1; i < partition.size(); ++i) {
55 auto continuous = certify_continuity_checked(expr, var_name,
56 partition[i - 1], partition[i], context);
57 if (!continuous || continuous.value() != Tribool::True) { return continuous; }
58 }
59 return Tribool::True;
60}
61
63 SymbolicExpr expression;
64 int divergence = 0;
65};
66
68 const std::string& var_name, const DefiniteInterval& interval, ComputationContext& context) {
69 auto rational = rational_checked(detail::node(expr), var_name, context);
71 RationalIntegrand result{expr};
72 if (rational.value() && interval.a && interval.b) {
76 result.divergence = divergence.value();
77 if (result.divergence) { return result; }
78 result.expression = *SymbolicExpr::divide(poly_to_symbolic(rational.value()->numerator),
79 poly_to_symbolic(rational.value()->denominator));
80 }
81 return result;
82}
83
85 const SymbolicExpr& value_expression, const std::string& var_name,
86 const SymbolicExpr& lower, const SymbolicExpr& upper, ComputationContext& context) {
87 auto selected = segment_expression_checked(value_expression, var_name, lower, upper, context);
88 if (!selected) { return selected; }
89 auto integrated = integrator.integrate_checked(selected.value(), var_name, context);
90 if (!integrated) { return integrated; }
91 if (contains_unevaluated_integral(detail::node(integrated.value()))) { return undecided<SymbolicExpr>(); }
92 return integrated;
93}
94
95Result<SymbolicExpr> accumulate_segments(Integrator& integrator, const SymbolicExpr& expr,
96 const SymbolicExpr& value_expression, const std::string& var_name,
97 const std::vector<SymbolicExpr>& partition, const std::optional<SymbolicExpr>& primitive,
98 bool reversed, ComputationContext& context) try {
99 detail::RewriteBudget transform_budget(context, (context).limits().max_recursion_depth,
100 (context).limits().max_ast_nodes, "transform");
101 SymbolicExpr sum = *SymbolicExpr::number(0);
102 int infinity = 0;
103 for (std::size_t i = 1; i < partition.size(); ++i) {
104 std::optional<SymbolicExpr> local_primitive;
105 if (!primitive) {
106 auto integrated = integrate_segment_primitive(integrator, value_expression, var_name,
107 partition[i - 1], partition[i], context);
108 if (!integrated) { return integrated; }
109 local_primitive = std::move(integrated.value());
110 }
111 auto segment = definite_segment_checked(expr, primitive ? *primitive : *local_primitive, var_name,
112 partition[i - 1], partition[i], context);
113 if (!segment) { return segment; }
114 int contribution = infinity_sign(detail::node(segment.value()));
115 if (contribution) {
116 if (infinity && infinity != contribution) { return divergent<SymbolicExpr>(); }
117 infinity = contribution;
118 } else { sum = *SymbolicExpr::add(detail::make_expression_ptr(sum), detail::make_expression_ptr(segment.value())); }
119 }
120 if (infinity) { return *SymbolicExpr::infinity(infinity * (reversed ? -1 : 1)); }
121 if (reversed) { sum = *SymbolicExpr::multiply(SymbolicExpr::number(-1), detail::make_expression_ptr(sum)); }
122 return *detail::make_expression_ptr(detail::normalize_node(detail::node(sum), transform_budget));
123} catch (const CasError& error) {
124 return Result<SymbolicExpr>::failure(error);
125} catch (const std::bad_alloc&) {
126 return Result<SymbolicExpr>::failure(CasErrc::ResourceLimit, "allocation failed", "accumulate_segments");
127} catch (const std::length_error& error) {
128 return Result<SymbolicExpr>::failure(CasErrc::ResourceLimit, error.what(), "accumulate_segments");
129} catch (const std::exception& error) {
130 return Result<SymbolicExpr>::failure(CasErrc::InternalInvariant, error.what(), "accumulate_segments");
131}
132
133Result<SymbolicExpr> integrate_ordered_interval(Integrator& integrator, const SymbolicExpr& expr,
134 const std::string& var_name,
135 const SymbolicExpr& lower, const SymbolicExpr& upper,
137 const auto unresolved = [&]() { return unresolved_integral(expr, var_name, lower, upper); };
138 auto partition = definite_partition_checked(expr, var_name, interval.lo, interval.hi, context);
139 if (!partition) { return is_undecided(partition.error()) ? unresolved() : Result<SymbolicExpr>::failure(partition.error()); }
140 auto continuous = certify_partition(expr, var_name, partition.value(), context);
141 if (!continuous) { return Result<SymbolicExpr>::failure(continuous.error()); }
142 if (continuous.value() == Tribool::False) { return divergent<SymbolicExpr>(); }
143 if (continuous.value() != Tribool::True) { return unresolved(); }
144 auto reduced = reduced_integrand_checked(expr, var_name, interval, context);
145 if (!reduced) { return Result<SymbolicExpr>::failure(reduced.error()); }
146 if (reduced.value().divergence) {
147 return *SymbolicExpr::infinity(reduced.value().divergence * (interval.reversed ? -1 : 1));
148 }
149 const auto& value_expression = reduced.value().expression;
150 std::optional<SymbolicExpr> primitive;
151 if (!needs_segment_expression(detail::node(value_expression))) {
152 auto integrated = integrator.integrate_checked(value_expression, var_name, context);
153 if (!integrated) { return is_undecided(integrated.error()) ? unresolved() : integrated; }
154 if (contains_unevaluated_integral(detail::node(integrated.value()))) { return unresolved(); }
155 primitive = std::move(integrated.value());
156 }
157 auto sum = accumulate_segments(integrator, expr, value_expression, var_name,
158 partition.value(), primitive, interval.reversed, context);
159 if (!sum && is_undecided(sum.error())) { return unresolved(); }
160 return sum;
161}
162
163Result<SymbolicExpr> integrate_interval_checked(Integrator& integrator, const SymbolicExpr& expr,
164 const std::string& var_name,
165 const SymbolicExpr& lower, const SymbolicExpr& upper, ComputationContext& context) {
169 if (interval.a && interval.b) {
171 if (!order) { return Result<SymbolicExpr>::failure(order.error()); }
172 if (!order.value()) {
173 return equal_endpoint_integral(expr, var_name, lower, upper, interval, context);
174 }
175 if (order.value() > 0) {
176 std::swap(interval.lo, interval.hi);
177 std::swap(interval.a.value(), interval.b.value());
178 interval.reversed = true;
179 }
180 }
182}
183}
184
185Result<SymbolicExpr> Integrator::integrate_def_checked(const SymbolicExpr& expr,
186 const std::string& var_name, const SymbolicExpr& lower, const SymbolicExpr& upper,
187 ComputationContext& context) {
188 auto access = context.consume_steps(1, operation);
189 if (!access) { return Result<SymbolicExpr>::failure(access.error()); }
190 if (var_name.empty() || depends_on_integration_variable(lower, var_name) ||
193 "integration endpoints must be independent of the integration variable", operation); }
194 try {
195 detail::RewriteBudget budget(context, context.limits().max_recursion_depth,
196 context.limits().max_ast_nodes, operation);
198 auto result = integrate_interval_checked(*this, expr, var_name, lower, upper, context);
199 if (!result) { return result; }
200 budget.measure(detail::node(result.value()));
201 return result;
202 } catch (const CasError& error) {
203 return Result<SymbolicExpr>::failure(error);
204 } catch (const std::bad_alloc&) {
206 "definite integration allocation failed", operation);
207 } catch (const std::length_error& error) {
208 return Result<SymbolicExpr>::failure(CasErrc::ResourceLimit, error.what(), operation);
209 } catch (const std::exception& error) {
210 return Result<SymbolicExpr>::failure(CasErrc::InternalInvariant, error.what(), operation);
211 }
212}
213
214}
Result(T value)
Allow direct return of a success value from a Result-returning function.
CasError & error()
static Result failure(CasErrc code, std::string message, std::string operation={})
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
Result< SymbolicExpr > integrate_ordered_interval(Integrator &integrator, const SymbolicExpr &expr, const std::string &var_name, const SymbolicExpr &lower, const SymbolicExpr &upper, const DefiniteInterval &interval, ComputationContext &context)
Result< Tribool > certify_partition(const SymbolicExpr &expr, const std::string &var_name, const std::vector< SymbolicExpr > &partition, ComputationContext &context)
Result< SymbolicExpr > integrate_interval_checked(Integrator &integrator, const SymbolicExpr &expr, const std::string &var_name, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< RationalIntegrand > reduced_integrand_checked(const SymbolicExpr &expr, const std::string &var_name, const DefiniteInterval &interval, ComputationContext &context)
Result< SymbolicExpr > integrate_segment_primitive(Integrator &integrator, const SymbolicExpr &value_expression, const std::string &var_name, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< SymbolicExpr > unresolved_integral(const SymbolicExpr &expr, const std::string &var_name, const SymbolicExpr &lower, const SymbolicExpr &upper)
Result< SymbolicExpr > accumulate_segments(Integrator &integrator, const SymbolicExpr &expr, const SymbolicExpr &value_expression, const std::string &var_name, const std::vector< SymbolicExpr > &partition, const std::optional< SymbolicExpr > &primitive, bool reversed, ComputationContext &context)
Result< SymbolicExpr > equal_endpoint_integral(const SymbolicExpr &expr, const std::string &var_name, const SymbolicExpr &lower, const SymbolicExpr &upper, const DefiniteInterval &interval, ComputationContext &context)
Result< SymbolicExpr > segment_expression_checked(const SymbolicExpr &expression, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< SymbolicExpr > definite_segment_checked(const SymbolicExpr &original, const SymbolicExpr &primitive, const std::string &var, const SymbolicExpr &a, const SymbolicExpr &b, ComputationContext &context)
Result< int > rational_divergence_checked(RationalFunction &rational, const Boundary &a, const Boundary &b, ComputationContext &context)
Result< Tribool > certify_continuity_checked(const SymbolicExpr &expression, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< std::vector< SymbolicExpr > > definite_partition_checked(const SymbolicExpr &original, const std::string &var, const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)
Result< int > compare_boundaries(const Boundary &a, const Boundary &b, ComputationContext &context)
Result< Boundary > boundary_checked(const SymbolicExpr &expression, ComputationContext &context)
RationalResult rational_checked(const Node &node, const std::string &var, ComputationContext &context)
Result< AssumptionContext > real_assumptions(const std::string &var, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
Result< Tribool > query_definedness(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context, bool *violated_real_restriction)
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
__attribute__((visibility("default"))) ExprResult function(const std __attribute__((visibility("default"))) ExprResult finite_set(std ExprPtr upper
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult interval(ExprPtr lower, ExprPtr upper, bool lower_closed, bool upper_closed)
const ExprPtr & lower
const std::vector< FGLMPoly > const MonomialOrder & order
bool contains_unevaluated_integral(const std::shared_ptr< const SymbolicNode > &node)
@ Real
Real numbers
@ True
Property definitely holds
@ False
Property definitely does not hold
bool depends_on_integration_variable(const SymbolicExpr &expression, const std::string &variable)
std::shared_ptr< SymbolicExpr > divergence(const VectorField &F, const std::vector< std::string > &vars)
const std::string const ExprPtr & value
ExprResult rational(const Rational &value)
const std::vector< IntegrationStep > Integrator & integrator
DefiniteInterval(const SymbolicExpr &lower, const SymbolicExpr &upper, ComputationContext &context)