8 const std::shared_ptr<const SymbolicNode>& factor) {
9 const auto* power =
dynamic_cast<const PowerNode*
>(factor.get());
10 const auto& base = power ? power->
base() : factor;
16 if (!power) {
return function->arguments()[0]; }
19 std::dynamic_pointer_cast<const NumberNode>(power->exponent()),
integer) ||
24 {power->exponent(),
function->arguments()[0]});
28 const std::vector<std::shared_ptr<const SymbolicNode>>& dependents) {
29 if (dependents.empty() || (dependents.size() == 1 &&
30 !
dynamic_cast<const PowerNode*
>(dependents[0].get()))) {
33 std::vector<std::shared_ptr<const SymbolicNode>> exponents;
34 exponents.reserve(dependents.size());
35 for (
const auto& dependent : dependents) {
37 if (!argument) {
return nullptr; }
38 exponents.push_back(std::move(argument));
42 std::vector<std::shared_ptr<const SymbolicNode>>{
52 std::vector<PiecewiseNode::Branch> branches;
53 branches.reserve(piecewise->branches().size());
54 for (
const auto& branch : piecewise->branches()) {
58 auto fallback = piecewise->default_expr()
70 if (
value->is_zero()) {
return true; }
72 if (!piecewise) {
return false; }
73 for (
const auto& branch : piecewise->branches()) {
79Result<std::optional<detail::IntegralParts>> Integrator::apply_linearity(
80 const SymbolicExpr& expr,
const std::string& var,
82 using Attempt = Result<std::optional<detail::IntegralParts>>;
83 detail::RewriteBudget budget(
context,
context.limits().max_recursion_depth,
84 context.limits().max_ast_nodes,
"integrate.linearity");
85 if (
const auto*
add =
dynamic_cast<const AddNode*
>(
detail::node(expr).get())) {
86 std::vector<detail::SymbolicNodePtr> primitives, remainders;
87 for (
const auto& operand :
add->operands()) {
89 auto parts = integrate_recursive(term, var,
context,
depth + 1, &term);
90 if (!parts) {
return Attempt::failure(parts.error()); }
91 primitives.push_back(
detail::node(parts.value().primitive));
93 remainders.push_back(
detail::node(parts.value().remainder));
96 const auto remainder = remainders.empty() ?
detail::node(zero_)
97 : remainders.size() == 1 ? remainders.front()
106 std::vector<detail::SymbolicNodePtr> constants, dependents;
107 for (
const auto& operand :
mul->operands()) {
109 dependents.push_back(operand);
111 else { constants.push_back(operand); }
114 if (!constants.empty() || exponential) {
116 : dependents.empty() ? *SymbolicExpr::number(1)
119 auto parts = integrate_recursive(dependent, var,
context,
depth + 1, &dependent);
120 if (!parts) {
return Attempt::failure(parts.error()); }
121 if (constants.empty()) {
return Attempt::success(std::move(parts.value())); }
122 auto coefficient = constants.size() == 1 ? constants.front()
125 auto scale = [&](
const SymbolicExpr&
value) {
130 scale(parts.value().primitive), scale(parts.value().remainder)});
133 return Attempt::success(std::nullopt);
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
const std::shared_ptr< const SymbolicNode > & default_expr() const noexcept
const std::shared_ptr< const SymbolicNode > & base() const noexcept
static std::shared_ptr< const SymbolicNode > create_add(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建加法节点,自动扁平化嵌套加法并消除零项.
static std::shared_ptr< const SymbolicNode > create_multiply(std::vector< std::shared_ptr< const SymbolicNode > > ops, detail::RewriteBudget *budget=nullptr)
创建乘法节点,自动扁平化嵌套乘法并消除单位元.
std::size_t measure(const std::shared_ptr< const SymbolicNode > &node)
std::shared_ptr< const SymbolicNode > integration_exponential_argument(const std::shared_ptr< const SymbolicNode > &factor)
std::shared_ptr< const SymbolicNode > combine_integration_exponentials(const std::vector< std::shared_ptr< const SymbolicNode > > &dependents)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
bool integration_depends_on_variable(const SymbolicNodePtr &expression, const std::string &variable, RewriteBudget *budget=nullptr)
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult integer(Integer)=delete
bool try_get_integer_value(const std::shared_ptr< const NumberNode > &node, BigInt &value)
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
ExprResult add(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
std::size_t std::size_t depth
static detail::SymbolicNodePtr scale_integral_field(const detail::SymbolicNodePtr &value, const detail::SymbolicNodePtr &coefficient, detail::RewriteBudget &budget)
static bool zero_remainder(const detail::SymbolicNodePtr &value, detail::RewriteBudget &budget)
const std::string const ExprPtr & value
std::shared_ptr< const SymbolicNode > make_normalized_multiply_node(const std::vector< std::shared_ptr< const SymbolicNode > > &operands, detail::RewriteBudget *budget=nullptr)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)