11 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(
detail::node(term))) {
22 const SymbolicExpr& candidate_term,
const SymbolicExpr&
u,
24 if (
auto power = std::dynamic_pointer_cast<const PowerNode>(
detail::node(candidate_term))) {
32 if (
auto function = std::dynamic_pointer_cast<const FunctionNode>(
detail::node(candidate_term))) {
37 return SymbolicExpr::multiply(SymbolicExpr::number(-1),
48 const SymbolicExpr& expr,
const SymbolicExpr& candidate_term,
51 (computation).limits().max_ast_nodes,
"transform");
55 if (!d_ptr) {
return nullptr; }
57 if (du->is_zero()) {
return nullptr; }
59 auto f_u = candidate_term;
64 if (!primitive) {
return primitive; }
65 if (!primitive.value()) {
return nullptr; }
66 return SymbolicExpr::multiply(ratio, primitive.value());
69}
catch (
const std::bad_alloc&) {
70 return Result<std::shared_ptr<SymbolicExpr>>::failure(
CasErrc::ResourceLimit,
"allocation failed",
"substitute_candidate");
71}
catch (
const std::length_error& error) {
73}
catch (
const std::exception& error) {
79 const SymbolicExpr& expr,
const std::string& var,
81 std::vector<std::shared_ptr<const SymbolicNode>> ops;
83 ops =
mul->operands();
87 for (
const auto& operand : ops) {
94 return std::optional<detail::IntegralParts>{{*result.value(), zero_}};
97 return std::optional<detail::IntegralParts>{};
105 std::shared_ptr<const PowerNode>
power;
114 case FT::Log:
return false;
115 default:
return function.arguments().size() == 1;
129 if (!wrapper.
power) {
return wrapper; }
131 wrapper.
function = std::dynamic_pointer_cast<const FunctionNode>(wrapper.
power->base());
160Result<std::optional<detail::IntegralParts>> Integrator::try_linear_substitution(
161 const SymbolicExpr& expr,
const std::string& var,
162 ComputationContext& computation,
int) {
163 detail::RewriteBudget budget(computation, computation.limits().max_recursion_depth,
164 computation.limits().max_ast_nodes,
"integrate.linear_substitution");
165 auto wrapper = classify_linear_wrapper(expr, var);
166 if (!wrapper.argument) {
return std::optional<detail::IntegralParts>{}; }
171 if (!affine.value()) {
return std::optional<detail::IntegralParts>{}; }
176 if (slope->is_one() && offset->is_zero()) {
177 return std::optional<detail::IntegralParts>{};
179 std::optional<detail::AssumptionFacts>
facts;
180 if (computation.assumptions()) {
facts.emplace(*computation.assumptions()); }
186 if (nonzero.value() !=
Tribool::True) {
return std::optional<detail::IntegralParts>{}; }
187 if (wrapper.kind == LinearWrapperKind::Function &&
195 auto primitive = SymbolicExpr::divide(SymbolicExpr::multiply(
197 SymbolicExpr::multiply(SymbolicExpr::number(2), slope));
202 auto variable = SymbolicExpr::variable(var);
204 std::shared_ptr<SymbolicExpr> primitive;
205 if (wrapper.kind == LinearWrapperKind::PowerOfLinear) {
215 if (!real_variable) {
221 if (!real_argument) {
225 return std::optional<detail::IntegralParts>{};
229 [](std::shared_ptr<SymbolicExpr> candidate) {
return candidate; });
231 if (!primitive) {
return std::optional<detail::IntegralParts>{}; }
235 SymbolicExpr::divide(substituted, slope)), budget));
236 return std::optional<detail::IntegralParts>{{std::move(result), zero_}};
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
LinearWrapper classify_linear_wrapper(const SymbolicExpr &expr, const std::string &var)
std::shared_ptr< SymbolicExpr > linear_reduced_expression(const LinearWrapper &wrapper, const std::shared_ptr< SymbolicExpr > &variable)
Result< std::shared_ptr< SymbolicExpr > > substitution_primitive(const SymbolicExpr &candidate_term, const SymbolicExpr &u, const std::string &var, ComputationContext &context)
std::shared_ptr< const FunctionNode > function
std::shared_ptr< const PowerNode > power
bool linear_substitutable_function(const FunctionNode &function)
Result< std::shared_ptr< SymbolicExpr > > substitute_candidate(const SymbolicExpr &expr, const SymbolicExpr &candidate_term, const std::string &var, ComputationContext &computation)
std::optional< SymbolicExpr > argument
std::optional< SymbolicExpr > substitution_argument(const SymbolicExpr &term)
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, 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
Result< Tribool > query_nonzero_value(const Node &node, const FactsQuery &facts, Domain domain, ComputationContext &context)
const FactsQuery & no_facts() noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
RewriteBudget const FactsQuery & facts
Result< std::optional< SymbolicExpr > > integrate_power_primitive(const SymbolicExpr &base, const SymbolicExpr &exponent, const std::string &variable, ComputationContext &)
std::shared_ptr< const Node > make_node(Args &&... args)
Result< Tribool > query_real_value(const Node &node, const FactsQuery &facts, ComputationContext &context)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
Result< std::optional< AffineForm > > recognize_affine(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
SymbolicNodePtr substitute_node(const SymbolicNodePtr &node, const std::string &variable, const SymbolicNodePtr &replacement, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::string & variable
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
std::shared_ptr< SymbolicExpr > lookup_integral(const std::vector< detail::IntegrationEntry > &table, const SymbolicExpr &matched, const std::string &matched_variable, detail::RewriteBudget &budget, Transform &&transform)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
@ True
Property definitely holds
bool depends_on_integration_variable(const SymbolicExpr &expression, const std::string &variable)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
__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 & u